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)); }
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))); } }
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)); } }
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")); } }
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); }
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")); } }
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)); }
private async Task HandleSingleHackAsync(IEnumerable <ActorInfo> actors, HackStatus hack, JudgeStatus judge, Problem problem, Guid?testCaseId, CancellationToken token) { var sub = new SubJudgeStatus(); var isBadData = false; if (actors.Count(x => x.Name == "CompareActor") == 0) { var rangeValidateActor = actors.FirstOrDefault(x => x.Stage == "ValidateData"); var rangeRunner = rangeValidateActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(rangeValidateActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var runActor = actors.FirstOrDefault(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = runActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (rangeRunner != null && rangeRunner.ExitCode != 0) { isBadData = true; sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.Accepted; sub.Hint = string.Join(Environment.NewLine, rangeValidateActor.Exceptions) + Environment.NewLine + rangeRunner.Error; } else if (runRunner.IsTimeout) { sub.TimeUsedInMs = problem.TimeLimitationPerCaseInMs; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.TimeExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode == 139 || runActor.Exceptions.Any(x => x.Contains("May cause by out of memory")) || runRunner.Error.Contains("std::bad_alloc") || runRunner.PeakMemory > problem.MemoryLimitationPerCaseInByte) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = problem.MemoryLimitationPerCaseInByte; sub.Result = JudgeResult.MemoryExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode != 0) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.RuntimeError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error + Environment.NewLine + $"User process exited with code { runRunner.ExitCode }"; } } else if (actors.Count(x => x.Name == "CompareActor") > 0) { var runners = actors.Where(x => x.Name == "CompareActor").Select(x => x.Outputs.Single(y => y.Name == "runner.json")); var runnerResults = runners.Select(x => _mgmt.ReadBlobAsObjectAsync <Runner>(x.Id, token).Result); var exitCodes = runnerResults.Select(x => x.ExitCode); if (exitCodes.Distinct().Count() > 1) { isBadData = true; } else { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var compareActor = actors.Last(x => x.Name == "CompareActor"); var runner = await _mgmt.ReadBlobAsObjectAsync <Runner>(compareActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (runner.ExitCode < 0 || runner.ExitCode > 2) { sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.SystemError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } else { var validatorOutput = Encoding.UTF8.GetString((await _mgmt.GetBlobAsync(compareActor.Outputs.Single(x => x.Name == "stdout.txt").Id)).Body); sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = (JudgeResult)runner.ExitCode; sub.Hint = validatorOutput + Environment.NewLine + string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } } } else { isBadData = true; } if (hack == null && actors.Count(x => x.Stage == "GenerateHackeeAnswer") > 0 && testCaseId.HasValue) { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var statusId = Guid.Parse(runActor.Tag); var testCase = await _db.TestCases.SingleAsync(x => x.Id == testCaseId.Value, token); var testCases = await _db.TestCases .Where(x => x.ProblemId == problem.Id) .Select(x => x.Id) .ToListAsync(token); var status = await _db.JudgeStatuses .Include(x => x.SubStatuses) .SingleAsync(x => x.Id == statusId, token); sub.StatusId = statusId; sub.TestCaseId = testCaseId.Value; sub.InputBlobId = testCase.InputBlobId; sub.OutputBlobId = testCase.OutputBlobId; sub.SubId = testCases.IndexOf(testCaseId.Value); status.SubStatuses.Add(sub); status.MemoryUsedInByte = status.SubStatuses.Max(x => x.MemoryUsedInByte); status.TimeUsedInMs = status.SubStatuses.Sum(x => x.TimeUsedInMs); status.Result = status.SubStatuses.Max(x => x.Result); _db.SaveChanges(); } if (hack != null) { _db.HackStatuses .Where(x => x.Id == hack.Id) .SetField(x => x.HackeeResult).WithValue(isBadData ? JudgeResult.Accepted : sub.Result) .SetField(x => x.TimeUsedInMs).WithValue(sub.TimeUsedInMs) .SetField(x => x.MemoryUsedInByte).WithValue(sub.MemoryUsedInByte) .SetField(x => x.Result).WithValue(isBadData ? (HackResult.BadData) : (sub.Result == JudgeResult.Accepted ? HackResult.Failed : HackResult.Succeeded)) .SetField(x => x.Hint).WithValue(sub.Hint) .Update(); } }
public async Task HandleJudgeResultAsync( Guid statemachineId, CancellationToken token) { bool isAccepted = false; var statemachine = await _mgmt.GetStateMachineInstanceAsync(statemachineId, token); if (statemachine.Status == ManagementService.Model.Enums.StateMachineStatus.Running && statemachine.Stage != "Finally") { throw new InvalidOperationException("The statemachine status is: " + statemachine.Status.ToString()); } var statusStatemachineRelation = (await _db.JudgeStatusStateMachines.FirstOrDefaultAsync(x => x.StateMachineId == statemachineId, token)); if (statusStatemachineRelation == null) { throw new KeyNotFoundException("Did not find the status which related to the statemachine " + statemachineId); } var statusId = statusStatemachineRelation.StatusId; var status = await _db.JudgeStatuses .AsNoTracking() .Where(x => x.Id == statusId) .Select(x => new { x.ProblemId, x.UserId, x.IsSelfTest, x.ContestId, x.Id }) .FirstOrDefaultAsync(token); var userId = status.UserId; var problemId = status.ProblemId; var isSelfTest = status.IsSelfTest; if (statemachine.Status == ManagementService.Model.Enums.StateMachineStatus.Failed) { _db.JudgeStatuses .Where(x => x.Id == statusId) .SetField(x => x.Hint).WithValue(statemachine.Exception) .SetField(x => x.Result).WithValue(JudgeResult.SystemError) .Update(); } _db.Problems .Where(x => x.Id == problemId) .SetField(x => x.CachedSubmitCount).Plus(1) .Update(); var problem = await _db.Problems.SingleAsync(x => x.Id == problemId, token); #region Local Judge if (problem.Source == ProblemSource.Local) { var compileResult = await IsFailedInCompileStageAsync(statemachine, token); if (compileResult.result) { _db.JudgeStatuses .Where(x => x.Id == statusId) .SetField(x => x.Result).WithValue((int)JudgeResult.CompileError) .SetField(x => x.Hint).WithValue(compileResult.hint) .Update(); _db.SubJudgeStatuses .Where(x => x.StatusId == statusId) .SetField(x => x.Result).WithValue((int)JudgeResult.CompileError) .Update(); } else { var runtimeResult = await HandleRuntimeResultAsync(statemachine, problem.MemoryLimitationPerCaseInByte, token); var finalResult = runtimeResult.Max(x => x.result); var finalTime = runtimeResult.Sum(x => x.time); var finalMemory = runtimeResult.Max(x => x.memory); _db.JudgeStatuses .Where(x => x.Id == statusId) .SetField(x => x.BinaryBlobId).WithValue(Guid.Parse(compileResult.hint)) .SetField(x => x.TimeUsedInMs).WithValue(finalTime) .SetField(x => x.MemoryUsedInByte).WithValue(finalMemory) .SetField(x => x.Result).WithValue((int)finalResult) .Update(); for (var i = 0; i < runtimeResult.Count(); i++) { _db.SubJudgeStatuses .Where(x => x.StatusId == statusId) .Where(x => x.SubId == i) .SetField(x => x.TimeUsedInMs).WithValue(runtimeResult.ElementAt(i).time) .SetField(x => x.MemoryUsedInByte).WithValue(runtimeResult.ElementAt(i).memory) .SetField(x => x.Result).WithValue((int)runtimeResult.ElementAt(i).result) .SetField(x => x.Hint).WithValue(runtimeResult.ElementAt(i).hint) .Update(); } if (finalResult == JudgeResult.Accepted) { isAccepted = true; } } if (!isSelfTest && string.IsNullOrEmpty(status.ContestId)) { UpdateUserProblemJson(userId, problem.Id, isAccepted); if (isAccepted) { _db.Problems .Where(x => x.Id == problemId) .SetField(x => x.CachedAcceptedCount).Plus(1) .Update(); } } } #endregion #region Virtual Judge else { _db.VirtualJudgeUsers .Where(x => x.LockerId == statusId) .SetField(x => x.LockerId).WithValue(null) .Update(); var resultBody = JsonConvert.DeserializeObject <VirtualJudgeResult>(Encoding.UTF8.GetString((await _mgmt.GetBlobAsync(statemachine.StartedActors.Last().Outputs.Single(x => x.Name == "result.json").Id, token)).Body)); var judgeResult = (Enum.Parse <JudgeResult>(resultBody.Result.Replace(" ", ""))); _db.JudgeStatuses .Where(x => x.Id == statusId) .SetField(x => x.TimeUsedInMs).WithValue(resultBody.TimeUsedInMs) .SetField(x => x.MemoryUsedInByte).WithValue(resultBody.MemoryUsedInByte) .SetField(x => x.Result).WithValue((int)judgeResult) .SetField(x => x.Hint).WithValue(resultBody.Hint) .Update(); // Handle sub-status if (resultBody.SubStatuses != null && resultBody.SubStatuses.Count() > 0) { foreach (var x in resultBody.SubStatuses) { _db.SubJudgeStatuses.Add(new SubJudgeStatus { SubId = x.SubId, Result = Enum.Parse <JudgeResult>(x.Result), TimeUsedInMs = (int)x.TimeUsedInMs, MemoryUsedInByte = (int)x.MemoryUsedInByte, StatusId = statusId, Hint = x.Hint }); } } else { _db.SubJudgeStatuses.Add(new SubJudgeStatus { SubId = 1, Result = Enum.Parse <JudgeResult>(resultBody.Result), TimeUsedInMs = (int)resultBody.TimeUsedInMs, MemoryUsedInByte = (int)resultBody.MemoryUsedInByte, StatusId = statusId, Hint = $"{ problem.Source }不支持查看测试点信息" }); } _db.SaveChanges(); if (string.IsNullOrEmpty(status.ContestId)) { UpdateUserProblemJson(userId, problem.Id, judgeResult == JudgeResult.Accepted); if (judgeResult == JudgeResult.Accepted) { _db.Problems .Where(x => x.Id == problemId) .SetField(x => x.CachedAcceptedCount).Plus(1) .Update(); } } } #endregion if (!string.IsNullOrEmpty(status.ContestId)) { var ce = _cef.Create(status.ContestId); ce.OnJudgeCompleted(_db.JudgeStatuses .Include(x => x.SubStatuses) .Single(x => x.Id == status.Id)); if (ce.PushNotificationSetting == PushNotificationType.All) { _hub.Clients.All.InvokeAsync("ItemUpdated", "judge", statusId); _hub.Clients.All.InvokeAsync("StandingsUpdated", status.ContestId, status.UserId); } else if (ce.PushNotificationSetting == PushNotificationType.Master) { _hub.Clients.Group("Masters").InvokeAsync("ItemUpdated", "judge", statusId); foreach (var x in ce.GetContestOwners()) { _hub.Clients.User(x).InvokeAsync("ItemUpdated", "judge", statusId); } } } else { _hub.Clients.All.InvokeAsync("ItemUpdated", "judge", statusId); } }
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(); } }