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._
|
2015-01-11 07:23:25 -07:00
|
|
|
import chess.{ Status, Color, Speed }
|
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
|
|
|
|
2013-05-17 19:03:53 -06:00
|
|
|
private[round] final class Finisher(
|
2013-04-08 13:21:03 -06:00
|
|
|
messenger: Messenger,
|
2014-01-13 15:51:49 -07:00
|
|
|
perfsUpdater: PerfsUpdater,
|
2014-02-27 17:18:22 -07:00
|
|
|
aiPerfApi: lila.ai.AiPerfApi,
|
2014-03-16 14:57:15 -06:00
|
|
|
crosstableApi: lila.game.CrosstableApi,
|
2014-07-27 04:07:13 -06:00
|
|
|
bus: lila.common.Bus,
|
2015-03-17 15:54:14 -06:00
|
|
|
timeline: akka.actor.ActorSelection,
|
2014-07-27 04:07:13 -06:00
|
|
|
casualOnly: Boolean) {
|
2013-04-08 13:21:03 -06:00
|
|
|
|
2013-05-17 19:03:53 -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,
|
2013-12-29 04:38:07 -07:00
|
|
|
message: Option[SelectI18nKey] = None): Fu[Events] = {
|
|
|
|
val prog = game.finish(status(Status), winner)
|
2015-03-17 15:54:14 -06:00
|
|
|
if (game.nonAi && game.isCorrespondence)
|
|
|
|
Color.all foreach notifyTimeline(prog.game)
|
2014-07-27 04:07:13 -06:00
|
|
|
casualOnly.fold(
|
|
|
|
GameRepo unrate prog.game.id inject prog.game.copy(mode = chess.Mode.Casual),
|
|
|
|
fuccess(prog.game)
|
|
|
|
) flatMap { g =>
|
|
|
|
(GameRepo save prog) >>
|
|
|
|
GameRepo.finish(g.id, winner, winner flatMap (g.player(_).userId)) >>
|
|
|
|
UserRepo.pair(
|
|
|
|
g.whitePlayer.userId,
|
|
|
|
g.blackPlayer.userId).flatMap {
|
|
|
|
case (whiteO, blackO) => {
|
|
|
|
val finish = FinishGame(g, whiteO, blackO)
|
|
|
|
updateCountAndPerfs(finish) inject {
|
|
|
|
message foreach { messenger.system(g, _) }
|
|
|
|
bus.publish(finish, 'finishGame)
|
|
|
|
prog.events
|
|
|
|
}
|
|
|
|
}
|
2014-12-02 10:42:33 -07:00
|
|
|
}
|
2014-07-27 04:07:13 -06:00
|
|
|
}
|
2013-12-29 04:38:07 -07:00
|
|
|
}
|
2013-12-21 05:14:50 -07:00
|
|
|
|
2015-03-17 15:54:14 -06:00
|
|
|
private def notifyTimeline(game: Game)(color: Color) = {
|
|
|
|
import lila.hub.actorApi.timeline.{ Propagate, GameEnd }
|
2015-04-19 12:23:58 -06:00
|
|
|
if (!game.aborted) {
|
|
|
|
game.player(color).userId foreach { userId =>
|
|
|
|
timeline ! (Propagate(GameEnd(
|
|
|
|
playerId = game fullIdOf color,
|
|
|
|
opponent = game.player(!color).userId,
|
|
|
|
win = game.winnerColor map (color ==),
|
|
|
|
perf = game.perfKey)) toUser userId)
|
|
|
|
}
|
2015-03-17 15:54:14 -06: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)
|
2015-02-28 03:04:39 -07:00
|
|
|
if !user.lame
|
2014-07-26 01:50:19 -06:00
|
|
|
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
|
|
|
}
|