WIP: feat: scoreboard (#15) #31

Closed
张佳澈520370910044 wants to merge 17 commits from scoreboard into master
2 changed files with 86 additions and 23 deletions
Showing only changes of commit 753ed6f9c6 - Show all commits

View File

@ -9,6 +9,7 @@ import (
"strings" "strings"
"testing" "testing"
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/scoreboard"
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" "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 return results
} }
func removeStringPrefix(s, prefix string) string {
if strings.HasPrefix(s, prefix) {
return s[len(prefix):]
}
return s
}
func TestMain(t *testing.T) { func TestMain(t *testing.T) {
scoreboard := scoreboard.Scoreboard{}
scoreboard.Init("TestingStudent", "520370000000")
var tests []string var tests []string
root := "../../tmp/submodules/JOJ3-examples" root := "../../tmp/submodules/JOJ3-examples"
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { 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) defer os.Remove(outputFile)
main() main()
stageResults := readStageResults(t, outputFile) stageResults := readStageResults(t, outputFile)
scoreboard.AddScore(removeStringPrefix(tt, "/examples/"), stageResults)
regex := true regex := true
expectedFile := "expected_regex.json" expectedFile := "expected_regex.json"
if _, err := os.Stat(expectedFile); os.IsNotExist(err) { if _, err := os.Stat(expectedFile); os.IsNotExist(err) {
@ -117,4 +128,9 @@ func TestMain(t *testing.T) {
compareStageResults(t, stageResults, expectedStageResults, regex) compareStageResults(t, stageResults, expectedStageResults, regex)
}) })
} }
if !t.Failed() {
scoreboard.SaveFile("../../scoreboard.json")
defer os.Remove("../../scoreboard.json")
scoreboard.Submit()
}
} }

View File

@ -1,44 +1,40 @@
package scoreboard package scoreboard
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt"
"log/slog"
"os" "os"
"os/exec"
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
) )
type Question struct { type StageRecord struct {
Name string `json:"name"` StageName string `json:"stagename"`
Score int `json:"score"` StageResults []stage.StageResult `json:"stageresults"`
Comment string `json:"comment"`
} }
type ScoreboardData struct { type ScoreboardData struct {
StudentName string `json:"studentname"` StageRecords []StageRecord `json:"stagerecords"`
StudentId string `json:"studentid"`
Questions []Question `json:"questions"`
} }
type Scoreboard struct { type Scoreboard struct {
scoreboard ScoreboardData studentName string
studentId string
scoreboard ScoreboardData
} }
func (b *Scoreboard) Init(studentName string, studentId string) { func (b *Scoreboard) Init(studentName string, studentId string) {
b.scoreboard.StudentName = studentName b.studentName = studentName
b.scoreboard.StudentId = studentId b.studentId = studentId
b.scoreboard.Questions = make([]Question, 0) b.scoreboard.StageRecords = make([]StageRecord, 0)
} }
func (b *Scoreboard) AddScore(questionName string, score int) { func (b *Scoreboard) AddScore(stagename string, results []stage.StageResult) {
flag := false b.scoreboard.StageRecords = append(b.scoreboard.StageRecords,
for i, question := range b.scoreboard.Questions { StageRecord{StageName: stagename, StageResults: results})
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) SaveFile(filePath string) { func (b *Scoreboard) SaveFile(filePath string) {
@ -50,3 +46,54 @@ func (b *Scoreboard) SaveFile(filePath string) {
encoder.SetIndent("", " ") encoder.SetIndent("", " ")
_ = encoder.Encode(b.scoreboard) _ = 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())
}