lila/modules/round/src/main/Finisher.scala

88 lines
2.9 KiB
Scala
Raw Normal View History

2013-04-08 13:21:03 -06:00
package lila.round
2013-05-24 11:04:49 -06:00
import chess.Color._
import chess.Status._
2013-12-17 15:20:18 -07:00
import chess.{ Status, Color, Speed, Variant }
2013-12-21 05:14:50 -07:00
2013-04-08 13:21:03 -06:00
import lila.db.api._
2014-01-27 06:38:23 -07:00
import lila.game.actorApi.FinishGame
2013-05-24 11:04:49 -06:00
import lila.game.tube.gameTube
import lila.game.{ GameRepo, Game, Pov, Event }
2014-02-17 02:12:19 -07:00
import lila.i18n.I18nKey.{ Select => SelectI18nKey }
2013-05-24 11:04:49 -06:00
import lila.user.tube.userTube
2014-07-26 01:50:19 -06:00
import lila.user.{ User, UserRepo, Perfs }
2013-04-08 13:21:03 -06:00
private[round] final class Finisher(
2013-04-08 13:21:03 -06:00
messenger: Messenger,
perfsUpdater: PerfsUpdater,
2014-02-27 17:18:22 -07:00
aiPerfApi: lila.ai.AiPerfApi,
crosstableApi: lila.game.CrosstableApi,
2014-04-20 14:26:40 -06:00
reminder: Reminder,
2014-01-27 06:38:23 -07:00
bus: lila.common.Bus) {
2013-04-08 13:21:03 -06:00
def apply(
2013-04-08 13:21:03 -06:00
game: Game,
2014-02-17 02:12:19 -07:00
status: Status.type => Status,
2013-04-08 13:21:03 -06:00
winner: Option[Color] = None,
message: Option[SelectI18nKey] = None): Fu[Events] = {
val prog = game.finish(status(Status), winner)
val g = prog.game
(GameRepo save prog) >>
GameRepo.finish(g.id, winner, winner flatMap (g.player(_).userId)) >>
2014-01-27 06:38:23 -07:00
UserRepo.pair(
2014-01-27 17:33:04 -07:00
g.player(White).userId,
g.player(Black).userId).flatMap {
2014-02-17 02:12:19 -07:00
case (whiteO, blackO) => {
2014-01-27 17:33:04 -07:00
val finish = FinishGame(g, whiteO, blackO)
2014-01-27 06:38:23 -07:00
updateCountAndPerfs(finish) inject {
2014-02-01 00:54:03 -07:00
message foreach { messenger.system(g, _) }
2014-01-27 06:38:23 -07:00
bus.publish(finish, 'finishGame)
prog.events
}
}
2014-04-20 14:26:40 -06:00
} >>- (reminder remind g)
}
2013-12-21 05:14:50 -07:00
2014-04-20 14:26:40 -06:00
private def updateCountAndPerfs(finish: FinishGame): Funit =
(!finish.isVsSelf && !finish.game.aborted) ?? {
(finish.white |@| finish.black).tupled ?? {
case (white, black) =>
crosstableApi add finish.game zip perfsUpdater.save(finish.game, white, black)
} zip
addAiGame(finish) zip
(finish.white ?? incNbGames(finish.game)) zip
(finish.black ?? incNbGames(finish.game)) void
}
2013-12-27 06:25:49 -07:00
2014-07-26 01:50:19 -06:00
private def addAiGame(finish: FinishGame): Funit =
Perfs.variantLens(finish.game.variant) ?? { perfLens =>
~{
import finish._
import lila.rating.Glicko.Result._
for {
level <- game.players.map(_.aiLevel).flatten.headOption
if game.turns > 10
humanColor <- game.players.find(_.isHuman).map(_.color)
user <- humanColor.fold(white, black)
if !user.engine
result = game.winnerColor match {
case Some(c) if c == humanColor => Loss
case Some(_) => Win
case None => Draw
}
} yield aiPerfApi.add(level, perfLens(user.perfs), result)
2014-02-27 17:18:22 -07:00
}
2014-07-26 01:50:19 -06:00
}
2014-02-27 17:18:22 -07:00
2013-12-27 06:25:49 -07:00
private def incNbGames(game: Game)(user: User): Funit = game.finished ?? {
2014-05-08 06:28:36 -06:00
val totalTime = user.playTime.isDefined option game.moveTimes.sum / 10
val tvTime = totalTime ifTrue game.metadata.tvAt.isDefined
2013-12-27 06:25:49 -07:00
UserRepo.incNbGames(user.id, game.rated, game.hasAi,
2014-02-02 17:08:04 -07:00
result = if (game.winnerUserId exists (user.id==)) 1
else if (game.loserUserId exists (user.id==)) -1
2014-05-08 06:28:36 -06:00
else 0,
totalTime = totalTime,
tvTime = tvTime)
2013-12-21 05:14:50 -07:00
}
2013-04-08 13:21:03 -06:00
}