fix tournament idle resign bug

pull/83/head
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 playerHasMoved(color: Color) = playerMoves(color) > 0
def playerBlurPercent(color: Color): Int = (turns > 5).fold(
(player(color).blurs * 100) / playerMoves(color),
0

View File

@ -33,4 +33,7 @@ object Pov {
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
)), name = ActorRoundHubMaster)
lazy val moveNotifier = new MoveNotifier(
private lazy val moveNotifier = new MoveNotifier(
siteHubName = ActorSiteHub,
lobbyHubName = ActorLobbyHub,
tournamentHubMasterName = ActorTournamentHubMaster,

View File

@ -1,7 +1,8 @@
package lila
package tournament
import game.{ DbGame, DbPlayer, GameRepo, Pov }
import chess.Color
import game.{ DbGame, DbPlayer, GameRepo, Pov, PovRef }
import user.User
import round.Meddler
@ -16,6 +17,8 @@ final class GameJoiner(
timelinePush: DbGame IO[Unit],
getUser: String IO[Option[User]]) {
private val secondsToMove = 20
def apply(tour: Started)(pairing: Pairing): IO[DbGame] = for {
user1 getUser(pairing.user1) 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 denormalizeStarted game
_ timelinePush(game)
_ scheduleIdleCheck(game.id)
_ scheduleIdleCheck(PovRef(game.id, Color.White), secondsToMove)
} yield game
private def scheduleIdleCheck(gameId: String) = io {
Akka.system.scheduler.scheduleOnce(20 seconds)(idleCheck(gameId))
}
private def scheduleIdleCheck(povRef: PovRef, in: Int) = io {
Akka.system.scheduler.scheduleOnce(in seconds)(idleCheck(povRef))
} map (_ ())
private def idleCheck(gameId: String) {
private def idleCheck(povRef: PovRef) {
(for {
gameOption gameRepo game gameId
_ gameOption.fold(
game game.playerWhoDidNotMove.fold(
player roundMeddler resign Pov(game, player),
io()
),
io()
)
povOption gameRepo pov povRef
_ povOption.filter(_.game.playable).fold(idleResult, io())
} 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 Forward(id, msg) hubs.get(id).foreach(_ ! msg)
case Forward(id, msg) hubs get id foreach (_ ! msg)
case GetHub(id: String) sender ! {
(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
tournament warmup games
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
- 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,