Skip to content

Commit

Permalink
美化榜单界面,修复含CRLF的答案文件无法正确比对的bug
Browse files Browse the repository at this point in the history
  • Loading branch information
odorajbotoj committed Mar 18, 2024
1 parent b07e963 commit c330471
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 45 deletions.
4 changes: 1 addition & 3 deletions internal/app/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

const (
// 项目基本信息
VERSION string = "v1.1.0" // 版本号
VERSION string = "v1.1.1" // 版本号
)

var (
Expand Down Expand Up @@ -71,7 +71,6 @@ var elog *log.Logger

// 正则
var goodUserName *regexp.Regexp // 合法用户名
var splitLine *regexp.Regexp // 分行

func Init() {
// 新建elog, 专用输出错误信息
Expand All @@ -83,7 +82,6 @@ func Init() {

// 编译正则
goodUserName = regexp.MustCompile("^[\u4E00-\u9FA5A-Za-z0-9_]{2,20}$")
splitLine = regexp.MustCompile(`[\t\n\f\r]`)

// 检查配置文件
err = checkConfig()
Expand Down
64 changes: 38 additions & 26 deletions internal/app/judge.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -109,7 +108,7 @@ func judger() {
// 循环,评测每个点
log.Println("运行")
var allOK = true
var m = make(map[string]TestPoint) // 储存每个点的状态
var m = make(map[int]TestPoint) // 储存每个点的状态
if jt.Task.FileIO {
// 文件输入输出
for i := 1; i <= cnt; i++ {
Expand All @@ -126,16 +125,16 @@ func judger() {
log.Println("测试点", i)
_, runstde, runisk, ti, runerr := cmdWithTimeout(jt.Task.Duration, nil, tdn+"/", exe)
if runisk { // 超时 TLE
m[strconv.Itoa(i)] = TestPoint{"TLE", "time limit exceed", ti.Milliseconds()}
m[i] = TestPoint{"TLE", "time limit exceed", ti.Milliseconds()}
log.Println("TLE")
continue
}
if runstde != "" { // 运行出错 RE
m[strconv.Itoa(i)] = TestPoint{"RE", runstde, ti.Milliseconds()}
m[i] = TestPoint{"RE", runstde, ti.Milliseconds()}
log.Println("RE")
continue
} else if runerr != nil {
m[strconv.Itoa(i)] = TestPoint{"RE", runerr.Error(), ti.Milliseconds()}
m[i] = TestPoint{"RE", runerr.Error(), ti.Milliseconds()}
log.Println("RE")
continue
}
Expand All @@ -161,18 +160,22 @@ func judger() {
out := string(outBytes)
ans = strings.TrimSpace(ans)
out = strings.TrimSpace(out)
ansLines := splitLine.Split(ans, -1)
outLines := splitLine.Split(out, -1)
ansLines := strings.Split(strings.ReplaceAll(ans, "\r\n", "\n"), "\n")
outLines := strings.Split(strings.ReplaceAll(out, "\r\n", "\n"), "\n")
if len(ansLines) != len(outLines) {
m[strconv.Itoa(i)] = TestPoint{"WA", "wrong answer", ti.Milliseconds()}
if len(ansLines) > len(outLines) {
m[i] = TestPoint{"WA", "wrong answer (too short)", ti.Microseconds()}
} else {
m[i] = TestPoint{"WA", "wrong answer (too long)", ti.Microseconds()}
}
log.Println("WA")
continue
}
m[strconv.Itoa(i)] = TestPoint{"AC", "accepted", ti.Milliseconds()}
m[i] = TestPoint{"AC", "accepted", ti.Milliseconds()}
log.Println("?AC")
for j := 0; j < len(ansLines); j++ {
if ansLines[j] != outLines[j] {
m[strconv.Itoa(i)] = TestPoint{"WA", "wrong answer", ti.Milliseconds()}
m[i] = TestPoint{"WA", "wrong answer (expect: " + ansLines[j] + ", get: " + outLines[j] + ")", ti.Milliseconds()}
log.Println("WA!")
break
}
Expand All @@ -195,16 +198,16 @@ func judger() {
runstdo, runstde, runisk, ti, runerr := cmdWithTimeout(jt.Task.Duration, inpFile, tdn+"/", exe)
inpFile.Close()
if runisk { // 超时 TLE
m[strconv.Itoa(i)] = TestPoint{"TLE", "time limit exceed", ti.Microseconds()}
m[i] = TestPoint{"TLE", "time limit exceed", ti.Microseconds()}
log.Println("TLE")
continue
}
if runstde != "" { // 运行出错 RE
m[strconv.Itoa(i)] = TestPoint{"RE", runstde, ti.Microseconds()}
m[i] = TestPoint{"RE", runstde, ti.Microseconds()}
log.Println("RE")
continue
} else if runerr != nil {
m[strconv.Itoa(i)] = TestPoint{"RE", runerr.Error(), ti.Microseconds()}
m[i] = TestPoint{"RE", runerr.Error(), ti.Microseconds()}
log.Println("RE")
continue
}
Expand All @@ -222,18 +225,22 @@ func judger() {
out := runstdo
ans = strings.TrimSpace(ans)
out = strings.TrimSpace(out)
ansLines := splitLine.Split(ans, -1)
outLines := splitLine.Split(out, -1)
ansLines := strings.Split(strings.ReplaceAll(ans, "\r\n", "\n"), "\n")
outLines := strings.Split(strings.ReplaceAll(out, "\r\n", "\n"), "\n")
if len(ansLines) != len(outLines) {
m[strconv.Itoa(i)] = TestPoint{"WA", "wrong answer", ti.Microseconds()}
if len(ansLines) > len(outLines) {
m[i] = TestPoint{"WA", "wrong answer (too short)", ti.Microseconds()}
} else {
m[i] = TestPoint{"WA", "wrong answer (too long)", ti.Microseconds()}
}
log.Println("WA")
continue
}
m[strconv.Itoa(i)] = TestPoint{"AC", "accepted", ti.Microseconds()}
m[i] = TestPoint{"AC", "accepted", ti.Microseconds()}
log.Println("?AC")
for j := 0; j < len(ansLines); j++ {
if ansLines[j] != outLines[j] {
m[strconv.Itoa(i)] = TestPoint{"WA", "wrong answer", ti.Microseconds()}
m[i] = TestPoint{"WA", "wrong answer (expect: " + ansLines[j] + ", get: " + outLines[j] + ")", ti.Microseconds()}
log.Println("WA!")
break
}
Expand Down Expand Up @@ -278,11 +285,11 @@ func cmdWithTimeout(tout int, inp io.Reader, dir string, cmd string, args ...str
c.Dir = dir
var t time.Duration
done := make(chan error)
sT := time.Now()
err = c.Start()
if err != nil {
return "", "", false, 0, err
}
sT := time.Now()
after := time.After(time.Duration(tout) * time.Millisecond)
go func() {
done <- c.Wait()
Expand Down Expand Up @@ -310,16 +317,21 @@ func cmdWithTimeout(tout int, inp io.Reader, dir string, cmd string, args ...str
}

// 生成TaskStat结果并存储至RDB
func sumRst(uname string, tname string, stat string, info string, details map[string]TestPoint) {
func sumRst(uname string, tname string, stat string, info string, details map[int]TestPoint) {
err := rdb.Update(func(tx *buntdb.Tx) error {
v, e := tx.Get(tname + ":" + uname)
if e != nil {
return e
}
var ts TaskStat
e = json.Unmarshal([]byte(v), &ts)
v, e := tx.Get(tname + ":" + uname)
if e != nil {
return e
if e != buntdb.ErrNotFound {
return e
} else {
ts.Judge = true
}
} else {
e = json.Unmarshal([]byte(v), &ts)
if e != nil {
return e
}
}
ts.Stat = stat
ts.Info = info
Expand Down
1 change: 1 addition & 0 deletions internal/app/recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func fSubmit(w http.ResponseWriter, r *http.Request) {
err = rdb.Update(func(tx *buntdb.Tx) error {
var t TaskStat
t.Md5 = newMd5
t.Info = "user submitted"
t.Judge = taskinfo.Judge
if t.Judge {
t.Stat = "Waiting"
Expand Down
25 changes: 21 additions & 4 deletions internal/app/rk.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ func fRk(w http.ResponseWriter, r *http.Request) {
return
}
tmpl, err := template.New("rk").Funcs(template.FuncMap{
"getrst": getrst,
"getcol": getcol,
"getRst": getRst,
"getCol": getCol,
"getPointCol": getPointCol,
}).Parse(RKHTML)
if err != nil {
elog.Println(err)
Expand Down Expand Up @@ -105,7 +106,7 @@ func sumRk() []string { // getUserSorted
return ul
}

func getrst(name, task string) TaskStat {
func getRst(name, task string) TaskStat {
var val string
var e error
err := rdb.View(func(tx *buntdb.Tx) error {
Expand All @@ -122,8 +123,10 @@ func getrst(name, task string) TaskStat {
return ts
}

func getcol(ts TaskStat) string {
func getCol(ts TaskStat) string {
switch ts.Stat {
case "Submitted":
return "0,255,0,0.5"
case "--":
return "255,0,0,0.5"
case "CE":
Expand All @@ -143,3 +146,17 @@ func getcol(ts TaskStat) string {
r := 0.1 + ac/total*0.4
return fmt.Sprintf("0,255,0,%f", r)
}

func getPointCol(tp TestPoint) string {
switch tp.Stat {
case "AC":
return "0,255,0,0.5"
case "WA":
return "255,0,0,0.5"
case "RE":
return "255,165,0,0.5"
case "TLE":
return "255,255,0,0.5"
}
return "255,255,255,0"
}
26 changes: 20 additions & 6 deletions internal/app/static/html/rk.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div id="rk">
<fieldset>
<legend id="top">榜单</legend>
<table border="1">
<table>
<tr>
<th>Name</th>
{{range $v := .TaskList}}
Expand All @@ -12,7 +12,7 @@
<tr>
<td>{{$n}}</td>
{{range $t := $.TaskList}}
{{with getrst $n $t}}<td style="background-color:rgba({{getcol .}})"><a href="#{{$n}}-{{$t}}">{{.Stat}}</a>{{end}}</td>
{{with getRst $n $t}}<td style="background-color:rgba({{getCol .}})"><a href="#{{$n}}-{{$t}}">{{.Stat}}</a>{{end}}</td>
{{end}}
</tr>
{{end}}
Expand All @@ -23,11 +23,25 @@
<legend>用户:{{$n}}</legend>
{{range $t := $.TaskList}}
<h3 id="{{$n}}-{{$t}}">题目:{{$t}}</h3>
{{with getrst $n $t}}
<pre>{{if .Info}}{{.Info}}{{end}}</pre>
{{with getRst $n $t}}
{{if .Info}}<pre>{{.Info}}</pre>{{end}}
{{if .Details}}
<table>
<tr>
<th>测试点</th>
<th>状态</th>
<th>耗时</th>
<th>详情</th>
</tr>
{{range $k, $v := .Details}}
<h4>{{$k}}# {{$v.Stat}} ({{$v.Time}}ms)</h4>
<pre>{{$v.Info}}</pre>
<tr>
<td>{{$k}}#</td>
<td style="background-color:rgba({{getPointCol .}})">{{$v.Stat}}</td>
<td>{{$v.Time}}ms</td>
<td><pre>{{$v.Info}}</pre></td>
</tr>
{{end}}
</table>
{{end}}
{{end}}
<a href="#top">回到顶部</a>
Expand Down
25 changes: 20 additions & 5 deletions internal/app/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ type TaskPoint struct {
}

type TaskStat struct {
Md5 string // 校验和
Judge bool // 是否评测(以下内容仅在此选项为真时有意义)
Stat string // 评测状态
Info string // 输出的信息
Details map[string]TestPoint // 测试点状态
Md5 string // 校验和
Judge bool // 是否评测(以下内容仅在此选项为真时有意义)
Stat string // 评测状态
Info string // 输出的信息
Details map[int]TestPoint // 测试点状态
}

type TestPoint struct {
Expand Down Expand Up @@ -449,6 +449,21 @@ func fUpldTest(w http.ResponseWriter, r *http.Request) {
elog.Println(err)
return
}
var t TaskPoint
err = tdb.View(func(tx *buntdb.Tx) error {
s, e := tx.Get("task:" + na + ":info")
if e != nil {
return e
}
e = json.Unmarshal([]byte(s), &t)
return e
})
if err != nil {
alertAndRedir(w, "上传失败:"+err.Error(), "/editTask?tn="+na)
elog.Println(err)
return
}
go reJudgeTask(t)
alertAndRedir(w, "上传成功", "/editTask?tn="+na)
log.Println("上传测试点 " + na)
return
Expand Down
3 changes: 2 additions & 1 deletion internal/app/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"log"
"net/http"
"net/url"
"strings"

"github.com/tidwall/buntdb"
)
Expand Down Expand Up @@ -113,7 +114,7 @@ func fRegAdmin(w http.ResponseWriter, r *http.Request) {
return
}
// 分割
users := splitLine.Split(r.Form.Get("userRegName"), -1)
users := strings.Split(strings.ReplaceAll(r.Form.Get("userRegName"), "\r\n", "\n"), "\n")
if len(users) == 0 {
alertAndRedir(w, "注册失败,表单为空", "/regAdmin")
return
Expand Down

0 comments on commit c330471

Please sign in to comment.