Add bot and session primitives
This commit is contained in:
parent
14ac80df84
commit
cd04155257
7 changed files with 230 additions and 23 deletions
|
@ -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) {
|
|
||||||
|
|
||||||
}
|
|
37
draftbot/bot/bot.go
Normal file
37
draftbot/bot/bot.go
Normal file
|
@ -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])
|
||||||
|
}
|
80
draftbot/cube.go
Normal file
80
draftbot/cube.go
Normal file
|
@ -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()
|
||||||
|
}
|
30
draftbot/draftbot.go
Normal file
30
draftbot/draftbot.go
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,6 @@ go 1.12
|
||||||
require (
|
require (
|
||||||
git.fromouter.space/Artificiale/moa v0.0.1-p2
|
git.fromouter.space/Artificiale/moa v0.0.1-p2
|
||||||
git.fromouter.space/mcg/cardgage 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
|
github.com/go-kit/kit v0.8.0
|
||||||
)
|
)
|
||||||
|
|
|
@ -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/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 h1:u65ofEmtDHHQ8nbai97DW9kcrYa4x0I3NHv2oXhw8dI=
|
||||||
git.fromouter.space/mcg/cardgage v0.0.1-p2/go.mod h1:vCmJ9HRdRGSWg2YQW9oNG7geYACdgWYmzL+zZdrsYhQ=
|
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.2 h1:OT1uztgfCZnZCOg3uOtjQKH2WdwRAxNdYr4KXklVgXY=
|
||||||
git.fromouter.space/mcg/draft v0.0.0-20190617210125-5e49b051369f/go.mod h1:QQmDm9FgAZL3b2/pIDd4Eo608SxMiCQQe5vIybe/CDY=
|
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/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/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=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
|
|
@ -1,9 +1,88 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"git.fromouter.space/mcg/draft"
|
"git.fromouter.space/mcg/draft"
|
||||||
|
"git.fromouter.space/mcg/draft/mlp"
|
||||||
|
"git.fromouter.space/mcg/mlp-server-tools/draftbot/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
type session struct {
|
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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue