feat: diff parser with example
This commit is contained in:
parent
a3deb3d974
commit
ab956f5662
31
README.md
31
README.md
|
@ -13,20 +13,20 @@ go build -o ./build/joj3 ./cmd/joj3
|
||||||
+ DIRNAME=./_example/simple
|
+ DIRNAME=./_example/simple
|
||||||
+ cd ./_example/simple
|
+ cd ./_example/simple
|
||||||
+ ./../../build/joj3
|
+ ./../../build/joj3
|
||||||
2024/03/04 02:09:42 INFO stage start name=compile
|
2024/03/04 02:57:50 INFO stage start name=compile
|
||||||
2024/03/04 02:09:42 INFO sandbox run cmd="{Args:[/usr/bin/g++ a.cc -o a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f540 0xc00007f580 0xc00007f5c0] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[] CopyInCwd:true CopyOut:[stdout stderr] CopyOutCached:[a] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
|
2024/03/04 02:57:50 INFO sandbox run cmd="{Args:[/usr/bin/g++ a.cc -o a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f540 0xc00007f580 0xc00007f5c0] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[] CopyInCwd:true CopyOut:[stdout stderr] CopyOutCached:[a] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
|
||||||
2024/03/04 02:09:42 INFO sandbox run copyInCwd=true
|
2024/03/04 02:57:50 INFO sandbox run copyInCwd=true
|
||||||
2024/03/04 02:09:42 INFO sandbox run ret="results:{status:Accepted time:321003000 runTime:321988110 memory:57888768 files:{key:\"stderr\" value:\"\"} files:{key:\"stdout\" value:\"\"} fileIDs:{key:\"a\" value:\"T6BQPS5B\"}}"
|
2024/03/04 02:57:50 INFO sandbox run ret="results:{status:Accepted time:298002000 runTime:298694146 memory:57880576 files:{key:\"stderr\" value:\"\"} files:{key:\"stdout\" value:\"\"} fileIDs:{key:\"a\" value:\"DMTRJR3V\"}}"
|
||||||
2024/03/04 02:09:42 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:321.003ms RunTime:321.98811ms Memory:55.2 MiB Files:map[stderr:len:0 stdout:len:0] FileIDs:map[a:T6BQPS5B] FileError:[]}"
|
2024/03/04 02:57:50 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:298.002ms RunTime:298.694146ms Memory:55.2 MiB Files:map[stderr:len:0 stdout:len:0] FileIDs:map[a:DMTRJR3V] FileError:[]}"
|
||||||
2024/03/04 02:09:42 INFO parser done result="&{Score:100 Comment:compile done, executor status: run time: 321988110 ns, memory: 57888768 bytes}"
|
2024/03/04 02:57:50 INFO parser done result="&{Score:100 Comment:compile done, executor status: run time: 298694146 ns, memory: 57880576 bytes}"
|
||||||
2024/03/04 02:09:42 INFO stage start name=run
|
2024/03/04 02:57:50 INFO stage start name=run
|
||||||
2024/03/04 02:09:42 INFO sandbox run cmd="{Args:[./a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f600 0xc00007f640 0xc00007f680] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[a:a] CopyInCwd:false CopyOut:[stdout stderr] CopyOutCached:[] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
|
2024/03/04 02:57:50 INFO sandbox run cmd="{Args:[./a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f600 0xc00007f640 0xc00007f680] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[a:a] CopyInCwd:false CopyOut:[stdout stderr] CopyOutCached:[] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
|
||||||
2024/03/04 02:09:42 INFO sandbox run ret="results:{status:Accepted time:1446000 runTime:2284978 memory:15384576 files:{key:\"stderr\" value:\"\"} files:{key:\"stdout\" value:\"2\\n\"}}"
|
2024/03/04 02:57:50 INFO sandbox run ret="results:{status:Accepted time:1122000 runTime:1723994 memory:15384576 files:{key:\"stderr\" value:\"\"} files:{key:\"stdout\" value:\"2\\n\"}}"
|
||||||
2024/03/04 02:09:42 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:1.446ms RunTime:2.284978ms Memory:14.7 MiB Files:map[stderr:len:0 stdout:len:2] FileIDs:map[] FileError:[]}"
|
2024/03/04 02:57:50 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:1.122ms RunTime:1.723994ms Memory:14.7 MiB Files:map[stderr:len:0 stdout:len:2] FileIDs:map[] FileError:[]}"
|
||||||
2024/03/04 02:09:42 INFO parser done result="&{Score:100 Comment:run done, executor status: run time: 2284978 ns, memory: 15384576 bytes}"
|
2024/03/04 02:57:50 INFO parser done result="&{Score:100 Comment:}"
|
||||||
2024/03/04 02:09:42 INFO stage result name=compile score=100 comment="compile done, executor status: run time: 321988110 ns, memory: 57888768 bytes"
|
2024/03/04 02:57:50 INFO stage result name=compile score=100 comment="compile done, executor status: run time: 298694146 ns, memory: 57880576 bytes"
|
||||||
2024/03/04 02:09:42 INFO stage result name=run score=100 comment="run done, executor status: run time: 2284978 ns, memory: 15384576 bytes"
|
2024/03/04 02:57:50 INFO stage result name=run score=100 comment=""
|
||||||
2024/03/04 02:09:42 INFO sandbox cleanup
|
2024/03/04 02:57:50 INFO sandbox cleanup
|
||||||
+ cd -
|
+ cd -
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -44,10 +44,11 @@ Parser takes a `ExecutorResult` and its config and returns a `ParserResult`.
|
||||||
|
|
||||||
Check `Cmd` in <https://github.com/criyle/go-judge#rest-api-interface>.
|
Check `Cmd` in <https://github.com/criyle/go-judge#rest-api-interface>.
|
||||||
|
|
||||||
Some extra fields:
|
Some difference:
|
||||||
|
|
||||||
- `CopyInCwd bool`: set to `true` to add everything in the current working directory to `CopyIn`.
|
- `CopyInCwd bool`: set to `true` to add everything in the current working directory to `CopyIn`.
|
||||||
- `CopyInCached map[string]string`: key: file name in sandbox, value: file name used in `CopyOutCached`.
|
- `CopyInCached map[string]string`: key: file name in sandbox, value: file name used in `CopyOutCached`.
|
||||||
|
- `LocalFile`: now support relative path
|
||||||
|
|
||||||
### `ExecutorResult`
|
### `ExecutorResult`
|
||||||
|
|
||||||
|
|
1
_example/simple/1.stdin
Normal file
1
_example/simple/1.stdin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1 1
|
1
_example/simple/1.stdout
Normal file
1
_example/simple/1.stdout
Normal file
|
@ -0,0 +1 @@
|
||||||
|
2
|
|
@ -38,7 +38,7 @@ copyOut = ["stdout", "stderr"]
|
||||||
[stages.executor.with.copyInCached]
|
[stages.executor.with.copyInCached]
|
||||||
a = "a"
|
a = "a"
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.files]]
|
||||||
content = "1 1"
|
src = "1.stdin"
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.files]]
|
||||||
name = "stdout"
|
name = "stdout"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
|
@ -46,7 +46,7 @@ max = 4_096
|
||||||
name = "stderr"
|
name = "stderr"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
[stages.parser]
|
[stages.parser]
|
||||||
name = "dummy"
|
name = "diff"
|
||||||
[stages.parser.with]
|
[stages.parser.with]
|
||||||
score = 100
|
score = 100
|
||||||
comment = "run done"
|
stdoutPath = "1.stdout"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package sandbox
|
package sandbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||||
|
@ -143,3 +144,14 @@ func convertPBFileError(fe []*pb.Response_FileError) []stage.FileError {
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertAbsPath(cmdFile *stage.CmdFile) error {
|
||||||
|
if cmdFile.Src != nil && !filepath.IsAbs(*cmdFile.Src) {
|
||||||
|
absPath, err := filepath.Abs(*cmdFile.Src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmdFile.Src = &absPath
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,16 @@ func (e *Sandbox) Run(cmd stage.Cmd) (*stage.ExecutorResult, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, file := range cmd.Files {
|
||||||
|
if err := convertAbsPath(file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, file := range cmd.CopyIn {
|
||||||
|
if err := convertAbsPath(&file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
req := &pb.Request{Cmd: convertPBCmd([]stage.Cmd{cmd})}
|
req := &pb.Request{Cmd: convertPBCmd([]stage.Cmd{cmd})}
|
||||||
ret, err := e.execClient.Exec(context.TODO(), req)
|
ret, err := e.execClient.Exec(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package parsers
|
package parsers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/diff"
|
||||||
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy"
|
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
9
internal/parsers/diff/meta.go
Normal file
9
internal/parsers/diff/meta.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package diff
|
||||||
|
|
||||||
|
import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||||
|
|
||||||
|
var name = "diff"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
stage.RegisterParser(name, &Diff{})
|
||||||
|
}
|
36
internal/parsers/diff/parser.go
Normal file
36
internal/parsers/diff/parser.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package diff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Score int
|
||||||
|
StdoutPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Diff struct{}
|
||||||
|
|
||||||
|
func (e *Diff) Run(result *stage.ExecutorResult, configAny any) (
|
||||||
|
*stage.ParserResult, error,
|
||||||
|
) {
|
||||||
|
config, err := stage.DecodeConfig[Config](configAny)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
score := 0
|
||||||
|
stdout, err := os.ReadFile(config.StdoutPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// TODO: more compare strategies
|
||||||
|
if string(stdout) == result.Files["stdout"] {
|
||||||
|
score = config.Score
|
||||||
|
}
|
||||||
|
return &stage.ParserResult{
|
||||||
|
Score: score,
|
||||||
|
Comment: "",
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -2,10 +2,8 @@ package dummy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -18,10 +16,8 @@ type Dummy struct{}
|
||||||
func (e *Dummy) Run(result *stage.ExecutorResult, configAny any) (
|
func (e *Dummy) Run(result *stage.ExecutorResult, configAny any) (
|
||||||
*stage.ParserResult, error,
|
*stage.ParserResult, error,
|
||||||
) {
|
) {
|
||||||
var config Config
|
config, err := stage.DecodeConfig[Config](configAny)
|
||||||
err := mapstructure.Decode(configAny, &config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("failed to decode config", "err", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &stage.ParserResult{
|
return &stage.ParserResult{
|
||||||
|
|
12
internal/stage/util.go
Normal file
12
internal/stage/util.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package stage
|
||||||
|
|
||||||
|
import "github.com/mitchellh/mapstructure"
|
||||||
|
|
||||||
|
func DecodeConfig[T any](configAny any) (*T, error) {
|
||||||
|
var config T
|
||||||
|
err := mapstructure.Decode(configAny, &config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &config, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user