fix tournament idle resign bug
This commit is contained in:
parent
d98a6f954b
commit
0d132d0826
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
1
todo
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue