From cd0415525715ec641f56840cb00c7068f6ea65ea Mon Sep 17 00:00:00 2001 From: Hamcha Date: Wed, 26 Jun 2019 12:56:02 +0200 Subject: [PATCH] Add bot and session primitives --- draftbot/bot.go | 19 ----------- draftbot/bot/bot.go | 37 ++++++++++++++++++++ draftbot/cube.go | 80 +++++++++++++++++++++++++++++++++++++++++++ draftbot/draftbot.go | 30 ++++++++++++++++ draftbot/go.mod | 2 +- draftbot/go.sum | 4 +-- draftbot/session.go | 81 +++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 230 insertions(+), 23 deletions(-) delete mode 100644 draftbot/bot.go create mode 100644 draftbot/bot/bot.go create mode 100644 draftbot/cube.go create mode 100644 draftbot/draftbot.go diff --git a/draftbot/bot.go b/draftbot/bot.go deleted file mode 100644 index a2bd43e..0000000 --- a/draftbot/bot.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - room "git.fromouter.space/mcg/cardgage/room/api" -) - -type draftBot struct { - Sessions map[string]session -} - -func newDraftBot() *draftBot { - return &draftBot{ - Sessions: make(map[string]session), - } -} - -func (d *draftBot) onMessage(msg room.ServerMessage) { - -} diff --git a/draftbot/bot/bot.go b/draftbot/bot/bot.go new file mode 100644 index 0000000..a64f6b8 --- /dev/null +++ b/draftbot/bot/bot.go @@ -0,0 +1,37 @@ +package bot + +import ( + "math/rand" + + "git.fromouter.space/mcg/draft" +) + +// Bot implements a bot for filling spots in draft pods +type Bot struct { + player *draft.Player + + // Currently unused, the bot just picks at random. + // In the future, these fields will be used for having the bot try to assemble + // a sort-of playable deck. The actual deck doesn't matter, just the fact + // that their picks make some sort of sense. + color1 string + color2 string + entryCount int + friendCount int + otherCount int +} + +// MakeBot returns a bot for a given pod spot +func MakeBot(player *draft.Player) *Bot { + bot := &Bot{ + player: player, + } + return bot +} + +// PickNext makes the bot pick a card from his pack +func (b *Bot) PickNext() { + // For now, just pick a card at random + cardid := rand.Intn(len(b.player.CurrentPack)) + b.player.Pick(b.player.CurrentPack[cardid]) +} diff --git a/draftbot/cube.go b/draftbot/cube.go new file mode 100644 index 0000000..8738aa0 --- /dev/null +++ b/draftbot/cube.go @@ -0,0 +1,80 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "strings" + + "git.fromouter.space/mcg/draft" + "git.fromouter.space/mcg/draft/mlp" +) + +func loadCube(cubeURL string) ([]draft.Card, error) { + // Fetch document + resp, err := http.Get(cubeURL) + if err != nil { + return nil, err + } + + respBytes, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return nil, err + } + + // Each line is a card ID + cardids := strings.Split(string(respBytes), "\n") + cards := make([]draft.Card, 0) + // Convert to draft.Card + for _, cardid := range cardids { + cardid := strings.TrimSpace(cardid) + if len(cardid) < 1 { + // Skip empty lines + continue + } + cards = append(cards, draft.Card{ID: cardid}) + } + return cards, nil +} + +// I8PCubeConfig is an external JSON doc with the I8PCube pack seeding schema and card list +type I8PCubeConfig struct { + Schema mlp.I8PSchema + Cards map[mlp.I8PType][]string +} + +// ToCube creates a I8PCube from the config +func (cfg *I8PCubeConfig) ToCube() (*mlp.I8PCube, error) { + // Load cards from given list + var err error + pool := make(mlp.I8PPool) + for typ, cardids := range cfg.Cards { + pool[typ], err = mlp.LoadCardList(cardids, true) + if err != nil { + return nil, err + } + } + + // Make cube and return it + return mlp.MakeI8PCube(pool, cfg.Schema), nil +} + +func loadI8PCube(cubeURL string) (*mlp.I8PCube, error) { + // Fetch document + resp, err := http.Get(cubeURL) + if err != nil { + return nil, err + } + + // Deserialize response to JSON object + var cubeconf I8PCubeConfig + err = json.NewDecoder(resp.Body).Decode(&cubeconf) + resp.Body.Close() + if err != nil { + return nil, err + } + + // Create cube from config + return cubeconf.ToCube() +} diff --git a/draftbot/draftbot.go b/draftbot/draftbot.go new file mode 100644 index 0000000..864c0e6 --- /dev/null +++ b/draftbot/draftbot.go @@ -0,0 +1,30 @@ +package main + +import ( + room "git.fromouter.space/mcg/cardgage/room/api" +) + +type draftBot struct { + Sessions map[string]session +} + +func newDraftBot() *draftBot { + return &draftBot{ + Sessions: make(map[string]session), + } +} + +func (d *draftBot) onMessage(msg room.ServerMessage) { + switch msg.Type { + case room.MsgMessage: + logger.Log("event", "message", + "roomid", msg.RoomID, + "from", msg.Message.From, + "to", msg.Message.To, + "content", msg.Message.Message) + case room.MsgEvent: + logger.Log("event", "event", + "roomid", msg.RoomID, + "content", msg.Event.Message) + } +} diff --git a/draftbot/go.mod b/draftbot/go.mod index fa9acac..57d3f28 100644 --- a/draftbot/go.mod +++ b/draftbot/go.mod @@ -5,6 +5,6 @@ go 1.12 require ( git.fromouter.space/Artificiale/moa v0.0.1-p2 git.fromouter.space/mcg/cardgage v0.0.1-p2 - git.fromouter.space/mcg/draft v0.0.0-20190617210125-5e49b051369f + git.fromouter.space/mcg/draft v0.0.2 github.com/go-kit/kit v0.8.0 ) diff --git a/draftbot/go.sum b/draftbot/go.sum index c198232..4637b78 100644 --- a/draftbot/go.sum +++ b/draftbot/go.sum @@ -3,8 +3,8 @@ git.fromouter.space/Artificiale/moa v0.0.1-p2 h1:KhoRQeYCFIpHZEucrXz142O5zfSsyEx git.fromouter.space/Artificiale/moa v0.0.1-p2/go.mod h1:dHYul6vVMwDCzre18AFs6NmI22yeI7AE0iQC1jFEQi0= git.fromouter.space/mcg/cardgage v0.0.1-p2 h1:u65ofEmtDHHQ8nbai97DW9kcrYa4x0I3NHv2oXhw8dI= git.fromouter.space/mcg/cardgage v0.0.1-p2/go.mod h1:vCmJ9HRdRGSWg2YQW9oNG7geYACdgWYmzL+zZdrsYhQ= -git.fromouter.space/mcg/draft v0.0.0-20190617210125-5e49b051369f h1:aw1RbRQnWsWYN0W3BL8u0xqkdeX1j7xnwan+du5UqHA= -git.fromouter.space/mcg/draft v0.0.0-20190617210125-5e49b051369f/go.mod h1:QQmDm9FgAZL3b2/pIDd4Eo608SxMiCQQe5vIybe/CDY= +git.fromouter.space/mcg/draft v0.0.2 h1:OT1uztgfCZnZCOg3uOtjQKH2WdwRAxNdYr4KXklVgXY= +git.fromouter.space/mcg/draft v0.0.2/go.mod h1:QQmDm9FgAZL3b2/pIDd4Eo608SxMiCQQe5vIybe/CDY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= diff --git a/draftbot/session.go b/draftbot/session.go index 167f266..d96208e 100644 --- a/draftbot/session.go +++ b/draftbot/session.go @@ -1,9 +1,88 @@ package main import ( + "errors" + "git.fromouter.space/mcg/draft" + "git.fromouter.space/mcg/draft/mlp" + "git.fromouter.space/mcg/mlp-server-tools/draftbot/bot" ) type session struct { - Players map[string]draft.Player + Options draftOptions + Players map[string]*draft.Player + Bots []*bot.Bot + Pod *draft.Pod +} + +// Types of drafts +const ( + draftBlock = "block" + draftSet = "set" + draftCube = "cube" + draftI8PCube = "i8pcube" +) + +type draftOptions struct { + Type string `json:"type"` + + // Block draft properties + Block string `json:"block,omitempty"` + + // Set draft properties + Set string `json:"set,omitempty"` + + // Cube draft properties + CubeURL string `json:"cube_url,omitempty"` + PackSize int `json:"pack_size,omitempty"` + + // I8PCube properties + MainCount int `json:"main_count,omitempty"` + ProblemCount int `json:"problem_count,omitempty"` + + // Shared + PackCount int `json:"pack_count,omitempty"` // Set and Cube +} + +func (do draftOptions) getProvider() (draft.PackProvider, error) { + switch do.Type { + case draftBlock: + return mlp.BlockPacks(mlp.BlockID(do.Block)) + case draftSet: + set, err := mlp.LoadSetHTTP(mlp.SetID(do.Set)) + if err != nil { + return nil, err + } + return draft.PacksFromSet(do.PackCount, set), nil + case draftCube: + cards, err := loadCube(do.CubeURL) + if err != nil { + return nil, err + } + cube := &draft.GenericCube{ + Cards: cards, + PackSize: do.PackSize, + } + return draft.PacksFromSet(do.PackCount, cube), nil + case draftI8PCube: + cube, err := loadI8PCube(do.CubeURL) + if err != nil { + return nil, err + } + return cube.PackProvider(do.MainCount, do.ProblemCount), nil + } + return nil, errors.New("unknown draft type") +} + +func newSession(playerCount int, opt draftOptions) (*session, error) { + // Get pack provider for given options + provider, err := opt.getProvider() + if err != nil { + return nil, err + } + + return &session{ + Options: opt, + Pod: draft.MakePod(playerCount, provider), + }, nil }