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;
}
}
}