public ContestExecutorFactory(OnlineJudgeContext db, SmartUser <User, Guid> user, ManagementServiceClient mgmt, IConfiguration config) { this._db = db; this._user = user; this._mgmt = mgmt; this._config = config; }
public HackStateMachineHandler(OnlineJudgeContext db, IHubContext <OnlineJudgeHub> hub, ManagementServiceClient mgmt, ContestExecutorFactory cef) { _db = db; _hub = hub; _mgmt = mgmt; _cef = cef; }
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> 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")); }
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); }
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(); }
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"); } } }
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")); }
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> 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)); } }
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)); }
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(); }
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); }
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 }
public JudgeStateMachineHandler(OnlineJudgeContext db, IHubContext <OnlineJudgeHub> hub, ManagementServiceClient mgmt) { _db = db; _hub = hub; _mgmt = mgmt; }
public StateMachineAwaiter(IConfiguration configuration, ManagementServiceClient managementServiceClient) { _configuration = configuration; _managementServiceClient = managementServiceClient; }
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")); } }