mobile API /@/<user>/mini - for veloce/lichobile#315

includes crosstable data and the 8 most played perfs
pull/1823/head
Thibault Duplessis 2016-04-17 14:44:37 +07:00
parent d2c73f692d
commit a92a571f0d
8 changed files with 78 additions and 44 deletions

View File

@ -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
}))
}

View File

@ -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)
)))
})
}
}
}

View File

@ -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"

View File

@ -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>

View File

@ -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 =>

View File

@ -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]
}

View File

@ -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))
})
}

View File

@ -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 {