/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package ch.bfh.jass.controller;
import ch.bfh.jass.exceptions.*;
import ch.bfh.jass.game.Card;
import ch.bfh.jass.game.Game;
import ch.bfh.jass.game.JassCardSet;
import ch.bfh.jass.game.Player;
import ch.bfh.jass.interfaces.IPlayer;
import ch.bfh.jass.model.EntityManager;
import ch.bfh.jass.model.FinishedGame;
import ch.bfh.jass.model.MessageFactory;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.faces.event.AjaxBehaviorEvent;
/**
* @author David Baumgartner <baumd9@bfh.ch>, Fabian Schneider <schnf6@bfh.ch>
* @version 1.0
*/
@SessionScoped
@ManagedBean
public class GameBean implements Serializable {
/**
* The player object of the session
*/
@ManagedProperty(value = "#{mainBean.player}")
private IPlayer player = new Player();
/**
* EntityManager singleton
*/
@ManagedProperty(value = "#{mainBean.entityManager}")
private EntityManager entityManager;
/**
* The game in which the player is
*/
private Game game;
/**
* Is the player on a place in the game
*/
private boolean hasPlace = false;
/**
* Is the player game administrator of the game
*/
private boolean gameAdmin = false;
/**
* Set the player
* @param player
*/
public void setPlayer(IPlayer player) {
this.player = player;
}
/**
* @return true if the game is started
*/
public boolean isStarted() {
if (this.game != null) {
return this.game.isStarted();
}
return false;
}
/**
* @return the handcards of the player
*/
public List<Card> getPlayerCards() {
return this.player.getHandCards();
}
/**
* @return a list of all games which you can join
*/
public Game[] getGameOverview() {
List<Game> games = new ArrayList<Game>(this.entityManager.getGames().values());
List<Game> newGames = new ArrayList<Game>();
Collections.reverse(games);
for (Game game_a : games) {
if (game_a.getPlayerCount() < 4) {
newGames.add(game_a);
}
}
Game[] gameOverview = new Game[newGames.size()];
return newGames.toArray(gameOverview);
}
/**
* Join a game
* @param e ActionEvent
*/
public void join(ActionEvent e) {
try {
this.game = this.entityManager.getGameByID(e.getComponent().getAttributes().get("title").toString());
} catch (GameNotExistsException ex) {
MessageFactory.error("gameDoesNotExist");
}
}
/**
* Create a new game in which you are administrator
* @return
*/
public String newGame() {
if (this.game != null) {
MessageFactory.error("alreadyInAGame");
} else {
try {
this.game = new Game(this.player);
this.entityManager.addGame(this.game);
this.hasPlace = true;
this.gameAdmin = true;
} catch (PlayerAlreadyInGameException ex) {
MessageFactory.error("playerAlreadyInGame");
} catch (PlaceTakenException ex) {
MessageFactory.error("placeTaken");
} catch (PlaceDoesNotExistException ex) {
MessageFactory.error("placeDoesNotExist");
}
}
return "game";
}
/**
* Start the game
* @return
*/
public String start() {
try {
this.game.start(player);
} catch (YouMustNotException ex) {
MessageFactory.error("mustNotStartGame");
}
this.playAI();
return "game";
}
/**
* Leave the game
* @return
*/
public String leave() {
this.finishGame(this.game);
this.game = null;
this.gameAdmin = false;
this.hasPlace = false;
this.player.clearHand();
this.player.setPlace(0);
return "game";
}
/**
* Listener for card clicks, plays the card which was clicked
* @param event
*/
public void cardClickListener(AjaxBehaviorEvent event) {
try {
String cardID = event.getComponent().getId();
String[] card = cardID.split("_");
this.game.play(new Card(JassCardSet.CardColor.valueOf(card[0]), JassCardSet.CardRank.valueOf(card[1])));
this.playAI();
} catch (NotYourCardException ex) {
MessageFactory.error("notYourTurn");
} catch (IsNotPlayableException ex) {
MessageFactory.error("cardNotPlayable");
} catch (GameOverException ex) {
this.finishGame(this.game);
} catch (NoTrumpfSetException ex) {
MessageFactory.error("noTrumpfSet");
}
}
/**
* Listener for clicks on the place you want join, takes the place if it's free
* @param event
*/
public void placeClickListener(AjaxBehaviorEvent event) {
try {
String placeID = event.getComponent().getId();
String[] place = placeID.split("_");
this.game.addPlayer(this.player, Integer.parseInt(place[1]));
this.hasPlace = true;
} catch (PlayerAlreadyInGameException ex) {
MessageFactory.error("playerAlreadyInGame");
} catch (PlaceTakenException ex) {
MessageFactory.error("placeTaken");
} catch (PlaceDoesNotExistException ex) {
MessageFactory.error("placeDoesNotExist");
}
}
/**
* Set the entityManager
* @param entityManager
*/
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
/**
* @return the trump of the game as a string
*/
public String getTrumpf() {
if (this.game == null || this.game.getTrumpf() == null) {
return MessageFactory.getText("gameNoTrumpf");
} else {
return this.game.getTrumpf().toString();
}
}
/**
* Listener for trump choose, sets the trump for the new round
* @param event
*/
public void trumpfClickListener(AjaxBehaviorEvent event) {
try {
this.game.setTrumpf(JassCardSet.CardColor.valueOf(event.getComponent().getId()), this.player);
} catch (YouMustNotSetTrumpfException ex) {
MessageFactory.error("mustNotSetTrumpf");
}
}
/**
* @return true if you have the permission to set the trump
*/
public boolean getCanSetTrumpf() {
if (this.game != null && this.game.isStarted()) {
if (this.game.getTrumpf() == null) {
if (!this.game.isTrumpfMoved()) {
if (this.game.getCurrentPlayer().equals(this.player)) {
return true;
}
} else {
if (this.game.getCurrentPlayer().equals(this.game.getTeamPlayer(this.player))) {
return true;
}
}
}
}
return false;
}
/**
* Moves the permission to set the trump to your teammate
* @return
*/
public String moveTrumpf() {
if (this.getCanSetTrumpf() && !this.game.isTrumpfMoved()) {
try {
this.game.moveTrumpf();
} catch (YouMustNotSetTrumpfException ex) {
MessageFactory.error("mustNotSetTrumpf");
}
}
return "game";
}
/**
* @return true if the trump set permission is moved to the teammate
*/
public boolean isTrumpfMoved() {
return this.game.isTrumpfMoved();
}
/**
* @return a list of the cards which are on the table
*/
public Card[] getTable() {
if (this.game == null) {
return new Card[0];
}
Card[] cards = this.game.getTable().getTableCardsArray();
Card[] newCards = new Card[cards.length];
int place = this.player.getPlace();
for (int i = 0; i < cards.length; i++) {
newCards[i] = cards[place];
place++;
if (place >= cards.length) {
place = 0;
}
}
return newCards;
}
/**
* @return an array of the players which are in the game, array is rotated so that you are on position 0
*/
public IPlayer[] getPlayers() {
if (this.game == null) {
return new IPlayer[0];
}
List<IPlayer> players = this.game.getPlayers();
IPlayer[] newPlayers = new IPlayer[players.size()];
int place = this.player.getPlace();
for (int i = 0; i < players.size(); i++) {
newPlayers[i] = players.get(place);
place++;
if (place >= players.size()) {
place = 0;
}
}
return newPlayers;
}
/**
* trigger the AIPlayer that he plays a card or chooses the trump
*/
public void playAI() {
try {
if (this.game.getCurrentPlayer().isAI() && !this.game.hasWinner()) {
this.game.playAI();
this.playAI();
}
} catch (GameOverException ex) {
this.finishGame(this.game);
}
}
/**
* @return a list with arrays of the team points of each round
*/
public List<int[]> getTeamPoints() {
if (this.game == null) {
return new ArrayList<int[]>();
}
return this.game.getTeamPoints();
}
/**
* @return an array of the total team points
*/
public int[] getTotalTeamPoints(){
int[] points = new int[this.game.getTeams().size()];
if(this.game == null){
return points;
}
for(int[] roundPoints : this.getTeamPoints()){
for(int i = 0; i < this.game.getTeams().size(); i++){
points[i] += roundPoints[i];
}
}
return points;
}
/**
* @return true if the player has taken a place
*/
public boolean isHasPlace() {
return this.hasPlace;
}
/**
* Set if the placer has a place
* @param hasPlace
*/
public void setHasPlace(boolean hasPlace) {
this.hasPlace = hasPlace;
}
/**
* @return true if the player is game administrator
*/
public boolean isGameAdmin() {
return this.gameAdmin;
}
/**
* @return the username of the player who is at the turn
*/
public String getCurrentUsername() {
if (this.game == null) {
return "None";
}
return this.game.getCurrentPlayer().getUsername();
}
/**
* @return an array with the names of the winners
*/
private Object[] getWinnerList() {
if (this.game == null) {
return new Object[0];
}
List<IPlayer> winnerlist = this.game.getWinnerList();
String[] winnerNames = new String[winnerlist.size()];
for (int i = 0; i < winnerlist.size(); i++) {
winnerNames[i] = winnerlist.get(i).getUsername();
}
return winnerNames;
}
/**
* @return true if the game has a winner
*/
public boolean isHasWinner() {
try {
if (this.game == null) {
return false;
}
return this.game.hasWinner();
} catch (GameOverException ex) {
this.finishGame(this.game);
return true;
}
}
/**
* Force finish the actual game
* @param game
*/
private void finishGame(Game game) {
if (game.isStarted()) {
try {
this.entityManager.writeGameResults(game);
} catch (SQLException ex) {
MessageFactory.error("couldntWriteResToDb");
System.out.println(ex.getMessage());
}
} else if (!game.isFinished()) {
this.entityManager.removeGame(game);
}
game.forceGameEnd();
}
/**
* @return the game
*/
public Game getGame() {
return this.game;
}
/**
* @return the winner message or a game aborted message
*/
public String getWinnerMessage() {
if (this.game.isFinished() && this.game.isStarted()) {
FacesMessage message = MessageFactory.getMessage(FacesMessage.SEVERITY_INFO, "gameOver", this.getWinnerList());
return message.getSummary();
} else {
return MessageFactory.getText("gameAborted");
}
}
/**
* @param place
* @return true if the place given is empty
*/
public boolean isEmptyPlace(int place){
System.out.println(place);
for(IPlayer inGamePlayer : this.getPlayers()){
if(inGamePlayer.getPlace() == place){
return false;
}
}
return true;
}
}