more puzzle UI WIP
This commit is contained in:
parent
1d838ff770
commit
ffc73161eb
|
@ -1,6 +1,7 @@
|
|||
@(title: String, evenMoreCss: Option[Html] = None, evenMoreJs: Option[Html] = None, openGraph: Option[lila.app.ui.OpenGraph] = None)(body: Html)(implicit ctx: Context)
|
||||
|
||||
@moreCss = {
|
||||
@cssTag("analyse.css")
|
||||
@cssTag("puzzle.css")
|
||||
@evenMoreCss
|
||||
}
|
||||
|
|
|
@ -21,5 +21,5 @@ description = s"Tactic puzzle #${puzzle.id}: " + puzzle.color.fold(
|
|||
trans.findTheBestMoveForWhite,
|
||||
trans.findTheBestMoveForBlack
|
||||
).str() + s" Played by ${puzzle.attempts} players.").some) {
|
||||
<div class="puzzle_app cg-512">@miniBoardContent</div>
|
||||
<div id="puzzle" class="cg-512">@miniBoardContent</div>
|
||||
}
|
||||
|
|
|
@ -11,26 +11,30 @@ object GameJson {
|
|||
|
||||
import lila.game.JsonView._
|
||||
|
||||
private val cache = lila.memo.AsyncCache[Game.ID, JsObject](
|
||||
case class CacheKey(gameId: Game.ID, plies: Int)
|
||||
|
||||
private val cache = lila.memo.AsyncCache[CacheKey, JsObject](
|
||||
name = "puzzle.gameJson",
|
||||
f = generate,
|
||||
maxCapacity = 500)
|
||||
|
||||
def apply(gameId: Game.ID): Fu[JsObject] = cache(gameId)
|
||||
def apply(gameId: Game.ID, plies: Int): Fu[JsObject] = cache(CacheKey(gameId, plies))
|
||||
|
||||
def generate(gameId: Game.ID): Fu[JsObject] =
|
||||
(GameRepo game gameId).flatten(s"Missing puzzle game $gameId!") map { game =>
|
||||
Json.obj(
|
||||
"id" -> game.id,
|
||||
"speed" -> game.speed.key,
|
||||
"perf" -> PerfPicker.key(game),
|
||||
"rated" -> game.rated,
|
||||
"winner" -> game.winnerColor.map(_.name),
|
||||
"turns" -> game.turns,
|
||||
"status" -> game.status,
|
||||
"tournamentId" -> game.tournamentId,
|
||||
"createdAt" -> game.createdAt,
|
||||
"treeParts" -> partitionTreeJsonWriter.writes(TreeBuilder(game))
|
||||
).noNull
|
||||
}
|
||||
def generate(ck: CacheKey): Fu[JsObject] = ck match {
|
||||
case CacheKey(gameId, plies) =>
|
||||
(GameRepo game gameId).flatten(s"Missing puzzle game $gameId!") map { game =>
|
||||
Json.obj(
|
||||
"id" -> game.id,
|
||||
"speed" -> game.speed.key,
|
||||
"perf" -> PerfPicker.key(game),
|
||||
"rated" -> game.rated,
|
||||
"winner" -> game.winnerColor.map(_.name),
|
||||
"turns" -> game.turns,
|
||||
"status" -> game.status,
|
||||
"tournamentId" -> game.tournamentId,
|
||||
"createdAt" -> game.createdAt,
|
||||
"treeParts" -> partitionTreeJsonWriter.writes(TreeBuilder(game, plies))
|
||||
).noNull
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ object JsonView {
|
|||
round: Option[Round] = None,
|
||||
win: Option[Boolean] = None,
|
||||
voted: Option[Boolean]): Fu[JsObject] =
|
||||
(!isMobileApi ?? GameJson(puzzle.gameId).map(_.some)) map { gameJson =>
|
||||
(!isMobileApi ?? GameJson(puzzle.gameId, puzzle.initialPly).map(_.some)) map { gameJson =>
|
||||
Json.obj(
|
||||
"game" -> gameJson,
|
||||
"puzzle" -> Json.obj(
|
||||
|
|
|
@ -19,9 +19,7 @@ case class Puzzle(
|
|||
attempts: Int,
|
||||
mate: Boolean) {
|
||||
|
||||
def initialPly: Option[Int] = fen.split(' ').lastOption flatMap parseIntOption map { move =>
|
||||
move * 2 + color.fold(0, 1)
|
||||
}
|
||||
def initialPly: Int = history.size
|
||||
|
||||
def withVote(f: AggregateVote => AggregateVote) = copy(vote = f(vote))
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ object TreeBuilder {
|
|||
|
||||
private type Ply = Int
|
||||
|
||||
def apply(game: Game): tree.Root = {
|
||||
chess.Replay.gameMoveWhileValid(game.pgnMoves, Forsyth.initial, game.variant) match {
|
||||
def apply(game: Game, plies: Int): tree.Root = {
|
||||
chess.Replay.gameMoveWhileValid(game.pgnMoves take plies, Forsyth.initial, game.variant) match {
|
||||
case (init, games, error) =>
|
||||
error foreach logChessError(game.id)
|
||||
val fen = Forsyth >> init
|
||||
|
|
|
@ -2009,7 +2009,7 @@ lichess.notifyApp = (function() {
|
|||
|
||||
function startPuzzle(cfg) {
|
||||
var puzzle;
|
||||
cfg.element = document.querySelector('#lichess .puzzle_app');
|
||||
cfg.element = document.querySelector('#puzzle');
|
||||
cfg.sideElement = document.querySelector('#site_header .side_box');
|
||||
lichess.socket = lichess.StrongSocket('/socket', 0, {
|
||||
options: {
|
||||
|
|
|
@ -1,16 +1,3 @@
|
|||
div.board_wrap {
|
||||
float: left;
|
||||
width: 514px;
|
||||
min-height: 558px;
|
||||
}
|
||||
div.moves_wrap {
|
||||
margin-left: 532px;
|
||||
position: relative;
|
||||
}
|
||||
p.rematch_wrap {
|
||||
margin-top: 31px;
|
||||
text-align: center;
|
||||
}
|
||||
div.analysis_menu {
|
||||
text-align: center;
|
||||
border-top: 1px solid #c0c0c0;
|
||||
|
|
251
public/stylesheets/puzzle-old.css
Normal file
251
public/stylesheets/puzzle-old.css
Normal file
|
@ -0,0 +1,251 @@
|
|||
#puzzle {
|
||||
position: relative;
|
||||
min-height: 600px;
|
||||
}
|
||||
#puzzle .board_and_ground {
|
||||
display: flex;
|
||||
}
|
||||
#puzzle div.box {
|
||||
margin-bottom: 1em;
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
}
|
||||
#puzzle > .side {
|
||||
position: absolute;
|
||||
top: 64px;
|
||||
left: -222px;
|
||||
width: 212px;
|
||||
}
|
||||
#puzzle > .side h1 {
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#puzzle > .side div.box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#puzzle div.box > p, div.training div.box > div {
|
||||
line-height: 1.8em;
|
||||
}
|
||||
#puzzle > .side .register {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#puzzle > .side .register .signup {
|
||||
margin: 1em auto;
|
||||
text-align: center;
|
||||
}
|
||||
#puzzle > .side .user_chart {
|
||||
margin: 0 0 -10px -9px;
|
||||
}
|
||||
#puzzle > .side .chart_container {
|
||||
margin-top: 30px;
|
||||
}
|
||||
#puzzle > .side .chart_container p {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
#puzzle div.comment {
|
||||
padding: 10px 5px;
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
#puzzle div.comment h3 {
|
||||
font-size: inherit;
|
||||
margin: 4px;
|
||||
display: block;
|
||||
}
|
||||
#puzzle .comment.great,
|
||||
#puzzle .comment.win {
|
||||
background: #DFF0D8;
|
||||
color: #3c763d;
|
||||
}
|
||||
#puzzle .comment.loss,
|
||||
#puzzle .comment.fail {
|
||||
color: #a94442;
|
||||
background: #ebccd1;
|
||||
}
|
||||
#puzzle .comment .rating {
|
||||
font-size: 2em;
|
||||
vertical-align: -3px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
#puzzle > .center {
|
||||
width: 512px;
|
||||
}
|
||||
#puzzle .right {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
padding-left: 15px;
|
||||
width: 242px;
|
||||
}
|
||||
#puzzle .right .spinner {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
#puzzle .right .box input {
|
||||
width: 214px;
|
||||
}
|
||||
#puzzle .right h2 {
|
||||
font-size: 1.4em;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
#puzzle .please_vote {
|
||||
background: #DFF0D8;
|
||||
color: #3c763d;
|
||||
margin-bottom: 1em;
|
||||
text-align: center;
|
||||
padding: 10px 5px;
|
||||
}
|
||||
#puzzle .please_vote .then,
|
||||
#puzzle .please_vote.thanks .first {
|
||||
display: none;
|
||||
}
|
||||
#puzzle .please_vote.thanks .then {
|
||||
display: block;
|
||||
}
|
||||
#puzzle .right .player {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
#puzzle .right .no-square {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.is3d #puzzle .right div.no-square {
|
||||
height: 82px;
|
||||
}
|
||||
#puzzle .right piece {
|
||||
position: inherit;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#puzzle .right .instruction > * {
|
||||
display: block;
|
||||
}
|
||||
#puzzle .right .instruction strong {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
#puzzle .right .control {
|
||||
text-align: center;
|
||||
font-size: 1.3em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#puzzle .right .control .giveup {
|
||||
visibility: hidden;
|
||||
font-weight: normal;
|
||||
transition: 1s;
|
||||
opacity: 0;
|
||||
}
|
||||
#puzzle .right .control .giveup.revealed {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
#puzzle .right .continue_wrap {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#puzzle .right .retry {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#puzzle .right .continue {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#puzzle .game_control {
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
#puzzle .game_control a {
|
||||
font-size: 16px;
|
||||
height: 22px;
|
||||
display:inline-block;
|
||||
}
|
||||
#puzzle #GameButtons {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
#puzzle #GameButtons a {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
margin-left: -2px;
|
||||
margin-right: -3px;
|
||||
}
|
||||
#puzzle #GameButtons a.disabled::before {
|
||||
opacity: 0.5;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
#puzzle div.upvote {
|
||||
float: right;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
#puzzle div.upvote a {
|
||||
cursor: default;
|
||||
}
|
||||
#puzzle div.upvote.enabled a {
|
||||
cursor: pointer;
|
||||
}
|
||||
#puzzle div.upvote a {
|
||||
font-size: 24px;
|
||||
}
|
||||
#puzzle div.upvote.enabled a:hover,
|
||||
#puzzle div.upvote a.active {
|
||||
color: #d85000;
|
||||
}
|
||||
#puzzle div.upvote span.count {
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
#puzzle .undertable td {
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
#puzzle .timeline {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
}
|
||||
#puzzle .timeline > * {
|
||||
flex: 1 0;
|
||||
background: #ccc;
|
||||
color: #fff;
|
||||
margin-left: 1px;
|
||||
box-sizing: border-box;
|
||||
opacity: 0.8;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
body.dark #puzzle .timeline > * {
|
||||
background: #444;
|
||||
}
|
||||
#puzzle .timeline a:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
#puzzle .timeline a:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
#puzzle .timeline a.current {
|
||||
background: #3893E8;
|
||||
}
|
||||
#puzzle .timeline a.win {
|
||||
background: #759900;
|
||||
}
|
||||
#puzzle .timeline a.loss {
|
||||
background: #dc322f;
|
||||
}
|
||||
#puzzle .timeline a.new {
|
||||
background: #fff;
|
||||
color: #444;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
body.dark #puzzle .timeline a.new {
|
||||
background: #555;
|
||||
color: #ddd;
|
||||
}
|
|
@ -1,213 +1,7 @@
|
|||
#puzzle {
|
||||
position: relative;
|
||||
min-height: 600px;
|
||||
}
|
||||
#puzzle .board_and_ground {
|
||||
display: flex;
|
||||
}
|
||||
#puzzle div.box {
|
||||
margin-bottom: 1em;
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
}
|
||||
#puzzle > .side {
|
||||
position: absolute;
|
||||
top: 64px;
|
||||
left: -222px;
|
||||
width: 212px;
|
||||
}
|
||||
#puzzle > .side h1 {
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#puzzle > .side div.box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#puzzle div.box > p, div.training div.box > div {
|
||||
line-height: 1.8em;
|
||||
}
|
||||
#puzzle > .side .register {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#puzzle > .side .register .signup {
|
||||
margin: 1em auto;
|
||||
text-align: center;
|
||||
}
|
||||
#puzzle > .side .user_chart {
|
||||
margin: 0 0 -10px -9px;
|
||||
}
|
||||
#puzzle > .side .chart_container {
|
||||
margin-top: 30px;
|
||||
}
|
||||
#puzzle > .side .chart_container p {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
#puzzle div.comment {
|
||||
padding: 10px 5px;
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
#puzzle div.comment h3 {
|
||||
font-size: inherit;
|
||||
margin: 4px;
|
||||
display: block;
|
||||
}
|
||||
#puzzle .comment.great,
|
||||
#puzzle .comment.win {
|
||||
background: #DFF0D8;
|
||||
color: #3c763d;
|
||||
}
|
||||
#puzzle .comment.loss,
|
||||
#puzzle .comment.fail {
|
||||
color: #a94442;
|
||||
background: #ebccd1;
|
||||
}
|
||||
#puzzle .comment .rating {
|
||||
font-size: 2em;
|
||||
vertical-align: -3px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
#puzzle > .center {
|
||||
width: 512px;
|
||||
}
|
||||
#puzzle .right {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
padding-left: 15px;
|
||||
width: 242px;
|
||||
}
|
||||
#puzzle .right .spinner {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
#puzzle .right .box input {
|
||||
width: 214px;
|
||||
}
|
||||
#puzzle .right h2 {
|
||||
font-size: 1.4em;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
#puzzle .please_vote {
|
||||
background: #DFF0D8;
|
||||
color: #3c763d;
|
||||
margin-bottom: 1em;
|
||||
text-align: center;
|
||||
padding: 10px 5px;
|
||||
}
|
||||
#puzzle .please_vote .then,
|
||||
#puzzle .please_vote.thanks .first {
|
||||
display: none;
|
||||
}
|
||||
#puzzle .please_vote.thanks .then {
|
||||
display: block;
|
||||
}
|
||||
#puzzle .right .player {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
#puzzle .right .no-square {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.is3d #puzzle .right div.no-square {
|
||||
height: 82px;
|
||||
}
|
||||
#puzzle .right piece {
|
||||
position: inherit;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#puzzle .right .instruction > * {
|
||||
display: block;
|
||||
}
|
||||
#puzzle .right .instruction strong {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
#puzzle .right .control {
|
||||
text-align: center;
|
||||
font-size: 1.3em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#puzzle .right .control .giveup {
|
||||
visibility: hidden;
|
||||
font-weight: normal;
|
||||
transition: 1s;
|
||||
opacity: 0;
|
||||
}
|
||||
#puzzle .right .control .giveup.revealed {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
#puzzle .right .continue_wrap {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#puzzle .right .retry {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#puzzle .right .continue {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#puzzle .game_control {
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
#puzzle .game_control a {
|
||||
font-size: 16px;
|
||||
height: 22px;
|
||||
display:inline-block;
|
||||
}
|
||||
#puzzle #GameButtons {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
#puzzle #GameButtons a {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
margin-left: -2px;
|
||||
margin-right: -3px;
|
||||
}
|
||||
#puzzle #GameButtons a.disabled::before {
|
||||
opacity: 0.5;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
#puzzle div.upvote {
|
||||
float: right;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
#puzzle div.upvote a {
|
||||
cursor: default;
|
||||
}
|
||||
#puzzle div.upvote.enabled a {
|
||||
cursor: pointer;
|
||||
}
|
||||
#puzzle div.upvote a {
|
||||
font-size: 24px;
|
||||
}
|
||||
#puzzle div.upvote.enabled a:hover,
|
||||
#puzzle div.upvote a.active {
|
||||
color: #d85000;
|
||||
}
|
||||
#puzzle div.upvote span.count {
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
#puzzle .undertable td {
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#puzzle .timeline {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
|
|
26
ui/puzzle/src/control.js
Normal file
26
ui/puzzle/src/control.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
var treePath = require('tree').path;
|
||||
|
||||
module.exports = {
|
||||
|
||||
canGoForward: function(ctrl) {
|
||||
return ctrl.vm.node.children.length > 0;
|
||||
},
|
||||
|
||||
next: function(ctrl) {
|
||||
var child = ctrl.vm.node.children[0];
|
||||
if (!child) return;
|
||||
ctrl.userJump(ctrl.vm.path + child.id);
|
||||
},
|
||||
|
||||
prev: function(ctrl) {
|
||||
ctrl.userJump(treePath.init(ctrl.vm.path));
|
||||
},
|
||||
|
||||
last: function(ctrl) {
|
||||
ctrl.userJump(treePath.fromNodeList(ctrl.vm.mainline));
|
||||
},
|
||||
|
||||
first: function(ctrl) {
|
||||
ctrl.userJump(treePath.root);
|
||||
}
|
||||
};
|
|
@ -1,10 +1,12 @@
|
|||
var m = require('mithril');
|
||||
var treeBuild = require('tree').build;
|
||||
var treeOps = require('tree').ops;
|
||||
var treePath = require('tree').path;
|
||||
var cevalCtrl = require('ceval').ctrl;
|
||||
var readDests = require('chess').readDests;
|
||||
var k = Mousetrap;
|
||||
var chessground = require('chessground');
|
||||
var keyboard = require('./keyboard');
|
||||
var opposite = chessground.util.opposite;
|
||||
var groundBuild = require('./ground');
|
||||
var socketBuild = require('./socket');
|
||||
|
@ -22,6 +24,7 @@ module.exports = function(opts, i18n) {
|
|||
var data = opts.data;
|
||||
var tree = treeBuild(treeOps.reconstruct(opts.data.game.treeParts));
|
||||
var ground;
|
||||
var ceval;
|
||||
|
||||
var setPath = function(path) {
|
||||
vm.path = path;
|
||||
|
@ -30,7 +33,7 @@ module.exports = function(opts, i18n) {
|
|||
vm.mainline = treeOps.mainlineNodeList(tree.root);
|
||||
};
|
||||
|
||||
setPath('');
|
||||
setPath(treePath.fromNodeList(treeOps.mainlineNodeList(tree.root)));
|
||||
|
||||
var showGround = function() {
|
||||
var node = vm.node;
|
||||
|
@ -93,6 +96,34 @@ module.exports = function(opts, i18n) {
|
|||
ground.playPremove();
|
||||
};
|
||||
|
||||
var instanciateCeval = function(failsafe) {
|
||||
ceval = cevalCtrl({
|
||||
variant: data.game.variant,
|
||||
possible: true,
|
||||
emit: function(res) {
|
||||
tree.updateAt(res.work.path, function(node) {
|
||||
if (node.ceval && node.ceval.depth >= res.eval.depth) return;
|
||||
node.ceval = res.eval;
|
||||
// if (res.work.path === vm.path) {
|
||||
// setAutoShapes();
|
||||
// m.redraw();
|
||||
// }
|
||||
});
|
||||
},
|
||||
setAutoShapes: $.noop,
|
||||
failsafe: failsafe,
|
||||
onCrash: function(e) {
|
||||
console.log('Local eval failed!', e);
|
||||
if (ceval.pnaclSupported) {
|
||||
console.log('Retrying in failsafe mode');
|
||||
instanciateCeval(true);
|
||||
startCeval();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
instanciateCeval();
|
||||
|
||||
var gameOver = function() {
|
||||
if (vm.node.dests !== '') return false;
|
||||
if (vm.node.check) {
|
||||
|
@ -139,6 +170,11 @@ module.exports = function(opts, i18n) {
|
|||
|
||||
showGround();
|
||||
|
||||
keyboard.bind({
|
||||
vm: vm,
|
||||
userJump: userJump
|
||||
});
|
||||
|
||||
console.log(data);
|
||||
|
||||
return {
|
||||
|
|
|
@ -29,7 +29,7 @@ function makeConfig(data, config, onMove) {
|
|||
},
|
||||
animation: {
|
||||
enabled: true,
|
||||
duration: data.pref.animationDuration
|
||||
duration: data.animation.duration
|
||||
},
|
||||
disableContextMenu: true
|
||||
};
|
||||
|
|
37
ui/puzzle/src/keyboard.js
Normal file
37
ui/puzzle/src/keyboard.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
var control = require('./control');
|
||||
var m = require('mithril');
|
||||
|
||||
function preventing(f) {
|
||||
return function(e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// internet explorer
|
||||
e.returnValue = false;
|
||||
}
|
||||
f();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bind: function(ctrl) {
|
||||
if (!window.Mousetrap) return;
|
||||
var kbd = window.Mousetrap;
|
||||
kbd.bind(['left', 'k'], preventing(function() {
|
||||
control.prev(ctrl);
|
||||
m.redraw();
|
||||
}));
|
||||
kbd.bind(['right', 'j'], preventing(function() {
|
||||
control.next(ctrl);
|
||||
m.redraw();
|
||||
}));
|
||||
kbd.bind(['up', '0'], preventing(function() {
|
||||
control.first(ctrl);
|
||||
m.redraw();
|
||||
}));
|
||||
kbd.bind(['down', '$'], preventing(function() {
|
||||
control.last(ctrl);
|
||||
m.redraw();
|
||||
}));
|
||||
}
|
||||
};
|
|
@ -1,6 +1,8 @@
|
|||
var m = require('mithril');
|
||||
var chessground = require('chessground');
|
||||
var bindOnce = require('common').bindOnce;
|
||||
var treeView = require('./treeView');
|
||||
var control = require('./control');
|
||||
|
||||
function renderOpeningBox(ctrl) {
|
||||
var opening = ctrl.tree.getOpening(ctrl.vm.nodeList);
|
||||
|
@ -45,6 +47,46 @@ function visualBoard(ctrl) {
|
|||
]);
|
||||
}
|
||||
|
||||
function dataAct(e) {
|
||||
return e.target.getAttribute('data-act') ||
|
||||
e.target.parentNode.getAttribute('data-act');
|
||||
}
|
||||
|
||||
function jumpButton(icon, effect) {
|
||||
return {
|
||||
tag: 'button',
|
||||
attrs: {
|
||||
'data-act': effect,
|
||||
'data-icon': icon
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var cachedButtons = (function() {
|
||||
return m('div.jumps', [
|
||||
jumpButton('W', 'first'),
|
||||
jumpButton('Y', 'prev'),
|
||||
jumpButton('X', 'next'),
|
||||
jumpButton('V', 'last')
|
||||
])
|
||||
})();
|
||||
|
||||
function buttons(ctrl) {
|
||||
return m('div.game_control', {
|
||||
config: bindOnce('mousedown', function(e) {
|
||||
var action = dataAct(e);
|
||||
if (action === 'prev') control.prev(ctrl);
|
||||
else if (action === 'next') control.next(ctrl);
|
||||
else if (action === 'first') control.first(ctrl);
|
||||
else if (action === 'last') control.last(ctrl);
|
||||
// else if (action === 'explorer') ctrl.explorer.toggle();
|
||||
// else if (action === 'menu') ctrl.actionMenu.toggle();
|
||||
})
|
||||
}, [
|
||||
cachedButtons
|
||||
]);
|
||||
}
|
||||
|
||||
var firstRender = true;
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
|
@ -66,7 +108,7 @@ module.exports = function(ctrl) {
|
|||
// cevalView.renderCeval(ctrl),
|
||||
// cevalView.renderPvs(ctrl),
|
||||
renderAnalyse(ctrl),
|
||||
// buttons(ctrl)
|
||||
buttons(ctrl)
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
|
Loading…
Reference in a new issue