feat: diff
This commit is contained in:
parent
9f0e9bf9f3
commit
fd69aebac5
|
@ -3,6 +3,7 @@ package diff
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||
)
|
||||
|
@ -26,25 +27,83 @@ func (*Diff) Run(results []stage.ExecutorResult, confAny any) (
|
|||
if len(conf.Cases) != len(results) {
|
||||
return nil, true, fmt.Errorf("cases number not match")
|
||||
}
|
||||
|
||||
var res []stage.ParserResult
|
||||
for i, caseConf := range conf.Cases {
|
||||
result := results[i]
|
||||
score := 0
|
||||
var comment string
|
||||
|
||||
stdout, err := os.ReadFile(caseConf.StdoutPath)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
// TODO: more compare strategies
|
||||
|
||||
// If no difference, assign score
|
||||
if string(stdout) == result.Files["stdout"] {
|
||||
score = caseConf.Score
|
||||
}
|
||||
res = append(res, stage.ParserResult{
|
||||
Score: score,
|
||||
Comment: fmt.Sprintf(
|
||||
comment = fmt.Sprintf(
|
||||
"executor status: run time: %d ns, memory: %d bytes",
|
||||
result.RunTime, result.Memory,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// Convert stdout to string and split by lines
|
||||
stdoutLines := strings.Split(string(stdout), "\n")
|
||||
resultLines := strings.Split(result.Files["stdout"], "\n")
|
||||
|
||||
// Find the first difference
|
||||
diffIndex := findFirstDifferenceIndex(stdoutLines, resultLines)
|
||||
if diffIndex != -1 {
|
||||
// Get the surrounding lines from both stdout and result
|
||||
stdoutContext := getContextLines(stdoutLines, diffIndex, 10)
|
||||
resultContext := getContextLines(resultLines, diffIndex, 10)
|
||||
comment = comment + fmt.Sprintf(
|
||||
"difference found at line %d:\nExpected output:\n%s\nActual output:\n%s",
|
||||
diffIndex+1,
|
||||
resultContext,
|
||||
stdoutContext,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
res = append(res, stage.ParserResult{
|
||||
Score: score,
|
||||
Comment: comment,
|
||||
})
|
||||
}
|
||||
|
||||
return res, false, nil
|
||||
}
|
||||
|
||||
// findFirstDifferenceIndex finds the index of the first line where stdout and result differ.
|
||||
func findFirstDifferenceIndex(stdoutLines, resultLines []string) int {
|
||||
maxLines := len(stdoutLines)
|
||||
if len(resultLines) > maxLines {
|
||||
maxLines = len(resultLines)
|
||||
}
|
||||
|
||||
for i := 0; i < maxLines; i++ {
|
||||
if i >= len(stdoutLines) || i >= len(resultLines) || stdoutLines[i] != resultLines[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// getContextLines returns the surrounding lines of the specified index.
|
||||
func getContextLines(lines []string, index, contextSize int) string {
|
||||
start := index - contextSize
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
end := index + contextSize + 1
|
||||
if end > len(lines) {
|
||||
end = len(lines)
|
||||
}
|
||||
|
||||
var context strings.Builder
|
||||
for i := start; i < end; i++ {
|
||||
context.WriteString(fmt.Sprintf("%d: %s\n", i+1, lines[i]))
|
||||
}
|
||||
return context.String()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user