code: def weighted_card_choice(source, weights: List[int], card_sets: List[str], count: int):
  	
  
  	chosen_cards = []
  
  	# sum all the weights
  	cum_weights = []
  	totalweight = 0
  	for i, w in enumerate(weights):
  		totalweight += w * len(card_sets[i])
  		cum_weights.append(totalweight)
  
  	# for each card
  	for i in range(count):
  		# choose a set according to weighting
  		chosen_set = bisect(cum_weights, random.random() * totalweight)
  
  		# choose a random card from that set
  		chosen_card_index = random.randint(0, len(card_sets[chosen_set]) - 1)
  
  		chosen_cards.append(card_sets[chosen_set].pop(chosen_card_index))
  		totalweight -= weights[chosen_set]
  		cum_weights[chosen_set:] = [x - weights[chosen_set] for x in cum_weights[chosen_set:]]
  
  	return [source.controller.card(card, source=source) for card in chosen_cards]
docs: Take a list of weights and a list of card pools and produce
  	a random weighted sample without replacement.
  	len(weights) == len(card_sets) (one weight per card set)