package com.matheusjardimb; import java.util.ArrayList; import java.util.Date; import java.util.Random; import com.matheusjardimb.exception.InvalidPlayerNameException; import com.matheusjardimb.exception.PlayerLimitReachedException; public class PlayerFactory { private static final int PLAYERS_LIMIT = 100; private static final ArrayList<Player> players = new ArrayList<Player>(); private static final ArrayList<Match> matches = new ArrayList<Match>(); private PlayerFactory() { } public static Player registerPlayer(String name) throws PlayerLimitReachedException, InvalidPlayerNameException { if (players.size() >= PLAYERS_LIMIT) { throw new PlayerLimitReachedException("Player registration limit reached"); } if (name == null || name.isEmpty()) { throw new InvalidPlayerNameException("Player name can't be null"); } boolean b = playerExist(name); if (b) { throw new InvalidPlayerNameException("Player name already registered"); } int id = players.size() + 1; Player player = new Player(name, id); players.add(player); return player; } private static boolean playerExist(String name) { for (Player p : players) { if (p.getName().equals(name)) { return true; } } return false; } private static Player playerExist(Integer id) { for (Player p : players) { if (p.getId() == id) { return p; } } return null; } public static class Player { private static final long TIMEOUT = 2 * 60 * 1000; private static Random randomNumber = new Random(); private static int nextHalf_id = 1; private String name; private Date created_at; private int id; private Player(String name, int id) { super(); this.name = name; this.created_at = new Date(); this.id = getNextId(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getCreated_at() { return created_at; } public int getId() { return id; } private int getNextId() { return (nextHalf_id++)<<8 | randomNumber.nextInt(256); } // TODO review/test this method @Override public boolean equals(Object obj) { if (!(obj instanceof Player)) { return false; } Player p = (Player) obj; return p.getId() == getId(); } public boolean hasExpired() { Date now = new Date(); long diff = now.getTime() - getCreated_at().getTime(); return diff > TIMEOUT; } } public static Integer assignToMatch(Integer id) { // TODO /* * Retorna: -2 (tempo de espera esgotado), -1 (erro), 0 (ainda não há * partida), 1 (sim, há partida e o jogador inicia jogando com “X”) ou 2 * (sim, há partida e o jogador é o segundo a jogar, usando “O”) */ Player p = playerExist(id); if (p == null) { return Match.ERROR; } // User is signed into a match? for (Match match : matches) { if (p.equals(match.getO())) { if (match.hasX()) { return Match.O; } return Match.NO_MATCH; } if (p.equals(match.getX())) { if (match.hasO()) { return Match.X; } return Match.NO_MATCH; } } if (p.hasExpired()) { return Match.TIMEOUT; } // Assign user to a match for (Match match : matches) { if (!match.hasO()) { match.setO(p); if (match.hasX()) { return Match.O; } return Match.NO_MATCH; } if (!match.hasX()) { match.setX(p); if (match.hasO()) { return Match.X; } return Match.NO_MATCH; } } Match match = new Match(); match.setX(p); matches.add(match); return Match.NO_MATCH; } public static String getBoard(Integer id) { Player p = playerExist(id); Match match = getMatch(p); if (match == null) { return null; } return match.getBoardToString(); } private static Match getMatch(Player p) { for (Match match : matches) { if (p.equals(match.getO()) || p.equals(match.getX())) { return match; } } return null; } public static String getOpponent(Integer id) { Player p = playerExist(id); if (p != null) { Match match = getMatch(p); if (match != null) { if (p.equals(match.getO())) { return match.hasX() ? match.getX().getName() : ""; } if (p.equals(match.getX())) { return match.hasO() ? match.getO().getName() : ""; } } } return null; } public static int isPlayerTurn(Integer id) { Player p = playerExist(id); if (p == null) { return Match.ERROR; } Match match = getMatch(p); if (match == null) { return Match.ERROR; } int winner = match.getWinner(); if (winner != Match.NONE) { if (winner == Match.O && match.getO().equals(p)) { return Match.WINNER; } else if (winner == Match.X && match.getX().equals(p)) { return Match.WINNER; } else if (winner == Match.DRAW) { return Match.DRAW; } return Match.LOOSER; } if ((match.getLastPlayer() == Match.O && match.getO().getId() == p.getId()) || (match.getLastPlayer() == Match.X && match.getX().getId() == p.getId())) { return Match.NO; } return Match.YES; } public static int setPosition(Integer id, Integer pos) { /** * TODO * * Retorna: 2 (partida encerrada, o que ocorrerá caso o jogador demore * muito para enviar a sua jogada e ocorra o time-out de 30 segundos * para envio de jogadas), * * 1 (tudo certo), * * 0 (posição ocupada) * * -1 (erro) */ Player p = playerExist(id); if (p == null) { return Match.ERROR; } Match match = getMatch(p); if (match == null) { return Match.ERROR; } int res = match.setPosition(p, pos); return res; } }