Skip to content

Commit

Permalink
Implement chain task type (#13)
Browse files Browse the repository at this point in the history
* implement running chained task type

* add .stages file description to problem files front-end

* add wiki reference for .stages in problem's new file form

* move run single-mutiple commands handler to two separate functions

* fix typo in worker/run.go
  • Loading branch information
aome510 authored Apr 19, 2020
1 parent d1041c2 commit 26704fa
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 8 deletions.
3 changes: 3 additions & 0 deletions frontend/html/admin/file_inputs.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
<span class="font-mono">py3</span>,
<span class="font-mono">pas</span>.
</li>
<li>
<span class="font-mono">.stages</span>: The file contains a list of arguments passed to the binary. <span class="font-mono">.stages</span> is required for a chained task type. Refer to <a title="Create a Chained Task" href="https://github.com/natsukagami/kjudge/wiki/Chained-Tasks" target="_blank">here</a> for further information about preparing a problem of this type.
</li>
</ul>
Any other files (e.g headers, provided libraries, ...) will be available at the current working directory when
compiling contestant's solutions.
Expand Down
77 changes: 69 additions & 8 deletions worker/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,58 @@ func (r *RunContext) CompareInput(submissionOutput []byte) (input *SandboxInput,
}, true, nil
}

func RunSingleCommand(sandbox Sandbox, r *RunContext, source []byte) (output *SandboxOutput, err error) {
// First, use the sandbox to run the submission itself.
input, err := r.RunInput(source)
if err != nil {
return nil, err
}
output, err = sandbox.Run(input)
if err != nil {
return nil, errors.WithStack(err)
}
return output, nil
}

func RunMutipleCommands(sandbox Sandbox, r *RunContext, source []byte, stages []string) (output *SandboxOutput, err error) {
command, args, err := RunCommand(r.Sub.Language)
if err != nil {
return nil, err
}

input := r.Test.Input
for i, stage := range stages {
// somehow Go includes EOF when splitting a string file line by line
if stage == "" && i == len(stages)-1 {
continue
}
stageArgs := strings.Split(stage, " ")

sandboxInput := &SandboxInput{
Command: command,
Args: append(stageArgs, args...),
Files: nil,
TimeLimit: r.TimeLimit(),
MemoryLimit: r.MemoryLimit(),

CompiledSource: source,
Input: input,
}

output, err = sandbox.Run(sandboxInput)
if err != nil {
return nil, err
}
// stop if the current run fails
if !output.Success {
break
}
// Next input in the chain will be the standard output of the previous command run
input = output.Stdout
}
return output, nil
}

// Run runs a RunContext.
func Run(sandbox Sandbox, r *RunContext) error {
compiled, source := r.CompiledSource()
Expand All @@ -128,17 +180,26 @@ func Run(sandbox Sandbox, r *RunContext) error {

log.Printf("[WORKER] Running submission %v on [test `%v`, group `%v`]\n", r.Sub.ID, r.Test.Name, r.TestGroup.Name)

// First, use the sandbox to run the submission itself.
input, err := r.RunInput(source)
if err != nil {
var output *SandboxOutput
file, err := models.GetFileWithName(r.DB, r.Problem.ID, ".stages")
if errors.Is(err, sql.ErrNoRows) {
// Problem type is not Chained Type, run a single command
output, err = RunSingleCommand(sandbox, r, source)
if err != nil {
return err
}
} else if err != nil {
return err
} else {
// Problem Type is Chained Type, we need to run mutiple commands with arguments from .stages (file)
stages := strings.Split(string(file.Content), "\n")
output, err = RunMutipleCommands(sandbox, r, source, stages)
if err != nil {
return err
}
}
output, err := sandbox.Run(input)
if err != nil {
return errors.WithStack(err)
}
result := parseSandboxOutput(output, r)

result := parseSandboxOutput(output, r)
if !output.Success {
result.Verdict = "Runtime Error"
if output.ErrorMessage != "" {
Expand Down

0 comments on commit 26704fa

Please sign in to comment.