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