package main import ( "fmt" "os" "strings" "github.com/Mond1c/judge/dsl" "github.com/Mond1c/judge/reporter" "github.com/Mond1c/judge/runner" ) const usage = `judge — CI/CD testing system for student solutions Usage: judge [flags] Flags: --json output as JSON instead of text --wrapper exec wrapper (e.g. "valgrind --error-exitcode=99") --binary name of executable produced by build (overrides .jdg) --help show help Example: judge lab1.jdg ./student-solution judge lab1.jdg ./student-solution --json judge lab1.jdg ./student-solution --wrapper "valgrind --error-exitcode=99" ` func main() { args := os.Args[1:] if len(args) == 0 || contains(args, "--help") || contains(args, "-h") { fmt.Print(usage) os.Exit(0) } if len(args) < 2 { fmt.Fprintf(os.Stderr, "error: need and \n\n%s", usage) os.Exit(1) } testFile := args[0] solutionDir := args[1] jsonOutput := contains(args, "--json") wrapper := flagValue(args, "--wrapper") binary := flagValue(args, "--binary") src, err := os.ReadFile(testFile) if err != nil { fatalf("cannot read %q: %v", testFile, err) } f, warns, err := dsl.Parse(string(src)) if err != nil { fatalf("parse error in %q:\n %v", testFile, err) } for _, w := range warns { fmt.Fprintf(os.Stderr, "warning: %s\n", w) } if _, err := os.Stat(solutionDir); err != nil { fatalf("solution dir %q not found: %v", solutionDir, err) } r := runner.New(f, runner.Config{ WorkDir: solutionDir, BinaryName: binary, Wrapper: wrapper, }) result := r.Run() if jsonOutput { if err := reporter.JSON(os.Stdout, result); err != nil { fatalf("json output error: %v", err) } } else { reporter.Text(os.Stdout, result) } if result.TotalScore < 0.9999 { os.Exit(1) } } func fatalf(msg string, args ...any) { fmt.Fprintf(os.Stderr, "error: "+msg+"\n", args...) os.Exit(1) } // flagValue returns the value of --name or --name=value, else "". func flagValue(args []string, name string) string { prefix := name + "=" for i, a := range args { if a == name && i+1 < len(args) { return args[i+1] } if strings.HasPrefix(a, prefix) { return a[len(prefix):] } } return "" } func contains(slice []string, s string) bool { for _, v := range slice { if v == s { return true } } return false }