예제 #1
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));
            }
        }
예제 #2
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
        }
예제 #3
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"));
            }
        }
        public override void OnHackCompleted(HackStatus status)
        {
            if (status.Result == HackResult.Succeeded)
            {
                // 1. Set the status to be non-hackable
                DB.ContestProblemLastStatuses
                .Where(x => x.StatusId == status.JudgeStatusId && x.ContestId == ContestId)
                .SetField(x => x.IsHackable).WithValue(false)
                .SetField(x => x.IsHacked).WithValue(true)
                .Update();

                // 2. Add the hack data to problem
                var input           = status.HackDataBlobId.Value;
                var testCase        = DB.TestCases.FirstOrDefault(x => x.InputBlobId == input && x.ProblemId == status.Status.ProblemId);
                var testCaseExisted = testCase != null;
                if (!testCaseExisted)
                {
                    var inputLength  = ManagementService.GetBlobAsync(input).Result.Body.Length;
                    var stateMachine = ManagementService.GetStateMachineInstanceAsync(status.RelatedStateMachineIds.Last().StateMachineId).Result;
                    var output       = stateMachine.StartedActors.First(x => x.Tag == "Standard").Outputs.First(x => x.Name == "stdout.txt").Id;
                    var outputLength = ManagementService.GetBlobAsync(output).Result.Body.Length;

                    testCase = new TestCase
                    {
                        ContestId        = ContestId,
                        InputBlobId      = input,
                        InputSizeInByte  = inputLength,
                        OutputBlobId     = output,
                        OutputSizeInByte = outputLength,
                        ProblemId        = status.Status.ProblemId,
                        Type             = TestCaseType.Hack
                    };
                    DB.TestCases.Add(testCase);
                    DB.SaveChanges();
                }

                // 3. Add the result into sub judge status
                if (!testCaseExisted)
                {
                    var sub = new SubJudgeStatus
                    {
                        SubId            = DB.SubJudgeStatuses.Where(x => x.StatusId == status.JudgeStatusId).Count(),
                        Hint             = status.Hint,
                        MemoryUsedInByte = status.MemoryUsedInByte,
                        TimeUsedInMs     = status.TimeUsedInMs,
                        Result           = status.HackeeResult,
                        InputBlobId      = testCase.InputBlobId,
                        OutputBlobId     = testCase.OutputBlobId,
                        TestCaseId       = testCase.Id,
                        StatusId         = status.JudgeStatusId
                    };
                    DB.SubJudgeStatuses.Add(sub);
                    DB.SaveChanges();
                }

                // 4. Add point for the hacker
                DB.ContestProblemLastStatuses
                .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId)
                .SetField(x => x.Point2).Plus(1)
                .Update();

                // 5. Hack all statuses
                if (!testCaseExisted && DB.Attendees.Any(x => x.ContestId == ContestId && x.UserId == status.UserId && !x.IsVirtual))
                {
                    var affectedStatuses = DB.ContestProblemLastStatuses
                                           .Include(x => x.Status)
                                           .Where(x => x.ProblemId == status.Status.ProblemId && x.ContestId == ContestId && x.Status.BinaryBlobId.HasValue && x.IsAccepted)
                                           .ToList();

                    var problem     = DB.Problems.Single(x => x.Id == status.Status.ProblemId);
                    var validatorId = problem.ValidatorBlobId.HasValue ? problem.ValidatorBlobId.Value : Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]);

                    var blobs = new List <BlobInfo>(affectedStatuses.Count + 10);
                    blobs.Add(new BlobInfo
                    {
                        Id = ManagementService.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
                        {
                            UserTime     = status.Status.Problem.TimeLimitationPerCaseInMs,
                            PhysicalTime = status.Status.Problem.TimeLimitationPerCaseInMs * 4,
                            Memory       = status.Status.Problem.MemoryLimitationPerCaseInByte
                        }))).Result,
                        Name = "limit.json",
                        Tag  = "Problem=" + status.Status.ProblemId
                    });
                    blobs.Add(new BlobInfo(validatorId, problem.ValidatorBlobId.HasValue ? "Validator" + Constants.GetBinaryExtension(problem.ValidatorLanguage) : "Validator.out"));
                    blobs.Add(new BlobInfo(status.HackDataBlobId.Value, "data.txt", testCase.Id.ToString()));
                    blobs.Add(new BlobInfo(testCase.OutputBlobId, "std.txt", testCase.Id.ToString()));
                    foreach (var x in affectedStatuses)
                    {
                        blobs.Add(new BlobInfo(x.Status.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(x.Status.Language), x.StatusId.ToString()));
                    }

                    ManagementService.PutStateMachineInstanceAsync("HackAllStateMachine", Configuration["ManagementService:CallBack"], blobs, 2);
                }
            }
            else if (status.Result == HackResult.Failed)
            {
                DB.ContestProblemLastStatuses
                .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId)
                .SetField(x => x.Point2).Subtract(1)
                .SetField(x => x.Point3).Plus(1)
                .Update();
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        public async Task <ActionResult> Create(int problem_id, string code, int language_id, int?contest_id)
        {
            var problem = DbContext.Problems.Find(problem_id);
            var user    = (User)ViewBag.CurrentUser;

            if (problem == null || (problem.Hide && !IsMaster() && CurrentUser.ID != problem.ID && !contest_id.HasValue))
            {
                return(Content("Problem not existed"));
            }
            if (problem.VIP && user.Role < UserRole.VIP && problem.UserID != user.ID)
            {
                return(Content("Need VIP"));
            }
            Contest contest = new Contest();

            if (contest_id != null)
            {
                contest = DbContext.Contests.Find(contest_id.Value);
                if (DateTime.Now < contest.Begin || DateTime.Now >= contest.End)
                {
                    return(Content("Insufficient permissions"));
                }
                if (contest.ContestProblems.Where(x => x.ProblemID == problem_id).Count() == 0)
                {
                    return(Content("Insufficient permissions"));
                }
                if (!Helpers.Contest.UserInContest(user.ID, contest_id.Value))
                {
                    return(Content("Insufficient permissions"));
                }
                ContestFormat[] SubmitAnyTime = { ContestFormat.ACM, ContestFormat.OI };
                if (DateTime.Now < contest.Begin && user.Role < UserRole.Master && contest.UserID != user.ID)
                {
                    return(Content("Insufficient permissions"));
                }
                if (contest.Format == ContestFormat.Codeforces && (from l in DbContext.Locks where l.ProblemID == problem_id && user.ID == l.UserID && l.ContestID == contest_id.Value select l).Count() > 0 && DateTime.Now < contest.End)
                {
                    return(Content("Locked"));
                }
            }

            var status = new Status
            {
                Code          = code,
                LanguageAsInt = language_id,
                ProblemID     = problem_id,
                UserID        = user.ID,
                Time          = DateTime.Now,
                Result        = JudgeResult.Pending,
                ContestID     = contest_id,
                Score         = 0,
                TimeUsage     = 0,
                MemoryUsage   = 0
            };

            DbContext.Statuses.Add(status);
            problem.SubmitCount++;
            user.SubmitCount++;
            var submitlist = Helpers.AcList.GetList(user.SubmitList);

            submitlist.Add(problem.ID);
            user.SubmitList = Helpers.AcList.ToString(submitlist);
            var _testcase_ids = (from tc in problem.TestCases
                                 where tc.Type != TestCaseType.Sample
                                 orderby tc.Type ascending
                                 select new { tc.ID, tc.InputBlobId })
                                .ToList();
            var testcase_ids = _testcase_ids.Select(x => x.ID).ToList();

            if (contest_id != null)
            {
                if (DateTime.Now < contest.Begin || DateTime.Now >= contest.End || contest.Format == ContestFormat.ACM || contest.Format == ContestFormat.OI)
                {
                    testcase_ids = (from tc in problem.TestCases
                                    where tc.Type != TestCaseType.Sample
                                    orderby tc.Type ascending
                                    select tc.ID).ToList();
                }
                else if (contest.Format == ContestFormat.Codeforces)
                {
                    testcase_ids = (from tc in problem.TestCases
                                    where tc.Type == TestCaseType.Unilateralism
                                    orderby tc.Type ascending
                                    select tc.ID).ToList();
                    var statuses = (from s in DbContext.Statuses
                                    where s.ContestID == contest_id.Value &&
                                    s.UserID == user.ID
                                    select s).ToList();
                    foreach (var s in statuses)
                    {
                        if (s.JudgeTasks == null)
                        {
                            continue;
                        }
                        foreach (var jt in s.JudgeTasks)
                        {
                            testcase_ids.Add(jt.TestCaseID);
                        }
                    }
                    testcase_ids = testcase_ids.Distinct().ToList();
                }
                foreach (var id in testcase_ids)
                {
                    DbContext.JudgeTasks.Add(new JudgeTask
                    {
                        StatusID    = status.ID,
                        TestCaseID  = id,
                        Result      = JudgeResult.Pending,
                        MemoryUsage = 0,
                        TimeUsage   = 0,
                        Hint        = ""
                    });
                }
                DbContext.SaveChanges();
                foreach (var jt in status.JudgeTasks)
                {
                    try
                    {
                        var group = SignalR.JudgeHub.GetNode();
                        if (group == null)
                        {
                            return(Content("No Online Judger"));
                        }
                        SignalR.JudgeHub.context.Clients.Group(group).Judge(new CodeComb.Judge.Models.JudgeTask(jt));
                        SignalR.JudgeHub.ThreadBusy(group);
                    }
                    catch { }
                }
                SignalR.UserHub.context.Clients.Group("Status").onStatusCreated(new vStatus(status));//推送新状态
                if (contest.Format == ContestFormat.OI && DateTime.Now >= contest.Begin && DateTime.Now < contest.End)
                {
                    return(Content("OI"));
                }
            }
            else // 不是比赛任务
            {
                var distinctSet = new HashSet <string>();
                foreach (var id in _testcase_ids)
                {
                    if (distinctSet.Any(x => x == id.InputBlobId && !string.IsNullOrWhiteSpace(id.InputBlobId)))
                    {
                        continue;
                    }
                    distinctSet.Add(id.InputBlobId);
                    DbContext.JudgeTasks.Add(new JudgeTask
                    {
                        StatusID    = status.ID,
                        TestCaseID  = id.ID,
                        Result      = JudgeResult.Pending,
                        MemoryUsage = 0,
                        TimeUsage   = 0,
                        Hint        = ""
                    });
                }
                DbContext.SaveChanges();
                if (string.IsNullOrWhiteSpace(problem.SpecialJudge) && (status.Language == Language.C || status.Language == Language.Cxx || status.Language == Language.Pascal || status.Language == Language.Cxx11 || status.Language == Language.Cxx14 || status.Language == Language.Java)) // 如果是c,c++,pascal则由JoyOI接管评测
                {
                    var sourceName = "Main";                                                                                                                                                                                                                                                   // 拼接选手源代码文件名
                    if (status.Language == Language.C)
                    {
                        sourceName += ".c";
                    }
                    else if (status.Language == Language.Cxx)
                    {
                        sourceName += ".cpp";
                    }
                    else if (status.Language == Language.Cxx11)
                    {
                        sourceName += "11.cpp";
                    }
                    else if (status.Language == Language.Cxx14)
                    {
                        sourceName += "14.cpp";
                    }
                    else if (status.Language == Language.Java)
                    {
                        sourceName += ".java";
                    }
                    else
                    {
                        sourceName += ".pas";
                    }

                    var blobs = new List <BlobInfo>(20);
                    blobs.Add(new BlobInfo {
                        Id = Guid.Parse("0083ca85-9ede-1004-a386-ac64710fd926"), Name = "Validator.out"
                    });                                                                                                        // 将标准比较器放入文件集合中
                    var sourceBlobId = await client.PutBlobAsync(sourceName, System.Text.Encoding.UTF8.GetBytes(status.Code)); // 将选手文件上传至Management Service

                    blobs.Add(new BlobInfo {
                        Id = sourceBlobId, Name = sourceName
                    });                                                               // 将选手代码放入文件集合中

                    // 准备测试用例
                    var caseIndex = 0;
                    foreach (var jt in status.JudgeTasks)
                    {
                        if (string.IsNullOrWhiteSpace(jt.TestCase.InputBlobId)) // 如果Management Service没有该测试用例则上传
                        {
                            var inputCaseBlobId = await client.PutBlobAsync("case_input_" + jt.TestCaseID + ".txt", System.Text.Encoding.UTF8.GetBytes(jt.TestCase.Input));

                            jt.TestCase.InputBlobId = inputCaseBlobId.ToString();
                        }
                        if (string.IsNullOrWhiteSpace(jt.TestCase.OutputBlobId)) // 如果Management Service没有该测试用例则上传
                        {
                            var outputCaseBlobId = await client.PutBlobAsync("case_output_" + jt.TestCaseID + ".txt", System.Text.Encoding.UTF8.GetBytes(jt.TestCase.Output));

                            jt.TestCase.OutputBlobId = outputCaseBlobId.ToString();
                        }
                        if (!blobs.Any(x => x.Id == Guid.Parse(jt.TestCase.InputBlobId)))
                        {
                            blobs.Add(new BlobInfo {
                                Id = Guid.Parse(jt.TestCase.InputBlobId), Name = "input_" + caseIndex + ".txt"
                            });
                            blobs.Add(new BlobInfo {
                                Id = Guid.Parse(jt.TestCase.OutputBlobId), Name = "output_" + caseIndex + ".txt"
                            });
                        }
                        else
                        {
                            continue;
                        }
                        ++caseIndex;
                    }
                    var stateMachineId = await client.PutStateMachineInstanceAsync("TyvjJudgeStateMachine", "http://tyvj.cn", blobs); // 创建StateMachine实例

                    status.StateMachineId = stateMachineId.ToString();
                    DbContext.SaveChanges();
                }
                else
                {
                    foreach (var jt in status.JudgeTasks)
                    {
                        try
                        {
                            var group = SignalR.JudgeHub.GetNode();
                            if (group == null)
                            {
                                return(Content("No Online Judger"));
                            }
                            SignalR.JudgeHub.context.Clients.Group(group).Judge(new CodeComb.Judge.Models.JudgeTask(jt));
                            SignalR.JudgeHub.ThreadBusy(group);
                        }
                        catch { }
                    }
                }
                SignalR.UserHub.context.Clients.Group("Status").onStatusCreated(new vStatus(status));//推送新状态
            }

            SignalR.UserHub.context.Clients.Group("Status").onStatusChanged(new vStatus(status));
            GC.Collect();
            return(Content(status.ID.ToString()));
        }