2013-05-18 09:26:37 -06:00
|
|
|
package lila.round
|
|
|
|
|
2013-12-05 16:53:18 -07:00
|
|
|
import lila.game.{ GameRepo, Game, UciMemo, Pov, Rewind, Event, Progress }
|
2014-05-01 06:08:54 -06:00
|
|
|
import lila.pref.{ Pref, PrefApi }
|
2013-05-18 09:26:37 -06:00
|
|
|
|
2014-05-01 06:08:54 -06:00
|
|
|
private[round] final class Takebacker(
|
|
|
|
messenger: Messenger,
|
|
|
|
uciMemo: UciMemo,
|
|
|
|
prefApi: PrefApi) {
|
2013-05-18 09:26:37 -06:00
|
|
|
|
2015-08-12 05:53:20 -06:00
|
|
|
def yes(pov: Pov): Fu[Events] = IfAllowed(pov.game) {
|
2014-05-01 06:08:54 -06:00
|
|
|
pov match {
|
2015-03-26 04:04:40 -06:00
|
|
|
case Pov(game, _) if pov.opponent.isProposingTakeback =>
|
|
|
|
if (pov.opponent.proposeTakebackAt == pov.game.turns) single(game)
|
|
|
|
else double(game)
|
|
|
|
case Pov(game, _) if pov.opponent.isAi => double(game)
|
2014-12-23 07:17:24 -07:00
|
|
|
case Pov(game, color) if (game playerCanProposeTakeback color) =>
|
2014-05-01 06:08:54 -06:00
|
|
|
messenger.system(game, _.takebackPropositionSent)
|
2015-03-26 04:04:40 -06:00
|
|
|
val progress = Progress(game) map { g =>
|
|
|
|
g.updatePlayer(color, _ proposeTakeback g.turns)
|
|
|
|
}
|
2015-05-13 15:04:24 -06:00
|
|
|
GameRepo save progress inject List(Event.TakebackOffers(color.white, color.black))
|
2014-05-01 06:08:54 -06:00
|
|
|
case _ => ClientErrorException.future("[takebacker] invalid yes " + pov)
|
|
|
|
}
|
2013-05-18 09:26:37 -06:00
|
|
|
}
|
2014-05-01 06:08:54 -06:00
|
|
|
|
2015-08-12 05:53:20 -06:00
|
|
|
def no(pov: Pov): Fu[Events] = IfAllowed(pov.game) {
|
2014-05-01 06:08:54 -06:00
|
|
|
pov match {
|
|
|
|
case Pov(game, color) if pov.player.isProposingTakeback => GameRepo save {
|
|
|
|
messenger.system(game, _.takebackPropositionCanceled)
|
|
|
|
Progress(game) map { g => g.updatePlayer(color, _.removeTakebackProposition) }
|
2015-05-13 15:04:24 -06:00
|
|
|
} inject List(Event.TakebackOffers(false, false))
|
2014-05-01 06:08:54 -06:00
|
|
|
case Pov(game, color) if pov.opponent.isProposingTakeback => GameRepo save {
|
|
|
|
messenger.system(game, _.takebackPropositionDeclined)
|
|
|
|
Progress(game) map { g => g.updatePlayer(!color, _.removeTakebackProposition) }
|
2015-05-13 15:04:24 -06:00
|
|
|
} inject List(Event.TakebackOffers(false, false))
|
2014-05-01 06:08:54 -06:00
|
|
|
case _ => ClientErrorException.future("[takebacker] invalid no " + pov)
|
|
|
|
}
|
2013-05-18 09:26:37 -06:00
|
|
|
}
|
|
|
|
|
2014-05-01 06:08:54 -06:00
|
|
|
def isAllowedByPrefs(game: Game): Fu[Boolean] =
|
2015-09-03 15:05:54 -06:00
|
|
|
if (game.hasAi) fuccess(true)
|
|
|
|
else game.userIds.map { userId =>
|
2014-05-01 06:08:54 -06:00
|
|
|
prefApi.getPref(userId, (p: Pref) => p.takeback)
|
|
|
|
}.sequenceFu map {
|
|
|
|
_.forall { p =>
|
|
|
|
p == Pref.Takeback.ALWAYS || (p == Pref.Takeback.CASUAL && game.casual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 05:53:20 -06:00
|
|
|
private def IfAllowed(game: Game)(f: => Fu[Events]): Fu[Events] =
|
|
|
|
if (!game.playable) ClientErrorException.future("[takebacker] game is over " + game.id)
|
|
|
|
else isAllowedByPrefs(game) flatMap {
|
2014-05-01 06:08:54 -06:00
|
|
|
_.fold(f, ClientErrorException.future("[takebacker] disallowed by preferences " + game.id))
|
|
|
|
}
|
|
|
|
|
2013-12-05 16:53:18 -07:00
|
|
|
private def single(game: Game): Fu[Events] = for {
|
2015-01-14 08:32:05 -07:00
|
|
|
fen ← GameRepo initialFen game
|
2013-12-29 04:38:07 -07:00
|
|
|
progress ← Rewind(game, fen).future
|
|
|
|
_ ← fuccess { uciMemo.drop(game, 1) }
|
|
|
|
events ← save(progress)
|
2013-12-05 16:53:18 -07:00
|
|
|
} yield events
|
2013-05-18 09:26:37 -06:00
|
|
|
|
2013-12-05 16:53:18 -07:00
|
|
|
private def double(game: Game): Fu[Events] = for {
|
2015-01-14 08:32:05 -07:00
|
|
|
fen ← GameRepo initialFen game
|
2013-12-05 16:53:18 -07:00
|
|
|
prog1 ← Rewind(game, fen).future
|
2014-02-17 02:12:19 -07:00
|
|
|
prog2 ← Rewind(prog1.game, fen).future map { progress =>
|
2013-12-05 16:53:18 -07:00
|
|
|
prog1 withGame progress.game
|
2013-05-18 09:26:37 -06:00
|
|
|
}
|
2013-12-05 16:53:18 -07:00
|
|
|
_ ← fuccess { uciMemo.drop(game, 2) }
|
|
|
|
events ← save(prog2)
|
|
|
|
} yield events
|
2013-05-18 09:26:37 -06:00
|
|
|
|
|
|
|
private def save(p1: Progress): Fu[Events] = {
|
|
|
|
val p2 = p1 + Event.Reload
|
2014-02-01 00:54:03 -07:00
|
|
|
messenger.system(p2.game, _.takebackPropositionAccepted)
|
2013-12-29 04:38:07 -07:00
|
|
|
(GameRepo save p2) inject p2.events
|
2013-05-18 09:26:37 -06:00
|
|
|
}
|
|
|
|
}
|