コード例 #1
0
 public ContestExecutorFactory(OnlineJudgeContext db, SmartUser <User, Guid> user, ManagementServiceClient mgmt, IConfiguration config)
 {
     this._db     = db;
     this._user   = user;
     this._mgmt   = mgmt;
     this._config = config;
 }
コード例 #2
0
 public HackStateMachineHandler(OnlineJudgeContext db, IHubContext <OnlineJudgeHub> hub, ManagementServiceClient mgmt, ContestExecutorFactory cef)
 {
     _db   = db;
     _hub  = hub;
     _mgmt = mgmt;
     _cef  = cef;
 }
コード例 #3
0
        public async Task <IActionResult> GetTestCase(
            [FromServices] ManagementServiceClient MgmtSvc,
            string problemId,
            string contestId,
            TestCaseType?type,
            bool?showContent,
            CancellationToken token)
        {
            this.HasOwnership = await HasPermissionToProblemAsync(problemId, token);

            var problem = await DB.Problems.SingleOrDefaultAsync(x => x.Id == problemId, token);

            if (!string.IsNullOrEmpty(contestId) && !await IsContestAttendeeAbleToAccessProblem(problemId, contestId, token))
            {
                return(Result(403, "You don't have the permission to view this problem."));
            }
            if ((problem == null || !problem.IsVisible && !this.HasOwnership) && string.IsNullOrEmpty(contestId))
            {
                return(Result <Problem>(404, "Not Found"));
            }

            IQueryable <TestCase> testCases = DB.TestCases
                                              .Where(x => x.ProblemId == problemId);

            if (type.HasValue)
            {
                testCases = testCases.Where(x => x.Type == type.Value);
            }

            testCases = testCases.OrderBy(x => x.Type);

            var ret = await testCases.Select(x => new TestCaseWithContent
            {
                Id               = x.Id,
                ContestId        = x.ContestId,
                InputBlobId      = x.InputBlobId,
                InputSizeInByte  = x.InputSizeInByte,
                OutputBlobId     = x.OutputBlobId,
                OutputSizeInByte = x.OutputSizeInByte,
                ProblemId        = x.ProblemId,
                Type             = x.Type
            })
                      .ToListAsync(token);

            if (showContent.HasValue && showContent.Value)
            {
                foreach (var x in ret)
                {
                    if (x.Type == TestCaseType.Sample || await IsAbleToAccessTestCaseContentAsync(x.ProblemId, token))
                    {
                        x.Input  = Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(x.InputBlobId, token)).Body);
                        x.Output = Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(x.OutputBlobId, token)).Body);
                    }
                }
            }

            return(Result(ret));
        }
コード例 #4
0
        static async Task MainAsync(CancellationToken token)
        {
            var connStr = JsonConvert.DeserializeObject <dynamic>(File.ReadAllText("config.json")).Oj;
            var builder = new DbContextOptionsBuilder <OnlineJudgeContext>();

            builder.UseMySql((string)connStr);
            var cnt = 0;

            using (var db = new OnlineJudgeContext(builder.Options))
            {
                var problemIds = await db.Problems
                                 .Where(x => x.Source == ProblemSource.Local)
                                 .Select(x => x.Id)
                                 .ToListAsync(token);

                var mgmt = new ManagementServiceClient("https://mgmtsvc.1234.sh", @"C:\Users\Yuko\Documents\webapi-client.pfx", "123456");

                var tasks  = new List <Task>();
                var cancel = new CancellationTokenSource();
                var ret    = new ConcurrentBag <(string, Guid)>();
                foreach (var id in problemIds)
                {
                    cnt++;
                    if (cnt % 10 == 0)
                    {
                        Console.WriteLine(cnt + " problems handled.");
                    }

                    foreach (var x in await db.TestCases.Where(x => x.ProblemId == id).ToListAsync(token))
                    {
                        tasks.Add(Task.Run(async() => {
                            try
                            {
                                await mgmt.GetBlobAsync(x.InputBlobId);
                            }
                            catch
                            {
                                ret.Add((x.ProblemId, x.InputBlobId));
                                Console.WriteLine("[Failed] " + x.ProblemId + ", input id = " + x.InputBlobId);
                            }
                            try
                            {
                                await mgmt.GetBlobAsync(x.OutputBlobId);
                            }
                            catch
                            {
                                ret.Add((x.ProblemId, x.OutputBlobId));
                                Console.WriteLine("[Failed] " + x.ProblemId + ", output id = " + x.OutputBlobId);
                            }
                        }));
                    }
                    await Task.WhenAll(tasks);
                }

                File.WriteAllText("result.txt", string.Join("\r\n", ret.Select(x => x.Item1 + " " + x.Item2)));
            }
        }
コード例 #5
0
        public async Task <IActionResult> Patch(
            Guid id,
            [FromServices] ManagementServiceClient mgmt,
            [FromServices] IHubContext <OnlineJudgeHub> hub,
            CancellationToken token)
        {
            var judge = await DB.JudgeStatuses
                        .Include(x => x.RelatedStateMachineIds)
                        .Include(x => x.SubStatuses)
                        .SingleOrDefaultAsync(x => x.Id == id, token);

            if (judge == null)
            {
                return(Result(404, "Not found"));
            }

            var request = JsonConvert.DeserializeObject <JudgeStatus>(RequestBody);

            if (request.Result != JudgeResult.Pending)
            {
                return(Result(400, "Operation is not supported"));
            }

            if (judge.RelatedStateMachineIds.Count < 1)
            {
                return(Result(404, "State machine is not found"));
            }

            if (!User.IsSignedIn() || judge.UserId != User.Current.Id && !IsMasterOrHigher && !await HasPermissionToProblemAsync(judge.ProblemId) && !await HasPermissionToContestAsync(judge.ContestId, token) && !await HasPermissionToSpecifiedGroupAsync(judge.GroupId, token))
            {
                return(Result(401, "No permission"));
            }

            if ((judge.Result == JudgeResult.Pending || judge.Result == JudgeResult.Running) && !IsMasterOrHigher)
            {
                return(Result(400, "The state machine is running."));
            }

            foreach (var x in judge.SubStatuses)
            {
                x.Result           = JudgeResult.Pending;
                x.Hint             = null;
                x.TimeUsedInMs     = 0;
                x.MemoryUsedInByte = 0;
            }
            judge.Hint   = null;
            judge.Result = JudgeResult.Pending;

            await DB.SaveChangesAsync(token);

            await mgmt.PatchStateMachineInstanceAsync(judge.RelatedStateMachineIds.Last().StateMachineId, "Start", token);

            hub.Clients.All.InvokeAsync("ItemUpdated", "judge", judge.Id);
            return(Result(200, "Patch succeeded"));
        }
