lila/modules/game/src/main/Pov.scala

121 lines
3.3 KiB
Scala

package lila.game
import chess.Color
import lila.user.User
case class Pov(game: Game, color: Color) {
def player = game player color
def playerId = player.id
def typedPlayerId = Game.PlayerId(player.id)
def fullId = game fullIdOf color
def gameId = game.id
def opponent = game player !color
def unary_! = Pov(game, !color)
def flip = Pov(game, !color)
def ref = PovRef(game.id, color)
def withGame(g: Game) = copy(game = g)
def withColor(c: Color) = copy(color = c)
lazy val isMyTurn = game.started && game.playable && game.turnColor == color
lazy val remainingSeconds: Option[Int] =
game.clock.map(c => c.remainingTime(color).roundSeconds).orElse {
game.playableCorrespondenceClock.map(_.remainingTime(color).toInt)
}
def hasMoved = game playerHasMoved color
def moves = game playerMoves color
def win = game wonBy color
def loss = game lostBy color
def forecastable = game.forecastable && game.turnColor != color
def mightClaimWin = game.resignable && !game.hasAi && game.hasClock && !isMyTurn
override def toString = ref.toString
}
object Pov {
def apply(game: Game): List[Pov] = game.players.map { apply(game, _) }
def naturalOrientation(game: Game) = apply(game, game.naturalOrientation)
def player(game: Game) = apply(game, game.player)
def apply(game: Game, player: Player) = new Pov(game, player.color)
def apply(game: Game, playerId: Player.ID): Option[Pov] =
game player playerId map { apply(game, _) }
def apply(game: Game, user: User): Option[Pov] =
game player user map { apply(game, _) }
def ofUserId(game: Game, userId: User.ID): Option[Pov] =
game playerByUserId userId map { apply(game, _) }
def opponentOfUserId(game: Game, userId: String): Option[Player] =
ofUserId(game, userId) map (_.opponent)
private def orInf(i: Option[Int]) = i getOrElse Int.MaxValue
private def isFresher(a: Pov, b: Pov) = {
val aDate = a.game.movedAt.getSeconds
val bDate = b.game.movedAt.getSeconds
if (aDate == bDate) a.gameId < b.gameId
else aDate > bDate
}
def priority(a: Pov, b: Pov) =
if (!a.isMyTurn && !b.isMyTurn) isFresher(a, b)
else if (!a.isMyTurn && b.isMyTurn) false
else if (a.isMyTurn && !b.isMyTurn) true
// first move has priority over games with more than 30s left
else if (!a.hasMoved && orInf(b.remainingSeconds) > 30) true
else if (!b.hasMoved && orInf(a.remainingSeconds) > 30) false
else if (orInf(a.remainingSeconds) < orInf(b.remainingSeconds)) true
else if (orInf(b.remainingSeconds) < orInf(a.remainingSeconds)) false
else isFresher(a, b)
}
case class PovRef(gameId: Game.ID, color: Color) {
def unary_! = PovRef(gameId, !color)
override def toString = s"$gameId/${color.name}"
}
case class PlayerRef(gameId: Game.ID, playerId: String)
object PlayerRef {
def apply(fullId: String): PlayerRef = PlayerRef(Game takeGameId fullId, Game takePlayerId fullId)
}
case class LightPov(game: LightGame, color: Color) {
def gameId = game.id
def player = game player color
def opponent = game player !color
def win = game wonBy color
}
object LightPov {
def apply(game: LightGame, player: Player) = new LightPov(game, player.color)
def ofUserId(game: LightGame, userId: User.ID): Option[LightPov] =
game playerByUserId userId map { apply(game, _) }
}