mobile API /@/<user>/mini - for veloce/lichobile#315
includes crosstable data and the 8 most played perfspull/1823/head
parent
d2c73f692d
commit
a92a571f0d
|
@ -88,7 +88,7 @@ object Relation extends LilaController {
|
|||
relatedWrites.writes(r) ++ Json.obj(
|
||||
"online" -> Env.user.isOnline(r.user.id).option(true),
|
||||
"perfs" -> r.user.perfs.bestPerfType.map { best =>
|
||||
Env.user.jsonView.perfs(r.user, best.some)
|
||||
lila.user.JsonView.perfs(r.user, best.some)
|
||||
}).noNull
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -44,10 +44,20 @@ object User extends LilaController {
|
|||
(ctx.userId ?? { relationApi.fetchBlocks(user.id, _) }) zip
|
||||
(ctx.userId ?? { Env.game.crosstableApi(user.id, _) }) zip
|
||||
(ctx.isAuth ?? { Env.pref.api.followable(user.id) }) zip
|
||||
(ctx.userId ?? { relationApi.fetchRelation(_, user.id) }) map {
|
||||
(ctx.userId ?? { relationApi.fetchRelation(_, user.id) }) flatMap {
|
||||
case (((((pov, donor), blocked), crosstable), followable), relation) =>
|
||||
Ok(html.user.mini(user, pov, blocked, followable, relation, crosstable, donor))
|
||||
.withHeaders(CACHE_CONTROL -> "max-age=5")
|
||||
negotiate(
|
||||
html = fuccess {
|
||||
Ok(html.user.mini(user, pov, blocked, followable, relation, crosstable, donor))
|
||||
.withHeaders(CACHE_CONTROL -> "max-age=5")
|
||||
},
|
||||
api = _ => {
|
||||
import lila.game.JsonView.crosstableWrites
|
||||
fuccess(Ok(Json.obj(
|
||||
"crosstable" -> crosstable,
|
||||
"perfs" -> lila.user.JsonView.perfs(user, user.best8Perfs)
|
||||
)))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,13 +37,6 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
|
|||
PerfType.RacingKings,
|
||||
PerfType.Crazyhouse)
|
||||
|
||||
private def best4Of(u: User, perfTypes: List[PerfType]) =
|
||||
perfTypes.sortBy { pt => -u.perfs(pt).nb } take 4
|
||||
|
||||
def miniViewSortedPerfTypes(u: User): List[PerfType] =
|
||||
best4Of(u, List(PerfType.Bullet, PerfType.Blitz, PerfType.Classical, PerfType.Correspondence)) :::
|
||||
best4Of(u, List(PerfType.Crazyhouse, PerfType.Chess960, PerfType.KingOfTheHill, PerfType.ThreeCheck, PerfType.Antichess, PerfType.Atomic, PerfType.Horde, PerfType.RacingKings))
|
||||
|
||||
def showPerfRating(rating: Int, name: String, nb: Int, provisional: Boolean, icon: Char, klass: String)(implicit ctx: Context) = Html {
|
||||
val title = s"$name rating over ${nb.localize} games"
|
||||
val attr = if (klass == "title") "title" else "data-hint"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class="warning" data-icon="j">@trans.thisPlayerUsesChessComputerAssistance()</div>
|
||||
} else {
|
||||
<div class="ratings">
|
||||
@miniViewSortedPerfTypes(u).map { pt =>
|
||||
@u.best8Perfs.map { pt =>
|
||||
@showPerfRating(u, pt)
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,17 @@ import chess.variant.Crazyhouse
|
|||
|
||||
object JsonView {
|
||||
|
||||
implicit val crosstableResultWrites = Json.writes[Crosstable.Result]
|
||||
|
||||
implicit val crosstableWrites = OWrites[Crosstable] { c =>
|
||||
Json.obj(
|
||||
"users" -> JsObject(c.users.map { u =>
|
||||
u.id -> JsNumber(u.score / 10d)
|
||||
}),
|
||||
"results" -> c.results,
|
||||
"nbGames" -> c.nbGames)
|
||||
}
|
||||
|
||||
implicit val crazyhousePocketWriter: OWrites[Crazyhouse.Pocket] = OWrites { v =>
|
||||
JsObject(
|
||||
Crazyhouse.storableRoles.flatMap { role =>
|
|
@ -10,6 +10,8 @@ import play.api.libs.json._
|
|||
|
||||
final class JsonView(getLightUser: String => Option[LightUser]) {
|
||||
|
||||
import JsonView._
|
||||
|
||||
def apply(
|
||||
user: User,
|
||||
stat: PerfStat,
|
||||
|
@ -25,6 +27,27 @@ final class JsonView(getLightUser: String => Option[LightUser]) {
|
|||
},
|
||||
"stat" -> stat.copy(playStreak = stat.playStreak.checkCurrent))
|
||||
|
||||
private implicit val userIdWriter: OWrites[UserId] = OWrites { u =>
|
||||
val light = getLightUser(u.value)
|
||||
Json.obj(
|
||||
"id" -> u.value,
|
||||
"name" -> light.fold(u.value)(_.name),
|
||||
"title" -> light.flatMap(_.title))
|
||||
}
|
||||
|
||||
implicit val ratingAtWrites = Json.writes[RatingAt]
|
||||
implicit val resultWrites = Json.writes[Result]
|
||||
implicit val resultsWrites = Json.writes[Results]
|
||||
implicit val streakWrites = Json.writes[Streak]
|
||||
implicit val streaksWrites = Json.writes[Streaks]
|
||||
implicit val playStreakWrites = Json.writes[PlayStreak]
|
||||
implicit val resultStreakWrites = Json.writes[ResultStreak]
|
||||
implicit val countWrites = Json.writes[Count]
|
||||
implicit val perfStatWrites = Json.writes[PerfStat]
|
||||
}
|
||||
|
||||
object JsonView {
|
||||
|
||||
private def truncate(v: Double) = lila.common.Maths.truncateAt(v, 2)
|
||||
|
||||
private val isoFormatter = ISODateTimeFormat.dateTime
|
||||
|
@ -34,38 +57,22 @@ final class JsonView(getLightUser: String => Option[LightUser]) {
|
|||
private implicit val userWriter: OWrites[User] = OWrites { u =>
|
||||
Json.obj("name" -> u.username)
|
||||
}
|
||||
private implicit val glickoWriter: OWrites[Glicko] = OWrites { p =>
|
||||
implicit val glickoWriter: OWrites[Glicko] = OWrites { p =>
|
||||
Json.obj(
|
||||
"rating" -> truncate(p.rating),
|
||||
"deviation" -> truncate(p.deviation),
|
||||
"volatility" -> truncate(p.volatility),
|
||||
"provisional" -> p.provisional)
|
||||
}
|
||||
private implicit val perfWriter: OWrites[Perf] = OWrites { p =>
|
||||
implicit val perfWriter: OWrites[Perf] = OWrites { p =>
|
||||
Json.obj("glicko" -> p.glicko, "nb" -> p.nb, "progress" -> p.progress)
|
||||
}
|
||||
private implicit val avgWriter: Writes[Avg] = Writes { a =>
|
||||
JsNumber(truncate(a.avg))
|
||||
}
|
||||
private implicit val perfTypeWriter: OWrites[PerfType] = OWrites { pt =>
|
||||
implicit val perfTypeWriter: OWrites[PerfType] = OWrites { pt =>
|
||||
Json.obj(
|
||||
"key" -> pt.key,
|
||||
"name" -> pt.name)
|
||||
}
|
||||
private implicit val userIdWriter: OWrites[UserId] = OWrites { u =>
|
||||
val light = getLightUser(u.value)
|
||||
Json.obj(
|
||||
"id" -> u.value,
|
||||
"name" -> light.fold(u.value)(_.name),
|
||||
"title" -> light.flatMap(_.title))
|
||||
}
|
||||
private implicit val ratingAtWrites = Json.writes[RatingAt]
|
||||
private implicit val resultWrites = Json.writes[Result]
|
||||
private implicit val resultsWrites = Json.writes[Results]
|
||||
private implicit val streakWrites = Json.writes[Streak]
|
||||
private implicit val streaksWrites = Json.writes[Streaks]
|
||||
private implicit val playStreakWrites = Json.writes[PlayStreak]
|
||||
private implicit val resultStreakWrites = Json.writes[ResultStreak]
|
||||
private implicit val countWrites = Json.writes[Count]
|
||||
private implicit val perfStatWrites = Json.writes[PerfStat]
|
||||
}
|
||||
|
|
|
@ -8,14 +8,6 @@ import User.{ PlayTime, LightPerf }
|
|||
final class JsonView(isOnline: String => Boolean) {
|
||||
|
||||
import JsonView._
|
||||
|
||||
private implicit val perfWrites: OWrites[Perf] = OWrites { o =>
|
||||
Json.obj(
|
||||
"games" -> o.nb,
|
||||
"rating" -> o.glicko.rating.toInt,
|
||||
"rd" -> o.glicko.deviation.toInt,
|
||||
"prog" -> o.progress)
|
||||
}
|
||||
private implicit val profileWrites = Json.writes[Profile]
|
||||
private implicit val playTimeWrites = Json.writes[PlayTime]
|
||||
|
||||
|
@ -34,11 +26,6 @@ final class JsonView(isOnline: String => Boolean) {
|
|||
"playTime" -> u.playTime
|
||||
).noNull
|
||||
|
||||
def perfs(u: User, onlyPerf: Option[PerfType] = None) =
|
||||
JsObject(u.perfs.perfsMap collect {
|
||||
case (key, perf) if onlyPerf.fold(true)(_.key == key) => key -> perfWrites.writes(perf)
|
||||
})
|
||||
|
||||
def lightPerfIsOnline(lp: LightPerf) = {
|
||||
val json = lightPerfWrites.writes(lp)
|
||||
if (isOnline(lp.user.id)) json ++ Json.obj("online" -> true)
|
||||
|
@ -61,4 +48,22 @@ object JsonView {
|
|||
l.perfKey -> Json.obj("rating" -> l.rating, "progress" -> l.progress))
|
||||
).noNull
|
||||
}
|
||||
|
||||
implicit val perfWrites: OWrites[Perf] = OWrites { o =>
|
||||
Json.obj(
|
||||
"games" -> o.nb,
|
||||
"rating" -> o.glicko.rating.toInt,
|
||||
"rd" -> o.glicko.deviation.toInt,
|
||||
"prog" -> o.progress)
|
||||
}
|
||||
|
||||
def perfs(u: User, onlyPerf: Option[PerfType] = None) =
|
||||
JsObject(u.perfs.perfsMap collect {
|
||||
case (key, perf) if onlyPerf.fold(true)(_.key == key) => key -> perfWrites.writes(perf)
|
||||
})
|
||||
|
||||
def perfs(u: User, onlyPerfs: List[PerfType]) =
|
||||
JsObject(onlyPerfs.map { perfType =>
|
||||
perfType.key -> perfWrites.writes(u.perfs(perfType))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import lila.common.LightUser
|
|||
|
||||
import chess.Speed
|
||||
import org.joda.time.DateTime
|
||||
import lila.rating.PerfType
|
||||
|
||||
case class User(
|
||||
id: String,
|
||||
|
@ -76,6 +77,13 @@ case class User(
|
|||
}
|
||||
|
||||
def lightCount = User.LightCount(light, count.game)
|
||||
|
||||
private def best4Of(perfTypes: List[PerfType]) =
|
||||
perfTypes.sortBy { pt => -perfs(pt).nb } take 4
|
||||
|
||||
def best8Perfs: List[PerfType] =
|
||||
best4Of(List(PerfType.Bullet, PerfType.Blitz, PerfType.Classical, PerfType.Correspondence)) :::
|
||||
best4Of(List(PerfType.Crazyhouse, PerfType.Chess960, PerfType.KingOfTheHill, PerfType.ThreeCheck, PerfType.Antichess, PerfType.Atomic, PerfType.Horde, PerfType.RacingKings))
|
||||
}
|
||||
|
||||
object User {
|
||||
|
|
Loading…
Reference in New Issue