feat(parser/tierscore): new tiered scoring parser
This commit is contained in:
parent
dd4e375dd4
commit
45490f3d1e
|
@ -13,6 +13,7 @@ import (
|
|||
_ "github.com/joint-online-judge/JOJ3/internal/parser/resultdetail"
|
||||
_ "github.com/joint-online-judge/JOJ3/internal/parser/resultstatus"
|
||||
_ "github.com/joint-online-judge/JOJ3/internal/parser/sample"
|
||||
_ "github.com/joint-online-judge/JOJ3/internal/parser/tierscore"
|
||||
)
|
||||
|
||||
// this file does nothing but imports to ensure all the init() functions
|
||||
|
|
24
internal/parser/tierscore/meta.go
Normal file
24
internal/parser/tierscore/meta.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Package tierscore provides a parser for tiered scoring based on
|
||||
// time and memory constraints. Leave the field empty or 0 to disable.
|
||||
|
||||
package tierscore
|
||||
|
||||
import "github.com/joint-online-judge/JOJ3/internal/stage"
|
||||
|
||||
var name = "tierscore"
|
||||
|
||||
type Tier struct {
|
||||
TimeLessThan uint64 // ns
|
||||
MemoryLessThan uint64 // bytes
|
||||
Score int
|
||||
}
|
||||
|
||||
type Conf struct {
|
||||
Tiers []Tier
|
||||
}
|
||||
|
||||
type TierScore struct{}
|
||||
|
||||
func init() {
|
||||
stage.RegisterParser(name, &TierScore{})
|
||||
}
|
102
internal/parser/tierscore/parser.go
Normal file
102
internal/parser/tierscore/parser.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package tierscore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/joint-online-judge/JOJ3/internal/stage"
|
||||
)
|
||||
|
||||
func (*TierScore) Run(results []stage.ExecutorResult, confAny any) (
|
||||
[]stage.ParserResult, bool, error,
|
||||
) {
|
||||
conf, err := stage.DecodeConf[Conf](confAny)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
var res []stage.ParserResult
|
||||
forceQuit := false
|
||||
|
||||
for _, result := range results {
|
||||
totalScore := 0
|
||||
var commentBuilder strings.Builder
|
||||
|
||||
for i, tier := range conf.Tiers {
|
||||
conditionsMet := true
|
||||
var conditionDesc []string
|
||||
|
||||
if tier.TimeLessThan > 0 {
|
||||
if result.Time < tier.TimeLessThan {
|
||||
conditionDesc = append(
|
||||
conditionDesc,
|
||||
fmt.Sprintf(
|
||||
"Time < `%d ms`",
|
||||
tier.TimeLessThan/1e6,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
conditionsMet = false
|
||||
}
|
||||
}
|
||||
|
||||
if tier.MemoryLessThan > 0 {
|
||||
if result.Memory < tier.MemoryLessThan {
|
||||
conditionDesc = append(
|
||||
conditionDesc,
|
||||
fmt.Sprintf(
|
||||
"Memory < `%.2f MiB`",
|
||||
float64(tier.MemoryLessThan)/(1024*1024),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
conditionsMet = false
|
||||
}
|
||||
}
|
||||
|
||||
if conditionsMet {
|
||||
totalScore += tier.Score
|
||||
fmt.Fprintf(
|
||||
&commentBuilder,
|
||||
"Tier %d: +%d (meets %s)\n",
|
||||
i,
|
||||
tier.Score,
|
||||
strings.Join(conditionDesc, " and "),
|
||||
)
|
||||
} else {
|
||||
var required []string
|
||||
if tier.TimeLessThan > 0 {
|
||||
required = append(
|
||||
required,
|
||||
fmt.Sprintf(
|
||||
"Time < `%d ms`",
|
||||
tier.TimeLessThan/1e6,
|
||||
),
|
||||
)
|
||||
}
|
||||
if tier.MemoryLessThan > 0 {
|
||||
required = append(
|
||||
required,
|
||||
fmt.Sprintf(
|
||||
"Memory < `%.2f MiB`",
|
||||
float64(tier.MemoryLessThan)/(1024*1024),
|
||||
),
|
||||
)
|
||||
}
|
||||
fmt.Fprintf(
|
||||
&commentBuilder,
|
||||
"Tier %d: +0 (requires %s)\n",
|
||||
i+1,
|
||||
strings.Join(required, " and "),
|
||||
)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&commentBuilder, "Final score: %d", totalScore)
|
||||
res = append(res, stage.ParserResult{
|
||||
Score: totalScore,
|
||||
Comment: commentBuilder.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return res, forceQuit, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user