コード例 #6
0
        public async Task <IActionResult> GetTestCase(
            [FromServices] ManagementServiceClient MgmtSvc,
            string problemId,
            Guid id,
            bool?showContent,
            CancellationToken token)
        {
            this.HasOwnership = await HasPermissionToProblemAsync(problemId, token);

            var problem = await DB.Problems.SingleOrDefaultAsync(x => x.Id == problemId, token);

            if (problem == null || !problem.IsVisible && !this.HasOwnership)
            {
                return(Result <Problem>(404, "Not Found"));
            }

            var ret = await DB.TestCases
                      .Select(x => new TestCaseWithContent
            {
                Id               = x.Id,
                ContestId        = x.ContestId,
                InputBlobId      = x.InputBlobId,
                InputSizeInByte  = x.InputSizeInByte,
                OutputBlobId     = x.OutputBlobId,
                OutputSizeInByte = x.OutputSizeInByte,
                ProblemId        = x.ProblemId,
                Type             = x.Type
            })
                      .SingleOrDefaultAsync(x => x.ProblemId == problemId && x.Id == id, token);

            if (ret == null)
            {
                return(Result <TestCaseWithContent>(404, "Not Found"));
            }
            else if (!await HasPermissionToProblemAsync(problemId, token) &&
                     !await DB.TestCasePurchases.AnyAsync(x => x.ProblemId == problemId && x.UserId == User.Current.Id, token))
            {
                return(Result <TestCaseWithContent>(401, "No Permission"));
            }
            else
            {
                if (showContent.HasValue && showContent.Value)
                {
                    if (await IsAbleToAccessTestCaseContentAsync(ret.ProblemId, token))
                    {
                        ret.Input  = Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(ret.InputBlobId, token)).Body);
                        ret.Output = Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(ret.OutputBlobId, token)).Body);
                    }
                }

                return(Result(ret));
            }
        }
コード例 #7
0
        public async Task <IActionResult> Download(Guid id, [FromServices] ManagementServiceClient mgmt)
        {
            var blob = await mgmt.GetBlobAsync(id);

            if (blob.Name.StartsWith("joyoi_online_judge_upload_"))
            {
                return(File(blob.Body, "application/octet-stream", blob.Name));
            }
            else
            {
                Response.StatusCode = 404;
                return(Content("Not Found"));
            }
        }
コード例 #8
0
ファイル: HackController.cs プロジェクト: syh325/OnlineJudge
        public async Task<IActionResult> Get(
            Guid id,
            [FromServices] ManagementServiceClient mgmt,
            [FromServices] ContestExecutorFactory cef,
            CancellationToken token)
        {
            var ret = await DB.HackStatuses
                .Include(x => x.Status)
                .Include(x => x.User)
                .SingleOrDefaultAsync(x => x.Id == id, token);

            if (IsGroupRequest() && ret.GroupId != CurrentGroup.Id)
            {
                return Result(400, "No permission");
            }

            if (ret.HackDataBlobId.HasValue)
            {
                ret.HackDataBody = Encoding.UTF8.GetString((await mgmt.GetBlobAsync(ret.HackDataBlobId.Value, token)).Body);
            }

            var username = ret.User.UserName;
            ret.User = null;

            if (ret == null)
            {
                return Result(404, "Hack status is not found");
            }

            if (!string.IsNullOrEmpty(ret.ContestId))
            {
                var ce = cef.Create(ret.ContestId);
                if ((ce.IsContestInProgress(User.Current?.UserName) || ce.IsContestInProgress(username)) && ret.UserId != User.Current?.Id && !IsMasterOrHigher && !ce.HasPermissionToContest(User.Current?.UserName))
                {
                    ce.OnShowHackResult(ret);
                }
            }

            if (User.Current?.Id != ret.UserId 
                && User.Current?.Id != ret.Status.UserId 
                && !await HasPermissionToProblemAsync(ret.Status.ProblemId, token)
                && !(IsGroupRequest() && await HasPermissionToGroupAsync(token)))
            {
                ret.HackDataBody = null;
            }

            return Result(ret);
        }
コード例 #9
0
        static void Main(string[] args)
        {
            var client = new ManagementServiceClient("https://mgmtsvc.1234.sh", @"C:\Users\Yuko\Documents\webapi-client.pfx", "123456");

            client.PatchStateMachineDefinitionAsync("CompileOnlyStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\CompileOnlyStateMachine.cs"), null).Wait();
            client.PatchStateMachineDefinitionAsync("JudgeStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\JudgeStateMachine.cs"), null).Wait();
            client.PatchStateMachineDefinitionAsync("HackStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\Hack\HackStateMachine.cs"), null).Wait();
            client.PatchActorAsync("CompareActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\CompareActor.cs")).Wait();
            client.PatchActorAsync("RunUserProgramActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\RunUserProgramActor.cs")).Wait();
            client.PatchActorAsync("CompileActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\CompileActor.cs"), default(CancellationToken)).Wait();
            client.PatchActorAsync("HackActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\LocalJudge\StateMachineAndActor\Hack\HackRunActor.cs"), default(CancellationToken)).Wait();

            //var validatorId = client.PutBlobAsync("Validator.out", File.ReadAllBytes(@"C:\Users\Yuko\Documents\Validator.out")).Result;
            //Console.WriteLine(validatorId);
            Console.Read();
        }
コード例 #10
0
 static void Main(string[] args)
 {
     while (true)
     {
         var id      = Guid.Parse(Console.ReadLine());
         var builder = new DbContextOptionsBuilder <OnlineJudgeContext>();
         var connStr = JsonConvert.DeserializeObject <dynamic>(File.ReadAllText("config.json")).Oj;
         builder.UseMySql((string)connStr);
         using (var db = new OnlineJudgeContext(builder.Options))
         {
             var statemachineId = db.JudgeStatusStateMachines.Where(x => x.StatusId == id).Last().StateMachineId;
             var mgmt           = new ManagementServiceClient("https://mgmtsvc.1234.sh", @"C:\Users\Yuko\Documents\webapi-client.pfx", "123456");
             mgmt.PatchStateMachineInstanceAsync(statemachineId, "Start");
             Console.WriteLine("OK");
         }
     }
 }
コード例 #11
0
        public async Task <IActionResult> LeetCode(
            [FromServices] ManagementServiceClient MgmtSvc,
            Guid id)
        {
            var statemachine = await MgmtSvc.GetStateMachineInstanceAsync(id, default(CancellationToken));

            var actors = statemachine.StartedActors.Where(x => x.Name == "LeetCodePullProblemBodyActor" && x.Outputs.Any(y => y.Name == "problem.json")).ToDictionary(x => "leetcode-" + x.Tag);
            var ids    = actors.Keys.Select(x => x).ToList();

            foreach (var i in ids)
            {
                var model   = JsonConvert.DeserializeObject <ProblemJson>(Encoding.UTF8.GetString((await ManagementService.GetBlobAsync(actors[i].Outputs.Single(x => x.Name == "problem.json").Id)).Body));
                var problem = await DB.Problems.SingleOrDefaultAsync(x => x.Id == i);

                if (problem == null)
                {
                    problem = new Problem
                    {
                        Title  = model.Title,
                        Id     = i,
                        Body   = model.Body,
                        Source = ProblemSource.LeetCode,
                        Tags   = "按题库:LeetCode",
                        TimeLimitationPerCaseInMs     = model.TimeLimitInMs,
                        MemoryLimitationPerCaseInByte = model.MemoryLimitInByte,
                        IsVisible = true,
                        Template  = JsonConvert.SerializeObject(model.CodeTemplate)
                    };
                    DB.Problems.Add(problem);
                }
                else
                {
                    problem.Title = model.Title;
                    problem.Body  = model.Body;
                    problem.TimeLimitationPerCaseInMs     = model.TimeLimitInMs;
                    problem.MemoryLimitationPerCaseInByte = model.MemoryLimitInByte;
                    problem.IsVisible = true;
                }
                await DB.SaveChangesAsync();
            }

            return(Result(200, "ok"));
        }
コード例 #12
0
        public async Task <IActionResult> GetTestCaseOutput(
            [FromServices] ManagementServiceClient MgmtSvc,
            string problemId,
            Guid id,
            CancellationToken token)
        {
            this.HasOwnership = await HasPermissionToProblemAsync(problemId, token);

            var problem = await DB.Problems.SingleOrDefaultAsync(x => x.Id == problemId, token);

            if (problem == null || !problem.IsVisible && !this.HasOwnership)
            {
                return(Result <Problem>(404, "Not Found"));
            }

            var ret = await DB.TestCases
                      .Select(x => new TestCaseWithContent
            {
                Id               = x.Id,
                ContestId        = x.ContestId,
                InputBlobId      = x.InputBlobId,
                InputSizeInByte  = x.InputSizeInByte,
                OutputBlobId     = x.OutputBlobId,
                OutputSizeInByte = x.OutputSizeInByte,
                ProblemId        = x.ProblemId,
                Type             = x.Type
            })
                      .SingleOrDefaultAsync(x => x.ProblemId == problemId && x.Id == id, token);

            if (ret == null)
            {
                return(Result <TestCaseWithContent>(404, "Not Found"));
            }
            else if (!await HasPermissionToProblemAsync(problemId, token) &&
                     !await DB.TestCasePurchases.AnyAsync(x => x.ProblemId == problemId && x.UserId == User.Current.Id, token))
            {
                return(Result <TestCaseWithContent>(401, "No Permission"));
            }
            else
            {
                return(File((await MgmtSvc.GetBlobAsync(ret.OutputBlobId, token)).Body, "text/plain", "output.txt"));
            }
        }
コード例 #13
0
        public async Task <IActionResult> Upload([FromServices] ManagementServiceClient mgmt)
        {
            var context = HttpContext;
            var file    = context.Request.Form.Files["file"];

            if (file != null)
            {
                var id = await mgmt.PutBlobAsync("joyoi_online_judge_upload_" + file.FileName, file.ReadAllBytes());

                var f = new
                {
                    Id            = id,
                    Time          = DateTime.Now,
                    ContentType   = file.ContentType,
                    ContentLength = file.Length,
                    FileName      = file.GetFileName(),
                    Bytes         = file.ReadAllBytes()
                };

                return(Json(f));
            }
            else
            {
                var blob = new Base64StringFile(context.Request.Form["file"]);
                var id   = await mgmt.PutBlobAsync("joyoi_online_judge_upload_file", blob.AllBytes);

                var f = new
                {
                    Id            = id,
                    Time          = DateTime.Now,
                    ContentType   = blob.ContentType,
                    ContentLength = blob.Base64String.Length,
                    FileName      = "file",
                    Bytes         = blob.AllBytes
                };

                return(Json(f));
            }
        }
