/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see .
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.UUID;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* This class handles the instance of a group. Each group instance has a leader which sets the behavior. All other
* participants follow the behavior of the leader in terms of speed, velocity, heading etc.
*
* @author Julian Zobel
*/
public class SocialMovementGroup {
public final UUID groupID;
private Random rand = Randoms.getRandom(SocialMovementGroup.class);
private SimLocationActuator leader;
private LinkedHashSet members;
private PositionVector destination;
private PositionVector meetingPoint;
/**
* Initializes the group with a given leader.
*
* @param SimLocationActuator New leader of the group
* @param int The ID of the group.
*/
public SocialMovementGroup(SimLocationActuator leader) {
this.groupID = UUID.randomUUID();
this.leader = leader;
this.members = new LinkedHashSet();
this.members.add(leader);
}
/**
* Initializes the group, sets the participants and groupId, finally chooses a random leader.
*
* @param Set All participants of the group.
* @param int The ID of the group.
*/
public SocialMovementGroup(LinkedHashSet participants) {
this.groupID = UUID.randomUUID();
setMembers(participants);
setRandomLeader();
}
/**
* Adds a host to the group. Manually check in {@link ModularMovementModel} class, if group size is exceeded by adding another host.
*
* @param SimLocationActuator The host to be added.
*/
public void addHostToGroup(SimLocationActuator host) {
members.add(host);
}
/**
* Removes a host from the group. If the host was the current leader, a random new leader is chosen from the remaining members.
*
* @param SimLocationActuator The host to be removed.
*/
public void removeHostFromGroup(SimLocationActuator host) {
if(members.contains(host)) {
if(host == leader) {
members.remove(host);
setRandomLeader();
}
else {
members.remove(host);
}
}
}
/**
* Sets a randomly chosen participant of the group as leader.
*/
private void setRandomLeader() {
this.leader = getRandomMember();
}
/**
* Returns a random participant of all group members.
*
* @return SimLocationActuator
*/
public SimLocationActuator getRandomMember() {
if(members.size() > 1) {
int item = rand.nextInt(members.size() - 1);
int i = 0;
for(SimLocationActuator host : members) {
if(i == item) {
return host;
}
i++;
}
}
else if(members.size() == 1) {
return members.iterator().next();
}
return null;
}
/**
* Returns true if this group has a specific host as member, false otherwise
*
* @param SimLocationActuator The host to be checked.
* @return boolean
*/
public boolean hasMember(SimLocationActuator host) {
if(members.contains(host)) {
return true;
}
return false;
}
/**
* Returns the position of the group leader.
*
* @return PositionVector The position of the group leader.
*/
public PositionVector getLeaderPosition() {
return leader.getRealPosition();
}
@Override
public String toString() {
return "Social Group of Leader #" + leader.getHost().getId() + " ("+ members.size() +")";
}
// ===================
// Getters and Setters
// ===================
public int getGroupSize() {
return members.size();
}
public LinkedHashSet getMembers() {
return new LinkedHashSet(members);
}
public void setMembers(LinkedHashSet participants) {
this.members = new LinkedHashSet<>(participants);
}
public SimLocationActuator getLeader() {
return leader;
}
public PositionVector getDestination() {
return destination;
}
public void setDestination(PositionVector destination) {
this.destination = destination;
}
public PositionVector getMeetingPoint() {
return meetingPoint;
}
public void setMeetingPoint(PositionVector meetingPoint) {
this.meetingPoint = meetingPoint;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SocialMovementGroup)) {
return false;
}
SocialMovementGroup toCompare = (SocialMovementGroup) obj;
if(this.groupID == toCompare.groupID) {
if(this.getLeader() == toCompare.getLeader()) {
return true;
}
else {
System.out.println("Leader seems to be different, but still the same UUID");
return false;
}
}
else return false;
}
@Override
public int hashCode() {
//FIXME hope this is correct -- should we include the leader and/or other fields as well?
return groupID.hashCode();
}
}