From e9f1c88348595a911445d7751dab7bcc63ea141e Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 22 Oct 2024 11:30:50 +0200 Subject: [PATCH] refactor game moretime, allow bypassing some conditions with API call --- modules/core/src/main/game/Game.scala | 5 --- modules/round/src/main/JsonView.scala | 2 +- modules/round/src/main/Moretimer.scala | 41 +++++++++--------------- modules/round/src/main/RoundMobile.scala | 2 +- 4 files changed, 17 insertions(+), 33 deletions(-) diff --git a/modules/core/src/main/game/Game.scala b/modules/core/src/main/game/Game.scala index 1999a1228418f..92e5a8ae3e163 100644 --- a/modules/core/src/main/game/Game.scala +++ b/modules/core/src/main/game/Game.scala @@ -163,11 +163,6 @@ case class Game( def boosted = rated && finished && bothPlayersHaveMoved && playedTurns < 10 - def moretimeable(color: Color) = - playable && canTakebackOrAddTime && !hasRule(_.noGiveTime) && { - clock.exists(_.moretimeable(color)) || correspondenceClock.exists(_.moretimeable(color)) - } - def abortable = status == Status.Started && playedTurns < 2 && nonMandatory def abortableByUser = abortable && !hasRule(_.noAbort) diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index f6d62689684f6..bf7dc549e2de4 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -68,7 +68,7 @@ final class JsonView( flags: ExportOptions ): Fu[JsObject] = for takebackable <- takebacker.isAllowedIn(pov.game, Preload(prefs)) - moretimeable <- moretimer.isAllowedIn(pov.game, Preload(prefs), byAdmin = false) + moretimeable <- moretimer.isAllowedIn(pov.game, Preload(prefs), force = false) socket <- getSocketStatus(pov.game) pref = prefs(pov.color) yield diff --git a/modules/round/src/main/Moretimer.scala b/modules/round/src/main/Moretimer.scala index 0b472f3da9295..0eba855ffe8dd 100644 --- a/modules/round/src/main/Moretimer.scala +++ b/modules/round/src/main/Moretimer.scala @@ -18,25 +18,24 @@ final class Moretimer( // pov of the player giving more time def apply(pov: Pov, duration: FiniteDuration, force: Boolean): Fu[Option[Progress]] = - IfAllowed(pov.game, Preload.none, force): - (pov.game - .moretimeable(!pov.color)) - .so: - if pov.game.hasClock - then give(pov.game, List(!pov.color), duration).some - else - pov.game.hasCorrespondenceClock.option: - messenger.volatile(pov.game, s"${!pov.color} gets more time") - val p = correspondenceGiveTime(pov.game) - p.game.correspondenceClock.map(Event.CorrespondenceClock.apply).fold(p)(p + _) + isAllowedIn(pov.game, Preload.none, force).map: + case false => + logger.warn(s"[moretimer] not allowed on ${pov.game.id}") + none + case true => + if pov.game.clock.exists(_.moretimeable(!pov.color)) + then give(pov.game, List(!pov.color), duration).some + else if pov.game.correspondenceClock.exists(_.moretimeable(!pov.color)) + then + messenger.volatile(pov.game, s"${!pov.color} gets more time") + val p = Progress(pov.game, pov.game.copy(movedAt = nowInstant)) + p.game.correspondenceClock.map(Event.CorrespondenceClock.apply).foldLeft(p)(_ + _).some + else none - TODO.duplicated(code) def isAllowedIn(game: Game, prefs: Preload[ByColor[Pref]], force: Boolean): Fu[Boolean] = - (game.canTakebackOrAddTime && game.playable).so: + (game.playable && !game.isUnlimited && game.canTakebackOrAddTime).so: if force then fuccess(true) - else (!game.metadata.hasRule(_.noGiveTime)).so(isAllowedByPrefs(game, prefs)) - - private def correspondenceGiveTime(g: Game) = Progress(g, g.copy(movedAt = nowInstant)) + else (!game.hasRule(_.noGiveTime)).so(isAllowedByPrefs(game, prefs)) private[round] def give(game: Game, colors: List[Color], unchecked: FiniteDuration): Progress = game.clock.fold(Progress(game)): clock => @@ -58,13 +57,3 @@ final class Moretimer( .dmap: _.forall: p => p.moretime == Pref.Moretime.ALWAYS || (p.moretime == Pref.Moretime.CASUAL && game.casual) - - private def IfAllowed[A](game: Game, prefs: Preload[ByColor[Pref]], force: Boolean)(f: => A): Fu[A] = - if !game.playable then fufail(ClientError("[moretimer] game is over")) - else if !game.canTakebackOrAddTime then fufail(ClientError("[moretimer] Can't add time to this game")) - else if !force && game.metadata.hasRule(_.noGiveTime) then - fufail(ClientError("[moretimer] game rules disallows it")) - else - isAllowedByPrefs(game, prefs).flatMap: - if _ then fuccess(f) - else fufail(ClientError("[moretimer] disallowed by preferences " + game.id)) diff --git a/modules/round/src/main/RoundMobile.scala b/modules/round/src/main/RoundMobile.scala index def55b84f90f3..7dd29ffd19b79 100644 --- a/modules/round/src/main/RoundMobile.scala +++ b/modules/round/src/main/RoundMobile.scala @@ -60,7 +60,7 @@ final class RoundMobile( users <- game.userIdPair.traverse(_.so(lightUserGet)) prefs <- prefApi.byId(game.userIdPair) takebackable <- takebacker.isAllowedIn(game, Preload(prefs)) - moretimeable <- moretimer.isAllowedIn(game, Preload(prefs), byAdmin = false) + moretimeable <- moretimer.isAllowedIn(game, Preload(prefs), force = false) chat <- use.chat.so(getPlayerChat(game, myPlayer.exists(_.hasUser))) chatLines <- chat.map(_.chat).soFu(lila.chat.JsonView.asyncLines) bookmarked <- use.bookmark.so(bookmarkExists(game, myPlayer.flatMap(_.userId)))