implement new ranking API
parent
6998a33f4c
commit
5ae3c70663
|
@ -538,6 +538,7 @@ user {
|
|||
user = user4
|
||||
note = note
|
||||
trophy = trophy
|
||||
ranking = ranking
|
||||
}
|
||||
}
|
||||
history {
|
||||
|
|
|
@ -22,6 +22,7 @@ final class Env(
|
|||
playban: lila.playban.PlaybanApi,
|
||||
lightUser: String => Option[lila.common.LightUser],
|
||||
userJsonView: lila.user.JsonView,
|
||||
rankingApi: lila.user.RankingApi,
|
||||
uciMemo: lila.game.UciMemo,
|
||||
rematch960Cache: lila.memo.ExpireSetMemo,
|
||||
isRematchCache: lila.memo.ExpireSetMemo,
|
||||
|
@ -112,7 +113,7 @@ final class Env(
|
|||
messenger = messenger,
|
||||
bus = system.lilaBus)
|
||||
|
||||
lazy val perfsUpdater = new PerfsUpdater(historyApi)
|
||||
lazy val perfsUpdater = new PerfsUpdater(historyApi, rankingApi)
|
||||
|
||||
lazy val forecastApi: ForecastApi = new ForecastApi(
|
||||
coll = db(CollectionForecast),
|
||||
|
@ -214,6 +215,7 @@ object Env {
|
|||
playban = lila.playban.Env.current.api,
|
||||
lightUser = lila.user.Env.current.lightUser,
|
||||
userJsonView = lila.user.Env.current.jsonView,
|
||||
rankingApi = lila.user.Env.current.rankingApi,
|
||||
uciMemo = lila.game.Env.current.uciMemo,
|
||||
rematch960Cache = lila.game.Env.current.cached.rematch960,
|
||||
isRematchCache = lila.game.Env.current.cached.isRematch,
|
||||
|
|
|
@ -8,9 +8,11 @@ import play.api.Logger
|
|||
import lila.game.{ GameRepo, Game, Pov, PerfPicker }
|
||||
import lila.history.HistoryApi
|
||||
import lila.rating.{ Glicko, Perf, PerfType => PT }
|
||||
import lila.user.{ UserRepo, User, Perfs }
|
||||
import lila.user.{ UserRepo, User, Perfs, RankingApi }
|
||||
|
||||
final class PerfsUpdater(historyApi: HistoryApi) {
|
||||
final class PerfsUpdater(
|
||||
historyApi: HistoryApi,
|
||||
rankingApi: RankingApi) {
|
||||
|
||||
private val VOLATILITY = Glicko.default.volatility
|
||||
private val TAU = 0.75d
|
||||
|
@ -65,7 +67,9 @@ final class PerfsUpdater(historyApi: HistoryApi) {
|
|||
UserRepo.setPerfs(white, perfsW, white.perfs) zip
|
||||
UserRepo.setPerfs(black, perfsB, black.perfs) zip
|
||||
historyApi.add(white, game, perfsW) zip
|
||||
historyApi.add(black, game, perfsB)
|
||||
historyApi.add(black, game, perfsB) zip
|
||||
rankingApi.save(white.id, game.perfType, perfsW) zip
|
||||
rankingApi.save(black.id, game.perfType, perfsB)
|
||||
}.void
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ final class Env(
|
|||
val CollectionUser = config getString "collection.user"
|
||||
val CollectionNote = config getString "collection.note"
|
||||
val CollectionTrophy = config getString "collection.trophy"
|
||||
val CollectionRanking = config getString "collection.ranking"
|
||||
}
|
||||
import settings._
|
||||
|
||||
|
@ -34,6 +35,8 @@ final class Env(
|
|||
|
||||
lazy val trophyApi = new TrophyApi(db(CollectionTrophy))
|
||||
|
||||
lazy val rankingApi = new RankingApi(db(CollectionRanking))
|
||||
|
||||
lazy val jsonView = new JsonView(isOnline)
|
||||
|
||||
val forms = DataForm
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package lila.user
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import play.api.libs.iteratee._
|
||||
import reactivemongo.bson._
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import lila.db.BSON.BSONJodaDateTimeHandler
|
||||
import lila.db.BSON.MapValue.MapHandler
|
||||
import lila.memo.AsyncCache
|
||||
import lila.rating.{ Perf, PerfType }
|
||||
|
||||
final class RankingApi(coll: lila.db.Types.Coll) {
|
||||
|
||||
private type Rating = Int
|
||||
|
||||
def save(userId: User.ID, perfType: Option[PerfType], perfs: Perfs): Funit =
|
||||
perfType ?? { pt =>
|
||||
save(userId, pt, perfs(pt).intRating)
|
||||
}
|
||||
|
||||
def save(userId: User.ID, perfType: PerfType, rating: Rating): Funit =
|
||||
coll.update(BSONDocument(
|
||||
"_id" -> makeId(userId, perfType)
|
||||
), BSONDocument(
|
||||
"user" -> userId,
|
||||
"perf" -> perfType.key,
|
||||
"rating" -> rating,
|
||||
"expiresAt" -> DateTime.now.plusDays(7)),
|
||||
upsert = true).void
|
||||
|
||||
def getAll(userId: User.ID): Fu[Map[Perf.Key, Int]] =
|
||||
lila.common.Future.traverseSequentially(PerfType.leaderboardable) { perf =>
|
||||
cache(perf.key) map { _ get userId map (perf.key -> _) }
|
||||
} map (_.flatten.toMap)
|
||||
|
||||
private val cache = AsyncCache[Perf.Key, Map[User.ID, Rating]](
|
||||
f = compute,
|
||||
timeToLive = 15 minutes)
|
||||
|
||||
private def compute(perfKey: Perf.Key): Fu[Map[User.ID, Rating]] = {
|
||||
val enumerator = coll.find(
|
||||
BSONDocument("perf" -> perfKey),
|
||||
BSONDocument("user" -> true, "_id" -> false)
|
||||
).sort(BSONDocument("rating" -> -1)).cursor[BSONDocument]().enumerate()
|
||||
var rank = 1
|
||||
val b = Map.newBuilder[User.ID, Rating]
|
||||
val mapBuilder: Iteratee[BSONDocument, Unit] = Iteratee.foreach { doc =>
|
||||
doc.getAs[User.ID]("user") foreach { user =>
|
||||
b += (user -> rank)
|
||||
rank = rank + 1
|
||||
}
|
||||
}
|
||||
enumerator.run(mapBuilder) inject b.result
|
||||
}
|
||||
|
||||
private def makeId(user: User.ID, perfType: PerfType) =
|
||||
s"$user:${perfType.key}"
|
||||
}
|
Loading…
Reference in New Issue