diff --git a/internal/api/runner/build.go b/internal/api/runner/build.go index c6749c7..1844a51 100644 --- a/internal/api/runner/build.go +++ b/internal/api/runner/build.go @@ -19,7 +19,7 @@ func (h *handler) Build(_ context.Context, t *asynq.Task) error { } h.log.Debug("build", zap.Any("payload", p)) - meta := runner.JudgeMeta{Version: p.ProblemVersionID} + meta := runner.JudgeMeta{Run: runner.JudgeMetaRun{Version: p.ProblemVersionID}} status, ctx := func() (e.Status, string) { url, status := h.storageService.Get(p.StorageKey, time.Second*60*5) diff --git a/internal/api/runner/judge.go b/internal/api/runner/judge.go index 5e015d0..390fc1f 100644 --- a/internal/api/runner/judge.go +++ b/internal/api/runner/judge.go @@ -15,6 +15,14 @@ import ( "time" ) +var ( + statusSystemError = runner.JudgeStatus{ + Message: "System Error", + CompileMessage: "", + Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "System Error"}}, + } +) + func (h *handler) Judge(_ context.Context, t *asynq.Task) error { var p model.SubmitJudgePayload if err := json.Unmarshal(t.Payload(), &p); err != nil { @@ -23,45 +31,59 @@ func (h *handler) Judge(_ context.Context, t *asynq.Task) error { user := utils.RandomString(16) h.log.Debug("judge", zap.Any("payload", p), zap.String("user", user)) - meta := runner.JudgeMeta{Version: p.ProblemVersionID, User: user, Lang: p.Submission.Language} - - SystemError := &runner.JudgeStatus{ - Message: "System Error", - Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "API Error"}}, + meta := runner.JudgeMeta{ + Run: runner.JudgeMetaRun{ + Version: p.ProblemVersionID, + User: user, + Lang: p.Submission.Language, + }, } status, point, ctx := func() (e.Status, int32, *runner.JudgeStatus) { - // 1. write user code userCode := filepath.Join(runner.UserDir, user, fmt.Sprintf("%s.%s", user, p.Submission.Language)) if !file.Touch(userCode) { - return e.InternalError, 0, SystemError + return e.InternalError, 0, &statusSystemError } err := file.Write(userCode, []byte(p.Submission.Code)) if err != nil { - return e.InternalError, 0, SystemError + return e.InternalError, 0, &statusSystemError } // 2. check problem if !h.runnerService.ProblemExists(&meta) { url, status := h.storageService.Get(p.StorageKey, time.Second*60*5) if status != e.Success { - return status, 0, SystemError + return status, 0, &statusSystemError } _, status = h.runnerService.NewProblem(&meta, url, false) if status != e.Success { - return status, 0, SystemError + return status, 0, &statusSystemError } } - // 3. compile + // 3. validate + if ret, status := h.runnerService.ValidatePath(&meta); status != e.Success { + return status, 0, ret + } + + // 4. extract config + if status := h.runnerService.GetConfig(&meta, true); status != e.Success { + return e.RunnerProblemParseFailed, 0, &runner.JudgeStatus{ + Message: fmt.Sprintf("System Error: Problem Malformed (%d:%s)", status, status.String()), + CompileMessage: "", + Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "System Error"}}, + } + } + + // 5. compile compileResult, status := h.runnerService.Compile(&meta) if status != e.Success { return status, 0, compileResult } - // 4. run and judge + // 6. run and judge result, point, status := h.runnerService.RunAndJudge(&meta) return status, point, result }() diff --git a/internal/service/runner/common.go b/internal/service/runner/common.go index e76abc7..9863f84 100644 --- a/internal/service/runner/common.go +++ b/internal/service/runner/common.go @@ -22,10 +22,20 @@ const ( ContainerImageRun = "git.0x7f.app/woj/ubuntu-run:latest" ) +type JudgeMetaRun struct { + Version uint // problem version id + User string // user id + Lang string // language +} + +type JudgeMetaConfig struct { + All *Config + Lang *ConfigLanguage +} + type JudgeMeta struct { - Version uint - User string - Lang string + Run JudgeMetaRun + Cfg JudgeMetaConfig } func init() { @@ -41,33 +51,47 @@ func init() { } func (s *service) ProblemExists(meta *JudgeMeta) bool { - problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version)) + problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version)) return file.Exist(problemPath) } -func (s *service) ValidatePath(meta *JudgeMeta) e.Status { +func (s *service) ValidatePath(meta *JudgeMeta) (*JudgeStatus, e.Status) { + gen := func(status e.Status) (*JudgeStatus, e.Status) { + return &JudgeStatus{ + Message: fmt.Sprintf("System Error: Problem/User Files Not Found (%d:%s)", status, status.String()), + CompileMessage: "", + Tasks: []TaskStatus{{Verdict: VerdictSystemError, Message: "System Error"}}, + }, status + } + if !s.ProblemExists(meta) { - s.log.Info("problem not exists", zap.Uint("version", meta.Version)) - return e.RunnerProblemNotExist + s.log.Error("problem not exists", zap.Uint("version", meta.Run.Version)) + return gen(e.RunnerProblemNotExist) } - userPath := filepath.Join(UserDir, meta.User, fmt.Sprintf("%s.%s", meta.User, meta.Lang)) + userPath := filepath.Join(UserDir, meta.Run.User, fmt.Sprintf("%s.%s", meta.Run.User, meta.Run.Lang)) if !file.Exist(userPath) { - s.log.Info("user program not exists", zap.String("user", meta.User), zap.String("lang", meta.Lang)) - return e.RunnerUserNotExist + s.log.Error("user program not exists", zap.String("user", meta.Run.User), zap.String("lang", meta.Run.Lang)) + return gen(e.RunnerUserNotExist) } - return e.Success + return nil, e.Success } -func (s *service) GetConfig(meta *JudgeMeta, skipCheck bool) (*Config, *ConfigLanguage, e.Status) { +func (s *service) GetConfig(meta *JudgeMeta, skipCheck bool) e.Status { config, err := s.ParseConfig(meta, skipCheck) if err != nil { - return nil, nil, e.RunnerProblemParseFailed + return e.RunnerProblemParseFailed } - cLang, ok := config.FilterLanguage(meta.Lang) + + lang, ok := config.FilterLanguage(meta.Run.Lang) if !ok { - return nil, nil, e.RunnerLanguageNotSupported + return e.RunnerLanguageNotSupported } - return config, cLang, e.Success + + meta.Cfg = JudgeMetaConfig{ + All: config, + Lang: lang, + } + return e.Success } diff --git a/internal/service/runner/compile.go b/internal/service/runner/compile.go index cf9662d..d7a3e3a 100644 --- a/internal/service/runner/compile.go +++ b/internal/service/runner/compile.go @@ -14,62 +14,44 @@ import ( ) func (s *service) Compile(meta *JudgeMeta) (*JudgeStatus, e.Status) { - // 1. ensure problem/user exists - status := s.ValidatePath(meta) - if status != e.Success { - return &JudgeStatus{Message: "check failed"}, status - } + // 1. prepare judge environment + workDir := filepath.Join(UserDir, meta.Run.User) + judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "judge") - config, cLang, status := s.GetConfig(meta, true) - if status != e.Success { - s.log.Error("[compile] parse config failed", zap.Any("meta", *meta)) - return &JudgeStatus{ - Message: "parse config failed", - Tasks: []TaskStatus{{Verdict: VerdictSystemError, Message: "parse config failed"}}, - }, e.RunnerProblemParseFailed - } + sourceFile := filepath.Join(workDir, fmt.Sprintf("%s.%s", meta.Run.User, meta.Run.Lang)) + targetFile := filepath.Join(workDir, fmt.Sprintf("%s.out", meta.Run.User)) - // 2. prepare judge environment - workDir := filepath.Join(UserDir, meta.User) - judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "judge") - - sourceFile := filepath.Join(workDir, fmt.Sprintf("%s.%s", meta.User, meta.Lang)) - targetFile := filepath.Join(workDir, fmt.Sprintf("%s.out", meta.User)) - - logFile := filepath.Join(workDir, fmt.Sprintf("%s.compile.log", meta.User)) + logFile := filepath.Join(workDir, fmt.Sprintf("%s.compile.log", meta.Run.User)) log, err := os.Create(logFile) if err != nil { s.log.Error("[compile] create log file failed", zap.Error(err)) return &JudgeStatus{ - Message: "create log file failed", - Tasks: []TaskStatus{{Verdict: VerdictSystemError, Message: "create log file failed"}}, + Message: "System Error: Unable to create log file", + CompileMessage: "", + Tasks: []TaskStatus{{Verdict: VerdictSystemError, Message: "System Error"}}, }, e.RunnerUserCompileFailed } defer func(log *os.File) { _ = log.Close() }(log) - // 3. compile + // 2. compile err = utils.NewMust(). DoAny(func() error { return os.Remove(targetFile) }). Do(func() error { return file.TouchErr(targetFile) }). Do(func() error { - l, ok := config.FilterLanguage(meta.Lang) - if !ok { - return e.RunnerProblemParseFailed.AsError() - } - script := l.JudgeScript() + script := meta.Cfg.Lang.JudgeScript() args := &RunArgs{ Program: ProgramArgs{ Args: []string{"sh", "-c", fmt.Sprintf("cd /woj/user && make -f %s compile", script)}, - Env: []string{fmt.Sprintf("USER_PROG=%s", meta.User), fmt.Sprintf("LANG=%s", meta.Lang)}, + Env: []string{fmt.Sprintf("USER_PROG=%s", meta.Run.User), fmt.Sprintf("LANG=%s", meta.Run.Lang)}, }, Runtime: RuntimeArgs{ Image: ContainerImageFull, - Pid: int64(cLang.Runtime.Compile.NProcLimit + 2), // bash + make - Memory: uint64(cLang.Runtime.Compile.MemoryLimit * 1024 * 1024), - Timeout: time.Duration((cLang.Runtime.Compile.TimeLimit+1000)/1000) * time.Second, + Pid: int64(meta.Cfg.Lang.Runtime.Compile.NProcLimit + 2), // bash + make + Memory: uint64(meta.Cfg.Lang.Runtime.Compile.MemoryLimit * 1024 * 1024), + Timeout: time.Duration((meta.Cfg.Lang.Runtime.Compile.TimeLimit+1000)/1000) * time.Second, }, IO: IOArgs{ Output: log, @@ -85,13 +67,13 @@ func (s *service) Compile(meta *JudgeMeta) (*JudgeStatus, e.Status) { }, { Source: sourceFile, - Destination: fmt.Sprintf("/woj/user/%s.%s", meta.User, meta.Lang), + Destination: fmt.Sprintf("/woj/user/%s.%s", meta.Run.User, meta.Run.Lang), Type: "bind", Options: []string{"rbind", "ro"}, }, { Source: targetFile, - Destination: fmt.Sprintf("/woj/user/%s.out", meta.User), + Destination: fmt.Sprintf("/woj/user/%s.out", meta.Run.User), Type: "bind", Options: []string{"rbind"}, }, @@ -102,6 +84,7 @@ func (s *service) Compile(meta *JudgeMeta) (*JudgeStatus, e.Status) { }). Done() + status := e.Success if err != nil { s.log.Info("[compile] compile failed", zap.Error(err), zap.Any("meta", *meta)) status = e.RunnerUserCompileFailed @@ -115,8 +98,9 @@ func (s *service) Compile(meta *JudgeMeta) (*JudgeStatus, e.Status) { if !file.Exist(targetFile) || file.Empty(targetFile) { return &JudgeStatus{ - Message: "compile failed", - Tasks: []TaskStatus{{Verdict: VerdictCompileError, Message: msgText}}}, + Message: "Compile Failed", + CompileMessage: msgText, + Tasks: []TaskStatus{{Verdict: VerdictCompileError, Message: msgText}}}, utils.If(status == e.Success, e.RunnerUserCompileFailed, status) } diff --git a/internal/service/runner/config.go b/internal/service/runner/config.go index 7e5ef5c..59d95a0 100644 --- a/internal/service/runner/config.go +++ b/internal/service/runner/config.go @@ -181,7 +181,7 @@ func (c *Config) FilterLanguage(lang string) (*ConfigLanguage, bool) { } func (s *service) ParseConfig(meta *JudgeMeta, skipCheck bool) (*Config, error) { - base := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version)) + base := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version)) file := filepath.Join(base, "config.json") data, err := os.ReadFile(file) diff --git a/internal/service/runner/new_problem.go b/internal/service/runner/new_problem.go index 47e9d1b..b1fe922 100644 --- a/internal/service/runner/new_problem.go +++ b/internal/service/runner/new_problem.go @@ -14,8 +14,8 @@ import ( ) func (s *service) DownloadProblem(meta *JudgeMeta, url string) e.Status { - zipPath := filepath.Join(TmpDir, fmt.Sprintf("%d.zip", meta.Version)) - problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version)) + zipPath := filepath.Join(TmpDir, fmt.Sprintf("%d.zip", meta.Run.Version)) + problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version)) err := down.Down(zipPath, url) if err != nil { @@ -37,21 +37,21 @@ func (s *service) PrebuildProblem(meta *JudgeMeta, config *Config, force bool) e return e.RunnerProblemNotExist } - mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), ".mark.prebuild") + mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), ".mark.prebuild") if force { _ = os.Remove(mark) } else if file.Exist(mark) { return e.Success } - prebuildScript := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "judge", "prebuild.Makefile") + prebuildScript := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "judge", "prebuild.Makefile") if !file.Exist(prebuildScript) { - s.log.Info("[new] prebuild script not found", zap.String("path", prebuildScript), zap.Uint("version", meta.Version)) + s.log.Info("[new] prebuild script not found", zap.String("path", prebuildScript), zap.Uint("version", meta.Run.Version)) return e.Success } - dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "data") - judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "judge") + dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "data") + judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "judge") args := &RunArgs{ Program: ProgramArgs{ @@ -83,7 +83,7 @@ func (s *service) PrebuildProblem(meta *JudgeMeta, config *Config, force bool) e err := s.pool.WaitForTask(id) if err != nil { - s.log.Warn("[new] prebuild problem failed", zap.Error(err), zap.Uint("version", meta.Version)) + s.log.Warn("[new] prebuild problem failed", zap.Error(err), zap.Uint("version", meta.Run.Version)) return e.RunnerProblemPrebuildFailed } @@ -92,7 +92,7 @@ func (s *service) PrebuildProblem(meta *JudgeMeta, config *Config, force bool) e func (s *service) NewProblem(meta *JudgeMeta, url string, force bool) (*Config, e.Status) { if force { - problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version)) + problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version)) _ = os.RemoveAll(problemPath) } @@ -105,7 +105,7 @@ func (s *service) NewProblem(meta *JudgeMeta, url string, force bool) (*Config, cfg, err := s.ParseConfig(meta, false) if err != nil { - s.log.Info("[new] parse problem failed", zap.Error(err), zap.Uint("version", meta.Version)) + s.log.Info("[new] parse problem failed", zap.Error(err), zap.Uint("version", meta.Run.Version)) return &Config{}, e.RunnerProblemParseFailed } diff --git a/internal/service/runner/run_judge.go b/internal/service/runner/run_judge.go index ea826aa..a270448 100644 --- a/internal/service/runner/run_judge.go +++ b/internal/service/runner/run_judge.go @@ -13,43 +13,43 @@ import ( "time" ) -func (s *service) SandboxArgsBuilder(meta *JudgeMeta, cLang *ConfigLanguage, id int) string { +func (s *service) SandboxArgsBuilder(meta *JudgeMeta, id int) string { var args []string - args = append(args, fmt.Sprintf("--memory_limit=%d", cLang.Runtime.Run.MemoryLimit)) - args = append(args, fmt.Sprintf("--nproc_limit=%d", cLang.Runtime.Run.NProcLimit)) - args = append(args, fmt.Sprintf("--time_limit=%d", cLang.Runtime.Run.TimeLimit)) - args = append(args, fmt.Sprintf("--sandbox_template=%s", cLang.Lang)) + args = append(args, fmt.Sprintf("--memory_limit=%d", meta.Cfg.Lang.Runtime.Run.MemoryLimit)) + args = append(args, fmt.Sprintf("--nproc_limit=%d", meta.Cfg.Lang.Runtime.Run.NProcLimit)) + args = append(args, fmt.Sprintf("--time_limit=%d", meta.Cfg.Lang.Runtime.Run.TimeLimit)) + args = append(args, fmt.Sprintf("--sandbox_template=%s", meta.Cfg.Lang.Lang)) args = append(args, fmt.Sprintf("--sandbox_action=ret")) args = append(args, fmt.Sprintf("--uid=1000")) args = append(args, fmt.Sprintf("--gid=1000")) args = append(args, fmt.Sprintf("--file_input=/woj/problem/data/input/%d.input", id)) args = append(args, fmt.Sprintf("--file_output=/woj/user/%d.out.usr", id)) args = append(args, fmt.Sprintf("--file_info=/woj/user/%d.info", id)) - args = append(args, fmt.Sprintf("--program=/woj/user/%s.out", meta.User)) + args = append(args, fmt.Sprintf("--program=/woj/user/%s.out", meta.Run.User)) return strings.Join(args, " ") } -func (s *service) ProblemRun(meta *JudgeMeta, config *Config, cLang *ConfigLanguage) { - workDir := filepath.Join(UserDir, meta.User) - dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "data", "input") +func (s *service) ProblemRun(meta *JudgeMeta) { + workDir := filepath.Join(UserDir, meta.Run.User) + dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "data", "input") runtimeArgs := RuntimeArgs{ Image: ContainerImageRun, // sh, woj_launcher:program, woj_launcher:killer, woj_launcher:stat - Pid: int64(cLang.Runtime.Run.NProcLimit + 4), - Memory: uint64(cLang.Runtime.Run.MemoryLimit * 1024 * 1024), + Pid: int64(meta.Cfg.Lang.Runtime.Run.NProcLimit + 4), + Memory: uint64(meta.Cfg.Lang.Runtime.Run.MemoryLimit * 1024 * 1024), // woj-sandbox killer will add 1 more second, here we add 1 also - Timeout: time.Duration((cLang.Runtime.Run.TimeLimit+1000)/1000+1+1) * time.Second, + Timeout: time.Duration((meta.Cfg.Lang.Runtime.Run.TimeLimit+1000)/1000+1+1) * time.Second, } ids := make([]int, 0) - for _, task := range config.Tasks { + for _, task := range meta.Cfg.All.Tasks { f := func(id int) func() error { return func() error { testCase := filepath.Join(dataDir, fmt.Sprintf("%d.input", id)) - targetFile := filepath.Join(workDir, fmt.Sprintf("%s.out", meta.User)) + targetFile := filepath.Join(workDir, fmt.Sprintf("%s.out", meta.Run.User)) ansFile := filepath.Join(workDir, fmt.Sprintf("%d.out.usr", id)) ifoFile := filepath.Join(workDir, fmt.Sprintf("%d.info", id)) @@ -58,7 +58,7 @@ func (s *service) ProblemRun(meta *JudgeMeta, config *Config, cLang *ConfigLangu Args: []string{ "sh", "-c", "cd /woj/user && /woj/framework/scripts/woj_launcher " + - s.SandboxArgsBuilder(meta, cLang, id), + s.SandboxArgsBuilder(meta, id), }, }, Runtime: runtimeArgs, @@ -72,7 +72,7 @@ func (s *service) ProblemRun(meta *JudgeMeta, config *Config, cLang *ConfigLangu }, { Source: targetFile, - Destination: fmt.Sprintf("/woj/user/%s.out", meta.User), + Destination: fmt.Sprintf("/woj/user/%s.out", meta.Run.User), Type: "bind", Options: []string{"rbind", "ro"}, }, @@ -114,21 +114,21 @@ func (s *service) ProblemRun(meta *JudgeMeta, config *Config, cLang *ConfigLangu } } -func (s *service) ProblemJudge(meta *JudgeMeta, config *Config, cLang *ConfigLanguage) { - workDir := filepath.Join(UserDir, meta.User) - dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "data") - judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Version), "judge") - script := cLang.JudgeScript() +func (s *service) ProblemJudge(meta *JudgeMeta) { + workDir := filepath.Join(UserDir, meta.Run.User) + dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "data") + judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", meta.Run.Version), "judge") + script := meta.Cfg.Lang.JudgeScript() runtimeArgs := RuntimeArgs{ Image: ContainerImageFull, - Pid: int64(cLang.Runtime.Check.NProcLimit + 2), // bash + make - Memory: uint64(cLang.Runtime.Check.MemoryLimit * 1024 * 1024), - Timeout: time.Duration((cLang.Runtime.Check.TimeLimit+1000)/1000) * time.Second, + Pid: int64(meta.Cfg.Lang.Runtime.Check.NProcLimit + 2), // bash + make + Memory: uint64(meta.Cfg.Lang.Runtime.Check.MemoryLimit * 1024 * 1024), + Timeout: time.Duration((meta.Cfg.Lang.Runtime.Check.TimeLimit+1000)/1000) * time.Second, } ids := make([]int, 0) - for _, task := range config.Tasks { + for _, task := range meta.Cfg.All.Tasks { f := func(id int) func() error { return func() error { ansFile := filepath.Join(workDir, fmt.Sprintf("%d.out.usr", id)) @@ -142,7 +142,7 @@ func (s *service) ProblemJudge(meta *JudgeMeta, config *Config, cLang *ConfigLan }, Env: []string{ fmt.Sprintf("TEST_NUM=%d", id), - fmt.Sprintf("CMP=%s", cLang.Judge.Cmp), + fmt.Sprintf("CMP=%s", meta.Cfg.Lang.Judge.Cmp), }, }, Runtime: runtimeArgs, @@ -197,26 +197,14 @@ func (s *service) ProblemJudge(meta *JudgeMeta, config *Config, cLang *ConfigLan } func (s *service) RunAndJudge(meta *JudgeMeta) (*JudgeStatus, int32, e.Status) { - // 1. ensure problem/user exists - status := s.ValidatePath(meta) - if status != e.Success { - return &JudgeStatus{Message: "check failed"}, 0, status - } + // 1. run user program + s.ProblemRun(meta) - // 2. config - config, cLang, status := s.GetConfig(meta, true) - if status != e.Success { - return &JudgeStatus{Message: status.String()}, 0, status - } + // 2. run judge + s.ProblemJudge(meta) - // 3. run user program - s.ProblemRun(meta, config, cLang) - - // 4. run judge - s.ProblemJudge(meta, config, cLang) - - // 5. check result - result, pts := s.CheckResults(meta, config, cLang) + // 3. check result + result, pts := s.CheckResults(meta) return result, pts, e.Success } diff --git a/internal/service/runner/service.go b/internal/service/runner/service.go index e7c5aff..4941bbf 100644 --- a/internal/service/runner/service.go +++ b/internal/service/runner/service.go @@ -32,6 +32,10 @@ type Service interface { ParseConfig(meta *JudgeMeta, skipCheck bool) (*Config, error) // ProblemExists check if problem exists ProblemExists(meta *JudgeMeta) bool + // ValidatePath check if problem/user exists + ValidatePath(meta *JudgeMeta) (*JudgeStatus, e.Status) + // GetConfig return config and filter language config, will fill result to meta.Config + GetConfig(meta *JudgeMeta, skipCheck bool) e.Status HealthCheck() error Shutdown() error diff --git a/internal/service/runner/status.go b/internal/service/runner/status.go index c800760..397551f 100644 --- a/internal/service/runner/status.go +++ b/internal/service/runner/status.go @@ -47,8 +47,9 @@ type TaskStatus struct { } type JudgeStatus struct { - Message string `json:"message"` - Tasks []TaskStatus `json:"tasks"` + Message string `json:"message"` + CompileMessage string `json:"compile_message"` + Tasks []TaskStatus `json:"tasks"` } func (t *TaskStatus) getInfoText(infoFile string) *TaskStatus { @@ -193,19 +194,19 @@ func (t *TaskStatus) checkJudge(pts *map[int]int32) *TaskStatus { return t } -func (s *service) CheckResults(meta *JudgeMeta, config *Config, cLang *ConfigLanguage) (*JudgeStatus, int32) { +func (s *service) CheckResults(meta *JudgeMeta) (*JudgeStatus, int32) { // CE will be processed in phase compile pts := map[int]int32{} - for _, task := range config.Tasks { + for _, task := range meta.Cfg.All.Tasks { pts[task.Id] = task.Points } var results []TaskStatus - dir := filepath.Join(UserDir, meta.User) + dir := filepath.Join(UserDir, meta.Run.User) var sum int32 = 0 - for i := 1; i <= len(config.Tasks); i++ { + for i := 1; i <= len(meta.Cfg.All.Tasks); i++ { result := TaskStatus{Id: i, Verdict: VerdictAccepted, Points: 0} info := filepath.Join(dir, fmt.Sprintf("%d.info", i)) @@ -213,8 +214,8 @@ func (s *service) CheckResults(meta *JudgeMeta, config *Config, cLang *ConfigLan result.getInfoText(info). getInfo(). - checkTime(cLang). - checkMemory(cLang). + checkTime(meta.Cfg.Lang). + checkMemory(meta.Cfg.Lang). checkExit(). getJudgeText(judge). getJudge().