Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/db/models/models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (

func fixtureDb(t *testing.T) *gorm.DB {
db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
err := db.AutoMigrate(&Submission{})
assert.NoError(t, err)
assert.NoError(t, db.AutoMigrate(&Submission{}))
assert.NoError(t, db.AutoMigrate(&Problem{}))
return db
}

Expand Down
81 changes: 76 additions & 5 deletions common/db/models/problem.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,86 @@
package models

import (
"database/sql/driver"
"encoding/json"
"errors"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"testing_system/lib/customfields"
)

type ProblemType int

const (
ProblemType_ICPC ProblemType = iota + 1
ProblemType_IOI
ProblemTypeICPC ProblemType = iota + 1
ProblemTypeIOI
)

// TestGroupScoringType sets how should scheduler set points for a group
type TestGroupScoringType int

const (
// TestGroupScoringTypeComplete means that group costs TestGroup.GroupScore (all the tests should be OK)
TestGroupScoringTypeComplete TestGroupScoringType = iota + 1
// TestGroupScoringTypeEachTest means that group score = TestGroup.TestScore * (number of tests with OK)
TestGroupScoringTypeEachTest
// TestGroupScoringTypeMin means that group score = min(checker's scores among all the tests)
TestGroupScoringTypeMin
)

// TestGroupFeedbackType sets which info about tests in a group would be shown
type TestGroupFeedbackType int

const (
// TestGroupFeedbackTypeNone won't show anything
TestGroupFeedbackTypeNone TestGroupFeedbackType = iota + 1
// TestGroupFeedbackTypePoints will show points only
TestGroupFeedbackTypePoints
// TestGroupFeedbackTypeICPC will show verdict, time and memory usage for the first test with no OK
TestGroupFeedbackTypeICPC
// TestGroupFeedbackTypeComplete same as TestGroupFeedbackTypeICPC, but for every test
TestGroupFeedbackTypeComplete
// TestGroupFeedbackTypeFull same as TestGroupFeedbackTypeComplete, but with input, output, stderr, etc.
TestGroupFeedbackTypeFull
)

type TestGroup struct {
Name string `json:"name" yaml:"name"`
FirstTest uint64 `json:"FirstTest" yaml:"FirstTest"`
LastTest uint64 `json:"LastTest" yaml:"LastTest"`
// TestScore meaningful only in case of TestGroupScoringTypeEachTest
TestScore *float64 `json:"TestScore" yaml:"TestScore"`
// GroupScore meaningful only in case of TestGroupScoringTypeComplete
GroupScore *float64 `json:"GroupScore" yaml:"GroupScore"`
ScoringType TestGroupScoringType `json:"ScoringType" yaml:"ScoringType"`
FeedbackType TestGroupFeedbackType `json:"FeedbackType" yaml:"FeedbackType"`
RequiredGroupNames []string `json:"RequiredGroupNames" yaml:"RequiredGroupNames"`
}

type TestGroups []TestGroup

func (t TestGroups) Value() (driver.Value, error) {
return json.Marshal(t)
}

func (t *TestGroups) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed while scanning TestGroups")
}
return json.Unmarshal(bytes, t)
}

func (t TestGroups) GormDBDataType(db *gorm.DB, field *schema.Field) string {
switch db.Dialector.Name() {
case "mysql", "sqlite":
return "JSON"
case "postgres":
return "JSONB"
}
return ""
}

type Problem struct {
gorm.Model

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

TestsNumber uint64 `yaml:"TestsNumber"`
// TestGroups ignored for ICPC problems
TestGroups TestGroups `yaml:"TestGroups"`

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

// MaxOpenFiles specifies maximum number of files, opened by testing system.
// MaxOpenFiles specifies the maximum number of files, opened by testing system.
// By default, it is 64
MaxOpenFiles *uint64 `yaml:"MaxOpenFiles,omitempty"`

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

Expand Down
41 changes: 37 additions & 4 deletions common/db/models/submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type TestResult struct {
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
Time customfields.Time `json:"Time" yaml:"Time"`
Memory customfields.Memory `json:"Memory" yaml:"Memory"`
Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
}

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

type GroupResult struct {
GroupName string `json:"GroupName" yaml:"GroupName"`
Points float64 `json:"Points" yaml:"Points"`
Passed bool `json:"Passed" yaml:"Passed"`
// TODO maybe more fields
}

type GroupResults []GroupResult

func (t GroupResults) Value() (driver.Value, error) {
return json.Marshal(t)
}

func (t *GroupResults) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed while scanning GroupResults")
}
return json.Unmarshal(bytes, t)
}

func (t GroupResults) GormDBDataType(db *gorm.DB, field *schema.Field) string {
switch db.Dialector.Name() {
case "mysql", "sqlite":
return "JSON"
case "postgres":
return "JSONB"
}
return ""
}

type Submission struct {
gorm.Model
ProblemID uint64 `json:"ProblemID" yaml:"ProblemID"`
Language string `json:"Language" yaml:"Language"`

Score float64 `json:"Score" yaml:"Score"`
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
TestResults TestResults `gorm:"type:jsonb" json:"TestResults" yaml:"TestResults"`
Score float64 `json:"Score" yaml:"Score"`
Verdict verdict.Verdict `json:"Verdict" yaml:"Verdict"`
TestResults TestResults `json:"TestResults" yaml:"TestResults"`
GroupResults GroupResults `json:"GroupResults" yaml:"GroupResults"`
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ require (
github.com/stretchr/testify v1.10.0
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.4
github.com/xorcare/pointer v1.2.2
golang.org/x/net v0.39.0
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -53,6 +52,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/swaggo/swag v1.16.4 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.16.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions master/queue/jobgenerators/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package jobgenerators

// used in IOI and ICPC generators
type generatorState int

const (
compilationNotStarted generatorState = iota
compilationStarted
compilationFinished
)
4 changes: 3 additions & 1 deletion master/queue/jobgenerators/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ type Generator interface {

func NewGenerator(problem *models.Problem, submission *models.Submission) (Generator, error) {
switch problem.ProblemType {
case models.ProblemType_ICPC:
case models.ProblemTypeICPC:
return newICPCGenerator(problem, submission)
case models.ProblemTypeIOI:
return NewIOIGenerator(problem, submission)
default:
return nil, fmt.Errorf("unknown problem type %v", problem.ProblemType)
}
Expand Down
Loading
Loading