{"id":557,"date":"2017-05-20T14:07:29","date_gmt":"2017-05-20T14:07:29","guid":{"rendered":"https:\/\/www.joseluisestevez.com\/?p=557"},"modified":"2017-07-15T06:35:50","modified_gmt":"2017-07-15T06:35:50","slug":"desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs","status":"publish","type":"post","link":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/","title":{"rendered":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS"},"content":{"rendered":"<h2>\u00bfQu\u00e9 es un WebSocket?<\/h2>\n<p>Un WebSocket es una aplicaci\u00f3n as\u00edncrona, de mensajer\u00eda bidireccional a trav\u00e9s de una \u00fanica conexi\u00f3n TCP permitiendo una comunicaci\u00f3n en ambas direcciones simult\u00e1neamente. Este\u00a0protocolo aprovecha una actualizaci\u00f3n de la cabecera HTTP, con los WebSockets de\u00a0HTML5 podemos crear aplicaciones en tiempo real con una arquitectura muy sencilla.<\/p>\n<h2>Algunos de los posibles usos de WebSocket son:<\/h2>\n<ul>\n<li>Aplicaciones de chat<\/li>\n<li>Juegos<\/li>\n<li>El comercio de acciones o de las aplicaciones financieras<\/li>\n<li>Edici\u00f3n de documentos de colaboraci\u00f3n<\/li>\n<li>Aplicaciones de redes sociales<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<h2>Desarrollo de un Juego de BlackJack usando Java WebSockets y AngularJS<\/h2>\n<p>Ahora vamos a poner a prueba los Sockets desarrollando una juego\u00a0de cartas muy conocido usando la tecnolog\u00eda Java JSR 356, AngularJS y Maven.<\/p>\n<p>Lo primero es crear\u00a0una clase que represente una carta:<\/p>\n<pre class=\"lang:java decode:true\">public class Card {\r\n\r\nprivate String rank;\r\nprivate String suit;\r\nprivate int value;\r\nprivate int sort;\r\n\r\n...\r\n}<\/pre>\n<p>Los tipos de cartas y los valores los voy a colocar en un Enum:<\/p>\n<pre class=\"lang:java decode:true\">public enum Suits {\r\n    SPADES, DIAMONDS, CLUBS, HEARTS\r\n}\r\n<\/pre>\n<pre class=\"lang:default decode:true \">public enum FaceCards {\r\n    TWO(\"2\", 2),\r\n    THREE(\"3\", 3),\r\n    FOUR(\"4\", 4),\r\n    FIVE(\"5\", 5),\r\n    SIX(\"6\", 6),\r\n    SEVEN(\"7\", 7),\r\n    EIGHT(\"8\", 8),\r\n    NINE(\"9\", 9),\r\n    TEN(\"10\", 10),\r\n    J(\"J\", 10),\r\n    Q(\"Q\", 10),\r\n    K(\"K\", 10),\r\n    A(\"A\", 11);\r\n\r\n    private final String rank;\r\n    private final int value;\r\n\r\n    private FaceCards(String rank, int value) {\r\n        this.rank = rank;\r\n        this.value = value;\r\n    }\r\n\r\n    public String getRank() {\r\n        return rank;\r\n    }\r\n\r\n    public int getValue() {\r\n        return value;\r\n    }\r\n\r\n}<\/pre>\n<p>Ahora creamos una\u00a0la clase que contenedora de cartas o un Maso este representa las 52 cartas del Juego:<\/p>\n<pre class=\"lang:default decode:true\">public class Deck {\r\n\r\n    private final List&lt;Card&gt; cards;\r\n\r\n    public Deck() {\r\n        \/\/ Crear paquete de 52 cartas\r\n        this.cards = new ArrayList&lt;&gt;();\r\n        for (Suits p : Suits.values()) {\r\n            \/\/System.out.printf(\"Suits %s\\n\", p);\r\n            int i = 0;\r\n            for (FaceCards f : FaceCards.values()) {\r\n                Card card = new Card();\r\n                card.setSuit(p.toString());\r\n                card.setRank(f.getRank());\r\n                card.setSort(i);\r\n                card.setValue(f.getValue());\r\n                \/\/System.out.printf(\"Face %s - %s\\n\", f.getRank(), f.getValue());\r\n                i++;\r\n                cards.add(card);\r\n            }\r\n        }\r\n        \r\n        \/\/ Barajear las cartas\r\n        Random random = new Random();\r\n        Collections.shuffle(cards, random);\r\n\r\n    }\r\n\r\n    public List&lt;Card&gt; getCards() {\r\n        return cards;\r\n    }\r\n    \r\n    public Card dealCard() {\r\n        return cards.remove(0);\r\n    }\r\n\r\n}<\/pre>\n<p>En el constructor se inicia el maso con\u00a052 cartas y se barajan usando colecciones de Java.<\/p>\n<p>Al jugador lo vamos a representar con la clase Player:<\/p>\n<pre class=\"lang:java decode:true \">public class Player {\r\n\r\n    private String playerName;\r\n    private double balance;\r\n<\/pre>\n<p>Una mano o una partida la vamos a representar con la Clase Hand<\/p>\n<pre class=\"lang:java decode:true \">public class Hand {\r\n\r\n    private final List&lt;Card&gt; cards;\r\n    private int score;\r\n\r\n    public Hand() {\r\n        this.cards = new ArrayList&lt;&gt;();\r\n    }\r\n\r\n    public List&lt;Card&gt; getCards() {\r\n        return cards;\r\n    }\r\n\r\n    public void addCard(Card card) {\r\n        this.cards.add(card);\r\n        if (\"A\".equalsIgnoreCase(card.getRank())) {\r\n            if (score &lt;= 10) {\r\n                score += 11;\r\n            } else {\r\n                score += 1;\r\n            }\r\n        } else {\r\n            \/\/ No es \"A\" tomar el valor de la carta\r\n            score += card.getValue();\r\n        }\r\n        \/\/ Recalcular para cambiar el valor del \"A\"\r\n        if(score &gt; 21) {\r\n            score = 0;\r\n            for (Card cardTmp : cards) {\r\n                if (\"A\".equalsIgnoreCase(cardTmp.getRank())) {\r\n                     score += 1;\r\n                } else {\r\n                    \/\/ No es \"A\" tomar el valor de la carta\r\n                    score += cardTmp.getValue();\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    public int getScore() {\r\n        return score;\r\n    }\r\n\r\n    public boolean isBlackjack() {\r\n        return score == 21;\r\n    }\r\n\r\n    public boolean isGameOver() {\r\n        return score &gt; 21;\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>En esta clase tenemos los siguientes m\u00e9todos:<\/p>\n<ul>\n<li>addCard, con este m\u00e9todo el jugador recibe una carta.<\/li>\n<li>isBlackjack, este m\u00e9todo verificar si el jugador tiene 21\u00a0puntos<\/li>\n<li>isGameOver, este m\u00e9todo valida que aun no se ha pasado de los 21 puntos<\/li>\n<\/ul>\n<p>Ahora vamos a desarrollar una clase con la l\u00f3gica del Juego:<\/p>\n<pre class=\"lang:java decode:true\">public class Blackjack21 implements Serializable {\r\n\r\n    private final Logger LOG = LoggerFactory.getLogger(Blackjack21.class);\r\n    private String gameStatus;\r\n    private Deck deck;\r\n    private Hand playerHand;\r\n    private Hand dealerHand;\r\n    private final Player player;\r\n    private double bet;\r\n    \r\n    public Blackjack21(Player player, double bet) throws Exception {\r\n        this.bet = bet;\r\n        this.player = player;\r\n        if (bet &gt; player.getBalance()) {\r\n            throw new Exception(\"El monto apostado \" + bet + \", es superior a su saldo \" + player.getBalance());\r\n        }\r\n        \/\/ Comprometer el saldo del cliente\r\n        player.decreaseBalance(bet);\r\n        \/\/ Crear una nueva mano\r\n        deck = new Deck();\r\n        \/\/ Jugador\r\n        playerHand = new Hand();\r\n        \/\/ Crupier\r\n        dealerHand = new Hand();\r\n\r\n        \/\/ Repartir primeras 4 cartas\r\n        playerHand.addCard(deck.dealCard());\r\n        dealerHand.addCard(deck.dealCard());\r\n        playerHand.addCard(deck.dealCard());\r\n        dealerHand.addCard(deck.dealCard());\r\n        gameStatus = \"OPEN\";\r\n        \/\/ Validar si el juego no ha terminado en la primera mano\r\n        if (dealerHand.isBlackjack() &amp;&amp; playerHand.isBlackjack()) {\r\n            LOG.info(\"Hay un empate entre el crupier y el jugador se retorna su apuesta inicial\");\r\n            player.increaseBalance(bet);\r\n            gameStatus = \"TIE\";\r\n        }\r\n        if (playerHand.isBlackjack()) {\r\n            LOG.info(\"El jugador tiene Blackjack! gana 3 a 2\");\r\n            player.increaseBalance(bet * 1.5);\r\n            gameStatus = \"BLACKJACK\";\r\n        }\r\n        \/\/Validar si el Crupier tiene Blackjack\r\n        if (dealerHand.isBlackjack()) {\r\n            LOG.info(\"El Crupier tiene Blackjack! el jugador pierde\");\r\n            gameStatus = \"LOSE\";\r\n        }\r\n    }\r\n    \r\n    public void hitDealer() {\r\n        if(dealerHand.getScore() &lt;=21 &amp;&amp; dealerHand.getScore() &gt;= playerHand.getScore()) {\r\n            \/\/ El crupier gana\r\n            LOG.info(\"El crupier gana! Crupier: \" +dealerHand.getScore() + \" Player: \"+playerHand.getScore());\r\n            gameStatus = \"LOSE\";\r\n        }\r\n        else {\r\n            Card card = deck.dealCard();\r\n            LOG.info(\"La carta del crupier es: \" + card);\r\n            dealerHand.addCard(card);\r\n            if(dealerHand.isGameOver()) {\r\n                \/\/ El jugador gana\r\n                LOG.info(\"El jugador gana!\");\r\n                gameStatus = \"WIN\";\r\n                player.increaseBalance(this.bet * 2);\r\n            }\r\n            if(dealerHand.isBlackjack()) {\r\n                \/\/ El crupier gana\r\n                LOG.info(\"El crupier gana! Crupier: \" +dealerHand.getScore() + \" Player: \"+playerHand.getScore());\r\n                gameStatus = \"LOSE\";\r\n            }\r\n        }\r\n        \r\n    }\r\n\r\n    public void hit() {\r\n        Card card = deck.dealCard();\r\n        LOG.info(\"La carta del jugador es: \" + card);\r\n        playerHand.addCard(card);\r\n        if (playerHand.isGameOver()) {\r\n            gameStatus = \"LOSE\";\r\n        }\r\n        if (playerHand.isBlackjack()) {\r\n            gameStatus = \"WIN\";\r\n            player.increaseBalance(this.bet * 2);\r\n        }\r\n    }\r\n\r\n    public void stand() {\r\n        if (\"OPEN\".equalsIgnoreCase(gameStatus)) {\r\n            gameStatus = \"STAND\";\r\n        }\r\n    }\r\n\r\n    public void split() {\r\n        \/\/ FIXME Tengo que implemetar el SPLIT\r\n    }\r\n\r\n    public void doubles(double bet) throws Exception {\r\n        if (bet &gt; player.getBalance()) {\r\n            throw new Exception(\"No tiene saldo para doblar la apuesta \" + bet + \" &lt; \" + player.getBalance());\r\n        }\r\n        player.decreaseBalance(bet);\r\n        this.bet += bet;\r\n        Card card = deck.dealCard();\r\n        playerHand.addCard(card);\r\n        if (playerHand.isGameOver()) {\r\n            gameStatus = \"LOSE\";\r\n        }\r\n        if (playerHand.isBlackjack()) {\r\n            gameStatus = \"WIN\";\r\n            player.increaseBalance(this.bet * 2);\r\n        }\r\n    }\r\n\r\n    public String getGameStatus() {\r\n        return gameStatus;\r\n    }\r\n\r\n    public void setGameStatus(String gameStatus) {\r\n        this.gameStatus = gameStatus;\r\n    }\r\n\r\n    public Hand getPlayerHand() {\r\n        return playerHand;\r\n    }\r\n\r\n    public Hand getDealerHand() {        \r\n        if(\"OPEN\".equalsIgnoreCase(gameStatus)) {\r\n            Hand hideHand = new Hand();\r\n            hideHand.addCard(dealerHand.getCards().get(0));\r\n            return hideHand;\r\n        }\r\n        else {\r\n            return dealerHand;\r\n        }\r\n        \r\n    }\r\n\r\n    public double getBet() {\r\n        return bet;\r\n    }\r\n\r\n    public void setBet(double bet) {\r\n        this.bet = bet;\r\n    }   \r\n}<\/pre>\n<p>Hasta este punto solo hemos realizado la l\u00f3gica del juego, ahora vamos a comenzar a implementar el socket.<\/p>\n<p>La clase SocketMessage representa el formato del mensaje con el cual vamos ha realizar la comunicaci\u00f3n cliente &#8211; servidor.<\/p>\n<pre class=\"lang:java decode:true \">public class SocketMessage {\r\n    private final Logger LOG = LoggerFactory.getLogger(SocketMessage.class);\r\n    \r\n    private String listener;\r\n    private String type;\r\n    private String message;\r\n\r\n    public String getListener() {\r\n        return listener;\r\n    }\r\n\r\n    public void setListener(String listener) {\r\n        this.listener = listener;\r\n    }\r\n\r\n    public String getMessage() {\r\n        return message;\r\n    }\r\n\r\n    public void setMessage(String message) {\r\n        this.message = message;\r\n    }\r\n\r\n    public String getType() {\r\n        return type;\r\n    }\r\n\r\n    public void setType(String type) {\r\n        this.type = type;\r\n    }\r\n\r\n    public static class MessageEncoder implements Encoder.Text&lt;SocketMessage&gt; {\r\n\r\n        @Override\r\n        public void init(EndpointConfig config) {\r\n        }\r\n\r\n        @Override\r\n        public String encode(SocketMessage message) throws EncodeException {\r\n            return Json.createObjectBuilder()\r\n                    .add(\"listener\", message.getListener())\r\n                    .add(\"type\", message.getType())\r\n                    .add(\"message\", message.getMessage()).build().toString();\r\n        }\r\n\r\n        @Override\r\n        public void destroy() {\r\n        }\r\n    }\r\n\r\n    public static class MessageDecoder implements Decoder.Text&lt;SocketMessage&gt; {\r\n\r\n        private JsonReaderFactory factory = Json.createReaderFactory(Collections.&lt;String, Object&gt;emptyMap());\r\n\r\n        @Override\r\n        public void init(EndpointConfig config) {\r\n        }\r\n\r\n        @Override\r\n        public SocketMessage decode(String str) throws DecodeException {\r\n            SocketMessage message = new SocketMessage();\r\n            JsonReader reader = factory.createReader(new StringReader(str));\r\n            JsonObject json = reader.readObject();\r\n            message.setListener(json.getString(\"listener\"));\r\n            message.setMessage(json.getString(\"message\"));\r\n            message.setType(json.getString(\"type\"));\r\n            return message;\r\n        }\r\n\r\n        @Override\r\n        public boolean willDecode(String str) {\r\n            return true;\r\n        }\r\n\r\n        @Override\r\n        public void destroy() {\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>La clase\u00a0WebSocketsDispatcher ser\u00e1 la encarga de despachar los mensajes a todos los clientes conectados al socket.<\/p>\n<pre class=\"lang:default decode:true\">import java.util.Map;\r\nimport javax.websocket.Session;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\npublic class WebSocketsDispatcher {\r\n\r\n    private final Logger LOG = LoggerFactory.getLogger(WebSocketsDispatcher.class);\r\n\r\n    public void dispatch(String listener, SocketMessage message) {\r\n        try {\r\n            if (listener == null || \"ALL\".equalsIgnoreCase(listener)) {\r\n                for (Map.Entry&lt;String, Session&gt; entry : ServerEndpoint.getListenerMap().entrySet()) {\r\n                    Session session = entry.getValue();\r\n                    session.getBasicRemote().sendObject(message);\r\n\r\n                    LOG.info(\"To: \" + message.getListener() + \";; Who: \" + message.getMessage() + \" \");\r\n                    \r\n                }\r\n            } else {\r\n\r\n                Session session = ServerEndpoint.getListenerMap().get(message.getListener());\r\n                session.getBasicRemote().sendObject(message);\r\n\r\n                LOG.info(\"To: \" + message.getListener() + \";; Who: \" + message.getMessage() + \" \");\r\n                \r\n            }\r\n\r\n        } catch (Exception e) {\r\n            LOG.error(\"Error dispatch {}\", e);\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>La clase ServerEndpoint crea un punto de acceso usando la especificaci\u00f3n de Java JSR 356<\/p>\n<pre class=\"lang:java decode:true \">@javax.websocket.server.ServerEndpoint(value = \"\/server\", encoders = {SocketMessage.MessageEncoder.class}, decoders = {SocketMessage.MessageDecoder.class})\r\npublic class ServerEndpoint {\r\n\r\n    private final Logger LOG = LoggerFactory.getLogger(ServerEndpoint.class);\r\n    private static final Set&lt;Session&gt; sessions = Collections.synchronizedSet(new HashSet&lt;Session&gt;());\r\n    private static ConcurrentHashMap&lt;String, Session&gt; sessionsMap = new ConcurrentHashMap&lt;String, Session&gt;();\r\n    private static WebSocketsDispatcher webSocketsDispatcher = new WebSocketsDispatcher();\r\n\r\n    @OnOpen\r\n    public void onOpen(Session session) {\r\n        sessions.add(session);\r\n    }\r\n\r\n    @OnClose\r\n    public void onClose(Session session) {\r\n        sessions.remove(session);\r\n    }\r\n\r\n    @OnMessage\r\n    public void onMessage(SocketMessage message, Session client)\r\n            throws IOException, EncodeException {\r\n        LOG.info(\"websockets onMessage {} \/ {} \", message.getListener(), message.getMessage());\r\n\r\n        if (\"Handshake\".equalsIgnoreCase(message.getType())) {\r\n            Player player = new Player(message.getListener(), 1000);\r\n            client.getUserProperties().put(\"player\", player);\r\n            sessionsMap.put(message.getListener(), client);\r\n        } else if (\"Bye\".equalsIgnoreCase(message.getType())) {\r\n            \/\/ Terminar sesion del usuario\r\n            try {\r\n                client.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, \"Game finished\"));\r\n            } catch (IOException e) {\r\n                throw new RuntimeException(e);\r\n            }\r\n            sessionsMap.remove(message.getListener());\r\n        } else {\r\n            \/\/String oldCmd = (String) client.getUserProperties().get(\"cmd\");\r\n            play(message, client);\r\n        }\r\n\r\n        for (Session session : sessions) {\r\n            session.getBasicRemote().sendObject(message);\r\n        }\r\n    }\r\n\r\n    private void play(SocketMessage message, Session session) {\r\n        try {\r\n            session.getUserProperties().put(\"cmd\", message.getType());\r\n\r\n            Player player = (Player) session.getUserProperties().get(\"player\");\r\n            Blackjack21 blackjack21;\r\n            \/\/ Si es dibujar\r\n            if (\"DRAW\".equalsIgnoreCase(message.getType())) {\r\n                double bet = Double.parseDouble(message.getMessage());\r\n                blackjack21 = new Blackjack21(player, bet);\r\n                session.getUserProperties().put(\"blackjack21\", blackjack21);\r\n            } else {\r\n                blackjack21 = (Blackjack21) session.getUserProperties().get(\"blackjack21\");\r\n            }\r\n\r\n            if (\"OPEN\".equalsIgnoreCase(blackjack21.getGameStatus())) {\r\n                if (\"HIT\".equalsIgnoreCase(message.getType())) {\r\n                    blackjack21.hit();\r\n                } else if (\"STAND\".equalsIgnoreCase(message.getType())) {\r\n                    blackjack21.stand();\r\n                } else if (\"SPLIT\".equalsIgnoreCase(message.getType())) {\r\n                    blackjack21.split();\r\n                } else if (\"DOUBLE\".equalsIgnoreCase(message.getType())) {\r\n                    double bet = Double.parseDouble(message.getMessage());\r\n                    blackjack21.doubles(bet);\r\n\r\n                }\r\n\r\n                ObjectMapper mapper = new ObjectMapper();\r\n                HashMap&lt;String, Object&gt; map = new HashMap&lt;&gt;();\r\n                map.put(\"blackjack21\", blackjack21);\r\n                WebSocketsDispatcher wss = ServerEndpoint.getWebSocketsDispatcher();\r\n\r\n                String json = mapper.writeValueAsString(map);\r\n                SocketMessage responseMessage = new SocketMessage();\r\n                responseMessage.setListener(message.getListener());\r\n                responseMessage.setMessage(json);\r\n                responseMessage.setType(\"CURRENT_GAME\");\r\n                wss.dispatch(message.getListener(), responseMessage);\r\n\r\n            } \r\n            \r\n            if (\"STAND\".equalsIgnoreCase(blackjack21.getGameStatus())) {\r\n                \/\/ Le toca jugar al crupier\r\n\r\n                while (\"STAND\".equalsIgnoreCase(blackjack21.getGameStatus())) {\r\n                    blackjack21.hitDealer();\r\n                    \r\n                    ObjectMapper mapper = new ObjectMapper();\r\n                    HashMap&lt;String, Object&gt; map = new HashMap&lt;&gt;();\r\n                    map.put(\"blackjack21\", blackjack21);\r\n                    WebSocketsDispatcher wss = ServerEndpoint.getWebSocketsDispatcher();\r\n                    String json = mapper.writeValueAsString(map);\r\n                    SocketMessage responseMessage = new SocketMessage();\r\n                    responseMessage.setListener(message.getListener());\r\n                    responseMessage.setMessage(json);\r\n                    responseMessage.setType(\"CURRENT_GAME\");\r\n                    wss.dispatch(message.getListener(), responseMessage);\r\n                }\r\n\r\n            }\r\n\r\n        } catch (Exception e) {\r\n            e.printStackTrace();\r\n            LOG.error(\"Play ERROR {}\", e);\r\n        }\r\n    }\r\n\r\n    public static WebSocketsDispatcher getWebSocketsDispatcher() {\r\n        return webSocketsDispatcher;\r\n    }\r\n\r\n    protected static ConcurrentHashMap&lt;String, Session&gt; getListenerMap() {\r\n        return sessionsMap;\r\n    }\r\n}\r\n<\/pre>\n<p>Ya tenemos listo el socket del lado del servidor, ahora vamos a desarrollar el cliente web usando AngularJS.<\/p>\n<p>El archivo\u00a0services.js inicia el servicio del lado del cliente usando AngularJS y WebSockets de JavaScript<\/p>\n<pre class=\"lang:js decode:true\">angular.module('starter')\r\n        .factory('WSS', function ($rootScope, API) {\r\n            var websocket;\r\n            var open = 0;\r\n            return {\r\n                isOpen: function () {\r\n                    return open;\r\n                },\r\n                subscribe: function () {\r\n                    websocket = new WebSocket(API.WSS_SOCKET);\r\n                    websocket.onopen = function (event) {\r\n                        console.log(\"ws opened\");\r\n                        open = 1;\r\n                        var message = {\r\n                            \"listener\": \"listener:\" + MASTER_ID,\r\n                            \"message\": \"subscribe\",\r\n                            \"type\": \"Handshake\"\r\n                        };\r\n                        websocket.send(JSON.stringify(message));\r\n                    };\r\n                    websocket.onmessage = function (event) {\r\n                        var json = JSON.parse(event.data);\r\n                        if (json.type === \"CURRENT_GAME\") {\r\n                             $rootScope.$broadcast('rootScope:broadcast', ['blackjack21', JSON.parse(event.data)]);\r\n                        }\r\n                    };\r\n                    websocket.onclose = function (event) {\r\n                        console.log(event.data);\r\n                    };\r\n                    websocket.onerror = function (event) {\r\n                        console.log(event.data);\r\n                    };\r\n                    return websocket;\r\n                },\r\n                closeSocket: function () {\r\n                    if (websocket !== undefined) {\r\n                        var message = {\r\n                            \"listener\": \"listener:\" + MASTER_ID,\r\n                            \"message\": \"unsubscribe\",\r\n                            \"type\": \"Bye\"\r\n                        };\r\n                        websocket.send(JSON.stringify(message));\r\n                    }\r\n                    open = 0;\r\n                },\r\n                sendMessage: function (msg, type) {\r\n                    if (websocket !== undefined) {\r\n                        var message = {\r\n                            \"listener\": \"listener:\" + MASTER_ID,\r\n                            \"message\": msg+\"\",\r\n                            \"type\": type\r\n                        };\r\n                        websocket.send(JSON.stringify(message));\r\n                    }\r\n                }\r\n                \r\n            };\r\n        });\r\n<\/pre>\n<p>Podemos ver como se implementa el metodo sendMessage que enviara los mensajes al socket y la implantaci\u00f3n de los m\u00e9todos escuchadores de WebSockets, donde podemos\u00a0resaltar el m\u00e9todo\u00a0onmessage que traduce los mensajes enviados desde el servidor y son enviados a toda la aplicaci\u00f3n usando\u00a0\u00a0$rootScope.$broadcast de AngularJS.<\/p>\n<p>El archivo constants.js creamos la variable WSS_SOCKET con el URI del Socket<\/p>\n<pre class=\"lang:default decode:true \">angular.module('starter')\r\n    .constant(\"API\", {\r\n        \"WSS_SOCKET\": \"ws:\/\/\"+ (document.location.hostname === \"\" ? \"localhost\" : document.location.hostname)+ \":\" + (document.location.port === \"\" ? \"8080\" : document.location.port) + \"\/blackjack21\/server\",\r\n    }\r\n);\r\n<\/pre>\n<p>El fichero mainController.js<\/p>\n<pre class=\"lang:js decode:true \">angular.module('starter')\r\n        .controller('MainCtrl', ['$rootScope', '$scope', '$state', '$location', '$http', 'API', 'WSS', '$cookies', function ($rootScope, $scope, $state, $location, $http, API, WSS, $cookies) {\r\n                $scope.bet = '1';\r\n                $scope.blackjack21 = {};\r\n                $rootScope.$on('rootScope:broadcast', function (event, data) {\r\n                    \/\/console.log(data);\r\n                    $scope.blackjack21 = {};\r\n                    if (data !== undefined &amp;&amp; data.length &gt; 0) {\r\n                        if ('blackjack21' === data[0]) {\r\n                            $scope.blackjack21 = (JSON.parse(data[1].message)).blackjack21;\r\n                            $scope.$apply();\r\n                        } \r\n                    }\r\n                });\r\n                if (WSS.isOpen() === 0) {\r\n                    $scope.wss = WSS.subscribe();\r\n                }\r\n\r\n                $scope.commad = function (type) {\r\n                    WSS.sendMessage($scope.bet, type);\r\n                    \/\/console.log(type);\r\n                };\r\n\r\n            }]);\r\n<\/pre>\n<p>Vamos a crear una interfaz muy simple en HTML,<\/p>\n<pre class=\"lang:default decode:true\">&lt;input type=\"text\" class=\"form-control text-right\" ng-model=\"bet\" required placeholder=\"0.00\"&gt;\r\n    \r\n    &lt;button type=\"button\" class=\"btn btn-default\" ng-disabled=\"blackjack21.gameStatus !== 'OPEN'\" ng-click=\"commad('DOUBLE')\"&gt;DOUBLE&lt;\/button&gt;\r\n    &lt;button type=\"button\" class=\"btn btn-default\" ng-disabled=\"blackjack21.gameStatus !== 'OPEN'\" ng-click=\"commad('SPLIT')\"&gt;SPLIT&lt;\/button&gt;\r\n    &lt;button type=\"button\" class=\"btn btn-default\" ng-disabled=\"blackjack21.gameStatus !== 'OPEN'\" ng-click=\"commad('HIT')\"&gt;HIT&lt;\/button&gt;\r\n    &lt;button type=\"button\" class=\"btn btn-default\" ng-disabled=\"blackjack21.gameStatus !== 'OPEN'\" ng-click=\"commad('STAND')\"&gt;STAND&lt;\/button&gt;\r\n    &lt;button type=\"button\" class=\"btn btn-default\" ng-click=\"commad('DRAW')\"&gt;DRAW&lt;\/button&gt;\r\n\r\n    &lt;h2&gt;{{blackjack21.gameStatus}}&lt;\/h2&gt;\r\n\r\n    &lt;p&gt;&lt;i&gt;{{blackjack21.playerHand.score}}&lt;\/i&gt; &lt;\/p&gt;\r\n    \r\n    &lt;div class=\"cardstack\" style=\"font-size: 18px;\"&gt;\r\n        &lt;div ng-repeat=\"cards in blackjack21.playerHand.cards\" class=\"card rank{{cards.rank}}{{cards.suit}}\"&gt;{{cards.rank}} &lt;\/div&gt;\r\n        &lt;p&gt;&lt;\/p&gt;\r\n    &lt;\/div&gt;\r\n      \r\n    &lt;p&gt;&lt;i&gt;{{blackjack21.dealerHand.score}}&lt;\/i&gt; &lt;\/p&gt;\r\n    \r\n    &lt;div class=\"cardstack\" style=\"font-size: 18px;\"&gt;\r\n        &lt;div ng-repeat=\"cards in blackjack21.dealerHand.cards\" class=\"card rank{{cards.rank}}{{cards.suit}}\"&gt;{{cards.rank}} &lt;\/div&gt;\r\n        &lt;p&gt;&lt;\/p&gt;\r\n    &lt;\/div&gt;<\/pre>\n<p>Como vemos ya tenemos una aplicaci\u00f3n en tiempo real usando Java WebSocket y AngularJS<\/p>\n<p>Si lo quieres ver en funcionamiento:<\/p>\n<p><a href=\"https:\/\/wss.araguaneybits.com:8443\/blackjack21\">https:\/\/wss.araguaneybits.com:8443\/blackjack21<\/a><\/p>\n<p>Para descargar el c\u00f3digo completo:<\/p>\n<p><a href=\"https:\/\/github.com\/jestevez\/blackjack21\">https:\/\/github.com\/jestevez\/blackjack21<\/a><\/p>\n<p>Ya tenemos un juego de Jackblack un poco B\u00e1sico nos falta implementar la funci\u00f3n SPLIT, aplicar saldos y puntos entre otras cosas. Si quieres colaborar o mejorar el c\u00f3digo eres bienvenido.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00bfQu\u00e9 es un WebSocket? Un WebSocket es una aplicaci\u00f3n as\u00edncrona, de mensajer\u00eda bidireccional a trav\u00e9s de una \u00fanica conexi\u00f3n TCP permitiendo una comunicaci\u00f3n en ambas direcciones simult\u00e1neamente. Este\u00a0protocolo aprovecha una actualizaci\u00f3n de la cabecera HTTP, con los WebSockets de\u00a0HTML5 podemos crear aplicaciones en tiempo real con una arquitectura muy sencilla. Algunos de los posibles usos [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":561,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75,8,74],"tags":[78,9,76,77],"class_list":["post-557","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angularjs","category-java","category-socket","tag-angularjs","tag-java","tag-socket","tag-websocket"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez\" \/>\n<meta property=\"og:description\" content=\"\u00bfQu\u00e9 es un WebSocket? Un WebSocket es una aplicaci\u00f3n as\u00edncrona, de mensajer\u00eda bidireccional a trav\u00e9s de una \u00fanica conexi\u00f3n TCP permitiendo una comunicaci\u00f3n en ambas direcciones simult\u00e1neamente. Este\u00a0protocolo aprovecha una actualizaci\u00f3n de la cabecera HTTP, con los WebSockets de\u00a0HTML5 podemos crear aplicaciones en tiempo real con una arquitectura muy sencilla. Algunos de los posibles usos [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/\" \/>\n<meta property=\"og:site_name\" content=\"El Blog de Jose Luis Estevez\" \/>\n<meta property=\"article:published_time\" content=\"2017-05-20T14:07:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-07-15T06:35:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png\" \/>\n\t<meta property=\"og:image:width\" content=\"572\" \/>\n\t<meta property=\"og:image:height\" content=\"621\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"yeyo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"yeyo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/\"},\"author\":{\"name\":\"yeyo\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/#\\\/schema\\\/person\\\/6a17b38fcac664fdb33a5fba8056d0ee\"},\"headline\":\"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS\",\"datePublished\":\"2017-05-20T14:07:29+00:00\",\"dateModified\":\"2017-07-15T06:35:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/\"},\"wordCount\":531,\"image\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.joseluisestevez.com\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Jackblack21.png\",\"keywords\":[\"AngularJS\",\"Java\",\"Socket\",\"WebSocket\"],\"articleSection\":[\"AngularJS\",\"Java\",\"Socket\"],\"inLanguage\":\"es\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/\",\"url\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/\",\"name\":\"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.joseluisestevez.com\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Jackblack21.png\",\"datePublished\":\"2017-05-20T14:07:29+00:00\",\"dateModified\":\"2017-07-15T06:35:50+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/#\\\/schema\\\/person\\\/6a17b38fcac664fdb33a5fba8056d0ee\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.joseluisestevez.com\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Jackblack21.png\",\"contentUrl\":\"https:\\\/\\\/www.joseluisestevez.com\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Jackblack21.png\",\"width\":572,\"height\":621},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/2017\\\/05\\\/20\\\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/www.joseluisestevez.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/#website\",\"url\":\"https:\\\/\\\/www.joseluisestevez.com\\\/\",\"name\":\"El Blog de Jose Luis Estevez\",\"description\":\"Desarrollador Senior\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.joseluisestevez.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.joseluisestevez.com\\\/#\\\/schema\\\/person\\\/6a17b38fcac664fdb33a5fba8056d0ee\",\"name\":\"yeyo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g\",\"caption\":\"yeyo\"},\"description\":\"Arquitecto de Software emprendedor con ardua experiencia en el camino de la tecnolog\u00eda.\",\"sameAs\":[\"http:\\\/\\\/www.joseluisestevez.com\"],\"url\":\"https:\\\/\\\/www.joseluisestevez.com\\\/index.php\\\/author\\\/yeyo\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/","og_locale":"es_ES","og_type":"article","og_title":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez","og_description":"\u00bfQu\u00e9 es un WebSocket? Un WebSocket es una aplicaci\u00f3n as\u00edncrona, de mensajer\u00eda bidireccional a trav\u00e9s de una \u00fanica conexi\u00f3n TCP permitiendo una comunicaci\u00f3n en ambas direcciones simult\u00e1neamente. Este\u00a0protocolo aprovecha una actualizaci\u00f3n de la cabecera HTTP, con los WebSockets de\u00a0HTML5 podemos crear aplicaciones en tiempo real con una arquitectura muy sencilla. Algunos de los posibles usos [&hellip;]","og_url":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/","og_site_name":"El Blog de Jose Luis Estevez","article_published_time":"2017-05-20T14:07:29+00:00","article_modified_time":"2017-07-15T06:35:50+00:00","og_image":[{"width":572,"height":621,"url":"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png","type":"image\/png"}],"author":"yeyo","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"yeyo","Tiempo de lectura":"12 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#article","isPartOf":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/"},"author":{"name":"yeyo","@id":"https:\/\/www.joseluisestevez.com\/#\/schema\/person\/6a17b38fcac664fdb33a5fba8056d0ee"},"headline":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS","datePublished":"2017-05-20T14:07:29+00:00","dateModified":"2017-07-15T06:35:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/"},"wordCount":531,"image":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#primaryimage"},"thumbnailUrl":"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png","keywords":["AngularJS","Java","Socket","WebSocket"],"articleSection":["AngularJS","Java","Socket"],"inLanguage":"es"},{"@type":"WebPage","@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/","url":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/","name":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS - El Blog de Jose Luis Estevez","isPartOf":{"@id":"https:\/\/www.joseluisestevez.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#primaryimage"},"image":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#primaryimage"},"thumbnailUrl":"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png","datePublished":"2017-05-20T14:07:29+00:00","dateModified":"2017-07-15T06:35:50+00:00","author":{"@id":"https:\/\/www.joseluisestevez.com\/#\/schema\/person\/6a17b38fcac664fdb33a5fba8056d0ee"},"breadcrumb":{"@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#primaryimage","url":"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png","contentUrl":"https:\/\/www.joseluisestevez.com\/wp-content\/uploads\/2017\/05\/Jackblack21.png","width":572,"height":621},{"@type":"BreadcrumbList","@id":"https:\/\/www.joseluisestevez.com\/index.php\/2017\/05\/20\/desarrollando-un-juego-de-blackjack-usando-java-websockets-y-angularjs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/www.joseluisestevez.com\/"},{"@type":"ListItem","position":2,"name":"Desarrollando un Juego de BlackJack usando Java WebSocket y AngularJS"}]},{"@type":"WebSite","@id":"https:\/\/www.joseluisestevez.com\/#website","url":"https:\/\/www.joseluisestevez.com\/","name":"El Blog de Jose Luis Estevez","description":"Desarrollador Senior","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.joseluisestevez.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Person","@id":"https:\/\/www.joseluisestevez.com\/#\/schema\/person\/6a17b38fcac664fdb33a5fba8056d0ee","name":"yeyo","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3565e9dac43d5a8d2b807866a3af3ab66eeacb68b2d28fc63b962ad40c6ef4c7?s=96&d=mm&r=g","caption":"yeyo"},"description":"Arquitecto de Software emprendedor con ardua experiencia en el camino de la tecnolog\u00eda.","sameAs":["http:\/\/www.joseluisestevez.com"],"url":"https:\/\/www.joseluisestevez.com\/index.php\/author\/yeyo\/"}]}},"_links":{"self":[{"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/posts\/557","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/comments?post=557"}],"version-history":[{"count":8,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/posts\/557\/revisions"}],"predecessor-version":[{"id":603,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/posts\/557\/revisions\/603"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/media\/561"}],"wp:attachment":[{"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/media?parent=557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/categories?post=557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.joseluisestevez.com\/index.php\/wp-json\/wp\/v2\/tags?post=557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}