package info.interactivesystems.gamificationengine.entities.rewards; import info.interactivesystems.gamificationengine.dao.GoalDAO; import info.interactivesystems.gamificationengine.dao.RuleDAO; import info.interactivesystems.gamificationengine.entities.Player; import info.interactivesystems.gamificationengine.entities.PlayerGroup; import info.interactivesystems.gamificationengine.entities.Role; import info.interactivesystems.gamificationengine.entities.goal.FinishedGoal; import info.interactivesystems.gamificationengine.entities.goal.GetPointsRule; import info.interactivesystems.gamificationengine.entities.goal.Goal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.validation.constraints.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Points class serves as a Reward-subclass, that allocates points to a player. * Points are a volatile reward which can be earned more than one time. The * awarded points are added to the current ones of a player. */ @Entity @DiscriminatorValue("RewPoints") public class Points extends VolatileReward { private static final Logger LOGGER = LoggerFactory.getLogger(Points.class); @NotNull private int amount; /** * Gets the concrete amount of points which a player can earn as a * reward. * * @return The concrete amount as int. */ public int getAmount() { return amount; } /** * Sets a specific amount of points which a player can earn as a reward. * * @param amount * The amount of points which a player can earn as int. */ public void setAmount(int amount) { this.amount = amount; } /** * Awards the player the concrete amount of points and add it to the * player's current points. After that it's checked if a PointsRule is * fulfilled so that the player can also earn another reward. * * @param player * The player who should award the points. This parameter must * not be null. * @param goalDao * The goal DAO is required to access created goals. * @param ruleDao * The rule DAO is required to access the created rules. */ @Override public void addReward(Player player, GoalDAO goalDao, RuleDAO ruleDao) { LocalDateTime finishedDate = LocalDateTime.now(); List<FinishedGoal> fGoalsList = new ArrayList<>(); List<Reward> recievedRewards = new ArrayList<>(); List<Role> matchingRoles; LOGGER.debug("Add points to player: " + amount); player.awardPoints(amount); LOGGER.debug("Points recieved -> check all points rules"); String apiKey = player.getBelongsTo().getApiKey(); List<GetPointsRule> completedPointsRules = ruleDao.getAllPointsRules(apiKey).stream().map(r -> (GetPointsRule) r).filter(r -> r.checkRule(player)) .collect(Collectors.toList()); // for each completed rule for (GetPointsRule rule : completedPointsRules) { LOGGER.debug("PointsRule: " + rule.getName()); // get goals which contain this rule for (Goal goal : goalDao.getGoalsByRule(rule, apiKey)) { if(!goal.isPlayerGroupGoal()){ //Test, if player role match with one role of the goal if (goal.getCanCompletedBy().size() > 0) { LOGGER.debug("Pointsgoal is restricted by roles"); matchingRoles = goal.getCanCompletedBy().stream().filter(r -> { if (player.getBelongsToRoles().contains(r)) { LOGGER.debug("Player has required Role to Complete Pointgoal: " + r.getName()); return true; } else { return false; } }).collect(Collectors.toList()); if (matchingRoles.size() > 0) { LOGGER.debug("Roles match for PointGoal -> proceed"); } else { LOGGER.debug("Roles don't match for Pointgoal -> Pointgoal can not be completed"); continue; } } else { LOGGER.debug("Pointgoal is not restricted by roles"); } List<FinishedGoal> oldFinishedGoals = player.getFinishedGoalsByGoal(goal); // check if goal is already finished (if not list ist empty) if(oldFinishedGoals.isEmpty()){ // goal has not yet been finished LOGGER.debug("Points Goal: is NOT on finished Goals list"); // check if points are reached if (rule.checkRule(player)) { // add goal to tempFinishedGoals list LOGGER.debug("Points Goal: Rule is completed! -> add to fGoalsList (temp)"); FinishedGoal fGoal = new FinishedGoal(); fGoal.setGoal(goal); fGoal.setFinishedDate(finishedDate); fGoalsList.add(fGoal); // for each reward -> addReward for (Reward reward : goal.getRewards()) { recievedRewards.add(reward); } } //TODO: Check, if PointsGoal is awarded again } else if(goal.isRepeatable()){ // goal has been finished but it is repeatable // check if points are reached if (rule.checkRule(player)) { // add goal to tempFinishedGoals list LOGGER.debug("Again: Points Goal: Rule is completed! -> add to fGoalsList (temp)"); FinishedGoal fGoal = new FinishedGoal(); fGoal.setGoal(goal); fGoal.setFinishedDate(finishedDate); fGoalsList.add(fGoal); // for each reward -> addReward for (Reward reward : goal.getRewards()) { recievedRewards.add(reward); } } } } } } LOGGER.debug("add finishedGoals to player"); // add Goals to finishedGaolsList if(fGoalsList.size() > 0){ player.addFinishedGoal(fGoalsList); } LOGGER.debug("add Rewards to player"); // add Rewards to rewardList for (Reward reward : recievedRewards) { reward.addReward(player, goalDao, ruleDao); } } /** * Awards the group of players the concrete amount of points and add them to * the group's current points. After that it is checked if a PointsRule is * fulfilled so that another reward can also be earned. * * @param group * The group of players which should award the points. This parameter * must not be null. * @param goalDao * The goal DAO is required to access created goals. * @param ruleDao * The rule DAO is required to access the created rules. */ @Override public void addReward(PlayerGroup group, GoalDAO goalDao, RuleDAO ruleDao) { LocalDateTime finishedDate = LocalDateTime.now(); List<FinishedGoal> fGoalsList = new ArrayList<>(); List<Reward> recievedRewards = new ArrayList<>(); List<Role> matchingRoles = new ArrayList<Role>(); LOGGER.debug("Add points to group: " + amount); group.awardPoints(amount); LOGGER.debug("Group: Points recieved -> check all points rules"); // check for organisation and check for group goal String apiKey = group.getBelongsTo().getApiKey(); List<GetPointsRule> completedPointsRules = ruleDao.getAllPointsRules(apiKey).stream().map(r -> (GetPointsRule) r).filter(r -> r.checkRule(group)) .collect(Collectors.toList()); // for each completed rule for (GetPointsRule rule : completedPointsRules) { LOGGER.debug("Group: PointsRule: " + rule.getName()); // get goals which contain this rule for (Goal goal : goalDao.getGoalsByRule(rule, apiKey)) { if(goal.isPlayerGroupGoal()){ //Test, if one player role of the group match with role of the goal if (goal.getCanCompletedBy().size() > 0) { LOGGER.debug("Pointsgoal is restricted by roles"); for(Player everyGroupPlayer : group.getPlayers()){ matchingRoles.addAll(goal.getCanCompletedBy().stream().filter(r -> { if (everyGroupPlayer.getBelongsToRoles().contains(r)) { LOGGER.debug("Player has required Role to Complete Pointgoal: " + r.getName()); return true; } else { return false; } }).collect(Collectors.toList())); } if (matchingRoles.size() > 0) { LOGGER.debug("Roles match for PointGoal -> proceed"); } else { LOGGER.debug("Roles don't match for Pointgoal -> Pointgoal can not be completed"); continue; } } else { LOGGER.debug("Pointgoal is not restricted by roles"); } List<FinishedGoal> oldFinishedGoals = group.getFinishedGoalsByGoal(goal); // check if goal is already finished (if not list is empty) if(oldFinishedGoals.isEmpty()){ // goal has not yet been finished LOGGER.debug("Group: Points Goal: is NOT on finished Goals list"); // check if points are reached if (rule.checkRule(group)) { // add goal to tempFinishedGoals list LOGGER.debug("Group: Points Goal: Rule is completed! -> add to fGoalsList (temp)"); FinishedGoal fGoal = new FinishedGoal(); fGoal.setGoal(goal); fGoal.setFinishedDate(finishedDate); fGoalsList.add(fGoal); // for each reward -> addReward for (Reward reward : goal.getRewards()) { recievedRewards.add(reward); } } } } } } LOGGER.debug("Group: add finishedGoals to group"); // add Goals to finishedGaolsList group.getFinishedGoals().addAll(fGoalsList); LOGGER.debug("Group: add Rewards to group"); // add Rewards to rewardList for (Reward reward : recievedRewards) { // reward.addReward(group, goalDao, ruleDao); //Test, if points are correct if(reward instanceof Points){ ((Points) reward).addReward(group, goalDao, ruleDao); } else { reward.addReward(group, goalDao, ruleDao); } } } }