From 8b676304fcd8be344139ff229fcb1d1150cbff4f Mon Sep 17 00:00:00 2001 From: Alexander Gornak Date: Wed, 28 Feb 2024 15:16:47 +0300 Subject: [PATCH] chore: more wooda mods (#23) * chore: more wooda mods * chore: checker + interactor + solutions + sample --- README.md | 28 ++++++++++++---- cmd/wooda/main.go | 7 ++++ polygon/api.go | 74 +++++++++++++++++++++++++++++++++++++---- polygon/requests.go | 70 +++++++++++++++++++++++++++++++++++++++ polygon/scoring.go | 3 +- polygon/wooda/wooda.go | 75 ++++++++++++++++++++++++++++++++++++++---- 6 files changed, 237 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2f8a22d..ad7fd8d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # algolymp -*A collection of useful CLI tools for managing Polygon and Ejudge.* +*Awesome collection of useful CLI tools for managing Polygon and Ejudge.* ## Workflow @@ -15,6 +15,8 @@ | [wooda](#wooda) | glob problem files upload | | 🦍 | 🧑‍💻 | | ⚙️ | move json config to ini | | | 🧑‍💻 | | 👻 | list/commit problems | | 🦍 | 🤔 | +| 👻 | set good random group scores | | 🦍 | 🤔 | +| 👻 | algolymp config manager | | | 🤔 | | 👻 | download/upload package | | 🦍 | 🤔 | | 👻 | import polygon problem | 🦍 | 🦍 | 🤔 | | 👻 | autogen static problem | 🦍 | | 🤔 | @@ -281,17 +283,24 @@ valeria -i 318882 | bat -l tex Match all files in directory with glob pattern. Upload recognized files to Polygon. -Supported modes: +#### Supported modes -- `test` -- `tags` +- `t` - test +- `tags` - tags (each tag is on a new line) +- `v` - validator +- `c` - checker +- `i` - interactor +- `ma` - main solution +- `ok` - correct solution +- `rj` - incorrect solution +- `s` - sample ### Flags - `-i` - problem id (required) - `-m` - uploading mode (required) - `-g` - problem files glob (required) -You should know your shell and probably pass `-g ""`, not `-g ` +You should know your shell and probably use `-g ""`, not `-g ` ### Config - `polygon.url` @@ -302,8 +311,15 @@ You should know your shell and probably pass `-g ""`, not `-g ` ```bash wooda --help -wooda -i 337320 -m test -g "tests/*[^.a]" +wooda -i 337320 -m t -g "tests/*[^.a]" # exclude output wooda -i 337320 -m tags -g tags +wooda -i 337320 -m v -g files/val*.cpp +wooda -i 337320 -m c -g check.cpp +wooda -i 337320 -m i -g interactor.cpp +wooda -i 337320 -m ma -g solutions/main.cpp # Main solution +wooda -i 337320 -m ok -g solutions/sol_apachee.cpp # OK solution +wooda -i 337320 -m rj -g solutions/brute.py # TL solution +wooda -i 337320 -m s -g "statements/russian/example.[0-9][0-9]" ``` ![wooda logo](https://algolymp.ru/static/img/wooda.png) diff --git a/cmd/wooda/main.go b/cmd/wooda/main.go index 960b858..b7f5bb8 100644 --- a/cmd/wooda/main.go +++ b/cmd/wooda/main.go @@ -15,6 +15,13 @@ func main() { woodaModes := []string{ wooda.ModeTest, wooda.ModeTags, + wooda.ModeValidator, + wooda.ModeChecker, + wooda.ModeInteractor, + wooda.ModeSolutionMain, + wooda.ModeSolutionCorrect, + wooda.ModeSolutionIncorrect, + wooda.ModeSample, } parser := argparse.NewParser("wooda", "Upload problem files filtered by glob to Polygon.") diff --git a/polygon/api.go b/polygon/api.go index 904aa3d..861939e 100644 --- a/polygon/api.go +++ b/polygon/api.go @@ -23,6 +23,22 @@ const ( defaultTestset = "tests" ) +type SolutionTag string + +const ( + TagMain SolutionTag = "MA" + TagCorrect SolutionTag = "OK" + TagIncorrect SolutionTag = "RJ" +) + +type FileType string + +const ( + TypeSource FileType = "source" + TypeResource FileType = "resource" + TypeAUX FileType = "aux" +) + var ( ErrBadPolygonStatus = errors.New("bad polygon status") ErrInvalidMethod = errors.New("invalid method") @@ -176,13 +192,8 @@ func (p *Polygon) EnablePoints(pID int) error { return err } -func (p *Polygon) SaveResource(pID int, name, content string) error { - link, params := p.buildURL("problem.saveFile", url.Values{ - "problemId": []string{strconv.Itoa(pID)}, - "type": []string{"resource"}, - "name": []string{name}, - "file": []string{content}, - }) +func (p *Polygon) SaveFile(fReq FileRequest) error { + link, params := p.buildURL("problem.saveFile", url.Values(fReq)) _, err := p.makeQuery(http.MethodPost, link, params) return err @@ -204,3 +215,52 @@ func (p *Polygon) SaveTags(pID int, tags string) error { return err } + +func (p *Polygon) SetValidator(pID int, validator string) error { + link, params := p.buildURL("problem.setValidator", url.Values{ + "problemId": []string{strconv.Itoa(pID)}, + "validator": []string{validator}, + }) + _, err := p.makeQuery(http.MethodPost, link, params) + + return err +} + +func (p *Polygon) SetChecker(pID int, checker string) error { + link, params := p.buildURL("problem.setChecker", url.Values{ + "problemId": []string{strconv.Itoa(pID)}, + "checker": []string{checker}, + }) + _, err := p.makeQuery(http.MethodPost, link, params) + + return err +} + +func (p *Polygon) UpdateInfo(pr ProblemRequest) error { + link, params := p.buildURL("problem.updateInfo", url.Values(pr)) + _, err := p.makeQuery(http.MethodPost, link, params) + + return err +} + +func (p *Polygon) SetInteractor(pID int, interactor string) error { + link, params := p.buildURL("problem.setInteractor", url.Values{ + "problemId": []string{strconv.Itoa(pID)}, + "interactor": []string{interactor}, + }) + _, err := p.makeQuery(http.MethodPost, link, params) + + return err +} + +func (p *Polygon) SaveSolution(pID int, name, data string, tag SolutionTag) error { + link, params := p.buildURL("problem.saveSolution", url.Values{ + "problemId": []string{strconv.Itoa(pID)}, + "name": []string{name}, + "file": []string{data}, + "tag": []string{string(tag)}, + }) + _, err := p.makeQuery(http.MethodPost, link, params) + + return err +} diff --git a/polygon/requests.go b/polygon/requests.go index 107bc6b..55b9f28 100644 --- a/polygon/requests.go +++ b/polygon/requests.go @@ -39,3 +39,73 @@ func (tr TestRequest) Description(description string) TestRequest { return tr } + +func (tr TestRequest) UseInStatements(f bool) TestRequest { + tr["testUseInStatements"] = []string{strconv.FormatBool(f)} + + return tr +} + +type ProblemRequest url.Values + +func NewProblemRequest(pID int) ProblemRequest { + return ProblemRequest{ + "problemId": []string{strconv.Itoa(pID)}, + } +} + +func (pr ProblemRequest) InputFile(name string) ProblemRequest { + pr["inputFile"] = []string{name} + + return pr +} + +func (pr ProblemRequest) OutputFile(name string) ProblemRequest { + pr["outputFile"] = []string{name} + + return pr +} + +func (pr ProblemRequest) Interactive(f bool) ProblemRequest { + pr["interactive"] = []string{strconv.FormatBool(f)} + + return pr +} + +func (pr ProblemRequest) TimeLimit(tl int) ProblemRequest { + pr["timeLimit"] = []string{strconv.Itoa(tl)} + + return pr +} + +func (pr ProblemRequest) MemoryLimit(ml int) ProblemRequest { + pr["memoryLimit"] = []string{strconv.Itoa(ml)} + + return pr +} + +type FileRequest url.Values + +func NewFileRequest(pID int, typ FileType, name, file string) FileRequest { + return FileRequest{ + "problemId": []string{strconv.Itoa(pID)}, + "type": []string{string(typ)}, + "name": []string{name}, + "file": []string{file}, + } +} + +// TODO: fix it. +func (fr FileRequest) CheckExisting(f bool) FileRequest { + fr["checkExisting"] = []string{strconv.FormatBool(f)} + + return fr +} + +func (fr FileRequest) SourceType(typ string) FileRequest { + fr["sourceType"] = []string{typ} + + return fr +} + +// TODO: add other options diff --git a/polygon/scoring.go b/polygon/scoring.go index e0be010..9ea69ee 100644 --- a/polygon/scoring.go +++ b/polygon/scoring.go @@ -118,7 +118,8 @@ func (p *Polygon) InformaticsValuer(pID int, verbose bool) error { if verbose { logrus.Info("valuer.cfg\n" + valuer) } - if err := p.SaveResource(pID, "valuer.cfg", valuer); err != nil { + fr := NewFileRequest(pID, TypeResource, "valuer.cfg", valuer) + if err := p.SaveFile(fr); err != nil { return err } diff --git a/polygon/wooda/wooda.go b/polygon/wooda/wooda.go index af9ec77..572991f 100644 --- a/polygon/wooda/wooda.go +++ b/polygon/wooda/wooda.go @@ -12,8 +12,15 @@ import ( ) const ( - ModeTest = "test" - ModeTags = "tags" + ModeTest = "t" + ModeTags = "tags" + ModeValidator = "v" + ModeChecker = "c" + ModeInteractor = "i" + ModeSolutionMain = "ma" + ModeSolutionCorrect = "ok" + ModeSolutionIncorrect = "rj" + ModeSample = "s" ) var ( @@ -42,20 +49,36 @@ func (w *Wooda) Resolve(path string) error { if err != nil { return err } + file := string(data) switch w.mode { case ModeTest: - return w.resolveTest(path, string(data)) + return w.resolveTest(path, file, false) case ModeTags: - return w.resolveTags(string(data)) + return w.resolveTags(file) + case ModeValidator: + return w.resolveValidator(path, file) + case ModeChecker: + return w.resolveChecker(path, file) + case ModeInteractor: + return w.resolveInteractor(path, file) + case ModeSolutionMain: + return w.resolveSolution(path, file, polygon.TagMain) + case ModeSolutionCorrect: + return w.resolveSolution(path, file, polygon.TagCorrect) + case ModeSolutionIncorrect: + return w.resolveSolution(path, file, polygon.TagIncorrect) + case ModeSample: + return w.resolveTest(path, file, true) default: return fmt.Errorf("%w: %s", ErrUnknownMode, w.mode) } } -func (w *Wooda) resolveTest(path, data string) error { +func (w *Wooda) resolveTest(path, data string, sample bool) error { tr := polygon.NewTestRequest(w.pID, w.testIndex). Input(data). - Description(fmt.Sprintf("File \"%s\"", filepath.Base(path))) + Description(fmt.Sprintf("File \"%s\"", filepath.Base(path))). + UseInStatements(sample) if err := w.client.SaveTest(tr); err != nil { return err } @@ -69,3 +92,43 @@ func (w *Wooda) resolveTags(data string) error { return w.client.SaveTags(w.pID, tags) } + +func (w *Wooda) resolveValidator(path, data string) error { + name := filepath.Base(path) + fr := polygon.NewFileRequest(w.pID, polygon.TypeSource, name, data) + if err := w.client.SaveFile(fr); err != nil { + return err + } + + return w.client.SetValidator(w.pID, name) +} + +// TODO: support standard checkers. +func (w *Wooda) resolveChecker(path, data string) error { + name := filepath.Base(path) + fr := polygon.NewFileRequest(w.pID, polygon.TypeSource, name, data) + if err := w.client.SaveFile(fr); err != nil { + return err + } + + return w.client.SetChecker(w.pID, name) +} + +func (w *Wooda) resolveInteractor(path, data string) error { + pr := polygon.NewProblemRequest(w.pID).Interactive(true) + if err := w.client.UpdateInfo(pr); err != nil { + return err + } + + name := filepath.Base(path) + fr := polygon.NewFileRequest(w.pID, polygon.TypeSource, name, data) + if err := w.client.SaveFile(fr); err != nil { + return err + } + + return w.client.SetInteractor(w.pID, name) +} + +func (w *Wooda) resolveSolution(path, data string, tag polygon.SolutionTag) error { + return w.client.SaveSolution(w.pID, filepath.Base(path), data, tag) +}