Skip to content

Commit

Permalink
chore(gibon): add groups mark up method
Browse files Browse the repository at this point in the history
  • Loading branch information
Gornak40 committed Feb 22, 2025
1 parent bc2ccb8 commit 1527a18
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 60 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ The method `contest` is useful when using [scalp](#scalp) or other [gibon](#gibo
- `contest` - print problem ids in specified contest
- `commit` - commit changes with empty message without email notification
- `download` - download the latest (problem revision) linux package
- `groups` - mark up test groups from `stdin` (CSV format) `{group},{test1}-{testn}`
- `package` - build full package with verification
- `update` - update working copy

Expand All @@ -339,9 +340,11 @@ gibon --help
gibon -i 42619 -m contest
gibon -i 363802 -m commit
gibon -i 363802 -m download
gibon -i 363802 -m groups
gibon -i 363802 -m package
gibon -i 363802 -m update
for i in $(gibon -i 42619 -m contest); do gibon -i $i -m commit && gibon -i $i -m package; done
echo "0,1-3\n1,4-10\n2,11-18" | gibon -i 363802 -m groups
```

![gibon logo](https://algolymp.ru/static/img/gibon.png)
Expand Down
1 change: 1 addition & 0 deletions cmd/gibon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func main() {
gibon.ModeContest,
gibon.ModeCommit,
gibon.ModeDownload,
gibon.ModeGroups,
gibon.ModePackage,
gibon.ModeUpdate,
}
Expand Down
96 changes: 56 additions & 40 deletions polygon/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,22 +168,22 @@ func (p *Polygon) skipEscape(params url.Values) string {
func (p *Polygon) buildURL(method string, params url.Values) (string, url.Values) {
url, _ := url.JoinPath(p.cfg.URL, "api", method)

params["apiKey"] = []string{p.cfg.APIKey}
params["time"] = []string{strconv.FormatInt(time.Now().Unix(), 10)}
params.Set("apiKey", p.cfg.APIKey)
params.Set("time", strconv.FormatInt(time.Now().Unix(), 10))
sig := fmt.Sprintf("%s/%s?%s#%s", sixSecretSymbols, method, p.skipEscape(params), p.cfg.APISecret)

b := sha512.Sum512([]byte(sig))
hsh := hex.EncodeToString(b[:])
params["apiSig"] = []string{sixSecretSymbols + hsh}
params.Set("apiSig", sixSecretSymbols+hsh)

return url, params
}

func (p *Polygon) BuildPackage(pID int, full, verify bool) error {
link, params := p.buildURL("problem.buildPackage", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"full": []string{strconv.FormatBool(full)},
"verify": []string{strconv.FormatBool(verify)},
"problemId": {strconv.Itoa(pID)},
"full": {strconv.FormatBool(full)},
"verify": {strconv.FormatBool(verify)},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -193,7 +193,7 @@ func (p *Polygon) BuildPackage(pID int, full, verify bool) error {
// Problem Idx (A, B, C) -> Problem.
func (p *Polygon) ContestProblems(pID int) (map[string]ProblemAnswer, error) {
link, params := p.buildURL("contest.problems", url.Values{
"contestId": []string{strconv.Itoa(pID)},
"contestId": {strconv.Itoa(pID)},
})
ansC, err := p.makeQuery(http.MethodGet, link, params)
if err != nil {
Expand All @@ -209,9 +209,9 @@ func (p *Polygon) ContestProblems(pID int) (map[string]ProblemAnswer, error) {

func (p *Polygon) Commit(pID int, minor bool, message string) error {
link, params := p.buildURL("problem.commitChanges", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"minorChanges": []string{strconv.FormatBool(minor)},
"message": []string{message},
"problemId": {strconv.Itoa(pID)},
"minorChanges": {strconv.FormatBool(minor)},
"message": {message},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -220,7 +220,7 @@ func (p *Polygon) Commit(pID int, minor bool, message string) error {

func (p *Polygon) UpdateWorkingCopy(pid int) error {
link, params := p.buildURL("problem.updateWorkingCopy", url.Values{
"problemId": []string{strconv.Itoa(pid)},
"problemId": {strconv.Itoa(pid)},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -229,7 +229,7 @@ func (p *Polygon) UpdateWorkingCopy(pid int) error {

func (p *Polygon) GetPackages(pID int) ([]PackageAnswer, error) {
link, params := p.buildURL("problem.packages", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"problemId": {strconv.Itoa(pID)},
})
ansP, err := p.makeQuery(http.MethodGet, link, params)
if err != nil {
Expand All @@ -245,8 +245,8 @@ func (p *Polygon) GetPackages(pID int) ([]PackageAnswer, error) {

func (p *Polygon) GetGroups(pID int) ([]GroupAnswer, error) {
link, params := p.buildURL("problem.viewTestGroup", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"testset": []string{defaultTestset},
"problemId": {strconv.Itoa(pID)},
"testset": {defaultTestset},
})
ansG, err := p.makeQuery(http.MethodGet, link, params)
if err != nil {
Expand All @@ -262,7 +262,7 @@ func (p *Polygon) GetGroups(pID int) ([]GroupAnswer, error) {

func (p *Polygon) GetProblem(pID int) (*ProblemAnswer, error) {
link, params := p.buildURL("problems.list", url.Values{
"id": []string{strconv.Itoa(pID)},
"id": {strconv.Itoa(pID)},
})
ansP, err := p.makeQuery(http.MethodGet, link, params)
if err != nil {
Expand All @@ -281,9 +281,9 @@ func (p *Polygon) GetProblem(pID int) (*ProblemAnswer, error) {

func (p *Polygon) GetTests(pID int) ([]TestAnswer, error) {
link, params := p.buildURL("problem.tests", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"testset": []string{defaultTestset},
"noInputs": []string{"true"},
"problemId": {strconv.Itoa(pID)},
"testset": {defaultTestset},
"noInputs": {"true"},
})
ansT, err := p.makeQuery(http.MethodGet, link, params)
if err != nil {
Expand All @@ -299,9 +299,9 @@ func (p *Polygon) GetTests(pID int) ([]TestAnswer, error) {

func (p *Polygon) DownloadPackage(pID, packID int, packType string) ([]byte, error) {
link, params := p.buildURL("problem.package", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"packageId": []string{strconv.Itoa(packID)},
"type": []string{packType},
"problemId": {strconv.Itoa(pID)},
"packageId": {strconv.Itoa(packID)},
"type": {packType},
})
req, err := buildRequest(http.MethodPost, link, params)
if err != nil {
Expand All @@ -318,9 +318,9 @@ func (p *Polygon) DownloadPackage(pID, packID int, packType string) ([]byte, err

func (p *Polygon) EnableGroups(pID int) error {
link, params := p.buildURL("problem.enableGroups", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"testset": []string{defaultTestset},
"enable": []string{"true"},
"problemId": {strconv.Itoa(pID)},
"testset": {defaultTestset},
"enable": {"true"},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -329,8 +329,24 @@ func (p *Polygon) EnableGroups(pID int) error {

func (p *Polygon) EnablePoints(pID int) error {
link, params := p.buildURL("problem.enablePoints", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"enable": []string{"true"},
"problemId": {strconv.Itoa(pID)},
"enable": {"true"},
})
_, err := p.makeQuery(http.MethodPost, link, params)

return err
}

func (p *Polygon) SetTestGroup(pID int, group string, tests []int) error {
st := make([]string, 0, len(tests))
for _, v := range tests {
st = append(st, strconv.Itoa(v))
}
link, params := p.buildURL("problem.setTestGroup", url.Values{
"problemId": {strconv.Itoa(pID)},
"testset": {defaultTestset},
"testGroup": {group},
"testIndices": {strings.Join(st, ",")},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -353,8 +369,8 @@ func (p *Polygon) SaveTest(tReq TestRequest) error {

func (p *Polygon) SaveTags(pID int, tags string) error {
link, params := p.buildURL("problem.saveTags", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"tags": []string{tags},
"problemId": {strconv.Itoa(pID)},
"tags": {tags},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -363,8 +379,8 @@ func (p *Polygon) SaveTags(pID int, tags string) error {

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},
"problemId": {strconv.Itoa(pID)},
"validator": {validator},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -373,8 +389,8 @@ func (p *Polygon) SetValidator(pID int, validator string) error {

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},
"problemId": {strconv.Itoa(pID)},
"checker": {checker},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -390,8 +406,8 @@ func (p *Polygon) UpdateInfo(pr ProblemRequest) error {

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},
"problemId": {strconv.Itoa(pID)},
"interactor": {interactor},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand All @@ -400,9 +416,9 @@ func (p *Polygon) SetInteractor(pID int, interactor string) error {

func (p *Polygon) SaveScript(pID int, testset, source string) error {
link, params := p.buildURL("problem.saveScript", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"testset": []string{testset},
"source": []string{source},
"problemId": {strconv.Itoa(pID)},
"testset": {testset},
"source": {source},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand Down Expand Up @@ -446,9 +462,9 @@ func (p *Polygon) SaveTestGroup(tgr TestGroupRequest) error {

func (p *Polygon) SaveStatementResource(pID int, name, data string) error {
link, params := p.buildURL("problem.saveStatementResource", url.Values{
"problemId": []string{strconv.Itoa(pID)},
"name": []string{name},
"file": []string{data},
"problemId": {strconv.Itoa(pID)},
"name": {name},
"file": {data},
})
_, err := p.makeQuery(http.MethodPost, link, params)

Expand Down
46 changes: 46 additions & 0 deletions polygon/gibon/gibon.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package gibon

import (
"encoding/csv"
"errors"
"fmt"
"io"
"os"
"slices"

Expand All @@ -14,6 +16,7 @@ const (
ModeContest = "contest"
ModeCommit = "commit"
ModeDownload = "download"
ModeGroups = "groups"
ModePackage = "package"
ModeUpdate = "update"
)
Expand All @@ -23,6 +26,7 @@ const packageMode = 0666
var (
ErrNoPackage = errors.New("no suitable package")
ErrUnknownMethod = errors.New("unknown method")
ErrBadGroupDesc = errors.New("bad group description")
)

type Gibon struct {
Expand Down Expand Up @@ -84,6 +88,46 @@ func (g *Gibon) listProblems() error {
return nil
}

func (g *Gibon) markGroups() error {
if err := g.client.EnableGroups(g.pID); err != nil {
return err
}
if err := g.client.EnablePoints(g.pID); err != nil {
return err
}
r := csv.NewReader(os.Stdin)
logrus.Info("waiting for TODO input...")
for {
ln, err := r.Read()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
if len(ln) != 2 { //nolint:mnd // line length
return fmt.Errorf("%w: invalid line length", ErrBadGroupDesc)
}
var l, r int
if _, err := fmt.Sscanf(ln[1], "%d-%d", &l, &r); err != nil {
return err
}
if r < l {
return fmt.Errorf("%w: r < l", ErrBadGroupDesc)
}
logrus.WithFields(logrus.Fields{"group": ln[0], "l": l, "r": r}).Info("set group")
ids := make([]int, 0, r-l+1)
for i := l; i <= r; i++ {
ids = append(ids, i)
}
if err := g.client.SetTestGroup(g.pID, ln[0], ids); err != nil {
return err
}
}

return nil
}

func (g *Gibon) Resolve(method string) error {
switch method {
case ModeContest:
Expand All @@ -96,6 +140,8 @@ func (g *Gibon) Resolve(method string) error {
return g.client.BuildPackage(g.pID, true, true)
case ModeUpdate:
return g.client.UpdateWorkingCopy(g.pID)
case ModeGroups:
return g.markGroups()
}

return fmt.Errorf("%w: %s", ErrUnknownMethod, method)
Expand Down
Loading

0 comments on commit 1527a18

Please sign in to comment.