package mage.abilities.dynamicvalue; import mage.cards.Card; import mage.cards.Cards; import mage.game.Game; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; /** * Used for when you need to know how attributes are assigned among cards, such as for party count * Can be adapted for various card attributes * * @author TheElk801 */ public abstract class RoleAssignment implements Serializable { protected final List attributes = new ArrayList<>(); protected RoleAssignment(T... attributes) { for (T attribute : attributes) { this.attributes.add(attribute); } } protected abstract Set makeSet(Card card, Game game); private boolean attemptRearrange(T attribute, UUID uuid, Set attributes, Map attributeUUIDMap, Map> attributeSetMap) { UUID uuid1 = attributeUUIDMap.get(attribute); if (uuid1 == null) { return false; } Set attributes1 = attributeSetMap.get(uuid1); for (T attribute1 : attributes1) { if (attribute == attribute1) { continue; } if (!attributeUUIDMap.containsKey(attribute1)) { attributeUUIDMap.put(attribute, uuid); attributeUUIDMap.put(attribute1, uuid1); return true; } } for (T attribute1 : attributes1) { if (attribute == attribute1) { continue; } if (attemptRearrange(attribute1, uuid1, attributes, attributeUUIDMap, attributeSetMap)) { attributeUUIDMap.put(attribute, uuid); attributeUUIDMap.put(attribute1, uuid1); return true; } } return false; } public int getRoleCount(Cards cards, Game game) { Map> attributeMap = new HashMap<>(); cards.getCards(game).forEach(card -> attributeMap.put(card.getId(), this.makeSet(card, game))); if (attributeMap.size() < 2) { return attributeMap.size(); } Set availableTypes = attributeMap .values() .stream() .flatMap(Collection::stream) .collect(Collectors.toSet()); if (attributeMap.size() == 2) { return Math.min(2, availableTypes.size()); } Map attributeUUIDMap = new HashMap<>(); for (Map.Entry> entry : attributeMap.entrySet()) { for (T attribute : entry.getValue()) { if (!attributeUUIDMap.containsKey(attribute)) { attributeUUIDMap.put(attribute, entry.getKey()); break; } } if (attributeUUIDMap.size() >= availableTypes.size()) { return attributeUUIDMap.size(); } else if (attributeUUIDMap.containsValue(entry.getKey())) { continue; } else { for (T attribute : entry.getValue()) { if (attemptRearrange(attribute, entry.getKey(), entry.getValue(), attributeUUIDMap, attributeMap)) { break; } } } } return attributeUUIDMap.keySet().size(); } }