diff --git a/app/controllers/Tournament.scala b/app/controllers/Tournament.scala index 3bb0a55c26..9432d20bb3 100644 --- a/app/controllers/Tournament.scala +++ b/app/controllers/Tournament.scala @@ -57,7 +57,7 @@ object Tournament extends LilaController { env.version(tour.id) zip { ctx.noKid ?? Env.chat.api.userChat.findMine(tour.id, ctx.me).map(some) }).flatMap { - case ((verdicts, version), chat) => env.jsonView(tour, page, ctx.userId, none, version.some) map { + case ((verdicts, version), chat) => env.jsonView(tour, page, ctx.me, none, version.some) map { html.tournament.show(tour, verdicts, _, chat) } }.map { Ok(_) }.mon(_.http.response.tournament.show.website) @@ -69,7 +69,7 @@ object Tournament extends LilaController { 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.userId, playerInfoExt, socketVersion) + env.jsonView(tour, page, ctx.me, playerInfoExt, socketVersion) } map { Ok(_) } }.mon(_.http.response.tournament.show.mobile) } map (_ as JSON) diff --git a/app/views/tournament/side.scala.html b/app/views/tournament/side.scala.html index ed66bde487..a56134f755 100644 --- a/app/views/tournament/side.scala.html +++ b/app/views/tournament/side.scala.html @@ -27,6 +27,9 @@
Condition of entry:
+ } @verdicts.list.map { v =>@v.condition
} diff --git a/modules/tournament/src/main/Condition.scala b/modules/tournament/src/main/Condition.scala index e61f659ccf..fdbf42f949 100644 --- a/modules/tournament/src/main/Condition.scala +++ b/modules/tournament/src/main/Condition.scala @@ -4,7 +4,7 @@ import lila.perfStat.PerfStat import lila.rating.PerfType import lila.user.User -sealed abstract class Condition(val key: String) { +sealed trait Condition { def apply(stats: Condition.GetStats)(user: User): Fu[Condition.Verdict] @@ -26,7 +26,7 @@ object Condition { case class WithVerdict(condition: Condition, verdict: Verdict) - case class NbRatedGame(perf: Option[PerfType], nb: Int) extends Condition("nb") { + case class NbRatedGame(perf: Option[PerfType], nb: Int) extends Condition { def apply(stats: GetStats)(user: User) = fuccess { perf match { @@ -43,7 +43,7 @@ object Condition { } } - case class MaxRating(perf: PerfType, rating: Int) extends Condition("rating") { + case class MaxRating(perf: PerfType, rating: Int) extends Condition { def apply(stats: GetStats)(user: User) = stats(perf) map { s => s.highest match { @@ -109,13 +109,18 @@ object Condition { private implicit val perfTypeWriter: OWrites[PerfType] = OWrites { pt => Json.obj("key" -> pt.key, "name" -> pt.name) } - implicit val NbRatedGameJSONWriter = Json.writes[NbRatedGame] - implicit val MaxRatingJSONWriter = Json.writes[MaxRating] - private implicit val conditionWriter: OWrites[Condition] = OWrites { - case x: NbRatedGame => NbRatedGameJSONWriter writes x - case x: MaxRating => MaxRatingJSONWriter writes x + private implicit val ConditionWriter: Writes[Condition] = Writes { o => + JsString(o.name) + } + private implicit val VerdictWriter: Writes[Verdict] = Writes { + case Refused(reason) => JsString(reason) + case Accepted => JsString("ok") } implicit val AllJSONWriter = Json.writes[All] + implicit val WithVerdictJSONWriter = Json.writes[WithVerdict] + implicit val AllWithVerdictsJSONWriter = Writes[All.WithVerdicts] { o => + Json.obj("list" -> o.list, "accepted" -> o.accepted) + } } object DataForm { diff --git a/modules/tournament/src/main/Env.scala b/modules/tournament/src/main/Env.scala index c8c59d3bd3..2f21ed6010 100644 --- a/modules/tournament/src/main/Env.scala +++ b/modules/tournament/src/main/Env.scala @@ -54,6 +54,8 @@ final class Env( createdTtl = CreatedCacheTtl, rankingTtl = RankingCacheTtl) + lazy val verify = new Condition.Verify(getStats) + lazy val api = new TournamentApi( cached = cached, scheduleJsonView = scheduleJsonView, @@ -67,7 +69,7 @@ final class Env( site = hub.socket.site, lobby = hub.socket.lobby, trophyApi = trophyApi, - verify = new Condition.Verify(getStats), + verify = verify, indexLeaderboard = leaderboardIndexer.indexOne _, roundMap = roundMap, roundSocketHub = roundSocketHub) @@ -88,7 +90,7 @@ final class Env( mongoCache = mongoCache, ttl = LeaderboardCacheTtl) - lazy val jsonView = new JsonView(lightUser, cached, performance) + lazy val jsonView = new JsonView(lightUser, cached, performance, verify) lazy val scheduleJsonView = new ScheduleJsonView(lightUser) diff --git a/modules/tournament/src/main/JsonView.scala b/modules/tournament/src/main/JsonView.scala index d29810b78a..19dc34dbe3 100644 --- a/modules/tournament/src/main/JsonView.scala +++ b/modules/tournament/src/main/JsonView.scala @@ -13,7 +13,8 @@ import lila.user.User final class JsonView( getLightUser: String => Option[LightUser], cached: Cached, - performance: Performance) { + performance: Performance, + verify: Condition.Verify) { import JsonView._ import Condition.JSONHandlers._ @@ -26,11 +27,11 @@ final class JsonView( def apply( tour: Tournament, page: Option[Int], - me: Option[String], + me: Option[User], playerInfoExt: Option[PlayerInfoExt], socketVersion: Option[Int]): Fu[JsObject] = for { data <- cachableData(tour.id) - myInfo <- me ?? { PlayerRepo.playerInfo(tour.id, _) } + myInfo <- me ?? { u => PlayerRepo.playerInfo(tour.id, u.id) } stand <- (myInfo, page) match { case (_, Some(p)) => standing(tour, p) case (Some(i), _) => standing(tour, i.page) @@ -39,6 +40,11 @@ final class JsonView( playerInfoJson <- playerInfoExt ?? { pie => playerInfo(pie).map(_.some) } + verdicts <- me match { + case None => fuccess(tour.conditions.accepted) + case Some(user) if myInfo.isDefined => fuccess(tour.conditions.accepted) + case Some(user) => verify(tour.conditions, user) + } } yield Json.obj( "id" -> tour.id, "createdBy" -> tour.createdBy, @@ -57,7 +63,7 @@ final class JsonView( "clock" -> clockJson(tour.clock), "position" -> tour.position.some.filterNot(_.initial).map(positionJson), "private" -> tour.`private`.option(true), - "conditions" -> tour.conditions.ifNonEmpty, + "verdicts" -> verdicts, "variant" -> tour.variant.key, "isStarted" -> tour.isStarted, "isFinished" -> tour.isFinished, diff --git a/modules/tournament/src/main/PlayerRepo.scala b/modules/tournament/src/main/PlayerRepo.scala index 52e4ad3aa1..380b8b5314 100644 --- a/modules/tournament/src/main/PlayerRepo.scala +++ b/modules/tournament/src/main/PlayerRepo.scala @@ -14,15 +14,15 @@ object PlayerRepo { private lazy val coll = Env.current.playerColl - private def selectId(id: String) = BSONDocument("_id" -> id) - private def selectTour(tourId: String) = BSONDocument("tid" -> tourId) - private def selectUser(userId: String) = BSONDocument("uid" -> userId) - private def selectTourUser(tourId: String, userId: String) = BSONDocument( + private def selectId(id: String) = $doc("_id" -> id) + private def selectTour(tourId: String) = $doc("tid" -> tourId) + private def selectUser(userId: String) = $doc("uid" -> userId) + private def selectTourUser(tourId: String, userId: String) = $doc( "tid" -> tourId, "uid" -> userId) - private val selectActive = BSONDocument("w" -> BSONDocument("$ne" -> true)) - private val selectWithdraw = BSONDocument("w" -> true) - private val bestSort = BSONDocument("m" -> -1) + private val selectActive = $doc("w" $ne true) + private val selectWithdraw = $doc("w" -> true) + private val bestSort = $doc("m" -> -1) def byId(id: String): Fu[Option[Player]] = coll.uno[Player](selectId(id)) @@ -59,7 +59,7 @@ object PlayerRepo { def unWithdraw(tourId: String) = coll.update( selectTour(tourId) ++ selectWithdraw, - BSONDocument("$unset" -> BSONDocument("w" -> true)), + $doc("$unset" -> $doc("w" -> true)), multi = true).void def find(tourId: String, userId: String): Fu[Option[Player]] = @@ -72,8 +72,8 @@ object PlayerRepo { def playerInfo(tourId: String, userId: String): Fu[Option[PlayerInfo]] = find(tourId, userId) flatMap { _ ?? { player => - coll.count(Some(selectTour(tourId) ++ BSONDocument( - "m" -> BSONDocument("$gt" -> player.magicScore)) + coll.count(Some(selectTour(tourId) ++ $doc( + "m" -> $doc("$gt" -> player.magicScore)) )) map { n => PlayerInfo((n + 1), player.withdraw).some } @@ -82,21 +82,21 @@ object PlayerRepo { def join(tourId: String, user: User, perfLens: Perfs => Perf) = find(tourId, user.id) flatMap { - case Some(p) if p.withdraw => coll.update(selectId(p._id), BSONDocument("$unset" -> BSONDocument("w" -> true))) + case Some(p) if p.withdraw => coll.update(selectId(p._id), $doc("$unset" -> $doc("w" -> true))) case Some(p) => funit case None => coll.insert(Player.make(tourId, user, perfLens)) } void def withdraw(tourId: String, userId: String) = coll.update( selectTourUser(tourId, userId), - BSONDocument("$set" -> BSONDocument("w" -> true))).void + $doc("$set" -> $doc("w" -> true))).void def withPoints(tourId: String): Fu[List[Player]] = coll.find( - selectTour(tourId) ++ BSONDocument("m" -> BSONDocument("$gt" -> 0)) + selectTour(tourId) ++ $doc("m" -> $doc("$gt" -> 0)) ).cursor[Player]().gather[List]() - private def aggregationUserIdList(res: Stream[BSONDocument]): List[String] = + private def aggregationUserIdList(res: Stream[Bdoc]): List[String] = res.headOption flatMap { _.getAs[List[String]]("uids") } getOrElse Nil import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework.{ Descending, Group, Match, Push, Sort } @@ -145,7 +145,7 @@ object PlayerRepo { } def setPerformance(player: Player, performance: Int) = - coll.update(selectId(player.id), BSONDocument("$set" -> BSONDocument("e" -> performance))).void + coll.update(selectId(player.id), $doc("$set" -> $doc("e" -> performance))).void private def rankPlayers(players: List[Player], ranking: Ranking): RankedPlayers = players.flatMap { p => diff --git a/ui/tournament/src/ctrl.js b/ui/tournament/src/ctrl.js index 0ab566aa56..0b4e75db5a 100644 --- a/ui/tournament/src/ctrl.js +++ b/ui/tournament/src/ctrl.js @@ -74,6 +74,10 @@ module.exports = function(env) { }.bind(this); this.join = function() { + if (!this.data.verdicts.accepted) + return this.data.verdicts.list.forEach(function(v) { + if (v.verdict !== 'ok') alert(v.verdict); + }); xhr.join(this); this.vm.joinSpinner = true; this.vm.focusOnMe = true;