static team battle full leaderboard page

pull/7989/head
Thibault Duplessis 2021-01-22 11:10:35 +01:00
parent e99c3fe802
commit 58e6f78d4d
7 changed files with 86 additions and 24 deletions

View File

@ -484,6 +484,20 @@ final class Tournament(
}.fuccess
}
def battleTeams(id: String) =
Open { implicit ctx =>
repo byId id flatMap {
_ ?? { tour =>
tour.teamBattle ?? { battle =>
env.tournament.cached.battle.teamStanding.get(tour.id) map { standing =>
Ok(views.html.tournament.teamBattle.standing(tour, battle, standing))
}
}
}
}
}
private def WithEditableTournament(id: String, me: UserModel)(
f: Tour => Fu[Result]
)(implicit ctx: Context): Fu[Result] =

View File

@ -116,7 +116,7 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
withTitle: Boolean = true,
truncate: Option[Int] = None,
params: String = ""
)(implicit lang: Lang): Frag =
)(implicit lang: Lang): Tag =
userIdNameLink(
userId = user.id,
username = user.name,
@ -150,7 +150,7 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
title: Option[Title],
params: String,
modIcon: Boolean
)(implicit lang: Lang): Frag =
)(implicit lang: Lang): Tag =
a(
cls := userClass(userId, cssClass, withOnline),
href := userUrl(username, params = params)
@ -170,7 +170,7 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
withPerfRating: Option[PerfType] = None,
name: Option[Frag] = None,
params: String = ""
)(implicit lang: Lang): Frag =
)(implicit lang: Lang): Tag =
a(
cls := userClass(user.id, cssClass, withOnline, withPowerTip),
href := userUrl(user.username, params)

View File

@ -1,15 +1,15 @@
package views.html
package tournament
import controllers.routes
import play.api.data.Form
import lila.api.Context
import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._
import lila.tournament.TeamBattle
import lila.tournament.Tournament
import controllers.routes
object teamBattle {
def edit(tour: Tournament, form: Form[_])(implicit ctx: Context) =
@ -52,4 +52,37 @@ object teamBattle {
)
)
)
private val scoreTag = tag("score")
def standing(tour: Tournament, battle: TeamBattle, standing: List[TeamBattle.RankedTeam])(implicit
ctx: Context
) =
views.html.base.layout(
title = tour.name(),
moreCss = cssTag("tournament.show.team-battle")
)(
main(cls := "tour__battle-standing box")(
h1(a(href := routes.Tournament.show(tour.id))(tour.name())),
table(cls := "slist slist-pad tour__team-standing")(
tbody(
standing.map { t =>
tr(
td(cls := "rank")(t.rank),
td(cls := "team")(teamIdToName(t.teamId)),
td(cls := "players")(
fragList(
t.leaders.map { l =>
scoreTag(dataHref := routes.User.show(l.userId), cls := "user-link ulpt")(l.score)
},
"+"
)
),
td(cls := "total")(t.score)
)
}
)
)
)
)
}

View File

@ -236,6 +236,7 @@ GET /tournament/$id<\w{8}>/team/:team controllers.Tournament.teamInfo(id
POST /tournament/$id<\w{8}>/terminate controllers.Tournament.terminate(id: String)
GET /tournament/$id<\w{8}>/edit controllers.Tournament.edit(id: String)
POST /tournament/$id<\w{8}>/edit controllers.Tournament.update(id: String)
GET /tournament/$id<\w{8}>/teams controllers.Tournament.battleTeams(id: String)
GET /tournament/help controllers.Tournament.help(system: Option[String] ?= None)
GET /tournament/leaderboard controllers.Tournament.leaderboard
GET /tournament/shields controllers.Tournament.shields

View File

@ -7,6 +7,7 @@ import lila.hub.LightTeam.TeamID
import lila.memo._
import lila.memo.CacheApi._
import lila.user.User
import play.api.libs.json.JsArray
final private[tournament] class Cached(
playerRepo: PlayerRepo,
@ -59,6 +60,19 @@ final private[tournament] class Cached(
.buildAsyncFuture(playerRepo.computeRanking)
}
object battle {
val teamStanding =
cacheApi[Tournament.ID, List[TeamBattle.RankedTeam]](8, "tournament.teamStanding") {
_.expireAfterWrite(1 second)
.buildAsyncFuture { id =>
tournamentRepo teamBattleOf id flatMap {
_ ?? { playerRepo.bestTeamIdsByTour(id, _) }
}
}
}
}
private[tournament] object sheet {
import arena.Sheet

View File

@ -363,23 +363,17 @@ final class JsonView(
"p" -> Json.arr(u1, u2)
)
private val teamStandingCache = cacheApi[Tournament.ID, JsArray](4, "tournament.teamStanding") {
_.expireAfterWrite(1 second)
private val teamStandingJsonCache = cacheApi[Tournament.ID, JsArray](4, "tournament.teamStanding") {
_.expireAfterWrite(500 millis)
.buildAsyncFuture { id =>
tournamentRepo.teamBattleOf(id) flatMap {
_.fold(fuccess(JsArray())) { battle =>
playerRepo.bestTeamIdsByTour(id, battle) map { ranked =>
JsArray(ranked take TeamBattle.displayTeams map teamBattleRankedWrites.writes)
}
}
cached.battle.teamStanding.get(id) map { ranked =>
JsArray(ranked take TeamBattle.displayTeams map teamBattleRankedWrites.writes)
}
}
}
def getTeamStanding(tour: Tournament): Fu[Option[JsArray]] =
tour.isTeamBattle ?? {
teamStandingCache get tour.id dmap some
}
tour.isTeamBattle ?? { teamStandingJsonCache get tour.id dmap some }
implicit private val teamBattleRankedWrites: Writes[TeamBattle.RankedTeam] = OWrites { rt =>
Json.obj(

View File

@ -26,12 +26,14 @@ team {
}
.tour__team-standing {
tbody tr:nth-child(odd) {
background: $c-bg-zebra;
}
tbody tr {
&:nth-child(odd) {
background: $c-bg-zebra;
}
tbody tr:nth-child(even) {
background: $c-bg-box;
&:nth-child(even) {
background: $c-bg-box;
}
}
.team {
@ -82,7 +84,7 @@ team {
background: linear-gradient(to left, $c-active-border 0px, $c-active-border 5px, rgba(0, 0, 0, 0) 5px, rgba(0, 0, 0, 0) 100%);
}
tr:hover {
.tour__main & tr:hover {
background: mix($c-primary, $c-bg-box, 30%) !important;
}
@ -91,9 +93,13 @@ team {
}
}
.team-battle {
&__title {}
.tour__battle-standing {
td {
padding: 2rem 1rem;
}
}
.team-battle {
&__list {
a {
display: block;