package draft import ( "math/rand" "strings" ) // Pack is a collection of cards from a booster pack type Pack []Card // Card is a single card type Card struct { ID string } // CardProvider is a function that returns as many cards of a certain types as needed type CardProvider func(int) []Card // PackSchema is all that's needed to generate a certain type of pack type PackSchema struct { Slots []PackSlot } // PackSlot is part of how packs are made, one or more providers provide // cards for X cards of the whole pack type PackSlot struct { Amount int Provider CardProvider Alternate []AlternateProvider } // AlternateProvider are Card providers that can replace one or more slots // with special cards (foils, ultra rares) type AlternateProvider struct { Probability float32 Provider CardProvider } // MakePack makes a booster pack from a given set // It's a shortcut to `MakePackWithSchema(set.PackSchema())` func MakePack(set Set) Pack { schema := set.PackSchema() return MakePackWithSchema(schema) } // MakePackWithSchema makes a booster pack from a given schema func MakePackWithSchema(schema PackSchema) Pack { pack := make(Pack, 0) for _, slot := range schema.Slots { // Default provider provider := slot.Provider // Check for random alternates if slot.Alternate != nil { var currentProb float32 var chosenProb = rand.Float32() for _, alt := range slot.Alternate { currentProb += alt.Probability if currentProb > chosenProb { provider = alt.Provider break } } } // Extract cards from provider and add them to the pack cards := provider(slot.Amount) pack = append(pack, cards...) } return pack } // String encodes a pack to a list of space-separated IDs func (p Pack) String() (str string) { for _, card := range p { str += " " + card.ID } str = strings.TrimSpace(str) return }