package info.interactivesystems.gamificationengine.entities;
import info.interactivesystems.gamificationengine.api.GoalApi;
import info.interactivesystems.gamificationengine.api.ValidateUtils;
import info.interactivesystems.gamificationengine.dao.PlayerDAO;
import info.interactivesystems.gamificationengine.entities.goal.FinishedGoal;
import info.interactivesystems.gamificationengine.entities.goal.Goal;
import info.interactivesystems.gamificationengine.entities.rewards.Achievement;
import info.interactivesystems.gamificationengine.entities.rewards.Badge;
import info.interactivesystems.gamificationengine.entities.rewards.PermanentReward;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* Players can be assigned to a group by its creation or at a later point in time.
* For example depending on the respective organization, a group can be a
* department, a work group or several employees with the same occupation. It is
* possible to create special tasks which can be done only as a group.
* When a member of a group completed such a task the group obtains its rewards.
* So a group can also have a list of already earned rewards and finished Goals.
* Like a player, a group can be assigned an image as a logo.
*/
@Entity
@JsonIgnoreProperties({ "belongsTo", "groupLogo" })
public class PlayerGroup {
private static final Logger LOGGER = LoggerFactory.getLogger(GoalApi.class);
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@NotNull
private String name;
@NotNull
@ManyToOne
private Organisation belongsTo;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private List<Player> players;
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, fetch = FetchType.EAGER)
private List<FinishedGoal> finishedGoals;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private List<PermanentReward> rewards;
private int coins;
private int points;
private int levelIndex;
private String levelLabel;
@Lob
@Column(columnDefinition = "MEDIUMBLOB", length = 3000000)
private byte[] groupLogo;
public PlayerGroup() {
players = new ArrayList<>();
finishedGoals = new ArrayList<>();
}
/**
* Gets the name of the group.
*
* @return a name of the group as String.
*/
public String getName() {
return name;
}
/**
* Set the name field to label a group.
*
* @param name
* The name of the group. May not be null.
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the current list of players who are belong to this group.
*
* @return a list of all players.
*/
public List<Player> getPlayers() {
return players;
}
/**
* Sets the list of players who belong to this group.
*
* @param players
* The new list of players who are assigned to this group.
*/
public void setPlayers(List<Player> players) {
this.players = players;
}
/**
* Gets all Goals a group has already completed.
*
* @return The list of already finished goals.
*/
public List<FinishedGoal> getFinishedGoals() {
return finishedGoals;
}
/**
* Sets the list of Goals a group has already finished.
*
* @param finishedGoals
* goals a group has finished
*/
public void setFinishedGoals(List<FinishedGoal> finishedGoals) {
this.finishedGoals = finishedGoals;
}
/**
* Gets the current amount of points a group owns.
*
* @return Current amount of points this group owns as int.
*/
public int getPoints() {
return points;
}
/**
* Set the current amount of points a group has collected.
*
* @param points
* The new amount of points this group owns.
*/
public void setPoints(int points) {
this.points = points;
}
/**
* The organisation the group belongs to. This parameter must
* not be null
*
* @return The organisations object the group belongs to.
*/
public Organisation getBelongsTo() {
return belongsTo;
}
/**
* Sets the organisation to which this group belongs. The parameter
* must not be null.
*
* @param belongsTo
* The organisation to which the group belongs to henceforth.
*/
public void setBelongsTo(Organisation belongsTo) {
this.belongsTo = belongsTo;
}
/**
* Gets the id of the group.
*
* @return The group's id as int.
*/
public int getId() {
return id;
}
/**
* Sets the id of the group.
*
* @param id
* The id of the group henceforth.
*/
public void setId(int id) {
this.id = id;
}
/**
* Gets the logo of a group as a byte[].
*
* @return Byte[] of the group's image's content.
*/
public byte[] getGroupLogo() {
return groupLogo;
}
/**
* Sets the new logo of a group.
*
* @param groupLogo
* Byte[] of the image's content.
*/
public void setGroupLogo(byte[] groupLogo) {
this.groupLogo = groupLogo;
}
/**
* This method checks if a group belongs to a specific organisation. Therefore
* it is tested if the organisation's API key matches the group's API key.
*
* @param organisation
* The organisation object a group may belong to.
* @return Boolean value if the API key of the group is the same
* of the tested organisation (true) or not (false).
*/
public boolean belongsTo(Organisation organisation) {
return getBelongsTo().getApiKey().equals(organisation.getApiKey());
}
/**
* Adds a permanent reward like a Badge or Achievement to the list of all
* already obtained rewards.
*
* @param reward
* The permanent reward object that was just obtained and should
* be added to the list.
*/
public void addPermanentReward(PermanentReward reward) {
rewards.add(reward);
}
/**
* Raises the current amount of coins a group owns by adding the amount
* of earned coins.
*
* @param amount
* The amount of coins that should be added passed as int.
*/
public void awardCoins(int amount) {
setCoins(getCoins() + amount);
}
/**
* Raises the current amount of points a group owns by adding the amount
* of earned coins.
*
* @param amount
* The amount of coins that should be added passed as int.
*/
public void awardPoints(int amount) {
this.points = this.points + amount;
}
/**
* This method tests if a goal was already finished and if so it returns
* all finished goal objects of the same type that are completed by this
* group.
*
* @param goal
* The goal object that should be compared.
* @return A list of all finished goals of the same type of the passed goal.
*/
public List<FinishedGoal> getFinishedGoalsByGoal(Goal goal) {
List<FinishedGoal> returnList = new ArrayList<>();
for (FinishedGoal fGoal : finishedGoals) {
if (fGoal.getGoal().equals(goal)) {
returnList.add(fGoal);
}
}
return returnList;
}
/**
* Gets the current amount of coins a group of players has obtained.
*
* @return The amount of obtained coins as int.
*/
public int getCoins() {
return coins;
}
/**
* Sets the current amount of coins a group of players has obtained.
*
* @param coins
* The amount of current coins a group owns has.
*/
public void setCoins(int coins) {
this.coins = coins;
}
/**
* Gets all permanent rewards a group of player has already obtained. These
* are for example all badges and achievements.
*
* @return List of all obtained permanent rewards.
*/
public List<PermanentReward> getRewards() {
return rewards;
}
/**
* Sets the list of all permanent rewards a group of players has obtained.
*
* @param rewards
* All permanent rewards a group of players has obtained.
*/
public void setRewards(List<PermanentReward> rewards) {
this.rewards = rewards;
}
/**
* Gets only all Badges a group of players has already obtained.
* If the group has no Badge, null is returned.
*
* @return A List of all obtained Badges as List.
*/
public List<Badge> getOnlyBadges() {
// filter PermanentRewards for Badges
if (rewards != null) {
List<Badge> badges = rewards.stream().filter(r -> r instanceof Badge).map(r -> (Badge) r).collect(Collectors.toList());
return badges;
} else {
return null;
}
}
/**
* Gets only all Achievements a group of players has already obtained.
* If the group has no Achievement, null is returned.
*
* @return A List of all obtained Achievements as List.
*/
public List<Achievement> getOnlyAchievement() {
// filter PermanantAchievements for Achievements
if (rewards != null) {
List<Achievement> achievements = rewards.stream().filter(r -> r instanceof Achievement).map(r -> (Achievement) r)
.collect(Collectors.toList());
return achievements;
} else {
return null;
}
}
/**
* Gets the current level index of a group of players.
*
* @return Level index returned as int.
*/
public int getLevelIndex() {
return levelIndex;
}
/**
* Sets the current level index a group of players has obtained.
*
* @param levelIndex
* The index of player's current level.
*/
public void setLevelIndex(int levelIndex) {
this.levelIndex = levelIndex;
}
/**
* Gets the label of a group's current level.
*
* @return The name of the player's current level as String.
*/
public String getLevelLabel() {
return levelLabel;
}
/**
* Sets the label of a group's current level.
*
* @param levelLabel
* The name of the group's current level.
*/
public void setLevelLabel(String levelLabel) {
this.levelLabel = levelLabel;
}
/**
* This method adds one or more players to the group's list of current players, but only if they
* are not in this list already.
*
* @param newPlayer
* The new players that should be added to the list of players.
*/
public void addPlayers(List<Player> newPlayer){
for(Player player : newPlayer){
if(!players.contains(player)){
players.add(player);
}
}
}
/**
* This method removes one or more players of the group's list of current players, but only if they
* are in this list already.
*
* @param oldPlayer
* The players that should be removed from the list of players.
*/
public void removePlayers(List<Player> oldPlayer){
for(Player player : oldPlayer){
if(players.contains(player)){
players.remove(player);
}
}
}
/**
* This method returns a list of players associated with the passed ids
*
* @param playerIds
* The ids that should be converted to a list of players.
* @param playerDao
* The player DAO is required to access created players.
* @param apiKey
* The API key of the organisation is needed to access the created players.
* @return A list of Players that are associated with the passed ids.
*/
public List<Player> parseIdsToPlayerList(String playerIds,PlayerDAO playerDao, String apiKey){
// Find all Players by Id
String[] playerIdList = playerIds.split(",");
List<Player> players = new ArrayList<>();
for (String playerIdString : playerIdList) {
LOGGER.debug("Player To Add: " + playerIdString);
Player player = playerDao.getPlayer(ValidateUtils.requireGreaterThanZero(playerIdString), apiKey);
if (player != null) {
LOGGER.debug("Player added: " + player.getId());
players.add(player);
}
}
return players;
}
}