feat: implemented Lifetime- and TimeoutTimer
This commit is contained in:
		@ -0,0 +1,34 @@
 | 
			
		||||
package uulm.teamname.marvelous.server.lobby;
 | 
			
		||||
 | 
			
		||||
import uulm.teamname.marvelous.server.Server;
 | 
			
		||||
import uulm.teamname.marvelous.server.lobbymanager.Participant;
 | 
			
		||||
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
import java.util.concurrent.ScheduledExecutorService;
 | 
			
		||||
import java.util.concurrent.ThreadFactory;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A timer meant to time the entire Lifetime of the lobby, and if it is higher than the maximum permitted value,
 | 
			
		||||
 * call a callback given by the lobby to compute a winner, and quit the lobby.
 | 
			
		||||
 */
 | 
			
		||||
public class LifetimeTimer {
 | 
			
		||||
 | 
			
		||||
    private final ScheduledExecutorService timer;
 | 
			
		||||
    private final int maxGameTime;
 | 
			
		||||
    private final Runnable callback;
 | 
			
		||||
 | 
			
		||||
    LifetimeTimer(int maxGameTime, Runnable callback) {
 | 
			
		||||
        String lobbyThreadName = Thread.currentThread().getName();
 | 
			
		||||
        ThreadFactory threadFactory = r -> new Thread(r, lobbyThreadName + "-LifetimeTimerThread");
 | 
			
		||||
        this.timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
 | 
			
		||||
 | 
			
		||||
        this.maxGameTime = maxGameTime;
 | 
			
		||||
        this.callback = callback;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void startTimer() {
 | 
			
		||||
        timer.schedule(callback, maxGameTime, TimeUnit.SECONDS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,89 @@
 | 
			
		||||
package uulm.teamname.marvelous.server.lobby;
 | 
			
		||||
 | 
			
		||||
import org.tinylog.Logger;
 | 
			
		||||
import uulm.teamname.marvelous.server.Server;
 | 
			
		||||
import uulm.teamname.marvelous.server.lobbymanager.Participant;
 | 
			
		||||
 | 
			
		||||
import java.util.concurrent.*;
 | 
			
		||||
import java.util.function.BiConsumer;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
public class TimeoutTimer {
 | 
			
		||||
 | 
			
		||||
    private final ScheduledExecutorService timer;
 | 
			
		||||
 | 
			
		||||
    private ScheduledFuture<Participant> player1AlmostTimeout, player1Timeout;
 | 
			
		||||
    private ScheduledFuture<Participant> player2AlmostTimeout, player2Timeout;
 | 
			
		||||
 | 
			
		||||
    private final BiConsumer<Participant, Integer> almostTimeoutCallback;
 | 
			
		||||
    private final Consumer<Participant> timeoutCallback;
 | 
			
		||||
 | 
			
		||||
    private final int almostTimeoutTime, timeoutTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class that manages timeouts of players after not sending a message for a long time.
 | 
			
		||||
     *
 | 
			
		||||
     * @param timeoutTime           is the time that a player has to send any message
 | 
			
		||||
     * @param almostTimeoutCallback is the callback that is called if the timeoutTime is almost over
 | 
			
		||||
     * @param timeoutCallback       is the callback that is called when the timeoutTime is over
 | 
			
		||||
     */
 | 
			
		||||
    public TimeoutTimer(int timeoutTime,
 | 
			
		||||
                        BiConsumer<Participant, Integer> almostTimeoutCallback,
 | 
			
		||||
                        Consumer<Participant> timeoutCallback) {
 | 
			
		||||
        this.almostTimeoutCallback = almostTimeoutCallback;
 | 
			
		||||
        this.timeoutCallback = timeoutCallback;
 | 
			
		||||
 | 
			
		||||
        this.timeoutTime = timeoutTime;
 | 
			
		||||
        this.almostTimeoutTime = Math.max(timeoutTime - 15, Math.min(timeoutTime, 5));
 | 
			
		||||
 | 
			
		||||
        String lobbyThreadName = Thread.currentThread().getName();
 | 
			
		||||
        ThreadFactory threadFactory = r -> new Thread(r, lobbyThreadName + "-timeoutTimer");
 | 
			
		||||
        timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Refreshes the timeout timer for the given Participant. This is meant to be used for Players, not Spectators. */
 | 
			
		||||
    public void refreshTimer(Participant participant) {
 | 
			
		||||
        Logger.debug("Refreshing turnTimer for participant of type '{}'", participant.type);
 | 
			
		||||
        switch (participant.type) {
 | 
			
		||||
            case PlayerOne -> {
 | 
			
		||||
                Logger.trace("Was playerOne, refreshing...");
 | 
			
		||||
                if (player1AlmostTimeout != null) player1AlmostTimeout.cancel(false);
 | 
			
		||||
                player1AlmostTimeout =
 | 
			
		||||
                        timer.schedule(() -> {
 | 
			
		||||
                            almostTimeoutCallback.accept(participant, almostTimeoutTime - timeoutTime);
 | 
			
		||||
                            return participant;
 | 
			
		||||
                        }, this.almostTimeoutTime, TimeUnit.SECONDS);
 | 
			
		||||
 | 
			
		||||
                if (player1Timeout != null) player1Timeout.cancel(false);
 | 
			
		||||
                player1Timeout =
 | 
			
		||||
                        timer.schedule(() -> {
 | 
			
		||||
                            timeoutCallback.accept(participant);
 | 
			
		||||
                            return participant;
 | 
			
		||||
                        }, this.timeoutTime, TimeUnit.SECONDS);
 | 
			
		||||
            }
 | 
			
		||||
            case PlayerTwo -> {
 | 
			
		||||
                Logger.trace("Was playerOne, refreshing...");
 | 
			
		||||
                if (player2AlmostTimeout != null) player2AlmostTimeout.cancel(false);
 | 
			
		||||
                player2AlmostTimeout =
 | 
			
		||||
                        timer.schedule(() -> {
 | 
			
		||||
                            almostTimeoutCallback.accept(participant, almostTimeoutTime - timeoutTime);
 | 
			
		||||
                            return participant;
 | 
			
		||||
                        }, this.almostTimeoutTime, TimeUnit.SECONDS);
 | 
			
		||||
 | 
			
		||||
                if (player2Timeout != null) player2Timeout.cancel(false);
 | 
			
		||||
                player2Timeout =
 | 
			
		||||
                        timer.schedule(() -> {
 | 
			
		||||
                            timeoutCallback.accept(participant);
 | 
			
		||||
                            return participant;
 | 
			
		||||
                        }, this.timeoutTime, TimeUnit.SECONDS);
 | 
			
		||||
            }
 | 
			
		||||
            case Spectator -> Logger.warn("Timeout called on spectator '{}'. This is probably a bug.",
 | 
			
		||||
                    participant.id.getName());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user