diff --git a/pod.go b/pod.go index 003e286..322fb8c 100644 --- a/pod.go +++ b/pod.go @@ -1,26 +1,122 @@ package draft +import "errors" + +// Errors that can happen during draft +var ( + ErrNotInPack = errors.New("card picked not in pack") + ErrNoPacksLeft = errors.New("no packs left to open") +) + +// PodDirection is the direction packs are passed between players +type PodDirection string + +// All rotations +var ( + PRClockwise PodDirection = "left" + PRAnticlockwise PodDirection = "right" +) + // Pod is a group of players drafting packs/cubes type Pod struct { - Players []*Player + Players []*Player + Direction PodDirection } // Player is a single player partecipating in a pod type Player struct { - Packs []Pack - Picks []Card + // Packs and picks + CurrentPack Pack + Packs []Pack + Picks []Card + + // Nearby players + left *Player + right *Player + + // Pod the player is in + pod *Pod } // MakePod creates a pod with a specified number of players and a given set of packs func MakePod(playerCount int, provider PackProvider) *Pod { + // Make player list players := make([]*Player, playerCount) + + // Make pod + pod := &Pod{ + Players: players, + Direction: PRAnticlockwise, + } + + // Fill players for i := range players { players[i] = &Player{ Packs: provider(), Picks: []Card{}, + pod: pod, } } - return &Pod{ - Players: players, + // Second loop to fill nearby players + for i := range players { + if i > 0 { + players[i].left = players[i-1] + } else { + players[i].left = players[playerCount-1] + } + players[i].right = players[(i+1)%playerCount] + } + + return pod +} + +// OpenPacks opens the next pack of each player +func (p *Pod) OpenPacks() error { + for _, p := range p.Players { + err := p.OpenPack() + if err != nil { + return err + } + } + p.flipDirection() + return nil +} + +func (p *Pod) flipDirection() { + if p.Direction == PRClockwise { + p.Direction = PRAnticlockwise + } else { + p.Direction = PRClockwise } } + +// OpenPack opens the next pack the player has +func (p *Player) OpenPack() error { + if len(p.Packs) < 1 { + return ErrNoPacksLeft + } + p.CurrentPack, p.Packs = p.Packs[0], p.Packs[1:] + return nil +} + +// Pick specified what card a player has picked and gives the pack to the next player +func (p *Player) Pick(pick Card) error { + // Check that pack contains specified card + id := -1 + for i, card := range p.CurrentPack { + if pick.ID == card.ID { + id = i + break + } + } + if id < 0 { + return ErrNotInPack + } + // Take card from pack and put it into the picks + p.Picks = append(p.Picks, p.CurrentPack[id]) + // Remove pick from pack using slice tricks + p.CurrentPack[id] = p.CurrentPack[len(p.CurrentPack)-1] + p.CurrentPack = p.CurrentPack[:len(p.CurrentPack)-1] + + return nil +} diff --git a/pod_test.go b/pod_test.go index c7ac577..a4b54b8 100644 --- a/pod_test.go +++ b/pod_test.go @@ -1,7 +1,6 @@ package draft_test import ( - "log" "testing" "git.fromouter.space/mcg/draft" @@ -19,7 +18,7 @@ func TestCreatePod(t *testing.T) { pod := draft.MakePod(PlayersPerPod, testProvider) if len(pod.Players) != PlayersPerPod { - log.Fatalf("Expected %d players in pod but got %d\n", PlayersPerPod, len(pod.Players)) + t.Fatalf("Expected %d players in pod but got %d\n", PlayersPerPod, len(pod.Players)) } for i, player := range pod.Players { @@ -28,7 +27,57 @@ func TestCreatePod(t *testing.T) { t.Logf(" - Pack #%d: %s", packi, pack) } if len(player.Packs) != PacksPerPlayer { - log.Fatalf("Player #%d has %d packs but should have %d\n", i, PacksPerPlayer, len(player.Packs)) + t.Fatalf("Player #%d has %d packs but should have %d\n", i, PacksPerPlayer, len(player.Packs)) } } } + +func TestPick(t *testing.T) { + const PacksPerPlayer = 3 + const PlayersPerPod = 5 + + // Get provider for test set + testProvider := draft.PacksFromSet(PacksPerPlayer, testSet) + + // Create pod + pod := draft.MakePod(PlayersPerPod, testProvider) + pod.OpenPacks() + + for _, player := range pod.Players { + // Pick first card for each player + err := player.Pick(player.CurrentPack[0]) + if err != nil { + t.Fatalf("Tried picking first card in pack but couldn't: %s\n", err.Error()) + } + } +} + +func TestPodErrors(t *testing.T) { + const PacksPerPlayer = 3 + const PlayersPerPod = 5 + + // Get provider for test set + testProvider := draft.PacksFromSet(PacksPerPlayer, testSet) + + // Create pod + pod := draft.MakePod(PlayersPerPod, testProvider) + pod.OpenPacks() + + // Pick a card that doesn't exist + err := pod.Players[0].Pick(draft.Card{ID: "nana"}) + if err == nil { + t.Fatal("Tried picking inexistant card but it succeeded\n") + } else if err != draft.ErrNotInPack { + t.Fatalf("Got error for wrong pick but not the right one: %s\n", err.Error()) + } + + // Try opening more packs than each player has + for i := 0; i < PacksPerPlayer; i++ { + err = pod.OpenPacks() + } + if err == nil { + t.Fatal("Tried opening too many packs but it succeeded\n") + } else if err != draft.ErrNoPacksLeft { + t.Fatalf("Got error for too many packs but not the right one: %s\n", err.Error()) + } +}