From 1c2c7c31d59eac0b1c5be69d34351cadc14e935e Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 00:51:54 -0700 Subject: [PATCH 01/20] Update ratingDifferenceSliders.ts to fix bug that default values aren't set to -500 and 500 when rating is provisional. --- .../setup/components/ratingDifferenceSliders.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts index 8e7dcd20da181..dacba0e6e3ad6 100644 --- a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts +++ b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts @@ -9,6 +9,10 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { const isProvisional = !!ctrl.data.ratingMap[selectedPerf].prov; const disabled = isProvisional ? '.disabled' : ''; + // Get current rating values or use default values if isProvisional + const currentRatingMin = isProvisional ? -500 : setupCtrl.ratingMin(); + const currentRatingMax = isProvisional ? 500 : setupCtrl.ratingMax(); + return h( `div.rating-range-config.optional-config${disabled}`, { @@ -27,7 +31,7 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { min: '-500', max: '0', step: '50', - value: setupCtrl.ratingMin(), + value: currentRatingMin, disabled: isProvisional, }, on: { @@ -38,16 +42,16 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { }, }, }), - h('span.rating-min', '-' + Math.abs(setupCtrl.ratingMin())), + h('span.rating-min', '-' + Math.abs(currentRatingMin)), '/', - h('span.rating-max', '+' + setupCtrl.ratingMax()), + h('span.rating-max', '+' + currentRatingMax), h('input.range.rating-range__max', { attrs: { type: 'range', min: '0', max: '500', step: '50', - value: setupCtrl.ratingMax(), + value: currentRatingMax, disabled: isProvisional, }, on: { @@ -62,3 +66,4 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { ] ); }; + From 6153cd11c8ecef1dd2f36c071a62a5ffbf92c22b Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:07:21 -0700 Subject: [PATCH 02/20] Update ratingDifferenceSliders.ts Changed ratingDifference Sliders to show -500 and 500 as default values when isProvisional --- ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts index dacba0e6e3ad6..33d4edfbef25e 100644 --- a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts +++ b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts @@ -3,7 +3,7 @@ import LobbyController from '../../../ctrl'; export const ratingDifferenceSliders = (ctrl: LobbyController) => { if (!ctrl.me || ctrl.opts.blindMode || !ctrl.data.ratingMap) return null; - + const { trans, setupCtrl } = ctrl; const selectedPerf = ctrl.setupCtrl.selectedPerf(); const isProvisional = !!ctrl.data.ratingMap[selectedPerf].prov; @@ -13,6 +13,7 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { const currentRatingMin = isProvisional ? -500 : setupCtrl.ratingMin(); const currentRatingMax = isProvisional ? 500 : setupCtrl.ratingMax(); + return h( `div.rating-range-config.optional-config${disabled}`, { @@ -66,4 +67,3 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { ] ); }; - From 1999d275036b3e7f0473071b5a97b038fae5d04f Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:08:26 -0700 Subject: [PATCH 03/20] Update variantPicker.ts Changed such that when a user switches to a variant that doesn't have a provisional rating, then rating slider sets back to stored values. --- .../src/view/setup/components/variantPicker.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index 64f5e64248095..59aea66380d92 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -13,7 +13,19 @@ export const variantPicker = (ctrl: LobbyController) => { 'select#sf_variant', { on: { - change: (e: Event) => setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey), + change: (e: Event) => {setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey); +if ( + ctrl.data.ratingMap !== null && + setupCtrl.selectedPerf() !== null && + ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov + ) { + // Check if the rating is provisional + if (!!ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { + setupCtrl.ratingMin(-500); // Set ratingMin to -500 for provisional rating + setupCtrl.ratingMax(500); + } + } +}, }, hook: onInsert(element => element.focus()), }, From e0aa1523397cf9ca58c506a7e5bb0da1472663df Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:09:38 -0700 Subject: [PATCH 04/20] Update setupCtrl.ts Changed functioning such that it knows when the variant of the game is changed so that it resets to stored value. --- ui/lobby/src/setupCtrl.ts | 59 ++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 3006651b74006..407236dddf081 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -72,7 +72,6 @@ export default class SetupController { constructor(ctrl: LobbyController) { this.root = ctrl; this.blindModeColor = propWithEffect('random', this.onPropChange); - // Initialize stores with default props as necessary this.store = { hook: this.makeSetupStore('hook'), @@ -101,7 +100,7 @@ export default class SetupController { private loadPropsFromStore = (forceOptions?: ForceSetupOptions) => { const storeProps = this.store[this.gameType!](); // Load props from the store, but override any store values with values found in forceOptions - this.variant = this.propWithApply(forceOptions?.variant || storeProps.variant); + this.variant = this.propWithApplyVariant(forceOptions?.variant || storeProps.variant); this.fen = this.propWithApply(forceOptions?.fen || storeProps.fen); this.timeMode = this.propWithApply(forceOptions?.timeMode || storeProps.timeMode); this.timeV = this.propWithApply(sliderInitVal(storeProps.time, timeVToTime, 100)!); @@ -109,14 +108,15 @@ export default class SetupController { this.daysV = this.propWithApply(sliderInitVal(storeProps.days, daysVToDays, 20)!); this.gameMode = this.propWithApply(storeProps.gameMode); this.ratingMin = this.propWithApply(storeProps.ratingMin); - this.ratingMax = this.propWithApply(storeProps.ratingMax); + this.ratingMax = this.propWithApply(storeProps.ratingMax); this.aiLevel = this.propWithApply(storeProps.aiLevel); - + this.enforcePropRules(); // Upon loading the props from the store, overriding with forced options, and enforcing rules, // immediately save them to the store. This way, the user can know that whatever they saw last // in the modal will be there when they open it at a later time. this.savePropsToStore(); + }; private enforcePropRules = () => { @@ -134,6 +134,7 @@ export default class SetupController { } }; + private savePropsToStore = () => this.gameType && this.store[this.gameType]({ @@ -148,14 +149,45 @@ export default class SetupController { ratingMax: this.ratingMax(), aiLevel: this.aiLevel(), }); - +private savePropsToStoreExceptRating = () => { + if (this.gameType && this.store[this.gameType]) { + const ratingMin = this.store[this.gameType]().ratingMin; + const ratingMax = this.store[this.gameType]().ratingMax; + this.store[this.gameType]({ + variant: this.variant(), + fen: this.fen(), + timeMode: this.timeMode(), + time: this.time(), + increment: this.increment(), + days: this.days(), + gameMode: this.gameMode(), + ratingMin: ratingMin, + ratingMax: ratingMax, + aiLevel: this.aiLevel(), + }); + } +}; private onPropChange = () => { this.enforcePropRules(); - this.savePropsToStore(); + console.log(this.gameType); + if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { + console.log("King Racing"); + this.savePropsToStoreExceptRating(); + console.log(this.ratingMin()); + } + else { + this.savePropsToStore(); + } this.root.redraw(); }; - private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); + private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); + + private propWithApplyVariant = (value: A) => { + const prop = propWithEffect(value, this.onVariantChange); + return prop; +}; + openModal = (gameType: GameType, forceOptions?: ForceSetupOptions, friendUser?: string) => { this.root.leavePool(); @@ -167,6 +199,19 @@ export default class SetupController { this.loadPropsFromStore(forceOptions); }; + private onVariantChange = () => { + // Handle rating update here + if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { + console.log("King Racing"); + this.savePropsToStoreExceptRating(); + console.log(this.ratingMin()); + } + else { + this.savePropsToStore(); + } + this.root.redraw(); +}; + closeModal = () => { this.gameType = null; this.root.redraw(); From 06b905e41cc96b833b0c1b18d8cb3e48c08ec62e Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:19:14 -0700 Subject: [PATCH 05/20] Update setupCtrl.ts Remove console logs --- ui/lobby/src/setupCtrl.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 407236dddf081..64c3382b2d735 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -169,11 +169,8 @@ private savePropsToStoreExceptRating = () => { }; private onPropChange = () => { this.enforcePropRules(); - console.log(this.gameType); if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { - console.log("King Racing"); this.savePropsToStoreExceptRating(); - console.log(this.ratingMin()); } else { this.savePropsToStore(); @@ -202,9 +199,7 @@ private savePropsToStoreExceptRating = () => { private onVariantChange = () => { // Handle rating update here if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { - console.log("King Racing"); this.savePropsToStoreExceptRating(); - console.log(this.ratingMin()); } else { this.savePropsToStore(); From b66b3232e7a8fb4517f8971fb305e87d8d94d074 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:27:05 -0700 Subject: [PATCH 06/20] Update setupCtrl.ts Lint issues with tabs and spaces. --- ui/lobby/src/setupCtrl.ts | 273 ++++++++++++++++++++++---------------- 1 file changed, 157 insertions(+), 116 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 64c3382b2d735..a04bbb77f4c21 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -1,8 +1,8 @@ -import { Prop, propWithEffect } from 'common'; -import debounce from 'common/debounce'; -import * as xhr from 'common/xhr'; -import { storedJsonProp, StoredJsonProp } from 'common/storage'; -import LobbyController from './ctrl'; +import { Prop, propWithEffect } from "common"; +import debounce from "common/debounce"; +import * as xhr from "common/xhr"; +import { storedJsonProp, StoredJsonProp } from "common/storage"; +import LobbyController from "./ctrl"; import { ForceSetupOptions, GameMode, @@ -12,7 +12,7 @@ import { RealValue, SetupStore, TimeMode, -} from './interfaces'; +} from "./interfaces"; import { daysVToDays, incrementVToIncrement, @@ -21,33 +21,38 @@ import { timeModes, timeVToTime, variants, -} from './options'; +} from "./options"; -const getPerf = (variant: VariantKey, timeMode: TimeMode, time: RealValue, increment: RealValue): Perf => { - if (!['standard', 'fromPosition'].includes(variant)) return variant as Perf; - if (timeMode !== 'realTime') return 'correspondence'; +const getPerf = ( + variant: VariantKey, + timeMode: TimeMode, + time: RealValue, + increment: RealValue +): Perf => { + if (!["standard", "fromPosition"].includes(variant)) return variant as Perf; + if (timeMode !== "realTime") return "correspondence"; const totalGameTime = time * 60 + increment * 40; return totalGameTime < 30 - ? 'ultraBullet' + ? "ultraBullet" : totalGameTime < 180 - ? 'bullet' + ? "bullet" : totalGameTime < 480 - ? 'blitz' + ? "blitz" : totalGameTime < 1500 - ? 'rapid' - : 'classical'; + ? "rapid" + : "classical"; }; export default class SetupController { root: LobbyController; store: Record>; gameType: GameType | null = null; - lastValidFen = ''; + lastValidFen = ""; fenError = false; - friendUser = ''; + friendUser = ""; loading = false; - blindModeColor: Prop; + blindModeColor: Prop; // Store props variant: Prop; @@ -71,27 +76,28 @@ export default class SetupController { constructor(ctrl: LobbyController) { this.root = ctrl; - this.blindModeColor = propWithEffect('random', this.onPropChange); + this.blindModeColor = propWithEffect("random", this.onPropChange); // Initialize stores with default props as necessary this.store = { - hook: this.makeSetupStore('hook'), - friend: this.makeSetupStore('friend'), - ai: this.makeSetupStore('ai'), + hook: this.makeSetupStore("hook"), + friend: this.makeSetupStore("friend"), + ai: this.makeSetupStore("ai"), }; } // Namespace the store by username for user specific modal settings - private storeKey = (gameType: GameType) => `lobby.setup.${this.root.me?.username || 'anon'}.${gameType}`; + private storeKey = (gameType: GameType) => + `lobby.setup.${this.root.me?.username || "anon"}.${gameType}`; makeSetupStore = (gameType: GameType) => storedJsonProp(this.storeKey(gameType), () => ({ - variant: 'standard', - fen: '', - timeMode: gameType === 'hook' ? 'realTime' : 'unlimited', + variant: "standard", + fen: "", + timeMode: gameType === "hook" ? "realTime" : "unlimited", time: 5, increment: 3, days: 2, - gameMode: gameType === 'ai' || !this.root.me ? 'casual' : 'rated', + gameMode: gameType === "ai" || !this.root.me ? "casual" : "rated", ratingMin: -500, ratingMax: 500, aiLevel: 1, @@ -100,33 +106,43 @@ export default class SetupController { private loadPropsFromStore = (forceOptions?: ForceSetupOptions) => { const storeProps = this.store[this.gameType!](); // Load props from the store, but override any store values with values found in forceOptions - this.variant = this.propWithApplyVariant(forceOptions?.variant || storeProps.variant); + this.variant = this.propWithApplyVariant( + forceOptions?.variant || storeProps.variant + ); this.fen = this.propWithApply(forceOptions?.fen || storeProps.fen); - this.timeMode = this.propWithApply(forceOptions?.timeMode || storeProps.timeMode); - this.timeV = this.propWithApply(sliderInitVal(storeProps.time, timeVToTime, 100)!); - this.incrementV = this.propWithApply(sliderInitVal(storeProps.increment, incrementVToIncrement, 100)!); - this.daysV = this.propWithApply(sliderInitVal(storeProps.days, daysVToDays, 20)!); + this.timeMode = this.propWithApply( + forceOptions?.timeMode || storeProps.timeMode + ); + this.timeV = this.propWithApply( + sliderInitVal(storeProps.time, timeVToTime, 100)! + ); + this.incrementV = this.propWithApply( + sliderInitVal(storeProps.increment, incrementVToIncrement, 100)! + ); + this.daysV = this.propWithApply( + sliderInitVal(storeProps.days, daysVToDays, 20)! + ); this.gameMode = this.propWithApply(storeProps.gameMode); this.ratingMin = this.propWithApply(storeProps.ratingMin); - this.ratingMax = this.propWithApply(storeProps.ratingMax); + this.ratingMax = this.propWithApply(storeProps.ratingMax); this.aiLevel = this.propWithApply(storeProps.aiLevel); - + this.enforcePropRules(); // Upon loading the props from the store, overriding with forced options, and enforcing rules, // immediately save them to the store. This way, the user can know that whatever they saw last // in the modal will be there when they open it at a later time. this.savePropsToStore(); - }; private enforcePropRules = () => { // reassign with this.propWithApply in this function to avoid calling this.onPropChange // replace underscores with spaces in FEN - if (this.variant() === 'fromPosition') this.fen = this.propWithApply(this.fen().replace(/_/g, ' ')); + if (this.variant() === "fromPosition") + this.fen = this.propWithApply(this.fen().replace(/_/g, " ")); - if (this.gameMode() === 'rated' && this.ratedModeDisabled()) { - this.gameMode = this.propWithApply('casual'); + if (this.gameMode() === "rated" && this.ratedModeDisabled()) { + this.gameMode = this.propWithApply("casual"); } if (this.ratingMin() === 0 && this.ratingMax() === 0) { @@ -134,7 +150,6 @@ export default class SetupController { } }; - private savePropsToStore = () => this.gameType && this.store[this.gameType]({ @@ -149,63 +164,73 @@ export default class SetupController { ratingMax: this.ratingMax(), aiLevel: this.aiLevel(), }); -private savePropsToStoreExceptRating = () => { - if (this.gameType && this.store[this.gameType]) { - const ratingMin = this.store[this.gameType]().ratingMin; - const ratingMax = this.store[this.gameType]().ratingMax; - this.store[this.gameType]({ - variant: this.variant(), - fen: this.fen(), - timeMode: this.timeMode(), - time: this.time(), - increment: this.increment(), - days: this.days(), - gameMode: this.gameMode(), - ratingMin: ratingMin, - ratingMax: ratingMax, - aiLevel: this.aiLevel(), - }); - } -}; + private savePropsToStoreExceptRating = () => { + if (this.gameType && this.store[this.gameType]) { + const ratingMin = this.store[this.gameType]().ratingMin; + const ratingMax = this.store[this.gameType]().ratingMax; + this.store[this.gameType]({ + variant: this.variant(), + fen: this.fen(), + timeMode: this.timeMode(), + time: this.time(), + increment: this.increment(), + days: this.days(), + gameMode: this.gameMode(), + ratingMin: ratingMin, + ratingMax: ratingMax, + aiLevel: this.aiLevel(), + }); + } + }; private onPropChange = () => { this.enforcePropRules(); - if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { - this.savePropsToStoreExceptRating(); - } - else { - this.savePropsToStore(); - } + if ( + this.root.data.ratingMap && + this.selectedPerf() && + !!this.root.data.ratingMap[this.selectedPerf()].prov + ) { + this.savePropsToStoreExceptRating(); + } else { + this.savePropsToStore(); + } this.root.redraw(); }; - private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); + private propWithApply = (value: A) => + propWithEffect(value, this.onPropChange); - private propWithApplyVariant = (value: A) => { + private propWithApplyVariant = (value: A) => { const prop = propWithEffect(value, this.onVariantChange); return prop; -}; - + }; - openModal = (gameType: GameType, forceOptions?: ForceSetupOptions, friendUser?: string) => { + openModal = ( + gameType: GameType, + forceOptions?: ForceSetupOptions, + friendUser?: string + ) => { this.root.leavePool(); this.gameType = gameType; this.loading = false; this.fenError = false; - this.lastValidFen = ''; - this.friendUser = friendUser || ''; + this.lastValidFen = ""; + this.friendUser = friendUser || ""; this.loadPropsFromStore(forceOptions); }; - private onVariantChange = () => { + private onVariantChange = () => { // Handle rating update here - if(this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { - this.savePropsToStoreExceptRating(); - } - else { - this.savePropsToStore(); - } + if ( + this.root.data.ratingMap && + this.selectedPerf() && + !!this.root.data.ratingMap[this.selectedPerf()].prov + ) { + this.savePropsToStoreExceptRating(); + } else { + this.savePropsToStore(); + } this.root.redraw(); -}; + }; closeModal = () => { this.gameType = null; @@ -215,47 +240,55 @@ private savePropsToStoreExceptRating = () => { validateFen = debounce(() => { const fen = this.fen(); if (!fen) return; - xhr.text(xhr.url('/setup/validate-fen', { fen, strict: this.gameType === 'ai' ? 1 : undefined })).then( - () => { - this.fenError = false; - this.lastValidFen = fen; - this.root.redraw(); - }, - () => { - this.fenError = true; - this.root.redraw(); - } - ); + xhr + .text( + xhr.url("/setup/validate-fen", { + fen, + strict: this.gameType === "ai" ? 1 : undefined, + }) + ) + .then( + () => { + this.fenError = false; + this.lastValidFen = fen; + this.root.redraw(); + }, + () => { + this.fenError = true; + this.root.redraw(); + } + ); }, 300); ratedModeDisabled = (): boolean => // anonymous games cannot be rated !this.root.me || // unlimited games cannot be rated - (this.gameType === 'hook' && this.timeMode() === 'unlimited') || + (this.gameType === "hook" && this.timeMode() === "unlimited") || // variants with very low time cannot be rated - (this.variant() !== 'standard' && - (this.timeMode() !== 'realTime' || + (this.variant() !== "standard" && + (this.timeMode() !== "realTime" || (this.time() < 0.5 && this.increment() == 0) || (this.time() == 0 && this.increment() < 2))); - selectedPerf = (): Perf => getPerf(this.variant(), this.timeMode(), this.time(), this.increment()); + selectedPerf = (): Perf => + getPerf(this.variant(), this.timeMode(), this.time(), this.increment()); ratingRange = (): string => { - if (!this.root.data.ratingMap) return ''; + if (!this.root.data.ratingMap) return ""; const rating = this.root.data.ratingMap[this.selectedPerf()].rating; return `${rating + this.ratingMin()}-${rating + this.ratingMax()}`; }; - hookToPoolMember = (color: Color | 'random'): PoolMember | null => { + hookToPoolMember = (color: Color | "random"): PoolMember | null => { const valid = - color == 'random' && - this.gameType === 'hook' && - this.variant() == 'standard' && - this.gameMode() == 'rated' && - this.timeMode() == 'realTime'; + color == "random" && + this.gameType === "hook" && + this.variant() == "standard" && + this.gameMode() == "rated" && + this.timeMode() == "realTime"; const id = `${this.time()}+${this.increment()}`; - return valid && this.root.pools.find(p => p.id === id) + return valid && this.root.pools.find((p) => p.id === id) ? { id, range: this.ratingRange(), @@ -263,7 +296,7 @@ private savePropsToStoreExceptRating = () => { : null; }; - propsToFormData = (color: Color | 'random'): FormData => + propsToFormData = (color: Color | "random"): FormData => xhr.form({ variant: keyToId(this.variant(), variants).toString(), fen: this.fen(), @@ -274,7 +307,7 @@ private savePropsToStoreExceptRating = () => { increment_range: this.incrementV().toString(), days: this.days().toString(), days_range: this.daysV().toString(), - mode: this.gameMode() === 'casual' ? '0' : '1', + mode: this.gameMode() === "casual" ? "0" : "1", ratingRange: this.ratingRange(), ratingRange_range_min: this.ratingMin().toString(), ratingRange_range_max: this.ratingMax().toString(), @@ -282,13 +315,18 @@ private savePropsToStoreExceptRating = () => { color, }); - validFen = (): boolean => this.variant() !== 'fromPosition' || !this.fenError; - validTime = (): boolean => this.timeMode() !== 'realTime' || this.time() > 0 || this.increment() > 0; + validFen = (): boolean => this.variant() !== "fromPosition" || !this.fenError; + validTime = (): boolean => + this.timeMode() !== "realTime" || this.time() > 0 || this.increment() > 0; validAiTime = (): boolean => - this.gameType !== 'ai' || this.timeMode() !== 'realTime' || this.variant() !== 'fromPosition' || this.time() >= 1; - valid = (): boolean => this.validFen() && this.validTime() && this.validAiTime(); - - submit = async (color: Color | 'random') => { + this.gameType !== "ai" || + this.timeMode() !== "realTime" || + this.variant() !== "fromPosition" || + this.time() >= 1; + valid = (): boolean => + this.validFen() && this.validTime() && this.validAiTime(); + + submit = async (color: Color | "random") => { const poolMember = this.hookToPoolMember(color); if (poolMember) { this.root.enterPool(poolMember); @@ -296,23 +334,26 @@ private savePropsToStoreExceptRating = () => { return; } - if (this.gameType === 'hook') this.root.setTab(this.timeMode() === 'realTime' ? 'real_time' : 'seeks'); + if (this.gameType === "hook") + this.root.setTab(this.timeMode() === "realTime" ? "real_time" : "seeks"); this.loading = true; this.root.redraw(); let urlPath = `/setup/${this.gameType}`; - if (this.gameType === 'hook') urlPath += `/${lichess.sri}`; + if (this.gameType === "hook") urlPath += `/${lichess.sri}`; const urlParams = { user: this.friendUser || undefined }; let response; try { response = await xhr.textRaw(xhr.url(urlPath, urlParams), { - method: 'post', + method: "post", body: this.propsToFormData(color), }); } catch (e) { this.loading = false; this.root.redraw(); - alert('Sorry, we encountered an error while creating your game. Please try again.'); + alert( + "Sorry, we encountered an error while creating your game. Please try again." + ); return; } @@ -323,9 +364,9 @@ private savePropsToStoreExceptRating = () => { alert( errs ? Object.keys(errs) - .map(k => `${k}: ${errs[k]}`) - .join('\n') - : 'Invalid setup' + .map((k) => `${k}: ${errs[k]}`) + .join("\n") + : "Invalid setup" ); if (response.status == 403) { // 403 FORBIDDEN closes this modal because challenges to the recipient From 48b24a219a9a3d53a6edfe536ef31c3b4de005c6 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:29:01 -0700 Subject: [PATCH 07/20] Update variantPicker.ts Removed double negation. --- ui/lobby/src/view/setup/components/variantPicker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index 59aea66380d92..71cd155183aef 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -20,7 +20,7 @@ if ( ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov ) { // Check if the rating is provisional - if (!!ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { + if (ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { setupCtrl.ratingMin(-500); // Set ratingMin to -500 for provisional rating setupCtrl.ratingMax(500); } From 609a20c56cec5d3c973cb380a4b4898d05012d32 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:29:39 -0700 Subject: [PATCH 08/20] Update variantPicker.ts Mixed tabs and spaces --- .../view/setup/components/variantPicker.ts | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index 71cd155183aef..e8bf3db233a4d 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -1,35 +1,44 @@ -import { onInsert } from 'common/snabbdom'; -import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; -import { variantsBlindMode, variants, variantsForGameType } from '../../../options'; -import { option } from './option'; +import { onInsert } from "common/snabbdom"; +import { h } from "snabbdom"; +import LobbyController from "../../../ctrl"; +import { + variantsBlindMode, + variants, + variantsForGameType, +} from "../../../options"; +import { option } from "./option"; export const variantPicker = (ctrl: LobbyController) => { const { trans, setupCtrl, opts } = ctrl; const baseVariants = opts.blindMode ? variantsBlindMode : variants; - return h('div.variant.label-select', [ - h('label', { attrs: { for: 'sf_variant' } }, trans('variant')), + return h("div.variant.label-select", [ + h("label", { attrs: { for: "sf_variant" } }, trans("variant")), h( - 'select#sf_variant', + "select#sf_variant", { on: { - change: (e: Event) => {setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey); -if ( - ctrl.data.ratingMap !== null && - setupCtrl.selectedPerf() !== null && - ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov - ) { - // Check if the rating is provisional - if (ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { - setupCtrl.ratingMin(-500); // Set ratingMin to -500 for provisional rating - setupCtrl.ratingMax(500); - } - } -}, + change: (e: Event) => { + setupCtrl.variant( + (e.target as HTMLSelectElement).value as VariantKey + ); + if ( + ctrl.data.ratingMap !== null && + setupCtrl.selectedPerf() !== null && + ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov + ) { + // Check if the rating is provisional + if (ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { + setupCtrl.ratingMin(-500); // Set ratingMin to -500 for provisional rating + setupCtrl.ratingMax(500); + } + } + }, }, - hook: onInsert(element => element.focus()), + hook: onInsert((element) => element.focus()), }, - variantsForGameType(baseVariants, setupCtrl.gameType!).map(variant => option(variant, setupCtrl.variant())) + variantsForGameType(baseVariants, setupCtrl.gameType!).map((variant) => + option(variant, setupCtrl.variant()) + ) ), ]); }; From 03def31fafa704e242a09f5f93f2400f234c99da Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:48:54 -0700 Subject: [PATCH 09/20] Update setupCtrl.ts Prettier formatting From 26f1d187b26768c85440daa0482c822351d3a971 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:49:52 -0700 Subject: [PATCH 10/20] Update variantPicker.ts Prettier Formatting From a24fc4c70eaef1c351675df20b5e49c5e4985823 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav <77366709+adityaj2003@users.noreply.github.com> Date: Fri, 26 May 2023 06:50:24 -0700 Subject: [PATCH 11/20] Update ratingDifferenceSliders.ts Prettier Formatting --- .../components/ratingDifferenceSliders.ts | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts index 33d4edfbef25e..0beddbcb285f5 100644 --- a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts +++ b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts @@ -1,64 +1,66 @@ -import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; +import { h } from "snabbdom"; +import LobbyController from "../../../ctrl"; export const ratingDifferenceSliders = (ctrl: LobbyController) => { if (!ctrl.me || ctrl.opts.blindMode || !ctrl.data.ratingMap) return null; - + const { trans, setupCtrl } = ctrl; const selectedPerf = ctrl.setupCtrl.selectedPerf(); const isProvisional = !!ctrl.data.ratingMap[selectedPerf].prov; - const disabled = isProvisional ? '.disabled' : ''; + const disabled = isProvisional ? ".disabled" : ""; // Get current rating values or use default values if isProvisional const currentRatingMin = isProvisional ? -500 : setupCtrl.ratingMin(); const currentRatingMax = isProvisional ? 500 : setupCtrl.ratingMax(); - return h( `div.rating-range-config.optional-config${disabled}`, { attrs: isProvisional ? { - title: 'Your rating is still provisional, play some rated games to use the rating range.', + title: + "Your rating is still provisional, play some rated games to use the rating range.", } : undefined, }, [ - trans('ratingRange'), - h('div.rating-range', [ - h('input.range.rating-range__min', { + trans("ratingRange"), + h("div.rating-range", [ + h("input.range.rating-range__min", { attrs: { - type: 'range', - min: '-500', - max: '0', - step: '50', + type: "range", + min: "-500", + max: "0", + step: "50", value: currentRatingMin, disabled: isProvisional, }, on: { input: (e: Event) => { const newVal = parseInt((e.target as HTMLInputElement).value); - if (newVal === 0 && setupCtrl.ratingMax() === 0) setupCtrl.ratingMax(50); + if (newVal === 0 && setupCtrl.ratingMax() === 0) + setupCtrl.ratingMax(50); setupCtrl.ratingMin(newVal); }, }, }), - h('span.rating-min', '-' + Math.abs(currentRatingMin)), - '/', - h('span.rating-max', '+' + currentRatingMax), - h('input.range.rating-range__max', { + h("span.rating-min", "-" + Math.abs(currentRatingMin)), + "/", + h("span.rating-max", "+" + currentRatingMax), + h("input.range.rating-range__max", { attrs: { - type: 'range', - min: '0', - max: '500', - step: '50', + type: "range", + min: "0", + max: "500", + step: "50", value: currentRatingMax, disabled: isProvisional, }, on: { input: (e: Event) => { const newVal = parseInt((e.target as HTMLInputElement).value); - if (newVal === 0 && setupCtrl.ratingMin() === 0) setupCtrl.ratingMin(-50); + if (newVal === 0 && setupCtrl.ratingMin() === 0) + setupCtrl.ratingMin(-50); setupCtrl.ratingMax(newVal); }, }, From 4b1a6dd3efcf42676e6ffbd111af41336e27fd42 Mon Sep 17 00:00:00 2001 From: Aditya Jadhav Date: Fri, 26 May 2023 07:09:23 -0700 Subject: [PATCH 12/20] Hopefully resolves formatting issues --- ui/lobby/src/setupCtrl.ts | 179 +++++++----------- .../components/ratingDifferenceSliders.ts | 45 ++--- .../view/setup/components/variantPicker.ts | 30 ++- 3 files changed, 102 insertions(+), 152 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index a04bbb77f4c21..f4dd99ac7748f 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -1,8 +1,8 @@ -import { Prop, propWithEffect } from "common"; -import debounce from "common/debounce"; -import * as xhr from "common/xhr"; -import { storedJsonProp, StoredJsonProp } from "common/storage"; -import LobbyController from "./ctrl"; +import { Prop, propWithEffect } from 'common'; +import debounce from 'common/debounce'; +import * as xhr from 'common/xhr'; +import { storedJsonProp, StoredJsonProp } from 'common/storage'; +import LobbyController from './ctrl'; import { ForceSetupOptions, GameMode, @@ -12,7 +12,7 @@ import { RealValue, SetupStore, TimeMode, -} from "./interfaces"; +} from './interfaces'; import { daysVToDays, incrementVToIncrement, @@ -21,38 +21,33 @@ import { timeModes, timeVToTime, variants, -} from "./options"; +} from './options'; -const getPerf = ( - variant: VariantKey, - timeMode: TimeMode, - time: RealValue, - increment: RealValue -): Perf => { - if (!["standard", "fromPosition"].includes(variant)) return variant as Perf; - if (timeMode !== "realTime") return "correspondence"; +const getPerf = (variant: VariantKey, timeMode: TimeMode, time: RealValue, increment: RealValue): Perf => { + if (!['standard', 'fromPosition'].includes(variant)) return variant as Perf; + if (timeMode !== 'realTime') return 'correspondence'; const totalGameTime = time * 60 + increment * 40; return totalGameTime < 30 - ? "ultraBullet" + ? 'ultraBullet' : totalGameTime < 180 - ? "bullet" + ? 'bullet' : totalGameTime < 480 - ? "blitz" + ? 'blitz' : totalGameTime < 1500 - ? "rapid" - : "classical"; + ? 'rapid' + : 'classical'; }; export default class SetupController { root: LobbyController; store: Record>; gameType: GameType | null = null; - lastValidFen = ""; + lastValidFen = ''; fenError = false; - friendUser = ""; + friendUser = ''; loading = false; - blindModeColor: Prop; + blindModeColor: Prop; // Store props variant: Prop; @@ -76,28 +71,27 @@ export default class SetupController { constructor(ctrl: LobbyController) { this.root = ctrl; - this.blindModeColor = propWithEffect("random", this.onPropChange); + this.blindModeColor = propWithEffect('random', this.onPropChange); // Initialize stores with default props as necessary this.store = { - hook: this.makeSetupStore("hook"), - friend: this.makeSetupStore("friend"), - ai: this.makeSetupStore("ai"), + hook: this.makeSetupStore('hook'), + friend: this.makeSetupStore('friend'), + ai: this.makeSetupStore('ai'), }; } // Namespace the store by username for user specific modal settings - private storeKey = (gameType: GameType) => - `lobby.setup.${this.root.me?.username || "anon"}.${gameType}`; + private storeKey = (gameType: GameType) => `lobby.setup.${this.root.me?.username || 'anon'}.${gameType}`; makeSetupStore = (gameType: GameType) => storedJsonProp(this.storeKey(gameType), () => ({ - variant: "standard", - fen: "", - timeMode: gameType === "hook" ? "realTime" : "unlimited", + variant: 'standard', + fen: '', + timeMode: gameType === 'hook' ? 'realTime' : 'unlimited', time: 5, increment: 3, days: 2, - gameMode: gameType === "ai" || !this.root.me ? "casual" : "rated", + gameMode: gameType === 'ai' || !this.root.me ? 'casual' : 'rated', ratingMin: -500, ratingMax: 500, aiLevel: 1, @@ -106,22 +100,12 @@ export default class SetupController { private loadPropsFromStore = (forceOptions?: ForceSetupOptions) => { const storeProps = this.store[this.gameType!](); // Load props from the store, but override any store values with values found in forceOptions - this.variant = this.propWithApplyVariant( - forceOptions?.variant || storeProps.variant - ); + this.variant = this.propWithApplyVariant(forceOptions?.variant || storeProps.variant); this.fen = this.propWithApply(forceOptions?.fen || storeProps.fen); - this.timeMode = this.propWithApply( - forceOptions?.timeMode || storeProps.timeMode - ); - this.timeV = this.propWithApply( - sliderInitVal(storeProps.time, timeVToTime, 100)! - ); - this.incrementV = this.propWithApply( - sliderInitVal(storeProps.increment, incrementVToIncrement, 100)! - ); - this.daysV = this.propWithApply( - sliderInitVal(storeProps.days, daysVToDays, 20)! - ); + this.timeMode = this.propWithApply(forceOptions?.timeMode || storeProps.timeMode); + this.timeV = this.propWithApply(sliderInitVal(storeProps.time, timeVToTime, 100)!); + this.incrementV = this.propWithApply(sliderInitVal(storeProps.increment, incrementVToIncrement, 100)!); + this.daysV = this.propWithApply(sliderInitVal(storeProps.days, daysVToDays, 20)!); this.gameMode = this.propWithApply(storeProps.gameMode); this.ratingMin = this.propWithApply(storeProps.ratingMin); this.ratingMax = this.propWithApply(storeProps.ratingMax); @@ -138,11 +122,10 @@ export default class SetupController { // reassign with this.propWithApply in this function to avoid calling this.onPropChange // replace underscores with spaces in FEN - if (this.variant() === "fromPosition") - this.fen = this.propWithApply(this.fen().replace(/_/g, " ")); + if (this.variant() === 'fromPosition') this.fen = this.propWithApply(this.fen().replace(/_/g, ' ')); - if (this.gameMode() === "rated" && this.ratedModeDisabled()) { - this.gameMode = this.propWithApply("casual"); + if (this.gameMode() === 'rated' && this.ratedModeDisabled()) { + this.gameMode = this.propWithApply('casual'); } if (this.ratingMin() === 0 && this.ratingMax() === 0) { @@ -184,11 +167,7 @@ export default class SetupController { }; private onPropChange = () => { this.enforcePropRules(); - if ( - this.root.data.ratingMap && - this.selectedPerf() && - !!this.root.data.ratingMap[this.selectedPerf()].prov - ) { + if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { this.savePropsToStoreExceptRating(); } else { this.savePropsToStore(); @@ -196,35 +175,26 @@ export default class SetupController { this.root.redraw(); }; - private propWithApply = (value: A) => - propWithEffect(value, this.onPropChange); + private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); private propWithApplyVariant = (value: A) => { const prop = propWithEffect(value, this.onVariantChange); return prop; }; - openModal = ( - gameType: GameType, - forceOptions?: ForceSetupOptions, - friendUser?: string - ) => { + openModal = (gameType: GameType, forceOptions?: ForceSetupOptions, friendUser?: string) => { this.root.leavePool(); this.gameType = gameType; this.loading = false; this.fenError = false; - this.lastValidFen = ""; - this.friendUser = friendUser || ""; + this.lastValidFen = ''; + this.friendUser = friendUser || ''; this.loadPropsFromStore(forceOptions); }; private onVariantChange = () => { // Handle rating update here - if ( - this.root.data.ratingMap && - this.selectedPerf() && - !!this.root.data.ratingMap[this.selectedPerf()].prov - ) { + if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { this.savePropsToStoreExceptRating(); } else { this.savePropsToStore(); @@ -242,9 +212,9 @@ export default class SetupController { if (!fen) return; xhr .text( - xhr.url("/setup/validate-fen", { + xhr.url('/setup/validate-fen', { fen, - strict: this.gameType === "ai" ? 1 : undefined, + strict: this.gameType === 'ai' ? 1 : undefined, }) ) .then( @@ -264,31 +234,30 @@ export default class SetupController { // anonymous games cannot be rated !this.root.me || // unlimited games cannot be rated - (this.gameType === "hook" && this.timeMode() === "unlimited") || + (this.gameType === 'hook' && this.timeMode() === 'unlimited') || // variants with very low time cannot be rated - (this.variant() !== "standard" && - (this.timeMode() !== "realTime" || + (this.variant() !== 'standard' && + (this.timeMode() !== 'realTime' || (this.time() < 0.5 && this.increment() == 0) || (this.time() == 0 && this.increment() < 2))); - selectedPerf = (): Perf => - getPerf(this.variant(), this.timeMode(), this.time(), this.increment()); + selectedPerf = (): Perf => getPerf(this.variant(), this.timeMode(), this.time(), this.increment()); ratingRange = (): string => { - if (!this.root.data.ratingMap) return ""; + if (!this.root.data.ratingMap) return ''; const rating = this.root.data.ratingMap[this.selectedPerf()].rating; return `${rating + this.ratingMin()}-${rating + this.ratingMax()}`; }; - hookToPoolMember = (color: Color | "random"): PoolMember | null => { + hookToPoolMember = (color: Color | 'random'): PoolMember | null => { const valid = - color == "random" && - this.gameType === "hook" && - this.variant() == "standard" && - this.gameMode() == "rated" && - this.timeMode() == "realTime"; + color == 'random' && + this.gameType === 'hook' && + this.variant() == 'standard' && + this.gameMode() == 'rated' && + this.timeMode() == 'realTime'; const id = `${this.time()}+${this.increment()}`; - return valid && this.root.pools.find((p) => p.id === id) + return valid && this.root.pools.find(p => p.id === id) ? { id, range: this.ratingRange(), @@ -296,7 +265,7 @@ export default class SetupController { : null; }; - propsToFormData = (color: Color | "random"): FormData => + propsToFormData = (color: Color | 'random'): FormData => xhr.form({ variant: keyToId(this.variant(), variants).toString(), fen: this.fen(), @@ -307,7 +276,7 @@ export default class SetupController { increment_range: this.incrementV().toString(), days: this.days().toString(), days_range: this.daysV().toString(), - mode: this.gameMode() === "casual" ? "0" : "1", + mode: this.gameMode() === 'casual' ? '0' : '1', ratingRange: this.ratingRange(), ratingRange_range_min: this.ratingMin().toString(), ratingRange_range_max: this.ratingMax().toString(), @@ -315,18 +284,13 @@ export default class SetupController { color, }); - validFen = (): boolean => this.variant() !== "fromPosition" || !this.fenError; - validTime = (): boolean => - this.timeMode() !== "realTime" || this.time() > 0 || this.increment() > 0; + validFen = (): boolean => this.variant() !== 'fromPosition' || !this.fenError; + validTime = (): boolean => this.timeMode() !== 'realTime' || this.time() > 0 || this.increment() > 0; validAiTime = (): boolean => - this.gameType !== "ai" || - this.timeMode() !== "realTime" || - this.variant() !== "fromPosition" || - this.time() >= 1; - valid = (): boolean => - this.validFen() && this.validTime() && this.validAiTime(); - - submit = async (color: Color | "random") => { + this.gameType !== 'ai' || this.timeMode() !== 'realTime' || this.variant() !== 'fromPosition' || this.time() >= 1; + valid = (): boolean => this.validFen() && this.validTime() && this.validAiTime(); + + submit = async (color: Color | 'random') => { const poolMember = this.hookToPoolMember(color); if (poolMember) { this.root.enterPool(poolMember); @@ -334,26 +298,23 @@ export default class SetupController { return; } - if (this.gameType === "hook") - this.root.setTab(this.timeMode() === "realTime" ? "real_time" : "seeks"); + if (this.gameType === 'hook') this.root.setTab(this.timeMode() === 'realTime' ? 'real_time' : 'seeks'); this.loading = true; this.root.redraw(); let urlPath = `/setup/${this.gameType}`; - if (this.gameType === "hook") urlPath += `/${lichess.sri}`; + if (this.gameType === 'hook') urlPath += `/${lichess.sri}`; const urlParams = { user: this.friendUser || undefined }; let response; try { response = await xhr.textRaw(xhr.url(urlPath, urlParams), { - method: "post", + method: 'post', body: this.propsToFormData(color), }); } catch (e) { this.loading = false; this.root.redraw(); - alert( - "Sorry, we encountered an error while creating your game. Please try again." - ); + alert('Sorry, we encountered an error while creating your game. Please try again.'); return; } @@ -364,9 +325,9 @@ export default class SetupController { alert( errs ? Object.keys(errs) - .map((k) => `${k}: ${errs[k]}`) - .join("\n") - : "Invalid setup" + .map(k => `${k}: ${errs[k]}`) + .join('\n') + : 'Invalid setup' ); if (response.status == 403) { // 403 FORBIDDEN closes this modal because challenges to the recipient diff --git a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts index 0beddbcb285f5..403f3696e07ae 100644 --- a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts +++ b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts @@ -1,5 +1,5 @@ -import { h } from "snabbdom"; -import LobbyController from "../../../ctrl"; +import { h } from 'snabbdom'; +import LobbyController from '../../../ctrl'; export const ratingDifferenceSliders = (ctrl: LobbyController) => { if (!ctrl.me || ctrl.opts.blindMode || !ctrl.data.ratingMap) return null; @@ -7,7 +7,7 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { const { trans, setupCtrl } = ctrl; const selectedPerf = ctrl.setupCtrl.selectedPerf(); const isProvisional = !!ctrl.data.ratingMap[selectedPerf].prov; - const disabled = isProvisional ? ".disabled" : ""; + const disabled = isProvisional ? '.disabled' : ''; // Get current rating values or use default values if isProvisional const currentRatingMin = isProvisional ? -500 : setupCtrl.ratingMin(); @@ -18,49 +18,46 @@ export const ratingDifferenceSliders = (ctrl: LobbyController) => { { attrs: isProvisional ? { - title: - "Your rating is still provisional, play some rated games to use the rating range.", + title: 'Your rating is still provisional, play some rated games to use the rating range.', } : undefined, }, [ - trans("ratingRange"), - h("div.rating-range", [ - h("input.range.rating-range__min", { + trans('ratingRange'), + h('div.rating-range', [ + h('input.range.rating-range__min', { attrs: { - type: "range", - min: "-500", - max: "0", - step: "50", + type: 'range', + min: '-500', + max: '0', + step: '50', value: currentRatingMin, disabled: isProvisional, }, on: { input: (e: Event) => { const newVal = parseInt((e.target as HTMLInputElement).value); - if (newVal === 0 && setupCtrl.ratingMax() === 0) - setupCtrl.ratingMax(50); + if (newVal === 0 && setupCtrl.ratingMax() === 0) setupCtrl.ratingMax(50); setupCtrl.ratingMin(newVal); }, }, }), - h("span.rating-min", "-" + Math.abs(currentRatingMin)), - "/", - h("span.rating-max", "+" + currentRatingMax), - h("input.range.rating-range__max", { + h('span.rating-min', '-' + Math.abs(currentRatingMin)), + '/', + h('span.rating-max', '+' + currentRatingMax), + h('input.range.rating-range__max', { attrs: { - type: "range", - min: "0", - max: "500", - step: "50", + type: 'range', + min: '0', + max: '500', + step: '50', value: currentRatingMax, disabled: isProvisional, }, on: { input: (e: Event) => { const newVal = parseInt((e.target as HTMLInputElement).value); - if (newVal === 0 && setupCtrl.ratingMin() === 0) - setupCtrl.ratingMin(-50); + if (newVal === 0 && setupCtrl.ratingMin() === 0) setupCtrl.ratingMin(-50); setupCtrl.ratingMax(newVal); }, }, diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index e8bf3db233a4d..67623a76b1aab 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -1,26 +1,20 @@ -import { onInsert } from "common/snabbdom"; -import { h } from "snabbdom"; -import LobbyController from "../../../ctrl"; -import { - variantsBlindMode, - variants, - variantsForGameType, -} from "../../../options"; -import { option } from "./option"; +import { onInsert } from 'common/snabbdom'; +import { h } from 'snabbdom'; +import LobbyController from '../../../ctrl'; +import { variantsBlindMode, variants, variantsForGameType } from '../../../options'; +import { option } from './option'; export const variantPicker = (ctrl: LobbyController) => { const { trans, setupCtrl, opts } = ctrl; const baseVariants = opts.blindMode ? variantsBlindMode : variants; - return h("div.variant.label-select", [ - h("label", { attrs: { for: "sf_variant" } }, trans("variant")), + return h('div.variant.label-select', [ + h('label', { attrs: { for: 'sf_variant' } }, trans('variant')), h( - "select#sf_variant", + 'select#sf_variant', { on: { change: (e: Event) => { - setupCtrl.variant( - (e.target as HTMLSelectElement).value as VariantKey - ); + setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey); if ( ctrl.data.ratingMap !== null && setupCtrl.selectedPerf() !== null && @@ -34,11 +28,9 @@ export const variantPicker = (ctrl: LobbyController) => { } }, }, - hook: onInsert((element) => element.focus()), + hook: onInsert(element => element.focus()), }, - variantsForGameType(baseVariants, setupCtrl.gameType!).map((variant) => - option(variant, setupCtrl.variant()) - ) + variantsForGameType(baseVariants, setupCtrl.gameType!).map(variant => option(variant, setupCtrl.variant())) ), ]); }; From b73fb463a678a1a86a5385dd08c9c793a087fd5a Mon Sep 17 00:00:00 2001 From: Aditya Jadhav Date: Sat, 27 May 2023 08:34:26 -0700 Subject: [PATCH 13/20] Fixed All issues with storing user selection of rating and changing rating as they switch variants --- ui/lobby/src/setupCtrl.ts | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index f4dd99ac7748f..999a6c50a6bb3 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -166,7 +166,6 @@ export default class SetupController { } }; private onPropChange = () => { - this.enforcePropRules(); if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { this.savePropsToStoreExceptRating(); } else { @@ -175,6 +174,23 @@ export default class SetupController { this.root.redraw(); }; + private onVariantChange = () => { + // Handle rating update here + this.enforcePropRules(); + if (this.root.data.ratingMap && this.selectedPerf() && this.root.data.ratingMap[this.selectedPerf()].prov) { + this.savePropsToStoreExceptRating(); + } else { + if (this.gameType) { + const ratingMin = this.store[this.gameType]().ratingMin; + const ratingMax = this.store[this.gameType]().ratingMax; + this.ratingMin(ratingMin); + this.ratingMax(ratingMax); + } + this.savePropsToStore(); + } + this.root.redraw(); + }; + private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); private propWithApplyVariant = (value: A) => { @@ -192,16 +208,6 @@ export default class SetupController { this.loadPropsFromStore(forceOptions); }; - private onVariantChange = () => { - // Handle rating update here - if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { - this.savePropsToStoreExceptRating(); - } else { - this.savePropsToStore(); - } - this.root.redraw(); - }; - closeModal = () => { this.gameType = null; this.root.redraw(); From 76ae50cedc0166c30c492d6b00697fe90ba7ea7a Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 30 May 2023 12:16:56 +0200 Subject: [PATCH 14/20] simplify lobby setupCtrl --- ui/lobby/src/setupCtrl.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 999a6c50a6bb3..ef0e6a939a87c 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -100,7 +100,7 @@ export default class SetupController { private loadPropsFromStore = (forceOptions?: ForceSetupOptions) => { const storeProps = this.store[this.gameType!](); // Load props from the store, but override any store values with values found in forceOptions - this.variant = this.propWithApplyVariant(forceOptions?.variant || storeProps.variant); + this.variant = propWithEffect(forceOptions?.variant || storeProps.variant, this.onVariantChange); this.fen = this.propWithApply(forceOptions?.fen || storeProps.fen); this.timeMode = this.propWithApply(forceOptions?.timeMode || storeProps.timeMode); this.timeV = this.propWithApply(sliderInitVal(storeProps.time, timeVToTime, 100)!); @@ -147,6 +147,7 @@ export default class SetupController { ratingMax: this.ratingMax(), aiLevel: this.aiLevel(), }); + private savePropsToStoreExceptRating = () => { if (this.gameType && this.store[this.gameType]) { const ratingMin = this.store[this.gameType]().ratingMin; @@ -166,11 +167,9 @@ export default class SetupController { } }; private onPropChange = () => { - if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { + if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) this.savePropsToStoreExceptRating(); - } else { - this.savePropsToStore(); - } + else this.savePropsToStore(); this.root.redraw(); }; @@ -193,11 +192,6 @@ export default class SetupController { private propWithApply = (value: A) => propWithEffect(value, this.onPropChange); - private propWithApplyVariant = (value: A) => { - const prop = propWithEffect(value, this.onVariantChange); - return prop; - }; - openModal = (gameType: GameType, forceOptions?: ForceSetupOptions, friendUser?: string) => { this.root.leavePool(); this.gameType = gameType; From 6b75a883e9f11f1f1d5d19a812337919f6313ece Mon Sep 17 00:00:00 2001 From: Aditya Jadhav Date: Wed, 31 May 2023 10:57:32 -0700 Subject: [PATCH 15/20] Removed elements that should not be part of frontend --- ui/lobby/src/setupCtrl.ts | 20 +++++++++---------- .../view/setup/components/variantPicker.ts | 17 ++-------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 999a6c50a6bb3..cdcb9e691192f 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -147,11 +147,10 @@ export default class SetupController { ratingMax: this.ratingMax(), aiLevel: this.aiLevel(), }); - private savePropsToStoreExceptRating = () => { - if (this.gameType && this.store[this.gameType]) { - const ratingMin = this.store[this.gameType]().ratingMin; - const ratingMax = this.store[this.gameType]().ratingMax; - this.store[this.gameType]({ + +private savePropsToStoreExceptRating = () => + this.gameType && + this.store[this.gameType]({ variant: this.variant(), fen: this.fen(), timeMode: this.timeMode(), @@ -159,12 +158,11 @@ export default class SetupController { increment: this.increment(), days: this.days(), gameMode: this.gameMode(), - ratingMin: ratingMin, - ratingMax: ratingMax, + ratingMin: this.store[this.gameType]().ratingMin, + ratingMax: this.store[this.gameType]().ratingMax, aiLevel: this.aiLevel(), - }); - } - }; + }); + private onPropChange = () => { if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) { this.savePropsToStoreExceptRating(); @@ -178,6 +176,8 @@ export default class SetupController { // Handle rating update here this.enforcePropRules(); if (this.root.data.ratingMap && this.selectedPerf() && this.root.data.ratingMap[this.selectedPerf()].prov) { + this.ratingMin(-500); + this.ratingMax(500); this.savePropsToStoreExceptRating(); } else { if (this.gameType) { diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index 67623a76b1aab..79a279b78d718 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -13,24 +13,11 @@ export const variantPicker = (ctrl: LobbyController) => { 'select#sf_variant', { on: { - change: (e: Event) => { - setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey); - if ( - ctrl.data.ratingMap !== null && - setupCtrl.selectedPerf() !== null && - ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov - ) { - // Check if the rating is provisional - if (ctrl.data.ratingMap[setupCtrl.selectedPerf()].prov) { - setupCtrl.ratingMin(-500); // Set ratingMin to -500 for provisional rating - setupCtrl.ratingMax(500); - } - } - }, + change: (e: Event) => setupCtrl.variant((e.target as HTMLSelectElement).value as VariantKey), }, hook: onInsert(element => element.focus()), }, variantsForGameType(baseVariants, setupCtrl.gameType!).map(variant => option(variant, setupCtrl.variant())) ), ]); -}; +}; \ No newline at end of file From d510038cc97295b3e0a196c9553bda13b65fa17c Mon Sep 17 00:00:00 2001 From: Aditya Jadhav Date: Wed, 31 May 2023 11:14:39 -0700 Subject: [PATCH 16/20] prettier formatting --- ui/lobby/src/view/setup/components/variantPicker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index 79a279b78d718..64f5e64248095 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -20,4 +20,4 @@ export const variantPicker = (ctrl: LobbyController) => { variantsForGameType(baseVariants, setupCtrl.gameType!).map(variant => option(variant, setupCtrl.variant())) ), ]); -}; \ No newline at end of file +}; From db97e7a57bc564996bcefdadb144f271a535e9f5 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 5 Jun 2023 11:17:04 +0200 Subject: [PATCH 17/20] remove superfluous check, the type says it always returns a Perf --- ui/lobby/src/setupCtrl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 246fa9b6509fa..1fbe627a11751 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -166,7 +166,7 @@ export default class SetupController { }); private onPropChange = () => { - if (this.root.data.ratingMap && this.selectedPerf() && !!this.root.data.ratingMap[this.selectedPerf()].prov) + if (this.root.data.ratingMap && !!this.root.data.ratingMap[this.selectedPerf()].prov) this.savePropsToStoreExceptRating(); else this.savePropsToStore(); this.root.redraw(); @@ -175,7 +175,7 @@ export default class SetupController { private onVariantChange = () => { // Handle rating update here this.enforcePropRules(); - if (this.root.data.ratingMap && this.selectedPerf() && this.root.data.ratingMap[this.selectedPerf()].prov) { + if (this.root.data.ratingMap && this.root.data.ratingMap[this.selectedPerf()].prov) { this.ratingMin(-500); this.ratingMax(500); this.savePropsToStoreExceptRating(); From d5f17c3d9d32ffc447f41b69fc69225cac5de7eb Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 5 Jun 2023 11:21:33 +0200 Subject: [PATCH 18/20] fix duplicated code, fix bug when ratingMap[perf] doesn't exist --- ui/lobby/src/setupCtrl.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 1fbe627a11751..825004ececa8f 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -165,9 +165,13 @@ export default class SetupController { aiLevel: this.aiLevel(), }); + private isProvisional = () => { + const rating = this.root.data.ratingMap && this.root.data.ratingMap[this.selectedPerf()]; + return rating?.prov ?? true; + }; + private onPropChange = () => { - if (this.root.data.ratingMap && !!this.root.data.ratingMap[this.selectedPerf()].prov) - this.savePropsToStoreExceptRating(); + if (!this.isProvisional()) this.savePropsToStoreExceptRating(); else this.savePropsToStore(); this.root.redraw(); }; @@ -175,7 +179,7 @@ export default class SetupController { private onVariantChange = () => { // Handle rating update here this.enforcePropRules(); - if (this.root.data.ratingMap && this.root.data.ratingMap[this.selectedPerf()].prov) { + if (!this.isProvisional()) { this.ratingMin(-500); this.ratingMax(500); this.savePropsToStoreExceptRating(); From 06f5a0ae904663101356e6ccf55e9e6edfac5be8 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 5 Jun 2023 11:24:35 +0200 Subject: [PATCH 19/20] fix more duplicated code --- ui/lobby/src/setupCtrl.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 825004ececa8f..e47c9a91291d2 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -135,7 +135,7 @@ export default class SetupController { } }; - private savePropsToStore = () => + private savePropsToStore = (override: Partial = {}) => this.gameType && this.store[this.gameType]({ variant: this.variant(), @@ -148,21 +148,14 @@ export default class SetupController { ratingMin: this.ratingMin(), ratingMax: this.ratingMax(), aiLevel: this.aiLevel(), + ...override, }); private savePropsToStoreExceptRating = () => this.gameType && - this.store[this.gameType]({ - variant: this.variant(), - fen: this.fen(), - timeMode: this.timeMode(), - time: this.time(), - increment: this.increment(), - days: this.days(), - gameMode: this.gameMode(), + this.savePropsToStore({ ratingMin: this.store[this.gameType]().ratingMin, ratingMax: this.store[this.gameType]().ratingMax, - aiLevel: this.aiLevel(), }); private isProvisional = () => { From 1484a6b19fd678021fa44b764e49aa79e5d429f2 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 5 Jun 2023 11:31:35 +0200 Subject: [PATCH 20/20] setup rating: final checks and simplification --- ui/lobby/src/setupCtrl.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index e47c9a91291d2..e42f7905389d8 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -160,11 +160,11 @@ export default class SetupController { private isProvisional = () => { const rating = this.root.data.ratingMap && this.root.data.ratingMap[this.selectedPerf()]; - return rating?.prov ?? true; + return rating ? !!rating.prov : true; }; private onPropChange = () => { - if (!this.isProvisional()) this.savePropsToStoreExceptRating(); + if (this.isProvisional()) this.savePropsToStoreExceptRating(); else this.savePropsToStore(); this.root.redraw(); }; @@ -172,16 +172,14 @@ export default class SetupController { private onVariantChange = () => { // Handle rating update here this.enforcePropRules(); - if (!this.isProvisional()) { + if (this.isProvisional()) { this.ratingMin(-500); this.ratingMax(500); this.savePropsToStoreExceptRating(); } else { if (this.gameType) { - const ratingMin = this.store[this.gameType]().ratingMin; - const ratingMax = this.store[this.gameType]().ratingMax; - this.ratingMin(ratingMin); - this.ratingMax(ratingMax); + this.ratingMin(this.store[this.gameType]().ratingMin); + this.ratingMax(this.store[this.gameType]().ratingMax); } this.savePropsToStore(); }