コード例 #14
0
ファイル: HackController.cs プロジェクト: syh325/OnlineJudge
        public async Task<IActionResult> GetData(
            Guid id,
            [FromServices] ManagementServiceClient mgmt,
            [FromServices] ContestExecutorFactory cef,
            CancellationToken token)
        {
            var hack = await DB.HackStatuses
                .Include(x => x.Status)
                .SingleOrDefaultAsync(x => x.Id == id);

            if (hack == null)
            {
                return Result(404, "Hack status is not found");
            }

            if (!hack.HackDataBlobId.HasValue)
            {
                return Result(404, "The hack data is not found");
            }

            if (!string.IsNullOrEmpty(hack.ContestId))
            {
                var ce = cef.Create(hack.ContestId);
                if (!IsMasterOrHigher && !await HasPermissionToProblemAsync(hack.Status.ProblemId, token) && ce.IsContestInProgress() && User.Current?.Id != hack.UserId)
                {
                    return Result(401, "No permission");
                }
            }
            else
            {
                if (!IsMasterOrHigher && !await HasPermissionToProblemAsync(hack.Status.ProblemId, token) && User.Current?.Id != hack.UserId)
                {
                    return Result(401, "No permission");
                }
            }

            var blob = await mgmt.GetBlobAsync(hack.HackDataBlobId.Value, token);
            return Result(Encoding.UTF8.GetString(blob.Body));
        }
コード例 #15
0
ファイル: Program.cs プロジェクト: JoyOI/VirtualJudge
        static void Main(string[] args)
        {
            var client = new ManagementServiceClient("https://mgmtsvc.1234.sh", @"C:\Users\Yuko\Documents\webapi-client.pfx", "123456");

            /* Judge Related */
            client.PatchActorAsync("BzojJudgeActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.Bzoj\BzojJudgeActor.cs")).Wait();
            client.PatchActorAsync("LeetCodeJudgeActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.LeetCode\LeetCodeJudgeActor.cs")).Wait();
            client.PatchActorAsync("CodeVSJudgeActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.CodeVS\CodeVSJudgeActor.cs")).Wait();
            client.PatchStateMachineDefinitionAsync("VirtualJudgeStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\Shared\JoyOI.VirtualJudge.StateMachine\VirtualJudgeStateMachine.cs"), null).Wait();

            /* Problem Related */
            client.PatchActorAsync("BzojPullProblemSetActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.Bzoj\BzojPullProblemSetActor.cs")).Wait();
            client.PatchActorAsync("BzojPullProblemBodyActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.Bzoj\BzojPullProblemBodyActor.cs")).Wait();
            client.PatchStateMachineDefinitionAsync("BzojSyncProblemStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.Bzoj\BzojSyncProblemStateMachine.cs"), null).Wait();

            client.PatchActorAsync("LeetCodePullProblemSetActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.LeetCode\LeetCodePullProblemSetActor.cs")).Wait();
            client.PatchActorAsync("LeetCodePullProblemBodyActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.LeetCode\LeetCodePullProblemBodyActor.cs")).Wait();
            client.PatchStateMachineDefinitionAsync("LeetCodeSyncProblemStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.LeetCode\LeetCodeSyncProblemStateMachine.cs"), null).Wait();

            client.PatchActorAsync("CodeVSPullProblemSetActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.CodeVS\CodeVSPullProblemSetActor.cs")).Wait();
            client.PatchActorAsync("CodeVSPullProblemBodyActor", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.CodeVS\CodeVSPullProblemBodyActor.cs")).Wait();
            client.PatchStateMachineDefinitionAsync("CodeVSSyncProblemStateMachine", File.ReadAllText(@"C:\Users\Yuko\Documents\GitHub\VirtualJudge\src\JoyOI.VirtualJudge.CodeVS\CodeVSSyncProblemStateMachine.cs"), null).Wait();

            ///* Trigger Pulling BZOJ */
            //var stateMachineId = client.PutStateMachineInstanceAsync("BzojSyncProblemStateMachine", "http://api.oj.joyoi.cn", null, 3).Result;
            //Console.WriteLine(stateMachineId);

            ///* Trigger Pulling LeetCode */
            //var stateMachineId = client.PutStateMachineInstanceAsync("LeetCodeSyncProblemStateMachine", "http://api.oj.joyoi.cn", null, 3).Result;
            //Console.WriteLine(stateMachineId);

            ///* Trigger Pulling CodeVS */
            //var stateMachineId = client.PutStateMachineInstanceAsync("CodeVSSyncProblemStateMachine", "http://api.oj.joyoi.cn", null, 3).Result;
            //Console.WriteLine(stateMachineId);

            Console.Read();
        }
