diff --git a/cmd/joj3/main_test.go b/cmd/joj3/main_test.go index 22cbb78..3273b32 100644 --- a/cmd/joj3/main_test.go +++ b/cmd/joj3/main_test.go @@ -9,6 +9,7 @@ import ( "strings" "testing" + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/scoreboard" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" ) @@ -61,7 +62,16 @@ func readStageResults(t *testing.T, path string) []stage.StageResult { return results } +func removeStringPrefix(s, prefix string) string { + if strings.HasPrefix(s, prefix) { + return s[len(prefix):] + } + return s +} + func TestMain(t *testing.T) { + scoreboard := scoreboard.Scoreboard{} + scoreboard.Init("TestingStudent", "520370000000") var tests []string root := "../../tmp/submodules/JOJ3-examples" err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { @@ -107,6 +117,7 @@ func TestMain(t *testing.T) { defer os.Remove(outputFile) main() stageResults := readStageResults(t, outputFile) + scoreboard.AddScore(removeStringPrefix(tt, "/examples/"), stageResults) regex := true expectedFile := "expected_regex.json" if _, err := os.Stat(expectedFile); os.IsNotExist(err) { @@ -117,4 +128,9 @@ func TestMain(t *testing.T) { compareStageResults(t, stageResults, expectedStageResults, regex) }) } + if !t.Failed() { + scoreboard.SaveFile("../../scoreboard.json") + defer os.Remove("../../scoreboard.json") + scoreboard.Submit() + } } diff --git a/internal/scoreboard/scoreboard.go b/internal/scoreboard/scoreboard.go index d306ee0..9030a9e 100644 --- a/internal/scoreboard/scoreboard.go +++ b/internal/scoreboard/scoreboard.go @@ -1,44 +1,40 @@ package scoreboard import ( + "bytes" "encoding/json" + "fmt" + "log/slog" "os" + "os/exec" + + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" ) -type Question struct { - Name string `json:"name"` - Score int `json:"score"` - Comment string `json:"comment"` +type StageRecord struct { + StageName string `json:"stagename"` + StageResults []stage.StageResult `json:"stageresults"` } type ScoreboardData struct { - StudentName string `json:"studentname"` - StudentId string `json:"studentid"` - Questions []Question `json:"questions"` + StageRecords []StageRecord `json:"stagerecords"` } type Scoreboard struct { - scoreboard ScoreboardData + studentName string + studentId string + scoreboard ScoreboardData } func (b *Scoreboard) Init(studentName string, studentId string) { - b.scoreboard.StudentName = studentName - b.scoreboard.StudentId = studentId - b.scoreboard.Questions = make([]Question, 0) + b.studentName = studentName + b.studentId = studentId + b.scoreboard.StageRecords = make([]StageRecord, 0) } -func (b *Scoreboard) AddScore(questionName string, score int) { - flag := false - for i, question := range b.scoreboard.Questions { - if question.Name == questionName { - b.scoreboard.Questions[i].Score = score - flag = true - break - } - } - if flag { - b.scoreboard.Questions = append(b.scoreboard.Questions, Question{Name: questionName, Score: score}) - } +func (b *Scoreboard) AddScore(stagename string, results []stage.StageResult) { + b.scoreboard.StageRecords = append(b.scoreboard.StageRecords, + StageRecord{StageName: stagename, StageResults: results}) } func (b *Scoreboard) SaveFile(filePath string) { @@ -50,3 +46,54 @@ func (b *Scoreboard) SaveFile(filePath string) { encoder.SetIndent("", " ") _ = encoder.Encode(b.scoreboard) } + +func (b *Scoreboard) Submit() { + e := os.Mkdir("repos", 0o777) + if e != nil { + slog.Error("Encountered problems createing folder: ", "err", e) + return + } + var teapotCommand string + origHome := os.Getenv("ORIG_HOME") + if origHome != "" { + // For drone server + teapotCommand = fmt.Sprintf("cp %s/.config/ci/teapot.env .env && joint-teapot JOJ3-scoreboard \"../../scoreboard.json\" %s %s \"JOJ3-examples\" \"JOJ3_dev.csv\"", origHome, b.studentName, b.studentId) + } else { + // For local developers + jointTeapotRoot := os.Getenv("TEAPOT_ROOT") + if jointTeapotRoot == "" { + slog.Error("Unable to find joint-teapot. Have you configured environment variable TEAPOT_ROOT?") + return + } + teapotCommand = fmt.Sprintf("cp %s/.env .env && source %s/env/bin/activate && python3 -m joint_teapot JOJ3-scoreboard \"../../scoreboard.json\" %s %s \"JOJ3-examples\" \"JOJ3_dev.csv\" && deactivate", jointTeapotRoot, jointTeapotRoot, b.studentName, b.studentId) + } + defer os.Remove(".env") + teapotCmd := exec.Command("/bin/bash", "-c", teapotCommand) + defer os.Remove("joint-teapot.log") + + stderrPipe, err := teapotCmd.StderrPipe() + if err != nil { + slog.Error("Error creating stderr pipe when submitting scoreboard: ", "err", err) + return + } + err = teapotCmd.Start() + if err != nil { + slog.Error("Error starting command when submitting scoreboard: ", "err", err) + return + } + + var stderr bytes.Buffer + _, err = stderr.ReadFrom(stderrPipe) + if err != nil { + slog.Error("Error reading stderr when submitting scoreboard: ", "err", err) + return + } + + err = teapotCmd.Wait() + if err != nil { + slog.Error("Tried to submit scoreboard, but it finished with error: ", "err", err) + slog.Error("Stderr output:", "stderr", stderr.String()) + return + } + slog.Info("Scoreboard was submitted with following outputs: ", "stderr", stderr.String()) +}