Skip to content

Commit

Permalink
golf ui/tournament
Browse files Browse the repository at this point in the history
  • Loading branch information
allanjoseph98 committed Oct 19, 2024
1 parent 7bb7790 commit 60a9d0f
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 202 deletions.
2 changes: 1 addition & 1 deletion ui/tournament/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export interface Pairing {
title?: string;
berserk?: boolean;
};
win: boolean;
win?: boolean;
status: number;
berserk: boolean;
}
Expand Down
28 changes: 12 additions & 16 deletions ui/tournament/src/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,25 @@ import * as search from './search';

export const maxPerPage = 10;

function button(
const button = (
text: string,
icon: string,
click: () => void,
enable: boolean,
ctrl: TournamentController,
): VNode {
return h('button.fbt.is', {
): VNode =>
h('button.fbt.is', {
attrs: { 'data-icon': icon, disabled: !enable, title: text },
hook: bind('mousedown', click, ctrl.redraw),
});
}

function scrollToMeButton(ctrl: TournamentController): VNode | undefined {
if (ctrl.data.me)
return h('button.fbt' + (ctrl.focusOnMe ? '.active' : ''), {
attrs: { 'data-icon': licon.Target, title: 'Scroll to your player' },
hook: bind('mousedown', ctrl.toggleFocusOnMe, ctrl.redraw),
});
return undefined;
}
const scrollToMeButton = (ctrl: TournamentController): VNode | undefined =>
ctrl.data.me
? h('button.fbt' + (ctrl.focusOnMe ? '.active' : ''), {
attrs: { 'data-icon': licon.Target, title: 'Scroll to your player' },
hook: bind('mousedown', ctrl.toggleFocusOnMe, ctrl.redraw),
})
: undefined;

export function renderPager(ctrl: TournamentController, pag: Pagination): MaybeVNodes {
const enabled = !!pag.currentPageResults,
Expand Down Expand Up @@ -66,7 +64,5 @@ export function players(ctrl: TournamentController): Pagination {
};
}

export function myPage(ctrl: TournamentController): number | undefined {
if (ctrl.data.me) return Math.floor((ctrl.data.me.rank - 1) / 10) + 1;
return undefined;
}
export const myPage = (ctrl: TournamentController): number | undefined =>
ctrl.data.me ? Math.floor((ctrl.data.me.rank - 1) / 10) + 1 : undefined;
10 changes: 4 additions & 6 deletions ui/tournament/src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { bind, onInsert } from 'common/snabbdom';
import TournamentController from './ctrl';
import { userComplete } from 'common/userComplete';

export function button(ctrl: TournamentController): VNode {
return h('button.fbt', {
export const button = (ctrl: TournamentController): VNode =>
h('button.fbt', {
class: { active: ctrl.searching },
attrs: { 'data-icon': ctrl.searching ? licon.X : licon.Search, title: 'Search tournament players' },
hook: bind('click', ctrl.toggleSearch, ctrl.redraw),
});
}

export function input(ctrl: TournamentController): VNode {
return h(
export const input = (ctrl: TournamentController): VNode =>
h(
'div.search',
h('input', {
attrs: { spellcheck: 'false' },
Expand Down Expand Up @@ -41,4 +40,3 @@ export function input(ctrl: TournamentController): VNode {
}),
}),
);
}
12 changes: 4 additions & 8 deletions ui/tournament/src/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,12 @@ function doCountDown(targetTime: number) {
}

export function end(data: TournamentData) {
if (data.me && data.isRecentlyFinished && once('tournament.end.sound.' + data.id)) {
let key = 'Other';
if (data.me.rank < 4) key = '1st';
else if (data.me.rank < 11) key = '2nd';
else if (data.me.rank < 21) key = '3rd';

site.sound.play('tournament' + key);
}
if (data.me && data.isRecentlyFinished && once('tournament.end.sound.' + data.id))
site.sound.play('tournament' + keyFromRank(data.me.rank));
}

const keyFromRank = (rank: number) => (rank < 4 ? '1st' : rank < 11 ? '2nd' : rank < 21 ? '3rd' : 'Other');

export function countDown(data: TournamentData) {
if (!data.me || !data.secondsToStart) {
if (countDownTimeout) clearTimeout(countDownTimeout);
Expand Down
17 changes: 6 additions & 11 deletions ui/tournament/src/view/arena.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,18 @@ import * as button from './button';
import * as pagination from '../pagination';
import { userLink } from 'common/userLink';

const renderScoreString = (scoreString: string, streakable: boolean) => {
const renderScoreString = (scoreString: string, streakable: boolean): VNode[] => {
const values = scoreString.split('').map(s => parseInt(s));
values.reverse(); // in place!
if (!streakable) return values.map(v => h('score', v));
const nodes = [];
let streak = 0;
for (const v of values) {
return values.map(v => {
const win = v == 2 ? streak < 2 : v > 2;
const tag = streak > 1 && v > 1 ? 'double' : win ? 'streak' : 'score';
if (win) {
streak++;
} else {
streak = 0;
}
nodes.push(h(tag, v));
}
return nodes;
if (win) streak++;
else streak = 0;
return h(tag, v);
});
};

function playerTr(ctrl: TournamentController, player: StandingPlayer) {
Expand Down
15 changes: 6 additions & 9 deletions ui/tournament/src/view/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import { spinnerVdom as spinner } from 'common/spinner';
import { bind, dataIcon } from 'common/snabbdom';
import TournamentController from '../ctrl';

function orJoinSpinner(ctrl: TournamentController, f: () => VNode): VNode {
return ctrl.joinSpinner ? spinner() : f();
}
const orJoinSpinner = (ctrl: TournamentController, f: () => VNode): VNode =>
ctrl.joinSpinner ? spinner() : f();

export function withdraw(ctrl: TournamentController): VNode {
return orJoinSpinner(ctrl, () => {
export const withdraw = (ctrl: TournamentController): VNode =>
orJoinSpinner(ctrl, () => {
const pause = ctrl.data.isStarted;
return h(
'button.fbt.text',
Expand All @@ -20,10 +19,9 @@ export function withdraw(ctrl: TournamentController): VNode {
ctrl.trans.noarg(pause ? 'pause' : 'withdraw'),
);
});
}

export function join(ctrl: TournamentController): VNode {
return orJoinSpinner(ctrl, () => {
export const join = (ctrl: TournamentController): VNode =>
orJoinSpinner(ctrl, () => {
const delay = ctrl.data.me && ctrl.data.me.pauseDelay;
const joinable = ctrl.data.verdicts.accepted && !delay;
const button = h(
Expand Down Expand Up @@ -57,7 +55,6 @@ export function join(ctrl: TournamentController): VNode {
])
: button;
});
}

export function joinWithdraw(ctrl: TournamentController): VNode | undefined {
if (!ctrl.opts.userId)
Expand Down
74 changes: 29 additions & 45 deletions ui/tournament/src/view/calendarView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import { Tournament } from '../interfaces';
import { Ctrl, Lanes } from '../tournament.calendar';
import * as licon from 'common/licon';
import perfIcons from 'common/perfIcons';
import { padWithZero } from './util';

function tournamentClass(tour: Tournament, day: Date): Classes {
const classes = {
const classes: Classes = {
rated: tour.rated,
casual: !tour.rated,
'max-rating': tour.hasMaxRating,
yesterday: tour.bounds.start < day,
} as Classes;
if (tour.schedule) classes[tour.schedule.freq] = true;
};
classes[tour.schedule.freq] = !!tour.schedule;
return classes;
}

Expand Down Expand Up @@ -48,31 +49,25 @@ function renderTournament(tour: Tournament, day: Date) {
);
}

function renderLane(tours: Tournament[], day: Date) {
return h(
const renderLane = (tours: Tournament[], day: Date) =>
h(
'lane',
tours.map(t => renderTournament(t, day)),
);
}

function fitLane(lane: Tournament[], tour2: Tournament) {
return !lane.some(tour1 => {
return areIntervalsOverlapping(tour1.bounds, tour2.bounds);
});
}
const fitLane = (lane: Tournament[], tour2: Tournament) =>
!lane.some(tour1 => areIntervalsOverlapping(tour1.bounds, tour2.bounds));

function makeLanes(tours: Tournament[]): Lanes {
const lanes: Lanes = [];
tours.forEach(t => {
const makeLanes = (tours: Tournament[]): Lanes =>
tours.reduce<Lanes>((lanes, t) => {
const lane = lanes.find(l => fitLane(l, t));
if (lane) lane.push(t);
else lanes.push([t]);
});
return lanes;
}
lane ? lane.push(t) : lanes.push([t]);
return lanes;
}, []);

function renderDay(ctrl: Ctrl) {
return function (day: Date): VNode {
const renderDay =
(ctrl: Ctrl) =>
(day: Date): VNode => {
const dayEnd = addDays(day, 1);
const tours = ctrl.data.tournaments.filter(t => t.bounds.start < dayEnd && t.bounds.end > day);
return h('day', [
Expand All @@ -83,40 +78,29 @@ function renderDay(ctrl: Ctrl) {
),
]);
};
}

function renderGroup(ctrl: Ctrl) {
return function (group: Date[]): VNode {
return h('group', [renderTimeline(), h('days', group.map(renderDay(ctrl)))]);
};
}
const renderGroup =
(ctrl: Ctrl) =>
(group: Date[]): VNode =>
h('group', [renderTimeline(), h('days', group.map(renderDay(ctrl)))]);

function renderTimeline() {
const hours: number[] = [];
for (let i = 0; i < 24; i++) hours.push(i);
return h(
const renderTimeline = () =>
h(
'div.timeline',
hours.map(hour =>
Array.from(Array(25).keys()).map(hour =>
h(
'div.timeheader',
{ attrs: { style: startDirection() + ': ' + (hour / 24) * 100 + '%' } },
timeString(hour),
padWithZero(hour),
),
),
);
}

// converts Date to "%H:%M" with leading zeros
function timeString(hour: number) {
return ('0' + hour).slice(-2);
}

function makeGroups(days: Date[]): Date[][] {
const groups: Date[][] = [],
chunk = 10;
for (let i = 0; i < days.length; i += chunk) groups.push(days.slice(i, i + chunk));
return groups;
}
const makeGroups = (days: Date[]): Date[][] =>
days.reduce<Date[][]>((groups, d, i) => {
i % 10 == 0 ? groups.push([d]) : groups[groups.length - 1].push(d);
return groups;
}, []);

export default function (ctrl: Ctrl) {
const days = eachDayOfInterval({
Expand Down
5 changes: 2 additions & 3 deletions ui/tournament/src/view/created.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,5 @@ export function main(ctrl: TournamentController): MaybeVNodes {
];
}

export function table(ctrl: TournamentController): VNode | undefined {
return ctrl.teamInfo.requested ? teamInfo(ctrl) : undefined;
}
export const table = (ctrl: TournamentController): VNode | undefined =>
ctrl.teamInfo.requested ? teamInfo(ctrl) : undefined;
18 changes: 8 additions & 10 deletions ui/tournament/src/view/finished.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ import { numberRow } from './util';
import { MaybeVNodes } from 'common/snabbdom';
import { once } from 'common/storage';

function confetti(data: TournamentData): VNode | undefined {
if (data.me && data.isRecentlyFinished && once('tournament.end.canvas.' + data.id))
return h('canvas#confetti', {
hook: { insert: _ => site.asset.loadEsm('bits.confetti') },
});
return undefined;
}
const confetti = (data: TournamentData): VNode | undefined =>
data.me && data.isRecentlyFinished && once('tournament.end.canvas.' + data.id)
? h('canvas#confetti', {
hook: { insert: _ => site.asset.loadEsm('bits.confetti') },
})
: undefined;

function stats(ctrl: TournamentController): VNode | undefined {
const data = ctrl.data,
Expand Down Expand Up @@ -111,6 +110,5 @@ export function main(ctrl: TournamentController): MaybeVNodes {
];
}

export function table(ctrl: TournamentController): VNode | undefined {
return ctrl.playerInfo.id ? playerInfo(ctrl) : ctrl.teamInfo.requested ? teamInfo(ctrl) : stats(ctrl);
}
export const table = (ctrl: TournamentController): VNode | undefined =>
ctrl.playerInfo.id ? playerInfo(ctrl) : ctrl.teamInfo.requested ? teamInfo(ctrl) : stats(ctrl);
10 changes: 4 additions & 6 deletions ui/tournament/src/view/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const hasFreq = (freq: 'shield' | 'marathon', d: TournamentData) => d.schedule?.
function clock(ctrl: TournamentController): VNode | undefined {
const d = ctrl.data;
if (d.isFinished) return;
if (d.secondsToFinish) return h('div.clock', [h('div.time', { hook: startClock(d.secondsToFinish) })]);
if (d.secondsToStart) {
else if (d.secondsToFinish) return h('div.clock', [h('div.time', { hook: startClock(d.secondsToFinish) })]);
else if (d.secondsToStart) {
if (d.secondsToStart > oneDayInSeconds)
return h('div.clock', [
h('time.timeago.shy', {
Expand All @@ -40,13 +40,11 @@ function clock(ctrl: TournamentController): VNode | undefined {
h('span.shy', ctrl.trans.noarg('startingIn')),
h('span.time.text', { hook: startClock(d.secondsToStart) }),
]);
}
return undefined;
} else return undefined;
}

function image(d: TournamentData): VNode | undefined {
if (d.isFinished) return;
if (hasFreq('shield', d) || hasFreq('marathon', d)) return;
if (d.isFinished || hasFreq('shield', d) || hasFreq('marathon', d)) return;
const s = d.spotlight;
if (s && s.iconImg) return h('img.img', { attrs: { src: site.asset.url('images/' + s.iconImg) } });
return h('i.img', { attrs: dataIcon(s?.iconFont || licon.Trophy) });
Expand Down
14 changes: 3 additions & 11 deletions ui/tournament/src/view/playerInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,8 @@ import * as status from 'game/status';
import TournamentController from '../ctrl';
import { Player } from '../interfaces';

function result(win: boolean, stat: number): string {
switch (win) {
case true:
return '1';
case false:
return '0';
default:
return stat >= status.ids.mate ? '½' : '*';
}
}
const result = (win: boolean | undefined, stat: number) =>
win !== undefined ? (win ? '1' : '0') : stat >= status.ids.mate ? '½' : '*';

const playerTitle = (player: Player) =>
h('h2', [player.rank ? h('span.rank', `${player.rank}. `) : '', renderPlayer(player, true, false, false)]);
Expand Down Expand Up @@ -101,4 +93,4 @@ export default function (ctrl: TournamentController): VNode {
}

const berserkTd = (b: boolean) =>
b ? h('td.berserk', { attrs: { 'data-icon': licon.Berserk, title: 'Berserk' } }) : h('td.berserk');
h('td.berserk', b && { attrs: { 'data-icon': licon.Berserk, title: 'Berserk' } });
Loading

0 comments on commit 60a9d0f

Please sign in to comment.