コード例 #16
0
ファイル: HackController.cs プロジェクト: syh325/OnlineJudge
        public async Task<IActionResult> Put(
            [FromServices] ContestExecutorFactory cef, 
            [FromServices] ManagementServiceClient mgmt,
            [FromServices] IHubContext<OnlineJudgeHub> hub,
            CancellationToken token)
        {
            var request = JsonConvert.DeserializeObject<HackRequest>(RequestBody);

            if (!User.IsSignedIn())
            {
                return Result(403, "Please login first.");
            }

            var judge = await DB.JudgeStatuses
                .Include(x => x.Problem)
                .SingleOrDefaultAsync(x => x.Id == request.JudgeStatusId, token);

            if (judge == null)
            {
                return Result(404, "The judge status is not found");
            }

            if (!judge.BinaryBlobId.HasValue)
            {
                return Result(400, "The lagency status could not be hacked.");
            }

            if (judge.UserId == User.Current.Id)
            {
                return Result(400, "You cannot hack yourself.");
            }
            
            if (IsGroupRequest() && !await IsGroupMemberAsync(token))
            {
                return Result(401, "You are not a member of this group.");
            }

            if (!string.IsNullOrEmpty(request.ContestId))
            {
                var ce = cef.Create(request.ContestId);

                if (!ce.IsStatusHackable(judge) || !ce.IsContestInProgress())
                {
                    return Result(400, "You cannot hack this status");
                }

                if (await DB.HackStatuses.AnyAsync(x => x.UserId == User.Current.Id && x.JudgeStatusId == request.JudgeStatusId && x.Result == HackResult.Succeeded && x.ContestId == request.ContestId, token))
                {
                    return Result(400, "You have already hacked this status.");
                }
            }

            // Upload hack data to management service
            if (request.IsBase64)
            {
                request.Data = request.Data.Substring(request.Data.IndexOf("base64,") + "base64,".Length);
            }
            var blobId = await mgmt.PutBlobAsync("data.txt", request.IsBase64 ? Convert.FromBase64String(request.Data) : Encoding.UTF8.GetBytes(request.Data), token);

            var hack = new HackStatus
            {
                ContestId = request.ContestId,
                JudgeStatusId = judge.Id,
                HackDataBlobId = blobId,
                Result = HackResult.Pending,
                Time = DateTime.UtcNow,
                UserId = User.Current.Id,
                HackeeResult = JudgeResult.Pending
            };
            DB.HackStatuses.Add(hack);
            await DB.SaveChangesAsync(token);

            var blobs = new List<BlobInfo>(10);

            // Put the limit.json into blob collection
            blobs.Add(new BlobInfo
            {
                Id = await mgmt.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
                {
                    UserTime = judge.Problem.TimeLimitationPerCaseInMs,
                    PhysicalTime = judge.Problem.TimeLimitationPerCaseInMs * 4,
                    Memory = judge.Problem.MemoryLimitationPerCaseInByte
                }))),
                Name = "limit.json",
                Tag = "Problem=" + judge.ProblemId
            });

            // Put the data into blob collection
            blobs.Add(new BlobInfo(blobId, "data.txt"));

            // Put the hackee program into blob collection
            blobs.Add(new BlobInfo(judge.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(judge.Language), judge.Id.ToString()));

            // Put range validator program into blob collection
            if (judge.Problem.RangeBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.RangeError))
            {
                blobs.Add(new BlobInfo(judge.Problem.RangeBlobId.Value, "Range" + Constants.GetBinaryExtension(judge.Problem.RangeLanguage)));
            }

            // Put standard program into blob collection
            if (judge.Problem.StandardBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.StandardError))
            {
                blobs.Add(new BlobInfo(judge.Problem.StandardBlobId.Value, "Standard" + Constants.GetBinaryExtension(judge.Problem.StandardLanguage)));
            }
            else
            {
                // Get 3 accepted programs instead of standard program
                var statuses = await DB.JudgeStatuses
                    .Where(x => x.Result == JudgeResult.Accepted && x.ProblemId == judge.ProblemId && x.BinaryBlobId.HasValue && x.Id != judge.Id)
                    .OrderBy(x => x.TimeUsedInMs)
                    .ThenBy(x => x.MemoryUsedInByte)
                    .Take(3)
                    .ToListAsync(token);

                if (statuses.Count == 0)
                {
                    return Result(400, "Missing standard program, this status could not be hacked");
                }

                var standards = statuses.Select(x => new BlobInfo(x.BinaryBlobId.Value, "Standard-" + x.Id.ToString().Substring(0,8) + Constants.GetBinaryExtension(x.Language), x.Id.ToString()));
                blobs.AddRange(standards);
            }

            // Put validator into blob collection
            if (judge.Problem.ValidatorBlobId.HasValue)
            {
                blobs.Add(new BlobInfo(judge.Problem.ValidatorBlobId.Value, "Validator" + Constants.GetBinaryExtension(judge.Problem.ValidatorLanguage)));
            }
            else
            {
                blobs.Add(new BlobInfo(Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]), "Validator.out"));
            }

            // Start hack state machine
            var stateMachineId = await mgmt.PutStateMachineInstanceAsync("HackStateMachine", Configuration["ManagementService:CallBack"], blobs.ToArray(), 1, token);
            var stateMachine = new StateMachine { CreatedTime = DateTime.Now, Name = "HackStateMachine", Id = stateMachineId };
            DB.StateMachines.Add(stateMachine);
            hack.RelatedStateMachineIds = new List<HackStatusStateMachine>();
            hack.RelatedStateMachineIds.Add(new HackStatusStateMachine { StateMachineId = stateMachine.Id, StatusId = judge.Id });
            await DB.SaveChangesAsync(token);

            hub.Clients.All.InvokeAsync("ItemUpdated", "hack", hack.Id);

            return Result(hack.Id);
        }
