-
Notifications
You must be signed in to change notification settings - Fork 0
/
commands.go
211 lines (171 loc) · 5.27 KB
/
commands.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package main
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/Leixb/jutge/commands"
"github.com/Leixb/jutge/database"
"github.com/alecthomas/kong"
)
func jutgeConf(globals *Globals) (*commands.JutgeConfig, error) {
regex, err := regexp.Compile(globals.Regex)
if err != nil {
return nil, err
}
return &commands.JutgeConfig{
URL: globals.URL,
Folder: globals.WorkDir,
Regex: regex,
}, nil
}
type DownloadCmd struct {
Codes []string `arg:"" required:"" help:"the codes of problems to download"`
Overwrite bool `help:"overwrite the existing files" default:"false"`
}
func (d *DownloadCmd) Run(ctx *kong.Context, globals *Globals) error {
conf, err := jutgeConf(globals)
if err != nil {
return err
}
return commands.Jutge(conf).DownloadProblems(
d.Codes, d.Overwrite, globals.Concurrency)
}
type TestCmd struct {
Programs []string `arg:"" required:"" type:"path" help:"the programs to test"`
Code string `help:"the code of problem to test"`
DownloadMissing bool `help:"download the missing programs" default:"false"`
Overwrite bool `help:"overwrite the existing files" default:"false"`
}
func (t *TestCmd) Run(ctx *kong.Context, globals *Globals) error {
conf, err := jutgeConf(globals)
if err != nil {
return err
}
passedTotal, countTotal, err := commands.Jutge(conf).TestPrograms(
t.Code, t.Programs, t.DownloadMissing, t.Overwrite, globals.Concurrency)
println("Passed:", passedTotal, "Total:", countTotal)
return err
}
type UploadCmd struct {
Files []string `arg:"" required:"" type:"path" help:"the files to upload"`
Code string `help:"the code of problem to upload"`
Compiler string `help:"the compiler of problem to upload" default:"AUTO" enum:"${compilers}"`
Annotation string `help:"the annotation of problem to upload" default:"Uploaded with jutge-go"`
Check bool `help:"check the uploaded files" default:"false"`
}
func (u *UploadCmd) Run(ctx *kong.Context, globals *Globals) error {
conf, err := jutgeConf(globals)
if err != nil {
return err
}
jutge := commands.Jutge(conf)
codes, err := jutge.UploadFiles(u.Files, u.Code, u.Compiler, u.Annotation, globals.Concurrency)
if err != nil {
return err
}
if u.Check {
codeList := make([]string, len(codes))
i := 0
for code := range codes {
codeList[i] = code
i++
}
time.Sleep(time.Second * 10)
err = jutge.CheckProblems(codeList, globals.Concurrency)
}
return err
}
type CheckCmd struct {
Codes []string `arg:"" required:"" help:"the codes of problems to check"`
Submission int `optional:"" short:"s" help:"the submission number to check (negative to check from back, 0 to check problem status as a whole)" default:"0"`
}
func (c *CheckCmd) Run(ctx *kong.Context, globals *Globals) error {
conf, err := jutgeConf(globals)
if err != nil {
return err
}
jutge := commands.Jutge(conf)
if c.Submission == 0 {
return jutge.CheckProblems(c.Codes, globals.Concurrency)
}
return commands.RunParallelFuncs(c.Codes, func(code string) error {
subn := c.Submission
if c.Submission < 0 {
n, err := jutge.GetNumSubmissions(code)
if err != nil {
fmt.Println("Error checking submissions of", code)
return err
}
subn = n + 1 + c.Submission
}
veredict, err := jutge.CheckSubmission(code, subn)
if err != nil {
fmt.Println("Error checking submission", subn, "of", code)
return err
}
fmt.Println(code, subn, veredict)
return nil
}, globals.Concurrency)
}
type DatabaseCmd struct {
Dump struct{} `cmd:"" help:"dump the database contents"`
Add struct {
Code string `arg:"" required:"" help:"the code of problem to add"`
Title string `arg:"" required:"" help:"the title of problem to add"`
} `cmd:"" help:"add a problem to the database"`
Query struct {
Code string `arg:"" required:"" help:"the code of problem to query"`
} `cmd:"" help:"query the database"`
Import struct {
ZipFile string `arg:"" required:"" type:"path" help:"the zip file to import"`
} `cmd:"" help:"import zip file into the database"`
Download struct{} `cmd:"" help:"download database from remote"`
Database string `type:"path" help:"the database file" env:"JUTGE_DATABASE"`
}
func (d *DatabaseCmd) Run(ctx *kong.Context, globals *Globals) error {
if d.Database == "" {
d.Database = filepath.Join(globals.WorkDir, "jutge.db")
}
db := database.NewJutgeDB(d.Database)
command := strings.SplitN(ctx.Command(), " ", 3)[1]
switch command {
case "dump":
return db.Print()
case "add":
return db.Add(d.Add.Code, d.Add.Title)
case "query":
title, err := db.Query(d.Query.Code);
if err != nil {
fmt.Println("Code not found in database")
return err
}
fmt.Println(title)
case "import":
return db.ImportZip(d.Import.ZipFile)
case "download":
return db.Download()
default:
return fmt.Errorf("unknown command: %s", command)
}
return nil
}
type NewCmd struct {
Code string `arg:"" required:"" help:"the code of problem to create"`
Extension string `help:"the extension of problem to create" default:"cc"`
}
func (n *NewCmd) Run(ctx *kong.Context, globals *Globals) error {
conf, err := jutgeConf(globals)
if err != nil {
return err
}
filename, err := commands.Jutge(conf).GetFilename(n.Code, n.Extension)
if err != nil {
return err
}
fmt.Println(filename)
_, err = os.Create(filename)
return err
}