eu.supersede.gr.rest.GameRest.java Source code

Java tutorial

Introduction

Here is the source code for eu.supersede.gr.rest.GameRest.java

Source

/*
   (C) Copyright 2015-2018 The SUPERSEDE Project Consortium
    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package eu.supersede.gr.rest;

import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import eu.supersede.dm.DMGame;
import eu.supersede.dm.ProcessManager;
import eu.supersede.dm.PropertyBag;
import eu.supersede.dm.datamodel.Feature;
import eu.supersede.dm.datamodel.FeatureList;
import eu.supersede.dm.methods.AHPPlayerMethod;
import eu.supersede.dm.services.EnactmentService;
import eu.supersede.fe.exception.NotFoundException;
import eu.supersede.fe.integration.ProxyWrapper;
import eu.supersede.fe.mail.SupersedeMailSender;
import eu.supersede.fe.notification.NotificationUtil;
import eu.supersede.fe.security.DatabaseUser;
import eu.supersede.gr.jpa.AHPCriteriasMatricesDataJpa;
import eu.supersede.gr.jpa.AHPGamesJpa;
import eu.supersede.gr.jpa.AHPGamesPlayersPointsJpa;
import eu.supersede.gr.jpa.AHPJudgeActsJpa;
import eu.supersede.gr.jpa.AHPPlayerMovesJpa;
import eu.supersede.gr.jpa.AHPRequirementsMatricesDataJpa;
import eu.supersede.gr.jpa.RequirementsJpa;
import eu.supersede.gr.jpa.UsersJpa;
import eu.supersede.gr.jpa.ValutationCriteriaJpa;
import eu.supersede.gr.model.HAHPCriteriasMatrixData;
import eu.supersede.gr.model.HAHPGame;
import eu.supersede.gr.model.HAHPGamePlayerPoint;
import eu.supersede.gr.model.HAHPJudgeAct;
import eu.supersede.gr.model.HAHPPlayerMove;
import eu.supersede.gr.model.HAHPRequirementsMatrixData;
import eu.supersede.gr.model.HActivity;
import eu.supersede.gr.model.Requirement;
import eu.supersede.gr.model.User;
import eu.supersede.gr.model.ValutationCriteria;
import eu.supersede.gr.utility.PointsLogic;
import eu.supersede.integration.api.datastore.fe.types.Profile;

@RestController
@RequestMapping("/ahprp/game")
public class GameRest {
    private static final String NEW_LINE = System.getProperty("line.separator");
    private static final String SEPARATOR = ";";
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss");
    private static final String ZERO_TIME = dateFormat.format(new Date(0));

    @Autowired
    private SupersedeMailSender supersedeMailSender;

    @Autowired
    private AHPGamesPlayersPointsJpa gamesPlayersPoints;

    @Autowired
    private PointsLogic pointsLogic;

    @Autowired
    private AHPGamesJpa games;

    @Autowired
    private UsersJpa users;

    @Autowired
    private RequirementsJpa requirements;

    @Autowired
    private ValutationCriteriaJpa criterias;

    @Autowired
    private AHPCriteriasMatricesDataJpa criteriasMatricesData;

    @Autowired
    private AHPRequirementsMatricesDataJpa requirementsMatricesData;

    @Autowired
    private AHPPlayerMovesJpa playerMoves;

    @Autowired
    private AHPJudgeActsJpa judgeActs;

    @Autowired
    private ProxyWrapper proxy;

    @Autowired
    private NotificationUtil notificationUtil;

    @RequestMapping(value = "id", method = RequestMethod.GET)
    public Long activit2gameId(Authentication authentication, @RequestParam Long processId,
            @RequestParam Long activityId) {
        HActivity a = DMGame.get().getJpa().activities.findOne(activityId);
        String ret = DMGame.get().getProcessManager(processId).getProperties(a).get("gameId", "");
        return Long.parseLong(ret);
    }

    @RequestMapping(value = "", method = RequestMethod.GET)
    public List<HAHPGame> getGames(Authentication authentication, @RequestParam(required = false) Boolean finished,
            @RequestParam(defaultValue = "false") Boolean byUser) {
        DatabaseUser currentUser = (DatabaseUser) authentication.getPrincipal();
        User user = users.findOne(currentUser.getUserId());
        List<HAHPGame> gs;

        if (!byUser && userIsGameMaster(currentUser)) {
            if (finished == null) {
                gs = games.findAll();
            } else {
                gs = games.findByFinished(finished);
            }
        } else {
            if (finished == null) {
                gs = games.findByPlayerContains(user);
            } else {
                gs = games.findByPlayerContainsAndFinished(user, finished);
            }

            for (HAHPGame g : gs) {
                g.setCurrentPlayer(user);
            }
        }

        return gs;
    }

    private boolean userIsGameMaster(DatabaseUser currentUser) {
        // TODO: fix for integration

        eu.supersede.integration.api.datastore.fe.types.User proxyUser = proxy.getFEDataStoreProxy().getUser(
                currentUser.getTenantId(), currentUser.getUserId().intValue(), false, currentUser.getToken());

        if (proxyUser == null) {
            throw new NotFoundException();
        }

        for (Profile p : proxyUser.getProfiles()) {
            if (p.getName().equals("DECISION_SCOPE_PROVIDER")) {
                return true;
            }
        }

        return false;
    }

    @RequestMapping(value = "/{gameId}", method = RequestMethod.GET)
    public HAHPGame getGame(Authentication authentication, @PathVariable Long gameId) {
        DatabaseUser currentUser = (DatabaseUser) authentication.getPrincipal();
        User user = users.findOne(currentUser.getUserId());
        HAHPGame g = games.findOne(gameId);

        if (g == null) {
            throw new NotFoundException();
        }

        g.setCurrentPlayer(user);

        return g;
    }

    @RequestMapping("/{gameId}/exportGameData")
    public ResponseEntity<?> exportGameData(@PathVariable Long gameId) {
        HAHPGame g = games.findOne(gameId);

        if (g == null) {
            throw new NotFoundException();
        }

        StringBuilder result = new StringBuilder();

        result.append("REQUIREMENT1").append(SEPARATOR).append("REQUIREMENT2").append(SEPARATOR).append("CRITERIA")
                .append(SEPARATOR).append("USER").append(SEPARATOR).append("VOTE").append(SEPARATOR)
                .append("VOTE_TIME").append(NEW_LINE);

        for (HAHPRequirementsMatrixData rmd : g.getRequirementsMatrixData()) {
            for (HAHPPlayerMove pm : rmd.getPlayerMoves()) {
                if (pm.getPlayed()) {
                    result.append(rmd.getRowRequirement().getName()).append(SEPARATOR)
                            .append(rmd.getColumnRequirement().getName()).append(SEPARATOR)
                            .append(rmd.getCriteria().getName()).append(SEPARATOR).append(pm.getPlayer().getName())
                            .append(SEPARATOR).append(pm.getValue()).append(SEPARATOR);

                    if (pm.getPlayedTime() == null) {
                        result.append(ZERO_TIME);
                    } else {
                        result.append(dateFormat.format(pm.getPlayedTime()));
                    }

                    result.append(NEW_LINE);
                }
            }
        }

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(new MediaType("text", "csv", Charset.forName("utf-8")));
        httpHeaders.setContentDispositionFormData("attachment", "dmp_" + g.getGameId() + "_data.csv");

        return new ResponseEntity<>(result.toString(), httpHeaders, HttpStatus.OK);
    }

    @RequestMapping("/{gameId}/exportGameResults")
    public ResponseEntity<?> exportGameResults(@PathVariable Long gameId) {
        HAHPGame g = games.findOne(gameId);

        if (g == null) {
            throw new NotFoundException();
        }

        StringBuilder result = new StringBuilder();

        result.append("REQUIREMENT").append(SEPARATOR).append("RESULT").append(NEW_LINE);
        List<HAHPCriteriasMatrixData> criteriasMatrixDataList = criteriasMatricesData.findByGame(g);
        Map<String, Double> rs = AHPRest.CalculateAHP(g.getCriterias(), g.getRequirements(),
                criteriasMatrixDataList, g.getRequirementsMatrixData());

        for (Entry<String, Double> e : rs.entrySet()) {
            result.append(requirements.getOne(new Long(e.getKey())).getName()).append(SEPARATOR)
                    .append(e.getValue()).append(NEW_LINE);
        }

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(new MediaType("text", "csv", Charset.forName("utf-8")));
        httpHeaders.setContentDispositionFormData("attachment", "dmp_" + g.getGameId() + "_results.csv");

        return new ResponseEntity<>(result.toString(), httpHeaders, HttpStatus.OK);
    }

    @RequestMapping(value = "/end/{gameId}", method = RequestMethod.PUT)
    public void setGameFinished(@PathVariable Long gameId) {
        HAHPGame g = games.findOne(gameId);
        g.setFinished(true);
        games.save(g);

        // set all judgeActs voted and playerMoves played
        List<HAHPRequirementsMatrixData> rmdList = g.getRequirementsMatrixData();

        for (int i = 0; i < rmdList.size(); i++) {
            HAHPRequirementsMatrixData rmd = rmdList.get(i);
            List<HAHPJudgeAct> jaList = judgeActs.findByRequirementsMatrixData(rmd);
            List<HAHPPlayerMove> pmList = playerMoves.findByRequirementsMatrixData(rmd);

            for (int j = 0; j < jaList.size(); j++) {
                jaList.get(j).setVoted(true);
                judgeActs.save(jaList.get(j));
            }

            for (int k = 0; k < pmList.size(); k++) {
                pmList.get(k).setPlayed(true);
                playerMoves.save(pmList.get(k));
            }
        }
    }

    @RequestMapping(value = "/enact/{gameId}", method = RequestMethod.PUT)
    public void doEnactGame(Authentication authentication, @PathVariable Long gameId,
            @RequestParam("useIF") Boolean useIf) {
        System.out.println("Sending requirements fo enactment - useIF = " + useIf.booleanValue());

        String tenant = ((DatabaseUser) authentication.getPrincipal()).getTenantId();
        HAHPGame g = games.findOne(gameId);
        double max = 1;
        Map<String, Double> rs = AHPRest.CalculateAHP(g.getCriterias(), g.getRequirements(),
                criteriasMatricesData.findByGame(g), g.getRequirementsMatrixData());

        for (Double d : rs.values()) {
            if (d > max) {
                max = d;
            }
        }

        FeatureList list = new FeatureList();

        for (Requirement r : g.getRequirements()) {
            Feature feature = new Feature();
            feature.setName(r.getName());
            feature.setPriority(6 - ((int) (1 + ((rs.get("" + r.getRequirementId()) / max) * 5))));
            feature.setId("" + r.getRequirementId());
            System.out.println("Added feature with id: " + feature.getId());
            list.list().add(feature);
        }

        EnactmentService.get().send(list, (useIf != null ? useIf.booleanValue() : true), tenant);
    }

    @RequestMapping(value = "", method = RequestMethod.POST)
    public ResponseEntity<?> createGame(Authentication auth, @RequestBody HAHPGame game,
            @RequestParam(required = true) String criteriaValues, @RequestParam Long processId)
            throws JsonParseException, JsonMappingException, IOException {
        TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {
        };

        ObjectMapper mapper = new ObjectMapper();
        Map<String, Map<String, Integer>> cvs = mapper.readValue(criteriaValues, typeRef);
        game.setStartTime(new Date());
        // re-attach detached requirements
        List<Requirement> rs = game.getRequirements();

        //        if( System.currentTimeMillis() > 0 )
        //           throw new RuntimeException("");

        for (int i = 0; i < rs.size(); i++) {
            rs.set(i, requirements.findOne(rs.get(i).getRequirementId()));
        }
        // re-attach detached users
        List<User> us = game.getPlayers();

        for (int i = 0; i < us.size(); i++) {
            us.set(i, users.findOne(us.get(i).getUserId()));
        }
        // re-attach detached criterias
        List<ValutationCriteria> cs = game.getCriterias();

        for (int i = 0; i < cs.size(); i++) {
            cs.set(i, criterias.findOne(cs.get(i).getCriteriaId()));
        }

        Object user = auth.getPrincipal();

        if (user instanceof DatabaseUser) {
            DatabaseUser dbUser = (DatabaseUser) user;
            User u = users.getOne(dbUser.getUserId());
            game.setCreator(u);

            // add points for the creation of a game
            pointsLogic.addPoint(u, -3l, -1l);
        }

        if (cs.size() < 2) {
            throw new RuntimeException("Not enough criteria");
        }
        if (us.size() < 1) {
            throw new RuntimeException("Not enough players");
        }
        if (rs.size() < 2) {
            throw new RuntimeException("Not enough requirements");
        }

        game.setFinished(false);
        game = games.save(game);

        ProcessManager mgr = DMGame.get().getProcessManager(processId);
        {
            HActivity a = mgr.createActivity(AHPPlayerMethod.NAME,
                    ((DatabaseUser) auth.getPrincipal()).getUserId());
            a.setUserId(null); // do this to avoid showing it in the supervisor pending activities list
            PropertyBag bag = mgr.getProperties(a);
            bag.set("gameId", "" + game.getGameId());
        }

        for (int i = 0; i < cs.size() - 1; i++) {
            for (int j = i + 1; j < cs.size(); j++) {
                HAHPCriteriasMatrixData cmd = new HAHPCriteriasMatrixData();
                cmd.setGame(game);
                cmd.setRowCriteria(cs.get(j));
                cmd.setColumnCriteria(cs.get(i));
                String c1Id = cs.get(j).getCriteriaId().toString();
                String c2Id = cs.get(i).getCriteriaId().toString();

                if (cvs.containsKey(c1Id) && cvs.get(c1Id).containsKey(c2Id)) {
                    cmd.setValue(new Long(cvs.get(c1Id).get(c2Id)));
                } else {
                    cmd.setValue(new Long(cvs.get(c2Id).get(c1Id)));
                }

                criteriasMatricesData.save(cmd);
            }
        }

        for (int c = 0; c < cs.size(); c++) {
            for (int i = 0; i < rs.size() - 1; i++) {
                for (int j = i + 1; j < rs.size(); j++) {
                    HAHPRequirementsMatrixData rmd = new HAHPRequirementsMatrixData();
                    rmd.setGame(game);
                    rmd.setRowRequirement(rs.get(j));
                    rmd.setColumnRequirement(rs.get(i));
                    rmd.setCriteria(cs.get(c));
                    rmd.setValue(-1l);
                    requirementsMatricesData.save(rmd);

                    for (int p = 0; p < us.size(); p++) {
                        HAHPPlayerMove pm = new HAHPPlayerMove();
                        pm.setPlayer(us.get(p));
                        pm.setRequirementsMatrixData(rmd);
                        pm.setPlayed(false);
                        playerMoves.save(pm);
                    }

                    HAHPJudgeAct ja = new HAHPJudgeAct();
                    ja.setVoted(false);
                    ja.setRequirementsMatrixData(rmd);
                    judgeActs.save(ja);
                }
            }
        }

        DatabaseUser currentUser = (DatabaseUser) auth.getPrincipal();

        for (User u : us) {
            eu.supersede.integration.api.datastore.fe.types.User proxyUser = proxy.getFEDataStoreProxy()
                    .getUser(currentUser.getTenantId(), u.getUserId().intValue(), true, currentUser.getToken());
            // creation of email for the players when a game is started
            supersedeMailSender.sendEmail("New Decision Making Process",
                    "Hi " + proxyUser.getFirst_name() + " " + proxyUser.getLast_name()
                            + ", this is an automatically generated mail. You have just been invited to "
                            + "participate in a prioritization process.",
                    proxyUser.getEmail());

            notificationUtil.createNotificationForUser(proxyUser.getEmail(),
                    "A new decision making process has been created, are you ready to vote?",
                    "supersede-dm-app/ahprp/player_games");

            // create a GamePlayerPoint for this game and for all the players in the game
            HAHPGamePlayerPoint gpp = new HAHPGamePlayerPoint();
            gpp.setGame(game);
            gpp.setUser(u);
            gpp.setPoints(0l);
            gamesPlayersPoints.save(gpp);

            HActivity a = mgr.createActivity(AHPPlayerMethod.NAME, u.getUserId());
            PropertyBag bag = mgr.getProperties(a);
            bag.set("gameId", "" + game.getGameId());
        }

        // FIXME
        //        notificationUtil.createNotificationsForProfile("OPINION_NEGOTIATOR",
        //                "A new decision making process has been created, you are in charge to take decisions",
        //                "supersede-dm-app/ahprp/judge_games");

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setLocation(ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(game.getGameId()).toUri());
        return new ResponseEntity<>(game.getGameId(), httpHeaders, HttpStatus.CREATED);
    }

}