Actualiser src/backend/ChessTimer.java

This commit is contained in:
Guillaume VALLENET 2025-04-25 16:12:57 +02:00
parent df366fa41e
commit 1c570c3d01
1 changed files with 56 additions and 36 deletions

View File

@ -3,21 +3,26 @@ package backend;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
/**
* ChessTimer manages the time control for both players in a chess game
*/
public class ChessTimer { public class ChessTimer {
private long whiteTimeMillis; // Time remaining for white player in milliseconds private long whiteTimeMillis; // Time remaining for white player in milliseconds
private long blackTimeMillis; // Time remaining for black player in milliseconds private long blackTimeMillis; // Time remaining for black player in milliseconds
private long lastUpdateTime; // Time when the timer was last updated private long lastUpdateTime; // The timestamp when timer was last updated
private boolean isRunning; // Is the timer currently running? private boolean isRunning; // Flag to track if timer is active
private boolean isWhiteTurn; // Is it white's turn? private boolean isWhiteTurn; // Flag to track which player's clock is running
private Timer timer; // Java util timer to handle periodic updates private Timer timer; // Java Timer object that handles periodic updates
private TimerUpdateListener listener; // Listener to notify UI when time changes private TimerUpdateListener listener; // Callback interface to notify UI of time changes
/** /**
* Interface for notifying time updates * Interface for notifying time updates to the UI or other components
*/ */
public interface TimerUpdateListener { public interface TimerUpdateListener {
// Called periodically to update displayed time
void onTimeUpdate(long whiteTimeMillis, long blackTimeMillis); void onTimeUpdate(long whiteTimeMillis, long blackTimeMillis);
void onTimeExpired(boolean isWhiteExpired); // Called when a player's time runs out // Called when a player runs out of time
void onTimeExpired(boolean isWhiteExpired);
} }
/** /**
@ -26,40 +31,43 @@ public class ChessTimer {
* @param listener Listener to receive time updates * @param listener Listener to receive time updates
*/ */
public ChessTimer(int initialTimeMinutes, TimerUpdateListener listener) { public ChessTimer(int initialTimeMinutes, TimerUpdateListener listener) {
// Convert minutes to milliseconds for internal tracking
this.whiteTimeMillis = initialTimeMinutes * 60 * 1000; this.whiteTimeMillis = initialTimeMinutes * 60 * 1000;
this.blackTimeMillis = initialTimeMinutes * 60 * 1000; this.blackTimeMillis = initialTimeMinutes * 60 * 1000;
this.isRunning = false; this.isRunning = false; // Timer starts paused
this.isWhiteTurn = true; // White starts in chess this.isWhiteTurn = true; // White always starts in chess
this.listener = listener; this.listener = listener; // Store the listener for callbacks
} }
/** /**
* Start the timer * Start the timer - begins counting down for the current player
*/ */
public void start() { public void start() {
if (!isRunning) { if (!isRunning) {
isRunning = true; isRunning = true;
// Record the current time to measure elapsed time later
lastUpdateTime = System.currentTimeMillis(); lastUpdateTime = System.currentTimeMillis();
// Schedule periodic updates (every 100ms) // Create a timer that updates every 100ms (10 times per second)
timer = new Timer(true); timer = new Timer(true); // true = daemon thread
timer.scheduleAtFixedRate(new TimerTask() { timer.scheduleAtFixedRate(new TimerTask() {
@Override @Override
public void run() { public void run() {
updateTime(); updateTime(); // Update the clock on each tick
} }
}, 0, 100); }, 0, 100); // Initial delay 0ms, then every 100ms
} }
} }
/** /**
* Stop the timer * Stop the timer - pauses countdown for both players
*/ */
public void stop() { public void stop() {
if (isRunning) { if (isRunning) {
isRunning = false; isRunning = false;
updateTime(); // Update one last time updateTime(); // Update one last time before stopping
// Clean up the timer resources
if (timer != null) { if (timer != null) {
timer.cancel(); timer.cancel();
timer = null; timer = null;
@ -72,56 +80,65 @@ public class ChessTimer {
* @param initialTimeMinutes New initial time in minutes * @param initialTimeMinutes New initial time in minutes
*/ */
public void reset(int initialTimeMinutes) { public void reset(int initialTimeMinutes) {
stop(); stop(); // Stop any running timer first
// Reset both clocks to the specified time
this.whiteTimeMillis = initialTimeMinutes * 60 * 1000; this.whiteTimeMillis = initialTimeMinutes * 60 * 1000;
this.blackTimeMillis = initialTimeMinutes * 60 * 1000; this.blackTimeMillis = initialTimeMinutes * 60 * 1000;
this.isWhiteTurn = true; this.isWhiteTurn = true; // White starts again
notifyTimeUpdate(); notifyTimeUpdate(); // Update the UI with new times
} }
/** /**
* Switch the active player * Switch the active player when a move is made
* @param isWhiteTurn True if it's now white's turn * @param isWhiteTurn True if it's now white's turn
*/ */
public void switchTurn(boolean isWhiteTurn) { public void switchTurn(boolean isWhiteTurn) {
if (isRunning) { if (isRunning) {
updateTime(); // Update time for the player who just completed their move // Before changing turns, update the current player's elapsed time
updateTime();
} }
// Switch to the other player's clock
this.isWhiteTurn = isWhiteTurn; this.isWhiteTurn = isWhiteTurn;
notifyTimeUpdate(); notifyTimeUpdate(); // Update the UI with current times
} }
/** /**
* Update the time based on elapsed time * Update the time based on elapsed time since last update
*/ */
private void updateTime() { private void updateTime() {
if (!isRunning) return; if (!isRunning) return; // Don't update if timer is paused
// Calculate elapsed time since last update
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long elapsedTime = currentTime - lastUpdateTime; long elapsedTime = currentTime - lastUpdateTime;
lastUpdateTime = currentTime; lastUpdateTime = currentTime; // Reset for next update
// Deduct time from the active player // Deduct time from the active player's clock
if (isWhiteTurn) { if (isWhiteTurn) {
// White's turn - deduct from white's clock
whiteTimeMillis -= elapsedTime; whiteTimeMillis -= elapsedTime;
if (whiteTimeMillis <= 0) { if (whiteTimeMillis <= 0) {
whiteTimeMillis = 0; // White ran out of time
stop(); whiteTimeMillis = 0; // Don't go negative
stop(); // Stop the timer
if (listener != null) { if (listener != null) {
listener.onTimeExpired(true); listener.onTimeExpired(true); // Notify that white's time expired
} }
} }
} else { } else {
// Black's turn - deduct from black's clock
blackTimeMillis -= elapsedTime; blackTimeMillis -= elapsedTime;
if (blackTimeMillis <= 0) { if (blackTimeMillis <= 0) {
blackTimeMillis = 0; // Black ran out of time
stop(); blackTimeMillis = 0; // Don't go negative
stop(); // Stop the timer
if (listener != null) { if (listener != null) {
listener.onTimeExpired(false); listener.onTimeExpired(false); // Notify that black's time expired
} }
} }
} }
// Notify the UI to update displayed times
notifyTimeUpdate(); notifyTimeUpdate();
} }
@ -130,6 +147,7 @@ public class ChessTimer {
*/ */
private void notifyTimeUpdate() { private void notifyTimeUpdate() {
if (listener != null) { if (listener != null) {
// Send current times to the UI
listener.onTimeUpdate(whiteTimeMillis, blackTimeMillis); listener.onTimeUpdate(whiteTimeMillis, blackTimeMillis);
} }
} }
@ -149,11 +167,13 @@ public class ChessTimer {
} }
/** /**
* Format milliseconds as "mm:ss" * Format milliseconds as "mm:ss" for display
*/ */
public static String formatTime(long timeMillis) { public static String formatTime(long timeMillis) {
// Extract minutes and seconds from milliseconds
int seconds = (int) (timeMillis / 1000) % 60; int seconds = (int) (timeMillis / 1000) % 60;
int minutes = (int) (timeMillis / (60 * 1000)); int minutes = (int) (timeMillis / (60 * 1000));
// Format as two digits for minutes and seconds
return String.format("%02d:%02d", minutes, seconds); return String.format("%02d:%02d", minutes, seconds);
} }