show verified tournament conditions

This commit is contained in:
Thibault Duplessis 2016-06-18 12:32:55 +02:00
parent bd00885abd
commit 46127c6d3d
6 changed files with 71 additions and 21 deletions

View file

@ -53,13 +53,14 @@ object Tournament extends LilaController {
negotiate(
html = repo byId id flatMap {
_.fold(tournamentNotFound.fuccess) { tour =>
env.version(tour.id).zip {
ctx.noKid ?? Env.chat.api.userChat.findMine(tour.id, ctx.me).map(some)
}.flatMap {
case (version, chat) => env.jsonView(tour, page, ctx.userId, none, version.some) map {
html.tournament.show(tour, _, chat)
}
}.map { Ok(_) }.mon(_.http.response.tournament.show.website)
(env.api.verdicts(tour, ctx.me) zip
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 {
html.tournament.show(tour, verdicts, _, chat)
}
}.map { Ok(_) }.mon(_.http.response.tournament.show.website)
}
},
api = _ => repo byId id flatMap {

View file

@ -1,4 +1,4 @@
@(tour: Tournament, data: play.api.libs.json.JsObject, chatOption: Option[lila.chat.UserChat.Mine])(implicit ctx: Context)
@(tour: Tournament, verdicts: lila.tournament.Condition.All.WithVerdicts, data: play.api.libs.json.JsObject, chatOption: Option[lila.chat.UserChat.Mine])(implicit ctx: Context)
@underchat = {
<div class="watchers none" data-icon="v">
@ -23,7 +23,7 @@ chat.ChatJsData.json(c.chat, name = trans.chatRoom.str(), timeout = c.timeout)
@tournament.layout(
title = s"${tour.fullName} #${tour.id}",
side = tournament.side(tour).some,
side = tournament.side(tour, verdicts).some,
chat = chat.dom().some,
underchat = underchat.some,
moreJs = moreJs,

View file

@ -1,4 +1,4 @@
@(tour: Tournament)(implicit ctx: Context)
@(tour: Tournament, verdicts: lila.tournament.Condition.All.WithVerdicts)(implicit ctx: Context)
<div class="side_box padded">
<div class="game_infos" data-icon="@tour.perfType.map(_.iconChar)">
@ -23,6 +23,15 @@
@markdownLinks(s.description)
</div>
}
@if(verdicts.relevant) {
<div class="game_infos conditions @if(ctx.isAuth) {
@if(verdicts.accepted){accepted}else{refused}
}" data-icon="7">
@verdicts.list.map { v =>
<p class="condition text @if(v.verdict.accepted){accepted}else{refused}">@v.condition</p>
}
</div>
}
@if(tour.createdBy == "lichess") {
@tour.id match {
case "summer15" => {

View file

@ -7,15 +7,24 @@ import lila.user.User
sealed abstract class Condition(val key: String) {
def apply(stats: Condition.GetStats)(user: User): Fu[Condition.Verdict]
def name: String
def withVerdict(stats: Condition.GetStats)(user: User): Fu[Condition.WithVerdict] =
apply(stats)(user) map { Condition.WithVerdict(this, _) }
override def toString = name
}
object Condition {
type GetStats = PerfType => Fu[PerfStat]
sealed trait Verdict
case object Accepted extends Verdict
case class Refused(reason: String) extends Verdict
sealed abstract class Verdict(val accepted: Boolean)
case object Accepted extends Verdict(true)
case class Refused(reason: String) extends Verdict(false)
case class WithVerdict(condition: Condition, verdict: Verdict)
case class NbRatedGame(perf: Option[PerfType], nb: Int) extends Condition("nb") {
@ -27,6 +36,11 @@ object Condition {
case None => Refused(s"Only ${user.count.rated} of $nb rated games played")
}
}
def name = perf match {
case None => s"$nb rated games"
case Some(p) => s"$nb ${p.name} rated games"
}
}
case class MaxRating(perf: PerfType, rating: Int) extends Condition("rating") {
@ -38,29 +52,41 @@ object Condition {
case Some(h) => Refused(s"Max ${perf.name} rating (${h.int}) is too high.")
}
}
def name = s"Rated ≤ $rating in ${perf.name}"
}
case class All(
nbRatedGame: Option[NbRatedGame],
maxRating: Option[MaxRating]) {
def relevant = list.nonEmpty
def list: List[Condition] = List(nbRatedGame, maxRating).flatten
def ifNonEmpty = list.nonEmpty option this
def withVerdicts(stats: Condition.GetStats)(user: User): Fu[All.WithVerdicts] =
list.map { cond =>
cond.withVerdict(stats)(user)
}.sequenceFu map All.WithVerdicts.apply
def accepted = All.WithVerdicts(list.map { WithVerdict(_, Accepted) })
}
object All {
val empty = All(nbRatedGame = none, maxRating = none)
case class WithVerdicts(list: List[WithVerdict]) {
def relevant = list.nonEmpty
def accepted = list.forall(_.verdict.accepted)
}
}
final class Verify(getStats: PerfStat.Getter) {
def apply(user: User, all: All): Fu[Verdict] = {
def apply(all: All, user: User): Fu[All.WithVerdicts] = {
val stats: GetStats = perf => getStats(user, perf)
all.list.map { cond =>
cond(stats)(user)
}.sequenceFu map { verdicts =>
verdicts.find(_ != Accepted) | Accepted
}
all.withVerdicts(stats)(user)
}
}

View file

@ -166,10 +166,15 @@ private[tournament] final class TournamentApi(
}
}
def verdicts(tour: Tournament, me: Option[User]): Fu[Condition.All.WithVerdicts] = me match {
case None => fuccess(tour.conditions.accepted)
case Some(user) => verify(tour.conditions, user)
}
def join(tourId: String, me: User) {
Sequencing(tourId)(TournamentRepo.enterableById) { tour =>
verify(me, tour.conditions) flatMap { verdict =>
(verdict == Condition.Accepted) ?? {
verdicts(tour, me.some) flatMap {
_.accepted ?? {
PlayerRepo.join(tour.id, me, tour.perfLens) >> updateNbPlayers(tour.id) >>- {
withdrawAllNonMarathonOrUniqueBut(tour.id, me.id)
socketReload(tour.id)

View file

@ -376,6 +376,15 @@ div.side_box .game_infos.spotlight {
div.side_box .game_infos.spotlight a {
text-decoration: underline;
}
div.side_box .conditions::before {
opacity: 0.6;
}
div.side_box .accepted {
color: #759900;
}
div.side_box .refused {
color: #dc322f;
}
#tournament_side {
position: relative;
float: right;