noImplicitAny for ui/tournament-schedule
parent
82d8761dce
commit
b2cf00bb6a
|
@ -0,0 +1 @@
|
|||
declare module 'dragscroll';
|
|
@ -0,0 +1,49 @@
|
|||
import perfIcons from 'common/perfIcons';
|
||||
|
||||
export interface Tournament {
|
||||
id: string;
|
||||
fullName: string;
|
||||
schedule: {
|
||||
freq: string;
|
||||
speed: string;
|
||||
};
|
||||
perf: {
|
||||
key: keyof typeof perfIcons;
|
||||
position: number;
|
||||
name: string;
|
||||
};
|
||||
hasMaxRating: boolean;
|
||||
variant: Variant;
|
||||
startsAt: number;
|
||||
finishesAt: number;
|
||||
status: number;
|
||||
position: number;
|
||||
rated: boolean;
|
||||
minutes: number;
|
||||
createdBy: string;
|
||||
clock: Clock;
|
||||
nbPlayers: number;
|
||||
}
|
||||
|
||||
export interface Data {
|
||||
created: Tournament[];
|
||||
started: Tournament[];
|
||||
finished: Tournament[];
|
||||
}
|
||||
|
||||
export interface Opts {
|
||||
data: Data;
|
||||
i18n: I18nDict;
|
||||
}
|
||||
|
||||
export interface Clock {
|
||||
limit: number;
|
||||
increment: number;
|
||||
}
|
||||
|
||||
export interface Ctrl {
|
||||
data(): Data;
|
||||
trans: Trans;
|
||||
}
|
||||
|
||||
export type Lane = Tournament[];
|
|
@ -2,19 +2,20 @@ import view from './view';
|
|||
|
||||
import { init, VNode, classModule, attributesModule } from 'snabbdom';
|
||||
import dragscroll from 'dragscroll';
|
||||
import { Opts, Tournament } from './interfaces';
|
||||
|
||||
const patch = init([classModule, attributesModule]);
|
||||
|
||||
dragscroll; // required to include the dependency :( :( :(
|
||||
|
||||
export default function (env: any) {
|
||||
export default function (opts: Opts) {
|
||||
lichess.StrongSocket.defaultParams.flag = 'tournament';
|
||||
|
||||
const element = document.querySelector('.tour-chart') as HTMLElement;
|
||||
|
||||
const ctrl = {
|
||||
data: () => env.data,
|
||||
trans: lichess.trans(env.i18n),
|
||||
data: () => opts.data,
|
||||
trans: lichess.trans(opts.i18n),
|
||||
};
|
||||
|
||||
let vnode: VNode;
|
||||
|
@ -27,16 +28,16 @@ export default function (env: any) {
|
|||
setInterval(redraw, 3700);
|
||||
|
||||
lichess.pubsub.on('socket.in.reload', d => {
|
||||
env.data = {
|
||||
created: update(env.data.created, d.created),
|
||||
started: update(env.data.started, d.started),
|
||||
finished: update(env.data.finished, d.finished),
|
||||
opts.data = {
|
||||
created: update(opts.data.created, d.created),
|
||||
started: update(opts.data.started, d.started),
|
||||
finished: update(opts.data.finished, d.finished),
|
||||
};
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
|
||||
function update(prevs, news) {
|
||||
function update(prevs: Tournament[], news: Tournament[]) {
|
||||
// updates ignore team tournaments (same for all)
|
||||
// also lacks finished tournaments
|
||||
const now = new Date().getTime();
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import { h, VNode } from 'snabbdom';
|
||||
import { Classes, h, VNode } from 'snabbdom';
|
||||
|
||||
import perfIcons from 'common/perfIcons';
|
||||
import { Clock, Ctrl, Lane, Tournament } from './interfaces';
|
||||
|
||||
const scale = 8;
|
||||
let now: number, startTime: number, stopTime: number;
|
||||
|
||||
const i18nNames = {};
|
||||
const i18nNames: Record<string, string> = {};
|
||||
|
||||
function i18nName(t) {
|
||||
function i18nName(t: Tournament) {
|
||||
if (!i18nNames[t.id]) i18nNames[t.id] = t.fullName;
|
||||
return i18nNames[t.id];
|
||||
}
|
||||
|
||||
function displayClockLimit(limit) {
|
||||
function displayClockLimit(limit: number) {
|
||||
switch (limit) {
|
||||
case 15:
|
||||
return '¼';
|
||||
|
@ -27,16 +28,16 @@ function displayClockLimit(limit) {
|
|||
}
|
||||
}
|
||||
|
||||
function displayClock(clock) {
|
||||
function displayClock(clock: Clock) {
|
||||
return displayClockLimit(clock.limit) + '+' + clock.increment;
|
||||
}
|
||||
|
||||
function leftPos(time) {
|
||||
function leftPos(time: number) {
|
||||
const rounded = 1000 * 60 * Math.floor(time / 1000 / 60);
|
||||
return (scale * (rounded - startTime)) / 1000 / 60;
|
||||
}
|
||||
|
||||
function laneGrouper(t) {
|
||||
function laneGrouper(t: Tournament): number {
|
||||
if (t.schedule && t.schedule.freq === 'unique') {
|
||||
return -1;
|
||||
} else if (t.variant.key !== 'standard') {
|
||||
|
@ -54,34 +55,34 @@ function laneGrouper(t) {
|
|||
}
|
||||
}
|
||||
|
||||
function group(arr, grouper) {
|
||||
const groups = {};
|
||||
function group(arr: Tournament[], grouper: (t: Tournament) => number): Lane[] {
|
||||
const groups: Dictionary<Tournament[]> = {};
|
||||
let g;
|
||||
arr.forEach(e => {
|
||||
g = grouper(e);
|
||||
if (!groups[g]) groups[g] = [];
|
||||
groups[g].push(e);
|
||||
if (groups[g]) groups[g]?.push(e);
|
||||
else groups[g] = [e];
|
||||
});
|
||||
return Object.keys(groups)
|
||||
.sort()
|
||||
.map(function (k) {
|
||||
return groups[k];
|
||||
return groups[k]!;
|
||||
});
|
||||
}
|
||||
|
||||
function fitLane(lane, tour2) {
|
||||
return !lane.some(function (tour1) {
|
||||
function fitLane(lane: Lane, tour2: Tournament) {
|
||||
return !lane.some(function (tour1: Tournament) {
|
||||
return !(tour1.finishesAt <= tour2.startsAt || tour2.finishesAt <= tour1.startsAt);
|
||||
});
|
||||
}
|
||||
|
||||
// splits lanes that have collisions, but keeps
|
||||
// groups separate by not compacting existing lanes
|
||||
function splitOverlaping(lanes) {
|
||||
let ret: any[] = [],
|
||||
function splitOverlaping(lanes: Lane[]): Lane[] {
|
||||
let ret: Lane[] = [],
|
||||
i: number;
|
||||
lanes.forEach(lane => {
|
||||
const newLanes: any[] = [[]];
|
||||
const newLanes: Lane[] = [[]];
|
||||
lane.forEach(tour => {
|
||||
let collision = true;
|
||||
for (i = 0; i < newLanes.length; i++) {
|
||||
|
@ -98,7 +99,7 @@ function splitOverlaping(lanes) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
function tournamentClass(tour) {
|
||||
function tournamentClass(tour: Tournament): Classes {
|
||||
const finished = tour.status === 30,
|
||||
userCreated = tour.createdBy !== 'lichess',
|
||||
classes = {
|
||||
|
@ -110,16 +111,16 @@ function tournamentClass(tour) {
|
|||
'tsht-thematic': !!tour.position,
|
||||
'tsht-short': tour.minutes <= 30,
|
||||
'tsht-max-rating': !userCreated && tour.hasMaxRating,
|
||||
};
|
||||
} as Classes;
|
||||
if (tour.schedule) classes['tsht-' + tour.schedule.freq] = true;
|
||||
return classes;
|
||||
}
|
||||
|
||||
const iconOf = tour => (tour.schedule?.freq === 'shield' ? '' : perfIcons[tour.perf.key]);
|
||||
const iconOf = (tour: Tournament) => (tour.schedule?.freq === 'shield' ? '' : perfIcons[tour.perf.key]);
|
||||
|
||||
let mousedownAt: number[] | undefined;
|
||||
|
||||
function renderTournament(ctrl, tour) {
|
||||
function renderTournament(ctrl: Ctrl, tour: Tournament) {
|
||||
let width = tour.minutes * scale;
|
||||
const left = leftPos(tour.startsAt);
|
||||
// moves content into viewport, for long tourneys and marathons
|
||||
|
@ -212,23 +213,23 @@ function renderTimeline() {
|
|||
}
|
||||
|
||||
// converts Date to "%H:%M" with leading zeros
|
||||
function timeString(time) {
|
||||
function timeString(time: Date) {
|
||||
return ('0' + time.getHours()).slice(-2) + ':' + ('0' + time.getMinutes()).slice(-2);
|
||||
}
|
||||
|
||||
function isSystemTournament(t) {
|
||||
function isSystemTournament(t: Tournament) {
|
||||
return !!t.schedule;
|
||||
}
|
||||
|
||||
export default function (ctrl) {
|
||||
export default function (ctrl: Ctrl) {
|
||||
now = Date.now();
|
||||
startTime = now - 3 * 60 * 60 * 1000;
|
||||
stopTime = startTime + 10 * 60 * 60 * 1000;
|
||||
|
||||
const data = ctrl.data();
|
||||
|
||||
const systemTours: any[] = [],
|
||||
userTours: any[] = [];
|
||||
const systemTours: Tournament[] = [],
|
||||
userTours: Tournament[] = [];
|
||||
|
||||
data.finished
|
||||
.concat(data.started)
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false
|
||||
}
|
||||
"extends": "../tsconfig.base.json"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue