gray out cheaters on swiss podiums

since they can't be removed because it makes
the tournament pairings become wrong
pull/7469/head
Thibault Duplessis 2020-10-15 22:53:11 +02:00
parent 4f2e4ddba4
commit 1040c0890e
5 changed files with 41 additions and 14 deletions

View File

@ -11,7 +11,7 @@ import lila.db.dsl._
import lila.game.Game
import lila.quote.Quote.quoteWriter
import lila.socket.Socket.SocketVersion
import lila.user.User
import lila.user.{ User, UserRepo }
final class SwissJson(
colls: SwissColls,
@ -19,6 +19,7 @@ final class SwissJson(
rankingApi: SwissRankingApi,
boardApi: SwissBoardApi,
statsApi: SwissStatsApi,
userRepo: UserRepo,
lightUserApi: lila.user.LightUserApi
)(implicit ec: ExecutionContext) {
@ -116,20 +117,26 @@ final class SwissJson(
.find($doc(f.swissId -> swiss.id))
.sort($sort desc f.score)
.cursor[SwissPlayer]()
.list(3) map { top3 =>
.list(3) flatMap { top3 =>
// check that the winner is still correctly denormalized
top3.headOption.map(_.userId).filter(w => swiss.winnerId.fold(true)(w !=)) foreach {
colls.swiss.updateField($id(swiss.id), "winnerId", _).void
}
JsArray {
top3.map { player =>
playerJsonBase(
player,
lightUserApi.sync(player.userId) | LightUser.fallback(player.userId),
performance = true
)
top3.headOption
.map(_.userId)
.filter(w => swiss.winnerId.fold(true)(w !=))
.foreach {
colls.swiss.updateField($id(swiss.id), "winnerId", _).void
}
}.some
.unit
userRepo.filterEngine(top3.map(_.userId)) map { engines =>
JsArray(
top3.map { player =>
playerJsonBase(
player,
lightUserApi.sync(player.userId) | LightUser.fallback(player.userId),
performance = true
).add("engine", engines(player.userId))
}
).some
}
}
}
}

View File

@ -357,6 +357,9 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
def isEngine(id: ID): Fu[Boolean] = coll.exists($id(id) ++ engineSelect(true))
def filterEngine(ids: Seq[ID]): Fu[Set[ID]] =
coll.distinct[ID, Set]("_id", Some($inIds(ids) ++ engineSelect(true)))
def isTroll(id: ID): Fu[Boolean] = coll.exists($id(id) ++ trollSelect(true))
def isCreatedSince(id: ID, since: DateTime): Fu[Boolean] =

View File

@ -26,6 +26,18 @@
display: inline-block;
text-align: center;
&.engine {
opacity: .5;
.user-link {
text-decoration: line-through;
font-weight: normal;
}
.trophy {
opacity: .3;
filter: grayscale(100%) contrast(10%);
}
}
}
.first {

View File

@ -96,6 +96,7 @@ export interface BasePlayer {
}
export interface PodiumPlayer extends BasePlayer {
engine?: boolean;
}
export interface Player extends BasePlayer {

View File

@ -14,7 +14,11 @@ function podiumStats(p: PodiumPlayer, trans: Trans): VNode {
}
function podiumPosition(p: PodiumPlayer, pos: string, trans: Trans): VNode | undefined {
return p ? h('div.' + pos, [
return p ? h('div.' + pos, {
class: {
engine: !!p.engine
}
}, [
h('div.trophy'),
h('a.text.ulpt.user-link', {
attrs: { href: '/@/' + p.user.name }