Skip to content

Commit

Permalink
feat(boban): boban ejudge runs filter + more linters small refactor (#17
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Gornak40 authored Feb 21, 2024
1 parent ef7e210 commit b348a27
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 59 deletions.
8 changes: 4 additions & 4 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ linters:
enable-all: true
disable:
- gofumpt
- interfacer
- varcheck
- nosnakecase
- interfacer
Expand All @@ -16,9 +15,10 @@ linters:
- depguard
- wsl
- wrapcheck
- nlreturn
- goerr113
- exhaustruct
- godox
- varnamelen
- cyclop

linters-settings:
cyclop:
max-complexity: 15
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,33 @@ blanka -i 51013 -t 51000 -e

![blanka logo](https://algolymp.ru/static/img/blanka.png)

## boban
*Filter Ejudge runs.*

### Abount

Filter and print Ejudge runs IDs in specified contest.

### Flags
- `-i` - contest id (required)
- `-f` - filter expression (default: empty)
- `-c` - last runs count (default: 20)

### Config
- `ejudge.url`
- `ejudge.login`
- `ejudge.password`

### Examples
```bash
boban --help
boban -i 47106 -f "prob == 'A'" > runs.txt
boban -i 50014 -f "status == PR" -c 1000
boban -i 50014 -c 10000 2> /dev/null | wc -l
```

![boban logo](https://algolymp.ru/static/img/boban.png)

## casper
*Change Ejudge contest visibility by id.*

Expand Down
61 changes: 61 additions & 0 deletions cmd/boban/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package main

import (
"fmt"
"os"

"github.com/Gornak40/algolymp/config"
"github.com/Gornak40/algolymp/ejudge"
"github.com/akamensky/argparse"
"github.com/sirupsen/logrus"
)

const (
DefaultRunsCount = 20
)

func main() {
parser := argparse.NewParser("boban", "Filter Ejudge runs.")
cID := parser.Int("i", "cid", &argparse.Options{
Required: true,
Help: "Ejudge contest ID",
})
filter := parser.String("f", "filter", &argparse.Options{
Required: false,
Help: "Filter expression",
})
count := parser.Int("c", "count", &argparse.Options{
Required: false,
Help: "Last runs count",
Default: DefaultRunsCount,
})
if err := parser.Parse(os.Args); err != nil {
logrus.WithError(err).Fatal("bad arguments")
}

cfg := config.NewConfig()
ejClient := ejudge.NewEjudge(&cfg.Ejudge)

sid, err := ejClient.Login()
if err != nil {
logrus.WithError(err).Fatal("login failed")
}

csid, err := ejClient.MasterLogin(sid, *cID)
if err != nil {
logrus.WithError(err).Fatal("master login failed")
}

runs, err := ejClient.FilterRuns(csid, *filter, *count)
if err != nil {
logrus.WithError(err).Fatal("filter runs failed")
}
for _, run := range runs {
fmt.Println(run) //nolint:forbidigo // Basic functionality.
}
logrus.WithField("runs", len(runs)).Info("filter result")

if err := ejClient.Logout(sid); err != nil {
logrus.WithError(err).Fatal("logout failed")
}
}
6 changes: 5 additions & 1 deletion cmd/ejik/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ func main() {
logrus.WithError(err).Fatal("check failed")
}

if err := ejClient.ReloadConfig(sid, *cID); err != nil {
csid, err := ejClient.MasterLogin(sid, *cID)
if err != nil {
logrus.WithError(err).Fatal("master login failed")
}
if err := ejClient.ReloadConfig(csid); err != nil {
logrus.WithError(err).Fatal("reload config failed")
}

Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ func NewConfig() *Config {
if err := json.Unmarshal(data, &cfg); err != nil {
logrus.WithError(err).Fatal("failed to unmarshal config")
}

return &cfg
}
74 changes: 62 additions & 12 deletions ejudge/ejudge.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package ejudge

import (
"errors"
"fmt"
"net/http"
"net/http/cookiejar"
"net/url"
"regexp"
"strconv"

"github.com/PuerkitoBio/goquery"
Expand Down Expand Up @@ -32,6 +34,7 @@ type Ejudge struct {
func NewEjudge(cfg *Config) *Ejudge {
logrus.WithField("url", cfg.URL).Info("init ejudge engine")
jar, _ := cookiejar.New(nil)

return &Ejudge{
cfg: cfg,
client: &http.Client{
Expand All @@ -58,6 +61,7 @@ func (ej *Ejudge) postRequest(method string, params url.Values) (*http.Request,
if err != nil {
return nil, nil, err
}

return resp.Request, doc, nil
}

Expand All @@ -74,6 +78,7 @@ func (ej *Ejudge) Login() (string, error) {
return BadSID, err
}
logrus.WithField("SID", sid).Info("success login")

return sid, nil
}

Expand All @@ -87,16 +92,18 @@ func (ej *Ejudge) Logout(sid string) error {
return err
}
logrus.WithField("SID", sid).Info("success logout")

return nil
}

func (ej *Ejudge) Lock(sid string, cid int) error {
logrus.WithFields(logrus.Fields{"CID": cid, "SID": sid}).Info("lock contest for editing")
_, _, err := ej.postRequest("serve-control", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"action": {"276"},
})

return err
}

Expand All @@ -111,13 +118,14 @@ func (ej *Ejudge) Commit(sid string) error {
}
status := doc.Find("h2").First().Text()
logrus.WithFields(logrus.Fields{"SID": sid}).Infof("ejudge answer %q", status)

return nil
}

func (ej *Ejudge) CheckContest(sid string, cid int, verbose bool) error {
logrus.WithFields(logrus.Fields{"CID": cid, "SID": sid}).Info("check contest settings, wait please")
_, doc, err := ej.postRequest("serve-control", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"action": {"262"},
})
Expand All @@ -129,43 +137,82 @@ func (ej *Ejudge) CheckContest(sid string, cid int, verbose bool) error {
}
status := doc.Find("h2").First().Text()
logrus.WithFields(logrus.Fields{"CID": cid, "SID": sid}).Infof("ejudge answer %q", status)

return nil
}

func (ej *Ejudge) ReloadConfig(sid string, cid int) error {
func (ej *Ejudge) MasterLogin(sid string, cid int) (string, error) {
req, _, err := ej.postRequest("new-master", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"action": {"3"},
})
if err != nil {
return err
return "", err
}
csid := req.URL.Query().Get("SID")
if csid == "" {
return ErrParseMasterSID
return "", ErrParseMasterSID
}
logrus.WithFields(logrus.Fields{"CID": cid, "CSID": csid, "SID": sid}).Info("success master login")
_, _, err = ej.postRequest("new-master", url.Values{

return csid, nil
}

func (ej *Ejudge) FilterRuns(csid string, filter string, count int) ([]int, error) {
_, doc, err := ej.postRequest("new-master", url.Values{
"SID": {csid},
"filter_view": {"1"},
"filter_expr": {filter},
"filter_first_run": {"-1"},
"filter_last_run": {strconv.Itoa(-count)},
})
if err != nil {
return nil, err
}
ejErr := doc.Find("#container > pre")
if ejErr.Text() != "" {
return nil, errors.New(ejErr.Text())
}
res := doc.Find("#container > table:nth-child(18) > tbody > tr > td:nth-child(1)")
digits := regexp.MustCompile("[^0-9]+")
runsStr := res.Map(func(_ int, s *goquery.Selection) string {
return digits.ReplaceAllString(s.Text(), "")
})
runs := make([]int, 0, len(runsStr))
for _, s := range runsStr {
run, err := strconv.Atoi(s)
if err != nil {
return nil, err
}
runs = append(runs, run)
}

return runs, nil
}

func (ej *Ejudge) ReloadConfig(csid string) error {
_, _, err := ej.postRequest("new-master", url.Values{
"SID": {csid},
"action": {"62"},
})
if err != nil {
return err
}
logrus.WithFields(logrus.Fields{"CID": cid, "CSID": csid, "SID": sid}).Info("success reload config")
logrus.WithFields(logrus.Fields{"CSID": csid}).Info("success reload config")

return nil
}

func (ej *Ejudge) CreateContest(sid string, cid int, tid int) error {
logrus.WithFields(logrus.Fields{"CID": cid, "TID": tid, "SID": sid}).Info("create contest")
_, doc, err := ej.postRequest("serve-control", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"num_mode": {"1"},
"action": {"259"},
"templ_mode": {"1"},
"templ_id": {strconv.FormatInt(int64(tid), 10)},
"templ_id": {strconv.Itoa(tid)},
})
if err != nil {
return err
Expand All @@ -175,25 +222,28 @@ func (ej *Ejudge) CreateContest(sid string, cid int, tid int) error {
status = "OK"
}
logrus.WithFields(logrus.Fields{"CID": cid, "TID": tid, "SID": sid}).Infof("ejudge answer %q", status)

return nil
}

func (ej *Ejudge) MakeInvisible(sid string, cid int) error {
logrus.WithFields(logrus.Fields{"CID": cid, "SID": sid}).Info("make invisible")
_, _, err := ej.postRequest("serve-control", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"action": {"6"},
})

return err
}

func (ej *Ejudge) MakeVisible(sid string, cid int) error {
logrus.WithFields(logrus.Fields{"CID": cid, "SID": sid}).Info("make visible")
_, _, err := ej.postRequest("serve-control", url.Values{
"contest_id": {strconv.FormatInt(int64(cid), 10)},
"contest_id": {strconv.Itoa(cid)},
"SID": {sid},
"action": {"7"},
})

return err
}
Binary file added logos/boban.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified logos/casper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b348a27

Please sign in to comment.