package games.strategy.engine.data; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import games.strategy.triplea.attachments.RelationshipTypeAttachment; public class RelationshipTracker extends RelationshipInterpreter { private static final long serialVersionUID = -4740671761925519069L; // map of "playername:playername" to RelationshipType that exists between those 2 players private final HashMap<RelatedPlayers, Relationship> m_relationships = new HashMap<>(); public RelationshipTracker(final GameData data) { super(data); } /** * Method for setting a relationship between two players, this should only be called through the Change Factory. * * @param p1 * Player1 that will get the relationship * @param p2 * Player2 that will get the relationship * @param r * the RelationshipType between those two players that will be set. */ public void setRelationship(final PlayerID p1, final PlayerID p2, final RelationshipType r) { m_relationships.put(new RelatedPlayers(p1, p2), new Relationship(r)); } /** * Method for setting a relationship between two players, this should only be called during the Game Parser. */ protected void setRelationship(final PlayerID p1, final PlayerID p2, final RelationshipType r, final int roundValue) { m_relationships.put(new RelatedPlayers(p1, p2), new Relationship(r, roundValue)); } /** * will give you the relationshipType that currently exists between 2 players. * * @param p1 * Player1 in the relationship * @param p2 * Player2 in the relationship * @return the current RelationshipType between those two players */ @Override public RelationshipType getRelationshipType(final PlayerID p1, final PlayerID p2) { return getRelationship(p1, p2).getRelationshipType(); } public Relationship getRelationship(final PlayerID p1, final PlayerID p2) { return m_relationships.get(new RelatedPlayers(p1, p2)); } public HashSet<Relationship> getRelationships(final PlayerID player1) { final HashSet<Relationship> relationships = new HashSet<>(); for (final PlayerID player2 : getData().getPlayerList().getPlayers()) { if (player2 == null || player2.equals(player1)) { continue; } relationships.add(getRelationship(player1, player2)); } return relationships; } public int getRoundRelationshipWasCreated(final PlayerID p1, final PlayerID p2) { return m_relationships.get(new RelatedPlayers(p1, p2)).getRoundCreated(); } /** * Convenience method to directly access relationshipTypeAttachment on the relationship that exists between two * players. * * @param p1 * Player 1 in the relationship * @param p2 * Player 2 in the relationship * @return the current RelationshipTypeAttachment attached to the current relationship that exists between those 2 * players */ protected RelationshipTypeAttachment getRelationshipTypeAttachment(final PlayerID p1, final PlayerID p2) { final RelationshipType relation = getRelationshipType(p1, p2); return RelationshipTypeAttachment.get(relation); } /** * This methods will create all SelfRelations of all players including NullPlayer with oneself. * This method should only be called once. */ protected void setSelfRelations() { for (final PlayerID p : getData().getPlayerList().getPlayers()) { setRelationship(p, p, getSelfRelationshipType()); } setRelationship(PlayerID.NULL_PLAYERID, PlayerID.NULL_PLAYERID, getSelfRelationshipType()); } /** * This methods will create all relationship of all players with the NullPlayer. * This method should only be called once. */ protected void setNullPlayerRelations() { for (final PlayerID p : getData().getPlayerList().getPlayers()) { setRelationship(p, PlayerID.NULL_PLAYERID, getNullRelationshipType()); } } /** convenience method to get the SelfRelationshipType added for readability. */ private RelationshipType getSelfRelationshipType() { return getData().getRelationshipTypeList().getSelfRelation(); } /** convenience method to get the NullRelationshipType (relationship with the Nullplayer) added for readability. */ private RelationshipType getNullRelationshipType() { return getData().getRelationshipTypeList().getNullRelation(); } /** * RelatedPlayers is a class of 2 players that are related, used in relationships. */ public class RelatedPlayers implements Serializable { private static final long serialVersionUID = 2124258606502106751L; /** * override hashCode to make sure that each new instance of this class can be matched in the Hashtable * even if it was put in as (p1,p2) and you want to get it out as (p2,p1). */ @Override public int hashCode() { return m_p1.hashCode() + m_p2.hashCode(); } private final PlayerID m_p1; private final PlayerID m_p2; public RelatedPlayers(final PlayerID p1, final PlayerID p2) { m_p1 = p1; m_p2 = p2; } @Override public boolean equals(final Object object) { if (object instanceof RelatedPlayers) { final RelatedPlayers relatedPlayers2 = (RelatedPlayers) object; return (relatedPlayers2.m_p1.equals(m_p1) && relatedPlayers2.m_p2.equals(m_p2)) || (relatedPlayers2.m_p2.equals(m_p1) && relatedPlayers2.m_p1.equals(m_p2)); } return super.equals(object); } /** * convenience method to get relationshipType from a new RelatedPlayers(p1,p2).getRelationshipType(); * * @return RelationshipType between these RelatedPlayers */ public RelationshipType getRelationshipType() { return getData().getRelationshipTracker().getRelationshipType(m_p1, m_p2); } /** * convenience method to get relationshipTypeAttachment from a new * RelatedPlayers(p1,p2).getRelationshipTypeAttachment(); * * @return RelationshipTypeAttachment between these RelatedPlayers */ public RelationshipTypeAttachment getRelationshipTypeAttachment() { return getData().getRelationshipTracker().getRelationshipTypeAttachment(m_p1, m_p2); } @Override public String toString() { return m_p1.getName() + "-" + m_p2.getName(); } } public class Relationship implements Serializable { private static final long serialVersionUID = -6718866176901627180L; /** * This should never be called outside of the change factory. */ public Relationship(final RelationshipType relationshipType) { this.relationshipType = relationshipType; this.roundCreated = getData().getSequence().getRound(); } /** * This should never be called outside of the game parser. */ public Relationship(final RelationshipType relationshipType, final int roundValue) { this.relationshipType = relationshipType; this.roundCreated = roundValue; } private final RelationshipType relationshipType; private final int roundCreated; public int getRoundCreated() { return roundCreated; } public RelationshipType getRelationshipType() { return relationshipType; } @Override public String toString() { return roundCreated + ":" + relationshipType; } } }