package games.strategy.engine.data; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import games.strategy.util.IntegerMap; import games.strategy.util.Match; /** * A collection of units. */ public class UnitCollection extends GameDataComponent implements Iterable<Unit> { private static final long serialVersionUID = -3534037864426122864L; private final List<Unit> m_units = new ArrayList<>(); private final NamedUnitHolder m_holder; /** * Creates new UnitCollection. * * @param holder * named unit holder * @param data * game data */ public UnitCollection(final NamedUnitHolder holder, final GameData data) { super(data); m_holder = holder; } void addUnit(final Unit unit) { m_units.add(unit); m_holder.notifyChanged(); } void addAllUnits(final UnitCollection collection) { m_units.addAll(collection.m_units); m_holder.notifyChanged(); } public void addAllUnits(final Collection<Unit> units) { m_units.addAll(units); m_holder.notifyChanged(); } public void removeAllUnits(final Collection<Unit> units) { m_units.removeAll(units); m_holder.notifyChanged(); } public int getUnitCount() { return m_units.size(); } public int getUnitCount(final UnitType type) { int count = 0; final Iterator<Unit> iterator = m_units.iterator(); while (iterator.hasNext()) { if (iterator.next().getType().equals(type)) { count++; } } return count; } public int getUnitCount(final UnitType type, final PlayerID owner) { int count = 0; final Iterator<Unit> iterator = m_units.iterator(); while (iterator.hasNext()) { final Unit current = iterator.next(); if (current.getType().equals(type) && current.getOwner().equals(owner)) { count++; } } return count; } public int getUnitCount(final PlayerID owner) { int count = 0; final Iterator<Unit> iterator = m_units.iterator(); while (iterator.hasNext()) { if (iterator.next().getOwner().equals(owner)) { count++; } } return count; } public boolean containsAll(final Collection<Unit> units) { // much faster for large sets if (m_units.size() > 500 && units.size() > 500) { return new HashSet<>(m_units).containsAll(units); } return m_units.containsAll(units); } /** * @param type * referring unit type * @param max_units * maximal number of units * @return up to count units of a given type currently in the collection. */ public Collection<Unit> getUnits(final UnitType type, final int max_units) { if (max_units == 0) { return new ArrayList<>(); } if (max_units < 0) { throw new IllegalArgumentException("value must be positiive. Instead its:" + max_units); } final Collection<Unit> rVal = new ArrayList<>(); for (final Unit current : m_units) { if (current.getType().equals(type)) { rVal.add(current); if (rVal.size() == max_units) { return rVal; } } } return rVal; } /** * @return integer map of UnitType. */ public IntegerMap<UnitType> getUnitsByType() { final IntegerMap<UnitType> units = new IntegerMap<>(); for (final UnitType type : getData().getUnitTypeList()) { final int count = getUnitCount(type); if (count > 0) { units.put(type, count); } } return units; } /** * @param id * referring player ID * @return map of UnitType (only of units for the specified player). */ public IntegerMap<UnitType> getUnitsByType(final PlayerID id) { final IntegerMap<UnitType> count = new IntegerMap<>(); for (final Unit unit : m_units) { if (unit.getOwner().equals(id)) { count.add(unit.getType(), 1); } } return count; } /** * @param types * map of unit types * @return collection of units of each type up to max. */ public Collection<Unit> getUnits(final IntegerMap<UnitType> types) { final Collection<Unit> units = new ArrayList<>(); for (final UnitType type : types.keySet()) { units.addAll(getUnits(type, types.getInt(type))); } return units; } public int size() { return m_units.size(); } public boolean isEmpty() { return m_units.isEmpty(); } public Collection<Unit> getUnits() { return new ArrayList<>(m_units); } /** * @return a Set of all players who have units in this collection. */ public Set<PlayerID> getPlayersWithUnits() { // note nulls are handled by PlayerID.NULL_PLAYERID final Set<PlayerID> ids = new HashSet<>(); for (final Unit unit : m_units) { ids.add(unit.getOwner()); } return ids; } /** * @return The count of units each player has in this collection. */ public IntegerMap<PlayerID> getPlayerUnitCounts() { final IntegerMap<PlayerID> count = new IntegerMap<>(); for (final Unit unit : m_units) { count.add(unit.getOwner(), 1); } return count; } public boolean hasUnitsFromMultiplePlayers() { return getPlayersWithUnits().size() > 1; } public NamedUnitHolder getHolder() { return m_holder; } public boolean allMatch(final Match<Unit> matcher) { for (final Unit unit : m_units) { if (!matcher.match(unit)) { return false; } } return true; } public boolean someMatch(final Match<Unit> matcher) { for (final Unit unit : m_units) { if (matcher.match(unit)) { return true; } } return false; } public int countMatches(final Match<Unit> predicate) { return Match.countMatches(m_units, predicate); } public List<Unit> getMatches(final Match<Unit> predicate) { final List<Unit> values = new ArrayList<>(); for (final Unit unit : m_units) { if (predicate.match(unit)) { values.add(unit); } } return values; } @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("Unit collecion held by ").append(m_holder.getName()); buf.append(" units:"); final IntegerMap<UnitType> units = getUnitsByType(); for (final UnitType unit : units.keySet()) { buf.append(" <").append(unit.getName()).append(",").append(units.getInt(unit)).append("> "); } return buf.toString(); } @Override public Iterator<Unit> iterator() { return Collections.unmodifiableList(m_units).iterator(); } }