Files
Application/app/src/main/res/layout/activity_jeux_parametres.xml
T
feldenr ecb44f1934 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>
2026-01-14 14:16:38 +01:00

398 lines
19 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/surface"
tools:context=".JeuxParametres">
<!-- App Bar -->
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
<!-- Main Content -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Title -->
<TextView
android:id="@+id/Titre"
style="@style/BoideloTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="@string/param_tres_du_jeu" />
<!-- Game Settings Card -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardBackgroundColor="@color/card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Number of Questions -->
<TextView
style="@style/BoideloSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="Paramètres de partie"
app:drawableStartCompat="@android:drawable/ic_menu_edit"
app:drawableTint="@color/primary"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
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"/>
<TextView
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"/>
</LinearLayout>
<SeekBar
android:id="@+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressTint="@color/accent"
android:thumbTint="@color/accent"/>
</LinearLayout>
<!-- Drink Addition -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
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"/>
<TextView
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"/>
</LinearLayout>
<SeekBar
android:id="@+id/seekBar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressTint="@color/accent"
android:thumbTint="@color/accent"/>
<!-- Palier Indicator -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:cardBackgroundColor="@color/surface_variant"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="12dp"
android:text="Palier : Grosse merde"
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:textStyle="bold"/>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- Duration of Challenges -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textViewDuration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Durée des défis"
android:textColor="@color/text_primary"
android:textSize="16sp"/>
<TextView
android:id="@+id/durationValue"
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/primary"
android:textSize="14sp"
android:textStyle="bold"/>
</LinearLayout>
<SeekBar
android:id="@+id/seekBarDuration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressTint="@color/accent"
android:thumbTint="@color/accent"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- OpenAI Settings Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/openaiCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardBackgroundColor="@color/card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:strokeColor="@color/surface_variant"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="8dp"
android:src="@android:drawable/ic_menu_edit"
app:tint="@color/primary" />
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/openai"
android:textColor="@color/text_primary"
android:textSize="18sp"
android:textStyle="bold" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/checkBoxGPT"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- Provider Selection -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayoutProvider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:enabled="false"
android:hint="Fournisseur IA"
app:boxBackgroundColor="@color/surface"
app:boxStrokeColor="@color/primary"
app:hintTextColor="@color/text_hint"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
<AutoCompleteTextView
android:id="@+id/autoCompleteProvider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="OpenAI" />
</com.google.android.material.textfield.TextInputLayout>
<!-- API Key Input -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayoutApiKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Clé API"
app:boxBackgroundColor="@color/surface"
app:boxStrokeColor="@color/primary"
app:endIconMode="password_toggle"
app:hintTextColor="@color/text_hint"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editTextGPT"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Ratio SeekBar -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textViewRatioGen"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="Ratio BDD/OPENAI : 1/8"
android:textColor="@color/text_primary"
android:textSize="14sp" />
</LinearLayout>
<SeekBar
android:id="@+id/seekBar3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:progressTint="@color/primary_light"
android:thumbTint="@color/primary_light" />
</LinearLayout>
<!-- Test API Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/ButtonTestApi"
style="@style/BoideloButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:onClick="onClickButtonTestAPI"
android:text="@string/test_de_connectivit_openai"
app:backgroundTint="@color/surface_variant"
app:icon="@android:drawable/ic_menu_info_details"
app:iconGravity="textStart" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Bottom Spacer -->
<View
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<!-- Floating Action Button -->
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/Go2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:onClick="onClickButtonStart"
android:text="@string/commencer_a_vous_mettre_une_mine"
android:textColor="@color/text_primary"
app:backgroundTint="@color/accent"
app:icon="@android:drawable/ic_media_play"
app:iconTint="@color/text_primary" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>