2013-05-07 17:44:26 -06:00
|
|
|
package controllers
|
|
|
|
|
2015-01-04 08:43:17 -07:00
|
|
|
import play.api.libs.json._
|
2013-07-30 15:02:12 -06:00
|
|
|
import play.api.mvc._
|
|
|
|
|
2013-12-29 02:51:40 -07:00
|
|
|
import lila.api.Context
|
2013-07-30 15:02:12 -06:00
|
|
|
import lila.app._
|
2015-01-18 10:40:22 -07:00
|
|
|
import lila.common.HTTPRequest
|
2015-01-22 06:39:17 -07:00
|
|
|
import lila.game.{ Pov, GameRepo }
|
2017-01-15 05:26:08 -07:00
|
|
|
import lila.tournament.{ System, TournamentRepo, PairingRepo }
|
2013-12-29 02:51:40 -07:00
|
|
|
import views._
|
2013-05-07 17:44:26 -06:00
|
|
|
|
|
|
|
object Tournament extends LilaController {
|
|
|
|
|
2013-05-12 09:02:45 -06:00
|
|
|
private def env = Env.tournament
|
|
|
|
private def repo = TournamentRepo
|
|
|
|
|
2013-05-12 16:48:48 -06:00
|
|
|
private def tournamentNotFound(implicit ctx: Context) = NotFound(html.tournament.notFound())
|
|
|
|
|
2016-01-10 16:19:36 -07:00
|
|
|
def home(page: Int) = Open { implicit ctx =>
|
2016-01-25 19:59:18 -07:00
|
|
|
negotiate(
|
2016-03-04 05:37:28 -07:00
|
|
|
html = Reasonable(page, 20) {
|
2016-01-25 19:59:18 -07:00
|
|
|
val finishedPaginator = repo.finishedPaginator(maxPerPage = 30, page = page)
|
2017-01-26 05:19:27 -07:00
|
|
|
if (HTTPRequest isXhr ctx.req) for {
|
|
|
|
pag <- finishedPaginator
|
|
|
|
_ <- Env.user.lightUserApi preloadMany pag.currentPageResults.flatMap(_.winnerId)
|
|
|
|
} yield Ok(html.tournament.finishedPaginator(pag))
|
|
|
|
else for {
|
|
|
|
visible <- env.api.fetchVisibleTournaments
|
|
|
|
scheduled <- repo.scheduledDedup
|
|
|
|
finished <- finishedPaginator
|
|
|
|
winners <- env.winners.all
|
|
|
|
_ <- Env.user.lightUserApi preloadMany {
|
|
|
|
finished.currentPageResults.flatMap(_.winnerId).toList :::
|
|
|
|
scheduled.flatMap(_.winnerId) ::: winners.userIds
|
|
|
|
}
|
2017-01-30 04:37:06 -07:00
|
|
|
scheduleJson <- env scheduleJsonView visible
|
2017-01-26 05:19:27 -07:00
|
|
|
} yield NoCache {
|
2017-01-30 04:37:06 -07:00
|
|
|
Ok(html.tournament.home(scheduled, finished, winners, scheduleJson))
|
2016-01-25 19:59:18 -07:00
|
|
|
}
|
|
|
|
},
|
2017-01-30 04:37:06 -07:00
|
|
|
api = _ => for {
|
|
|
|
visible <- env.api.fetchVisibleTournaments
|
|
|
|
scheduleJson <- env scheduleJsonView visible
|
|
|
|
} yield Ok(scheduleJson)
|
2016-01-25 19:59:18 -07:00
|
|
|
)
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
|
2014-07-23 15:08:59 -06:00
|
|
|
def help(sysStr: Option[String]) = Open { implicit ctx =>
|
|
|
|
val system = sysStr flatMap {
|
|
|
|
case "arena" => System.Arena.some
|
2017-02-14 08:34:07 -07:00
|
|
|
case _ => none
|
2014-07-23 15:08:59 -06:00
|
|
|
}
|
|
|
|
Ok(html.tournament.faqPage(system)).fuccess
|
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
|
2016-10-17 08:17:55 -06:00
|
|
|
def leaderboard = Open { implicit ctx =>
|
2017-01-26 05:19:27 -07:00
|
|
|
for {
|
|
|
|
winners <- env.winners.all
|
|
|
|
_ <- Env.user.lightUserApi preloadMany winners.userIds
|
|
|
|
} yield Ok(html.tournament.leaderboard(winners))
|
2016-10-17 08:17:55 -06:00
|
|
|
}
|
|
|
|
|
2014-02-17 02:12:19 -07:00
|
|
|
def show(id: String) = Open { implicit ctx =>
|
2015-06-14 05:23:40 -06:00
|
|
|
val page = getInt("page")
|
2015-06-14 04:27:43 -06:00
|
|
|
negotiate(
|
|
|
|
html = repo byId id flatMap {
|
2017-01-09 01:44:13 -07:00
|
|
|
_.fold(tournamentNotFound.fuccess) { tour =>
|
2017-01-26 05:19:27 -07:00
|
|
|
(for {
|
|
|
|
verdicts <- env.api.verdicts(tour, ctx.me)
|
|
|
|
version <- env.version(tour.id)
|
|
|
|
chat <- ctx.noKid ?? Env.chat.api.userChat.findMine(tour.id, ctx.me).map(some)
|
|
|
|
json <- env.jsonView(tour, page, ctx.me, none, version.some)
|
|
|
|
_ <- chat ?? { c => Env.user.lightUserApi.preloadMany(c.chat.userIds) }
|
|
|
|
} yield Ok(html.tournament.show(tour, verdicts, json, chat))).mon(_.http.response.tournament.show.website)
|
2017-01-09 01:44:13 -07:00
|
|
|
}
|
|
|
|
},
|
2015-06-14 04:27:43 -06:00
|
|
|
api = _ => repo byId id flatMap {
|
2017-01-09 01:44:13 -07:00
|
|
|
case None => NotFound(jsonError("No such tournament")).fuccess
|
|
|
|
case Some(tour) => {
|
|
|
|
get("playerInfo").?? { env.api.playerInfo(tour.id, _) } zip
|
|
|
|
getBool("socketVersion").??(env version tour.id map some) flatMap {
|
|
|
|
case (playerInfoExt, socketVersion) =>
|
|
|
|
env.jsonView(tour, page, ctx.me, playerInfoExt, socketVersion)
|
|
|
|
} map { Ok(_) }
|
|
|
|
}.mon(_.http.response.tournament.show.mobile)
|
|
|
|
} map (_ as JSON)
|
2015-06-19 09:36:31 -06:00
|
|
|
) map NoCache
|
2015-06-13 14:34:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
def standing(id: String, page: Int) = Open { implicit ctx =>
|
|
|
|
OptionFuResult(repo byId id) { tour =>
|
|
|
|
env.jsonView.standing(tour, page) map { data =>
|
|
|
|
Ok(data) as JSON
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-13 14:52:04 -06:00
|
|
|
def gameStanding(id: String) = Open { implicit ctx =>
|
2015-06-11 16:54:51 -06:00
|
|
|
env.api.miniStanding(id, true) map {
|
|
|
|
case Some(m) if !m.tour.isCreated => Ok(html.tournament.gameStanding(m))
|
2017-02-14 08:34:07 -07:00
|
|
|
case _ => NotFound
|
2015-05-13 14:52:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-18 18:05:26 -06:00
|
|
|
def userGameNbMini(id: String, user: String, nb: Int) = Open { implicit ctx =>
|
|
|
|
withUserGameNb(id, user, nb) { pov =>
|
2015-08-25 06:23:49 -06:00
|
|
|
Ok(html.tournament.miniGame(pov))
|
2015-08-18 18:05:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def userGameNbShow(id: String, user: String, nb: Int) = Open { implicit ctx =>
|
|
|
|
withUserGameNb(id, user, nb) { pov =>
|
|
|
|
Redirect(routes.Round.watcher(pov.game.id, pov.color.name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private def withUserGameNb(id: String, user: String, nb: Int)(withPov: Pov => Result)(implicit ctx: Context): Fu[Result] = {
|
|
|
|
val userId = lila.user.User normalize user
|
|
|
|
OptionFuResult(PairingRepo.byTourUserNb(id, userId, nb)) { pairing =>
|
|
|
|
GameRepo game pairing.id map {
|
2015-10-02 13:31:25 -06:00
|
|
|
_.flatMap { Pov.ofUserId(_, userId) }.fold(Redirect(routes.Tournament show id))(withPov)
|
2015-08-18 18:05:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-02 16:29:56 -06:00
|
|
|
def player(id: String, userId: String) = Open { implicit ctx =>
|
2015-10-07 09:05:39 -06:00
|
|
|
JsonOk {
|
|
|
|
env.api.playerInfo(id, userId) flatMap {
|
2015-10-05 06:40:42 -06:00
|
|
|
_ ?? env.jsonView.playerInfo
|
2015-10-02 14:52:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def join(id: String) = AuthBody(BodyParsers.parse.json) { implicit ctx => implicit me =>
|
|
|
|
NoLame {
|
|
|
|
val password = ctx.body.body.\("p").asOpt[String]
|
|
|
|
negotiate(
|
|
|
|
html = repo enterableById id map {
|
|
|
|
case None => tournamentNotFound
|
|
|
|
case Some(tour) =>
|
|
|
|
env.api.join(tour.id, me, password)
|
|
|
|
Redirect(routes.Tournament.show(tour.id))
|
|
|
|
},
|
|
|
|
api = _ => OptionFuResult(repo enterableById id) { tour =>
|
|
|
|
env.api.joinWithResult(tour.id, me, password) map { result =>
|
|
|
|
if (result) Ok(jsonOkBody)
|
|
|
|
else BadRequest(Json.obj("joined" -> false))
|
|
|
|
}
|
2017-02-14 08:34:07 -07:00
|
|
|
}
|
|
|
|
)
|
2017-01-09 01:44:13 -07:00
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def withdraw(id: String) = Auth { implicit ctx => me =>
|
|
|
|
OptionResult(repo byId id) { tour =>
|
|
|
|
env.api.withdraw(tour.id, me.id)
|
|
|
|
if (HTTPRequest.isXhr(ctx.req)) Ok(Json.obj("ok" -> true)) as JSON
|
|
|
|
else Redirect(routes.Tournament.show(tour.id))
|
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def terminate(id: String) = Secure(_.TerminateTournament) { implicit ctx => me =>
|
|
|
|
OptionResult(repo startedById id) { tour =>
|
|
|
|
env.api finish tour
|
|
|
|
Env.mod.logApi.terminateTournament(me.id, tour.fullName)
|
|
|
|
Redirect(routes.Tournament show tour.id)
|
|
|
|
}
|
2016-01-21 01:18:22 -07:00
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def form = Auth { implicit ctx => me =>
|
|
|
|
NoLame {
|
|
|
|
Ok(html.tournament.form(env.forms.create, env.forms)).fuccess
|
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def create = AuthBody { implicit ctx => implicit me =>
|
|
|
|
NoLame {
|
|
|
|
import play.api.i18n.Messages.Implicits._
|
|
|
|
import play.api.Play.current
|
|
|
|
implicit val req = ctx.body
|
|
|
|
negotiate(
|
|
|
|
html = env.forms.create.bindFromRequest.fold(
|
|
|
|
err => BadRequest(html.tournament.form(err, env.forms)).fuccess,
|
|
|
|
setup => env.api.createTournament(setup, me) map { tour =>
|
|
|
|
Redirect(routes.Tournament.show(tour.id))
|
2017-02-14 08:34:07 -07:00
|
|
|
}
|
|
|
|
),
|
2017-01-09 01:44:13 -07:00
|
|
|
api = _ => env.forms.create.bindFromRequest.fold(
|
|
|
|
err => BadRequest(errorsAsJson(err)).fuccess,
|
|
|
|
setup => env.api.createTournament(setup, me) map { tour =>
|
|
|
|
Ok(Json.obj("id" -> tour.id))
|
2017-02-14 08:34:07 -07:00
|
|
|
}
|
|
|
|
)
|
2017-01-09 01:44:13 -07:00
|
|
|
)
|
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
|
|
|
|
2017-01-09 01:44:13 -07:00
|
|
|
def limitedInvitation = Auth { implicit ctx => me =>
|
|
|
|
env.api.fetchVisibleTournaments.flatMap { tours =>
|
|
|
|
lila.tournament.TournamentInviter.findNextFor(me, tours, env.verify.canEnter(me))
|
|
|
|
} map {
|
2017-02-14 08:34:07 -07:00
|
|
|
case None => Redirect(routes.Tournament.home(1))
|
2017-01-09 01:44:13 -07:00
|
|
|
case Some(t) => Redirect(routes.Tournament.show(t.id))
|
|
|
|
}
|
2016-06-19 15:54:42 -06:00
|
|
|
}
|
|
|
|
|
2015-01-22 06:39:17 -07:00
|
|
|
def websocket(id: String, apiVersion: Int) = SocketOption[JsValue] { implicit ctx =>
|
2017-02-01 07:31:22 -07:00
|
|
|
getSocketUid("sri") ?? { uid =>
|
2016-02-01 07:56:35 -07:00
|
|
|
env.socketHandler.join(id, uid, ctx.me)
|
2015-01-22 06:39:17 -07:00
|
|
|
}
|
2013-05-12 09:02:45 -06:00
|
|
|
}
|
2013-05-07 17:44:26 -06:00
|
|
|
}
|