implement literate PGN export

This commit is contained in:
Thibault Duplessis 2018-05-09 19:16:47 +02:00
parent d702766e76
commit 54fbb92d68
7 changed files with 21 additions and 14 deletions

View file

@ -54,7 +54,7 @@ object Analyse extends LilaController {
pov, pov,
data, data,
initialFen, initialFen,
Env.analyse.annotator(pgn, analysis, pov.game.opening, pov.game.winnerColor, pov.game.status, pov.game.clock).toString, Env.analyse.annotator(pgn, analysis, pov.game.opening, pov.game.winnerColor, pov.game.status).toString,
analysis, analysis,
analysisInProgress, analysisInProgress,
simul, simul,
@ -104,7 +104,7 @@ object Analyse extends LilaController {
} yield Ok(html.analyse.replayBot( } yield Ok(html.analyse.replayBot(
pov, pov,
initialFen, initialFen,
Env.analyse.annotator(pgn, analysis, pov.game.opening, pov.game.winnerColor, pov.game.status, pov.game.clock).toString, Env.analyse.annotator(pgn, analysis, pov.game.opening, pov.game.winnerColor, pov.game.status).toString,
analysis, analysis,
simul, simul,
crosstable crosstable

View file

@ -72,14 +72,16 @@ object Game extends LilaController {
perfType = ~get("perfType", req) split "," flatMap { lila.rating.PerfType(_) } toSet, perfType = ~get("perfType", req) split "," flatMap { lila.rating.PerfType(_) } toSet,
color = get("color", req) flatMap chess.Color.apply, color = get("color", req) flatMap chess.Color.apply,
analysed = getBoolOpt("analysed", req), analysed = getBoolOpt("analysed", req),
flags = requestPgnFlags(req, extended = false), flags = requestPgnFlags(req, extended = false).copy(
literate = false
),
perSecond = MaxPerSecond(me match { perSecond = MaxPerSecond(me match {
case Some(m) if m is user.id => 50 case Some(m) if m is user.id => 50
case Some(_) if oauth => 20 // bonus for oauth logged in only (not for XSRF) case Some(_) if oauth => 20 // bonus for oauth logged in only (not for XSRF)
case _ => 10 case _ => 10
}) })
) )
val date = (DateTimeFormat forPattern "yyyy-MM-dd") print new DateTime val date = DateTimeFormat forPattern "yyyy-MM-dd" print new DateTime
Ok.chunked(Env.api.gameApiV2.exportByUser(config)).withHeaders( Ok.chunked(Env.api.gameApiV2.exportByUser(config)).withHeaders(
CONTENT_TYPE -> gameContentType(config), CONTENT_TYPE -> gameContentType(config),
CONTENT_DISPOSITION -> s"attachment; filename=lichess_${user.username}_$date.${format.toString.toLowerCase}" CONTENT_DISPOSITION -> s"attachment; filename=lichess_${user.username}_$date.${format.toString.toLowerCase}"
@ -120,7 +122,8 @@ object Game extends LilaController {
tags = getBoolOpt("tags", req) | true, tags = getBoolOpt("tags", req) | true,
clocks = getBoolOpt("clocks", req) | extended, clocks = getBoolOpt("clocks", req) | extended,
evals = getBoolOpt("evals", req) | extended, evals = getBoolOpt("evals", req) | extended,
opening = getBoolOpt("opening", req) | extended opening = getBoolOpt("opening", req) | extended,
literate = getBoolOpt("literate", req) | false
) )
private def gameContentType(config: GameApiV2.Config) = config.format match { private def gameContentType(config: GameApiV2.Config) = config.format match {

View file

@ -69,7 +69,7 @@ atom = atom.some) {
<div class="pgn_options"> <div class="pgn_options">
<strong>PGN</strong> <strong>PGN</strong>
<div> <div>
<a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)">@trans.downloadAnnotated()</a> <a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)?literate=1">@trans.downloadAnnotated()</a>
<a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)?evals=0&clocks=0">@trans.downloadRaw()</a> <a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)?evals=0&clocks=0">@trans.downloadRaw()</a>
@if(game.isPgnImport) { @if(game.isPgnImport) {
<a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)?imported=1">@trans.downloadImported()</a> <a data-icon="x" class="text" rel="nofollow" href="@routes.Game.exportOne(game.id)?imported=1">@trans.downloadImported()</a>

View file

@ -4,15 +4,14 @@ import chess.format.pgn.{ Pgn, Tag, Turn, Move, Glyphs }
import chess.opening._ import chess.opening._
import chess.{ Status, Color, Clock } import chess.{ Status, Color, Clock }
private[analyse] final class Annotator(netDomain: String) { final class Annotator(netDomain: String) {
def apply( def apply(
p: Pgn, p: Pgn,
analysis: Option[Analysis], analysis: Option[Analysis],
opening: Option[FullOpening.AtPly], opening: Option[FullOpening.AtPly],
winner: Option[Color], winner: Option[Color],
status: Status, status: Status
clock: Option[Clock]
): Pgn = ): Pgn =
annotateStatus(winner, status) { annotateStatus(winner, status) {
annotateOpening(opening) { annotateOpening(opening) {
@ -38,7 +37,7 @@ private[analyse] final class Annotator(netDomain: String) {
turn.update(advice.color, move => turn.update(advice.color, move =>
move.copy( move.copy(
glyphs = Glyphs.fromList(advice.judgment.glyph :: Nil), glyphs = Glyphs.fromList(advice.judgment.glyph :: Nil),
comments = List(advice.makeComment(true, true)), comments = advice.makeComment(true, true) :: move.comments,
variations = makeVariation(turn, advice) :: Nil variations = makeVariation(turn, advice) :: Nil
))) )))
} }

View file

@ -23,7 +23,7 @@ final class Env(
gamePgnDump: lila.game.PgnDump, gamePgnDump: lila.game.PgnDump,
gameCache: lila.game.Cached, gameCache: lila.game.Cached,
userEnv: lila.user.Env, userEnv: lila.user.Env,
analyseEnv: lila.analyse.Env, annotator: lila.analyse.Annotator,
lobbyEnv: lila.lobby.Env, lobbyEnv: lila.lobby.Env,
setupEnv: lila.setup.Env, setupEnv: lila.setup.Env,
getSimul: Simul.ID => Fu[Option[Simul]], getSimul: Simul.ID => Fu[Option[Simul]],
@ -84,6 +84,7 @@ final class Env(
val pgnDump = new PgnDump( val pgnDump = new PgnDump(
dumper = gamePgnDump, dumper = gamePgnDump,
annotator = annotator,
getSimulName = getSimulName, getSimulName = getSimulName,
getTournamentName = getTournamentName getTournamentName = getTournamentName
) )
@ -163,7 +164,7 @@ object Env {
settingStore = lila.memo.Env.current.settingStore, settingStore = lila.memo.Env.current.settingStore,
renderer = lila.hub.Env.current.actor.renderer, renderer = lila.hub.Env.current.actor.renderer,
userEnv = lila.user.Env.current, userEnv = lila.user.Env.current,
analyseEnv = lila.analyse.Env.current, annotator = lila.analyse.Env.current.annotator,
lobbyEnv = lila.lobby.Env.current, lobbyEnv = lila.lobby.Env.current,
setupEnv = lila.setup.Env.current, setupEnv = lila.setup.Env.current,
getSimul = lila.simul.Env.current.repo.find, getSimul = lila.simul.Env.current.repo.find,

View file

@ -12,6 +12,7 @@ import lila.game.{ Game, GameRepo, Query }
final class PgnDump( final class PgnDump(
val dumper: lila.game.PgnDump, val dumper: lila.game.PgnDump,
annotator: Annotator,
getSimulName: String => Fu[Option[String]], getSimulName: String => Fu[Option[String]],
getTournamentName: String => Option[String] getTournamentName: String => Option[String]
) { ) {
@ -23,7 +24,9 @@ final class PgnDump(
} }
else fuccess(pgn) else fuccess(pgn)
} map { pgn => } map { pgn =>
analysis.ifTrue(flags.evals).fold(pgn)(addEvals(pgn, _)) val evaled = analysis.ifTrue(flags.evals).fold(pgn)(addEvals(pgn, _))
if (flags.literate) annotator(evaled, analysis, game.opening, game.winnerColor, game.status)
else evaled
} }
private def addEvals(p: Pgn, analysis: Analysis): Pgn = analysis.infos.foldLeft(p) { private def addEvals(p: Pgn, analysis: Analysis): Pgn = analysis.infos.foldLeft(p) {

View file

@ -138,7 +138,8 @@ object PgnDump {
moves: Boolean = true, moves: Boolean = true,
tags: Boolean = true, tags: Boolean = true,
evals: Boolean = true, evals: Boolean = true,
opening: Boolean = true opening: Boolean = true,
literate: Boolean = false
) )
def result(game: Game) = def result(game: Game) =