Complete user module
parent
5213003e4b
commit
ef9975e445
|
@ -2,7 +2,7 @@ package lila
|
|||
|
||||
import ornicar.scalalib
|
||||
|
||||
import scalaz.Zero
|
||||
import scalaz.{ Zero, Functor }
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait PackageObject
|
||||
|
@ -66,6 +66,7 @@ trait WithFuture extends scalaz.Zeros {
|
|||
type Funit = Fu[Unit]
|
||||
|
||||
def fuccess[A](a: A) = Future successful a
|
||||
def fufail[A <: Throwable](a: A) = Future failed a
|
||||
def funit = fuccess(())
|
||||
|
||||
implicit def FuZero[A: Zero]: Zero[Fu[A]] = new Zero[Fu[A]] { val zero = fuccess(∅[A]) }
|
||||
|
@ -73,9 +74,10 @@ trait WithFuture extends scalaz.Zeros {
|
|||
|
||||
trait WithDb { self: PackageObject ⇒
|
||||
|
||||
type LilaDB = reactivemongo.api.DB
|
||||
|
||||
type ReactiveColl = reactivemongo.api.collections.default.BSONCollection
|
||||
// implicit def reactiveSortJsObject(sort: (String, SortOrder)): (String, JsValueWrapper) = sort match {
|
||||
// case (field, SortOrder.Ascending) ⇒ field -> 1
|
||||
// case (field, _) ⇒ field -> -1
|
||||
// }
|
||||
}
|
||||
|
||||
trait WithPlay { self: PackageObject ⇒
|
||||
|
@ -91,6 +93,10 @@ trait WithPlay { self: PackageObject ⇒
|
|||
type JsEnumerator = Enumerator[JsValue]
|
||||
type SocketFuture = Future[(Iteratee[JsValue, _], JsEnumerator)]
|
||||
|
||||
implicit def FutureFunctor = new Functor[Fu] {
|
||||
def fmap[A, B](r: Fu[A], f: A ⇒ B) = r map f
|
||||
}
|
||||
|
||||
implicit def lilaRicherFuture[A](fua: Fu[A]) = new {
|
||||
|
||||
def >>[B](fub: Fu[B]): Fu[B] = fua flatMap (_ ⇒ fub)
|
||||
|
@ -100,7 +106,7 @@ trait WithPlay { self: PackageObject ⇒
|
|||
def inject[B](b: B): Fu[B] = fua map (_ ⇒ b)
|
||||
}
|
||||
|
||||
implicit def lilaRicherFutureZero[A : Zero](fua: Fu[A]) = new {
|
||||
implicit def lilaRicherFutureZero[A: Zero](fua: Fu[A]) = new {
|
||||
|
||||
def doIf(cond: Boolean): Fu[A] = cond.fold(fua, fuccess(∅[A]))
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
package lila.common
|
||||
package paginator
|
||||
|
||||
import scalaz.Success
|
||||
|
||||
import play.api.libs.concurrent.Execution.Implicits._
|
||||
|
||||
trait AdapterLike[A] {
|
||||
|
||||
/**
|
||||
* Returns the total number of results.
|
||||
*/
|
||||
def nbResults: Fu[Int]
|
||||
|
||||
/**
|
||||
* Returns a slice of the results.
|
||||
*
|
||||
* @param offset The number of elements to skip, starting from zero
|
||||
* @param length The maximum number of elements to return
|
||||
*/
|
||||
def slice(offset: Int, length: Int): Fu[Seq[A]]
|
||||
|
||||
/**
|
||||
* FUNCTOR INTERFACE
|
||||
*/
|
||||
def map[B](f: A ⇒ B): AdapterLike[B] = new AdapterLike[B] {
|
||||
def nbResults = AdapterLike.this.nbResults
|
||||
def slice(offset: Int, length: Int) = AdapterLike.this.slice(offset, length) map2 f
|
||||
}
|
||||
}
|
||||
|
||||
final class Paginator[A] private[paginator] (
|
||||
val currentPage: Int,
|
||||
val maxPerPage: Int,
|
||||
/**
|
||||
* Returns the results for the current page.
|
||||
* The result is cached.
|
||||
*/
|
||||
val currentPageResults: Seq[A],
|
||||
/**
|
||||
* Returns the number of results.
|
||||
* The result is cached.
|
||||
*/
|
||||
val nbResults: Int) {
|
||||
|
||||
/**
|
||||
* Returns the previous page.
|
||||
*/
|
||||
def previousPage: Option[Int] =
|
||||
if (currentPage == 1) None else Some(currentPage - 1)
|
||||
|
||||
/**
|
||||
* Returns the next page.
|
||||
*/
|
||||
def nextPage: Option[Int] =
|
||||
if (currentPage == nbPages) None else Some(currentPage + 1)
|
||||
|
||||
/**
|
||||
* FUNCTOR INTERFACE
|
||||
*/
|
||||
|
||||
def map[B](f: A ⇒ B): Paginator[B] = new Paginator(
|
||||
currentPage = currentPage,
|
||||
maxPerPage = maxPerPage,
|
||||
currentPageResults = currentPageResults map f,
|
||||
nbResults = nbResults)
|
||||
|
||||
/**
|
||||
* Returns the number of pages.
|
||||
*/
|
||||
def nbPages: Int = scala.math.ceil(nbResults.toFloat / maxPerPage).toInt
|
||||
|
||||
/**
|
||||
* Returns whether we have to paginate or not.
|
||||
* This is true if the number of results is higher than the max per page.
|
||||
*/
|
||||
def hasToPaginate: Boolean = nbResults > maxPerPage
|
||||
|
||||
/**
|
||||
* Returns whether there is previous page or not.
|
||||
*/
|
||||
def hasPreviousPage: Boolean = None != previousPage
|
||||
|
||||
/**
|
||||
* Returns whether there is next page or not.
|
||||
*/
|
||||
def hasNextPage: Boolean = None != nextPage
|
||||
}
|
||||
|
||||
object Paginator {
|
||||
|
||||
def apply[A](
|
||||
adapter: AdapterLike[A],
|
||||
currentPage: Int = 1,
|
||||
maxPerPage: Int = 10): Valid[Fu[Paginator[A]]] =
|
||||
if (currentPage <= 0) !!("Max per page must be greater than zero")
|
||||
else if (maxPerPage <= 0) !!("Current page must be greater than zero")
|
||||
else Success(for {
|
||||
results ← adapter.slice((currentPage - 1) * maxPerPage, maxPerPage)
|
||||
nbResults ← adapter.nbResults
|
||||
} yield new Paginator(currentPage, maxPerPage, results, nbResults))
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package lila.db
|
||||
|
||||
import com.github.ornicar.paginator._
|
||||
import com.novus.salat.dao.DAO
|
||||
import com.novus.salat._
|
||||
import com.mongodb.casbah.Imports.DBObject
|
||||
|
||||
final class CachedAdapter[A <: CaseClass, B <: Any](
|
||||
dao: DAO[A, B],
|
||||
query: DBObject,
|
||||
sort: DBObject,
|
||||
val nbResults: Int) extends Adapter[A] {
|
||||
|
||||
private val salatAdapter = SalatAdapter(
|
||||
dao = dao,
|
||||
query = query,
|
||||
sort = sort)
|
||||
|
||||
def slice(offset: Int, length: Int) = salatAdapter.slice(offset, length)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package lila
|
||||
|
||||
import reactivemongo.api.collections.GenericQueryBuilder
|
||||
import reactivemongo.bson._
|
||||
|
||||
package object db extends PackageObject with WithPlay with WithDb {
|
||||
|
||||
type WithStringId = { def id: String }
|
||||
|
||||
type QueryBuilder = GenericQueryBuilder[BSONDocument, BSONDocumentReader, BSONDocumentWriter]
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package lila.db
|
||||
|
||||
import play.api.libs.json._, Json.JsValueWrapper
|
||||
import reactivemongo.api.collections.GenericQueryBuilder
|
||||
import reactivemongo.bson._
|
||||
import reactivemongo.api._
|
||||
import reactivemongo.api.SortOrder
|
||||
import play.modules.reactivemongo.Implicits._
|
||||
|
||||
object Implicits extends Implicits
|
||||
trait Implicits {
|
||||
|
||||
type LilaDB = reactivemongo.api.DB
|
||||
|
||||
type ReactiveColl = reactivemongo.api.collections.default.BSONCollection
|
||||
|
||||
type WithStringId = { def id: String }
|
||||
|
||||
type QueryBuilder = GenericQueryBuilder[BSONDocument, BSONDocumentReader, BSONDocumentWriter]
|
||||
|
||||
// hack, this should be in reactivemongo
|
||||
implicit def richerQueryBuilder(b: QueryBuilder) = new {
|
||||
|
||||
def sort(sorters: (String, SortOrder)*): QueryBuilder =
|
||||
if (sorters.size == 0) b
|
||||
else b sort {
|
||||
BSONDocument(
|
||||
(for (sorter ← sorters) yield sorter._1 -> BSONInteger(
|
||||
sorter._2 match {
|
||||
case SortOrder.Ascending ⇒ 1
|
||||
case SortOrder.Descending ⇒ -1
|
||||
})).toStream)
|
||||
}
|
||||
|
||||
// def sortJs(sorter: JsObject): QueryBuilder = b sort JsObjectWriter.write(sorter)
|
||||
|
||||
def limit(nb: Int): QueryBuilder = b.options(b.options batchSize nb)
|
||||
|
||||
def skip(nb: Int): QueryBuilder = b.options(b.options skip nb)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package lila.db
|
||||
package paginator
|
||||
|
||||
import lila.common.paginator.AdapterLike
|
||||
import play.api.libs.json._
|
||||
import reactivemongo.api.SortOrder
|
||||
|
||||
final class Adapter[A <: WithStringId](
|
||||
repo: Repo[A],
|
||||
query: JsObject,
|
||||
sort: Seq[(String, SortOrder)]) extends AdapterLike[A] {
|
||||
|
||||
def nbResults: Fu[Int] = repo count query
|
||||
|
||||
def slice(offset: Int, length: Int): Fu[Seq[A]] = repo find {
|
||||
richerQueryBuilder(repo query query).sort(sort: _*) skip offset limit length
|
||||
}
|
||||
}
|
||||
|
||||
final class CachedAdapter[A <: WithStringId](
|
||||
adapter: Adapter[A],
|
||||
val nbResults: Fu[Int]) extends AdapterLike[A] {
|
||||
|
||||
def slice(offset: Int, length: Int) = adapter.slice(offset, length)
|
||||
}
|
|
@ -11,7 +11,7 @@ import play.api.libs.concurrent.Execution.Implicits._
|
|||
|
||||
import scala.concurrent.Future
|
||||
|
||||
abstract class Coll[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]) extends DbApi {
|
||||
abstract class Repo[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]) extends DbApi {
|
||||
|
||||
object query {
|
||||
|
||||
|
@ -123,23 +123,6 @@ abstract class Coll[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]
|
|||
|
||||
type ID = String
|
||||
|
||||
// hack, this should be in reactivemongo
|
||||
protected implicit def richerQueryBuilder(b: QueryBuilder) = new {
|
||||
|
||||
def sort(sorters: (String, SortOrder)*): QueryBuilder =
|
||||
if (sorters.size == 0) b
|
||||
else b sort {
|
||||
BSONDocument(
|
||||
(for (sorter ← sorters) yield sorter._1 -> BSONInteger(
|
||||
sorter._2 match {
|
||||
case SortOrder.Ascending ⇒ 1
|
||||
case SortOrder.Descending ⇒ -1
|
||||
})).toStream)
|
||||
}
|
||||
|
||||
def limit(nb: Int): QueryBuilder = b.options(b.options batchSize nb)
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// PRIVATE SHIT //
|
||||
//////////////////
|
||||
|
@ -160,5 +143,5 @@ abstract class Coll[Doc <: WithStringId](coll: ReactiveColl, json: JsonTube[Doc]
|
|||
def read(bson: BSONDocument): Option[Doc] = json.fromMongo(JsObjectReader read bson).asOpt
|
||||
}
|
||||
|
||||
private def fuck(msg: Any) = Future failed (new DbException(msg.toString))
|
||||
private def fuck(msg: Any) = fufail(new DbException(msg.toString))
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package lila
|
||||
|
||||
package object db
|
||||
extends PackageObject
|
||||
with WithPlay
|
||||
with db.Implicits
|
|
@ -27,8 +27,6 @@ trait Dependencies {
|
|||
val slf4jNop = "org.slf4j" %% "slf4j-nop" % "1.6.4"
|
||||
val guava = "com.google.guava" % "guava" % "14.0"
|
||||
val findbugs = "com.google.code.findbugs" % "jsr305" % "2.0.1"
|
||||
val paginator = "com.github.ornicar" % "paginator-core_2.9.1" % "1.6"
|
||||
val paginatorSalat = "com.github.ornicar" % "paginator-salat-adapter_2.9.1" % "1.5"
|
||||
val csv = "com.github.tototoshi" % "scala-csv_2.9.1" % "0.3"
|
||||
val hasher = "hasher" %% "hasher" % "0.3.1"
|
||||
val jgit = "org.eclipse.jgit" % "org.eclipse.jgit" % "1.3.0.201202151440-r"
|
||||
|
@ -37,7 +35,7 @@ trait Dependencies {
|
|||
val jodaConvert = "org.joda" % "joda-convert" % "1.2"
|
||||
val scalastic = "scalastic" % "scalastic_2.9.2" % "0.20.1-THIB"
|
||||
val reactivemongo = "org.reactivemongo" %% "reactivemongo" % "0.9-SNAPSHOT"
|
||||
val playReactivemongo = "org.reactivemongo" %% "play2-reactivemongo" % "0.9-SNAPSHOT"
|
||||
val playReactivemongo = "org.reactivemongo" %% "play2-reactivemongo" % "0.9-SNAPSHOT"
|
||||
val playProvided = "play" %% "play" % "2.1-SNAPSHOT" % "provided"
|
||||
val playTestProvided = "play" %% "play-test" % "2.1-SNAPSHOT" % "provided"
|
||||
val sprayCaching = "io.spray" % "spray-caching" % "1.1-M7"
|
||||
|
@ -58,11 +56,16 @@ object ApplicationBuild extends Build with Resolvers with Dependencies {
|
|||
"-language:_")
|
||||
)
|
||||
|
||||
private val srcMain = Seq(
|
||||
scalaSource in Compile <<= (sourceDirectory in Compile)(identity),
|
||||
scalaSource in Test <<= (sourceDirectory in Test)(identity)
|
||||
)
|
||||
|
||||
lazy val lila = play.Project("lila", "4",
|
||||
settings = buildSettings ++ Seq(
|
||||
libraryDependencies := Seq(
|
||||
scalaz, scalalib, hasher, config, salat, apache, scalaTime,
|
||||
paginator, paginatorSalat, csv, jgit, actuarius, scalastic, findbugs,
|
||||
csv, jgit, actuarius, scalastic, findbugs,
|
||||
reactivemongo),
|
||||
templatesImport ++= Seq(
|
||||
"lila.app.game.{ DbGame, DbPlayer, Pov }",
|
||||
|
@ -71,8 +74,8 @@ object ApplicationBuild extends Build with Resolvers with Dependencies {
|
|||
"lila.app.templating.Environment._",
|
||||
"lila.app.ui",
|
||||
"lila.app.http.Context",
|
||||
"com.github.ornicar.paginator.Paginator")
|
||||
)) dependsOn (user) aggregate (scalachess, common, db, user)
|
||||
"lila.common.paginator.Paginator")
|
||||
)) dependsOn (user, wiki) aggregate (scalachess, common, db, user, wiki)
|
||||
|
||||
lazy val common = project("common").settings(
|
||||
libraryDependencies := Seq(
|
||||
|
@ -85,26 +88,26 @@ object ApplicationBuild extends Build with Resolvers with Dependencies {
|
|||
|
||||
lazy val db = project("db", Seq(common)).settings(
|
||||
libraryDependencies := Seq(
|
||||
scalaz, scalalib, playProvided, salat, reactivemongo,
|
||||
paginator, paginatorSalat, playReactivemongo
|
||||
scalaz, scalalib, playProvided, salat, reactivemongo, playReactivemongo
|
||||
)
|
||||
)
|
||||
).settings(srcMain: _*)
|
||||
|
||||
lazy val user = project("user", Seq(common, memo, db, scalachess)).settings(
|
||||
libraryDependencies := Seq(
|
||||
scalaz, scalalib, hasher, jodaTime, jodaConvert, playProvided, salat,
|
||||
paginator, paginatorSalat, sprayCaching, playTestProvided,
|
||||
reactivemongo, playReactivemongo),
|
||||
scalaSource in Compile <<= (sourceDirectory in Compile)(identity),
|
||||
scalaSource in Test <<= (sourceDirectory in Test)(identity)
|
||||
)
|
||||
scalaz, scalalib, hasher, jodaTime, jodaConvert, playProvided,
|
||||
sprayCaching, playTestProvided, reactivemongo, playReactivemongo)
|
||||
).settings(srcMain: _*)
|
||||
|
||||
lazy val wiki = project("wiki", Seq(common, db)).settings(
|
||||
libraryDependencies := Seq(
|
||||
scalaz, scalalib, jodaTime, jodaConvert, playProvided,
|
||||
playTestProvided, reactivemongo, playReactivemongo)
|
||||
).settings(srcMain: _*)
|
||||
|
||||
lazy val scalachess = project("scalachess").settings(
|
||||
libraryDependencies := Seq(scalaz, scalalib, hasher, jodaTime, jodaConvert)
|
||||
)
|
||||
|
||||
private def project(name: String, deps: Seq[sbt.ClasspathDep[sbt.ProjectReference]] = Seq.empty) =
|
||||
Project(name, file(name), dependencies = deps, settings = buildSettings ++ Seq(
|
||||
// scalaSource in Compile <<= (sourceDirectory in Compile)(identity)
|
||||
))
|
||||
Project(name, file(name), dependencies = deps, settings = buildSettings)
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package lila.user
|
||||
|
||||
import com.github.ornicar.paginator._
|
||||
import com.mongodb.casbah.Imports.DBObject
|
||||
|
||||
import lila.db.CachedAdapter
|
||||
|
||||
final class PaginatorBuilder(userRepo: UserRepo, countUsers: () ⇒ Int, maxPerPage: Int) {
|
||||
|
||||
def elo(page: Int): Paginator[User] =
|
||||
paginator(recentAdapter, page)
|
||||
|
||||
private val recentAdapter =
|
||||
adapter(DBObject("enabled" -> true))
|
||||
|
||||
private def adapter(query: DBObject) = new CachedAdapter(
|
||||
dao = userRepo,
|
||||
query = query,
|
||||
sort = DBObject("elo" -> -1),
|
||||
nbResults = countUsers())
|
||||
|
||||
private def paginator(adapter: Adapter[User], page: Int) = Paginator(
|
||||
adapter,
|
||||
currentPage = page,
|
||||
maxPerPage = maxPerPage).fold(_ ⇒ elo(0), identity)
|
||||
}
|
|
@ -18,7 +18,7 @@ final class Cached(userRepo: UserRepo, ttl: Duration) {
|
|||
|
||||
def usernameOrAnonymous(id: Option[String]): String = (id flatMap username) | Users.anonymous
|
||||
|
||||
def countEnabled: Int = cache.fromFuture("count-enabled")(userRepo.countEnabled).await
|
||||
def countEnabled: Fu[Int] = cache.fromFuture("count-enabled")(userRepo.countEnabled)
|
||||
|
||||
// id => username
|
||||
private val usernameCache = mutable.Map[String, Option[String]]()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package lila.user
|
||||
|
||||
import scala.math.round
|
||||
import scalaz.effects._
|
||||
import play.api.libs.json.Json
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.format.{ DateTimeFormat, DateTimeFormatter }
|
||||
|
||||
import play.api.libs.concurrent.Execution.Implicits._
|
||||
|
||||
final class EloChart(rawElos: List[(Int, Int, Option[Int])]) {
|
||||
|
||||
private val points = 100
|
||||
|
@ -62,10 +63,10 @@ object EloChart {
|
|||
Json.arr("number", "Average")
|
||||
)
|
||||
|
||||
def apply(historyRepo: HistoryRepo)(user: User): IO[Option[EloChart]] =
|
||||
def apply(historyRepo: HistoryRepo)(user: User): Fu[Option[EloChart]] =
|
||||
historyRepo userElos user.username map { elos ⇒
|
||||
(elos.size > 1) option {
|
||||
new EloChart((user.createdAt.getSeconds.toInt, User.STARTING_ELO, None) :: elos)
|
||||
new EloChart((user.createdAt.getSeconds.toInt, Users.STARTING_ELO, None) :: elos.toList)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package lila.user
|
||||
|
||||
import lila.db.{ Coll, DbApi }
|
||||
import lila.db.DbApi
|
||||
import lila.db.Implicits._
|
||||
|
||||
import play.api.libs.json._
|
||||
import play.api.libs.concurrent.Execution.Implicits._
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package lila.user
|
||||
|
||||
import lila.common.paginator._
|
||||
import lila.db.paginator._
|
||||
|
||||
import play.api.libs.json._
|
||||
|
||||
final class PaginatorBuilder(userRepo: UserRepo, countUsers: Fu[Int], maxPerPage: Int) {
|
||||
|
||||
def elo(page: Int): Fu[Paginator[User]] = paginator(recentAdapter, page)
|
||||
|
||||
private val recentAdapter: AdapterLike[User] = adapter(Json.obj("enabled" -> true))
|
||||
|
||||
private def adapter(query: JsObject): AdapterLike[User] = new CachedAdapter(
|
||||
adapter = new Adapter(
|
||||
repo = userRepo,
|
||||
query = query,
|
||||
sort = Seq(userRepo.sortEloDesc)
|
||||
),
|
||||
nbResults = countUsers
|
||||
)
|
||||
|
||||
private def paginator(adapter: AdapterLike[User], page: Int): Fu[Paginator[User]] =
|
||||
Paginator(
|
||||
adapter,
|
||||
currentPage = page,
|
||||
maxPerPage = maxPerPage
|
||||
).fold(_ ⇒ elo(0), identity)
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package lila.user
|
||||
|
||||
import lila.db.ReactiveColl
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import akka.actor.ActorSystem
|
||||
|
||||
|
@ -9,25 +10,25 @@ final class UserEnv(settings: Settings, db: String ⇒ ReactiveColl) {
|
|||
|
||||
import settings._
|
||||
|
||||
// lazy val historyRepo = new HistoryRepo(mongodb(CollectionHistory))
|
||||
lazy val historyRepo = new HistoryRepo(db(CollectionHistory))
|
||||
|
||||
lazy val userRepo = new UserRepo(db(CollectionUser))
|
||||
|
||||
// lazy val paginator = new PaginatorBuilder(
|
||||
// userRepo = userRepo,
|
||||
// countUsers = () ⇒ cached.countEnabled,
|
||||
// maxPerPage = PaginatorMaxPerPage)
|
||||
lazy val paginator = new PaginatorBuilder(
|
||||
userRepo = userRepo,
|
||||
countUsers = cached.countEnabled,
|
||||
maxPerPage = PaginatorMaxPerPage)
|
||||
|
||||
// lazy val eloUpdater = new EloUpdater(
|
||||
// userRepo = userRepo,
|
||||
// historyRepo = historyRepo,
|
||||
// floor = EloUpdaterFloor)
|
||||
lazy val eloUpdater = new EloUpdater(
|
||||
userRepo = userRepo,
|
||||
historyRepo = historyRepo,
|
||||
floor = EloUpdaterFloor)
|
||||
|
||||
lazy val usernameMemo = new UsernameMemo(ttl = OnlineTtl)
|
||||
|
||||
// lazy val cached = new Cached(
|
||||
// userRepo = userRepo,
|
||||
// ttl = CachedNbTtl)
|
||||
lazy val cached = new Cached(
|
||||
userRepo = userRepo,
|
||||
ttl = CachedNbTtl)
|
||||
|
||||
// lazy val eloChart = EloChart(historyRepo) _
|
||||
lazy val eloChart = EloChart(historyRepo) _
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lila.user
|
||||
|
||||
import lila.db.{ Coll, DbApi }
|
||||
import lila.db.{ Repo, DbApi }
|
||||
import lila.db.Implicits._
|
||||
|
||||
import play.api.libs.json.Json
|
||||
import play.api.libs.concurrent.Execution.Implicits._
|
||||
|
@ -16,7 +17,7 @@ import com.roundeights.hasher.Implicits._
|
|||
import org.joda.time.DateTime
|
||||
import ornicar.scalalib.Random
|
||||
|
||||
final class UserRepo(coll: ReactiveColl) extends Coll[User](coll, Users.json) {
|
||||
final class UserRepo(coll: ReactiveColl) extends Repo[User](coll, Users.json) {
|
||||
|
||||
def normalize(id: ID) = id.toLowerCase
|
||||
|
||||
|
@ -32,7 +33,7 @@ final class UserRepo(coll: ReactiveColl) extends Coll[User](coll, Users.json) {
|
|||
|
||||
val enabledQuery = Json.obj("enabled" -> true)
|
||||
|
||||
val sortEloDesc = ("elo" -> sort.desc)
|
||||
val sortEloDesc = "elo" -> sort.desc
|
||||
|
||||
def incNbGames(id: ID, rated: Boolean, ai: Boolean, result: Option[Int]) = {
|
||||
val incs = List(
|
||||
|
|
Loading…
Reference in New Issue