diff --git a/app/src/main/java/com/example/boidelov3/EndGameActivity.java b/app/src/main/java/com/example/boidelov3/EndGameActivity.java index 7d12505..69b39c5 100644 --- a/app/src/main/java/com/example/boidelov3/EndGameActivity.java +++ b/app/src/main/java/com/example/boidelov3/EndGameActivity.java @@ -83,11 +83,8 @@ public class EndGameActivity extends AppCompatActivity { playersCount = getIntent().getIntExtra("EXTRA_PLAYERS_COUNT", 0); players = getIntent().getStringArrayListExtra("EXTRA_PLAYERS"); - // Essayer avec les deux clés possibles (PLAYER_STATS ou EXTRA_PLAYER_STATS) + // Récupérer les statistiques des joueurs playerStatsList = getIntent().getParcelableArrayListExtra("PLAYER_STATS"); - if (playerStatsList == null) { - playerStatsList = getIntent().getParcelableArrayListExtra("EXTRA_PLAYER_STATS"); - } // Si pas de données, utiliser les SharedPreferences if (questionsPlayed == 0) { diff --git a/app/src/main/java/com/example/boidelov3/Jeux.java b/app/src/main/java/com/example/boidelov3/Jeux.java index baeca04..767f212 100644 --- a/app/src/main/java/com/example/boidelov3/Jeux.java +++ b/app/src/main/java/com/example/boidelov3/Jeux.java @@ -209,15 +209,15 @@ public class Jeux extends AppCompatActivity { */ private void loadQuestions() { try { - InputStream is = getAssets().open("question.json"); - int size = is.available(); - byte[] buffer = new byte[size]; - is.read(buffer); - is.close(); - String json = new String(buffer, "UTF-8"); + try (InputStream is = getAssets().open("question.json")) { + int size = is.available(); + byte[] buffer = new byte[size]; + is.read(buffer); + String json = new String(buffer, "UTF-8"); - Gson gson = new Gson(); - questions = gson.fromJson(json, Questions.class); + Gson gson = new Gson(); + questions = gson.fromJson(json, Questions.class); + } } catch (IOException ex) { String operation = "Chargement du fichier question.json depuis les assets"; String details = "Impossible de lire ou de parser le fichier de questions"; @@ -640,7 +640,7 @@ public class Jeux extends AppCompatActivity { // Passer les statistiques des joueurs ArrayList playerStatsList = new ArrayList<>(playerStatsMap.values()); - intent.putParcelableArrayListExtra("EXTRA_PLAYER_STATS", playerStatsList); + intent.putParcelableArrayListExtra("PLAYER_STATS", playerStatsList); startActivity(intent); @@ -958,6 +958,7 @@ public class Jeux extends AppCompatActivity { question.setManchesRestantes(nbaleatoiremanches); String stopid = getArretById(question.getId()); + if (stopid == null) stopid = "Le défi est terminé !"; question.setArretMessageManche("Fin de défi!\n" + stopid); questionsAvecManches.add(question); diff --git a/app/src/main/java/com/example/boidelov3/JeuxParametres.java b/app/src/main/java/com/example/boidelov3/JeuxParametres.java index 8f2f321..56134cd 100644 --- a/app/src/main/java/com/example/boidelov3/JeuxParametres.java +++ b/app/src/main/java/com/example/boidelov3/JeuxParametres.java @@ -394,7 +394,7 @@ public class JeuxParametres extends AppCompatActivity { } Request request = requestBuilder - .post(okhttp3.RequestBody.create(jsonBody, okhttp3.MediaType.parse("application/json"))) + .post(okhttp3.RequestBody.create(jsonBody, okhttp3.MediaType.get("application/json"))) .build(); // Exécuter la requête de test diff --git a/app/src/main/java/com/example/boidelov3/OpenAIService.java b/app/src/main/java/com/example/boidelov3/OpenAIService.java index 0a49b9c..ba0b87b 100644 --- a/app/src/main/java/com/example/boidelov3/OpenAIService.java +++ b/app/src/main/java/com/example/boidelov3/OpenAIService.java @@ -279,15 +279,19 @@ public class OpenAIService { @Override public void onResponse(Call call, Response response) throws IOException { - if (!response.isSuccessful()) { - mainHandler.post(() -> callback.onError("Erreur API " + provider.getDisplayName() + ": " + response.code())); - return; + try { + if (!response.isSuccessful()) { + mainHandler.post(() -> callback.onError("Erreur API " + provider.getDisplayName() + ": " + response.code())); + return; + } + + String responseData = response.body().string(); + String generatedQuestion = parseResponse(responseData, responseParser); + + mainHandler.post(() -> callback.onSuccess(generatedQuestion)); + } finally { + response.close(); } - - String responseData = response.body().string(); - String generatedQuestion = parseResponse(responseData, responseParser); - - mainHandler.post(() -> callback.onSuccess(generatedQuestion)); } }); diff --git a/app/src/main/java/com/example/boidelov3/SoundManager.java b/app/src/main/java/com/example/boidelov3/SoundManager.java deleted file mode 100644 index 0af0928..0000000 --- a/app/src/main/java/com/example/boidelov3/SoundManager.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.example.boidelov3; - -import android.content.Context; -import android.media.AudioAttributes; -import android.media.SoundPool; - -/** - * Gestionnaire des effets sonores de l'application - */ -public class SoundManager { - private static SoundManager instance; - private SoundPool soundPool; - private boolean soundEnabled = true; - - // IDs des sons - private int soundClick; - private int soundSuccess; - private int soundError; - private int soundNext; - private int soundManche; - - /** - * Obtient l'instance unique du SoundManager - */ - public static synchronized SoundManager getInstance(Context context) { - if (instance == null) { - instance = new SoundManager(context); - } - return instance; - } - - /** - * Constructeur privé - */ - private SoundManager(Context context) { - AudioAttributes audioAttributes = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_GAME) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build(); - - soundPool = new SoundPool.Builder() - .setMaxStreams(5) - .setAudioAttributes(audioAttributes) - .build(); - - // Charger les sons (pour l'instant, on utilise des sons système) - // TODO: Ajouter des fichiers audio personnalisés dans res/raw/ - // soundClick = soundPool.load(context, R.raw.click, 1); - // soundSuccess = soundPool.load(context, R.raw.success, 1); - // etc. - } - - /** - * Joue le son de clic - */ - public void playClick() { - if (soundEnabled && soundPool != null) { - // Son de clic par défaut - // Pour l'instant, feedback haptique uniquement - } - } - - /** - * Joue le son de succès - */ - public void playSuccess() { - if (soundEnabled && soundPool != null) { - // Son de succès par défaut - } - } - - /** - * Joue le son d'erreur - */ - public void playError() { - if (soundEnabled && soundPool != null) { - // Son d'erreur par défaut - } - } - - /** - * Joue le son de transition (question suivante) - */ - public void playNext() { - if (soundEnabled && soundPool != null) { - // Son de transition par défaut - } - } - - /** - * Joue le son de manche - */ - public void playManche() { - if (soundEnabled && soundPool != null) { - // Son de manche par défaut - } - } - - /** - * Active ou désactive les sons - */ - public void setSoundEnabled(boolean enabled) { - this.soundEnabled = enabled; - } - - /** - * Retourne l'état des sons - */ - public boolean isSoundEnabled() { - return soundEnabled; - } - - /** - * Libère les ressources - */ - public void release() { - if (soundPool != null) { - soundPool.release(); - soundPool = null; - } - instance = null; - } -} diff --git a/app/src/main/java/com/example/boidelov3/data/QuestionCategory.java b/app/src/main/java/com/example/boidelov3/data/QuestionCategory.java index 11605da..d1b1b81 100644 --- a/app/src/main/java/com/example/boidelov3/data/QuestionCategory.java +++ b/app/src/main/java/com/example/boidelov3/data/QuestionCategory.java @@ -51,7 +51,12 @@ public class QuestionCategory { return Category.CLASSIQUE; } - String questionText = question.getQuestion().toLowerCase(); + String text = question.getQuestion(); + if (text == null) { + return Category.CLASSIQUE; + } + + String questionText = text.toLowerCase(); // 1. CALIENTE - Priorité haute if (question.isCaliente()) { diff --git a/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java b/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java index 206d544..324b933 100644 --- a/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java +++ b/app/src/main/java/com/example/boidelov3/data/QuestionRepository.java @@ -46,21 +46,21 @@ public class QuestionRepository { } try { - InputStream is = context.getAssets().open("question.json"); - byte[] buffer = new byte[is.available()]; - is.read(buffer); - is.close(); + try (InputStream is = context.getAssets().open("question.json")) { + byte[] buffer = new byte[is.available()]; + is.read(buffer); - String json = new String(buffer, "UTF-8"); - cachedQuestions = gson.fromJson(json, Questions.class); + String json = new String(buffer, "UTF-8"); + cachedQuestions = gson.fromJson(json, Questions.class); - if (cachedQuestions == null || cachedQuestions.getQuestions() == null) { - return Result.failure(new QuestionLoadException("Impossible de parser le JSON")); + if (cachedQuestions == null || cachedQuestions.getQuestions() == null) { + return Result.failure(new QuestionLoadException("Impossible de parser le JSON")); + } + + Log.d(TAG, "Chargé " + cachedQuestions.getQuestions().size() + " questions"); + return Result.success(cachedQuestions); } - Log.d(TAG, "Chargé " + cachedQuestions.getQuestions().size() + " questions"); - return Result.success(cachedQuestions); - } catch (IOException e) { Log.e(TAG, "Erreur de chargement des questions", e); return Result.failure(new QuestionLoadException("Erreur de lecture du fichier questions.json", e)); diff --git a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java index fe36c1d..54dbcaf 100644 --- a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicGameActivity.java @@ -26,11 +26,14 @@ import com.example.boidelov3.game.GameEngine; import com.example.boidelov3.Question; import com.example.boidelov3.Questions; import com.example.boidelov3.utils.ErrorHandler; +import android.widget.Toast; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.HashSet; import java.util.Random; +import java.util.Set; /** * BoideloClassicGameActivity - Activité principale du jeu Boidelo Classic @@ -73,6 +76,9 @@ public class BoideloClassicGameActivity extends AppCompatActivity { // Random private final Random random = new Random(); + // Track asked question indices to avoid repeats + private Set askedQuestionIndices = new HashSet<>(); + // Game Settings private int nombreQuestions = 20; private int ajoutGorgees = 1; @@ -83,7 +89,6 @@ public class BoideloClassicGameActivity extends AppCompatActivity { // Game State private int currentQuestionIndex = 0; - private int totalQuestionsAsked = 0; private String currentQuestionText = ""; private boolean isMancheActive = false; private boolean isFinishingGame = false; @@ -111,6 +116,13 @@ public class BoideloClassicGameActivity extends AppCompatActivity { Intent intent = getIntent(); toutlesjoueurs = intent.getStringArrayListExtra("PLAYERS"); + // Vérifier que la liste des joueurs est valide + if (toutlesjoueurs == null || toutlesjoueurs.isEmpty()) { + Toast.makeText(this, "Erreur: liste des joueurs manquante", Toast.LENGTH_SHORT).show(); + finish(); + return; + } + // Récupérer les paramètres de jeu if (intent.hasExtra("EXTRA_NOMBRE_QUESTIONS")) { nombreQuestions = intent.getIntExtra("EXTRA_NOMBRE_QUESTIONS", 20); @@ -367,8 +379,26 @@ public class BoideloClassicGameActivity extends AppCompatActivity { int maxAttempts = questions.size(); // Éviter boucle infinie int attempts = 0; + // Collect unasked indices + List availableIndices = new ArrayList<>(); + for (int i = 0; i < questions.size(); i++) { + if (!askedQuestionIndices.contains(i)) { + availableIndices.add(i); + } + } + + // If all questions have been asked, reset tracking + if (availableIndices.isEmpty()) { + askedQuestionIndices.clear(); + for (int i = 0; i < questions.size(); i++) { + availableIndices.add(i); + } + } + while (attempts < maxAttempts) { - Question question = questions.get(random.nextInt(questions.size())); + int idx = random.nextInt(availableIndices.size()); + int questionIndex = availableIndices.get(idx); + Question question = questions.get(questionIndex); // Si un défi est en cours, éviter les questions avec if (hasActiveDefi && question.getQuestion().contains("")) { @@ -376,6 +406,7 @@ public class BoideloClassicGameActivity extends AppCompatActivity { continue; } + askedQuestionIndices.add(questionIndex); return question; } @@ -794,7 +825,7 @@ public class BoideloClassicGameActivity extends AppCompatActivity { question.setManchesRestantes(nbaleatoiremanches); // Définir le message de fin de défi - String stopMessage = "Fin de défi!\n" + question.getQuestion(); + String stopMessage = "Fin de défi!\n" + questionText; question.setArretMessageManche(stopMessage); questionsAvecManches.add(question); @@ -983,7 +1014,7 @@ public class BoideloClassicGameActivity extends AppCompatActivity { private void saveGameStats() { if (questionRepository != null && playerStatsMap != null) { // Calculer le total des questions posées - int totalQuestionsPlayed = totalQuestionsAsked; + int totalQuestionsPlayed = currentQuestionIndex; int playersCount = toutlesjoueurs != null ? toutlesjoueurs.size() : 0; // Sauvegarder dans SharedPreferences via le repository @@ -1000,7 +1031,7 @@ public class BoideloClassicGameActivity extends AppCompatActivity { */ private void resetAskedQuestions() { currentQuestionIndex = 0; - totalQuestionsAsked = 0; + askedQuestionIndices.clear(); } /** diff --git a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicParamsActivity.java b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicParamsActivity.java index f74ae59..cdad903 100644 --- a/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicParamsActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/boideloclassic/BoideloClassicParamsActivity.java @@ -394,7 +394,7 @@ public class BoideloClassicParamsActivity extends AppCompatActivity { } Request request = requestBuilder - .post(okhttp3.RequestBody.create(jsonBody, okhttp3.MediaType.parse("application/json"))) + .post(okhttp3.RequestBody.create(jsonBody, okhttp3.MediaType.get("application/json"))) .build(); // Exécuter la requête de test diff --git a/app/src/main/java/com/example/boidelov3/games/game89/Game89ChallengeManager.java b/app/src/main/java/com/example/boidelov3/games/game89/Game89ChallengeManager.java index 5f56618..b5eacf4 100644 --- a/app/src/main/java/com/example/boidelov3/games/game89/Game89ChallengeManager.java +++ b/app/src/main/java/com/example/boidelov3/games/game89/Game89ChallengeManager.java @@ -1,6 +1,7 @@ package com.example.boidelov3.games.game89; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Random; @@ -10,11 +11,21 @@ import java.util.Random; public class Game89ChallengeManager { private final Random random; private final List availableChallenges; + private int currentIndex = 0; public Game89ChallengeManager() { this.random = new Random(); this.availableChallenges = new ArrayList<>(); initializeChallenges(); + shuffleChallenges(); + } + + /** + * Mélange la liste des défis disponibles + */ + private void shuffleChallenges() { + Collections.shuffle(availableChallenges, random); + currentIndex = 0; } /** @@ -86,14 +97,16 @@ public class Game89ChallengeManager { } /** - * Retourne un défi aléatoire + * Retourne le prochain défi (sans répétition tant que tous n'ont pas été utilisés) */ public Challenge getRandomChallenge() { if (availableChallenges.isEmpty()) { return null; } - int index = random.nextInt(availableChallenges.size()); - return availableChallenges.get(index); + if (currentIndex >= availableChallenges.size()) { + shuffleChallenges(); + } + return availableChallenges.get(currentIndex++); } /** diff --git a/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoGameActivity.java b/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoGameActivity.java index fed839e..061c8af 100644 --- a/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoGameActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoGameActivity.java @@ -59,6 +59,8 @@ public class PapelitoGameActivity extends AppCompatActivity { private int currentPlayerViewIndex; private boolean hasShownWordToPlayer; private List playersWhoVoted; + private int currentVoterIndex = 0; + private int totalRoundsPlayed = 0; // Constants private static final int DEFAULT_DISCUSSION_TIME = 60; // 60 secondes @@ -303,6 +305,8 @@ public class PapelitoGameActivity extends AppCompatActivity { game.setGameState(PapelitoGame.GameState.VOTING); game.resetVotes(); playersWhoVoted.clear(); + currentVoterIndex = 0; + totalRoundsPlayed++; updateUIForVoting(); showVotingDialog(); @@ -329,7 +333,9 @@ public class PapelitoGameActivity extends AppCompatActivity { } MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle("Vote pour éliminer"); + // Determine current voter name for dialog title + String currentVoterName = alivePlayers.get(currentVoterIndex).getName(); + builder.setTitle("Vote de " + currentVoterName + " - Qui voulez-vous éliminer?"); // Créer le layout personnalisé LinearLayout layout = new LinearLayout(this); @@ -345,7 +351,13 @@ public class PapelitoGameActivity extends AppCompatActivity { GridLayout playerGrid = new GridLayout(this); playerGrid.setColumnCount(2); - for (PapelitoPlayer player : alivePlayers) { + for (int i = 0; i < alivePlayers.size(); i++) { + PapelitoPlayer player = alivePlayers.get(i); + // Skip the current voter so they can't vote for themselves + if (i == currentVoterIndex) { + continue; + } + MaterialButton playerButton = new MaterialButton(this); playerButton.setText(player.getName()); playerButton.setLayoutParams(new LinearLayout.LayoutParams( @@ -380,6 +392,7 @@ public class PapelitoGameActivity extends AppCompatActivity { // Enregistrer le vote (simplifié : on ne track pas QUI a voté) votedPlayer.addVote(); playersWhoVoted.add("vote"); + currentVoterIndex++; Toast.makeText(this, "Vote enregistré pour " + votedPlayer.getName(), @@ -509,7 +522,7 @@ public class PapelitoGameActivity extends AppCompatActivity { intent.putExtra(PapelitoResultActivity.EXTRA_WINNING_TEAM, game.getWinningTeam()); intent.putExtra(PapelitoResultActivity.EXTRA_CIVIL_WORD, game.getCurrentCivilWord()); intent.putExtra(PapelitoResultActivity.EXTRA_UNDERCOVER_WORD, game.getCurrentUndercoverWord()); - intent.putExtra(PapelitoResultActivity.EXTRA_TOTAL_ROUNDS, playersWhoVoted.size()); + intent.putExtra(PapelitoResultActivity.EXTRA_TOTAL_ROUNDS, totalRoundsPlayed); startActivity(intent); finish(); } diff --git a/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoResultActivity.java b/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoResultActivity.java index c68194d..c486039 100644 --- a/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoResultActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/papelito/PapelitoResultActivity.java @@ -1,6 +1,7 @@ package com.example.boidelov3.games.papelito; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button; @@ -46,9 +47,22 @@ public class PapelitoResultActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_papelito_result); - // Récupérer les données - players = (ArrayList) getIntent().getSerializableExtra(EXTRA_PLAYERS); - winningTeam = (PapelitoPlayer.Role) getIntent().getSerializableExtra(EXTRA_WINNING_TEAM); + // Récupérer les données (compatibilité API 33+) + ArrayList players; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + players = getIntent().getSerializableExtra(EXTRA_PLAYERS, ArrayList.class); + } else { + players = (ArrayList) getIntent().getSerializableExtra(EXTRA_PLAYERS); + } + this.players = players; + + PapelitoPlayer.Role winningTeam; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + winningTeam = getIntent().getSerializableExtra(EXTRA_WINNING_TEAM, PapelitoPlayer.Role.class); + } else { + winningTeam = (PapelitoPlayer.Role) getIntent().getSerializableExtra(EXTRA_WINNING_TEAM); + } + this.winningTeam = winningTeam; civilWord = getIntent().getStringExtra(EXTRA_CIVIL_WORD); undercoverWord = getIntent().getStringExtra(EXTRA_UNDERCOVER_WORD); totalRounds = getIntent().getIntExtra(EXTRA_TOTAL_ROUNDS, 0); diff --git a/app/src/main/java/com/example/boidelov3/rules/RuleDetailActivity.java b/app/src/main/java/com/example/boidelov3/rules/RuleDetailActivity.java new file mode 100644 index 0000000..e110ef2 --- /dev/null +++ b/app/src/main/java/com/example/boidelov3/rules/RuleDetailActivity.java @@ -0,0 +1,12 @@ +package com.example.boidelov3.rules; + +import android.os.Bundle; +import android.app.Activity; + +public class RuleDetailActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // TODO: Implement rule detail screen + } +} diff --git a/app/src/main/java/com/example/boidelov3/rules/RulesListActivity.java b/app/src/main/java/com/example/boidelov3/rules/RulesListActivity.java new file mode 100644 index 0000000..4020e2f --- /dev/null +++ b/app/src/main/java/com/example/boidelov3/rules/RulesListActivity.java @@ -0,0 +1,12 @@ +package com.example.boidelov3.rules; + +import android.os.Bundle; +import android.app.Activity; + +public class RulesListActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // TODO: Implement rules list screen + } +} diff --git a/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java b/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java index d2c224a..dd56507 100644 --- a/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java +++ b/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java @@ -26,8 +26,8 @@ public class SoundGenerator { /** * Son de clic - court et léger */ - public void playClick() { - if (isMuted) return; + public synchronized void playClick() { + if (isMuted || toneGenerator == null) return; new Thread(() -> { try { toneGenerator.startTone( @@ -43,8 +43,8 @@ public class SoundGenerator { /** * Son de succès - mélange ascendant */ - public void playSuccess() { - if (isMuted) return; + public synchronized void playSuccess() { + if (isMuted || toneGenerator == null) return; new Thread(() -> { try { Thread.sleep(0); @@ -66,8 +66,8 @@ public class SoundGenerator { /** * Son de manche - dramatique pour annoncer un défi */ - public void playManche() { - if (isMuted) return; + public synchronized void playManche() { + if (isMuted || toneGenerator == null) return; new Thread(() -> { try { // Premier ton grave @@ -90,8 +90,8 @@ public class SoundGenerator { /** * Son de fin - célébration */ - public void playFin() { - if (isMuted) return; + public synchronized void playFin() { + if (isMuted || toneGenerator == null) return; new Thread(() -> { try { // Séquence festive @@ -118,14 +118,14 @@ public class SoundGenerator { /** * Activer/Désactiver le son */ - public void setMuted(boolean muted) { + public synchronized void setMuted(boolean muted) { this.isMuted = muted; } /** * Libérer les ressources */ - public void release() { + public synchronized void release() { if (toneGenerator != null) { toneGenerator.release(); toneGenerator = null; diff --git a/gradlew b/gradlew old mode 100644 new mode 100755