-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Analysis/study page keyboard input #15019
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5f2dd8b
dd7573f
f5663ad
03a4439
269431f
d899200
e677a01
4a83260
5cfc135
c5b80c1
e11dc11
7da7fd8
b550956
17bf59c
d47eca7
4298eb9
5059e3e
6f17c16
42bbde4
fcbf24f
a5558c1
10b0d24
66f4608
1a4004b
06b84be
7f4517e
862a8d5
70fa45e
eda9c79
104f937
bad525a
b32612e
812f0c7
650176c
f45c60e
dca9c2e
d57c5fd
a31f327
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,8 @@ | ||
| .analyse__underboard { | ||
| margin-top: calc($analyse-block-gap / 2); | ||
| } | ||
|
|
||
| .analyse .keyboard-move { | ||
| margin-top: calc($analyse-block-gap * 2); | ||
ornicar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| margin-bottom: calc($analyse-block-gap * -1); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,8 @@ import { uciToMove } from 'chessground/util'; | |
| import Persistence from './persistence'; | ||
| import pgnImport from './pgnImport'; | ||
| import ForecastCtrl from './forecast/forecastCtrl'; | ||
| import { ArrowKey, KeyboardMove, ctrl as makeKeyboardMove } from 'keyboardMove'; | ||
| import * as control from './control'; | ||
|
|
||
| export default class AnalyseCtrl { | ||
| data: AnalyseData; | ||
|
|
@@ -123,6 +125,7 @@ export default class AnalyseCtrl { | |
| cgConfig: any; // latest chessground config (useful for revert) | ||
| nvui?: NvuiPlugin; | ||
| pvUciQueue: Uci[] = []; | ||
| keyboardMove?: KeyboardMove; | ||
|
|
||
| constructor( | ||
| readonly opts: AnalyseOpts, | ||
|
|
@@ -359,6 +362,24 @@ export default class AnalyseCtrl { | |
| return config; | ||
| } | ||
|
|
||
| setChessground = (cg: CgApi) => { | ||
| this.chessground = cg; | ||
|
|
||
| if (this.data.pref.keyboardMove) { | ||
| this.keyboardMove ??= makeKeyboardMove({ | ||
| ...this, | ||
| data: { ...this.data, player: { color: 'both' } }, | ||
| flipNow: this.flip, | ||
| }); | ||
| this.keyboardMove.update({ fen: this.node.fen, canMove: true, cg }); | ||
| requestAnimationFrame(() => this.redraw()); | ||
| } | ||
|
|
||
| this.setAutoShapes(); | ||
| if (this.node.shapes) this.chessground.setShapes(this.node.shapes as DrawShape[]); | ||
| this.cgVersion.dom = this.cgVersion.js; | ||
| }; | ||
|
|
||
| private onChange: () => void = throttle(300, () => { | ||
| site.pubsub.emit('analysis.change', this.node.fen, this.path); | ||
| }); | ||
|
|
@@ -398,6 +419,7 @@ export default class AnalyseCtrl { | |
| } | ||
| site.pubsub.emit('ply', this.node.ply, this.tree.lastMainlineNode(this.path).ply === this.node.ply); | ||
| this.showGround(); | ||
| this.pluginUpdate(this.node.fen); | ||
| } | ||
|
|
||
| userJump = (path: Tree.Path): void => { | ||
|
|
@@ -418,12 +440,12 @@ export default class AnalyseCtrl { | |
| if (this.canJumpTo(path)) this.userJump(path); | ||
| } | ||
|
|
||
| mainlinePathToPly(ply: Ply): Tree.Path { | ||
| mainlinePlyToPath(ply: Ply): Tree.Path { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lol good catch! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Couldn't unsee it 🙃 |
||
| return treeOps.takePathWhile(this.mainline, n => n.ply <= ply); | ||
| } | ||
|
|
||
| jumpToMain = (ply: Ply): void => { | ||
| this.userJump(this.mainlinePathToPly(ply)); | ||
| this.userJump(this.mainlinePlyToPath(ply)); | ||
| }; | ||
|
|
||
| jumpToIndex = (index: number): void => { | ||
|
|
@@ -455,7 +477,7 @@ export default class AnalyseCtrl { | |
| } as AnalyseData; | ||
| if (andReload) { | ||
| this.reloadData(data, false); | ||
| this.userJump(this.mainlinePathToPly(this.tree.lastPly())); | ||
| this.userJump(this.mainlinePlyToPath(this.tree.lastPly())); | ||
| this.redraw(); | ||
| } | ||
| return data; | ||
|
|
@@ -474,6 +496,21 @@ export default class AnalyseCtrl { | |
| encodeURIComponent(fen).replace(/%20/g, '_').replace(/%2F/g, '/'); | ||
| } | ||
|
|
||
| crazyValid = (role: cg.Role, key: cg.Key): boolean => { | ||
| const color = this.chessground.state.movable.color; | ||
| return ( | ||
| (color === 'white' || color === 'black') && | ||
| crazyValid(this.chessground, this.node.drops, { color, role }, key) | ||
| ); | ||
| }; | ||
|
|
||
| getCrazyhousePockets = () => this.node.crazy?.pockets; | ||
|
|
||
| sendNewPiece = (role: cg.Role, key: cg.Key): void => { | ||
| const color = this.chessground.state.movable.color; | ||
| if (color === 'white' || color === 'black') this.userNewPiece({ color, role }, key); | ||
| }; | ||
|
|
||
| userNewPiece = (piece: cg.Piece, pos: Key): void => { | ||
| if (crazyValid(this.chessground, this.node.drops, piece, pos)) { | ||
| this.justPlayed = roleToChar(piece.role).toUpperCase() + '@' + pos; | ||
|
|
@@ -555,6 +592,7 @@ export default class AnalyseCtrl { | |
| this.tree.addDests(dests, path); | ||
| if (path === this.path) { | ||
| this.showGround(); | ||
| this.pluginUpdate(this.node.fen); | ||
| if (this.outcome()) this.ceval.stop(); | ||
| } | ||
| this.withCg(cg => cg.playPremove()); | ||
|
|
@@ -947,4 +985,29 @@ export default class AnalyseCtrl { | |
|
|
||
| withCg = <A>(f: (cg: ChessgroundApi) => A): A | undefined => | ||
| this.chessground && this.cgVersion.js === this.cgVersion.dom ? f(this.chessground) : undefined; | ||
|
|
||
| handleArrowKey = (arrowKey: ArrowKey) => { | ||
| if (arrowKey === 'ArrowUp') { | ||
| if (this.fork.prev()) this.setAutoShapes(); | ||
| else control.first(this); | ||
| } else if (arrowKey === 'ArrowDown') { | ||
| if (this.fork.next()) this.setAutoShapes(); | ||
| else control.last(this); | ||
| } else if (arrowKey === 'ArrowLeft') control.prev(this); | ||
| else if (arrowKey === 'ArrowRight') control.next(this); | ||
| this.redraw(); | ||
| }; | ||
|
|
||
| pluginMove = (orig: cg.Key, dest: cg.Key, prom: cg.Role | undefined) => { | ||
| const capture = this.chessground.state.pieces.get(dest); | ||
| this.sendMove(orig, dest, capture, prom); | ||
| }; | ||
|
|
||
| pluginUpdate = (fen: string) => { | ||
| // if controller and chessground board state differ, ignore this update. once the chessground | ||
| // state is updated to match, pluginUpdate will be called again. | ||
| if (!fen.startsWith(this.chessground?.getFen())) return; | ||
|
|
||
| this.keyboardMove?.update({ fen, canMove: true }); | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |
| { "path": "../chess/tsconfig.json" }, | ||
| { "path": "../common/tsconfig.json" }, | ||
| { "path": "../game/tsconfig.json" }, | ||
| { "path": "../keyboardMove/tsconfig.json" }, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tsc dependency mechanism isn't documented anywhere so I'm impressed. I think you're the first to do this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I won't pretend to understand it, but I will pretend to be quite good at pattern matching 😎 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's actually straightforward. tsc doesn't care about our monorepo dependencies (package.json), so if you want correct behavior when type checking - you have to either compile everything in the correct order (bad) or express dependencies in tsconfig.json (better, but still not great). |
||
| { "path": "../nvui/tsconfig.json" }, | ||
| { "path": "../tree/tsconfig.json" } | ||
| ], | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.