コード例 #17
0
        public async Task <IActionResult> Put(
            [FromServices] IConfiguration Config,
            [FromServices] IServiceScopeFactory scopeFactory,
            [FromServices] StateMachineAwaiter awaiter,
            [FromServices] ManagementServiceClient MgmtSvc,
            [FromServices] IHubContext <OnlineJudgeHub> hub,
            [FromServices] ContestExecutorFactory cef,
            CancellationToken token)
        {
            var request = JsonConvert.DeserializeObject <JudgeRequest>(RequestBody);
            var problem = await DB.Problems
                          .Include(x => x.TestCases)
                          .SingleOrDefaultAsync(x => x.Id == request.problemId, token);

            if (problem == null)
            {
                return(Result(400, "The problem is not exist."));
            }

            if (!problem.IsVisible && string.IsNullOrWhiteSpace(request.contestId) && !await HasPermissionToProblemAsync(problem.Id, token))
            {
                return(Result(403, "You have no permission to the problem."));
            }

            if (IsGroupRequest() && !await IsGroupMemberAsync(token))
            {
                return(Result(401, "You are not a member of this group."));
            }

            if (!Constants.SupportedLanguages.Contains(request.language))
            {
                return(Result(400, "The language has not been supported."));
            }
            if (string.IsNullOrEmpty(request.code))
            {
                return(Result(400, "Code could not be empty."));
            }

            if (!string.IsNullOrEmpty(request.contestId))
            {
                var ce = cef.Create(request.contestId);

                if (!ce.IsContestInProgress(User.Current?.UserName))
                {
                    return(Result(400, "The contest is inactive."));
                }

                if (request.isSelfTest)
                {
                    return(Result(400, "You could not do a self test during the contest is in progress."));
                }

                if (await DB.ContestProblemLastStatuses.AnyAsync(x => x.IsLocked && x.ContestId == request.contestId && User.Current.Id == x.UserId && x.ProblemId == request.problemId, token))
                {
                    return(Result(400, "You have locked this problem."));
                }
            }

            if (!Constants.SupportedLanguages.Contains(request.language) && !Constants.UnsupportedLanguages.Contains(request.language) && problem.Source == ProblemSource.Local)
            {
                return(Result(400, "The programming language which you selected was not supported"));
            }

            if (request.isSelfTest && request.data.Count() == 0)
            {
                return(Result(400, "The self testing data has not been found"));
            }

            if (problem.Source != ProblemSource.Local && request.isSelfTest)
            {
                return(Result(400, "You could not use self data to test with a remote problem."));
            }

            if (IsGroupRequest() && !await DB.GroupProblems.AnyAsync(x => x.ProblemId == problem.Id && x.GroupId == CurrentGroup.Id) && string.IsNullOrEmpty(request.contestId))
            {
                return(Result(404, "The problem does not exist."));
            }

            #region Local Judge
            if (problem.Source == ProblemSource.Local)
            {
                var blobs = new ConcurrentDictionary <int, BlobInfo[]>();
                blobs.TryAdd(-1, new[] { new BlobInfo
                                         {
                                             Id   = await MgmtSvc.PutBlobAsync("Main" + Constants.GetSourceExtension(request.language), Encoding.UTF8.GetBytes(request.code)),
                                             Name = "Main" + Constants.GetSourceExtension(request.language),
                                             Tag  = "Problem=" + problem.Id
                                         } });
                blobs.TryAdd(-2, new[] { new BlobInfo
                                         {
                                             Id = await MgmtSvc.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
                        {
                            UserTime     = problem.TimeLimitationPerCaseInMs,
                            PhysicalTime = problem.TimeLimitationPerCaseInMs * 4,
                            Memory       = problem.MemoryLimitationPerCaseInByte
                        }))),
                                             Name = "limit.json",
                                             Tag  = "Problem=" + problem.Id
                                         } });
                if (!problem.ValidatorBlobId.HasValue)
                {
                    blobs.TryAdd(-3, new[]
                    {
                        new BlobInfo
                        {
                            Id   = Guid.Parse(Config["JoyOI:StandardValidatorBlobId"]),
                            Name = "Validator.out"
                        }
                    });
                }
                else
                {
                    blobs.TryAdd(-3, new[]
                    {
                        new BlobInfo
                        {
                            Id   = problem.ValidatorBlobId.Value,
                            Name = "Validator" + Constants.GetBinaryExtension(problem.ValidatorLanguage)
                        }
                    });
                }

                List <TestCase> testCases = null;
                if (request.isSelfTest)
                {
                    Parallel.For(0, request.data.Count(), i =>
                    {
                        // Uploading custom data
                        var inputId  = MgmtSvc.PutBlobAsync($"input_{ i }.txt", Encoding.UTF8.GetBytes(request.data.ElementAt(i).input), token).Result;
                        var outputId = MgmtSvc.PutBlobAsync($"output_{ i }.txt", Encoding.UTF8.GetBytes(request.data.ElementAt(i).output), token).Result;
                        blobs.TryAdd(i, new[] {
                            new BlobInfo {
                                Id = inputId, Name = $"input_{ i }.txt", Tag = i.ToString()
                            },
                            new BlobInfo {
                                Id = outputId, Name = $"output_{ i }.txt", Tag = i.ToString()
                            }
                        });
                    });
                }
                else
                {
                    testCases = await DB.TestCases
                                .Where(x => x.ProblemId == problem.Id && (x.Type == TestCaseType.Small || x.Type == TestCaseType.Large || x.Type == TestCaseType.Hack))
                                .ToListAsync(token);

                    if (testCases.Count == 0)
                    {
                        return(Result(400, "No test case found."));
                    }

                    for (var i = 0; i < testCases.Count; i++)
                    {
                        blobs.TryAdd(i, new[] {
                            new BlobInfo {
                                Id = testCases[i].InputBlobId, Name = $"input_{ i }.txt", Tag = i.ToString()
                            },
                            new BlobInfo {
                                Id = testCases[i].OutputBlobId, Name = $"output_{ i }.txt", Tag = i.ToString()
                            }
                        });
                    }
                }

                var stateMachineId = await MgmtSvc.PutStateMachineInstanceAsync("JudgeStateMachine", Config["ManagementService:CallBack"], blobs.SelectMany(x => x.Value), await CalculatePriorityAsync(), token);

                var substatuses = blobs
                                  .Where(x => x.Key >= 0)
                                  .Select(x => new SubJudgeStatus
                {
                    SubId        = x.Key,
                    Result       = JudgeResult.Pending,
                    InputBlobId  = x.Value.Single(y => y.Name.StartsWith("input_")).Id,
                    OutputBlobId = x.Value.Single(y => y.Name.StartsWith("output_")).Id,
                    TestCaseId   = testCases != null ? (Guid?)testCases[x.Key].Id : null
                })
                                  .ToList();

                var status = new JudgeStatus
                {
                    Code                   = request.code,
                    Language               = request.language,
                    Result                 = JudgeResult.Pending,
                    CreatedTime            = DateTime.UtcNow,
                    ContestId              = request.contestId,
                    SubStatuses            = substatuses,
                    ProblemId              = problem.Id,
                    UserId                 = User.Current.Id,
                    IsSelfTest             = request.isSelfTest,
                    RelatedStateMachineIds = new List <JudgeStatusStateMachine>
                    {
                        new JudgeStatusStateMachine
                        {
                            StateMachine = new StateMachine
                            {
                                CreatedTime = DateTime.UtcNow,
                                Name        = "JudgeStateMachine",
                                Id          = stateMachineId
                            },
                            StateMachineId = stateMachineId
                        }
                    },
                };

                if (IsGroupRequest())
                {
                    status.GroupId = CurrentGroup.Id;
                }

                DB.JudgeStatuses.Add(status);
                await DB.SaveChangesAsync(token);

                hub.Clients.All.InvokeAsync("ItemUpdated", "judge", status.Id);

                // For debugging
                if (Config["ManagementService:Mode"] == "Polling")
                {
                    Task.Factory.StartNew(async() =>
                    {
                        using (var scope = scopeFactory.CreateScope())
                            using (var db = scope.ServiceProvider.GetService <OnlineJudgeContext>())
                            {
                                try
                                {
                                    await awaiter.GetStateMachineResultAsync(stateMachineId);
                                    var handler = scope.ServiceProvider.GetService <JudgeStateMachineHandler>();
                                    await handler.HandleJudgeResultAsync(stateMachineId, default(CancellationToken));
                                }
                                catch (Exception ex)
                                {
                                    Console.Error.WriteLine(ex);
                                }
                            }
                    });
                }
                return(Result(status.Id));
            }
            #endregion
            #region Bzoj, LeetCode, CodeVS
            else if (problem.Source == ProblemSource.Bzoj || problem.Source == ProblemSource.LeetCode || problem.Source == ProblemSource.CodeVS)
            {
                var metadata = new
                {
                    Source    = problem.Source.ToString(),
                    Language  = request.language,
                    Code      = request.code,
                    ProblemId = problem.Id.Replace(problem.Source.ToString().ToLower() + "-", "")
                };

                var metadataBlob = new BlobInfo
                {
                    Id   = await MgmtSvc.PutBlobAsync("metadata.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(metadata)), token),
                    Name = "metadata.json",
                    Tag  = "Problem=" + problem.Id
                };

                var stateMachineId = await MgmtSvc.PutStateMachineInstanceAsync("VirtualJudgeStateMachine", Config["ManagementService:Callback"], new[] { metadataBlob }, await CalculatePriorityAsync(), token);

                var status = new JudgeStatus
                {
                    Code                   = request.code,
                    ContestId              = request.contestId,
                    Language               = request.language,
                    ProblemId              = problem.Id,
                    IsSelfTest             = false,
                    UserId                 = User.Current.Id,
                    Result                 = JudgeResult.Pending,
                    RelatedStateMachineIds = new List <JudgeStatusStateMachine>
                    {
                        new JudgeStatusStateMachine {
                            StateMachine = new StateMachine
                            {
                                CreatedTime = DateTime.UtcNow,
                                Name        = "JudgeStateMachine",
                                Id          = stateMachineId
                            },
                            StateMachineId = stateMachineId
                        }
                    }
                };

                if (IsGroupRequest())
                {
                    status.GroupId = CurrentGroup.Id;
                }

                DB.JudgeStatuses.Add(status);
                await DB.SaveChangesAsync(token);

                // For debugging
                if (Config["ManagementService:Mode"] == "Polling")
                {
                    Task.Factory.StartNew(async() =>
                    {
                        using (var scope = scopeFactory.CreateScope())
                        {
                            try
                            {
                                await awaiter.GetStateMachineResultAsync(stateMachineId);
                                var handler = scope.ServiceProvider.GetService <JudgeStateMachineHandler>();
                                await handler.HandleJudgeResultAsync(stateMachineId, default(CancellationToken));
                            }
                            catch (Exception ex)
                            {
                                Console.Error.WriteLine(ex);
                            }
                        }
                    });
                }

                hub.Clients.All.InvokeAsync("ItemUpdated", "judge", status.Id);

                return(Result(status.Id));
            }
            #endregion
            #region Others
            else
            {
                throw new NotSupportedException(problem.Source.ToString() + " has not been supported yet.");
            }
            #endregion
        }
