package draft_test import ( "fmt" "math/rand" "testing" "git.fromouter.space/mcg/draft" ) const PACKSIZE = 5 // Test set that can be used by tests that don't need special features (like alternates) var testSet = &draft.GenericSet{ Cards: []draft.Card{{ID: "a"}, {ID: "b"}, {ID: "c"}}, PackSize: PACKSIZE, } // Test cube that can be used by tests that don't need special features var testCube = &draft.GenericCube{ Cards: []draft.Card{ {ID: "a"}, {ID: "b"}, {ID: "c"}, {ID: "d"}, {ID: "e"}, {ID: "f"}, {ID: "g"}, {ID: "h"}, {ID: "i"}, }, PackSize: PACKSIZE, } // TestSetRepeatable makes sure that a set can generate more cards than it contains func TestSetRepeatable(t *testing.T) { // Create a pack pack := draft.MakePack(testSet) if len(pack) < PACKSIZE { t.Fatalf("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.Fatalf("Pack contains \"empty\" card") } if card.ID != "a" && card.ID != "b" && card.ID != "c" { t.Fatalf("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) []draft.Card { out := make([]draft.Card, n) for n := range out { out[n] = draft.Card{ID: "x"} } return out } s := &draft.GenericSet{ Cards: []draft.Card{{ID: "a"}, {ID: "b"}, {ID: "c"}}, PackSize: 1, Alternates: []draft.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 := draft.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.Fatalf("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) { pack1 := draft.MakePack(testCube) pack2 := draft.MakePack(testCube) // Pack 2 can only contain 4 cards, as there are not enough cards to fill it if len(pack2) >= PACKSIZE { t.Fatalf("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.Fatalf("Duplicate cards found across packs") } } // TestPackString makes sure packs are serialized correctly func TestPackString(t *testing.T) { p := draft.Pack{{ID: "a"}, {ID: "b"}, {ID: "c"}} expected := "a b c" if p.String() != expected { t.Fatalf("Expected \"%s\" but got \"%s\"", expected, p) } } // ExampleGenericSet is an example usage of the Set APIs to make packs func ExampleGenericSet() { // Create a set with some items s := &draft.GenericSet{ Cards: []draft.Card{ {ID: "a"}, {ID: "b"}, {ID: "c"}, }, PackSize: 5, } // Create a pack pack := draft.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 []draft.Card) []draft.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 }