diff --git a/src/main/java/com/bernard/nodecames/HttpController.java b/src/main/java/com/bernard/nodecames/HttpController.java index 3ecdf81..c6a6050 100644 --- a/src/main/java/com/bernard/nodecames/HttpController.java +++ b/src/main/java/com/bernard/nodecames/HttpController.java @@ -9,8 +9,13 @@ import org.springframework.web.servlet.view.RedirectView; import com.bernard.nodecames.game.GameManager; +import lombok.AllArgsConstructor; + +@AllArgsConstructor @Controller public class HttpController { + + GameManager gm; @GetMapping("/") public String index() { @@ -24,7 +29,7 @@ public class HttpController { @GetMapping("/create-room") public RedirectView createRoom() { - UUID uuid = GameManager.newGrid(); + UUID uuid = gm.newGrid(); return new RedirectView("/room/"+uuid.toString()+"/grid"); } } diff --git a/src/main/java/com/bernard/nodecames/frontend/WebSocketController.java b/src/main/java/com/bernard/nodecames/frontend/WebSocketController.java index 544410e..9aed68a 100644 --- a/src/main/java/com/bernard/nodecames/frontend/WebSocketController.java +++ b/src/main/java/com/bernard/nodecames/frontend/WebSocketController.java @@ -1,30 +1,56 @@ package com.bernard.nodecames.frontend; -import org.springframework.beans.factory.annotation.Autowired; +import java.util.Map; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import com.bernard.nodecames.game.GameManager; +import com.bernard.nodecames.model.Card; import com.bernard.nodecames.model.Grid; +import com.bernard.nodecames.model.Card.Color; +import com.bernard.nodecames.model.Grid.Phase; +import lombok.AllArgsConstructor; import tools.jackson.databind.JsonNode; import tools.jackson.databind.node.JsonNodeFactory; +import tools.jackson.databind.node.ObjectNode; @Controller +@AllArgsConstructor public class WebSocketController { private static final JsonNodeFactory jsn = JsonNodeFactory.instance; - @Autowired - GameManager gm; + private GameManager gm; + private SimpMessagingTemplate template; + + public void publishNewPhase(Grid g) { + this.template.convertAndSend( + "/topic/new-phase", + g.getPhase().name().toLowerCase() + ); + } + public void publishCardUpdateToPlayer(Grid g, int cardIndex, char player) { + Card c = g.getCards()[cardIndex]; + this.template.convertAndSend( + "/topic/update-card/" + Character.toLowerCase(player), + gm.cardData(c, player), + Map.of("cardIndex", cardIndex) + ); + } + public void publishCardUpdate(Grid g, int cardIndex) { + publishCardUpdateToPlayer(g, cardIndex, 'A'); + publishCardUpdateToPlayer(g, cardIndex, 'B'); + } @GetMapping("/room/{id}/game/{player}") public Object grid(@PathVariable("id") String gridId, @PathVariable("player") String playerStr) { @@ -36,9 +62,9 @@ public class WebSocketController { else throw new IllegalArgumentException("Unknown player type"); - Grid g = GameManager.findGrid(gridId); + Grid g = gm.findGrid(gridId); - return new ResponseEntity<>(GameManager.gridData(g, player), HttpStatus.OK); + return new ResponseEntity<>(gm.gridData(g, player), HttpStatus.OK); } @MessageMapping("submit-hint") @@ -47,10 +73,11 @@ public class WebSocketController { String hint = content.asObject().get("hint").stringValue(); int wordCount = content.asObject().get("hintWordCount").intValue(); - Grid g = GameManager.findGrid(roomId); + Grid g = gm.findGrid(roomId); gm.proposeHint(g, player.charAt(0), hint, wordCount); - + content.asObject().set("player", jsn.stringNode(player)); + this.publishNewPhase(g); return content; } @@ -59,17 +86,24 @@ public class WebSocketController { public JsonNode pointCard(@Header("room") String roomId, @Header("player") String player, @Payload JsonNode content) { int cardIndex = content.asObject().get("cardIndex").intValue(); - Grid g = GameManager.findGrid(roomId); - gm.pointCard(g, player.charAt(0), cardIndex); + Grid g = gm.findGrid(roomId); + Color c = gm.pointCard(g, player.charAt(0), cardIndex); + content.asObject().set("color", jsn.stringNode(c.name().toLowerCase())); + content.asObject().set("player", jsn.stringNode(player)); + if(g.getPhase() != Phase.GUESSING_A && g.getPhase() != Phase.GUESSING_B) + publishNewPhase(g); + publishCardUpdate(g, cardIndex); return content; } @MessageMapping("end-guessing") @SendTo("/topic/end-guessing") - public String endGuessing(@Header("room") String roomId, @Header("player") String player) { - Grid g = GameManager.findGrid(roomId); + public JsonNode endGuessing(@Header("room") String roomId, @Header("player") String player) { + Grid g = gm.findGrid(roomId); gm.endGuessing(g, player.charAt(0)); - return ""; + ObjectNode out = jsn.objectNode(); + out.set("player", jsn.stringNode(player)); + return out; } } diff --git a/src/main/java/com/bernard/nodecames/game/GameManager.java b/src/main/java/com/bernard/nodecames/game/GameManager.java index dabd4a9..1fb21fb 100644 --- a/src/main/java/com/bernard/nodecames/game/GameManager.java +++ b/src/main/java/com/bernard/nodecames/game/GameManager.java @@ -1,14 +1,20 @@ package com.bernard.nodecames.game; +import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Random; +import java.util.Scanner; +import java.util.Set; import java.util.UUID; import java.util.stream.IntStream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import com.bernard.nodecames.model.Card; @@ -27,48 +33,90 @@ public class GameManager { private static final JsonNodeFactory jsn = JsonNodeFactory.instance; + //TODO Remove static, make something more Spring Boot-y private static Map games = new HashMap<>(); - public static JsonNode gridData(Grid g, char player) { + @Value("classpath:dictionaries/fr.txt") + Resource dictFr; + + //TODO do Spring boot magic to only generate this once + public List allWords() { + try (Scanner wordsScanner = new Scanner(dictFr.getInputStream())) { + List out = new ArrayList<>(); + while (wordsScanner.hasNextLine()) + out.add(wordsScanner.nextLine()); + return Collections.unmodifiableList(out); + } catch (IOException e) { + throw new IllegalStateException("Could not read internal dictionnary", e); + } + } + + public String[] randomWords(int count) { + List allWords = allWords(); + //TODO seed the games + Random r = new Random(); + if(count > allWords.size()) + throw new IllegalArgumentException("Not enough words in the dictionary"); + String[] out = new String[count]; + Set already = new HashSet<>(); + int k; + for(int i = 0; i c == g.getCards()[i]) + .findFirst() + .getAsInt(); + geNode.set("card-index", jsn.numberNode(pos)); + break; + case GameEvent.Type.END_GUESSING: + geNode.set("manual", jsn.booleanNode((Boolean)ge.getData())); + break; + case GameEvent.Type.START_GAME: + break; + } + return geNode; + } + + public JsonNode gridData(Grid g, char player) { ArrayNode cardsNode = jsn.arrayNode(g.getCardCount()); - for (int i = 0; i < g.getCardCount(); i++) { - ObjectNode cardNode = jsn.objectNode(); - Card c = g.getCards()[i]; - cardNode.set("word", jsn.stringNode(c.getWord())); - cardNode.set("color", jsn.stringNode((player=='A'?c.getColorA():c.getColorB()).name().toLowerCase())); - if((player=='A' && c.isRevealedA()) || (player=='B' && c.isRevealedB())) - cardNode.set("otherColor", jsn.stringNode((player=='A'?c.getColorB():c.getColorA()).name().toLowerCase())); - cardsNode.add(cardNode); - } + for (int i = 0; i < g.getCardCount(); i++) + cardsNode.add(cardData(g.getCards()[i], player)); ArrayNode eventsNode = jsn.arrayNode(g.getGameEvents().size()); - for(GameEvent ge : g.getGameEvents()) { - ObjectNode geNode = jsn.objectNode(); - geNode.set("type", jsn.stringNode(ge.getType().name().toLowerCase())); - geNode.set("issuer", jsn.stringNode(Character.toString(ge.getIssuer()))); - switch (ge.getType()) { - case GameEvent.Type.HINT: - Hint hint = (Hint)ge.getData(); - geNode.set("word", jsn.stringNode(hint.getWord())); - geNode.set("wordCount", jsn.numberNode(hint.getWordCount())); - break; - case GameEvent.Type.GUESS: - Card c = (Card)ge.getData(); - Integer pos = IntStream.range(0, g.getCardCount()) - .filter(i -> c == g.getCards()[i]) - .findFirst() - .getAsInt(); - geNode.set("card-index", jsn.numberNode(pos)); - break; - case GameEvent.Type.END_GUESSING: - geNode.set("manual", jsn.booleanNode((Boolean)ge.getData())); - break; - case GameEvent.Type.START_GAME: - break; - } - eventsNode.add(geNode); - } + for(GameEvent ge : g.getGameEvents()) + eventsNode.add(eventData(g, ge)); ObjectNode currentHintNode = jsn.objectNode(); if(g.getCurrentHint() != null) { @@ -89,15 +137,13 @@ public class GameManager { return out; } - public static Grid findGrid(String gridId) { + public Grid findGrid(String gridId) { return games.get(UUID.fromString(gridId)); } - public static UUID newGrid() { + public UUID newGrid() { UUID uuid = UUID.randomUUID(); - String[] words = new String[25]; - for (int i = 0; i < words.length; i++) - words[i] = "MotNumero"+Integer.toString(i); + String[] words = randomWords(25); List cards = new ArrayList<>(25); int i = 0; cards.add(new Card(words[i++], Color.BLACK, Color.BLACK)); @@ -141,7 +187,7 @@ public class GameManager { g.setCurrentGuessCount(0); } - public void pointCard(Grid g, char player, int cardIndex) { + public Card.Color pointCard(Grid g, char player, int cardIndex) { if (!(((player == 'A') && (g.getPhase() == Grid.Phase.GUESSING_A)) || ((player == 'B') && (g.getPhase() == Grid.Phase.GUESSING_B)))) { throw new RuntimeException("This action is not allowed now"); @@ -199,7 +245,7 @@ public class GameManager { g.setPhase(Grid.Phase.HINTING_B); g.newGameEvent(GameEvent.newEndGuessingEvent(false, player)); } - + return (player == 'A')?c.getColorB():c.getColorA(); } public void endGuessing(Grid g, char player) { diff --git a/src/main/resources/dictionaries/fr.txt b/src/main/resources/dictionaries/fr.txt new file mode 100644 index 0000000..33db616 --- /dev/null +++ b/src/main/resources/dictionaries/fr.txt @@ -0,0 +1,697 @@ +Accident +Achat +Acné +Action +Adolescent +Afrique +Aiguille +Allumer +Alpes +Alphabet +Altitude +Amérique +Ami +Amour +Ampoule +Anniversaire +Appétit +Araignée +Arbre +Arc +Arc-en-ciel +Argent +Arme +Armée +Ascenseur +Asie +Assis +Astronaute +Atchoum +Athlète +Atlantide +Aube +Australie +Avec +Aventure +Avion +Avocat +Bac +Baguette +Bain +Baiser +Balai +Balle +Ballon +Bambou +Banane +Bannir +Barbe +Barrière +Bas +Basket +Bateau +Bâton +Batterie +Bébé +Beethoven +Bête +Biberon +Bière +Blanc +Blé +Bleu +Bob +Boisson +Boîte +Bombe +Bonbon +Bonnet +Bord +Bordeaux +Botte +Boue +Bougie +Boule +Bouteille +Bouton +Branche +Bras +Bravo +Bretagne +Brise +Brosse +Bruit +Brume +Brun +Bûche +Bulle +Bureau +But +Cabane +Cabine +Cacher +Cadeau +Cafard +Café +Caisse +Calculer +Calme +Caméra +Camion +Camping +Canada +Canard +Canette +Canine +Cap +Capitalisme +Car +Carotte +Carré +Carte +Carton +Casque +Casser +Cassette +Cauchemar +Cause +Ceinture +Cellule +Cercle +Chaîne +Chair +Chaise +Champ +Champion +Chant +Chapeau +Charbon +Charge +Chasse +Chat +Château +Chaud +Chaussure +Chauve +Chef +Chemise +Chêne +Cher +Cheval +Chevalier +Cheveu +Chien +Chiffre +Chine +Chocolat +Chômage +Ciel +Cil +Cinéma +Cire +Cirque +Citron +Clé +Clou +Clown +Coach +Coccinelle +Code +Cœur +Col +Colle +Colline +Colonne +Cône +Confort +Continu +Contre +Conversation +Copain +Coq +Coquillage +Corbeau +Corde +Corps +Côte +Coude +Couloir +Coup +Cour +Courant +Courrier +Cours +Course +Court +Couteau +Couvert +Couverture +Cowboy +Crac +Crayon +Crème +Critique +Crochet +Croix +Croûte +Cuillère +Cuir +Cuisine +Culotte +Cycle +Dard +Dé +Debout +Défaut +Dehors +Démocratie +Dent +Dentiste +Dessin +Devoir +Diamant +Dictionnaire +Dieu +Dinosaure +Discours +Disque +Dix +Docteur +Doigt +Domino +Dormir +Droit +Eau +Échec +Échelle +Éclair +École +Écran +Écraser +Écrit +Église +Égout +Électricité +Éléphant +Élève +Elfe +Empreinte +Enceinte +Épice +Épine +Erreur +Espace +Espion +Essence +État +Été +Étoile +Étranger +Éventail +Évolution +Explosion +Extension +Face +Fan +Farce +Fatigue +Fauteuil +Femme +Fenêtre +Fer +Fête +Feu +Feuille +Fidèle +Fil +Fille +Flamme +Flèche +Fleur +Fleuve +Fond +Football +Forêt +Forger +Foudre +Fouet +Four +Fourmi +Froid +Fromage +Front +Fruit +Fuir +Futur +Garçon +Gâteau +Gauche +Gaz +Gazon +Gel +Genou +Glace +Gomme +Gorge +Goutte +Grand +Grèce +Grenouille +Grippe +Gris +Gros +Groupe +Guitare +Hasard +Haut +Hélicoptère +Herbe +Heureux +Histoire +Hiver +Hôtel +Hugo +Huile +Humide +Humour +Indice +Internet +Inviter +Italie +Jacques +Jambe +Jambon +Jardin +Jaune +Jean +Jeanne +Jet +Jeu +Jogging +Jour +Journal +Jupiter +Kilo +Kiwi +Laine +Lait +Langue +Lapin +Latin +Laver +Lecteur +Léger +Lent +Lettre +Lien +Ligne +Linge +Lion +Lit +Livre +Loi +Long +Louis +Loup +Lumière +Lundi +Lune +Lunette +Machine +Macho +Main +Maison +Maîtresse +Mal +Maladie +Maman +Mammouth +Manger +Marais +Marc +Marche +Mariage +Marie +Mariée +Marque +Marseille +Masse +Mer +Messe +Mètre +Métro +Miaou +Micro +Mieux +Mille +Mine +Miroir +Moderne +Moitié +Monde +Monstre +Montagne +Montre +Mort +Moteur +Moto +Mou +Mouche +Moulin +Moustache +Mouton +Mur +Muscle +Musique +Mystère +Nage +Nature +Neige +Neutre +New York +Nez +Nid +Ninja +Niveau +Noël +Nœud +Noir +Nous +Nuage +Nuit +Numéro +Œil +Œuf +Oiseau +Olympique +Ombre +Ongle +Or +Oral +Orange +Ordinateur +Ordre +Ordure +Oreille +Organe +Orgueil +Ours +Outil +Ouvert +Ovale +Pain +Palais +Panneau +Pantalon +Pantin +Papa +Papier +Papillon +Paradis +Parc +Paris +Parole +Partie +Passe +Pâte +Patin +Patte +Payer +Pêche +Peinture +Pendule +Penser +Personne +Petit +Peur +Philosophe +Photo +Phrase +Piano +Pièce +Pied +Pierre +Pile +Pilote +Pince +Pioche +Pion +Pirate +Pire +Piscine +Place +Plafond +Plage +Plaie +Plan +Planche +Planète +Plante +Plastique +Plat +Plat +Plomb +Plonger +Pluie +Poche +Poète +Poids +Poing +Point +Poivre +Police +Politique +Pollen +Polo +Pomme +Pompe +Pont +Population +Port +Porte +Portefeuille +Positif +Poste +Poubelle +Poule +Poupée +Pousser +Poussière +Pouvoir +Préhistoire +Premier +Présent +Presse +Prier +Princesse +Prise +Privé +Professeur +Psychologie +Public +Pull +Punk +Puzzle +Pyjama +Quatre +Quinze +Race +Radio +Raisin +Rap +Rayé +Rayon +Réfléchir +Reine +Repas +Reptile +Requin +Rêve +Riche +Rideau +Rien +Rire +Robinet +Roche +Roi +Rond +Rose +Roue +Rouge +Rouille +Roux +Russie +Sable +Sabre +Sac +Sain +Saison +Sale +Salle +Salut +Samu +Sandwich +Sang +Sapin +Satellite +Saumon +Saut +Savoir +Schtroumpf +Science +Scout +Sec +Seine +Sel +Sept +Serpent +Serrer +Sexe +Shampooing +Siècle +Siège +Sieste +Silhouette +Sirène +Ski +Soleil +Sommeil +Son +Sonner +Sorcière +Sourd +Souris +Sport +Star +Station +Stylo +Sur +Surface +Sushi +Swing +Tableau +Tache +Taille +Tante +Tapis +Tard +Taxi +Téléphone +Télévision +Temple +Temps +Tennis +Tête +Thé +Tigre +Tintin +Tissu +Titre +Titre +Toast +Toilette +Tokyo +Tombe +Ton +Top +Touche +Toujours +Tour +Tournoi +Tout +Trace +Train +Traîner +Transport +Travail +Trésor +Triangle +Triste +Trône +Troupeau +Tsar +Tube +Tuer +Tuer +Tupperware +Tuyau +Twitter +Type +Université +Vache +Vache +Vague +Vaisselle +Valeur +Ver +Verdict +Verre +Vers +Vert +Veste +Viande +Vide +Vie +Vieux +Ville +Vin +Vingt +Violon +Vipère +Vision +Vite +Vive +Vœu +Voile +Voisin +Voiture +Vol +Volume +Vote +Vouloir +Voyage +Zen +Zéro +Zodiaque +Zone +Zoo diff --git a/src/main/resources/static/css/grid.css b/src/main/resources/static/css/grid.css index 756fe9f..1cc2030 100644 --- a/src/main/resources/static/css/grid.css +++ b/src/main/resources/static/css/grid.css @@ -2,7 +2,11 @@ li.card { border: purple solid 2pt; list-style-type: none; padding: 1ex; - margin: 1ex; + margin: .2ex; + width: 30ex; + height: 12ex; + line-break: anywhere; + text-align: center; font-size: 16px; } ul#cards-list { @@ -13,4 +17,62 @@ ul#cards-list { span.card-word { font-weight: bold; font-size: 30px; +} + +.green { + color: #111111; + background: + linear-gradient(63deg, #40DD62 23%, transparent 23%) 7px 0, + linear-gradient(63deg, transparent 74%, #40DD62 78%), + linear-gradient(63deg, transparent 34%, #40DD62 38%, #40DD62 58%, transparent 62%), + #5CE279; + background-size: 16px 48px; +} + +.black { + color: #EEEEEE; + background: + linear-gradient(27deg, #151515 5px, transparent 5px) 0 5px, + linear-gradient(207deg, #151515 5px, transparent 5px) 10px 0px, + linear-gradient(27deg, #222 5px, transparent 5px) 0px 10px, + linear-gradient(207deg, #222 5px, transparent 5px) 10px 5px, + linear-gradient(90deg, #1b1b1b 10px, transparent 10px), + linear-gradient(#1d1d1d 25%, #1a1a1a 25%, #1a1a1a 50%, transparent 50%, transparent 75%, #242424 75%, #242424); + background-color: #131313; + background-size: 20px 20px; +} + +.white { + color: #222222; + background-color:#EEEEEE; + background-image: + radial-gradient(circle at 100% 150%, #EEEEEE 24%, white 24%, white 28%, #EEEEEE 28%, #EEEEEE 36%, white 36%, white 40%, transparent 40%, transparent), + radial-gradient(circle at 0 150%, #EEEEEE 24%, white 24%, white 28%, #EEEEEE 28%, #EEEEEE 36%, white 36%, white 40%, transparent 40%, transparent), + radial-gradient(circle at 50% 100%, white 10%, #EEEEEE 10%, #EEEEEE 23%, white 23%, white 30%, #EEEEEE 30%, #EEEEEE 43%, white 43%, white 50%, #EEEEEE 50%, #EEEEEE 63%, white 63%, white 71%, transparent 71%, transparent), + radial-gradient(circle at 100% 50%, white 5%, #EEEEEE 5%, #EEEEEE 15%, white 15%, white 20%, #EEEEEE 20%, #EEEEEE 29%, white 29%, white 34%, #EEEEEE 34%, #EEEEEE 44%, white 44%, white 49%, transparent 49%, transparent), + radial-gradient(circle at 0 50%, white 5%, #EEEEEE 5%, #EEEEEE 15%, white 15%, white 20%, #EEEEEE 20%, #EEEEEE 29%, white 29%, white 34%, #EEEEEE 34%, #EEEEEE 44%, white 44%, white 49%, transparent 49%, transparent); + background-size: 100px 50px; +} + +.card-bottom-bar { + display: grid; + grid-template-columns: 5ex 17ex 5ex; + justify-content: center; +} + +.card-bottom-bar div { + width: 3ex; + height: 3ex; + font-size: 20pt; + border: black solid 2pt; + font-weight: bold; +} + +.card-bottom-bar button { + margin-left: 1ex; + margin-right: 1ex; +} + +.card.card-done { + opacity: 70%; } \ No newline at end of file diff --git a/src/main/resources/static/js/grid.js b/src/main/resources/static/js/grid.js index f042e12..deab79e 100644 --- a/src/main/resources/static/js/grid.js +++ b/src/main/resources/static/js/grid.js @@ -2,6 +2,7 @@ var socket = null var player = '_' var roomId = '_' var wsHeaders = {} +var cards = [] function getRoomId() { const urlRegex = /\/room\/([a-f0-9-]{36})\/grid$/ @@ -11,27 +12,93 @@ function getRoomId() { return res[1] } -function makeCards(data) { - var cards = data['cards'] +function updatePhase(phase) { + if(phase == "hinting_any" || (phase == "hinting_a" && player == 'A') || (phase == "hinting_b" && player == 'B')) { + // Hinting + $('.card-button').css('visibility', 'hidden') + $('#hint-text').hide() + $('#submit-hint').show() + $('#other-playing').hide() + $('#end-guessing').hide() + } else if ((phase == "hinting_b" && player == 'A') || (phase == "hinting_a" && player == 'B')) { + // Wait for the other one + $('.card-button').css('visibility', 'hidden') + $('#hint-text').hide() + $('#submit-hint').hide() + $('#other-playing').show() + $('#end-guessing').hide() + } else if ((phase == "guessing_a" && player == 'B') || (phase == "guessing_b" && player == 'A')) { + // Wait for the other one + $('.card-button').css('visibility', 'hidden') + $('#hint-text').show() + $('#submit-hint').hide() + $('#other-playing').show() + $('#end-guessing').hide() + } else if ((phase == "guessing_a" && player == 'A') || (phase == "guessing_b" && player == 'B')) { + // Guessing + $('.card-button').css('visibility', 'visible') + $('.card-button.untouchable').css('visibility', 'hidden') + $('#hint-text').show() + $('#submit-hint').hide() + $('#other-playing').hide() + $('#end-guessing').show() + } +} + +function setHint(hint, wordCount) { + $('#hint-text').text(hint+" in "+wordCount) +} + +function updateCard(i) { + card = cards[i] + if(card['revealed-a']) { + $(`#card-${i}-b-public`).addClass((player=='A')?card.otherColor:card.color) + $(`#card-${i}-b-public`).css('visibility', 'visible') + } else { + $(`#card-${i}-b-public`).css('visibility', 'hidden') + } + if(card['revealed-b']) { + $(`#card-${i}-a-public`).addClass((player=='B')?card.otherColor:card.color) + $(`#card-${i}-a-public`).css('visibility', 'visible') + } else { + $(`#card-${i}-a-public`).css('visibility', 'hidden') + } + cardDone = (card['revealed-a'] && ((player=='A')?card.otherColor:card.color == "green")) || + (card['revealed-b'] && ((player=='B')?card.otherColor:card.color == "green")) || + (card['revealed-a'] && card['revealed-b']); + if(cardDone) $(`#card-${i}`).addClass('card-done') + cantTouch = cardDone || + (player=='A' && card['revealed-a']) || + (player=='B' && card['revealed-b']); + if(cantTouch) { + $(`#card-${i}-button`).addClass('untouchable') + $(`#card-${i}-button`).css('visibility', 'hidden') + } +} + +function initGame(data) { + cards = data['cards'] $('#cards-list').empty() for(var i = 0; i +
  • ${cards[i].word}
    - Color: ${cards[i].color}
    - +
    +
    A
    + +
    B
    +
  • ` $('#cards-list').append($(html)) $(`#card-${i}-button`).on('click', pointCard) + updateCard(i) } + + updatePhase(data['phase']) } function selectPlayer(e) { - console.log(e) - console.log(e.target) - console.log(e.target.id) - console.log(e.target.id == "select-player-a") player = (e.target.id == "select-player-a") ? 'A' : 'B' wsHeaders = { "room": roomId, @@ -44,7 +111,7 @@ function selectPlayer(e) { contentType: 'application/json', type: "GET", url: "/room/"+roomId+"/game/player-"+player.toLowerCase(), - success: makeCards + success: initGame }) socket = Stomp.over(new SockJS('/socket')); @@ -52,6 +119,8 @@ function selectPlayer(e) { socket.subscribe('/topic/submit-hint', onSubmitHint); socket.subscribe('/topic/point-card', onPointCard); socket.subscribe('/topic/end-guessing', onEndGuessing); + socket.subscribe('/topic/new-phase', onNewPhase); + socket.subscribe('/topic/update-card/' + player.toLowerCase(), onUpdateCard); }); } @@ -75,17 +144,19 @@ function endGuessing(e) { function onSubmitHint(m) { data = JSON.parse(m.body) + setHint(data['hint'], data['hintWordCount']) $("#event-log").append($(`
  • - ${data['hint']} en ${data['hintWordCount']} + ${data.player} proposed "${data['hint']}" in ${data['hintWordCount']} word(s)
  • `)) } function onPointCard(m) { data = JSON.parse(m.body) + i = data['cardIndex'] $("#event-log").append($(`
  • - Pointed card ${data['cardIndex']} + ${data.player} pointed card ${cards[i].word} (${data.color})
  • `)) } @@ -96,6 +167,16 @@ function onEndGuessing(m) { `)) } +function onNewPhase(m) { + updatePhase(m.body) +} + +function onUpdateCard(m) { + data = JSON.parse(m.body) + i = Number(m.headers['cardIndex']) + cards[i] = data + updateCard(i) +} function initialize() { $('#select-player-a').on('click', selectPlayer) diff --git a/src/main/resources/templates/grid.html b/src/main/resources/templates/grid.html index ae44ce9..d3eb6ae 100644 --- a/src/main/resources/templates/grid.html +++ b/src/main/resources/templates/grid.html @@ -21,6 +21,10 @@ +
    + +
    +
    - +
    + Waiting for the other side to play +
    +
    + +