80 lines
2.7 KiB
Scala
80 lines
2.7 KiB
Scala
package lila.gameSearch
|
|
|
|
import play.api.libs.json._
|
|
import scala.concurrent.duration._
|
|
|
|
import lila.game.{ Game, GameRepo }
|
|
import lila.search._
|
|
import akka.stream.scaladsl.Source
|
|
|
|
final class GameSearchApi(
|
|
client: ESClient,
|
|
gameRepo: GameRepo
|
|
)(implicit
|
|
ec: scala.concurrent.ExecutionContext,
|
|
system: akka.actor.ActorSystem
|
|
) extends SearchReadApi[Game, Query] {
|
|
|
|
def search(query: Query, from: From, size: Size) =
|
|
client.search(query, from, size) flatMap { res =>
|
|
gameRepo gamesFromSecondary res.ids
|
|
}
|
|
|
|
def count(query: Query) =
|
|
client.count(query) dmap (_.count)
|
|
|
|
def ids(query: Query, max: Int): Fu[List[String]] =
|
|
client.search(query, From(0), Size(max)).map(_.ids)
|
|
|
|
def store(game: Game) =
|
|
storable(game) ?? {
|
|
gameRepo isAnalysed game.id flatMap { analysed =>
|
|
lila.common.Future
|
|
.retry(
|
|
() => client.store(Id(game.id), toDoc(game, analysed)),
|
|
delay = 20.seconds,
|
|
retries = 2,
|
|
logger.some
|
|
)
|
|
}
|
|
}
|
|
|
|
def source(query: Query, nb: Int): Source[Game, _] = {
|
|
val perPage = config.MaxPerPage(50)
|
|
val lastPage = math.ceil(nb.toFloat / perPage.value) atLeast 1 atMost (1000 / perPage.value)
|
|
Source.unfoldAsync(1) { page =>
|
|
search(query, From((page - 1) * perPage.value), Size(perPage.value))
|
|
}
|
|
}
|
|
|
|
private def storable(game: Game) = game.finished || game.imported
|
|
|
|
private def toDoc(game: Game, analysed: Boolean) =
|
|
Json
|
|
.obj(
|
|
Fields.status -> (game.status match {
|
|
case s if s.is(_.Timeout) => chess.Status.Resign
|
|
case s if s.is(_.NoStart) => chess.Status.Resign
|
|
case _ => game.status
|
|
}).id,
|
|
Fields.turns -> (game.turns + 1) / 2,
|
|
Fields.rated -> game.rated,
|
|
Fields.perf -> game.perfType.map(_.id),
|
|
Fields.uids -> game.userIds.toArray.some.filterNot(_.isEmpty),
|
|
Fields.winner -> game.winner.flatMap(_.userId),
|
|
Fields.loser -> game.loser.flatMap(_.userId),
|
|
Fields.winnerColor -> game.winner.fold(3)(_.color.fold(1, 2)),
|
|
Fields.averageRating -> game.averageUsersRating,
|
|
Fields.ai -> game.aiLevel,
|
|
Fields.date -> (lila.search.Date.formatter print game.movedAt),
|
|
Fields.duration -> game.durationSeconds, // for realtime games only
|
|
Fields.clockInit -> game.clock.map(_.limitSeconds),
|
|
Fields.clockInc -> game.clock.map(_.incrementSeconds),
|
|
Fields.analysed -> analysed,
|
|
Fields.whiteUser -> game.whitePlayer.userId,
|
|
Fields.blackUser -> game.blackPlayer.userId,
|
|
Fields.source -> game.source.map(_.id)
|
|
)
|
|
.noNull
|
|
}
|