Merge branch 'master' into reportWeight

* master:
  upgrade chessground to 7.2.10
  restore `ui/build dev upgrade`
  tweak deploy script
  also tweak light theme clock sep opacity
  provide types for Trans
  Clock tweaks
  Update StringUtils.java
This commit is contained in:
Thibault Duplessis 2017-12-03 17:35:12 -05:00
commit 1d29391e7a
25 changed files with 71 additions and 57 deletions

View file

@ -27,4 +27,4 @@ rsync --archive --no-o --no-g --progress public $REMOTE:$REMOTE_DIR
lilalog "Deploy complete"
xdg-open https://lichess.org/dev/asset-version
xdg-open https://lichess.org/dev/settings

View file

@ -77,7 +77,7 @@ public class StringUtils {
* between two strings is no greater than the sum Levenshtein distances from
* a third string).
*
* Implementation uses dynamic programming (WagnerFischer algorithm), with
* Implementation uses dynamic programming (Wagner-Fischer algorithm), with
* only 2 rows of data. The space requirement is thus O(m) and the algorithm
* runs in O(mn).
*

File diff suppressed because one or more lines are too long

View file

@ -642,7 +642,7 @@ div.table_wrap .clock huns {
font-size: 80%;
}
div.table_wrap .clock sep {
opacity: 0.6;
opacity: 0.5;
}
div.table_wrap .clock sep.low {
opacity: 0.15;

View file

@ -1,6 +1,6 @@
interface Lichess {
pubsub: Pubsub
trans: Trans
trans(i18n: { [key: string]: string | undefined }): Trans
numberFormat(n: number): string
once(key: string): boolean
quietMode: boolean
@ -55,7 +55,11 @@ interface AssetUrlOpts {
declare type SocketSend = (type: string, data?: any, opts?: any, noRetry?: boolean) => void;
declare type Trans = any; // todo
interface Trans {
(key: string, ...args: Array<string | number>): string;
noarg(key: string): string;
plural(key: string, count: number, ...args: Array<string | number>): string;
}
interface Pubsub {
on(msg: string, f: (data: any) => void): void

View file

@ -33,7 +33,7 @@ export default function(root: AnalyseCtrl, opts, allow: boolean): ExplorerCtrl {
cache = {};
setNode();
}
const withGames = synthetic(root.data) || gameUtil.replayable(root.data) || root.data.opponent.ai;
const withGames = synthetic(root.data) || gameUtil.replayable(root.data) || !!root.data.opponent.ai;
const effectiveVariant = root.data.game.variant.key === 'fromPosition' ? 'standard' : root.data.game.variant.key;
const config = configCtrl(root.data.game, onConfigClose, root.trans, root.redraw);

View file

@ -176,9 +176,9 @@ function showTablebase(ctrl: AnalyseCtrl, title: string, moves: TablebaseMoveSta
}
function winner(stm: string, move: TablebaseMoveStats): Color | undefined {
if ((stm[0] == 'w' && move.wdl < 0) || (stm[0] == 'b' && move.wdl > 0))
if ((stm[0] == 'w' && move.wdl! < 0) || (stm[0] == 'b' && move.wdl! > 0))
return 'white';
if ((stm[0] == 'b' && move.wdl < 0) || (stm[0] == 'w' && move.wdl > 0))
if ((stm[0] == 'b' && move.wdl! < 0) || (stm[0] == 'w' && move.wdl! > 0))
return 'black';
}
@ -251,15 +251,16 @@ function show(ctrl: AnalyseCtrl) {
else lastShow = showEmpty(ctrl);
} else if (data && isTablebase(data)) {
const moves = data.moves;
if (moves.length) lastShow = h('div.data', [
if (moves.length) lastShow = h('div.data', ([
[trans('winning'), m => m.wdl === -2],
[trans('unknown'), m => m.wdl === null],
[trans('winPreventedBy50MoveRule'), m => m.wdl === -1],
[trans('drawn'), m => m.wdl === 0],
[trans('lossSavedBy50MoveRule'), m => m.wdl === 1],
[trans('losing'), m => m.wdl === 2],
].map(a => showTablebase(ctrl, a[0] as string, moves.filter(a[1]), data.fen))
.reduce(function(a, b) { return a.concat(b); }, []))
] as [string, (move: TablebaseMoveStats) => boolean][])
.map(a => showTablebase(ctrl, a[0] as string, moves.filter(a[1]), data.fen))
.reduce(function(a, b) { return a.concat(b); }, []));
else if (data.checkmate) lastShow = showGameEnd(ctrl, trans('checkmate'))
else if (data.stalemate) lastShow = showGameEnd(ctrl, trans('stalemate'))
else if (data.variant_win || data.variant_loss) lastShow = showGameEnd(ctrl, trans('variantEnding'));

View file

@ -82,15 +82,15 @@ export interface OpeningMoveStats extends MoveStats {
averageRating: number;
}
export interface TablebaseMoveStats extends MoveStats {
dtm: number;
dtz: number;
wdl: number | null;
dtz: number | null;
dtm: number | undefined;
checkmate: boolean;
stalemate: boolean;
variant_win: boolean;
variant_loss: boolean;
insufficient_material: boolean;
zeroing: boolean;
wdl: number;
}
export function isOpening(m: ExplorerData): m is OpeningData {

View file

@ -53,9 +53,9 @@ function renderEnd(root: AnalyseCtrl, end: string): VNode {
color ? h('div.no-square', h('piece.king.' + color)) : h('div.icon.off', '!'),
h('div.instruction', [
h('strong', root.trans.noarg(end)),
h('em', isMate ?
h('color', root.trans.noarg(color === 'white' ? 'whiteWinsGame' : 'blackWinsGame')) :
root.trans.noarg('theGameIsADraw'))
isMate ?
h('em', h('color', root.trans.noarg(color === 'white' ? 'whiteWinsGame' : 'blackWinsGame'))) :
h('em', root.trans.noarg('theGameIsADraw'))
])
]);
}

View file

@ -1,7 +1,8 @@
#!/bin/bash -ea
target=${1-dev}
mode=${2-build} # use "upgrade" to upgrade all deps
echo "building ui modules with target=$target"
echo "building ui modules with target=$target and mode=$mode"
cd "$(git rev-parse --show-toplevel)"
@ -11,7 +12,11 @@ ts_apps1="common chess"
ts_apps2="ceval game tree chat"
apps="site chat cli challenge notify learn insight editor puzzle round analyse lobby tournament tournamentSchedule simul perfStat dasher"
yarn install --non-interactive
if [ $mode == "upgrade" ]; then
yarn upgrade --non-interactive
else
yarn install --non-interactive
fi
build_ts() {
echo "build_ts" "$@"

View file

@ -3,12 +3,12 @@ import { Ctrl, ChallengeOpts, ChallengeData, ChallengeUser } from './interfaces'
export default function(opts: ChallengeOpts, data: ChallengeData, redraw: () => void): Ctrl {
let trans: Trans = (key: string) => key;
let trans = (key: string) => key;
let redirecting = false;
function update(d: ChallengeData) {
data = d;
if (d.i18n) trans = window.lichess.trans(d.i18n);
if (d.i18n) trans = window.lichess.trans(d.i18n).noarg;
opts.setCount(countActiveIn());
notifyNew();
}

View file

@ -8,7 +8,7 @@ export interface ChallengeOpts {
export interface Ctrl {
update(data: ChallengeData): void
data(): ChallengeData
trans(): Trans
trans(): (key: string) => string
decline(id: string): void
cancel(id: string): void
onRedirect(): void

View file

@ -10,7 +10,7 @@ export interface ChatOpts {
public: boolean
permissions: Permissions
timeoutReasons?: ModerationReason[]
i18n: Object
i18n: { [key: string]: string | undefined }
preset?: string
noteId?: string
loadCss: (url: string) => void

View file

@ -49,6 +49,7 @@ function tabName(ctrl: Ctrl, tab: Tab) {
})
})
];
if (tab === 'note') return ctrl.trans.noarg('notes');
if (ctrl.plugin && tab === ctrl.plugin.tab.key) return ctrl.plugin.tab.name;
if (tab === 'note') return [ctrl.trans.noarg('notes')];
if (ctrl.plugin && tab === ctrl.plugin.tab.key) return [ctrl.plugin.tab.name];
return [];
}

View file

@ -1,7 +1,7 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Redraw, Prop, defined } from './util'
import { Redraw, defined } from './util'
export interface PingData {
ping: number | undefined
@ -13,7 +13,7 @@ export interface PingCtrl {
trans: Trans
}
export function ctrl(trans: Prop<Trans>, redraw: Redraw): PingCtrl {
export function ctrl(trans: Trans, redraw: Redraw): PingCtrl {
const data: PingData = {
ping: undefined,

View file

@ -84,7 +84,7 @@ export function getPlayer(data: GameData, color?: Color): Player | null {
}
export function hasAi(data: GameData): boolean {
return data.player.ai || data.opponent.ai;
return !!(data.player.ai || data.opponent.ai);
}
export function userAnalysable(data: GameData): boolean {
@ -97,7 +97,7 @@ export function isCorrespondence(data: GameData): boolean {
export function setOnGame(data: GameData, color: Color, onGame: boolean): void {
var player = getPlayer(data, color);
onGame = onGame || player.ai;
onGame = onGame || !!player.ai;
player.onGame = onGame;
if (onGame) setIsGone(data, color, false);
}

View file

@ -50,7 +50,7 @@ export interface Player {
proposingTakeback?: boolean;
offeringRematch?: boolean;
offeringDraw?: boolean;
ai: boolean;
ai: number | null;
onGame: boolean;
isGone: boolean;
blurs?: Blurs;

View file

@ -43,7 +43,7 @@ export default function(ctrl: LobbyController) {
pov.opponent.ai ? ctrl.trans('aiNameLevelAiLevel', 'Stockfish', pov.opponent.ai) : pov.opponent.username,
h('span.indicator',
pov.isMyTurn ?
(pov.secondsLeft ? timer(pov) : ctrl.trans('yourTurn')) :
(pov.secondsLeft ? timer(pov) : [ctrl.trans.noarg('yourTurn')]) :
h('span', {
hook: {
insert(vnode) {

View file

@ -19,9 +19,9 @@ export default function(ctrl: LobbyController) {
}).length;
const active = ctrl.tab;
return [
tab(ctrl, 'pools', active, ctrl.trans.noarg('quickPairing')),
tab(ctrl, 'real_time', active, ctrl.trans.noarg('lobby')),
tab(ctrl, 'seeks', active, ctrl.trans.noarg('correspondence')),
tab(ctrl, 'pools', active, [ctrl.trans.noarg('quickPairing')]),
tab(ctrl, 'real_time', active, [ctrl.trans.noarg('lobby')]),
tab(ctrl, 'seeks', active, [ctrl.trans.noarg('correspondence')]),
(active === 'now_playing' || ctrl.data.nbNowPlaying > 0) ? tab(ctrl, 'now_playing', active, [
ctrl.trans.plural('nbGamesInPlay', ctrl.data.nbNowPlaying),
myTurnPovsNb > 0 ? h('span.unread', myTurnPovsNb) : null

View file

@ -128,6 +128,8 @@ export class ClockController {
}
}
hardStopClock = (): void => this.times.activeColor = undefined;
scheduleTick = (time: Millis, extraDelay: Millis) => {
if (this.tickCallback !== undefined) clearTimeout(this.tickCallback);
this.tickCallback = setTimeout(

View file

@ -234,10 +234,12 @@ export default class RoundController {
};
if (this.clock) {
socketOpts.withLag = !this.shouldSendMoveTime || !this.clock.isRunning;
const moveMillis = this.clock.stopClock();
if (this.shouldSendMoveTime) {
if (meta.premove) socketOpts.millis = 0;
else if (moveMillis !== undefined) {
if (meta.premove && this.shouldSendMoveTime) {
this.clock.hardStopClock();
socketOpts.millis = 0;
} else {
const moveMillis = this.clock.stopClock();
if (moveMillis !== undefined && this.shouldSendMoveTime) {
socketOpts.millis = moveMillis;
if (socketOpts.millis < 3) {
// instant move, no premove? might be fishy

View file

@ -25,7 +25,7 @@ function bottomPlayer(ctrl: RoundController) {
function renderPlayer(ctrl: RoundController, player: Player) {
return player.ai ? h('div.username.user_link.online', [
h('i.line'),
h('name', renderUser.aiName(ctrl, player))
h('name', renderUser.aiName(ctrl, player.ai))
]) :
renderUser.userHtml(ctrl, player);
}

View file

@ -10,8 +10,8 @@ function ratingDiff(player: Player): VNode | undefined {
return;
}
export function aiName(ctrl: RoundController, player: Player) {
return ctrl.trans('aiNameLevelAiLevel', 'Stockfish', player.ai);
export function aiName(ctrl: RoundController, level: number) {
return ctrl.trans('aiNameLevelAiLevel', 'Stockfish', level);
}
export function userHtml(ctrl: RoundController, player: Player) {
@ -71,6 +71,6 @@ export function userHtml(ctrl: RoundController, player: Player) {
export function userTxt(ctrl: RoundController, player: Player) {
if (player.user) {
return (player.user.title ? player.user.title + ' ' : '') + player.user.username;
} else if (player.ai) return aiName(ctrl, player)
} else if (player.ai) return aiName(ctrl, player.ai)
else return 'Anonymous';
}

View file

@ -22,10 +22,5 @@ lichess.trans = function(i18n) {
// optimisation for translations without arguments
return i18n[key] || key;
};
trans.merge = function(more) {
Object.keys(more).forEach(function(k) {
i18n[k] = more[k];
});
};
return trans;
};

View file

@ -64,8 +64,8 @@ ajv@^4.9.1:
json-stable-stringify "^1.0.1"
ajv@^5.1.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.0.tgz#eb2840746e9dc48bd5e063a36e3fd400c5eab5a9"
version "5.5.1"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.1.tgz#b38bb8876d9e86bee994956a04e721e88b248eb2"
dependencies:
co "^4.6.0"
fast-deep-equal "^1.0.0"
@ -583,8 +583,8 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
resolved "https://codeload.github.com/ornicar/chess.js/tar.gz/ad0709c0b07773d9d0da8e4605a9a2a28f00d249"
chessground@^7.2:
version "7.2.9"
resolved "https://registry.yarnpkg.com/chessground/-/chessground-7.2.9.tgz#3f030f7290037024457e00cbde64a5e163083892"
version "7.2.10"
resolved "https://registry.yarnpkg.com/chessground/-/chessground-7.2.10.tgz#8b8f920db8ef85b6e7e37e7ec5769e8ea1523058"
"chessground@github:ornicar/chessground#v4.4.0":
version "4.4.0"
@ -983,8 +983,8 @@ detect-newline@2.X:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
detective@^4.0.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/detective/-/detective-4.6.0.tgz#d1a793ad0bcc829fa225465061096b7bca040527"
version "4.7.0"
resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.0.tgz#6276e150f9e50829ad1f90ace4d9a2304188afcf"
dependencies:
acorn "^5.2.1"
defined "^1.0.0"
@ -1187,10 +1187,14 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
extsprintf@1.3.0, extsprintf@^1.2.0:
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
fancy-log@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948"
@ -3886,8 +3890,8 @@ uglify-js@^2, uglify-js@^2.6:
uglify-to-browserify "~1.0.0"
uglify-js@^3.0.5:
version "3.2.0"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.2.0.tgz#cb411ee4ca0e0cadbfe3a4e1a1da97e6fa0d19c1"
version "3.2.1"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.2.1.tgz#d6427fd45a25fefc5d196689c0c772a6915e10fe"
dependencies:
commander "~2.12.1"
source-map "~0.6.1"