2020-09-22 00:56:13 -06:00
|
|
|
|
import sparkline from "@fnando/sparkline";
|
|
|
|
|
import { Controller, Puzzle, PuzzleGame, MaybeVNode } from '../interfaces';
|
|
|
|
|
import { dataIcon } from '../util';
|
2017-07-03 05:52:21 -06:00
|
|
|
|
import { h, thunk } from 'snabbdom';
|
2020-09-12 02:13:01 -06:00
|
|
|
|
import { numberFormat } from 'common/number';
|
2020-09-22 00:56:13 -06:00
|
|
|
|
import { VNode } from 'snabbdom/vnode';
|
2017-07-03 05:52:21 -06:00
|
|
|
|
|
2020-01-02 08:51:13 -07:00
|
|
|
|
export function puzzleBox(ctrl: Controller): VNode {
|
2017-07-03 05:52:21 -06:00
|
|
|
|
var data = ctrl.getData();
|
2019-02-14 21:04:24 -07:00
|
|
|
|
return h('div.puzzle__side__metas', [
|
2017-07-03 05:52:21 -06:00
|
|
|
|
puzzleInfos(ctrl, data.puzzle),
|
2019-02-14 21:04:24 -07:00
|
|
|
|
gameInfos(ctrl, data.game, data.puzzle)
|
|
|
|
|
]);
|
2017-07-03 05:52:21 -06:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-11 00:58:13 -06:00
|
|
|
|
function puzzleInfos(ctrl: Controller, puzzle: Puzzle): VNode {
|
2019-02-14 21:04:24 -07:00
|
|
|
|
return h('div.infos.puzzle', {
|
2017-07-03 05:52:21 -06:00
|
|
|
|
attrs: dataIcon('-')
|
2019-02-14 21:04:24 -07:00
|
|
|
|
}, [h('div', [
|
|
|
|
|
h('a.title', {
|
|
|
|
|
attrs: { href: '/training/' + puzzle.id }
|
|
|
|
|
}, ctrl.trans('puzzleId', puzzle.id)),
|
2019-08-16 05:52:10 -06:00
|
|
|
|
h('p', ctrl.trans.vdom('ratingX', ctrl.vm.mode === 'play' ? h('span.hidden', ctrl.trans.noarg('hidden')) : h('strong', puzzle.rating))),
|
2020-09-12 02:13:01 -06:00
|
|
|
|
h('p', ctrl.trans.vdom('playedXTimes', h('strong', numberFormat(puzzle.attempts))))
|
2019-02-14 21:04:24 -07:00
|
|
|
|
])]);
|
2017-07-03 05:52:21 -06:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-11 00:58:13 -06:00
|
|
|
|
function gameInfos(ctrl: Controller, game: PuzzleGame, puzzle: Puzzle): VNode {
|
2019-02-14 21:04:24 -07:00
|
|
|
|
return h('div.infos', {
|
|
|
|
|
attrs: dataIcon(game.perf.icon)
|
|
|
|
|
}, [h('div', [
|
2019-08-16 05:21:06 -06:00
|
|
|
|
h('p', ctrl.trans.vdom('fromGameLink', h('a', {
|
|
|
|
|
attrs: { href: `/${game.id}/${puzzle.color}#${puzzle.initialPly}` }
|
|
|
|
|
}, '#' + game.id))),
|
2019-02-14 21:04:24 -07:00
|
|
|
|
h('p', [
|
|
|
|
|
game.clock, ' • ',
|
|
|
|
|
game.perf.name, ' • ',
|
|
|
|
|
ctrl.trans.noarg(game.rated ? 'rated' : 'casual')
|
2017-07-03 05:52:21 -06:00
|
|
|
|
]),
|
|
|
|
|
h('div.players', game.players.map(function(p) {
|
|
|
|
|
return h('div.player.color-icon.is.text.' + p.color,
|
2019-04-08 03:19:22 -06:00
|
|
|
|
p.userId ? h('a.user-link.ulpt', {
|
2017-07-03 05:52:21 -06:00
|
|
|
|
attrs: { href: '/@/' + p.userId }
|
|
|
|
|
}, p.name) : p.name
|
|
|
|
|
);
|
|
|
|
|
}))
|
2019-02-14 21:04:24 -07:00
|
|
|
|
])]);
|
2017-07-03 05:52:21 -06:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-02 08:51:13 -07:00
|
|
|
|
export function userBox(ctrl: Controller): MaybeVNode {
|
2017-07-03 06:30:50 -06:00
|
|
|
|
const data = ctrl.getData();
|
2017-07-03 05:52:21 -06:00
|
|
|
|
if (!data.user) return;
|
2019-08-16 05:21:06 -06:00
|
|
|
|
const diff = ctrl.vm.round && ctrl.vm.round.ratingDiff;
|
2017-07-03 06:23:08 -06:00
|
|
|
|
const hash = ctrl.recentHash();
|
2019-02-14 21:04:24 -07:00
|
|
|
|
return h('div.puzzle__side__user', [
|
2019-08-16 05:21:06 -06:00
|
|
|
|
h('h2', ctrl.trans.vdom('yourPuzzleRatingX', h('strong', [
|
|
|
|
|
data.user.rating,
|
2020-02-23 18:21:27 -07:00
|
|
|
|
...(diff >= 0 ? [' ', h('good.rp', '+' + diff)] : []),
|
2019-08-16 05:21:06 -06:00
|
|
|
|
...(diff < 0 ? [' ', h('bad.rp', '−' + (-diff))] : [])
|
|
|
|
|
]))),
|
2017-07-03 06:23:08 -06:00
|
|
|
|
h('div', thunk('div.rating_chart.' + hash, ratingChart, [ctrl, hash]))
|
2017-07-03 05:52:21 -06:00
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-02 08:51:13 -07:00
|
|
|
|
function ratingChart(ctrl: Controller, hash: string): VNode {
|
2017-07-03 06:23:08 -06:00
|
|
|
|
return h('div.rating_chart.' + hash, {
|
2017-07-03 05:52:21 -06:00
|
|
|
|
hook: {
|
|
|
|
|
insert(vnode) { drawRatingChart(ctrl, vnode) },
|
|
|
|
|
postpatch(_, vnode) { drawRatingChart(ctrl, vnode) }
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-02 08:51:13 -07:00
|
|
|
|
function drawRatingChart(ctrl: Controller, vnode: VNode): void {
|
2019-02-14 21:04:24 -07:00
|
|
|
|
const $el = $(vnode.elm as HTMLElement);
|
2020-09-22 00:56:13 -06:00
|
|
|
|
const points = ctrl.getData().user!.recent.map(r => r[2] + r[1]);
|
2020-10-02 07:46:16 -06:00
|
|
|
|
const localPuzzleMin = Math.min(...points);
|
2020-09-22 00:56:13 -06:00
|
|
|
|
const redraw = () => {
|
|
|
|
|
const $svg = $('<svg class="sparkline" height="80px" stroke-width="3">')
|
|
|
|
|
.attr('width', Math.round($el.outerWidth()) + 'px')
|
|
|
|
|
.prependTo($(vnode.elm).empty());
|
2020-11-07 07:30:58 -07:00
|
|
|
|
sparkline($svg[0] as unknown as SVGSVGElement, points.map(r => r - localPuzzleMin), {
|
2020-09-22 00:56:13 -06:00
|
|
|
|
interactive: true,
|
|
|
|
|
})
|
|
|
|
|
};
|
2020-07-01 06:19:16 -06:00
|
|
|
|
requestAnimationFrame(redraw);
|
2019-02-15 02:12:19 -07:00
|
|
|
|
window.addEventListener('resize', redraw);
|
2017-07-03 05:52:21 -06:00
|
|
|
|
}
|