Added card styles
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<UUID, Grid> 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<String> allWords() {
|
||||
try (Scanner wordsScanner = new Scanner(dictFr.getInputStream())) {
|
||||
List<String> 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<String> 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<Integer> already = new HashSet<>();
|
||||
int k;
|
||||
for(int i = 0; i<count; i++) {
|
||||
do {
|
||||
k = r.nextInt(allWords.size());
|
||||
} while (already.contains(k));
|
||||
out[i] = allWords.get(k);
|
||||
already.add(k);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public JsonNode cardData(Card c, char player) {
|
||||
ObjectNode cardNode = jsn.objectNode();
|
||||
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()));
|
||||
cardNode.set("revealed-a", jsn.booleanNode(c.isRevealedA()));
|
||||
cardNode.set("revealed-b", jsn.booleanNode(c.isRevealedB()));
|
||||
return cardNode;
|
||||
}
|
||||
|
||||
public JsonNode eventData(Grid g, GameEvent ge) {
|
||||
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;
|
||||
}
|
||||
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<Card> 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) {
|
||||
|
||||
@@ -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
|
||||
@@ -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%;
|
||||
}
|
||||
@@ -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.length; i++) {
|
||||
html = `
|
||||
<li class="card" id="card-${i}">
|
||||
<li class="card ${cards[i].color}" id="card-${i}">
|
||||
<span class="card-word">${cards[i].word}</span><br/>
|
||||
Color: <span class="card-color-text" id="card-${i}-color">${cards[i].color}</span><br/>
|
||||
<button id="card-${i}-button">Toucher</button>
|
||||
<div class="card-bottom-bar">
|
||||
<div id="card-${i}-a-public">A</div>
|
||||
<button class="card-button" id="card-${i}-button">Toucher</button>
|
||||
<div id="card-${i}-b-public">B</div>
|
||||
</div>
|
||||
</li>
|
||||
`
|
||||
$('#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($(`
|
||||
<li>
|
||||
${data['hint']} en ${data['hintWordCount']}
|
||||
${data.player} proposed "${data['hint']}" in ${data['hintWordCount']} word(s)
|
||||
</li>
|
||||
`))
|
||||
}
|
||||
function onPointCard(m) {
|
||||
data = JSON.parse(m.body)
|
||||
i = data['cardIndex']
|
||||
$("#event-log").append($(`
|
||||
<li>
|
||||
Pointed card ${data['cardIndex']}
|
||||
${data.player} pointed card ${cards[i].word} (${data.color})
|
||||
</li>
|
||||
`))
|
||||
}
|
||||
@@ -96,6 +167,16 @@ function onEndGuessing(m) {
|
||||
</li>
|
||||
`))
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
</ul>
|
||||
|
||||
<div id="hint-text">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="submit-hint">
|
||||
<input type="text" id="submit-hint-text"/>
|
||||
<select id="submit-hint-wordcount">
|
||||
@@ -33,7 +37,12 @@
|
||||
</select>
|
||||
<button>Submit Hint</button>
|
||||
</div>
|
||||
<button id="end-guessing-button">End Guessing</button>
|
||||
<div id="other-playing">
|
||||
Waiting for the other side to play
|
||||
</div>
|
||||
<div id="end-guessing">
|
||||
<button id="end-guessing-button">End Guessing</button>
|
||||
</div>
|
||||
<br/>
|
||||
<ol id="event-log">
|
||||
|
||||
|
||||
Reference in New Issue
Block a user