convert ui/game to typescript
parent
03c2f1751e
commit
5607a40c15
|
@ -313,12 +313,12 @@ module.exports = {
|
|||
deleteButton(d, ctrl.userId),
|
||||
canContinue ? m('div.continue_with.g_' + d.game.id, [
|
||||
m('a.button', {
|
||||
href: d.userAnalysis ? '/?fen=' + ctrl.encodeNodeFen() + '#ai' : router.continue(d, 'ai') + '?fen=' + ctrl.vm.node.fen,
|
||||
href: d.userAnalysis ? '/?fen=' + ctrl.encodeNodeFen() + '#ai' : router.cont(d, 'ai') + '?fen=' + ctrl.vm.node.fen,
|
||||
rel: 'nofollow'
|
||||
}, ctrl.trans('playWithTheMachine')),
|
||||
m('br'),
|
||||
m('a.button', {
|
||||
href: d.userAnalysis ? '/?fen=' + ctrl.encodeNodeFen() + '#friend' : router.continue(d, 'friend') + '?fen=' + ctrl.vm.node.fen,
|
||||
href: d.userAnalysis ? '/?fen=' + ctrl.encodeNodeFen() + '#friend' : router.cont(d, 'friend') + '?fen=' + ctrl.vm.node.fen,
|
||||
rel: 'nofollow'
|
||||
}, ctrl.trans('playWithAFriend'))
|
||||
]) : null
|
||||
|
|
1
ui/build
1
ui/build
|
@ -35,6 +35,7 @@ build() {
|
|||
build_ts "common"
|
||||
build_ts "chess"
|
||||
build_ts "ceval"
|
||||
build_ts "game"
|
||||
|
||||
if [ -f $prll_sh ]; then # parallel execution!
|
||||
. $prll_sh
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"name": "game",
|
||||
"version": "1.0.0",
|
||||
"description": "lichess.org game",
|
||||
"main": "src/main.js",
|
||||
"main": "dist/main.js",
|
||||
"types": "dist/main",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ornicar/lila"
|
||||
|
@ -19,17 +20,14 @@
|
|||
"url": "https://github.com/ornicar/lila/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ornicar/lila",
|
||||
"scripts": {
|
||||
"compile": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^14",
|
||||
"gulp": "^3",
|
||||
"gulp-streamify": "^1",
|
||||
"gulp-uglify": "^2",
|
||||
"gulp-util": "^3",
|
||||
"uglify-js": "^2",
|
||||
"vinyl-source-stream": "^1",
|
||||
"watchify": "^3"
|
||||
"typescript": "^2",
|
||||
"types": "file:../types"
|
||||
},
|
||||
"dependencies": {
|
||||
"chess": "file:../chess"
|
||||
"mithril": "github:ornicar/mithril.js#lila-vdom-only-2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
var status = require('./status');
|
||||
import { Data, Player } from './interfaces';
|
||||
import * as status from './status';
|
||||
|
||||
function playable(data) {
|
||||
export function playable(data: Data): boolean {
|
||||
return data.game.status.id < status.ids.aborted && !imported(data);
|
||||
}
|
||||
|
||||
function isPlayerPlaying(data) {
|
||||
export function isPlayerPlaying(data: Data): boolean {
|
||||
return playable(data) && !data.player.spectator;
|
||||
}
|
||||
|
||||
function isPlayerTurn(data) {
|
||||
export function isPlayerTurn(data: Data): boolean {
|
||||
return isPlayerPlaying(data) && data.game.player == data.player.color;
|
||||
}
|
||||
|
||||
function mandatory(data) {
|
||||
export function mandatory(data: Data): boolean {
|
||||
return !!data.tournament || !!data.simul;
|
||||
}
|
||||
|
||||
function playedTurns(data) {
|
||||
export function playedTurns(data: Data): number {
|
||||
return data.game.turns - data.game.startedAtTurn;
|
||||
}
|
||||
|
||||
function bothPlayersHavePlayed(data) {
|
||||
export function bothPlayersHavePlayed(data: Data): boolean {
|
||||
return playedTurns(data) > 1;
|
||||
}
|
||||
|
||||
function abortable(data) {
|
||||
export function abortable(data: Data): boolean {
|
||||
return playable(data) && !bothPlayersHavePlayed(data) && !mandatory(data);
|
||||
}
|
||||
|
||||
function takebackable(data) {
|
||||
export function takebackable(data: Data): boolean {
|
||||
return playable(data) &&
|
||||
data.takebackable &&
|
||||
!data.tournament &&
|
||||
|
@ -38,93 +39,75 @@ function takebackable(data) {
|
|||
!data.opponent.proposingTakeback;
|
||||
}
|
||||
|
||||
function drawable(data) {
|
||||
export function drawable(data: Data): boolean {
|
||||
return playable(data) &&
|
||||
data.game.turns >= 2 &&
|
||||
!data.player.offeringDraw &&
|
||||
!hasAi(data);
|
||||
}
|
||||
|
||||
function resignable(data) {
|
||||
export function resignable(data: Data): boolean {
|
||||
return playable(data) && !abortable(data);
|
||||
}
|
||||
|
||||
// can the current player go berserk?
|
||||
function berserkableBy(data) {
|
||||
export function berserkableBy(data: Data): boolean {
|
||||
return data.tournament &&
|
||||
data.tournament.berserkable &&
|
||||
isPlayerPlaying(data) &&
|
||||
!bothPlayersHavePlayed(data);
|
||||
}
|
||||
|
||||
function moretimeable(data) {
|
||||
export function moretimeable(data: Data): boolean {
|
||||
return data.clock && isPlayerPlaying(data) && !mandatory(data);
|
||||
}
|
||||
|
||||
function imported(data) {
|
||||
export function imported(data: Data): boolean {
|
||||
return data.game.source === 'import';
|
||||
}
|
||||
|
||||
function replayable(data) {
|
||||
export function replayable(data: Data): boolean {
|
||||
return imported(data) || status.finished(data) ||
|
||||
(status.aborted(data) && bothPlayersHavePlayed(data));
|
||||
}
|
||||
|
||||
function getPlayer(data, color) {
|
||||
export function getPlayer(data: Data, color: Color): Player;
|
||||
export function getPlayer(data: Data, color?: Color): Player | null {
|
||||
if (data.player.color == color) return data.player;
|
||||
if (data.opponent.color == color) return data.opponent;
|
||||
return null;
|
||||
}
|
||||
|
||||
function hasAi(data) {
|
||||
export function hasAi(data: Data): boolean {
|
||||
return data.player.ai || data.opponent.ai;
|
||||
}
|
||||
|
||||
function userAnalysable(data) {
|
||||
export function userAnalysable(data: Data): boolean {
|
||||
return playable(data) && (!data.clock || !isPlayerPlaying(data));
|
||||
}
|
||||
|
||||
function isCorrespondence(data) {
|
||||
export function isCorrespondence(data: Data): boolean {
|
||||
return data.game.speed === 'correspondence';
|
||||
}
|
||||
|
||||
function setOnGame(data, color, onGame) {
|
||||
export function setOnGame(data: Data, color: Color, onGame: boolean): void {
|
||||
var player = getPlayer(data, color);
|
||||
onGame = onGame || player.ai;
|
||||
player.onGame = onGame;
|
||||
if (onGame) setIsGone(data, color, false);
|
||||
}
|
||||
|
||||
function setIsGone(data, color, isGone) {
|
||||
export function setIsGone(data: Data, color: Color, isGone: boolean): void {
|
||||
var player = getPlayer(data, color);
|
||||
isGone = isGone && !player.ai;
|
||||
player.isGone = isGone;
|
||||
if (!isGone && player.user) player.user.online = true;
|
||||
}
|
||||
|
||||
function nbMoves(data, color) {
|
||||
export function nbMoves(data: Data, color: Color): number {
|
||||
return Math.floor((data.game.turns + (color == 'white' ? 1 : 0)) / 2);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isPlayerPlaying: isPlayerPlaying,
|
||||
isPlayerTurn: isPlayerTurn,
|
||||
playable: playable,
|
||||
abortable: abortable,
|
||||
takebackable: takebackable,
|
||||
drawable: drawable,
|
||||
resignable: resignable,
|
||||
berserkableBy: berserkableBy,
|
||||
moretimeable: moretimeable,
|
||||
mandatory: mandatory,
|
||||
replayable: replayable,
|
||||
userAnalysable: userAnalysable,
|
||||
getPlayer: getPlayer,
|
||||
nbMoves: nbMoves,
|
||||
setOnGame: setOnGame,
|
||||
setIsGone: setIsGone,
|
||||
isCorrespondence: isCorrespondence,
|
||||
isSwitchable: function(data) {
|
||||
return !hasAi(data) && (data.simul || isCorrespondence(data));
|
||||
}
|
||||
};
|
||||
export function isSwitchable(data: Data): boolean {
|
||||
return !hasAi(data) && (!!data.simul || isCorrespondence(data));
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
export interface Data {
|
||||
game: Game;
|
||||
player: Player;
|
||||
opponent: Player;
|
||||
spectator: boolean;
|
||||
tournament: Tournament;
|
||||
simul: Simul;
|
||||
takebackable: boolean;
|
||||
clock: Clock;
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
id: string;
|
||||
status: Status;
|
||||
player: Color;
|
||||
turns: number;
|
||||
startedAtTurn: number;
|
||||
source: Source;
|
||||
speed: Speed;
|
||||
variant: Variant;
|
||||
winner?: Color;
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
id: StatusId;
|
||||
name: StatusName;
|
||||
}
|
||||
|
||||
export type StatusName = 'started' | 'aborted' | 'mate' | 'resign' |
|
||||
'stalemate' | 'timeout' | 'draw' | 'outoftime' |
|
||||
'noStart' | 'cheat' | 'variantEnd';
|
||||
|
||||
export type StatusId = 0;
|
||||
|
||||
export interface Player {
|
||||
id: string;
|
||||
user: User;
|
||||
spectator: boolean;
|
||||
color: Color;
|
||||
proposingTakeback: boolean;
|
||||
offeringDraw: boolean;
|
||||
ai: boolean;
|
||||
onGame: boolean;
|
||||
isGone: boolean;
|
||||
blurs?: Blurs;
|
||||
hold?: Hold;
|
||||
}
|
||||
|
||||
export interface Tournament {
|
||||
berserkable: boolean;
|
||||
}
|
||||
|
||||
export interface Simul {
|
||||
name: string;
|
||||
hostId: string;
|
||||
nbPlaying: number;
|
||||
}
|
||||
|
||||
export interface Clock {
|
||||
}
|
||||
|
||||
export type Source = 'import' | 'lobby' | 'pool';
|
||||
|
||||
export type Speed = 'correspondence';
|
||||
|
||||
export interface User {
|
||||
online: boolean;
|
||||
}
|
||||
|
||||
export interface Ctrl {
|
||||
data: Data;
|
||||
trans: Trans;
|
||||
}
|
||||
|
||||
export interface Blurs {
|
||||
nb: number;
|
||||
percent: number;
|
||||
}
|
||||
|
||||
export interface Trans {
|
||||
(key: string): string;
|
||||
}
|
||||
|
||||
export interface Hold {
|
||||
ply: number;
|
||||
mean: number;
|
||||
sd: number;
|
||||
}
|
||||
|
||||
export type ContinueMode = 'friend' | 'ai';
|
||||
|
||||
export interface GameView {
|
||||
status(ctrl: Ctrl): string;
|
||||
mod: ModView;
|
||||
}
|
||||
|
||||
export interface ModView {
|
||||
blursOf(ctrl: Ctrl, player: Player): Mithril.Renderable;
|
||||
holdOf(ctrl: Ctrl, player: Player): Mithril.Renderable;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
module.exports = {
|
||||
game: require('./game'),
|
||||
status: require('./status'),
|
||||
router: require('./router'),
|
||||
view: {
|
||||
status: require('./view/status'),
|
||||
mod: require('./view/mod')
|
||||
},
|
||||
perf: {
|
||||
icons: {
|
||||
bullet: "T",
|
||||
blitz: ")",
|
||||
classical: "+",
|
||||
correspondence: ";",
|
||||
chess960: "'",
|
||||
kingOfTheHill: "(",
|
||||
threeCheck: ".",
|
||||
antichess: "@",
|
||||
atomic: ">",
|
||||
horde: "_"
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/// <reference types="types/lichess" />
|
||||
/// <reference types="types/mithril" />
|
||||
|
||||
import { GameView } from './interfaces';
|
||||
|
||||
import * as game from './game';
|
||||
import * as status from './status';
|
||||
import * as router from './router';
|
||||
import viewStatus from './view/status';
|
||||
import * as viewMod from './view/mod';
|
||||
|
||||
export { game, status, router };
|
||||
|
||||
export const view: GameView = {
|
||||
status: viewStatus,
|
||||
mod: viewMod
|
||||
};
|
||||
|
||||
export const perf = {
|
||||
icons: {
|
||||
bullet: "T",
|
||||
blitz: ")",
|
||||
classical: "+",
|
||||
correspondence: ";",
|
||||
chess960: "'",
|
||||
kingOfTheHill: "(",
|
||||
threeCheck: ".",
|
||||
antichess: "@",
|
||||
atomic: ">",
|
||||
horde: "_"
|
||||
}
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
var player = function(data) {
|
||||
return '/' + data.game.id + data.player.id;
|
||||
};
|
||||
var game = function(data, color, embed) {
|
||||
return (embed ? '/embed/' : '/') + (data.game ? data.game.id : data) + (color ? '/' + color : '');
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
game: game,
|
||||
player: player,
|
||||
forecasts: function(data) {
|
||||
return player(data) + '/forecasts';
|
||||
},
|
||||
continue: function(data, mode) {
|
||||
return game(data) + '/continue/' + mode;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
import { Data, ContinueMode } from './interfaces';
|
||||
|
||||
export function player(data: Data): string {
|
||||
return '/' + data.game.id + data.player.id;
|
||||
}
|
||||
|
||||
export function game(data: Data, color?: Color, embed?: boolean): string {
|
||||
return (embed ? '/embed/' : '/') + (data.game ? data.game.id : data) + (color ? '/' + color : '');
|
||||
}
|
||||
|
||||
export function forecasts(data: Data): string {
|
||||
return player(data) + '/forecasts';
|
||||
}
|
||||
|
||||
export function cont(data: Data, mode: ContinueMode): string {
|
||||
return game(data) + '/continue/' + mode;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { Data } from './interfaces';
|
||||
|
||||
// https://github.com/ornicar/scalachess/blob/master/src/main/scala/Status.scala
|
||||
|
||||
var ids = {
|
||||
export const ids = {
|
||||
created: 10,
|
||||
started: 20,
|
||||
aborted: 25,
|
||||
|
@ -15,26 +17,18 @@ var ids = {
|
|||
variantEnd: 60
|
||||
};
|
||||
|
||||
function started(data) {
|
||||
export function started(data: Data): boolean {
|
||||
return data.game.status.id >= ids.started;
|
||||
}
|
||||
|
||||
function finished(data) {
|
||||
export function finished(data: Data): boolean {
|
||||
return data.game.status.id >= ids.mate;
|
||||
}
|
||||
|
||||
function aborted(data) {
|
||||
export function aborted(data: Data): boolean {
|
||||
return data.game.status.id === ids.aborted;
|
||||
}
|
||||
|
||||
function playing(data) {
|
||||
export function playing(data: Data): boolean {
|
||||
return started(data) && !finished(data) && !aborted(data);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ids: ids,
|
||||
started: started,
|
||||
finished: finished,
|
||||
aborted: aborted,
|
||||
playing: playing
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
var m = require('mithril');
|
||||
var game = require('../game');
|
||||
|
||||
function blursOf(ctrl, player) {
|
||||
if (player.blurs) return m('p', [
|
||||
player.color,
|
||||
' ' + player.blurs.nb + '/' + game.nbMoves(ctrl.data, player.color) + ' blurs = ',
|
||||
m('strong', player.blurs.percent + '%')
|
||||
]);
|
||||
}
|
||||
|
||||
function holdOf(ctrl, player) {
|
||||
var h = player.hold;
|
||||
if (h) return m('p', [
|
||||
player.color,
|
||||
' hold alert',
|
||||
m('br'),
|
||||
'ply=' + h.ply + ', mean=' + h.mean + ' ms, SD=' + h.sd
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
blursOf: blursOf,
|
||||
holdOf: holdOf
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
import { Ctrl, Player } from '../interfaces';
|
||||
|
||||
import * as m from 'mithril';
|
||||
import * as game from '../game';
|
||||
|
||||
export function blursOf(ctrl: Ctrl, player: Player): Mithril.Renderable {
|
||||
return player.blurs ? m('p', [
|
||||
player.color,
|
||||
' ' + player.blurs.nb + '/' + game.nbMoves(ctrl.data, player.color) + ' blurs = ',
|
||||
m('strong', player.blurs.percent + '%')
|
||||
]) : null;
|
||||
}
|
||||
|
||||
export function holdOf(_ctrl: Ctrl, player: Player): Mithril.Renderable {
|
||||
var h = player.hold;
|
||||
return h ? m('p', [
|
||||
player.color,
|
||||
' hold alert',
|
||||
m('br'),
|
||||
'ply=' + h.ply + ', mean=' + h.mean + ' ms, SD=' + h.sd
|
||||
]) : null;
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
module.exports = function(ctrl) {
|
||||
import { Ctrl } from '../interfaces';
|
||||
|
||||
export default function(ctrl: Ctrl): string {
|
||||
switch (ctrl.data.game.status.name) {
|
||||
case 'started':
|
||||
return ctrl.trans('playingRightNow');
|
||||
|
@ -37,4 +39,4 @@ module.exports = function(ctrl) {
|
|||
default:
|
||||
return ctrl.data.game.status.name;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"include": ["src/*.ts"],
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": true,
|
||||
"noEmitOnError": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedParameters": true,
|
||||
"target": "es5",
|
||||
"lib": ["DOM", "ES5"]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue