implement year ranges for masters explorer

explorer-config-quicktabs
Niklas Fiekas 2021-10-31 14:32:27 +01:00
parent 143391dfbe
commit d77cfc5e50
4 changed files with 70 additions and 25 deletions

View File

@ -4,6 +4,12 @@
margin: 0.4em $block-gap 0 $block-gap;
}
p.message {
white-space: normal;
padding: 5px 5px 0;
margin: $block-gap 0 0 0;
}
section.save {
text-align: center;
padding: 15px 0 10px 0;
@ -83,7 +89,7 @@
line-height: 2em;
}
.month {
.date {
margin-top: 1em;
label {
@extend %flex-between-nowrap;

View File

@ -333,9 +333,4 @@
.message button {
margin: 0 30px;
}
.message.masters i {
font-size: 40px;
margin: 10px 0;
}
}

View File

@ -15,6 +15,7 @@ import { Redraw } from '../interfaces';
const allSpeeds: ExplorerSpeed[] = ['ultraBullet', 'bullet', 'blitz', 'rapid', 'classical', 'correspondence'];
const allModes: ExplorerMode[] = ['casual', 'rated'];
const allRatings = [1600, 1800, 2000, 2200, 2500];
const minYear = 1952;
type Month = string;
@ -92,8 +93,11 @@ export class ExplorerConfigCtrl {
};
fullHouse = () =>
this.data.db() === 'masters' ||
(this.data.rating().length === allRatings.length && this.data.speed().length === allSpeeds.length);
this.data.since() <= `${minYear}-01` &&
(!this.data.until() || new Date().toISOString().slice(0, 7) <= this.data.until()) &&
(this.data.db() === 'masters' || this.data.speed().length == allSpeeds.length) &&
(this.data.db() !== 'lichess' || this.data.rating().length == allRatings.length) &&
(this.data.db() !== 'player' || this.data.mode().length == allModes.length);
}
export function view(ctrl: ExplorerConfigCtrl): VNode[] {
@ -177,9 +181,14 @@ const advancedSection = (ctrl: ExplorerConfigCtrl, content: VNode[]): VNode =>
]);
const masterDb = (ctrl: ExplorerConfigCtrl) =>
h('div.masters.message', [
h('i', { attrs: dataIcon('') }),
h('p', ctrl.root.trans('masterDbExplanation', 2200, '1952', '2019')),
h('div', [
h('p.message', ctrl.root.trans('masterDbExplanation', 2200, minYear, '2019')),
advancedSection(ctrl, [
h('section.date', [
h('label', ['Since', yearInput(ctrl.data.since, () => '', ctrl.root.redraw)]),
h('label', ['Until', yearInput(ctrl.data.until, ctrl.data.since, ctrl.root.redraw)]),
]),
]),
]);
const radioButton =
@ -196,13 +205,15 @@ const radioButton =
const lichessDb = (ctrl: ExplorerConfigCtrl) =>
h('div', [
h('p.message', [h('br'), 'Rated games sampled from all Lichess players']),
h('p.message', 'Rated games sampled from all Lichess players'),
speedSection(ctrl),
h('section.rating', [
h('label', ctrl.root.trans.noarg('averageElo')),
h('div.choices', allRatings.map(radioButton(ctrl, ctrl.data.rating))),
advancedSection(ctrl, [
h('section.rating', [
h('label', ctrl.root.trans.noarg('averageElo')),
h('div.choices', allRatings.map(radioButton(ctrl, ctrl.data.rating))),
]),
monthSection(ctrl),
]),
advancedSection(ctrl, [monthSection(ctrl)]),
]);
const speedSection = (ctrl: ExplorerConfigCtrl) =>
@ -214,16 +225,17 @@ const speedSection = (ctrl: ExplorerConfigCtrl) =>
const modeSection = (ctrl: ExplorerConfigCtrl) =>
h('section.mode', [h('div.choices', allModes.map(radioButton(ctrl, ctrl.data.mode)))]);
const monthInput = (prop: StoredProp<Month>, min: () => Month, redraw: Redraw) => {
const monthInput = (prop: StoredProp<Month>, after: () => Month, redraw: Redraw) => {
const validateRange = (input: HTMLInputElement) =>
input.setCustomValidity(!input.value || min() <= input.value ? '' : 'Invalid date range');
input.setCustomValidity(!input.value || after() <= input.value ? '' : 'Invalid date range');
const max = new Date().toISOString().slice(0, 7);
return h('input', {
attrs: {
type: 'month',
pattern: '^20[12][0-9]-(0[1-9]|1[012])$',
min: '2010-01',
max: new Date().toISOString().slice(0, 7),
value: prop() || '',
pattern: '^(19|20)[0-9]{2}-(0[1-9]|1[012])$',
min: `${minYear}-01`,
max,
value: prop() > max ? max : prop(),
},
hook: {
insert: vnode => {
@ -244,8 +256,37 @@ const monthInput = (prop: StoredProp<Month>, min: () => Month, redraw: Redraw) =
});
};
const yearInput = (prop: StoredProp<Month>, after: () => Month, redraw: Redraw) => {
const validateRange = (input: HTMLInputElement) =>
input.setCustomValidity(!input.value || after().split('-')[0] <= input.value ? '' : 'Invalid date range');
return h('input', {
attrs: {
type: 'number',
min: minYear,
max: new Date().toISOString().slice(0, 4),
value: prop().split('-')[0],
},
hook: {
insert: vnode => {
const input = vnode.elm as HTMLInputElement;
validateRange(input);
input.addEventListener('change', e => {
const input = e.target as HTMLInputElement;
input.setCustomValidity('');
if (input.checkValidity()) {
validateRange(input);
prop(`${input.value}-${after() ? '12' : '01'}`);
redraw();
}
});
},
update: (_, vnode) => validateRange(vnode.elm as HTMLInputElement),
},
});
};
const monthSection = (ctrl: ExplorerConfigCtrl) =>
h('section.month', [
h('section.date', [
h('label', ['Since', monthInput(ctrl.data.since, () => '', ctrl.root.redraw)]),
h('label', ['Until', monthInput(ctrl.data.until, ctrl.data.since, ctrl.root.redraw)]),
]);

View File

@ -25,10 +25,13 @@ export async function opening(
params.set('variant', opts.variant || 'standard');
params.set('fen', opts.rootFen);
params.set('play', opts.play.join(','));
if (opts.db !== 'masters') {
params.set('speeds', conf.speed().join(','));
if (opts.db === 'masters') {
if (conf.since()) params.set('since', conf.since().split('-')[0]);
if (conf.until()) params.set('until', conf.until().split('-')[0]);
} else {
if (conf.since()) params.set('since', conf.since());
if (conf.until()) params.set('until', conf.until());
params.set('speeds', conf.speed().join(','));
}
if (opts.db === 'lichess') {
params.set('ratings', conf.rating().join(','));