diff --git a/.gitmodules b/.gitmodules index 66b7eadf20..f6c2c412fc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "public/vendor/bar-rating"] path = public/vendor/bar-rating url = https://github.com/antennaio/jquery-bar-rating +[submodule "public/visualizer"] + path = public/visualizer + url = https://github.com/ornicar/chess_game_visualizer diff --git a/app/controllers/Export.scala b/app/controllers/Export.scala index 736e2ddbce..9f078e19be 100644 --- a/app/controllers/Export.scala +++ b/app/controllers/Export.scala @@ -18,24 +18,33 @@ object Export extends LilaController { def pgn(id: String) = Open { implicit ctx => OnlyHumans { lila.mon.export.pgn.game() - OptionFuResult(GameRepo game id) { - case game if game.playable => NotFound("Can't export PGN of game in progress").fuccess - case game => (game.pgnImport.ifTrue(get("as") contains "imported") match { - case Some(i) => fuccess(i.pgn) - case None => for { - initialFen <- GameRepo initialFen game - pgn = Env.api.pgnDump(game, initialFen) - analysis ← !get("as").contains("raw") ?? (Env.analyse.analyser get game.id) - } yield Env.analyse.annotator(pgn, analysis, game.opening, game.winnerColor, game.status, game.clock).toString - }) map { content => - Ok(content).withHeaders( - CONTENT_TYPE -> ContentTypes.TEXT, - CONTENT_DISPOSITION -> ("attachment; filename=" + (Env.api.pgnDump filename game))) - } + OptionFuResult(GameRepo game id) { game => + gameToPgn( + game, + asImported = get("as") contains "imported", + asRaw = get("as").contains("raw")) map { content => + Ok(content).withHeaders( + CONTENT_TYPE -> ContentTypes.TEXT, + CONTENT_DISPOSITION -> ("attachment; filename=" + (Env.api.pgnDump filename game))) + } recover { + case err => NotFound(err.getMessage) + } } } } + private def gameToPgn(from: GameModel, asImported: Boolean, asRaw: Boolean): Fu[String] = from match { + case game if game.playable => fufail("Can't export PGN of game in progress") + case game => (game.pgnImport.ifTrue(asImported) match { + case Some(i) => fuccess(i.pgn) + case None => for { + initialFen <- GameRepo initialFen game + pgn = Env.api.pgnDump(game, initialFen) + analysis ← !asRaw ?? (Env.analyse.analyser get game.id) + } yield Env.analyse.annotator(pgn, analysis, game.opening, game.winnerColor, game.status, game.clock).toString + }) + } + private val PdfRateLimitGlobal = new lila.memo.RateLimit( credits = 20, duration = 1 minute, @@ -74,6 +83,22 @@ object Export extends LilaController { } } + def visualizer(id: String) = Open { implicit ctx => + OptionFuResult(GameRepo game id) { game => + gameToPgn(game, asImported = true, asRaw = true) map { pgn => + lila.mon.export.visualizer() + Redirect { + import lila.api.Env.current.Net._ + val base = s"$Protocol$AssetDomain/assets" + val encoded = java.net.URLEncoder.encode(pgn.toString, "UTF-8") + s"$base/visualizer/index_lichess.html?pgn=$encoded" + } + } recoverWith { + case _: Exception => notFound + } + } + } + def puzzlePng(id: Int) = Open { implicit ctx => OnlyHumansAndFacebook { PngRateLimitGlobal("-", msg = HTTPRequest lastRemoteAddress ctx.req) { diff --git a/app/views/analyse/replay.scala.html b/app/views/analyse/replay.scala.html index f590ae6ddb..53e440a288 100644 --- a/app/views/analyse/replay.scala.html +++ b/app/views/analyse/replay.scala.html @@ -64,17 +64,19 @@ atom = atom.some) {
FEN
PGN - @trans.downloadAnnotated() + @trans.downloadAnnotated() @if(analysis.isDefined) { / - @trans.downloadRaw() + @trans.downloadRaw() } @if(game.isPgnImport) { / - @trans.downloadImported() + @trans.downloadImported() } / - @trans.printFriendlyPDF() + @trans.printFriendlyPDF() + / + Generate images