package net.yura.lobby.database;
import java.util.Collection;
import java.util.Set;
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.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import net.yura.lobby.model.Game;
/**
* @author Yura Mamyrin
*/
@Entity
@Table(name="games")
public class GameRoom implements Comparable<GameRoom> {
private GameTypeRoom gameTypeRoom;
private final Game game;
private byte[] gameData;
/**
* this is to avoid 2 modifications to the game at the same time
* as that may cause the game to never start as 2 people can join it at the same time
*/
@Version int version;
public GameRoom() {
game = new Game();
}
public GameRoom(Game game) {
this.game = game;
if (getMaxPlayers() <= 0) {
throw new IllegalStateException("can not make a game room with no players: "+getMaxPlayers() );
}
if (!getUsers().isEmpty()) {
throw new IllegalStateException("why are there players already here? "+game+" "+getUsers() );
}
if (getId() != null) {
throw new IllegalArgumentException("creating a new game, but it already has a id "+getId());
}
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable=false)
public Integer getId() {
int id = game.getId();
return id==-1?null:id;
}
public void setId(Integer id) {
game.setId(id==null?-1:id);
}
@Column(name="name", nullable=false, length=100)
public String getName() {
return game.getName();
}
public void setName(String name) {
game.setName(name);
}
@Column(name="options", nullable=false, length=100)
public String getOptions() {
return game.getOptions();
}
public void setOptions(String options) {
game.setOptions(options);
}
@Column(name="max_players", nullable=false)
public int getMaxPlayers() {
return game.getMaxPlayers();
}
public void setMaxPlayers(int maxPlayers) {
game.setMaxPlayers(maxPlayers);
}
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="game_type_id", nullable=false)
public GameTypeRoom getGameTypeRoom() {
return gameTypeRoom;
}
public void setGameTypeRoom(GameTypeRoom gtr) {
gameTypeRoom = gtr;
game.setType( gameTypeRoom==null?null:gameTypeRoom.getGameType() );
}
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
name = "game_users",
joinColumns = { @JoinColumn(name="game_id") },
inverseJoinColumns = { @JoinColumn(name="user_id") },
uniqueConstraints = {@UniqueConstraint(columnNames = {"game_id", "user_id"})} )
public Set<User> getUsers() {
return game.getPlayers();
}
public void setUsers(Set<User> usrs) {
game.setPlayers(usrs);
}
public boolean hasUser(String username) {
for (User user:getUsers()) {
if (username.equals(user.getName())) {
return true;
}
}
return false;
}
@Column(name="timeout", nullable=true)
public int getTimeout() {
return game.getTimeout();
}
public void setTimeout(int timeout) {
game.setTimeout(timeout);
}
// this is a waste of memory to load this every time we get a list of games
//@javax.persistence.Basic(fetch = FetchType.EAGER)
@Column(name="game_date", nullable=true)
public byte[] getGameData() {
return gameData;
}
public void setGameData(byte[] gameData) {
this.gameData = gameData;
}
@Transient
public int getNumOfPlayers() {
return getUsers().size();
}
@Transient
public Game getGame() {
getUsers(); // HACK
return game;
}
public void joinGame(User player) {
if (player==null) {
throw new NullPointerException("why you pass null to joinGame(User)?");
}
Collection<User> players = getUsers();
if (players.contains(player)) {
throw new IllegalStateException("can not join game, you are already in it");
}
if (game.getNumOfPlayers() >= getMaxPlayers()) {
throw new IllegalStateException("no room to join game "+game.getNumOfPlayers()+"/"+getMaxPlayers() );
}
players.add( player );
player.getGames().add(this);
}
public void leaveGame(User player) {
if (player==null) {
throw new NullPointerException("why you pass null?");
}
Collection<User> players = getUsers();
if (!players.contains(player)) {
throw new IllegalStateException("you are not in this game so can not leave");
}
players.remove(player);
player.getGames().remove(this);
}
@Override
public int compareTo(GameRoom o) {
return game.compareTo(o.game);
}
@Override
public String toString() {
return "Game{"+getId()+" "+getName()+" "+getNumOfPlayers()+"/"+getMaxPlayers()+"}";
}
}