From de85af4e2a472bcd0027a995fbd028b5dc60e758 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 19 Aug 2026 18:41:07 +0000 Subject: [PATCH] =?UTF-8?q?fix(classic):=20anti-r=C3=A9p=C3=A9tition=20per?= =?UTF-8?q?sistante=20+=20coh=C3=A9rence=20des=20questions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anti-répétition: - Chaque question posée est marquée en SharedPreferences (par ID): elle ne revient plus, même entre les parties, tant que le stock de 185 questions n'est pas épuisé (reset automatique ensuite) - Le fallback ne renvoie plus une question déjà posée Cohérence (audit croisé JSON <-> moteur, 185 questions): - Accord du verbe selon le sujet réel: 62 questions à sujet pluriel recevaient «boit» au lieu de «boivent» (isPluralSubject) - Remplacement indépendant des balises //: une question contenant sans n'affichait plus la balise brute - Le champ arret du JSON est désormais utilisé comme message de fin de défi (27 messages étaient des données mortes) - id 84: champ "distribut" (typo) jamais lu -> question muette - 16 questions à double consigne (gorgées en dur + gorgées du moteur) passées en auto-suffisantes - Balises manquantes (ids 21, 97) rétablies - 78 corrections de langue/accord dans les textes (orthographe, accords m/f, variantes vieux/vieille, branché(e), fins de phrases incohérentes avec le verbe ajouté...) --- app/src/main/assets/question.json | 228 +++++++++--------- .../boidelov3/data/QuestionRepository.java | 7 + .../example/boidelov3/game/GameEngine.java | 53 +++- .../BoideloClassicGameActivity.java | 99 ++++++-- 4 files changed, 245 insertions(+), 142 deletions(-) diff --git a/app/src/main/assets/question.json b/app/src/main/assets/question.json index 91d99cc..e575ffd 100644 --- a/app/src/main/assets/question.json +++ b/app/src/main/assets/question.json @@ -17,14 +17,14 @@ }, { "id": 3, - "question": "si tu n'as pas ton véritable nom sur insta", + "question": "Ceux/Celles qui n'ont pas leur véritable nom sur Insta", "gorger": 3, "distribution": true, "recois": true }, { "id": 4, - "question": "si tu as des photos sur insta", + "question": "Ceux/Celles qui ont des photos compromettantes sur Insta", "gorger": 3, "distribution": true, "recois": true @@ -45,7 +45,7 @@ }, { "id": 7, - "question": "Toutes celles (ou ceux) qui ont du verni à ongles", + "question": "Toutes celles (ou ceux) qui ont du vernis à ongles", "gorger": 3, "distribution": true, "recois": true @@ -80,7 +80,7 @@ }, { "id": 12, - "question": " à toi de juger : entre et qui stresse le plus pour un rien selon toi? Le perdant ", + "question": ", à toi de juger : entre et qui stresse le plus pour un rien selon toi ? Le perdant ", "gorger": 5, "distribution": false, "recois": true @@ -101,12 +101,12 @@ }, { "id": 15, - "question": ", donne le nombre d'habitant du/de la ( à 1 000 000 près) Si tu as faux tu bois, sinon tu ", + "question": ", donne le nombre d'habitants du/de la (à 1 000 000 près). Si tu as faux, le joueur ", "gorger": 3, "distribution": true, "recois": false, "variante": [ - "Tadjikistant", + "Tadjikistan", "Monaco", "Belgique", "Suisse", @@ -126,12 +126,12 @@ "id": 17, "question": " à qui appartient le slogan suivant? ", "variante": [ - "Des pâtes oui mais des (panzani)", + "Des pâtes oui, mais des Panzani ! (Panzani)", " Le plaisir pour les petites faims. (Kinder Bueno)", - "Réveillez le lion qui est en vous. (Cereale lion)", + "Réveillez le lion qui est en vous. (Céréales Lion)", "Parce que le monde bouge (CIC)", "Ça coule de source ! (Cristaline)", - "Pensez différemment (apple)" + "Pensez différemment (Apple)" ], "gorger": 3, "distribution": true, @@ -139,14 +139,14 @@ }, { "id": 18, - "question": "Celles et ceux qui ont eu un Windows phone", + "question": "Celles et ceux qui ont eu un Windows Phone", "gorger": 3, "distribution": true, "recois": true }, { "id": 19, - "question": ", Boire un café fait baisser le taux d'alcool? Si tu as faux ", + "question": ", Boire un café fait baisser le taux d'alcool ? Si tu as faux, ", "gorger": 3, "distribution": false, "recois": true @@ -160,10 +160,10 @@ }, { "id": 21, - "question": "Celui/Celle qui pèse le plus lourd", + "question": "Celui/Celle qui pèse le plus ", "variante": [ "lourd", - "leger" + "léger" ], "gorger": 3, "distribution": true, @@ -174,9 +174,9 @@ "question": "Pour se décoincer, le/la plus ", "variante": [ "timide", - "enervé ", - "angoissé", - "aigri" + "énervé(e)", + "angoissé(e)", + "aigri(e)" ], "gorger": 2, "distribution": false, @@ -188,7 +188,7 @@ "gorger": 3, "variante": [ "jeune", - "vieille" + "vieux/vieille" ], "distribution": false, "recois": true @@ -200,7 +200,7 @@ "variante": [ "L", "Scientifique", - "Bac Professionel", + "Bac Professionnel", "STMG" ], "distribution": true, @@ -208,7 +208,7 @@ }, { "id": 25, - "question": "Celles et ceux qui ont deja joué de maniere recurrente ", + "question": "Celles et ceux qui ont déjà joué de manière récurrente ", "gorger": 3, "variante": [ "du piano", @@ -229,7 +229,7 @@ }, { "id": 27, - "question": "Celui ou celle a la meilleure place", + "question": "Celui ou celle à la meilleure place", "gorger": 2, "distribution": false, "recois": true @@ -268,7 +268,7 @@ }, { "id": 32, - "question": "La personne la plus maquillé ", + "question": "La personne la plus maquillée ", "gorger": 2, "distribution": true, "recois": true @@ -282,7 +282,7 @@ }, { "id": 34, - "question": "Celles et ceux qui boit de la actuellement", + "question": "Celles et ceux qui boivent de la actuellement", "gorger": 3, "distribution": true, "recois": true, @@ -332,7 +332,7 @@ }, { "id": 38, - "question": "Celui/celle avec le plus gros appetit sexuel", + "question": "Celui/celle avec le plus gros appétit sexuel", "gorger": 3, "distribution": false, "recois": true, @@ -340,7 +340,7 @@ }, { "id": 39, - "question": "Ceux/Celles qui fumes (VapeNation compris)", + "question": "Ceux/Celles qui fument (vapoteurs compris)", "gorger": 3, "distribution": false, "recois": true @@ -378,7 +378,7 @@ }, { "id": 43, - "question": "Le premier joueur à enlever un vêtements", + "question": "Le premier joueur à enlever un vêtement", "gorger": 3, "distribution": true, "recois": true @@ -392,14 +392,14 @@ }, { "id": 45, - "question": "Celui/Celle avec le plus de follow sur ", + "question": "Celui/Celle avec le plus d'abonnés sur ", "gorger": 3, "distribution": true, "recois": true, "variante": [ "instagram", "facebook", - "tik-tok" + "TikTok" ] }, { @@ -426,7 +426,7 @@ }, { "id": 49, - "question": "Celles et ceux qui ont déjà dépenser plus de 2000 euros en un achat", + "question": "Celles et ceux qui ont déjà dépensé plus de 2000 euros en un achat", "gorger": 3, "distribution": true, "recois": true @@ -440,7 +440,7 @@ }, { "id": 51, - "question": "Celles/Ceux qui rentre chez eux à la fin de la soirée", + "question": "Celles/Ceux qui rentrent chez eux à la fin de la soirée", "gorger": 3, "distribution": true, "recois": true @@ -452,13 +452,13 @@ "distribution": true, "recois": true, "variante": [ - "impaire", - "paire" + "impair", + "pair" ] }, { "id": 53, - "question": "Si tu as un téléphone qui a un prix supérieur d'achat à 1000 euros, tu es riche donc en tant que personne généreuse", + "question": "Si tu as un téléphone acheté plus de 1000 euros, tu es riche, donc en tant que personne généreuse", "gorger": 3, "distribution": true, "recois": false @@ -473,7 +473,7 @@ { "id": 55, "jeux": true, - "question": "Le jeu du revolver: Chaque joueur a maintenant 7 balles, une balle correspondant à une gorgée. Les joueurs ont la capacité de tirer des balles à tout moment du jeu.", + "question": "Le jeu du revolver: Chaque joueur a maintenant 7 balles, une balle correspond à une gorgée. Les joueurs ont la capacité de tirer des balles à tout moment du jeu.", "distribution": false, "recois": false }, @@ -487,14 +487,14 @@ { "id": 57, "jeux": true, - "question": " est le vieu/vieille briscard ! Interdiction de montrer tes dents pendant manches", + "question": " est un vieux/une vieille briscard(e) ! Interdiction de montrer tes dents pendant manches", "manches": true, - "arret": "Tu peux arreter de cacher tes belles dents" + "arret": "Tu peux arrêter de cacher tes belles dents" }, { "id": 58, "jeux": true, - "question": " et liser le premier SMS qui s'affiche quand on tape dans la barre de recherche. le plus marrant", + "question": " et , lisez le premier SMS qui s'affiche quand on tape dans la barre de recherche. le plus marrant", "gorger": 3, "variante": [ "désolé", @@ -509,7 +509,7 @@ { "id": 59, "jeux": true, - "question": "A tour de role, vous avez exactement 3 secondes pour donner un mot en rapport avec le mots dit precedemment. tu commences en choissisant un mot. Le perdant", + "question": "À tour de rôle, vous avez exactement 3 secondes pour donner un mot en rapport avec le mot dit précédemment. , tu commences en choisissant un mot. Le perdant", "gorger": 3, "distribution": false, "recois": true @@ -525,7 +525,7 @@ { "id": 61, "jeux": true, - "question": " defie au chifoumi ! Le perdant", + "question": " défie au chifoumi ! Le perdant", "gorger": 3, "distribution": false, "recois": true @@ -539,7 +539,7 @@ "futur" ], "manches": true, - "arret": "Tu est revenu dans le present", + "arret": "Tu es revenu dans le présent", "distribution": false, "recois": false, "caliente": false @@ -551,7 +551,7 @@ { "id": 64, "jeux": true, - "question": " et ferment leurs yeux ! Ils/Elles doivent deviner la couleur des yeux de l'autre. ", + "question": " et ferment leurs yeux ! Ils/Elles doivent deviner la couleur des yeux de l'autre. Le perdant ", "gorger": 3, "distribution": false, "recois": true @@ -559,27 +559,27 @@ { "id": 65, "jeux": true, - "question": " est manchot ! Il/Elle ne peut plus utiliser ses doigts durant manches . Si il/elle s'en sert, il/elle devra boire autant de gorgées qu'il/elle a utilisé de doigts", + "question": " est manchot ! Il/Elle ne peut plus utiliser ses doigts durant manches . S'il/elle s'en sert, il/elle devra boire autant de gorgées qu'il/elle a utilisé de doigts", "distribution": false, "arret": "Tu n'es plus manchot", - "recois": true + "recois": false }, { "id": 66, "jeux": true, - "question": " et , si vous êtes ensemble dans la vraie vie, vous pouvez distribuer 2 gorgées , autrement buvez-les" + "question": " et , si vous êtes ensemble dans la vraie vie, vous pouvez distribuer 2 gorgées , autrement buvez-les" }, { "id": 67, "jeux": true, - "question": " a la tourette ! A chaque fois que tu bois une gorgée, tu dois CRIER une insulte. C'est un stade avancé, ça dure manches", + "question": " a la Tourette ! A chaque fois que tu bois une gorgée, tu dois CRIER une insulte. C'est un stade avancé, ça dure manches", "manches": true, - "arret": "Tu n'as plus tourette." + "arret": "Tu n'as plus la Tourette." }, { "id": 68, "jeux": true, - "question": ", donne la couleur préférée de si tu te trompes", + "question": ", donne la couleur préférée de . En cas d'erreur, ", "gorger": 3, "distribution": false, "recois": true @@ -587,19 +587,20 @@ { "id": 69, "jeux": true, - "question": " à l'oeil de serpent ! Dès qu'un joueur te regarde dans les yeux, il/elle boit. Si tu es arrivé à faire boire personne avant manches, tu ", + "question": " a l'œil de serpent ! Dès qu'un joueur te regarde dans les yeux, il/elle boit. Si tu n'as réussi à faire boire personne avant manches, le serpent ", "gorger": 4, "distribution": false, - "recois": true + "recois": true, + "arret": "Tu n'as plus l'œil de serpent !" }, { "id": 70, "jeux": true, - "question": " et se mesurent ! Le/la plus ", + "question": " et se mesurent ! Le/la plus ", "gorger": 3, "variante": [ - "petit", - "grand" + "petit(e)", + "grand(e)" ], "distribution": true, "recois": true @@ -612,12 +613,13 @@ "C'est clair", "han", "quoicoubeh" - ] + ], + "arret": "Tu peux enfin parler normalement !" }, { "id": 72, "jeux": true, - "question": " et se défient au 'je te tiens, tu me tiens', le premier qui rit sera dechiré, et ", + "question": " et se défient au 'je te tiens, tu me tiens', le premier qui rit sera déchiré, et ", "gorger": 3, "distribution": false, "recois": true @@ -627,7 +629,7 @@ "jeux": true, "question": " et n'ont plus le droit d'utiliser leur téléphone pendant manches !", "manches": "true", - "arret": "vous pouvez enfin utiliser vos téléphone bande de geek" + "arret": "vous pouvez enfin utiliser vos téléphones, bande de geeks" }, { "id": 74, @@ -645,7 +647,7 @@ { "id": 75, "jeux": true, - "question": ", Si on te dit Marco? ... Si tu as dis Polo ", + "question": ", Si on te dit Marco? ... Si tu as dit Polo ", "gorger": 3, "distribution": true, "recois": true @@ -653,11 +655,11 @@ { "id": 76, "jeux": true, - "question": " est l'aigris pendant manches ! Dès que tu souris ou rigoles,", + "question": " est l'aigri pendant manches ! Dès que tu souris ou rigoles,", "gorger": 1, "manches": true, "distribution": false, - "arret": "Tu n'es plus aigris!", + "arret": "Tu n'es plus aigri !", "recois": true }, { @@ -689,9 +691,9 @@ { "id": 81, "jeux": true, - "question": " et sont lies, si l'un boit alors l'autre aussi, et ce pendant manches", + "question": " et sont liés : si l'un boit alors l'autre aussi, et ce pendant manches", "manches": true, - "arret": "Vous n'etes plus liés par le verre de l'amitié et plus.." + "arret": "Vous n'êtes plus liés par le verre de l'amitié !" }, { "id": 82, @@ -703,19 +705,18 @@ "question": " doit choisir un mot que tout le monde devra dire à chaque fois qu'une personne boit. Pendant manches", "jeux": false, "manches": true, - "arret": "Plus besoin de dire le mots avant de boire" + "arret": "Plus besoin de dire le mot avant de boire" }, { "id": 84, "question": "Quand l'heure affichera un multiple de 10 (22h, 22h10 ...) le premier à crier 'merde j'ai oublié mon chat'", "gorger": 3, - "distribut": false, - "manches": true, - "arret": "Vous avez retrouver le chat!" + "distribution": false, + "recois": true }, { "id": 85, - "question": "Plutôt ne plus avoir de mains ou de jambes? les perdants ", + "question": "Plutôt ne plus avoir de mains ou de jambes ? Votez tous en même temps. La minorité ", "gorger": 3, "jeux": false, "distribution": false, @@ -745,7 +746,7 @@ "filles", "garçons", "couples", - "celibataires" + "célibataires" ], "gorger": 3, "distribution": true, @@ -784,21 +785,21 @@ }, { "id": 93, - "question": "Plutôt jeux-videos ou livre ? Votez tous en même temps. La minorité ", + "question": "Plutôt jeux vidéo ou livres ? Votez tous en même temps. La minorité ", "gorger": 3, "distribution": false, "recois": true }, { "id": 94, - "question": "Plutôt anime ou jeux-videos ? Votez tous en même temps. La minorité ", + "question": "Plutôt animés ou jeux vidéo ? Votez tous en même temps. La minorité ", "gorger": 3, "distribution": false, "recois": true }, { "id": 95, - "question": "Elisez le plus d'entre vous, ce dernier ", + "question": "Élisez le plus d'entre vous, ce dernier ", "variante": [ "con", "intelligent", @@ -821,16 +822,16 @@ "Christopher Nolan", "James Cameron", "Tim Burton", - "Quentin tarantino", + "Quentin Tarantino", "Steven Spielberg" ] }, { "id": 97, - "question": "Le premier qui donne un film avec ", + "question": "Le premier qui donne un film avec ", "variante": [ "Christian Clavier", - "Morgan freeman", + "Morgan Freeman", "Brad Pitt", "Jean Reno", "Marion Cotillard" @@ -847,7 +848,7 @@ "recois": false, "variante": [ "jeune", - "vieille" + "vieux/vieille" ] }, { @@ -866,14 +867,14 @@ }, { "id": 101, - "question": "Plutot vaincre le patrikaka ou la polution dans le monde? Votez tous en meme temps. La minorité ", + "question": "Plutôt vaincre le patrikaka ou la pollution dans le monde ? Votez tous en même temps. La minorité ", "gorger": 3, "distribution": false, "recois": true }, { "id": 102, - "question": "Jeu du LUTIN : Pendant manches. Vous devez enlever le lutin de votre verre pour pouvoir boire et le remettre ensuite sinon vous devait reboire", + "question": "Jeu du LUTIN : Pendant manches. Vous devez enlever le lutin de votre verre pour pouvoir boire et le remettre ensuite sinon vous devez reboire", "gorger": 3, "distribution": false, "recois": false, @@ -896,17 +897,17 @@ }, { "id": 104, - "question": "Le premier joueur qui dévoile un de ses secrets et que personne ne sait ", + "question": "Le premier joueur qui dévoile un de ses secrets et que personne ne connaissait : le perdant ", "gorger": 3, "distribution": true, "recois": false }, { "id": 105, - "question": "Jeu des peaux! Triez vous du joueur le plus bronzé au joueur le moins bronzé. Le plus bronzé prend 1 gorgée, le second 2 gorgées, etc.", + "question": "Jeu des peaux! Triez-vous : du joueur le plus bronzé au joueur le moins bronzé. Le plus bronzé prend 1 gorgée, le second 2 gorgées, etc.", "gorger": 3, - "distribution": true, - "recois": true + "distribution": false, + "recois": false }, { "id": 106, @@ -919,11 +920,11 @@ "id": 107, "question": "Il est désormais interdit de se tutoyer pendant manches", "manches": true, - "arret": "Vous pouvez vous enfin vous tutoyer" + "arret": "Vous pouvez enfin vous tutoyer" }, { "id": 108, - "question": "Vaccin contre le COVID19 : Le DR Raoul à dit que boire un cul sec avait les mêmes effets que le vaccin. Tout le monde bois sont verre cul sec" + "question": "Vaccin contre le COVID19 : Le Dr Raoult a dit que boire un cul sec avait les mêmes effets que le vaccin. Tout le monde boit son verre cul sec" }, { "id": 109, @@ -948,29 +949,28 @@ { "id": 112, "question": "Le prochain qui parle de travail ou d'école doit boire un shot", - "duree": true, - "arret": "Fin de l'interdiction" + "duree": true }, { "id": 113, - "question": "Karaoké improvisé : choisit une chanson pour ", + "question": "Karaoké improvisé : choisit une chanson, et c'est qui doit la chanter. ", "gorger": 3, "distribution": false, "recois": true }, { "id": 114, - "question": "Qui serait le plus susceptible de survivre dans un film de survie ? Votez", + "question": "Qui serait le plus susceptible de survivre dans un film de survie ? Votez, et le perdant ", "gorger": 3, "distribution": false, "recois": true }, { "id": 115, - "question": "Défi cuisine : doit créer la combinaison d'alcool la plus bizarre avec les ingrédients présents, doit boire la mixture", + "question": "Défi cuisine : doit créer la combinaison d'alcool la plus bizarre avec les ingrédients présents, et c'est qui doit la boire cul sec", "gorger": 2, "distribution": false, - "recois": true + "recois": false }, { "id": 116, @@ -1051,14 +1051,14 @@ }, { "id": 127, - "question": "Le/La plus drôle du groupe (vote à main levée, le perdant boit)", + "question": "Le/La plus drôle du groupe (vote à main levée)", "gorger": 3, "distribution": false, "recois": true }, { "id": 128, - "question": "Le/La plus 'bête' cul du groupe", + "question": "Le/La plus beau cul du groupe", "gorger": 4, "distribution": false, "recois": true @@ -1072,7 +1072,7 @@ }, { "id": 130, - "question": "Le/La plus likely to rater sa vie", + "question": "Le/La plus susceptible de rater sa vie", "gorger": 4, "distribution": false, "recois": true @@ -1146,7 +1146,7 @@ }, { "id": 139, - "question": "Pause pip interdite pendant manches. 5 gorgées si tu vas aux toilettes !", + "question": "Pause pipi interdite pendant manches. 5 gorgées si tu vas aux toilettes !", "gorger": 0, "arret": "Tu peux enfin aller aux toilettes !" }, @@ -1190,49 +1190,57 @@ "id": 146, "question": " et se regardent dans les yeux pendant 10 secondes sans rire. Le premier à rire boit 4 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 147, "question": " doit donner un compliment à . Si n'est pas satisfait : boit 3 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 148, - "question": " à toi de choisir : qui de ou a le plus mauvais goût musical ? Le perdant boit 3 gorgées", + "question": ", à toi de choisir : qui de ou a le plus mauvais goût musical ? Le perdant boit 3 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 149, "question": " doit deviner ce que a mangé aujourd'hui. 1 gorgée par mauvaise réponse, max 5", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 150, "question": " et font un bras de fer. Le perdant boit 5 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 151, "question": " doit nommer une qualité de . Si n'est pas d'accord : 3 gorgées pour ", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 152, "question": " doit deviner la couleur des sous-vêtements de . 2 gorgées si faux", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 153, "question": " doit mimer le métier de . Les autres doivent deviner en moins de 30 secondes ou boit 4 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 154, @@ -1286,7 +1294,7 @@ }, { "id": 158, - "question": "Le/La plus 'influençant' du groupe (vote à main levée)", + "question": "Le/La plus influenceur/euse du groupe (vote à main levée)", "gorger": 3, "distribution": false, "recois": true @@ -1302,7 +1310,8 @@ "id": 160, "question": " doit dire 3 mots commençant par la même lettre que choisit. Si échec : 3 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 161, @@ -1313,7 +1322,7 @@ }, { "id": 162, - "question": "Le/La plus 'branché' du groupe selon les autres", + "question": "Le/La plus 'branché(e)' du groupe selon les autres", "gorger": 3, "distribution": false, "recois": true @@ -1382,7 +1391,8 @@ "id": 171, "question": " doit faire rire en 30 secondes. Si échec : 5 gorgées", "gorger": 0, - "recois": true + "recois": false, + "distribution": false }, { "id": 172, @@ -1408,8 +1418,7 @@ "une voiture", "un téléphone", "un avion" - ], - "arret": "Fin du mime !" + ] }, { "id": 175, @@ -1435,8 +1444,7 @@ "mèche", "alliance", "bracelet" - ], - "arret": "Fin du jeu du NI !" + ] }, { "id": 178, @@ -1479,14 +1487,14 @@ }, { "id": 183, - "question": "Ceux qui ont déjà fait un regretté post-soirée (message à un ex)", + "question": "Ceux qui ont déjà envoyé un message à leur ex après une soirée", "gorger": 4, "distribution": true, "recois": true }, { "id": 184, - "question": "Le/La plus 'organisé' du groupe", + "question": "Le/La plus 'organisé(e)' du groupe", "gorger": 2, "distribution": false, "recois": true @@ -1499,4 +1507,4 @@ "recois": true } ] -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java b/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java index 324b933..c14785e 100644 --- a/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java +++ b/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java @@ -98,6 +98,13 @@ public class QuestionRepository { return Result.success(selected); } + /** + * Retourne l'ensemble des IDs des questions déjà posées (toutes parties confondues). + */ + public Set getAskedQuestionIds() { + return new HashSet<>(prefs.getStringSet(KEY_ASKED_QUESTIONS, new HashSet<>())); + } + /** * Marque une question comme étant posée. */ diff --git a/app/src/main/java/com/example/boidelov3/game/GameEngine.java b/app/src/main/java/com/example/boidelov3/game/GameEngine.java index 1358c2a..a347e8d 100644 --- a/app/src/main/java/com/example/boidelov3/game/GameEngine.java +++ b/app/src/main/java/com/example/boidelov3/game/GameEngine.java @@ -100,23 +100,25 @@ public class GameEngine { String result = questionText; int playerCount = 0; - if (hasJ1 && hasJ2 && hasJ3 && selectedPlayers.size() >= 3) { - playerCount = 3; + // Chaque balise est remplacée indépendamment : une question contenant + // uniquement ou reste jouable (l'ordre J1, J2, J3 est conservé) + if (hasJ1 && selectedPlayers.size() >= 1) { + playerCount++; result = result.replace("", selectedPlayers.get(0)); + } + if (hasJ2 && selectedPlayers.size() >= 2) { + playerCount++; result = result.replace("", selectedPlayers.get(1)); + } + if (hasJ3 && selectedPlayers.size() >= 3) { + playerCount++; result = result.replace("", selectedPlayers.get(2)); - } else if (hasJ1 && hasJ2 && selectedPlayers.size() >= 2) { - playerCount = 2; - result = result.replace("", selectedPlayers.get(0)); - result = result.replace("", selectedPlayers.get(1)); - } else if (hasJ1 && selectedPlayers.size() >= 1) { - playerCount = 1; - result = result.replace("", selectedPlayers.get(0)); } return new PlayerReplaceResult(result, playerCount); } + /** * Ajoute le texte des gorgées à la question. */ @@ -130,9 +132,11 @@ public class GameEngine { int totalGorgees = question.getGorger() + addedGorgees; - // Accord du verbe selon le nombre de joueurs - String boisVerb = (playerCount > 1) ? "boivent" : "boit"; - String distribueVerb = (playerCount > 1) ? "distribuent" : "distribue"; + // Accord du verbe selon le véritable sujet de la phrase + boolean pluriel = isPluralSubject(questionText); + String boisVerb = pluriel ? "boivent" : "boit"; + String distribueVerb = pluriel ? "distribuent" : "distribue"; + // Déterminer si boire ou distribuer if (question.isRecois() && question.isDistribution()) { @@ -152,6 +156,31 @@ public class GameEngine { return sb.toString(); } + /** + * Indique si le sujet de la question est pluriel, pour accorder le verbe + * (boit/boivent, distribue/distribuent) ajouté en fin de question. + */ + private static boolean isPluralSubject(String questionText) { + String t = questionText.trim().toLowerCase(); + if (t.isEmpty()) { + return false; + } + // Sujet de groupe en tête de question : « Ceux qui… », « Les fans de… », « Tous ceux qui… » + if (t.startsWith("ceux") || t.startsWith("celles") || t.startsWith("tous ") || t.startsWith("toutes ") + || t.startsWith("les ")) { + return true; + } + // Sujet pluriel en toute fin de phrase, juste avant le verbe ajouté + String[] finsPlurielles = {"perdants", "joueurs", "joueuses", "gens", "ceux", "celles", "eux", "elles", + "abonnés", "abonnées", "végans", "célibataires", "filles", "garçons", "couples"}; + for (String fin : finsPlurielles) { + if (t.endsWith(fin)) { + return true; + } + } + return false; + } + /** * Sélectionne n joueurs aléatoires uniques. */ diff --git a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java index 54dbcaf..0a5a855 100644 --- a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java @@ -191,6 +191,24 @@ public class BoideloClassicGameActivity extends AppCompatActivity { if (result.isSuccess()) { Questions q = result.getData(); questions = q != null && q.getQuestions() != null ? q.getQuestions() : new ArrayList<>(); + + // Exclure les questions déjà posées lors des parties précédentes, + // pour qu'une question ne revienne pas tant que tout le stock n'a pas été épuisé + java.util.Set askedIds = questionRepository.getAskedQuestionIds(); + if (!askedIds.isEmpty()) { + List unasked = new ArrayList<>(); + for (Question question : questions) { + if (!askedIds.contains(String.valueOf(question.getId()))) { + unasked.add(question); + } + } + if (unasked.isEmpty()) { + // Toutes les questions ont été posées : on repart sur le stock complet + questionRepository.resetAskedQuestions(); + } else { + questions = unasked; + } + } } else { android.util.Log.e("BoideloClassicGame", "Erreur lors du chargement des questions: " + result.getError()); questions = new ArrayList<>(); @@ -407,10 +425,19 @@ public class BoideloClassicGameActivity extends AppCompatActivity { } askedQuestionIndices.add(questionIndex); + // Persistance : la question ne reviendra plus lors des prochaines parties + questionRepository.markQuestionAsAsked(question.getId()); return question; } - // Si on ne trouve pas de question valide, retourner une question aléatoire + // Si on ne trouve pas de question valide (toutes les restantes ont ), + // retourner une question non posée plutôt qu'une question au hasard + if (!availableIndices.isEmpty()) { + int fallbackIndex = availableIndices.get(random.nextInt(availableIndices.size())); + askedQuestionIndices.add(fallbackIndex); + questionRepository.markQuestionAsAsked(questions.get(fallbackIndex).getId()); + return questions.get(fallbackIndex); + } return questions.get(random.nextInt(questions.size())); } @@ -825,8 +852,10 @@ public class BoideloClassicGameActivity extends AppCompatActivity { question.setManchesRestantes(nbaleatoiremanches); // Définir le message de fin de défi - String stopMessage = "Fin de défi!\n" + questionText; - question.setArretMessageManche(stopMessage); + // Message de fin de défi : texte d'arrêt dédié s'il existe, sinon rappel de la consigne + String arret = question.getArret(); + String stopMessage = "Fin de défi !\n" + (arret != null && !arret.trim().isEmpty() ? arret : questionText); + questionsAvecManches.add(question); @@ -873,24 +902,25 @@ public class BoideloClassicGameActivity extends AppCompatActivity { if (isJoueurs1 || isJoueurs2 || isJoueurs3) { List aleatoirejoueurs = TroisJoueurAleatoire(); - if (isJoueurs1 && isJoueurs2 && isJoueurs3 && aleatoirejoueurs.size() >= RANDOM_PLAYER_SELECTION_COUNT) { - playerCount = 3; - j1Name = aleatoirejoueurs.get(0); - questionText = questionText.replace("", ErrorHandler.escapeHtml(j1Name)); - questionText = questionText.replace("", ErrorHandler.escapeHtml(aleatoirejoueurs.get(1))); - questionText = questionText.replace("", ErrorHandler.escapeHtml(aleatoirejoueurs.get(2))); - } else if (isJoueurs1 && isJoueurs2 && aleatoirejoueurs.size() >= TWO_PLAYERS) { - playerCount = 2; - j1Name = aleatoirejoueurs.get(0); - questionText = questionText.replace("", ErrorHandler.escapeHtml(j1Name)); - questionText = questionText.replace("", ErrorHandler.escapeHtml(aleatoirejoueurs.get(1))); - } else if (isJoueurs1 && aleatoirejoueurs.size() >= ONE_PLAYER) { - playerCount = 1; + // Chaque balise est remplacée indépendamment : une question contenant + // uniquement ou reste jouable (l'ordre J1, J2, J3 est conservé) + if (isJoueurs1 && aleatoirejoueurs.size() >= ONE_PLAYER) { + playerCount++; j1Name = aleatoirejoueurs.get(0); questionText = questionText.replace("", ErrorHandler.escapeHtml(j1Name)); } + if (isJoueurs2 && aleatoirejoueurs.size() >= TWO_PLAYERS) { + playerCount++; + questionText = questionText.replace("", ErrorHandler.escapeHtml(aleatoirejoueurs.get(1))); + } + if (isJoueurs3 && aleatoirejoueurs.size() >= RANDOM_PLAYER_SELECTION_COUNT) { + playerCount++; + questionText = questionText.replace("", ErrorHandler.escapeHtml(aleatoirejoueurs.get(2))); + } } + + return new PlayerSelectionResult(questionText, j1Name, playerCount); } @@ -949,15 +979,19 @@ public class BoideloClassicGameActivity extends AppCompatActivity { } /** - * Détermine l'action (boit/boivent ou distribue/distribuent) selon le nombre de joueurs + /** + * Détermine l'action (boit/boivent ou distribue/distribuent) selon le véritable + * sujet de la phrase, pour un accord grammatical correct. */ private ActionChoiceResult determineActionChoice(Question question, String questionText, int playerCount) { boolean isBois = false; boolean isDistribue = false; - // Accord du verbe selon le nombre de joueurs - String boisVerb = (playerCount > 1) ? "boivent" : "boit"; - String distribueVerb = (playerCount > 1) ? "distribuent" : "distribue"; + // Accord du verbe selon le sujet réel de la question + boolean pluriel = isPluralSubject(questionText); + String boisVerb = pluriel ? "boivent" : "boit"; + String distribueVerb = pluriel ? "distribuent" : "distribue"; + if (question.isRecois() && question.isDistribution()) { boolean rand = random.nextBoolean(); @@ -979,6 +1013,31 @@ public class BoideloClassicGameActivity extends AppCompatActivity { return new ActionChoiceResult(questionText, isBois, isDistribue); } + /** + * Indique si le sujet de la question est pluriel, pour accorder le verbe + * (boit/boivent, distribue/distribuent) ajouté en fin de question. + */ + private boolean isPluralSubject(String questionText) { + String t = questionText.trim().toLowerCase(); + if (t.isEmpty()) { + return false; + } + // Sujet de groupe en tête de question : « Ceux qui… », « Les fans de… », « Tous ceux qui… » + if (t.startsWith("ceux") || t.startsWith("celles") || t.startsWith("tous ") || t.startsWith("toutes ") + || t.startsWith("les ")) { + return true; + } + // Sujet pluriel en toute fin de phrase, juste avant le verbe ajouté + String[] finsPlurielles = {"perdants", "joueurs", "joueuses", "gens", "ceux", "celles", "eux", "elles", + "abonnés", "abonnées", "végans", "célibataires", "filles", "garçons", "couples"}; + for (String fin : finsPlurielles) { + if (t.endsWith(fin)) { + return true; + } + } + return false; + } + /** * Ajoute le nombre de gorgées au texte de la question */