Skip to content

Commit

Permalink
Добавлены раунды и регулирование количества логов через флаги
Browse files Browse the repository at this point in the history
  • Loading branch information
RobolabGs2 committed Oct 9, 2020
1 parent 377b6c9 commit 942f629
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 19 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@ CLI утилита для проведения соревнований межд
+ `stdin` принимает ходы соперника
+ `stdout` пишет свой ход
+ `stderr` пишет всё остальное - логи, информацию для человека, состояние доски
+ `exit code`: победа-`0`, поражение-`1`, ничья-`2`

# Использование
`botctl path/to/mybot1.exe path/to/mybot2.exe`
```
Usage:
botctl [flags] path/to/mybot1.exe path/to/mybot2.exe
-r int
Количество раундов (default 1)
-v int
0 - логи ботов не выводятся, 1 - выводятся логи первого, 2 - обоих ботов (default 1)
```

Порядок ботов влияет на очерёдность хода, в результате будет выводиться `stderr` первого бота
Порядок ботов влияет на вывод: в `stdout` будет писаться `stderr` первого бота, в `stderr` - второго.

По окончанию всех раундов будет выведен суммарный счёт. При смене раунда цвета меняются.
107 changes: 90 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,107 @@
package main

import (
"errors"
"flag"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
)

func main() {
if (len(os.Args)) != 3 {
log.Fatalf("bot-connector [bot1].exe [bot2].exe")
}
bot1ExeName := os.Args[1]
bot2ExeName := os.Args[2]
bot1, bot2 := MakeCmd(bot1ExeName, "0"), MakeCmd(bot2ExeName, "1")
bot1.Stdout, _ = bot2.StdinPipe()
bot2.Stdout, _ = bot1.StdinPipe()
bot1.Stderr = os.Stdout
logAndExitOnError(bot1.Start(), bot1ExeName)
logAndExitOnError(bot2.Start(), bot2ExeName)
logAndExitOnError(bot1.Wait(), bot1ExeName)
logAndExitOnError(bot2.Wait(), bot2ExeName)
rounds := flag.Int("r", 1, "Количество раундов")
verbosity := flag.Int("v", 1, "0 - логи ботов не выводятся, 1 - выводятся логи первого, 2 - обоих ботов")
flag.Parse()
if flag.NArg() != 2 {
_, _ = fmt.Fprintln(os.Stderr, "Usage:\n botctl [flags] path/to/mybot1.exe path/to/mybot2.exe")
flag.PrintDefaults()
return
}
bot1ExeName := filepath.Clean(flag.Arg(0))
bot2ExeName := filepath.Clean(flag.Arg(1))
checkFile(bot1ExeName)
checkFile(bot2ExeName)
totalScore1, totalScore2 := GameResult(0), GameResult(0)
for i := 0; i < *rounds; i++ {
bot1, bot2 := MakeCmd(bot1ExeName, i%2), MakeCmd(bot2ExeName, 1-i%2)
bot1.Stdout, _ = bot2.StdinPipe()
bot2.Stdout, _ = bot1.StdinPipe()
switch *verbosity {
case 2:
bot2.Stderr = os.Stderr
fallthrough
case 1:
bot1.Stderr = os.Stdout
}
log.Println("Раунд:", i)
logAndExitOnError(bot1.Start(), bot1ExeName)
logAndExitOnErrorAndAction(bot2.Start(), bot2ExeName, bot1.Process.Kill)
score1, err := SummarizeGame(bot1.Wait())
if err != nil {
log.Println(bot1ExeName, ": ", err)
}
score2, err := SummarizeGame(bot2.Wait())
if err != nil {
log.Println(bot2ExeName, ": ", err)
}
if score1+score2 != Draw {
log.Println("Кто-то из ботов мухлюет")
}
totalScore1 += score1
totalScore2 += score2
log.Println(score1, ":", score2)
}
if *rounds > 1 {
log.Println("Итого:")
log.Println(totalScore1, ":", totalScore2)
}
}

func checkFile(filename string) {
if _, err := os.Stat(filename); err != nil {
log.Fatalln("Проблемы с ", filename, ":", err)
}
}

func logAndExitOnError(err error, bot1ExeName string) {
func logAndExitOnError(err error, botExeName string) {
if err != nil {
log.Fatalln(botExeName, err)
}
}
func logAndExitOnErrorAndAction(err error, botExeName string, action func() error) {
if err != nil {
log.Fatalln(bot1ExeName, err)
_ = action()
log.Fatalln(botExeName, err)
}
}

type GameResult int

const (
Win GameResult = 1
Lose GameResult = -1
Draw GameResult = 0
)

func SummarizeGame(err error) (GameResult, error) {
if err == nil {
return Win, nil
}
if exit := new(exec.ExitError); errors.As(err, &exit) {
switch exit.ExitCode() {
case 1:
return Lose, nil
case 2:
return Draw, nil
}
}
return 0, err
}

func MakeCmd(botExeName string, order string) *exec.Cmd {
func MakeCmd(botExeName string, order int) *exec.Cmd {
// Платформозависимо - запускаем с помощью cmd
return exec.Command("cmd", "/C", botExeName, order)
return exec.Command("cmd", "/C", botExeName, strconv.Itoa(order))
}

0 comments on commit 942f629

Please sign in to comment.