From 55a3754a23982d7189320e2a93e2e334832f976b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AEittaG=20ordnasselA?= Date: Fri, 31 May 2019 10:57:51 +0200 Subject: [PATCH] Add tests --- example/draft-mlp/README.md | 4 ++ set.go | 7 +- set_test.go | 136 ++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 example/draft-mlp/README.md create mode 100644 set_test.go diff --git a/example/draft-mlp/README.md b/example/draft-mlp/README.md new file mode 100644 index 0000000..6e03c64 --- /dev/null +++ b/example/draft-mlp/README.md @@ -0,0 +1,4 @@ +# draft-mlp + +Example command that generates random MLP:CCG booster packs for a given set. +This is mostly done to test the library itself. diff --git a/set.go b/set.go index ef1b1bc..4bd1db5 100644 --- a/set.go +++ b/set.go @@ -10,15 +10,16 @@ type Set interface { // GenericSet is an generalized set of a card game // Treat this as an example implementation or a starting type GenericSet struct { - Cards []Card - PackSize int + Cards []Card + PackSize int + Alternates []AlternateProvider } // PackSchema returns the pack schema from a booster containing all possible cards func (g *GenericSet) PackSchema() PackSchema { return PackSchema{ Slots: []PackSlot{ - {Amount: g.PackSize, Provider: g.RandomProvider()}, + {Amount: g.PackSize, Provider: g.RandomProvider(), Alternate: g.Alternates}, }, } } diff --git a/set_test.go b/set_test.go new file mode 100644 index 0000000..69cbabb --- /dev/null +++ b/set_test.go @@ -0,0 +1,136 @@ +package draft + +import ( + "fmt" + "math/rand" + "testing" +) + +// TestSetRepeatable makes sure that a set can generate more cards than it contains +func TestSetRepeatable(t *testing.T) { + const PACKSIZE = 5 + s := &GenericSet{ + Cards: []Card{{ID: "a"}, {ID: "b"}, {ID: "c"}}, + PackSize: PACKSIZE, + } + + // Create a pack + pack := MakePack(s) + + if len(pack) < PACKSIZE { + t.Errorf("Pack expected to contain %d cards, contains %d", PACKSIZE, len(pack)) + } + + // Check that all cards have something in it + for i, card := range pack { + if card.ID == "" { + t.Errorf("Pack contains \"empty\" card") + } + if card.ID != "a" && card.ID != "b" && card.ID != "c" { + t.Errorf("Pack contains unexpected card %s at index %d, not contained in pool", card.ID, i) + } + } +} + +// TestAlternateProviders tests alternate providers +func TestAlternateProviders(t *testing.T) { + customProvider := func(n int) []Card { + out := make([]Card, n) + for n := range out { + out[n] = Card{ID: "x"} + } + return out + } + s := &GenericSet{ + Cards: []Card{{ID: "a"}, {ID: "b"}, {ID: "c"}}, + PackSize: 1, + Alternates: []AlternateProvider{ + { + Probability: 0.3, + Provider: customProvider, + }, + }, + } + // Use set seed for getting deterministic results + rand.Seed(0) + + nonalternates, alternates := 0, 0 + for i := 0; i < 500000; i++ { + pack := MakePack(s) + if pack[0].ID == "x" { + alternates++ + } else { + nonalternates++ + } + } + + // Calculate distribution + distribution := float32(float32(alternates) / (float32(nonalternates) + float32(alternates))) + + // After 500k packs, I'm expecting distribution to be within 2% + if distribution < 0.29 || distribution > 0.31 { + t.Errorf("Distribution is sketchy after 500k packs: %f%%", distribution*100) + } +} + +// TestCubeOverflow makes sure cubes stop providing cards as they are exhausted instead of going out of bound +func TestCubeOverflow(t *testing.T) { + const PACKSIZE = 5 + c := &GenericCube{ + Cards: []Card{ + {ID: "a"}, {ID: "b"}, {ID: "c"}, {ID: "d"}, {ID: "e"}, + {ID: "f"}, {ID: "g"}, {ID: "h"}, {ID: "i"}, + }, + PackSize: PACKSIZE, + } + + pack1 := MakePack(c) + pack2 := MakePack(c) + + // Pack 2 can only contain 4 cards, as there are not enough cards to fill it + if len(pack2) >= PACKSIZE { + t.Errorf("Pack 2 expected to contain only 4 cards, has %d", len(pack2)) + } + + // Check for duplicates + allcards := append(pack1, pack2...) + uniq := sliceUniq(allcards) + if len(allcards) != len(uniq) { + t.Errorf("Duplicate cards found across packs") + } +} + +// ExampleGenericSet is an example usage of the Set APIs to make packs +func ExampleGenericSet() { + // Create a set with some items + s := &GenericSet{ + Cards: []Card{ + {ID: "a"}, + {ID: "b"}, + {ID: "c"}, + }, + PackSize: 5, + } + + // Create a pack + pack := MakePack(s) + + // Print cards in pack + for i, card := range pack { + fmt.Printf("Card #%d: %s\n", i, card.ID) + } +} + +// https://gist.github.com/alioygur/16c66b4249cb42715091fe010eec7e33 +func sliceUniq(s []Card) []Card { + for i := 0; i < len(s); i++ { + for i2 := i + 1; i2 < len(s); i2++ { + if s[i].ID == s[i2].ID { + // delete + s = append(s[:i2], s[i2+1:]...) + i2-- + } + } + } + return s +}