fix tournament idle resign bug

This commit is contained in:
Thibault Duplessis 2012-09-23 13:42:46 +02:00
parent d98a6f954b
commit 0d132d0826
6 changed files with 33 additions and 18 deletions

View file

@ -342,6 +342,8 @@ case class DbGame(
def playerMoves(color: Color): Int = (turns + color.fold(1, 0)) / 2 def playerMoves(color: Color): Int = (turns + color.fold(1, 0)) / 2
def playerHasMoved(color: Color) = playerMoves(color) > 0
def playerBlurPercent(color: Color): Int = (turns > 5).fold( def playerBlurPercent(color: Color): Int = (turns > 5).fold(
(player(color).blurs * 100) / playerMoves(color), (player(color).blurs * 100) / playerMoves(color),
0 0

View file

@ -33,4 +33,7 @@ object Pov {
game player playerId map { p new Pov(game, p.color) } game player playerId map { p new Pov(game, p.color) }
} }
case class PovRef(gameId: String, color: Color) case class PovRef(gameId: String, color: Color) {
def unary_! = PovRef(gameId, !color)
}

View file

@ -40,7 +40,7 @@ final class RoundEnv(
playerTimeout = RoundPlayerTimeout playerTimeout = RoundPlayerTimeout
)), name = ActorRoundHubMaster) )), name = ActorRoundHubMaster)
lazy val moveNotifier = new MoveNotifier( private lazy val moveNotifier = new MoveNotifier(
siteHubName = ActorSiteHub, siteHubName = ActorSiteHub,
lobbyHubName = ActorLobbyHub, lobbyHubName = ActorLobbyHub,
tournamentHubMasterName = ActorTournamentHubMaster, tournamentHubMasterName = ActorTournamentHubMaster,

View file

@ -1,7 +1,8 @@
package lila package lila
package tournament package tournament
import game.{ DbGame, DbPlayer, GameRepo, Pov } import chess.Color
import game.{ DbGame, DbPlayer, GameRepo, Pov, PovRef }
import user.User import user.User
import round.Meddler import round.Meddler
@ -16,6 +17,8 @@ final class GameJoiner(
timelinePush: DbGame IO[Unit], timelinePush: DbGame IO[Unit],
getUser: String IO[Option[User]]) { getUser: String IO[Option[User]]) {
private val secondsToMove = 20
def apply(tour: Started)(pairing: Pairing): IO[DbGame] = for { def apply(tour: Started)(pairing: Pairing): IO[DbGame] = for {
user1 getUser(pairing.user1) map (_ err "No such user " + pairing) user1 getUser(pairing.user1) map (_ err "No such user " + pairing)
user2 getUser(pairing.user2) map (_ err "No such user " + pairing) user2 getUser(pairing.user2) map (_ err "No such user " + pairing)
@ -38,23 +41,31 @@ final class GameJoiner(
_ gameRepo insert game _ gameRepo insert game
_ gameRepo denormalizeStarted game _ gameRepo denormalizeStarted game
_ timelinePush(game) _ timelinePush(game)
_ scheduleIdleCheck(game.id) _ scheduleIdleCheck(PovRef(game.id, Color.White), secondsToMove)
} yield game } yield game
private def scheduleIdleCheck(gameId: String) = io { private def scheduleIdleCheck(povRef: PovRef, in: Int) = io {
Akka.system.scheduler.scheduleOnce(20 seconds)(idleCheck(gameId)) Akka.system.scheduler.scheduleOnce(in seconds)(idleCheck(povRef))
} } map (_ ())
private def idleCheck(gameId: String) { private def idleCheck(povRef: PovRef) {
(for { (for {
gameOption gameRepo game gameId povOption gameRepo pov povRef
_ gameOption.fold( _ povOption.filter(_.game.playable).fold(idleResult, io())
game game.playerWhoDidNotMove.fold(
player roundMeddler resign Pov(game, player),
io()
),
io()
)
} yield ()).unsafePerformIO } yield ()).unsafePerformIO
} }
private def idleResult(pov: Pov) = {
val idle = !pov.game.playerHasMoved(pov.color)
idle.fold(
roundMeddler resign pov,
(pov.color.white && !pov.game.playerHasMoved(Color.Black)).fold(
scheduleIdleCheck(!pov.ref, pov.game.lastMoveTime.fold(
lastMoveTime lastMoveTime - nowSeconds + secondsToMove,
secondsToMove
)),
io()
)
)
}
} }

View file

@ -30,7 +30,7 @@ final class HubMaster(
case msg @ SendTo(_, _) hubs.values foreach (_ ! msg) case msg @ SendTo(_, _) hubs.values foreach (_ ! msg)
case Forward(id, msg) hubs.get(id).foreach(_ ! msg) case Forward(id, msg) hubs get id foreach (_ ! msg)
case GetHub(id: String) sender ! { case GetHub(id: String) sender ! {
(hubs get id) | { (hubs get id) | {

1
todo
View file

@ -49,7 +49,6 @@ tournament detect leavers and withdraw them (started) (also use force resign)
-> or show current tournament on every page, with (join) and (redraw) buttons -> or show current tournament on every page, with (join) and (redraw) buttons
tournament warmup games tournament warmup games
send lobby new forum posts html through websockets send lobby new forum posts html through websockets
BUG tournament idle resign: based on 20 seconds added time! can make black resign by playing after 19s
AI thinks during your time (premove?) http://en.lichess.org/forum/lichess-feedback/y-u-so-greedy-with-time-stockfish#4 AI thinks during your time (premove?) http://en.lichess.org/forum/lichess-feedback/y-u-so-greedy-with-time-stockfish#4
- in fact it does not, but the UI clocks only update once the ai made the move - in fact it does not, but the UI clocks only update once the ai made the move
- solution: do AI asynchronously. Send player move events right away, - solution: do AI asynchronously. Send player move events right away,