コード例 #18
0
 public JudgeStateMachineHandler(OnlineJudgeContext db, IHubContext <OnlineJudgeHub> hub, ManagementServiceClient mgmt)
 {
     _db   = db;
     _hub  = hub;
     _mgmt = mgmt;
 }
コード例 #19
0
 public StateMachineAwaiter(IConfiguration configuration, ManagementServiceClient managementServiceClient)
 {
     _configuration           = configuration;
     _managementServiceClient = managementServiceClient;
 }
コード例 #20
0
        public async Task <IActionResult> Patch(
            string id,
            [FromServices] ManagementServiceClient MgmtSvc,
            [FromServices] StateMachineAwaiter Awaiter,
            [FromServices] IHubContext <OnlineJudgeHub> hub,
            CancellationToken token)
        {
            if (!await HasPermissionToProblemAsync(id, token))
            {
                return(Result(401, "No Permission"));
            }
            else
            {
                var problem = await DB.Problems.SingleOrDefaultAsync(x => x.Id == id, token);

                if (problem == null)
                {
                    return(Result(404, "Not Found"));
                }

                var fields = PatchEntity(problem, RequestBody);

                // Check difficulty range
                if (fields.Any(x => x == nameof(Problem.Difficulty)) && (problem.Difficulty < 0 || problem.Difficulty > 9))
                {
                    return(Result(400, "The difficulty must be 0-9."));
                }

                // Update validator
                if (fields.Any(x => x == nameof(Problem.ValidatorCode)) || fields.Any(x => x == nameof(Problem.ValidatorLanguage)))
                {
                    if (string.IsNullOrWhiteSpace(problem.ValidatorCode))
                    {
                        problem.ValidatorBlobId   = null;
                        problem.ValidatorCode     = null;
                        problem.ValidatorError    = null;
                        problem.ValidatorLanguage = null;
                    }
                    else
                    {
                        var validatorCodeId = await MgmtSvc.PutBlobAsync("validator-" + problem.Id, Encoding.UTF8.GetBytes(problem.ValidatorCode), token);

                        var stateMachineId = await MgmtSvc.PutStateMachineInstanceAsync("CompileOnlyStateMachine", Configuration["ManagementService:CallBack"], new BlobInfo[] { new BlobInfo(validatorCodeId, "Main" + Constants.GetSourceExtension(problem.ValidatorLanguage)) });

                        var result = await Awaiter.GetStateMachineResultAsync(stateMachineId, true, token);

                        var runner = JsonConvert.DeserializeObject <dynamic>(Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(result.StartedActors.Last().Outputs.Single(x => x.Name == "runner.json").Id, token)).Body));
                        if (result.StartedActors.Any(x => x.Name == "CompileActor" && runner.ExitCode == 0 && x.Status == JoyOI.ManagementService.Model.Enums.ActorStatus.Succeeded))
                        {
                            problem.ValidatorBlobId = result.StartedActors.Last().Outputs.Single(x => x.Name.StartsWith("Main.")).Id;
                            problem.ValidatorError  = null;
                        }
                        else
                        {
                            problem.ValidatorBlobId = null;
                            problem.ValidatorError  = runner.Error;
                        }
                    }
                }

                // Update standard
                if (fields.Any(x => x == nameof(Problem.StandardCode)) || fields.Any(x => x == nameof(Problem.StandardLanguage)))
                {
                    if (string.IsNullOrWhiteSpace(problem.StandardCode))
                    {
                        problem.StandardBlobId   = null;
                        problem.StandardCode     = null;
                        problem.StandardError    = null;
                        problem.StandardLanguage = null;
                    }
                    else
                    {
                        var standardCodeId = await MgmtSvc.PutBlobAsync("standard-" + problem.Id, Encoding.UTF8.GetBytes(problem.StandardCode), token);

                        var stateMachineId = await MgmtSvc.PutStateMachineInstanceAsync("CompileOnlyStateMachine", Configuration["ManagementService:CallBack"], new BlobInfo[] { new BlobInfo(standardCodeId, "Main" + Constants.GetSourceExtension(problem.StandardLanguage)) });

                        var result = await Awaiter.GetStateMachineResultAsync(stateMachineId, true, token);

                        var runner = JsonConvert.DeserializeObject <dynamic>(Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(result.StartedActors.Last().Outputs.Single(x => x.Name == "runner.json").Id, token)).Body));
                        if (result.StartedActors.Any(x => x.Name == "CompileActor" && runner.ExitCode == 0 && x.Status == JoyOI.ManagementService.Model.Enums.ActorStatus.Succeeded))
                        {
                            problem.StandardBlobId = result.StartedActors.Last().Outputs.Single(x => x.Name.StartsWith("Main.")).Id;
                            problem.StandardError  = null;
                        }
                        else
                        {
                            problem.StandardBlobId = null;
                            problem.StandardError  = runner.Error;
                        }
                    }
                }

                // Update range
                if (fields.Any(x => x == nameof(Problem.RangeCode)) || fields.Any(x => x == nameof(Problem.RangeLanguage)))
                {
                    if (string.IsNullOrWhiteSpace(problem.RangeCode))
                    {
                        problem.RangeBlobId   = null;
                        problem.RangeCode     = null;
                        problem.RangeError    = null;
                        problem.RangeLanguage = null;
                    }
                    else
                    {
                        var rangeCodeId = await MgmtSvc.PutBlobAsync("range-" + problem.Id, Encoding.UTF8.GetBytes(problem.RangeCode), token);

                        var stateMachineId = await MgmtSvc.PutStateMachineInstanceAsync("CompileOnlyStateMachine", Configuration["ManagementService:CallBack"], new BlobInfo[] { new BlobInfo(rangeCodeId, "Main" + Constants.GetSourceExtension(problem.RangeLanguage)) });

                        var result = await Awaiter.GetStateMachineResultAsync(stateMachineId, true, token);

                        var runner = JsonConvert.DeserializeObject <dynamic>(Encoding.UTF8.GetString((await MgmtSvc.GetBlobAsync(result.StartedActors.Last().Outputs.Single(x => x.Name == "runner.json").Id, token)).Body));
                        if (result.StartedActors.Any(x => x.Name == "CompileActor" && runner.ExitCode == 0 && x.Status == JoyOI.ManagementService.Model.Enums.ActorStatus.Succeeded))
                        {
                            problem.RangeBlobId = result.StartedActors.Last().Outputs.Single(x => x.Name.StartsWith("Main.")).Id;
                            problem.RangeError  = null;
                        }
                        else
                        {
                            problem.RangeBlobId = null;
                            problem.RangeError  = runner.Error;
                        }
                    }
                }

                if ((string.IsNullOrWhiteSpace(problem.Tags) || problem.Tags.IndexOf(LocalProblemSetTag) < 0) && problem.Source == ProblemSource.Local)
                {
                    problem.Tags += "," + LocalProblemSetTag;
                    problem.Tags  = problem.Tags.Trim(',');
                }

                await DB.SaveChangesAsync(token);

                hub.Clients.All.InvokeAsync("ItemUpdated", "problem", problem.Id);
                if (fields.Any(x => x == nameof(Problem.Title)) || fields.Any(x => x == nameof(Problem.IsVisible)))
                {
                    hub.Clients.All.InvokeAsync("ItemUpdated", "problem-list", problem.Id);
                }

                return(Result(200, "Patch Succeeded"));
            }
        }