new attempt at getting rid of stalled analysis
This commit is contained in:
parent
e7f6e0a273
commit
6f29cc3272
|
@ -60,7 +60,7 @@ object Analyse extends LilaController {
|
|||
case Some(i) => fuccess(i.pgn)
|
||||
case None => for {
|
||||
pgn ← Env.game.pgnDump(game)
|
||||
analysis ← env.analyser get game.id
|
||||
analysis ← env.analyser getDone game.id
|
||||
} yield analysis.fold(pgn)(a => Env.analyse.annotator(pgn, a)).toString
|
||||
}) flatMap { content =>
|
||||
Env.game.pgnDump filename game map { filename =>
|
||||
|
|
|
@ -45,14 +45,13 @@ object Round extends LilaController with TheftPrevention {
|
|||
PreventTheft(pov) {
|
||||
env.version(pov.gameId) zip
|
||||
pov.opponent.userId.??(UserRepo.isEngine) zip
|
||||
(analyser has pov.gameId) zip
|
||||
(pov.game.tournamentId ?? TournamentRepo.byId) zip
|
||||
Env.game.crosstableApi(pov.game) zip
|
||||
(pov.game.hasChat optionFu {
|
||||
Env.chat.api.playerChat find pov.gameId map (_ forUser ctx.me)
|
||||
}) map {
|
||||
case (((((v, engine), analysed), tour), crosstable), chat) =>
|
||||
Ok(html.round.player(pov, v, engine, analysed,
|
||||
case ((((v, engine), tour), crosstable), chat) =>
|
||||
Ok(html.round.player(pov, v, engine,
|
||||
chat = chat, tour = tour, cross = crosstable))
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@(pov: Pov, version: Int, engine: Boolean, analysed: Boolean, chat: Option[lila.chat.MixedChat], tour: Option[lila.tournament.Tournament], cross: Option[lila.game.Crosstable])(implicit ctx: Context)
|
||||
@(pov: Pov, version: Int, engine: Boolean, chat: Option[lila.chat.MixedChat], tour: Option[lila.tournament.Tournament], cross: Option[lila.game.Crosstable])(implicit ctx: Context)
|
||||
|
||||
@import pov._
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<td>@tournamentLink(tour)</td>
|
||||
<td class="small">@tourMode(tour)</td>
|
||||
<td data-icon="p"> @tour.clock.show | @tour.durationString</td>
|
||||
<td data-icon="r"> @tour.nbPlayers</td>
|
||||
<td data-icon="r"> @tour.playerRatio</td>
|
||||
<td>@joinButton(tour)</td>
|
||||
</tr>
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import scala.concurrent.Future
|
|||
|
||||
import akka.actor.ActorSelection
|
||||
import akka.pattern.ask
|
||||
import org.joda.time.DateTime
|
||||
import chess.format.UciDump
|
||||
import chess.Replay
|
||||
|
||||
|
@ -16,9 +17,15 @@ import tube.analysisTube
|
|||
|
||||
final class Analyser(ai: ActorSelection, indexer: ActorSelection) {
|
||||
|
||||
def get(id: String): Fu[Option[Analysis]] = AnalysisRepo doneById id
|
||||
def get(id: String): Fu[Option[Analysis]] = AnalysisRepo byId id flatMap evictStalled
|
||||
|
||||
def has(id: String): Fu[Boolean] = AnalysisRepo isDone id
|
||||
def getDone(id: String): Fu[Option[Analysis]] = AnalysisRepo doneById id flatMap evictStalled
|
||||
|
||||
def evictStalled(oa: Option[Analysis]): Fu[Option[Analysis]] = oa ?? { a =>
|
||||
if (a.stalled) (AnalysisRepo remove a) inject none[Analysis] else fuccess(a.some)
|
||||
}
|
||||
|
||||
def hasDone(id: String): Fu[Boolean] = getDone(id) map (_.isDefined)
|
||||
|
||||
def hasMany(ids: Seq[String]): Fu[Set[String]] =
|
||||
$primitive[Analysis, String]($select byIds ids, "_id")(_.asOpt[String]) map (_.toSet)
|
||||
|
@ -40,7 +47,7 @@ final class Analyser(ai: ActorSelection, indexer: ActorSelection) {
|
|||
replay ← Replay(game.pgnMoves mkString " ", initialFen, game.variant).future
|
||||
uciMoves = UciDump(replay)
|
||||
infos ← ai ? lila.hub.actorApi.ai.Analyse(uciMoves, initialFen) mapTo manifest[List[Info]]
|
||||
analysis = Analysis(id, infos, true)
|
||||
analysis = Analysis(id, infos, true, DateTime.now)
|
||||
} yield UciToPgn(replay, analysis)) flatFold (
|
||||
e => fufail[Analysis](e.getMessage), {
|
||||
case (a, errors) => {
|
||||
|
|
|
@ -3,16 +3,19 @@ package lila.analyse
|
|||
import chess.Color
|
||||
import chess.format.Nag
|
||||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
case class Analysis(
|
||||
id: String,
|
||||
infos: List[Info],
|
||||
done: Boolean,
|
||||
date: DateTime,
|
||||
old: Boolean = false) {
|
||||
|
||||
lazy val infoAdvices: InfoAdvices = {
|
||||
(Info.start :: infos) sliding 2 collect {
|
||||
case List(prev, info) => info -> {
|
||||
(old || info.hasVariation) ?? Advice(prev, info)
|
||||
(old || info.hasVariation) ?? Advice(prev, info)
|
||||
}
|
||||
}
|
||||
}.toList
|
||||
|
@ -24,7 +27,7 @@ case class Analysis(
|
|||
i.best map { b => i.ply -> b.keys }
|
||||
}).flatten.toMap
|
||||
|
||||
def encode: RawAnalysis = RawAnalysis(id, encodeInfos, done)
|
||||
def encode: RawAnalysis = RawAnalysis(id, encodeInfos, done, date, old)
|
||||
private def encodeInfos = Info encodeList infos
|
||||
|
||||
def summary: List[(Color, List[(Nag, Int)])] = Color.all map { color =>
|
||||
|
@ -36,15 +39,17 @@ case class Analysis(
|
|||
}
|
||||
|
||||
def valid = encodeInfos.replace(";", "").nonEmpty
|
||||
|
||||
def stalled = (done && !valid) || (!done && date.isBefore(DateTime.now minusMinutes 20))
|
||||
}
|
||||
|
||||
object Analysis {
|
||||
|
||||
import lila.db.JsTube
|
||||
import lila.db.JsTube, JsTube.Helpers._
|
||||
import play.api.libs.json._
|
||||
|
||||
private[analyse] lazy val tube = JsTube(
|
||||
reader = Reads[Analysis](js =>
|
||||
reader = (__.json update readDate('date)) andThen Reads[Analysis](js =>
|
||||
~(for {
|
||||
obj ← js.asOpt[JsObject]
|
||||
rawAnalysis ← RawAnalysis.tube.read(obj).asOpt
|
||||
|
@ -53,16 +58,21 @@ object Analysis {
|
|||
),
|
||||
writer = Writes[Analysis](analysis =>
|
||||
RawAnalysis.tube.write(analysis.encode) getOrElse JsUndefined("[db] Can't write analysis " + analysis.id)
|
||||
)
|
||||
) andThen (__.json update writeDate('date))
|
||||
)
|
||||
}
|
||||
|
||||
private[analyse] case class RawAnalysis(id: String, data: String, done: Boolean, old: Boolean = false) {
|
||||
private[analyse] case class RawAnalysis(
|
||||
id: String,
|
||||
data: String,
|
||||
done: Boolean,
|
||||
date: DateTime,
|
||||
old: Boolean = false) {
|
||||
|
||||
def decode: Option[Analysis] = (done, data) match {
|
||||
case (true, "") => new Analysis(id, Nil, false, old).some
|
||||
case (true, d) => Info decodeList d map { new Analysis(id, _, done, old) }
|
||||
case (false, _) => new Analysis(id, Nil, false, old).some
|
||||
case (true, "") => new Analysis(id, Nil, false, date, old).some
|
||||
case (true, d) => Info decodeList d map { new Analysis(id, _, done, date, old) }
|
||||
case (false, _) => new Analysis(id, Nil, false, date, old).some
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ object AnalysisRepo {
|
|||
)) ++ $unset("old", "data"),
|
||||
upsert = true)
|
||||
|
||||
def byId(id: ID): Fu[Option[Analysis]] = $find byId id
|
||||
|
||||
def doneById(id: ID): Fu[Option[Analysis]] =
|
||||
$find.one($select(id) ++ Json.obj("done" -> true))
|
||||
|
||||
|
@ -59,4 +61,6 @@ object AnalysisRepo {
|
|||
$find($query(Json.obj("done" -> true)) skip skip, nb)
|
||||
|
||||
def count = $count($select.all)
|
||||
|
||||
def remove(a: Analysis) = $remove byId a.id
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ private[gameSearch] final class Indexer(
|
|||
case FinishGame(game, _, _) => self ! InsertGame(game)
|
||||
|
||||
case InsertGame(game) => if (storable(game)) {
|
||||
analyser has game.id foreach { analysed =>
|
||||
analyser hasDone game.id foreach { analysed =>
|
||||
client execute store(game, analysed)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue