lila/ui/round/src/clock/clockCtrl.ts

150 lines
3.5 KiB
TypeScript
Raw Normal View History

2017-07-08 09:04:16 -06:00
import { updateElements } from './clockView';
import { RoundData } from '../interfaces'
import { game } from 'game';
2017-04-24 06:57:06 -06:00
2017-07-08 09:04:16 -06:00
export type Seconds = number;
export type Centis = number;
export type Millis = number;
interface ClockOpts {
onFlag(): void;
soundColor?: Color
}
export type TenthsPref = 0 | 1 | 2;
2017-07-08 09:04:16 -06:00
export interface ClockData {
running: boolean;
initial: Seconds;
increment: Seconds;
white: Seconds;
black: Seconds;
emerg: Seconds;
showTenths: TenthsPref;
2017-07-08 09:04:16 -06:00
showBar: boolean;
2017-07-08 15:09:41 -06:00
moretime: number;
2017-07-08 09:04:16 -06:00
}
interface Times {
white: Millis;
black: Millis;
activeColor?: Color;
2017-07-08 09:04:16 -06:00
lastUpdate: Millis;
}
type ColorMap<T> = { [C in Color]: T };
2017-07-08 09:04:16 -06:00
export interface ClockElements {
time?: HTMLElement;
bar?: HTMLElement;
2017-07-08 09:04:16 -06:00
}
interface EmergSound {
play(): void;
next?: number;
delay: Millis,
playable: {
white: boolean;
black: boolean;
};
2017-07-08 06:49:10 -06:00
}
const nowFun = window.performance && performance.now() > 0 ?
performance.now.bind(performance) : Date.now;
2017-07-08 09:04:16 -06:00
export class ClockController {
emergSound: EmergSound = {
play: window.lichess.sound.lowtime,
2017-04-24 06:57:06 -06:00
delay: 20000,
playable: {
white: true,
black: true
}
};
showTenths: TenthsPref;
showBar: boolean;
2017-07-08 09:04:16 -06:00
times: Times;
2017-04-24 06:57:06 -06:00
2017-07-08 09:04:16 -06:00
timePercentDivisor: number
emergMs: Millis;
elements = {
2017-07-08 09:04:16 -06:00
white: {},
black: {}
} as ColorMap<ClockElements>;
2017-07-08 09:04:16 -06:00
constructor(d: RoundData, public opts: ClockOpts) {
const cdata = d.clock!;
2017-07-08 09:04:16 -06:00
this.showTenths = cdata.showTenths;
this.showBar = cdata.showBar;
this.timePercentDivisor = .1 / (Math.max(cdata.initial, 2) + 5 * cdata.increment);
2017-07-08 09:04:16 -06:00
this.emergMs = 1000 * Math.min(60, Math.max(10, cdata.initial * .125));
2017-04-24 06:57:06 -06:00
this.setClock(d, cdata.white, cdata.black);
2017-07-08 09:04:16 -06:00
}
2017-04-24 06:57:06 -06:00
timePercent = (millis: number): number =>
Math.max(0, Math.min(100, millis * this.timePercentDivisor));
setClock = (d: RoundData, white: Seconds, black: Seconds, delay: Centis = 0) => {
const isClockRunning = game.playable(d) &&
((d.game.turns - d.game.startedAtTurn) > 1 || d.clock!.running);
2017-04-24 06:57:06 -06:00
2017-07-08 09:04:16 -06:00
this.times = {
2017-04-24 06:57:06 -06:00
white: white * 1000,
black: black * 1000,
activeColor: isClockRunning ? d.game.player : undefined,
lastUpdate: nowFun() + delay * 10
2017-04-24 06:57:06 -06:00
};
};
addTime = (color: Color, time: Centis): void => {
this.times[color] += time * 10
}
stopClock = (): Millis|void => {
const color = this.times.activeColor;
if (color) {
const curElapse = this.elapsed();
this.times[color] = Math.max(0, this.times[color] - curElapse);
this.times.activeColor = undefined;
return curElapse;
2017-06-16 19:56:18 -06:00
}
}
tick = (): void => {
const color = this.times.activeColor;
if (!color) return;
const now = nowFun();
const millis = this.times[color] - this.elapsed(now);
2017-04-24 06:57:06 -06:00
2017-07-08 09:04:16 -06:00
if (millis <= 0) this.opts.onFlag();
else updateElements(this, this.elements[color], millis);
2017-04-24 06:57:06 -06:00
if (this.opts.soundColor === color) {
2017-07-08 09:04:16 -06:00
if (this.emergSound.playable[color]) {
if (millis < this.emergMs && !(now < this.emergSound.next!)) {
this.emergSound.play();
this.emergSound.next = now + this.emergSound.delay;
this.emergSound.playable[color] = false;
2017-04-24 06:57:06 -06:00
}
2017-07-08 09:04:16 -06:00
} else if (millis > 1.5 * this.emergMs) {
this.emergSound.playable[color] = true;
2017-04-24 06:57:06 -06:00
}
}
};
elapsed = (now = nowFun()) => Math.max(0, now - this.times.lastUpdate);
millisOf = (color: Color): Millis => (this.times.activeColor === color ?
Math.max(0, this.times[color] - this.elapsed()) :
this.times[color]
);
2017-04-24 06:57:06 -06:00
}