Skip to content

Commit 639b2c4

Browse files
authored
scheduler for IOI problems (#17)
* WIP ioi scheduler * fixes and tests * i hate IOI problems * new generation of ioi generators * small fixes * tmp * try to resolve conflicts * fixes * more checks at problem creation * fixes v2
1 parent 98e5e26 commit 639b2c4

File tree

11 files changed

+1720
-283
lines changed

11 files changed

+1720
-283
lines changed

common/db/models/models_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515

1616
func fixtureDb(t *testing.T) *gorm.DB {
1717
db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
18-
err := db.AutoMigrate(&Submission{})
19-
assert.NoError(t, err)
18+
assert.NoError(t, db.AutoMigrate(&Submission{}))
19+
assert.NoError(t, db.AutoMigrate(&Problem{}))
2020
return db
2121
}
2222

common/db/models/problem.go

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,86 @@
11
package models
22

33
import (
4+
"database/sql/driver"
5+
"encoding/json"
6+
"errors"
47
"gorm.io/gorm"
8+
"gorm.io/gorm/schema"
59
"testing_system/lib/customfields"
610
)
711

812
type ProblemType int
913

1014
const (
11-
ProblemType_ICPC ProblemType = iota + 1
12-
ProblemType_IOI
15+
ProblemTypeICPC ProblemType = iota + 1
16+
ProblemTypeIOI
1317
)
1418

19+
// TestGroupScoringType sets how should scheduler set points for a group
20+
type TestGroupScoringType int
21+
22+
const (
23+
// TestGroupScoringTypeComplete means that group costs TestGroup.GroupScore (all the tests should be OK)
24+
TestGroupScoringTypeComplete TestGroupScoringType = iota + 1
25+
// TestGroupScoringTypeEachTest means that group score = TestGroup.TestScore * (number of tests with OK)
26+
TestGroupScoringTypeEachTest
27+
// TestGroupScoringTypeMin means that group score = min(checker's scores among all the tests)
28+
TestGroupScoringTypeMin
29+
)
30+
31+
// TestGroupFeedbackType sets which info about tests in a group would be shown
32+
type TestGroupFeedbackType int
33+
34+
const (
35+
// TestGroupFeedbackTypeNone won't show anything
36+
TestGroupFeedbackTypeNone TestGroupFeedbackType = iota + 1
37+
// TestGroupFeedbackTypePoints will show points only
38+
TestGroupFeedbackTypePoints
39+
// TestGroupFeedbackTypeICPC will show verdict, time and memory usage for the first test with no OK
40+
TestGroupFeedbackTypeICPC
41+
// TestGroupFeedbackTypeComplete same as TestGroupFeedbackTypeICPC, but for every test
42+
TestGroupFeedbackTypeComplete
43+
// TestGroupFeedbackTypeFull same as TestGroupFeedbackTypeComplete, but with input, output, stderr, etc.
44+
TestGroupFeedbackTypeFull
45+
)
46+
47+
type TestGroup struct {
48+
Name string `json:"name" yaml:"name"`
49+
FirstTest uint64 `json:"FirstTest" yaml:"FirstTest"`
50+
LastTest uint64 `json:"LastTest" yaml:"LastTest"`
51+
// TestScore meaningful only in case of TestGroupScoringTypeEachTest
52+
TestScore *float64 `json:"TestScore" yaml:"TestScore"`
53+
// GroupScore meaningful only in case of TestGroupScoringTypeComplete
54+
GroupScore *float64 `json:"GroupScore" yaml:"GroupScore"`
55+
ScoringType TestGroupScoringType `json:"ScoringType" yaml:"ScoringType"`
56+
FeedbackType TestGroupFeedbackType `json:"FeedbackType" yaml:"FeedbackType"`
57+
RequiredGroupNames []string `json:"RequiredGroupNames" yaml:"RequiredGroupNames"`
58+
}
59+
60+
type TestGroups []TestGroup
61+
62+
func (t TestGroups) Value() (driver.Value, error) {
63+
return json.Marshal(t)
64+
}
65+
66+
func (t *TestGroups) Scan(value interface{}) error {
67+
bytes, ok := value.([]byte)
68+
if !ok {
69+
return errors.New("type assertion to []byte failed while scanning TestGroups")
70+
}
71+
return json.Unmarshal(bytes, t)
72+
}
73+
74+
func (t TestGroups) GormDBDataType(db *gorm.DB, field *schema.Field) string {
75+
switch db.Dialector.Name() {
76+
case "mysql", "sqlite":
77+
return "JSON"
78+
case "postgres":
79+
return "JSONB"
80+
}
81+
return ""
82+
}
83+
1584
type Problem struct {
1685
gorm.Model
1786

@@ -21,17 +90,19 @@ type Problem struct {
2190
MemoryLimit customfields.Memory `yaml:"MemoryLimit"`
2291

2392
TestsNumber uint64 `yaml:"TestsNumber"`
93+
// TestGroups ignored for ICPC problems
94+
TestGroups TestGroups `yaml:"TestGroups"`
2495

2596
// WallTimeLimit specifies maximum execution and wait time.
2697
// By default, it is max(5s, TimeLimit * 2)
2798
WallTimeLimit *customfields.Time `yaml:"WallTimeLimit,omitempty"`
2899

29-
// MaxOpenFiles specifies maximum number of files, opened by testing system.
100+
// MaxOpenFiles specifies the maximum number of files, opened by testing system.
30101
// By default, it is 64
31102
MaxOpenFiles *uint64 `yaml:"MaxOpenFiles,omitempty"`
32103

33-
// MaxThreads specifies maximum number of threads and/or processes
34-
// By default, it is single thread
104+
// MaxThreads specifies the maximum number of threads and/or processes;
105+
// By default, it is a single thread
35106
// If MaxThreads equals to -1, any number of threads allowed
36107
MaxThreads *int64 `yaml:"MaxThreads,omitempty"`
37108

common/db/models/submission.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type TestResult struct {
1616
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
1717
Time customfields.Time `json:"Time" yaml:"Time"`
1818
Memory customfields.Memory `json:"Memory" yaml:"Memory"`
19+
Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
1920
}
2021

2122
type TestResults []TestResult
@@ -27,7 +28,7 @@ func (t TestResults) Value() (driver.Value, error) {
2728
func (t *TestResults) Scan(value interface{}) error {
2829
bytes, ok := value.([]byte)
2930
if !ok {
30-
return errors.New("type assertion to []byte failed")
31+
return errors.New("type assertion to []byte failed while scanning TestResults")
3132
}
3233
return json.Unmarshal(bytes, t)
3334
}
@@ -42,12 +43,44 @@ func (t TestResults) GormDBDataType(db *gorm.DB, field *schema.Field) string {
4243
return ""
4344
}
4445

46+
type GroupResult struct {
47+
GroupName string `json:"GroupName" yaml:"GroupName"`
48+
Points float64 `json:"Points" yaml:"Points"`
49+
Passed bool `json:"Passed" yaml:"Passed"`
50+
// TODO maybe more fields
51+
}
52+
53+
type GroupResults []GroupResult
54+
55+
func (t GroupResults) Value() (driver.Value, error) {
56+
return json.Marshal(t)
57+
}
58+
59+
func (t *GroupResults) Scan(value interface{}) error {
60+
bytes, ok := value.([]byte)
61+
if !ok {
62+
return errors.New("type assertion to []byte failed while scanning GroupResults")
63+
}
64+
return json.Unmarshal(bytes, t)
65+
}
66+
67+
func (t GroupResults) GormDBDataType(db *gorm.DB, field *schema.Field) string {
68+
switch db.Dialector.Name() {
69+
case "mysql", "sqlite":
70+
return "JSON"
71+
case "postgres":
72+
return "JSONB"
73+
}
74+
return ""
75+
}
76+
4577
type Submission struct {
4678
gorm.Model
4779
ProblemID uint64 `json:"ProblemID" yaml:"ProblemID"`
4880
Language string `json:"Language" yaml:"Language"`
4981

50-
Score float64 `json:"Score" yaml:"Score"`
51-
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
52-
TestResults TestResults `gorm:"type:jsonb" json:"TestResults" yaml:"TestResults"`
82+
Score float64 `json:"Score" yaml:"Score"`
83+
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
84+
TestResults TestResults `json:"TestResults" yaml:"TestResults"`
85+
GroupResults GroupResults `json:"GroupResults" yaml:"GroupResults"`
5386
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ require (
1010
github.com/stretchr/testify v1.10.0
1111
github.com/swaggo/files v1.0.1
1212
github.com/swaggo/gin-swagger v1.6.0
13-
github.com/swaggo/swag v1.16.4
1413
github.com/xorcare/pointer v1.2.2
1514
golang.org/x/net v0.39.0
1615
gopkg.in/yaml.v3 v3.0.1
@@ -53,6 +52,7 @@ require (
5352
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
5453
github.com/pmezard/go-difflib v1.0.0 // indirect
5554
github.com/rogpeppe/go-internal v1.13.1 // indirect
55+
github.com/swaggo/swag v1.16.4 // indirect
5656
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
5757
github.com/ugorji/go/codec v1.2.12 // indirect
5858
golang.org/x/arch v0.16.0 // indirect
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package jobgenerators
2+
3+
// used in IOI and ICPC generators
4+
type generatorState int
5+
6+
const (
7+
compilationNotStarted generatorState = iota
8+
compilationStarted
9+
compilationFinished
10+
)

master/queue/jobgenerators/generator.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ type Generator interface {
2121

2222
func NewGenerator(problem *models.Problem, submission *models.Submission) (Generator, error) {
2323
switch problem.ProblemType {
24-
case models.ProblemType_ICPC:
24+
case models.ProblemTypeICPC:
2525
return newICPCGenerator(problem, submission)
26+
case models.ProblemTypeIOI:
27+
return NewIOIGenerator(problem, submission)
2628
default:
2729
return nil, fmt.Errorf("unknown problem type %v", problem.ProblemType)
2830
}

0 commit comments

Comments
 (0)