Améliorations majeures : bugfix, refactoring, sécurité et tests

🐛 Bugfixes:
- Correction des noms en double : vérification uniques des joueurs (insensible à la casse)
- Accord des verbes selon le nombre de joueurs : "boit/distribue" (1 joueur) vs "boivent/distribuent" (2+)
- Défis minimum 3 manches au lieu de 2 (réglable via slider -5 à +15, défaut 0)
- Gorgées minimum 1 au lieu de 2

🎨 Design:
- Bouton de suppression élégant : circulaire blanc avec icône grise (remplace croix rouge sur fond noir)

♻️ Refactoring (Jeux.java):
- Extraction de méthodes longues : processQuestion(), updateQuestion(), displayQuestion()
- Constantes pour nombres magiques : MIN_DEFI_ROUNDS, MAX_DEFI_ROUNDS_RANDOM, MIN_AI_GORGEE, etc.
- Nouvelles classes internes : PlayerSelectionResult, GorgeeResult, ActionChoiceResult
- Méthodes extraites : processVariantes(), processManches(), replacePlayers(), processGorgees(), etc.

🔒 Sécurité:
- Suppression des credentials exposés (DB_PASSWORD dans BuildConfig)
- Création de SecureConfig.java pour gestion sécurisée des clés API
- Validation des clés API avec vérification de format (OpenAI, OpenRouter, Z.ai)
- Protection HTML : ErrorHandler.escapeHtml() pour les noms de joueurs

⚠️ Gestion des erreurs:
- ErrorHandler.java : centralisation avec logError(), showError(), escapeHtml()
- Remplacement de tous les printStackTrace() par Log.e() avec TAG descriptif
- Messages utilisateurs clairs et informatifs

🧪 Tests:
- QuestionTest.java : 18 tests (constructeur, getters, setters, cas limites)
- PlayerStatsTest.java : 22 tests (opérations, Parcelable, indépendance)
- QuestionCategoryTest.java : 28 tests (détection catégories, couleurs, priorités)
- GameEngineTest.java : +15 tests (manches, états, préservation questions)
- Couverture : ~89% sur les classes testées

📦 Dépendances:
- compileSdk/targetSdk : 33 → 35
- OkHttp : 4.9.1 → 4.12.0
- Material : 1.9.0 → 1.12.0
- AppCompat : 1.6.1 → 1.7.0
- Gson : 2.8.8 → 2.11.0

📝 Documentation:
- Javadoc améliorée pour Question.java, PlayerStats.java
- PreferencesKeys.java : constantes centralisées pour SharedPreferences

🔨 Nettoyage:
- Suppression de Jeuxold.java (fichier obsolète)
- question.json : 165 questions avec IDs uniques (correction des doublons)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
feldenr
2026-01-14 14:16:38 +01:00
co-authored by Claude
parent 7ba8e54368
commit ecb44f1934
48 changed files with 3576 additions and 715 deletions
@@ -0,0 +1,87 @@
package com.example.boidelov3.utils;
import android.content.Context;
/**
* Gestionnaire de sons pour l'application
* Utilise SoundGenerator pour créer des sons sans fichiers externes
*/
public class SoundManager {
private static SoundManager instance;
private SoundGenerator soundGenerator;
private Context context;
/**
* Obtient l'instance unique du SoundManager (Singleton)
*/
public static synchronized SoundManager getInstance(Context context) {
if (instance == null) {
instance = new SoundManager(context.getApplicationContext());
}
return instance;
}
/**
* Constructeur privé
*/
private SoundManager(Context context) {
this.context = context;
this.soundGenerator = new SoundGenerator();
}
/**
* Joue le son de clic
*/
public void playClick() {
if (soundGenerator != null) {
soundGenerator.playClick();
}
}
/**
* Joue le son de succès
*/
public void playSuccess() {
if (soundGenerator != null) {
soundGenerator.playSuccess();
}
}
/**
* Joue le son de manche (nouveau défi)
*/
public void playManche() {
if (soundGenerator != null) {
soundGenerator.playManche();
}
}
/**
* Joue le son de fin de partie
*/
public void playFin() {
if (soundGenerator != null) {
soundGenerator.playFin();
}
}
/**
* Active ou désactive le son
*/
public void setMuted(boolean muted) {
if (soundGenerator != null) {
soundGenerator.setMuted(muted);
}
}
/**
* Libère les ressources
*/
public void release() {
if (soundGenerator != null) {
soundGenerator.release();
soundGenerator = null;
}
instance = null;
}
}