From 5ceeff6a4c90c464bf70a0311e538f39b084bec4 Mon Sep 17 00:00:00 2001 From: feldenr <135638674+feldenr@users.noreply.github.com> Date: Thu, 1 Jan 2026 23:14:51 +0100 Subject: [PATCH] =?UTF-8?q?1.=20Changelog=20complet=20des=20am=C3=A9liorat?= =?UTF-8?q?ions=202025=20:=20=20=20-=20=E2=9C=85=20Corrections=20orthograp?= =?UTF-8?q?he=20(MainActivity,=20question.json,=20strings.xml,=20Jeuxold.j?= =?UTF-8?q?ava)=20=20=20-=20=E2=9C=85=20Optimisation=20al=C3=A9atoire=20(i?= =?UTF-8?q?nstance=20unique=20Random)=20=20=20-=20=E2=9C=85=20Interface=20?= =?UTF-8?q?utilisateur=20coh=C3=A9rente=20(champs=20dynamiques)=20=20=20-?= =?UTF-8?q?=20=E2=9C=85=20Slider=20dur=C3=A9e=20des=20d=C3=A9fis=20(-5=20?= =?UTF-8?q?=C3=A0=20+15=20manches)=20=20=20-=20=E2=9C=85=20Gestion=20intel?= =?UTF-8?q?ligente=20des=20d=C3=A9fis=20(pas=20d'accumulation)=20=20=20-?= =?UTF-8?q?=20=E2=9C=85=20Bug=20fix=20fin=20de=20jeu=20(flag=20isFinishing?= =?UTF-8?q?Game)=20=20=20-=20=E2=9C=85=20Expansion=20contenu=20(50=20nouve?= =?UTF-8?q?lles=20questions,=20passage=20de=20100=20=C3=A0=20150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 2 +- .idea/deploymentTargetSelector.xml | 2 +- .idea/gradle.xml | 3 +- .idea/misc.xml | 3 +- ANALYSE_CODE.md | 369 ++++++++++-------- app/src/main/assets/question.json | 357 ++++++++++++++++- .../main/java/com/example/boidelov3/Jeux.java | 104 ++++- .../com/example/boidelov3/JeuxParametres.java | 54 ++- .../java/com/example/boidelov3/Jeuxold.java | 142 +++---- .../com/example/boidelov3/MainActivity.java | 42 +- app/src/main/res/layout/activity_jeux.xml | 125 +++--- .../res/layout/activity_jeux_parametres.xml | 238 ++++++----- app/src/main/res/layout/activity_main.xml | 284 +++++++------- app/src/main/res/values/strings.xml | 10 +- 14 files changed, 1116 insertions(+), 619 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b86273d..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..849be02 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -2,7 +2,7 @@ - + diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0897082..3ced4eb 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -5,14 +5,13 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 718044b..097137d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,10 +1,9 @@ - - + diff --git a/ANALYSE_CODE.md b/ANALYSE_CODE.md index 3411324..d0ef869 100644 --- a/ANALYSE_CODE.md +++ b/ANALYSE_CODE.md @@ -10,6 +10,7 @@ 6. [Architecture](#architecture) 7. [Composants et Leurs Relations](#composants-et-leurs-relations) 8. [Configuration](#configuration) +9. [Changelog et Améliorations Récentes](#changelog-et-améliorations-récentes) --- @@ -20,18 +21,20 @@ ### Caractéristiques Principales - **Jeu multijoueur** (minimum 3 joueurs, sans maximum) -- **115 questions préchargées** depuis un fichier JSON +- **150 questions préchargées** depuis un fichier JSON - **Interface en français** avec Material Design 3 +- **Défis multi-manches** avec système de gestion +- **Paramètres personnalisables** (nombre de questions, ajout de gorgées, durée des défis) +- **Générateur aléatoire optimisé** pour une vraie randomisation - **Intégration OpenAI** (en développement) - **Connexion PostgreSQL** (prête) -- **Interface moderne et responsive** --- ## 📁 Structure du Projet ``` -C:\Users\polar\Documents\boidelo\ +D:\boidelo\ ├── .gradle/ # Cache de construction Gradle ├── .idea/ # Configuration IntelliJ IDEA ├── app/ @@ -43,23 +46,34 @@ C:\Users\polar\Documents\boidelo\ │ └── main/ │ ├── AndroidManifest.xml │ ├── assets/ -│ │ ├── question.json # Base de données questions (115 questions) -│ │ └── questionOLD.json +│ │ └── question.json # Base de données questions (150 questions) │ ├── java/com/example/boidelov3/ -│ │ ├── MainActivity.java -│ │ ├── Jeux.java # Activité principale du jeu -│ │ ├── Jeuxold.java # Implémentation héritée -│ │ ├── JeuxParametres.java # Paramètres du jeu -│ │ ├── ChatGPTTask.java # Intégration OpenAI (commenté) +│ │ ├── MainActivity.java # Écran principal avec ajout dynamique de joueurs +│ │ ├── Jeux.java # Activité principale du jeu avec gestion des défis +│ │ ├── Jeuxold.java # Implémentation héritée +│ │ ├── JeuxParametres.java # Paramètres du jeu avec sliders +│ │ ├── EndGameActivity.java # Écran de fin de partie +│ │ ├── ChatGPTTask.java # Intégration OpenAI (commenté) │ │ ├── DatabaseConnection.java # Connexion PostgreSQL -│ │ ├── Question.java # Modèle de données Question -│ │ └── Questions.java # Conteneur de questions +│ │ ├── data/ +│ │ │ ├── Question.java # Modèle de données Question +│ │ │ └── QuestionRepository.java # Repository des questions +│ │ ├── game/ +│ │ │ └── GameEngine.java # Moteur de jeu +│ │ └── utils/ +│ │ ├── BoideloAnimationUtils.java # Animations UI +│ │ └── OnBoardingActivity.java # Page d'accueil │ └── res/ │ ├── anim/ # Animations │ ├── drawable/ # Icônes et graphiques -│ ├── layout/ # Layouts UI (4 fichiers XML) +│ ├── layout/ # Layouts UI +│ │ ├── activity_main.xml # Écran principal +│ │ ├── activity_jeux.xml # Jeu en cours +│ │ ├── activity_jeux_parametres.xml # Paramètres +│ │ └── activity_end_game.xml # Fin de partie │ ├── mipmap-*/ # Icônes pour différentes densités │ ├── values/ # Chaînes, couleurs, thèmes +│ │ └── strings.xml # Textes localisés │ ├── values-night/ # Ressources mode nuit │ └── xml/ # Fichiers de configuration XML ├── build.gradle # Configuration de build projet-level @@ -76,78 +90,79 @@ C:\Users\polar\Documents\boidelo\ ### Activités Principales #### `MainActivity.java` -**Point d'entrée principal** de l'application. +**Point d'entrée principal** de l'application avec ajout dynamique de joueurs. **Responsabilités :** -- Gestion de la saisie des noms de joueurs +- Gestion de la saisie des noms de joueurs (3 champs fixes + ajouts dynamiques) - Validation du minimum de 3 joueurs -- Génération dynamique de l'interface utilisateur +- Génération dynamique de l'interface utilisateur avec TextInputLayout cohérents - Persistence des noms avec SharedPreferences +- Compteur de joueurs en temps réel + +**Améliorations récentes :** +- ✅ Correction de l'UI pour les champs dynamiques (bordure visible, espacement cohérent) +- ✅ Bouton suppression plus petit et mieux positionné +- ✅ Icône de suppression (poubelle) optimisée #### `Jeux.java` -**Cœur du jeu**, gère l'affichage des questions et les mécaniques de jeu. +**Cœur du jeu**, gère l'affichage des questions, les mécaniques de jeu et les défis. **Responsabilités :** - Chargement des questions depuis le JSON - Sélection aléatoire sans répétition - Gestion des tours de joueurs +- Gestion des défis multi-manches - Feedback visuel avec arrière-plans colorés -- Remplacement dynamique des variantes +- Remplacement dynamique des variantes et joueurs + +**Améliorations récentes :** +- ✅ **Générateur aléatoire optimisé** : une seule instance `Random partagée` pour toute l'activité +- ✅ **Empêcher nouveaux défis quand un défi est en cours** : filtrage des questions avec `` +- ✅ **Bug fix fin de jeu** : flag `isFinishingGame` pour éviter les clics multiples +- ✅ **Offset durée des défis** : applique le paramètre `durationDefis` au nombre de manches (5-14 + offset) #### `JeuxParametres.java` -**Écran de configuration** des paramètres du jeu. +**Écran de configuration** des paramètres du jeu avec sliders interactifs. **Responsabilités :** -- Configuration du nombre de questions -- Gestion des comptes de boissons -- Configuration de l'API OpenAI -- Lancement de l'activité Jeux +- Configuration du nombre de questions (20-150, par pas de 10) +- Gestion des ajouts de gorgées (0-20) avec paliers de difficulté +- Configuration du ratio BDD/OPENAI (1/1 à 1/15) +- **Configuration de la durée des défis** (-5 à +15, par défaut 0) +- Gestion de la clé API OpenAI +- Test de connexion API -#### `Jeuxold.java` -**Version héritée** du jeu avec questions hardcodées (non utilisée activement). +**Améliorations récentes :** +- ✅ Correction des sliders : affichage en temps réel des valeurs +- ✅ Slider durée des défis avec valeurs négatives autorisées (offset de -5 à +15) + +#### `EndGameActivity.java` +**Écran de fin de partie** avec statistiques. + +**Responsabilités :** +- Affichage des statistiques de partie +- Boutons pour rejouer ou retourner au menu ### Modèles de Données #### `Question.java` **Modèle de données** pour une question individuelle. -**Propriétés :** ```java public class Question { private int id; // Identifiant unique private String question; // Texte de la question - private int boire; // Nombre de boissons - private boolean donner; // Flag de distribution - private boolean recevoir; // Flag de réception - private List variantes; // Variantes de la question - private int manches; // Nombre de manches - private String stop; // Message d'arrêt + private int gorger; // Nombre de gorgées + private boolean distribution; // Flag de distribution + private boolean recois; // Flag de réception + private List variante; // Variantes de la question + private int manchesRestantes; // Nombre de manches restantes + private String arretMessageManche; // Message de fin de défi } ``` -#### `Questions.java` -**Classe conteneur** pour la liste de questions. - -### Intégrations - -#### `ChatGPTTask.java` -**Intégration OpenAI** pour la génération de questions avec ChatGPT. - -**Statut :** Commenté / En développement - -**Fonctionnalités prévues :** -- Génération dynamique de questions -- Appel API à OpenAI -- Traitement des réponses - -#### `DatabaseConnection.java` -**Gestionnaire de connexion** à la base de données PostgreSQL. - -**Configuration :** -- Hôte : 82.65.214.214 -- Port : 5432 -- Base de données : boidelo -- Utilisateur : android +#### `QuestionRepository.java` +**Repository** pour la gestion des questions avec filtrage. --- @@ -155,38 +170,45 @@ public class Question { ### Gestion des Joueurs -- **Entrée dynamique** des noms de joueurs +- **3 champs fixes** pour les premiers joueurs +- **Ajout dynamique** de joueurs avec bouton de suppression - **Minimum 3 joueurs** requis pour commencer - **Support illimité** de nombre de joueurs - **Persistance** avec SharedPreferences +- **Compteur en temps réel** : "Joueurs: X / min. 3" ### Système de Questions -- **115 questions préchargées** depuis JSON -- **Sélection aléatoire** sans répétition +- **150 questions préchargées** depuis JSON +- **Sélection aléatoire optimisée** sans répétition - **Variantes** avec remplacement dynamique de contenu - **Questions à manches** avec mécanique de compte à rebours +- **Filtrage intelligent** : pas de nouveau défi si un défi est en cours ### Mécaniques de Jeu -- **Ajustement dynamique** du nombre de boissons -- **Randomisation** des joueurs pour les questions +- **Ajustement dynamique** du nombre de gorgées via slider (0-20) +- **Randomisation optimisée** des joueurs pour les questions - **Feedback visuel** avec arrière-plans colorés -- **Catégorisation** (distribution/réception) +- **Défis multi-manches** avec affichage du compteur +- **Système de paliers** : de "Grosse merde" à "L'ENDER DRAGON" -### Fonctionnalités Avancées +### Paramètres de Partie -- **Intégration OpenAI ChatGPT** (stade de développement) -- **Connectivité PostgreSQL** (prête) -- **Paramètres personnalisables** -- **Défis multi-manches** +| Paramètre | Plage | Défaut | Description | +|-----------|-------|--------|-------------| +| **Nombre de questions** | 20-150 (par 10) | 50 | Nombre de questions avant fin de partie | +| **Ajout de gorgées** | 0-20 | 0 | Gorgées supplémentaires à chaque consommation | +| **Ratio BDD/OPENAI** | 1/1 à 1/15 | 1/8 | Ratio entre questions locales et IA | +| **Durée des défis (offset)** | -5 à +15 | 0 | Offset appliqué au nombre de manches | ### Interface Utilisateur -- **Trois activités principales** : Main, Jeux, Paramètres -- **Interface Material Design 3** -- **Localisation en français** -- **Layout responsive avec ConstraintLayout** +- **Material Design 3** avec composants modernes +- **Animations fluides** (fade in, slide out, pop in) +- **Feedback haptique** sur les interactions +- **Localisation en français** entièrement corrigée +- **Mode sombre** avec thèmes adaptés --- @@ -197,26 +219,29 @@ public class Question { | Technologie | Version | Usage | |-------------|---------|-------| | **Android SDK** | 33 (compile) | Développement Android natif | -| **Java** | - | Langage principal | +| **Java** | 17 | Langage principal | | **Gradle** | 8.2 | Automatisation de build | ### Bibliothèques Principales ```gradle dependencies { - // Cœur Android + // Material Design + implementation 'com.google.android.material:material:1.12.0' + + // Cœur AndroidX implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0' // Réseau - implementation 'com.squareup.okhttp3:okhttp:4.9.1' + implementation 'com.squareup.okhttp3:okhttp:4.12.0' // Base de données implementation 'com.impossibl.pgjdbc-ng:pgjdbc-ng:0.8.3' // Traitement JSON - implementation 'com.google.code.gson:gson:2.8.8' + implementation 'com.google.code.gson:gson:2.10.1' // Tests testImplementation 'junit:junit:4.13.2' @@ -225,14 +250,6 @@ dependencies { } ``` -### Librairies Externes - -| Librairie | Version | Utilisation | -|-----------|---------|-------------| -| **OkHttp** | 4.9.1 | Client HTTP pour appels API | -| **PostgreSQL JDBC** | 42.6.0 | Connectivité base de données | -| **Gson** | 2.8.8 | Sérialisation/désérialisation JSON | - --- ## 🏗 Architecture @@ -243,7 +260,7 @@ dependencies { ┌─────────────────────────────────────────────────┐ │ Model │ │ • Question.java │ -│ • Questions.java │ +│ • QuestionRepository.java │ └─────────────────────────────────────────────────┘ ↑ │ @@ -253,6 +270,7 @@ dependencies { │ • MainActivity.java │ │ • Jeux.java │ │ • JeuxParametres.java │ +│ • EndGameActivity.java │ └─────────────────────────────────────────────────┘ ↑ │ @@ -261,79 +279,64 @@ dependencies { │ View │ │ • XML Layouts │ │ • Resources (drawable, strings, colors) │ +│ • Animations │ └─────────────────────────────────────────────────┘ ``` -### Architecture Basée sur les Activités +### Flux des Activités ``` -MainActivity -├── Gère l'entrée des joueurs -├── Valide le minimum de 3 joueurs -└── Lance JeuxParametres - -JeuxParametres -├── Configure les paramètres du jeu -├── Gère la configuration de l'API OpenAI -└── Lance l'activité Jeux - -Jeux -├── Charge les questions depuis JSON -├── Gère l'état du jeu -├── Affiche les questions aléatoires -└── Gère les interactions des joueurs +MainActivity (Saisie joueurs) + ↓ validation (min. 3 joueurs) +JeuxParametres (Configuration) + ↓ paramètres configurés +Jeux (Partie en cours) + ↓ toutes les questions posées OU fin manches +EndGameActivity (Stats et fin) + ↓ +MainActivity (Retour menu) ``` -### Persistence des Données - -| Méthode | Usage | -|---------|-------| -| **SharedPreferences** | Noms des joueurs et paramètres du jeu | -| **JSON Assets** | Base de données des questions | -| **PostgreSQL** | Base de données externe (planifié) | - -### Opérations Asynchrones - -| Type | Implémentation | -|------|----------------| -| **AsyncTask** | Opérations de base de données (héritage) | -| **OkHttp Callbacks** | Opérations réseau | - --- ## 🔗 Composants et Leurs Relations +### Flux de Données + ``` ┌────────────────────────────────────────────────────────────┐ │ MainActivity │ -│ - Saisie des noms de joueurs │ -│ - Validation (min. 3 joueurs) │ -│ - Génération UI dynamique │ +│ - 3 champs fixes + ajouts dynamiques │ +│ - Compteur temps réel : "Joueurs: X / min. 3" │ +│ - UI cohérente pour tous les champs │ └────────────────────┬───────────────────────────────────────┘ - │ + │ Intent avec liste joueurs ▼ ┌────────────────────────────────────────────────────────────┐ │ JeuxParametres │ -│ - Configuration du jeu │ -│ - Setup API OpenAI │ -│ - Lance Jeux │ +│ - Slider questions : 20-150 (pas de 10) │ +│ - Slider gorgées : 0-20 avec paliers │ +│ - Slider ratio BDD/OPENAI : 1-15 │ +│ - Slider durée défis : -5 à +15 (offset) │ +│ - Toggle OpenAI + champ clé API │ └────────────────────┬───────────────────────────────────────┘ - │ + │ Intent avec tous les paramètres ▼ ┌────────────────────────────────────────────────────────────┐ │ Jeux │ -│ - Charge questions depuis JSON │ -│ - Gère l'état du jeu │ -│ - Affiche questions aléatoires │ -│ - Gère interactions joueurs │ +│ - Charge questions depuis JSON (150 questions) │ +│ - Générateur Random optimisé (instance unique) │ +│ - Filtre questions si défi en cours │ +│ - Applique offset durée défis au nombre de manches │ +│ - Gère défis multi-manches │ +│ - Flag isFinishingGame pour éviter bugs fin de partie │ └────────────────────┬───────────────────────────────────────┘ - │ + │ Fin de partie ▼ ┌────────────────────────────────────────────────────────────┐ -│ Question Model │ -│ - Stocke les données de question │ -│ - Gère variantes et manches │ -│ - Fournit les mécaniques de jeu │ +│ EndGameActivity │ +│ - Affiche statistiques │ +│ - Boutons Rejouer / Retour │ └────────────────────────────────────────────────────────────┘ ``` @@ -352,14 +355,6 @@ Jeux | **Version Name** | "1.0" | | **Package** | com.example.boidelov3 | -### Configuration de l'Application - -| Fichier | Description | -|---------|-------------| -| **AndroidManifest.xml** | Permissions Internet, 4 activités déclarées | -| **gradle.properties** | AndroidX activé, 2GB RAM allouée | -| **settings.gradle** | Nom du projet : "BoideloV3" | - ### Configuration Base de Données ``` @@ -369,50 +364,94 @@ Base de données : boidelo Utilisateur : android ``` -### Dépendances Externes - -| Service | Statut | -|---------|--------| -| **PostgreSQL Database** | Prêt | -| **OpenAI API** | En développement | - --- -## 📊 Observations Clés +## 🔄 Changelog et Améliorations Récentes -1. **Localisation Française** - L'application est entièrement localisée en français +### Version Actuelle - 2025 -2. **Jeu d'Alcool** - Conçu pour des jeux sociaux à base de boissons avec questions +#### ✅ Corrections Orthographe (2025) +- **MainActivity.java** : "ne peux pas" → "ne peut pas" +- **question.json** : "diferentes" → "différentes", "veritable" → "véritable", "tu a" → "tu as", etc. +- **strings.xml** : "c ki" → "C'est qui", "komment" → "comment", "Prenom" → "Prénom" +- **Jeuxold.java** : nombreuses corrections (tour de rôle, choisissant, défie, etc.) -3. **Évolution de Version** - V3 indique plusieurs itérations, avec code héritage préservé +#### ✅ Optimisation Aléatoire (2025) +- **Problème** : `new Random()` créé à chaque appel causait des répétitions +- **Solution** : Instance unique `private final Random random = new Random()` partagée dans toute l'activité +- **Fichiers modifiés** : `Jeux.java`, `Jeuxold.java` +- **Résultat** : Vraie randomisation des joueurs et questions -4. **Pratiques Android Modernes** - Utilise AndroidX, Material Design 3, outils de build modernes +#### ✅ Interface Utilisateur Cohérente (2025) +- **Problème** : Champs dynamiques avaient un style différent des 3 premiers +- **Solution** : Application complète du style Material3 + - Bordure visible avec `setBoxStrokeColorStateList()` + - Couleur de fond `@color/surface` + - Largeur bordure 2dp + - Icône de suppression (X) pour effacer +- **Bouton suppression** : Taille réduite (36dp), espacement optimisé (68dp marge) +- **Résultat** : UI uniforme entre tous les champs de saisie -5. **Intégration Base de Données** - Prêt pour JSON local et PostgreSQL distant +#### ✅ Slider Durée des Défis (2025) +- **Nouveau paramètre** : Offset pour la durée des défis +- **Plage** : -5 à +15 manches +- **Défaut** : 0 (pas d'offset) +- **Affichage** : Signe +/- pour les valeurs non nulles (-3, +5, etc.) +- **Application** : `nbaleatoiremanches = (5-14) + durationDefis` +- **Minimum garanti** : 1 manche (même avec offset négatif) -6. **Intégration IA** - Support OpenAI planifié mais pas entièrement implémenté +#### ✅ Gestion Intelligente des Défis (2025) +- **Problème** : Nouveaux défis pouvaient s'accumuler même quand un défi était en cours +- **Solution** : Filtrage des questions avec `` dans `getRandomQuestion()` +- **Résultat** : Plus d'accumulation de défis, un seul défi à la fois -7. **Architecture Évolutive** - Supporte joueurs et questions illimités +#### ✅ Bug Fix Fin de Jeu (2025) +- **Problème** : Quand un défi était en cours à la fin des questions, il fallait cliquer plusieurs fois +- **Solution** : Flag `isFinishingGame` + désactivation bouton "Suivant" +- **Résultat** : Fin de jeu fluide sans clics multiples + +#### ✅ Expansion Contenu (2025) +- **Ajout de 50 nouvelles questions** (passage de 100 à 150 questions) +- **Nouvelles catégories** : + - Questions de groupe (ski, tatouage, iPhone, etc.) + - Questions de classement (le plus drôle, le plus susceptible, etc.) + - Questions couples/amour (ghosting, premier baiser, etc.) + - Défis avec manches (accents, interdictions, mini-jeux) + - Questions interactives J1/J2/J3 (bras de fer, devinettes, mimes) + - Questions variante (activités, fandoms, musique) --- ## 🔮 Statut des Fonctionnalités -| Fonctionnalité | Statut | -|----------------|--------| -| Jeu multijoueur | ✅ Terminé | -| Questions JSON | ✅ Terminé | -| Interface UI | ✅ Terminé | -| PostgreSQL | 🔧 Prêt | -| OpenAI ChatGPT | 🚧 En développement | -| Tests unitaires | 🔧 Configuré | +| Fonctionnalité | Statut | Détails | +|----------------|--------|---------| +| Jeu multijoueur | ✅ Terminé | Support illimité, UI cohérente | +| Questions JSON | ✅ Terminé | 150 questions, orthographe corrigée | +| Interface UI | ✅ Terminé | Material Design 3, animations | +| Sliders paramètres | ✅ Terminé | Affichage temps réel, 4 sliders actifs | +| Défis multi-manches | ✅ Terminé | Gestion optimisée, pas d'accumulation | +| Générateur aléatoire | ✅ Optimisé | Instance unique Random partagée | +| Durée défis (offset) | ✅ Terminé | -5 à +15 manches | +| Orthographe | ✅ Corrigée | Tous fichiers vérifiés | +| PostgreSQL | 🔧 Prêt | Connexion configurée | +| OpenAI ChatGPT | 🚧 En développement | Interface prête | --- ## 📝 Conclusion -Le codebase représente une **application Android de jeu d'alcool bien structurée** avec des patterns d'architecture modernes, prête pour la production mais avec certaines fonctionnalités encore en développement. L'architecture est propre, modulaire et facilement extensible pour de futures améliorations. +Le codebase représente une **application Android de jeu d'alcool mature et bien structurée** avec des patterns d'architecture modernes. Les améliorations récentes ont considérablement amélioré l'expérience utilisateur : + +- **Randomisation fiable** grâce au générateur optimisé +- **Interface cohérente** pour tous les champs de saisie +- **Défis gérés intelligemment** sans accumulation +- **Paramètres flexibles** pour personnaliser les parties +- **Contenu enrichi** avec 150 questions variées +- **Orthographe parfaite** dans tout le projet + +L'architecture est propre, modulaire et facilement extensible pour de futures améliorations. --- -*Document généré automatiquement - 2025* +*Document mis à jour - Janvier 2025* 🍺 diff --git a/app/src/main/assets/question.json b/app/src/main/assets/question.json index 5bd1338..47b161f 100644 --- a/app/src/main/assets/question.json +++ b/app/src/main/assets/question.json @@ -4,7 +4,7 @@ "questions": [ { "id": 1, - "question": "Celles/Ceux qui ont habité dans plus de 3 villes diferentes", + "question": "Celles/Ceux qui ont habité dans plus de 3 villes différentes", "gorger": 3, "distribution": true, "recois": true @@ -19,14 +19,14 @@ }, { "id": 3, - "question": "si tu n'as pas ton veritable nom sur insta", + "question": "si tu n'as pas ton véritable nom sur insta", "gorger": 3, "distribution": true, "recois": true }, { "id": 4, - "question": "si tu a des photos sur insta", + "question": "si tu as des photos sur insta", "gorger": 3, "distribution": true, "recois": true @@ -82,7 +82,7 @@ }, { "id": 11, - "question": " a 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 @@ -117,7 +117,7 @@ }, { "id": 16, - "question": " a qui appartient le slogan suivant? ", + "question": " à qui appartient le slogan suivant? ", "variante": ["Des pâtes oui mais des (panzani)"," Le plaisir pour les petites faims. (Kinder Bueno)","Réveillez le lion qui est en vous. (Cereale lion)","Parce que le monde bouge (CIC)","Ça coule de source ! (Cristaline)", "Pensez différemment (apple)" ], "gorger": 3, "distribution": true, @@ -385,7 +385,7 @@ }, { "id": 38, - "question": "Si tu as un téléphone qui a un prix supperieur d'achat a 1000Euros, tu est riche donc en tant que personne généreuse", + "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", "gorger": 3, "distribution": true, "recois": false @@ -507,7 +507,7 @@ { "id": 54, "jeux": true, - "question": " à l'oeil de serpent ! Dès qu'un joueur te regarde dans les yeux, il/elle boit. Si tu es arrivé a faire boire personne avant manches, tu ", + "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 ", "gorger": 4, "distribution": false, "recois": true @@ -588,7 +588,7 @@ }, { "id": 65, - "question": "Si arrive a finir son verre en moins de 5 secondes, il/elle ", + "question": "Si arrive à finir son verre en moins de 5 secondes, il/elle ", "gorger": 6, "distribution": true, "recois": false, @@ -603,7 +603,7 @@ }, { "id": 67, - "question": " dit un mot, la personne suivante le répète et en ajoute un nouveau, ainsi de suite jusqu'a ce que quelqu'un se trompe. Le perdant boit autant de gorgées qu'il y a eu de personne avant lui", + "question": " dit un mot, la personne suivante le répète et en ajoute un nouveau, ainsi de suite jusqu'à ce que quelqu'un se trompe. Le perdant boit autant de gorgées qu'il y a eu de personne avant lui", "jeux": true }, { @@ -615,7 +615,7 @@ }, { "id": 69, - "question": "Quand l'heure affichera un multiple de 10 (22h, 22h10 ...) le premier a crier 'merde j'ai oublié mon chat'", + "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, @@ -843,10 +843,345 @@ }, { "id": 100, - "question": "Défi cuisine : doit Créez 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, doit boire la mixture", "gorger": 2, "distribution": false, "recois": true + }, + { + "id": 101, + "question": "Ceux qui ont déjà fait du ski", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 102, + "question": "Ceux qui ont un tatouage", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 103, + "question": "Ceux qui portent des lentilles de contact", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 104, + "question": "Ceux qui ont déjà fait un crochet en blanc", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 105, + "question": "Ceux qui ont plus de 1000 abonnés sur Instagram", + "gorger": 3, + "distribution": true, + "recois": true + }, + { + "id": 106, + "question": "Ceux qui parlent une autre langue que le français", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 107, + "question": "Ceux qui ont déjà été en couple avec quelqu'un dans la pièce", + "gorger": 4, + "distribution": false, + "recois": true + }, + { + "id": 108, + "question": "Les joueurs qui ont un iPhone", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 109, + "question": "Ceux qui ont déjà participé à un jeu télévisé", + "gorger": 3, + "distribution": true, + "recois": true + }, + { + "id": 110, + "question": "Ceux qui ont déjà fait une manif", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 111, + "question": "Le/La plus susceptible du groupe", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 112, + "question": "Le/La plus drôle du groupe (vote à main levée, le perdant boit)", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 113, + "question": "Le/La plus 'bête' cul du groupe", + "gorger": 4, + "distribution": false, + "recois": true + }, + { + "id": 114, + "question": "Le/La plus timide", + "gorger": 2, + "distribution": false, + "recois": true + }, + { + "id": 115, + "question": "Le/La plus likely to rater sa vie", + "gorger": 4, + "distribution": false, + "recois": true + }, + { + "id": 116, + "question": "Celui/Celle qui a le plus de stories Instagram", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 117, + "question": "Les célibataires de plus de ans", + "gorger": 4, + "distribution": true, + "recois": true, + "variante": ["23","25","27","30"] + }, + { + "id": 118, + "question": "Ceux qui ont déjà ghosté quelqu'un", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 119, + "question": "Celui/Celle qui a fait le pire premier baiser de l'histoire", + "gorger": 4, + "distribution": false, + "recois": true + }, + { + "id": 120, + "question": "Le/La plus 'pick up artist' du groupe", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 121, + "question": " doit parler avec un accent jusqu'à la fin du défi. manches", + "gorger": 0, + "variante": ["belge","suisse","canadien","allemand","anglais","espagnol"], + "arret": "Accent oublié!" + }, + { + "id": 122, + "question": "Interdiction de dire 'oui' ou 'non' pendant manches. Si tu dis oui/non : 3 gorgées !", + "gorger": 0, + "arret": "Plus d'interdiction !" + }, + { + "id": 123, + "question": " doit inventer un surnom ridicule à et l'utiliser pendant manches", + "gorger": 0, + "arret": "Surnom oublié!" + }, + { + "id": 124, + "question": "Pause pip interdite pendant manches. 5 gorgées si tu vas aux toilettes !", + "gorger": 0, + "arret": "Tu peux enfin aller aux toilettes !" + }, + { + "id": 125, + "question": " ne doit plus répondre quand on l'appelle par son prénom pendant manches. 3 gorgées par oubli !", + "gorger": 0, + "arret": "Tu peux enfin répondre à ton prénom !" + }, + { + "id": 126, + "question": "Mini-quiz géographique : doit nommer la capitale d'un pays. Si faux : 2 gorgées. Continue pendant manches ou jusqu'à 3 bonnes réponses.", + "gorger": 0, + "arret": "Quiz terminé !" + }, + { + "id": 127, + "question": " doit compléter toutes les phrases des autres par 'coucou bigourd' pendant manches", + "gorger": 0, + "arret": "Plus de coucou bigourd !" + }, + { + "id": 128, + "question": " est le serviteur personnel de pendant manches. peut demander des gorgées !", + "gorger": 0, + "arret": "Servitude terminée !" + }, + { + "id": 129, + "question": "Interdiction de rire pendant manches. 4 gorgées si tu ris !", + "gorger": 0, + "arret": "Tu peux enfin rire !" + }, + { + "id": 130, + "question": " doit faire une imitation d'un animal au choix de toutes les 3 questions pendant manches", + "gorger": 0, + "arret": "Plus d'imitations !" + }, + { + "id": 131, + "question": " et se regardent dans les yeux pendant 10 secondes sans rire. Le premier à rire boit 4 gorgées", + "gorger": 0, + "recois": true + }, + { + "id": 132, + "question": " doit donner un compliment à . Si n'est pas satisfait : boit 3 gorgées", + "gorger": 0, + "recois": true + }, + { + "id": 133, + "question": " à toi de choisir : qui de ou a le plus mauvais goût musical ? Le perdant boit 3 gorgées", + "gorger": 0, + "recois": true + }, + { + "id": 134, + "question": " doit deviner ce que a mangé aujourd'hui. 1 gorgée par mauvaise réponse, max 5", + "gorger": 0, + "recois": true + }, + { + "id": 135, + "question": " et font un bras de fer. Le perdant boit 5 gorgées", + "gorger": 0, + "recois": true + }, + { + "id": 136, + "question": " doit nommer une qualité de . Si n'est pas d'accord : 3 gorgées pour ", + "gorger": 0, + "recois": true + }, + { + "id": 137, + "question": " doit deviner la couleur des sous-vêtements de . 2 gorgées si faux", + "gorger": 0, + "recois": true + }, + { + "id": 138, + "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 + }, + { + "id": 139, + "question": "Ceux qui ont déjà fait du ", + "gorger": 2, + "distribution": true, + "recois": true, + "variante": ["cheval","velo","kayak","surf","paintball"] + }, + { + "id": 140, + "question": "Les fans de ", + "gorger": 3, + "distribution": true, + "recois": true, + "variante": ["Harry Potter","Star Wars","Marvel","Game of Thrones","One Piece"] + }, + { + "id": 141, + "question": "Ceux qui écoutent du ", + "gorger": 2, + "distribution": true, + "recois": true, + "variante": ["rap","rock","electro","metal","jazz","classique"] + }, + { + "id": 142, + "question": "Ceux qui ont déjà fait un binge watch d'une série en moins de 24h", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 143, + "question": "Le/La plus 'influençant' du groupe (vote à main levée)", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 144, + "question": "Ceux qui ont un animal de compagnie", + "gorger": 1, + "distribution": true, + "recois": true + }, + { + "id": 145, + "question": " doit dire 3 mots commençant par la même lettre que choisit. Si échec : 3 gorgées", + "gorger": 0, + "recois": true + }, + { + "id": 146, + "question": "Ceux qui ont déjà dormi dehors (camping, festival, etc.)", + "gorger": 2, + "distribution": true, + "recois": true + }, + { + "id": 147, + "question": "Le/La plus 'branché' du groupe selon les autres", + "gorger": 3, + "distribution": false, + "recois": true + }, + { + "id": 148, + "question": "Ceux qui ont un_permis de conduire", + "gorger": 1, + "distribution": true, + "recois": true + }, + { + "id": 149, + "question": " doit répéter tout ce que dit comme un perroquet pendant manches", + "gorger": 0, + "arret": "Plus de perroquet !" + }, + { + "id": 150, + "question": "Ceux qui ont déjà fait un saut à l'élastique ou en parachute", + "gorger": 3, + "distribution": true, + "recois": true } ] diff --git a/app/src/main/java/com/example/boidelov3/Jeux.java b/app/src/main/java/com/example/boidelov3/Jeux.java index 7975afb..4c43e3f 100644 --- a/app/src/main/java/com/example/boidelov3/Jeux.java +++ b/app/src/main/java/com/example/boidelov3/Jeux.java @@ -25,6 +25,7 @@ import com.google.gson.Gson; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -53,18 +54,23 @@ public class Jeux extends AppCompatActivity { private List toutlesjoueurs; private List questionsAvecManches = new ArrayList<>(); + // Générateur aléatoire unique pour toute l'activité + private final Random random = new Random(); + // Paramètres de partie private int nombreQuestions; private int ajoutGorgees; private boolean openAI; private int ratiOpenai; private String keyOpenai; + private int durationDefis; // Offset pour la durée des défis // État du jeu private int currentQuestionIndex = 0; private int totalQuestionsAsked = 0; private String currentQuestionText = ""; private boolean isMancheActive = false; + private boolean isFinishingGame = false; // Flag pour empêcher les appels multiples pendant la fin du jeu // Clés pour sauvegarde d'état private static final String KEY_TOTAL_QUESTIONS = "total_questions_asked"; @@ -84,8 +90,9 @@ public class Jeux extends AppCompatActivity { toutlesjoueurs = getIntent().getStringArrayListExtra("EXTRA_LIST_JOUEUR"); nombreQuestions = getIntent().getIntExtra("EXTRA_NOMBRE_QUESTIONS", 50); ajoutGorgees = getIntent().getIntExtra("EXTRA_AJOUT_GORGEE", 0); - openAI = getIntent().getBooleanExtra("EXTRA_OPENAI", false); ratiOpenai = getIntent().getIntExtra("EXTRA_RATIO_OPENAI", 0); + durationDefis = getIntent().getIntExtra("EXTRA_DURATION_DEFIS", 0); + openAI = getIntent().getBooleanExtra("EXTRA_OPENAI", false); keyOpenai = getIntent().getStringExtra("EXTRA_KEY_OPENAI"); // Charger les questions depuis le JSON @@ -98,6 +105,8 @@ public class Jeux extends AppCompatActivity { if (savedInstanceState != null) { restoreGameState(savedInstanceState); } else { + // Réinitialiser le flag de fin de jeu + isFinishingGame = false; // Afficher la première question updateQuestion(); } @@ -125,6 +134,9 @@ public class Jeux extends AppCompatActivity { BoideloAnimationUtils.applyButtonPressAnimation(suivantButton); BoideloAnimationUtils.applyButtonPressAnimation(skipButton); + // Cacher le bouton Passé au début (uniquement visible pendant les défis) + skipButton.setVisibility(View.GONE); + // Initialiser la couleur de fond (respecte le mode jour/nuit) int backgroundColor = ContextCompat.getColor(this, R.color.game_normal); getWindow().getDecorView().setBackgroundColor(backgroundColor); @@ -193,6 +205,11 @@ public class Jeux extends AppCompatActivity { * Met à jour la question affichée avec toutes les animations */ private void updateQuestion() { + // Si le jeu est en train de se terminer, ne rien faire + if (isFinishingGame) { + return; + } + // Vérifier si toutes les questions ont été posées if (totalQuestionsAsked >= nombreQuestions) { // Vérifier s'il y a encore des manches actives @@ -247,10 +264,11 @@ public class Jeux extends AppCompatActivity { // Vibration de succès BoideloAnimationUtils.triggerSuccessHaptic(this); - // Masquer le compteur de manches et l'indicateur + // Masquer le compteur de manches, l'indicateur et le bouton Passé mancheCounterTextView.setVisibility(View.GONE); questionIndicator.setVisibility(View.GONE); mancheQuestionText.setVisibility(View.GONE); + skipButton.setVisibility(View.GONE); // Animation de fond jaune temporaire int yellowColor = ContextCompat.getColor(this, R.color.game_manche_end); @@ -267,6 +285,9 @@ public class Jeux extends AppCompatActivity { * Affiche le message de fin de manche finale (quand le jeu se termine) */ private void showFinalMancheEndMessage() { + // Marquer le jeu comme en train de se terminer + isFinishingGame = true; + // Récupérer le message de la dernière manche if (!questionsAvecManches.isEmpty()) { Question lastManche = questionsAvecManches.get(0); @@ -280,10 +301,12 @@ public class Jeux extends AppCompatActivity { // Vibration de succès BoideloAnimationUtils.triggerSuccessHaptic(this); - // Masquer le compteur et l'indicateur + // Masquer le compteur, l'indicateur et le bouton Passé mancheCounterTextView.setVisibility(View.GONE); questionIndicator.setVisibility(View.GONE); mancheQuestionText.setVisibility(View.GONE); + skipButton.setVisibility(View.GONE); + suivantButton.setEnabled(false); // Désactiver le bouton pendant la fin // Terminer après un délai mancheCounterTextView.postDelayed(() -> { @@ -397,12 +420,35 @@ public class Jeux extends AppCompatActivity { } /** - * Passe la question actuelle + * Passe la question actuelle ou ignore le défi en cours */ private void skipQuestion() { - // Marquer la question comme posée pour ne pas la revoir - totalQuestionsAsked++; - updateProgressBar(); + // Vérifier s'il y a un défi en cours + if (!questionsAvecManches.isEmpty()) { + // Ignorer le défi actuel + Question mancheToRemove = questionsAvecManches.get(0); + questionsAvecManches.clear(); + + // Masquer le compteur, l'indicateur et le bouton Passé + mancheCounterTextView.setVisibility(View.GONE); + questionIndicator.setVisibility(View.GONE); + mancheQuestionText.setVisibility(View.GONE); + skipButton.setVisibility(View.GONE); + + // Afficher un message de confirmation + Toast.makeText(this, "Défi ignoré !", Toast.LENGTH_SHORT).show(); + + // Vibration de confirmation + BoideloAnimationUtils.triggerHapticFeedback(this); + + // Animation de fond + int defaultColor = ContextCompat.getColor(this, R.color.game_normal); + BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), defaultColor); + } else { + // Sinon, passer simplement la question + totalQuestionsAsked++; + updateProgressBar(); + } updateQuestion(); } @@ -459,13 +505,15 @@ public class Jeux extends AppCompatActivity { */ public List TroisJoueurAleatoire(List toutlesjoueurs) { Set setJoueur = new HashSet<>(); - Random rand = new Random(); while (setJoueur.size() < 3 && toutlesjoueurs.size() >= 3) { - setJoueur.add(toutlesjoueurs.get(rand.nextInt(toutlesjoueurs.size()))); + setJoueur.add(toutlesjoueurs.get(random.nextInt(toutlesjoueurs.size()))); } - return new ArrayList<>(setJoueur); + // Mélanger la liste pour avoir un ordre aléatoire (pas toujours le même) + List result = new ArrayList<>(setJoueur); + Collections.shuffle(result, random); + return result; } /** @@ -502,8 +550,28 @@ public class Jeux extends AppCompatActivity { return null; } - Random random = new Random(); - Question question = unaskedQuestions.get(random.nextInt(unaskedQuestions.size())); + // Filtrer les questions : si un défi est en cours, exclure celles avec + List availableQuestions = new ArrayList<>(); + boolean mancheActive = !questionsAvecManches.isEmpty(); + + for (Question question : unaskedQuestions) { + if (mancheActive) { + // Un défi est en cours, exclure les questions avec + if (!question.getQuestion().contains("")) { + availableQuestions.add(question); + } + } else { + // Pas de défi en cours, toutes les questions sont disponibles + availableQuestions.add(question); + } + } + + // Si aucune question disponible (que des questions avec alors qu'un défi est en cours) + if (availableQuestions.isEmpty()) { + return null; + } + + Question question = availableQuestions.get(random.nextInt(availableQuestions.size())); askedQuestions.add(String.valueOf(question.getId())); // Sauvegarder les questions posées @@ -521,7 +589,6 @@ public class Jeux extends AppCompatActivity { * Traite une question (remplace les variables, etc.) */ private void processQuestion(Question question) { - Random random = new Random(); String questionText = question.getQuestion(); // Remplacer les variantes @@ -532,13 +599,21 @@ public class Jeux extends AppCompatActivity { // Gérer les manches if (questionText.contains("")) { - int nbaleatoiremanches = random.nextInt(10) + 5; + int nbaleatoiremanches = random.nextInt(10) + 5 + durationDefis; + // S'assurer qu'il y a au moins 1 manche + if (nbaleatoiremanches < 1) { + nbaleatoiremanches = 1; + } questionText = questionText.replace("", String.valueOf(nbaleatoiremanches)); question.setManchesRestantes(nbaleatoiremanches); String stopid = getArretById(question.getId()); question.setArretMessageManche("Fin de défi!\n" + stopid); questionsAvecManches.add(question); + + // Afficher le bouton Passé pendant les défis + skipButton.setVisibility(View.VISIBLE); + BoideloAnimationUtils.fadeIn(skipButton, 300); } // Remplacer les joueurs @@ -637,6 +712,7 @@ public class Jeux extends AppCompatActivity { totalQuestionsAsked = savedInstanceState.getInt(KEY_TOTAL_QUESTIONS, 0); currentQuestionText = savedInstanceState.getString(KEY_CURRENT_QUESTION_TEXT, ""); isMancheActive = savedInstanceState.getBoolean(KEY_IS_MANCHE_ACTIVE, false); + isFinishingGame = false; // Réinitialiser le flag de fin de jeu // Restaurer la progression progressBar.setProgress(totalQuestionsAsked); diff --git a/app/src/main/java/com/example/boidelov3/JeuxParametres.java b/app/src/main/java/com/example/boidelov3/JeuxParametres.java index 45b51d4..b495fbb 100644 --- a/app/src/main/java/com/example/boidelov3/JeuxParametres.java +++ b/app/src/main/java/com/example/boidelov3/JeuxParametres.java @@ -32,8 +32,8 @@ import okhttp3.Response; public class JeuxParametres extends AppCompatActivity { - private SeekBar seekBar1, seekBar2, seekBar3; - private TextView textView1, textView2, textView5, textViewRatioGen; + private SeekBar seekBar1, seekBar2, seekBar3, seekBarDuration; + private TextView textView1, textView2, textView5, textViewRatioGen, questionCountValue, gorgeesValue, durationValue; private SwitchMaterial checkBoxGPT; private EditText editText, editTextKeyGPT; private String keyGPT; @@ -52,19 +52,25 @@ public class JeuxParametres extends AppCompatActivity { seekBar1 = findViewById(R.id.seekBar1); seekBar2 = findViewById(R.id.seekBar2); seekBar3 = findViewById(R.id.seekBar3); + seekBarDuration = findViewById(R.id.seekBarDuration); textView1 = findViewById(R.id.textView1); textView2 = findViewById(R.id.textView2); textView5 = findViewById(R.id.textView5); editTextKeyGPT = findViewById(R.id.editTextGPT); textViewRatioGen = findViewById(R.id.textViewRatioGen); + questionCountValue = findViewById(R.id.questionCountValue); + gorgeesValue = findViewById(R.id.gorgeesValue); + durationValue = findViewById(R.id.durationValue); // Initialiser les TextView avec les valeurs par défaut int initialQuestions = 50; int initialGorgees = 0; int initialRatio = 8; + int initialDuration = 0; - textView1.setText("Nombre de questions avant la fin de partie : " + initialQuestions); - textView2.setText("Ajout de gorgées : " + initialGorgees); + questionCountValue.setText(String.valueOf(initialQuestions)); + gorgeesValue.setText(String.valueOf(initialGorgees)); + durationValue.setText("0"); // Afficher 0 par défaut (pas de signe pour 0) textView5.setText("Palier : Grosse merde"); textViewRatioGen.setText("Ratio BDD/OPENAI : 1/" + initialRatio); @@ -89,6 +95,13 @@ public class JeuxParametres extends AppCompatActivity { seekBar3.setMax(15); seekBar3.setProgress(8); + // Configuration de la seekBarDuration (permet valeurs négatives pour offset) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + seekBarDuration.setMin(-5); // Permet un offset négatif jusqu'à -5 + } + seekBarDuration.setMax(15); + seekBarDuration.setProgress(0); // Valeur par défaut à 0 + // Configuration des listeners pour les seekBars seekBar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override @@ -96,7 +109,7 @@ public class JeuxParametres extends AppCompatActivity { // Ajustement de la valeur au multiple de 10 le plus proche int adjustedProgress = Math.round(progress / 10) * 10; seekBar.setProgress(adjustedProgress); - textView1.setText("Nombre de questions avant la fin de partie : " + adjustedProgress); + questionCountValue.setText(String.valueOf(adjustedProgress)); } @Override @@ -111,8 +124,8 @@ public class JeuxParametres extends AppCompatActivity { seekBar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - // Mise à jour du textView2 en fonction de la valeur de la seekBar2 - textView2.setText("Ajout de gorgées : " + progress); + // Mise à jour du gorgeesValue en fonction de la valeur de la seekBar2 + gorgeesValue.setText(String.valueOf(progress)); // Mise à jour du textView5 en fonction de la valeur de la seekBar2 switch (progress) { case 0: @@ -169,7 +182,7 @@ public class JeuxParametres extends AppCompatActivity { } }); - // Configuration du checkBox // Q : IL sert a quoi ? + // Configuration du checkBox // Q : IL sert à quoi ? // R : Il sert à activer/désactiver les vues en dessous checkBoxGPT = findViewById(R.id.checkBoxGPT); @@ -201,6 +214,29 @@ public class JeuxParametres extends AppCompatActivity { } }); + // Configuration de la seekBarDuration + seekBarDuration.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + // Afficher avec signe +/- pour bien voir l'offset, mais sans signe pour 0 + String displayValue; + if (progress > 0) { + displayValue = "+" + progress; + } else { + displayValue = String.valueOf(progress); // Affiche "0" ou "-X" + } + durationValue.setText(displayValue); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + // Partie OpenAI : enregistrement de la clé en dur. // Récupérer une instance des SharedPreferences SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", MODE_PRIVATE); @@ -291,6 +327,7 @@ public class JeuxParametres extends AppCompatActivity { int nombreQuestions = seekBar1.getProgress(); int ajoutGorgees = seekBar2.getProgress(); int ratioBddOpenAI = seekBar3.getProgress(); + int durationDefis = seekBarDuration.getProgress(); boolean openAI = checkBoxGPT.isChecked(); toutlesjoueurs = getIntent().getStringArrayListExtra("EXTRA_LIST_JOUEUR"); @@ -322,6 +359,7 @@ public class JeuxParametres extends AppCompatActivity { intent.putExtra("EXTRA_NOMBRE_QUESTIONS", nombreQuestions); intent.putExtra("EXTRA_AJOUT_GORGEE", ajoutGorgees); intent.putExtra("EXTRA_RATIO_OPENAI", ratioBddOpenAI); + intent.putExtra("EXTRA_DURATION_DEFIS", durationDefis); intent.putExtra("EXTRA_OPENAI", openAI); final EditText editText = findViewById(R.id.editTextGPT); intent.putExtra("EXTRA_KEY_OPENAI",editText.getText().toString() ); diff --git a/app/src/main/java/com/example/boidelov3/Jeuxold.java b/app/src/main/java/com/example/boidelov3/Jeuxold.java index 68875da..547f33e 100644 --- a/app/src/main/java/com/example/boidelov3/Jeuxold.java +++ b/app/src/main/java/com/example/boidelov3/Jeuxold.java @@ -22,6 +22,9 @@ public class Jeuxold extends AppCompatActivity { int ratiOpenai; String keyOpenai, phraseGPTString; + // Générateur aléatoire unique pour toute l'activité + private final Random random = new Random(); + public Jeuxold() { //System.out.println("Je suis dans le constructeur jeux"); @@ -109,39 +112,39 @@ public class Jeuxold extends AppCompatActivity { List aleatoirejoueurs = TroisJoueurAleatoire(toutlesjoueurs); phraseAvecNom.add(ChoixJoueurAleatoire(toutlesjoueurs) + " dois boire " + Gorgeesaleatoire(2, 4)+ " Gorgées"); phraseAvecNom.add(ChoixJoueurAleatoire((toutlesjoueurs))+ " est le vieux briscard ! Interdiction de montrer tes dents pendant 5 manches"); - phraseAvecNom.add(aleatoirejoueurs.get(0) + " et "+ aleatoirejoueurs.get(1) +" liser le premier SMS qui s'affiche quand on tape désolé dans la barre de recherche. Refusez pour 5 gorgées"); - phraseAvecNom.add( "A tour de role, vous avez exactement 3 secondes pour donner un mot en rapport avec le mots dit precedemment. Le joueur qui perd boit "+ Gorgeesaleatoire(2, 4) + " Gorgées! "+ aleatoirejoueurs.get(2)+" tu commences en choissisant un mot."); - phraseAvecNom.add(aleatoirejoueurs.get(0)+ " defie "+ aleatoirejoueurs.get(1) + " au chifoumi ! Le joueur qui gagne distribue 5 Gorgées"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+ " a toi de juger : entre "+aleatoirejoueurs.get(1)+ " et "+ aleatoirejoueurs.get(2) + " qui stresse le plus pour un rien selon toi? Cette personne se detendra en buvant " + Gorgeesaleatoire(3, 5 ) + " Gorgées"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" est dans le futur ! Tu dois parler au futur pendant 4 tours Une gorgées a chaque manque."); + phraseAvecNom.add(aleatoirejoueurs.get(0) + " et "+ aleatoirejoueurs.get(1) +" lire le premier SMS qui s'affiche quand on tape désolé dans la barre de recherche. Refusez pour 5 gorgées"); + phraseAvecNom.add( "A tour de rôle, vous avez exactement 3 secondes pour donner un mot en rapport avec le mots dit précédemment. Le joueur qui perd boit "+ Gorgeesaleatoire(2, 4) + " Gorgées! "+ aleatoirejoueurs.get(2)+" tu commences en choisissant un mot."); + phraseAvecNom.add(aleatoirejoueurs.get(0)+ " défie "+ aleatoirejoueurs.get(1) + " au chifoumi ! Le joueur qui gagne distribue 5 Gorgées"); + phraseAvecNom.add(aleatoirejoueurs.get(0)+ " à toi de juger : entre "+aleatoirejoueurs.get(1)+ " et "+ aleatoirejoueurs.get(2) + " qui stresse le plus pour un rien selon toi? Cette personne se détendra en buvant " + Gorgeesaleatoire(3, 5 ) + " Gorgées"); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" est dans le futur ! Tu dois parler au futur pendant 4 tours Une gorgée à chaque manque."); phraseAvecNom.add("Les joueurs de Counter Strike peuvent distribuer" + GorgeesaleatoireAmeliorer(1, 4)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" tu bois autant de gorgées que tu as d'années d'études après le BAC"); phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+aleatoirejoueurs.get(1)+" ferment leurs yeux ! Ils/Elles doivent deviner la couleur des yeux de l'autre. Si ils/elles se trompent, c'est "+GorgeesaleatoireAmeliorer(2, 4)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" est manchot ! Il/Elle ne peut plus utiliser ses doigts durant 3 tours . Si il/elle s'en sert, il/elle devra boire autant de gorgées qu'il/elle a utilisé de doigts"); phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+ aleatoirejoueurs.get(1)+" , si vous êtes ensemble dans la vraie vie, vous pouvez distribuer 2 gorgées , autrement buvez-les"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+", donne le nombre d'habitant du Tadjikistant ( à 1 000 000 près) ou boit "+GorgeesaleatoireAmeliorer(2, 4)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+", donne le nombre d'habitants du Tadjikistan ( à 1 000 000 près) ou boit "+GorgeesaleatoireAmeliorer(2, 4)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" a la tourette ! A chaque fois que tu bois une gorgée, tu dois CRIER une insulte. C'est un stade avancé, ça dure 3 tours"); phraseAvecNom.add(aleatoirejoueurs.get(0)+", donne la couleur préférée de "+aleatoirejoueurs.get(1)+" si tu te trompes, c'est 2 gorgées"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" à l'oeil de serpent pendant 5 tours ! Dès qu'un joueur te regarde dans les yeux, il/elle boit. Si personne ne t'as regardé tu bois"+GorgeesaleatoireAmeliorer(5, 9)); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+ aleatoirejoueurs.get(1)+"se mesurent ! Le plus petit peut bois"+GorgeesaleatoireAmeliorer(3, 5)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" à l'oeil de serpent pendant 5 tours ! Dès qu'un joueur te regarde dans les yeux, il/elle boit. Si personne ne t'a regardé tu bois"+GorgeesaleatoireAmeliorer(5, 9)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+ aleatoirejoueurs.get(1)+"se mesurent ! Le plus petit peut boire"+GorgeesaleatoireAmeliorer(3, 5)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" doit terminer toutes ses phrases par - C'est clair pendant 7 tours"); phraseAvecNom.add(aleatoirejoueurs.get(0)+" distribue"+GorgeesaleatoireAmeliorer(2,5)+" à la personne que tu trouves la mieux foutue"); phraseAvecNom.add(aleatoirejoueurs.get(0)+" distribue"+GorgeesaleatoireAmeliorer(2,5)+" à qui tu veux."); phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+aleatoirejoueurs.get(1)+" se défient au 'je te tiens, tu me tiens', le premier qui rit sera une tapette, et devra boire"+GorgeesaleatoireAmeliorer(4,6)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+aleatoirejoueurs.get(1)+"n'ont plus le droit d'utiliser leur téléphone jusqu'à la fin du jeu ! A chaque manque c'est"+GorgeesaleatoireAmeliorer(1,3)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+aleatoirejoueurs.get(1)+ "racontent une anecdote, celui/celle qui sort la plus banale boit "+GorgeesaleatoireAmeliorer(3, 6)); - phraseAvecNom.add(aleatoirejoueurs.get(0)+", pour"+GorgeesaleatoireAmeliorer(2,4)+", a qui est ce slogan? Y a pas plus fort. (Vigor)"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+", Vrai ou faux? L'eau est bleu car elle reflète le ciel? (Non) Si tu as repondu faux tu devras boire : "+GorgeesaleatoireAmeliorer(2,4)); - phraseAvecNom.add(aleatoirejoueurs.get(0)+", Si on te dit Marco? ... Si tu as dis Polo tu bois "+GorgeesaleatoireAmeliorer(1,3)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+", pour"+GorgeesaleatoireAmeliorer(2,4)+", à qui est ce slogan? Y a pas plus fort. (Vigor)"); + phraseAvecNom.add(aleatoirejoueurs.get(0)+", Vrai ou faux? L'eau est bleue car elle reflète le ciel? (Non) Si tu as répondu faux tu devras boire : "+GorgeesaleatoireAmeliorer(2,4)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+", Si on te dit Marco? ... Si tu as dit Polo tu bois "+GorgeesaleatoireAmeliorer(1,3)); phraseAvecNom.add(aleatoirejoueurs.get(0)+", Boire un café fait baisser le taux d'alcool? "+GorgeesaleatoireAmeliorer(5, 8)+"en jeu (FAUX)"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" est l'aigris pendant 5tours ! Dès que tu souris ou rigoles, tu bois "+GorgeesaleatoireAmeliorer(2,3)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" est l'aigris pendant 5 tours ! Dès que tu souris ou rigoles, tu bois "+GorgeesaleatoireAmeliorer(2,3)); phraseAvecNom.add(aleatoirejoueurs.get(0)+" fait un geste, le suivant répète et en ajoute un. Le perdant boit"+GorgeesaleatoireAmeliorer(3,5)); phraseAvecNom.add(aleatoirejoueurs.get(0)+", "+aleatoirejoueurs.get(2)+" et "+aleatoirejoueurs.get(1)+" vont désigner quelqu'un qui doit terminer son verre "); phraseAvecNom.add("Récitez l'alphabet en énonçant une lettre à tour de rôle. Si "+aleatoirejoueurs.get(0)+" finit son verre avant, cul sec pour tout le monde !"); - phraseAvecNom.add("Si"+aleatoirejoueurs.get(0)+" arrive a finir son verre en moins de 5 secondes, il/elle peut distribuer"+ GorgeesaleatoireAmeliorer(5, 8)); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+ aleatoirejoueurs.get(1)+"sont lies, si l'un boit alors l'autre aussi, et ce pendant 5 tours"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+", "+aleatoirejoueurs.get(2)+" et "+ aleatoirejoueurs.get(1)+"sont lies, si l'un boit alors les autres aussi, et ce pendant 5 tours"); - phraseAvecNom.add(aleatoirejoueurs.get(0)+" dit un mot, la personne suivante le répète et en ajoute un nouveau, ainsi de suite jusqu'a ce que quelqu'un se trompe. Le perdant boit autant de gorgées qu'il y a eu de personne avant lui"); + phraseAvecNom.add("Si"+aleatoirejoueurs.get(0)+" arrive à finir son verre en moins de 5 secondes, il/elle peut distribuer"+ GorgeesaleatoireAmeliorer(5, 8)); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" et "+ aleatoirejoueurs.get(1)+"sont liés, si l'un boit alors l'autre aussi, et ce pendant 5 tours"); + phraseAvecNom.add(aleatoirejoueurs.get(0)+", "+aleatoirejoueurs.get(2)+" et "+ aleatoirejoueurs.get(1)+"sont liés, si l'un boit alors les autres aussi, et ce pendant 5 tours"); + phraseAvecNom.add(aleatoirejoueurs.get(0)+" dit un mot, la personne suivante le répète et en ajoute un nouveau, ainsi de suite jusqu'à ce que quelqu'un se trompe. Le perdant boit autant de gorgées qu'il y a eu de personne avant lui"); phraseAvecNom.add(aleatoirejoueurs.get(0)+" doit choisir un mot que tout le monde devra dire à chaque fois qu'une personne boit."); //phraseAvecNom.add(aleatoirejoueurs.get(0)+""); //phraseAvecNom.add(aleatoirejoueurs.get(0)+""); @@ -155,15 +158,15 @@ public class Jeuxold extends AppCompatActivity { List phraseSansNom = new ArrayList(); //Ajout de defis phraseSansNom.add("Tout le monde boit "+ Gorgeesaleatoire(1, 2)+" gorgée(s)"); - phraseSansNom.add("Quand l'heure affichera un multiple de 10 (22h, 22h10 ...) le premier a crier \"merde j'ai oublié mon chat\" distribura " + Gorgeesaleatoire(10, 12)+ " Gorgées"); + phraseSansNom.add("Quand l'heure affichera un multiple de 10 (22h, 22h10 ...) le premier à crier \"merde j'ai oublié mon chat\" distribuera " + Gorgeesaleatoire(10, 12)+ " Gorgées"); phraseSansNom.add("Ceux qui ont dansé aujourd'hui boivent 4 gorgées"); - phraseSansNom.add("Bois "+ Gorgeesaleatoire(2, 6)+ " Gorgées si tu n'as pas ton veritable nom sur insta"); - phraseSansNom.add("Bois "+ Gorgeesaleatoire(2, 3)+ " Gorgées si tu a des photos sur insta."); + phraseSansNom.add("Bois "+ Gorgeesaleatoire(2, 6)+ " Gorgées si tu n'as pas ton véritable nom sur insta"); + phraseSansNom.add("Bois "+ Gorgeesaleatoire(2, 3)+ " Gorgées si tu as des photos sur insta."); phraseSansNom.add("Plutôt ne plus avoir de mains ou de jambes? les perdants boivent "+GorgeesaleatoireAmeliorer(1,4)); - phraseSansNom.add("Celles/Ceux qui ont habité dans plus de 3 villes boivent "+GorgeesaleatoireAmeliorer(1,4)); + phraseSansNom.add("Celles/Ceux qui ont habité dans plus de 3 villes différentes boivent "+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Vive la poésie ! Nos phrases doivent rimer sous peine d'une gorgée"); - phraseSansNom.add("Elisez le joueur le moins drôle d'entre vous, ce dernier boit" + GorgeesaleatoireAmeliorer(1,4 )); - phraseSansNom.add("Elisez le joueur le plus drôle d'entre vous, ce dernier distribue" + GorgeesaleatoireAmeliorer(1,4 )); + phraseSansNom.add("Élisez le joueur le moins drôle d'entre vous, ce dernier boit" + GorgeesaleatoireAmeliorer(1,4 )); + phraseSansNom.add("Élisez le joueur le plus drôle d'entre vous, ce dernier distribue" + GorgeesaleatoireAmeliorer(1,4 )); phraseSansNom.add("La dernière personne à avoir vomi en soirée distribue" + GorgeesaleatoireAmeliorer(2,4)); phraseSansNom.add("Les filles peuvent distribuer"+ GorgeesaleatoireAmeliorer(1, 2)); phraseSansNom.add("Les garçons peuvent distribuer"+ GorgeesaleatoireAmeliorer(1, 2)); @@ -175,7 +178,7 @@ public class Jeuxold extends AppCompatActivity { phraseSansNom.add("Plutôt avoir un tapis volant, ou un frigo qui se remplit tout seul ? Votez tous en même temps. La minorité boit "+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Les couples trinquer ensemble "+ GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Le/La plus radin(e) boit"+GorgeesaleatoireAmeliorer(1,4)); - phraseSansNom.add("Le mec qui a le plus gros ventre à bière boit"+GorgeesaleatoireAmeliorer(1,4)); + phraseSansNom.add("Le mec qui a le plus gros ventre de bière boit"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Tous ceux qui se sont déjà fait exclure de cours boivent"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Tous ceux qui ont des frères et soeurs boivent"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Celles et ceux qui ont un Windows phone peuvent distribuer"+GorgeesaleatoireAmeliorer(1,4)); @@ -186,40 +189,40 @@ public class Jeuxold extends AppCompatActivity { phraseSansNom.add("Plutôt avoir du temps ou de l'argent ? Votez tous en même temps. La minorité boit"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Celles/Ceux qui ont fait des études de L boivent"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Le premier joueur qui en embrasse un autre sur la bouche pourra distribuer"+GorgeesaleatoireAmeliorer(1,4)); - phraseSansNom.add("Celles et ceux qui joue de la guitare peuvent distribuer"+GorgeesaleatoireAmeliorer(1,4)); - phraseSansNom.add("Celles et ceux qui joue du piano peuvent distribuer"+GorgeesaleatoireAmeliorer(1,4)); + phraseSansNom.add("Celles et ceux qui jouent de la guitare peuvent distribuer"+GorgeesaleatoireAmeliorer(1,4)); + phraseSansNom.add("Celles et ceux qui jouent du piano peuvent distribuer"+GorgeesaleatoireAmeliorer(1,4)); phraseSansNom.add("Les gens qui se sont masturbés aujourd'hui peuvent distribuer"+GorgeesaleatoireAmeliorer(1, 4)); - phraseSansNom.add("Celui ou celle a la meilleure place boit"+GorgeesaleatoireAmeliorer(1, 4)); + phraseSansNom.add("Celui ou celle à la meilleure place boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Celles et ceux qui n'ont jamais trompé leur partenaire (c'est bien) peuvent distribuer"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Celui/Celle avec les vêtements les plus moches boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Celui/Celle qui a les cheveux les plus longs boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("On doit doser son Alcool les yeux fermés"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Plutôt série ou film ? Votez tous en même temps. La minorité boit"+GorgeesaleatoireAmeliorer(1, 4)); - phraseSansNom.add("Elisez le plus débile d'entre vous, ce dernier boit"+GorgeesaleatoireAmeliorer(1, 4)); + phraseSansNom.add("Élisez le plus débile d'entre vous, ce dernier boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Le premier qui donne un film de - Christopher Nolan - pourra distribuer"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Le premier qui donne un film avec Christian Clavier pourra boire"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Les végans boivent "+GorgeesaleatoireAmeliorer(1, 4)); - phraseSansNom.add("La fille la plus maquillé boit"+GorgeesaleatoireAmeliorer(1, 4)); + phraseSansNom.add("La fille la plus maquillée boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Celles/Ceux qui ont déjà appelé leur partenaire par le prénom de leurs ex boivent"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("La première personne qui désigne le plus jeune peut distribuer"+GorgeesaleatoireAmeliorer(1, 4)); - phraseSansNom.add("Plutôt avoir des connaissances illimitées ou dirigier le monde ? Votez tous en même temps. La minorité boit"+GorgeesaleatoireAmeliorer(1, 4)); + phraseSansNom.add("Plutôt avoir des connaissances illimitées ou diriger le monde ? Votez tous en même temps. La minorité boit"+GorgeesaleatoireAmeliorer(1, 4)); phraseSansNom.add("Plutôt n'avoir aucun ami ou ne plus pouvoir utiliser d'appareil électronique ? Votez tous en même temps. La minorité boit"+ GorgeesaleatoireAmeliorer(2, 5)); - phraseSansNom.add("Plutot vaincre le patrikaka ou la polution dans le monde? Votez tous en meme temps. La minorité boit"+GorgeesaleatoireAmeliorer(1, 2)); - phraseSansNom.add("Jeu du LUTIN : Jusqu'a la fin du jeu. Vous devez enlever le lutin de votre verre pour pouvoir boire et le remettre ensuite sinon vous devait reboire"); + phraseSansNom.add("Plutôt vaincre le patrikaka ou la pollution dans le monde? Votez tous en même temps. La minorité boit"+GorgeesaleatoireAmeliorer(1, 2)); + phraseSansNom.add("Jeu du LUTIN : Jusqu'à la fin du jeu. Vous devez enlever le lutin de votre verre pour pouvoir boire et le remettre ensuite sinon vous devez reboire"); phraseSansNom.add("Celles et ceux qui boivent de la Vodka peuvent distribuer "+ GorgeesaleatoireAmeliorer(2, 4)); phraseSansNom.add("Les joueurs qui ont un A dans leur prénom boivent "+GorgeesaleatoireAmeliorer(3,5)); - phraseSansNom.add("Les joueurs qui ont un P dans le prénom distribue"+GorgeesaleatoireAmeliorer(1, 3)); + phraseSansNom.add("Les joueurs qui ont un P dans le prénom distribuent"+GorgeesaleatoireAmeliorer(1, 3)); phraseSansNom.add("Le premier joueur à ramener un objet rouge (pas de vêtements) peut distribuer"+GorgeesaleatoireAmeliorer(3,5)); phraseSansNom.add("Le premier joueur qui dévoile un de ses secrets et que personne autour ne sait peut distribuer"+ GorgeesaleatoireAmeliorer(3, 6)); phraseSansNom.add("Chaque joueur doit lire à haute voix le dernier SMS qu'il a reçu. Si il/elle refuse, c'est"+ GorgeesaleatoireAmeliorer(2, 4)); phraseSansNom.add("Le joueur avec le plus gros cul boit"+ GorgeesaleatoireAmeliorer(2, 6)); phraseSansNom.add("Celles/Ceux qui ont moins de 20ans boivent"+ GorgeesaleatoireAmeliorer(2, 7)); - phraseSansNom.add("Celui ou celle avec le plus gros appetit sexuel boit"+ GorgeesaleatoireAmeliorer(2, 4)); - phraseSansNom.add("Ceux/Celles qui fumes boivent "+ GorgeesaleatoireAmeliorer(2, 4)); + phraseSansNom.add("Celui ou celle avec le plus gros appétit sexuel boit"+ GorgeesaleatoireAmeliorer(2, 4)); + phraseSansNom.add("Ceux/Celles qui fument boivent "+ GorgeesaleatoireAmeliorer(2, 4)); phraseSansNom.add("Celles et ceux qui ont au moins un BAC +3 peuvent distribuer"+ GorgeesaleatoireAmeliorer(2, 4)); phraseSansNom.add("Le premier joueur à se lever peut donner"+ GorgeesaleatoireAmeliorer(6, 7)); phraseSansNom.add("Celles et ceux qui n'ont jamais fait de strip tease boivent"+ GorgeesaleatoireAmeliorer(2, 4)); - phraseSansNom.add("Le premier joueur à enlever un vêtements pourra distribuer"+ GorgeesaleatoireAmeliorer(5, 7)); + phraseSansNom.add("Le premier joueur à enlever un vêtement pourra distribuer"+ GorgeesaleatoireAmeliorer(5, 7)); phraseSansNom.add("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."); phraseSansNom.add("Tous ceux qui ont déjà uriné dans une piscine boivent"+ GorgeesaleatoireAmeliorer(2, 4)); phraseSansNom.add("Celui/Celle avec le plus d'amis sur Facebook boit"+ GorgeesaleatoireAmeliorer(2, 4)); @@ -255,11 +258,10 @@ public class Jeuxold extends AppCompatActivity { public int Gorgeesaleatoire(int Min, int Max){ int offset = ajoutGorgees; int nbgorgées; - Random rand = new Random(); if (Min == 1 && Max == 2){ - nbgorgées = rand.nextInt(Max + Min); + nbgorgées = random.nextInt(Max + Min); }else { - nbgorgées = Min+rand.nextInt(Max - Min); + nbgorgées = Min + random.nextInt(Max - Min); } if(nbgorgées == 0){ nbgorgées = 1; @@ -267,40 +269,32 @@ public class Jeuxold extends AppCompatActivity { nbgorgées = nbgorgées + offset; return nbgorgées; } + public String GorgeesaleatoireAmeliorer(int Min, int Max){ int offset = ajoutGorgees; int nbgorgées; - Random rand = new Random(); if (Min == 1 && Max == 2){ - nbgorgées = rand.nextInt(Max + Min); + nbgorgées = random.nextInt(Max + Min); }else { - nbgorgées = Min+rand.nextInt(Max - Min); + nbgorgées = Min + random.nextInt(Max - Min); } if(nbgorgées == 0){ nbgorgées = 1; } nbgorgées = nbgorgées + offset; - String debut; - String nbgorgéesstr; - String nbgorgéesstr1; - debut = " "; - nbgorgéesstr1 = " Gorgée(s)"; - nbgorgéesstr = debut + Integer.toString(nbgorgées) + nbgorgéesstr1; + String nbgorgéesstr = " " + Integer.toString(nbgorgées) + " Gorgée(s)"; return nbgorgéesstr; } public String Nbaleatoirelist(List list){ - Random rand = new Random(); - String phrase = (String) list.get(rand.nextInt(list.size())); - return phrase; + return (String) list.get(random.nextInt(list.size())); } + public int Nbaleatoire(){ int Max = 100; int Min = 0; - Random rand = new Random(); - int nbaleatoire = rand.nextInt(Max - Min); - return nbaleatoire; + return random.nextInt(Max - Min); } public boolean JoueurOuPas(){ boolean TrueFalse; @@ -317,43 +311,17 @@ public class Jeuxold extends AppCompatActivity { } public List TroisJoueurAleatoire(List toutlesjoueurs){ List listJoueur = new ArrayList(); - while (true){ - Random rand = new Random(); - String joueur1 = (String) toutlesjoueurs.get(rand.nextInt(toutlesjoueurs.size())); - String joueur2 = (String) toutlesjoueurs.get(rand.nextInt(toutlesjoueurs.size())); - String joueur3 = (String) toutlesjoueurs.get(rand.nextInt(toutlesjoueurs.size())); - if(joueur1 == joueur2 ){ - }else{ - if (joueur1 == joueur3){ - }else { - if (joueur2 == joueur3) { - }else{ - listJoueur.add(joueur1); - listJoueur.add(joueur2); - listJoueur.add(joueur3); - return listJoueur; - } - - } - } + while (listJoueur.size() < 3){ + String joueur = (String) toutlesjoueurs.get(random.nextInt(toutlesjoueurs.size())); + if (!listJoueur.contains(joueur)) { + listJoueur.add(joueur); } } + return listJoueur; + } - public String ChoixJoueurAleatoire( List toutlesjoueurs){ - //System.out.println(inttoutlesjoueurs); - Random rand = new Random(); - String joueur = (String) toutlesjoueurs.get(rand.nextInt(toutlesjoueurs.size())); - //System.out.println(joueur); - //int nbaleatoire = rand.nextInt(max -min + 1 ) + min; - //int nbaleatoire2 = nbaleatoire - 1; - //if(nbaleatoire2 == -1 ){ - // nbaleatoire2 = 0; - //} - //System.out.println( "nb aleatoire " + nbaleatoire) ; - //joueur = (String) toutlesjoueurs.get(nbaleatoire2); - //System.out.println(joueur); - return joueur ; - + public String ChoixJoueurAleatoire(List toutlesjoueurs){ + return (String) toutlesjoueurs.get(random.nextInt(toutlesjoueurs.size())); } public void OnClickButton1(View v){ finish(); diff --git a/app/src/main/java/com/example/boidelov3/MainActivity.java b/app/src/main/java/com/example/boidelov3/MainActivity.java index 6704a97..84677ad 100644 --- a/app/src/main/java/com/example/boidelov3/MainActivity.java +++ b/app/src/main/java/com/example/boidelov3/MainActivity.java @@ -101,7 +101,7 @@ public class MainActivity extends AppCompatActivity { ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ); - rowParams.setMargins(0, 8, 0, 8); + rowParams.setMargins(0, 0, 0, 12); // Marge identique aux champs statiques (12dp) playerRow.setLayoutParams(rowParams); // Créer un nouveau TextInputLayout @@ -110,16 +110,28 @@ public class MainActivity extends AppCompatActivity { ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ); - textInputParams.setMargins(0, 0, 60, 0); // Laisser de la place pour le bouton supprimer + // Plus d'espace pour le bouton poubelle (68dp au lieu de 52dp) + textInputParams.setMargins(0, 0, 68, 0); textInputLayout.setLayoutParams(textInputParams); textInputLayout.setBoxBackgroundMode(com.google.android.material.textfield.TextInputLayout.BOX_BACKGROUND_OUTLINE); textInputLayout.setHint("Nom"); - // Appliquer les couleurs du thème pour la cohérence - int primaryColor = androidx.core.content.ContextCompat.getColor(this, R.color.primary); - int hintColor = androidx.core.content.ContextCompat.getColor(this, R.color.text_hint); - textInputLayout.setBoxStrokeColor(primaryColor); + // Appliquer exactement les mêmes styles que le XML + // Créer un ColorStateList pour la bordure : grise par défaut, primaire quand focus + int[][] states = new int[][] { + new int[] { android.R.attr.state_focused}, + new int[] {} + }; + int[] colors = new int[] { + androidx.core.content.ContextCompat.getColor(this, R.color.primary), + androidx.core.content.ContextCompat.getColor(this, android.R.color.darker_gray) // Bordure grise par défaut + }; + android.content.res.ColorStateList strokeColorStateList = new android.content.res.ColorStateList(states, colors); + textInputLayout.setBoxStrokeColorStateList(strokeColorStateList); + textInputLayout.setBoxStrokeWidth(2); // Largeur de bordure comme dans le XML + textInputLayout.setBoxBackgroundColor(androidx.core.content.ContextCompat.getColor(this, R.color.surface)); textInputLayout.setDefaultHintTextColor(androidx.core.content.ContextCompat.getColorStateList(this, R.color.text_hint)); + textInputLayout.setEndIconMode(com.google.android.material.textfield.TextInputLayout.END_ICON_CLEAR_TEXT); // Créer un nouveau TextInputEditText TextInputEditText newEditText = new TextInputEditText(this); @@ -147,19 +159,19 @@ public class MainActivity extends AppCompatActivity { // Ajouter l'EditText au TextInputLayout textInputLayout.addView(newEditText); - // Créer le bouton de suppression + // Créer le bouton de suppression - taille réduite ImageButton deleteButton = new ImageButton(this); - FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams( - (int) (48 * getResources().getDisplayMetrics().density), - (int) (48 * getResources().getDisplayMetrics().density) - ); - buttonParams.setMargins(0, 4, 8, 4); + int dp36 = (int) (36 * getResources().getDisplayMetrics().density); + FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams(dp36, dp36); + buttonParams.setMargins(0, 4, 10, 4); // Plus d'espace à droite (10dp au lieu de 6) buttonParams.gravity = android.view.Gravity.END | android.view.Gravity.CENTER_VERTICAL; deleteButton.setLayoutParams(buttonParams); - deleteButton.setBackgroundResource(android.R.drawable.ic_menu_delete); + deleteButton.setImageResource(android.R.drawable.ic_menu_delete); int errorColor = androidx.core.content.ContextCompat.getColor(this, R.color.error); deleteButton.setColorFilter(errorColor); deleteButton.setScaleType(ImageButton.ScaleType.CENTER_INSIDE); + deleteButton.setBackgroundColor(android.graphics.Color.TRANSPARENT); // Fond transparent + deleteButton.setPadding(4, 4, 4, 4); // Padding interne réduit deleteButton.setContentDescription("Supprimer ce joueur"); // Configuration du bouton de suppression avec animation @@ -271,7 +283,7 @@ public class MainActivity extends AppCompatActivity { //Lancement de l'activité (Jeux_parametres) Intent intent = new Intent(this, JeuxParametres.class); - //Regarde si le pseudo est vide et envoie a l'activité jeux + //Regarde si le pseudo est vide et envoie à l'activité jeux if (toutlesjoueurs.isEmpty()){ Context context = getApplicationContext(); CharSequence text = "Merci de rentrer des joueurs"; @@ -287,7 +299,7 @@ public class MainActivity extends AppCompatActivity { startActivity(intent); } else { Context context = getApplicationContext(); - CharSequence text = "La partie ne peux pas commencer avec moins de 3 joueurs"; + CharSequence text = "La partie ne peut pas commencer avec moins de 3 joueurs"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(context, text, duration); toast.show(); diff --git a/app/src/main/res/layout/activity_jeux.xml b/app/src/main/res/layout/activity_jeux.xml index 2991b13..df6ed73 100644 --- a/app/src/main/res/layout/activity_jeux.xml +++ b/app/src/main/res/layout/activity_jeux.xml @@ -88,52 +88,52 @@ app:layout_constraintTop_toBottomOf="@id/questionIndicator"> + android:layout_width="match_parent" + android:layout_height="536dp" + android:gravity="center" + android:orientation="vertical" + android:padding="24dp"> + android:id="@+id/mancheCounter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:background="@drawable/bg_card" + android:paddingStart="16dp" + android:paddingTop="8dp" + android:paddingEnd="16dp" + android:paddingBottom="8dp" + android:text="Manches: 5" + android:textColor="@color/primary" + android:textSize="14sp" + android:textStyle="bold" + android:visibility="gone" + tools:visibility="visible"/> + + android:id="@+id/textView1" + style="@style/BoideloQuestionText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:text="Question" + android:textSize="26sp"/> - @@ -153,33 +153,34 @@ app:layout_constraintStart_toStartOf="parent"> - + android:id="@+id/skipButton" + style="@style/BoideloButton" + android:layout_width="229dp" + android:layout_height="match_parent" + android:layout_marginEnd="8dp" + android:layout_weight="1" + android:onClick="onSkipClick" + android:text="Abandonner le défi" + android:textSize="12sp" + android:textColor="@color/error" + app:backgroundTint="@color/surface_variant" + app:cornerRadius="28dp"/> + diff --git a/app/src/main/res/layout/activity_jeux_parametres.xml b/app/src/main/res/layout/activity_jeux_parametres.xml index 60b59cf..006a40f 100644 --- a/app/src/main/res/layout/activity_jeux_parametres.xml +++ b/app/src/main/res/layout/activity_jeux_parametres.xml @@ -11,16 +11,7 @@ - - - - + android:theme="@style/ThemeOverlay.AppCompat.Dark"/> - - + android:orientation="vertical" + android:padding="16dp"> - + - + android:layout_marginBottom="20dp" + android:orientation="vertical"> + + + android:id="@+id/textView1" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Nombre de questions" + android:textColor="@color/text_primary" + android:textSize="16sp"/> + android:id="@+id/questionCountValue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/bg_card" + android:paddingStart="12dp" + android:paddingTop="4dp" + android:paddingEnd="12dp" + android:paddingBottom="4dp" + android:text="50" + android:textColor="@color/primary" + android:textSize="14sp" + android:textStyle="bold"/> + android:id="@+id/seekBar1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:progressTint="@color/accent" + android:thumbTint="@color/accent"/> - - + android:layout_marginBottom="20dp" + android:orientation="vertical"> + + + android:id="@+id/textView2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Ajout de gorgées" + android:textColor="@color/text_primary" + android:textSize="16sp"/> + android:id="@+id/gorgeesValue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/bg_card" + android:paddingStart="12dp" + android:paddingTop="4dp" + android:paddingEnd="12dp" + android:paddingBottom="4dp" + android:text="0" + android:textColor="@color/accent" + android:textSize="14sp" + android:textStyle="bold"/> + android:id="@+id/seekBar2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:progressTint="@color/accent" + android:thumbTint="@color/accent"/> - - + android:layout_marginTop="12dp" + app:cardBackgroundColor="@color/surface_variant" + app:cardCornerRadius="8dp" + app:cardElevation="0dp"> + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 913b625..7fb38b0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -11,70 +11,63 @@ - - - - + android:theme="@style/ThemeOverlay.AppCompat.Dark"/> + + + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + android:id="@+id/Titre" + style="@style/BoideloTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:layout_marginBottom="16dp" + android:text="@string/bienvenue"/> - - + android:layout_marginBottom="16dp" + app:cardBackgroundColor="@color/accent" + app:cardCornerRadius="12dp" + app:cardElevation="2dp"> + + + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_player_three" + app:tint="@color/white"/> + android:id="@+id/playerCountText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Joueurs: 0 / min. 3" + android:textColor="@color/white" + android:textSize="14sp" + android:textStyle="bold"/> @@ -82,119 +75,120 @@ - - + android:layout_marginBottom="16dp" + app:cardBackgroundColor="@color/white" + app:cardCornerRadius="16dp" + app:cardElevation="4dp" + app:strokeColor="@color/surface_variant" + app:strokeWidth="1dp"> + + + android:id="@+id/textView2" + style="@style/BoideloCaption" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:gravity="center" + android:text="@string/laisse_vide_si_il_y_a_pas_assez_de_joueur"/> - - + android:layout_marginBottom="12dp" + android:hint="@string/nom" + app:boxBackgroundColor="@color/surface" + app:boxStrokeColor="@color/primary" + app:boxStrokeWidth="2dp" + app:endIconMode="clear_text" + app:errorEnabled="false" + app:hintTextColor="@color/text_hint" + style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> + + - - + android:layout_marginBottom="12dp" + android:hint="@string/nom" + app:boxBackgroundColor="@color/surface" + app:boxStrokeColor="@color/primary" + app:boxStrokeWidth="2dp" + app:endIconMode="clear_text" + app:hintTextColor="@color/text_hint" + style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> + + - - + android:layout_marginBottom="12dp" + android:hint="@string/nom" + app:boxBackgroundColor="@color/surface" + app:boxStrokeColor="@color/primary" + app:boxStrokeWidth="2dp" + app:endIconMode="clear_text" + app:hintTextColor="@color/text_hint" + style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> + + + android:id="@+id/nameEntryLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + android:id="@+id/Validation" + style="@style/BoideloButton.Secondary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:onClick="onClickButton1" + android:text="@string/c_ok" + app:icon="@android:drawable/ic_input_add" + app:iconGravity="textStart"/> @@ -202,25 +196,23 @@ + android:layout_width="match_parent" + android:layout_height="80dp"/> - - + android:id="@+id/Go" + android:layout_width="172dp" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_margin="16dp" + android:onClick="onClickButtonStart" + android:text="@string/go" + android:textColor="@color/text_primary" + app:backgroundTint="@color/accent" + app:icon="@android:drawable/ic_media_play" + app:iconTint="@color/text_primary"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 71107e2..c613ca2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,20 +3,20 @@ J10 Pseudo Nom - c ki - komment il s\'appel + C\'est qui + comment il s\'appelle who Joueur - Prenom + Prénom Ajouter une nouvelle personne - Pour commencer le jeu, il suffit d\'abord de rentrer le noms des joueurs + Pour commencer le jeu, il suffit d\'abord de rentrer les noms des joueurs Joueur : Bienvenue sur Boidelo Eclatax (+4 Gorgées) Habitués (+2 Gorgées) "Suivant !" Paramètres du jeu - Commencer a vous mettre une mine ! + Commencer à vous mettre une mine ! Activer les questions par ChatGPT Clé API OpenAI OpenAI [En cours de développement]