lila/app/views/analyse/replay.scala.html

186 lines
6.5 KiB
HTML

@(pov: Pov, pgn: String, opening: Option[chess.OpeningExplorer.Opening], analysis: Option[lila.analyse.Analysis], advantageChart: Option[String], version: Int, chat: Option[lila.chat.UserChat], tour: Option[lila.tournament.Tournament], timeChart: lila.analyse.TimeChart, cross: Option[lila.game.Crosstable])(implicit ctx: Context)
@import pov._
@title = @{ s"${playerText(pov.player)} vs ${playerText(pov.opponent)} in $gameId : ${opening.fold(trans.replayAndAnalyse.str())(_.fullName)}" }
@moreCss = {
@cssTag("analyse.css")
}
@moreJs = {
@jsAt("vendor/pgn4web/pgn4web-compacted.js")
@jsTag("vendor/jquery.mousewheel.js")
@jsTagCompiled("pgn4hacks.js")
@highchartsTag
@jsTagCompiled("chart2.js")
@analysis.map { a =>
@embedJs(s"var lichess_best_moves=${toJson(a.bestMoves)};")
}
}
@underchat = {
@views.html.game.watchers()
<div class="shortcuts">
<p class="title" data-icon="u"> Keyboard Shortcuts</p>
<div class="inner">
<ul>
<li><strong>h</strong>/<strong>l</strong> or <strong></strong>/<strong></strong> move backward/forward</li>
<li><strong>j</strong>/<strong>k</strong> or <strong></strong>/<strong></strong> go to start/end</li>
<li><strong>i</strong>/<strong>o</strong> go to previous/next mistake</li>
<li><strong>p</strong> show/hide comments</li>
</ul>
You can also scroll over the board to move in the game.
</div>
</div>
}
@analyse.layout(
title = title,
side = views.html.game.side(pov, tour, withTourStanding = false).some,
chat = chat.map(c => base.chat(c, trans.spectatorRoom.str())),
underchat = underchat.some,
moreCss = moreCss,
moreJs = moreJs,
openGraph = povOpenGraph(pov)) {
<div class="analyse clearfix">
@if(ctx.blindMode) {
<div id="lichess_board_blind" data-href="@routes.Round.watcherText(gameId, color.name)">
@views.html.game.textualRepresentation(pov, false)
</div>
}
<div class="board_wrap">
<div
id="GameBoard"
data-version="@version"
data-socket-url="@routes.Round.websocketWatcher(gameId, color.name)"
class="@color.fold("", "flip") @pov.game.variant.key"></div>
<div class="game_control">
<a class="button flip hint--bottom" data-hint="@trans.flipBoard()" href="@routes.Round.watcher(gameId, (!color).name)#0">
<span data-icon="B"></span>
</a>
<a class="fen_link button hint--bottom" data-hint="@trans.boardEditor()" href="@routes.Editor.game(game.id)?fen=">
<span data-icon="m"></span>
</a>
<a class="continue button hint--bottom" data-hint="@trans.continueFromHere()" href="#">
<span data-icon="U"></span>
</a>
<div id="GameButtons"></div>
</div>
<div class="continue none">
<a class="fen_link button" href="@routes.Round.continue(game.id, "ai")?fen=">@trans.playWithTheMachine()</a>
<a class="fen_link button" href="@routes.Round.continue(game.id, "friend")?fen=">@trans.playWithAFriend()</a>
</div>
</div>
<div class="moves_wrap">
<div id="GameText" class="scroll-shadow-soft"></div>
@game.next.map { n =>
<p class="rematch_wrap">
<a class="button" href="@routes.Round.watcher(n, pov.opponent.color.name)" data-icon="G">&nbsp;@trans.viewRematch()</a>
</p>
}
<div class="advice_summary">
@round.blurs(game)
@round.holdAlerts(game)
@analysis.filter(_.done).map { a =>
<table>
@for((color, pairs) <- a.summary) {
<thead>
<tr>
<th colspan="3">
@playerLink(pov.game.player(color), withOnline = false, cssClass = Some("player color " + color.name))
</th>
</tr>
</thead>
@for((nag, nb) <- pairs) {
<tbody>
<tr>
<th>@nagName(nag)</th>
<td><strong>@nb</strong></td>
<td><strong>@("%.1f".format(100f * nb / pov.game.playerMoves(color)))</strong>%</td>
</tr>
</tbody>
}
}
</table>
}
</div>
</div>
</div>
<textarea id="pgnText" readonly="readonly">@Html(pgn)</textarea>
<div class="analysis_panels">
@if(game.analysable) {
<div class="panel computer_analysis">
@analysis.map { a =>
@advantageChart.map { chart =>
<div
id="adv_chart"
data-title="Advantage (up: white, down: black)"
data-max="@lila.analyse.AdvantageChart.max"
data-rows="@chart"></div>
}.getOrElse {
@analyse.computing()
}
}.getOrElse {
@if(analysis.isEmpty) {
<form class="future_game_analysis@if(ctx.isAnon) { must_login }" action="@routes.Analyse.requestAnalysis(gameId)" method="post">
<button type="submit" class="button"><span class="is3" data-icon="A"> @trans.requestAComputerAnalysis()</span></button>
</form>
}
}
<div class="view_game_analysis future_game_analysis" data-href="@routes.Round.watcher(pov.gameId, pov.color.name)">
<a class="button" href="@routes.Round.watcher(pov.gameId, pov.color.name)">
<span class="is3" data-icon="A"> @trans.viewTheComputerAnalysis()</span>
</a>
</div>
</div>
}
<div class="panel fen_pgn">
<p><strong>FEN</strong><input type="input" readonly="true" spellcheck="false" class="copyable fen" /></p>
<p><strong>PGN</strong>
<a data-icon="x" href="@routes.Export.pgn(game.id)"> Download annotated</a>
@if(analysis.isDefined) {
/
<a data-icon="x" href="@routes.Export.pgn(game.id)?as=raw"> Download raw</a>
}
@if(game.isPgnImport) {
/
<a data-icon="x" href="@routes.Export.pgn(game.id)?as=imported"> Download imported</a>
}
</p>
<div class="pgn">@Html(nl2br(escape(pgn)))</div>
</div>
<div class="panel move_times">
<div
id="movetimes_chart"
data-series="@timeChart.series"
data-max="@timeChart.maxTime"></div>
</div>
@cross.map { c =>
<div class="panel crosstable">
@views.html.game.crosstable(pov.player.userId.fold(c)(c.fromPov))
</div>
}
</div>
<div class="analysis_menu">
@if(game.analysable) {
<a data-panel="computer_analysis">@trans.computerAnalysis()</a>
}
@if(!game.isPgnImport) {
<a data-panel="move_times">@trans.moveTimes()</a>
@if(cross.isDefined) {
<a data-panel="crosstable">Crosstable</a>
}
}
<a data-panel="fen_pgn">FEN &amp; PGN</a>
<a target="_blank" href="@cdnUrl(routes.Export.pdf(game.id).url)">Print</a>
</div>
@analysis.filter(_.old && ctx.isAuth).map { a =>
<form class="better_analysis" action="@routes.Analyse.betterAnalysis(gameId, color.name)" method="post">
<button type="submit" class="button">
<span class="is3" data-icon="A"> Request a better computer analysis</span>
</button>
</form>
}
}