2013-03-25 11:52:18 -06:00
|
|
|
package controllers
|
|
|
|
|
2013-05-31 09:55:11 -06:00
|
|
|
import akka.pattern.ask
|
|
|
|
import play.api.libs.iteratee._
|
|
|
|
import play.api.libs.json._
|
|
|
|
import play.api.mvc._
|
2014-06-01 15:22:17 -06:00
|
|
|
import play.twirl.api.Html
|
2013-05-31 09:55:11 -06:00
|
|
|
|
2013-12-27 15:12:20 -07:00
|
|
|
import lila.api.Context
|
2013-05-07 17:44:26 -06:00
|
|
|
import lila.app._
|
2014-02-17 02:12:19 -07:00
|
|
|
import lila.game.{ Pov, PlayerRef, GameRepo, Game => GameModel }
|
2013-05-29 09:46:21 -06:00
|
|
|
import lila.hub.actorApi.map.Tell
|
2013-05-31 09:55:11 -06:00
|
|
|
import lila.round.actorApi.round._
|
2014-02-17 02:12:19 -07:00
|
|
|
import lila.tournament.{ TournamentRepo, Tournament => Tourney }
|
2014-08-15 05:44:32 -06:00
|
|
|
import lila.user.{ User => UserModel, UserRepo }
|
2013-05-18 09:26:37 -06:00
|
|
|
import makeTimeout.large
|
2013-05-31 09:55:11 -06:00
|
|
|
import views._
|
2013-03-25 11:52:18 -06:00
|
|
|
|
2013-08-02 03:27:28 -06:00
|
|
|
object Round extends LilaController with TheftPrevention {
|
2013-03-25 11:52:18 -06:00
|
|
|
|
2013-05-07 17:44:26 -06:00
|
|
|
private def env = Env.round
|
|
|
|
private def bookmarkApi = Env.bookmark.api
|
|
|
|
private def analyser = Env.analyse.analyser
|
2013-03-25 11:52:18 -06:00
|
|
|
|
2014-02-17 02:12:19 -07:00
|
|
|
def websocketWatcher(gameId: String, color: String) = Socket[JsValue] { implicit ctx =>
|
2013-05-17 18:09:35 -06:00
|
|
|
(get("sri") |@| getInt("version")).tupled ?? {
|
2014-08-15 05:44:32 -06:00
|
|
|
case (uid, version) => env.socketHandler.watcher(
|
|
|
|
gameId = gameId,
|
|
|
|
colorName = color,
|
|
|
|
version = version,
|
|
|
|
uid = uid,
|
|
|
|
user = ctx.me,
|
|
|
|
ip = ctx.ip,
|
|
|
|
userTv = get("userTv"))
|
2013-05-07 17:44:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-11 15:26:11 -06:00
|
|
|
def websocketPlayer(fullId: String, apiVersion: Int) = Socket[JsValue] { implicit ctx =>
|
2014-07-13 08:49:11 -06:00
|
|
|
GameRepo pov fullId flatMap {
|
2014-07-30 03:08:18 -06:00
|
|
|
_ ?? { pov =>
|
2014-07-13 08:49:11 -06:00
|
|
|
(get("sri") |@| getInt("version")).tupled ?? {
|
|
|
|
case (uid, version) => env.socketHandler.player(pov, version, uid, ~get("ran"), ctx.me, ctx.ip)
|
|
|
|
}
|
|
|
|
}
|
2013-05-07 17:44:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-17 02:12:19 -07:00
|
|
|
def player(fullId: String) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(GameRepo pov fullId) { pov =>
|
2014-05-11 14:28:56 -06:00
|
|
|
negotiate(
|
2014-11-03 13:45:35 -07:00
|
|
|
html = {
|
|
|
|
if (pov.game.playableByAi) env.roundMap ! Tell(pov.game.id, AiPlay)
|
|
|
|
pov.game.started.fold(
|
|
|
|
PreventTheft(pov) {
|
|
|
|
(pov.game.tournamentId ?? TournamentRepo.byId) zip
|
2014-12-02 17:34:34 -07:00
|
|
|
Env.game.crosstableApi(pov.game) zip
|
2014-12-21 03:21:35 -07:00
|
|
|
otherPovs(pov.gameId) flatMap {
|
2014-12-20 08:18:51 -07:00
|
|
|
case ((tour, crosstable), playing) =>
|
2014-11-03 13:45:35 -07:00
|
|
|
Env.api.roundApi.player(pov, Env.api.version) map { data =>
|
2014-12-20 08:18:51 -07:00
|
|
|
Ok(html.round.player(pov, data, tour = tour, cross = crosstable, playing = playing))
|
2014-11-03 13:45:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Redirect(routes.Setup.await(fullId)).fuccess
|
|
|
|
)
|
|
|
|
},
|
2014-10-03 14:13:59 -06:00
|
|
|
api = apiVersion => Env.api.roundApi.player(pov, apiVersion) map { Ok(_) }
|
2014-01-28 02:57:59 -07:00
|
|
|
)
|
2013-05-07 17:44:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-21 03:21:35 -07:00
|
|
|
private def otherPovs(gameId: String)(implicit ctx: Context) = ctx.me ?? { user =>
|
2014-12-02 17:34:34 -07:00
|
|
|
GameRepo nowPlaying user map {
|
2014-12-22 06:55:20 -07:00
|
|
|
_ filter { _.game.id != gameId }
|
2014-12-02 17:34:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 12:07:31 -07:00
|
|
|
private def getNext(currentGame: GameModel)(povs: List[Pov])(implicit ctx: Context) =
|
|
|
|
povs find { pov =>
|
|
|
|
pov.isMyTurn && (pov.game.hasClock || !currentGame.hasClock)
|
|
|
|
} map (_.fullId)
|
|
|
|
|
|
|
|
def others(gameId: String) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(GameRepo game gameId) { currentGame =>
|
|
|
|
otherPovs(gameId) map { povs =>
|
|
|
|
Ok(html.round.others(povs, nextId = getNext(currentGame)(povs)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-22 10:12:29 -07:00
|
|
|
def next(gameId: String) = Open { implicit ctx =>
|
2014-12-23 10:32:34 -07:00
|
|
|
OptionFuResult(GameRepo game gameId) { currentGame =>
|
2014-12-23 12:07:31 -07:00
|
|
|
otherPovs(gameId) map getNext(currentGame) map { nextId =>
|
|
|
|
Ok(Json.obj("next" -> nextId))
|
2014-12-23 10:32:34 -07:00
|
|
|
}
|
2014-12-22 10:12:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-17 02:12:19 -07:00
|
|
|
def watcher(gameId: String, color: String) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(GameRepo.pov(gameId, color)) { pov =>
|
2014-10-19 03:25:32 -06:00
|
|
|
watch(pov)
|
2013-05-07 17:44:26 -06:00
|
|
|
}
|
2014-01-28 02:57:59 -07:00
|
|
|
}
|
2013-05-07 17:44:26 -06:00
|
|
|
|
2014-10-19 03:25:32 -06:00
|
|
|
def watch(pov: Pov, userTv: Option[UserModel] = None)(implicit ctx: Context): Fu[Result] =
|
|
|
|
negotiate(
|
2014-12-26 14:29:53 -07:00
|
|
|
html = if (pov.game.replayable) Analyse.replay(pov, userTv = userTv)
|
2014-10-19 03:25:32 -06:00
|
|
|
else if (pov.game.joinable) join(pov)
|
|
|
|
else ctx.userId.flatMap(pov.game.playerByUserId).ifTrue(pov.game.playable) match {
|
|
|
|
case Some(player) => fuccess(Redirect(routes.Round.player(pov.game fullIdOf player.color)))
|
|
|
|
case None =>
|
|
|
|
(pov.game.tournamentId ?? TournamentRepo.byId) zip
|
|
|
|
Env.game.crosstableApi(pov.game) zip
|
2014-10-23 03:11:10 -06:00
|
|
|
Env.api.roundApi.watcher(pov, Env.api.version, tv = none) map {
|
2014-10-19 03:25:32 -06:00
|
|
|
case ((tour, crosstable), data) =>
|
|
|
|
Ok(html.round.watcher(pov, data, tour, crosstable, userTv = userTv))
|
|
|
|
}
|
|
|
|
},
|
2014-10-20 03:11:22 -06:00
|
|
|
api = apiVersion => Env.api.roundApi.watcher(pov, apiVersion, tv = none) map { Ok(_) }
|
2014-10-19 03:25:32 -06:00
|
|
|
)
|
2013-08-02 03:27:28 -06:00
|
|
|
|
2014-06-01 17:01:39 -06:00
|
|
|
private def join(pov: Pov)(implicit ctx: Context): Fu[Result] =
|
2013-12-25 12:49:08 -07:00
|
|
|
GameRepo initialFen pov.gameId zip
|
2014-10-17 15:24:53 -06:00
|
|
|
Env.api.roundApi.player(pov, Env.api.version) zip
|
2013-12-25 12:49:08 -07:00
|
|
|
((pov.player.userId orElse pov.opponent.userId) ?? UserRepo.byId) map {
|
2014-10-17 15:24:53 -06:00
|
|
|
case ((fen, data), opponent) => Ok(html.setup.join(
|
|
|
|
pov, data, opponent, Env.setup.friendConfigMemo get pov.game.id, fen))
|
2013-12-25 12:49:08 -07:00
|
|
|
}
|
2013-05-07 17:44:26 -06:00
|
|
|
|
2014-06-10 17:00:47 -06:00
|
|
|
def playerText(fullId: String) = Open { implicit ctx =>
|
2014-06-05 04:07:41 -06:00
|
|
|
OptionResult(GameRepo pov fullId) { pov =>
|
2014-06-10 16:51:59 -06:00
|
|
|
if (ctx.blindMode) Ok(html.game.textualRepresentation(pov, true))
|
2014-06-05 04:07:41 -06:00
|
|
|
else BadRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-10 17:00:47 -06:00
|
|
|
def watcherText(gameId: String, color: String) = Open { implicit ctx =>
|
|
|
|
OptionResult(GameRepo.pov(gameId, color)) { pov =>
|
|
|
|
if (ctx.blindMode) Ok(html.game.textualRepresentation(pov, false))
|
|
|
|
else BadRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-12 16:17:24 -06:00
|
|
|
def sideWatcher(gameId: String, color: String) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(GameRepo.pov(gameId, color)) { side(_, false) }
|
2013-12-24 03:47:52 -07:00
|
|
|
}
|
|
|
|
|
2014-10-12 16:17:24 -06:00
|
|
|
def sidePlayer(fullId: String) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(GameRepo pov fullId) { side(_, true) }
|
2013-12-24 03:47:52 -07:00
|
|
|
}
|
|
|
|
|
2014-12-07 04:32:18 -07:00
|
|
|
def writeNote(gameId: String) = AuthBody { implicit ctx =>
|
|
|
|
me =>
|
|
|
|
import play.api.data.Forms._
|
|
|
|
import play.api.data._
|
|
|
|
implicit val req = ctx.body
|
|
|
|
Form(single("text" -> text)).bindFromRequest.fold(
|
|
|
|
err => fuccess(BadRequest),
|
2014-12-09 11:07:16 -07:00
|
|
|
text => Env.round.noteApi.set(gameId, me.id, text.trim take 10000))
|
2014-12-07 04:01:56 -07:00
|
|
|
}
|
|
|
|
|
2014-10-12 16:17:24 -06:00
|
|
|
private def side(pov: Pov, isPlayer: Boolean)(implicit ctx: Context) =
|
2014-10-03 13:08:19 -06:00
|
|
|
pov.game.tournamentId ?? TournamentRepo.byId map { tour =>
|
2014-10-12 16:17:24 -06:00
|
|
|
Ok(html.game.side(pov, tour, withTourStanding = isPlayer))
|
2014-10-03 13:08:19 -06:00
|
|
|
}
|
2013-05-31 09:55:11 -06:00
|
|
|
|
2014-02-17 02:12:19 -07:00
|
|
|
def continue(id: String, mode: String) = Open { implicit ctx =>
|
|
|
|
OptionResult(GameRepo game id) { game =>
|
2013-05-31 09:55:11 -06:00
|
|
|
Redirect("%s?fen=%s#%s".format(
|
|
|
|
routes.Lobby.home(),
|
2013-05-31 12:19:59 -06:00
|
|
|
get("fen") | (chess.format.Forsyth >> game.toChess),
|
2013-05-31 09:55:11 -06:00
|
|
|
mode))
|
|
|
|
}
|
|
|
|
}
|
2013-03-25 11:52:18 -06:00
|
|
|
}
|