diff --git a/src/lib/automatch_manager.tsx b/src/lib/automatch_manager.tsx index a375c1a1bc..e4273be25a 100644 --- a/src/lib/automatch_manager.tsx +++ b/src/lib/automatch_manager.tsx @@ -31,7 +31,11 @@ interface Events { export type AutomatchPreferences = AutomatchPreferencesBase & { uuid: string; - size_speed_options: Array<{ size: Size; speed: Speed }>; + size_speed_options: Array<{ + size: Size; + speed: Speed; + system: "byoyomi" | "fischer"; + }>; }; class AutomatchToast extends React.PureComponent<{}, any> { diff --git a/src/lib/preferences.ts b/src/lib/preferences.ts index a3b03893bc..be6d596541 100644 --- a/src/lib/preferences.ts +++ b/src/lib/preferences.ts @@ -34,7 +34,7 @@ export const defaults = { "play.tab": "automatch" as "automatch" | "custom", "automatch.size": "9x9" as Size, "automatch.speed": "rapid" as JGOFTimeControlSpeed, - "automatch.game-clock": "flexible" as "exact" | "flexible", + "automatch.game-clock": "flexible" as "exact" | "flexible" | "multiple", "automatch.handicaps": "standard" as "enabled" | "standard" | "disabled", "automatch.time-control": "fischer" as "fischer" | "byoyomi", "automatch.opponent": "human" as "human" | "bot", @@ -42,6 +42,15 @@ export const defaults = { "automatch.lower-rank-diff": 3, "automatch.upper-rank-diff": 3, "automatch.show-custom-games": false, + "automatch.multiple-sizes": { "9x9": false, "13x13": false, "19x19": false }, + "automatch.multiple-speeds": { + "blitz-fischer": false, + "blitz-byoyomi": false, + "rapid-fischer": false, + "rapid-byoyomi": false, + "live-fischer": false, + "live-byoyomi": false, + }, "board-labeling": "automatic", "chat.show-all-global-channels": true, "chat.show-all-group-channels": true, diff --git a/src/lib/types.ts b/src/lib/types.ts index b9647cf50e..252f1026ca 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -100,21 +100,6 @@ export interface AutomatchPreferencesBase { condition: AutomatchCondition; value: "japanese" | "chinese" | "aga" | "korean" | "nz" | "ing"; }; - time_control: { - condition: AutomatchCondition; - value: { - system: AutomatchTimeControlSystem; - initial_time?: number; - time_increment?: number; - max_time?: number; - main_time?: number; - period_time?: number; - periods?: number; - stones_per_period?: number; - per_move?: number; - pause_on_weekends?: boolean; - }; - }; handicap: { condition: AutomatchCondition; value: "enabled" | "disabled"; diff --git a/src/views/Play/CustomGames.tsx b/src/views/Play/CustomGames.tsx index 786fd94226..bb94641fc1 100644 --- a/src/views/Play/CustomGames.tsx +++ b/src/views/Play/CustomGames.tsx @@ -567,10 +567,8 @@ export function CustomGames(): JSX.Element { .join(",")} - - {m.time_control.condition === "no-preference" - ? pgettext("Automatch: no preference", "No preference") - : timeControlSystemText(m.time_control.value.system)} + + {timeControlSystemText(m.size_speed_options[0].system)} diff --git a/src/views/Play/QuickMatch.styl b/src/views/Play/QuickMatch.styl index ffd045907d..c66b427417 100644 --- a/src/views/Play/QuickMatch.styl +++ b/src/views/Play/QuickMatch.styl @@ -385,7 +385,7 @@ } .speed-options { - margin-bottom: 2rem; + //margin-bottom: 2rem; } .opponent-options { @@ -539,7 +539,14 @@ } } - + .multiple-options-description { + font-size: 0.9rem; + font-style: italic; + themed color shade1 + padding-right: 0.5rem; + padding-left: 0.5rem; + margin-bottom: 0.5rem; + } } @media (max-width: hamburger-cutoff) { diff --git a/src/views/Play/QuickMatch.tsx b/src/views/Play/QuickMatch.tsx index 3258dc0701..56ac1edb6b 100644 --- a/src/views/Play/QuickMatch.tsx +++ b/src/views/Play/QuickMatch.tsx @@ -78,6 +78,14 @@ const game_clock_options: OptionWithDescription[] = [ "Prefer one time setting, but accept the other similarly paced time setting", ), }, + { + value: "multiple", + label: _("Multiple"), + description: pgettext( + "Game Clock option description for being able to choose between multiple time settings", + "Pick multiple acceptable time settings", + ), + }, ]; const handicap_options: OptionWithDescription[] = [ @@ -159,6 +167,13 @@ export function QuickMatch(): JSX.Element { const cancel_bot_game = React.useRef<() => void>(() => {}); const [game_clock, setGameClock] = preferences.usePreference("automatch.game-clock"); + const [multiple_sizes, setMultipleSizes] = preferences.usePreference( + "automatch.multiple-sizes", + ); + const [multiple_speeds, setMultipleSpeeds] = preferences.usePreference( + "automatch.multiple-speeds", + ); + React.useEffect(() => { automatch_manager.on("entry", refresh); automatch_manager.on("start", refresh); @@ -192,9 +207,40 @@ export function QuickMatch(): JSX.Element { // Open challenge console.log("findMatch", board_size, game_speed); - const size_speed_options: Array<{ size: Size; speed: Speed }> = [ - { size: board_size, speed: game_speed }, - ]; + const size_speed_options: Array<{ + size: Size; + speed: Speed; + system: "fischer" | "byoyomi"; + }> = []; + + if (game_clock === "exact" || game_clock === "flexible") { + size_speed_options.push({ + size: board_size, + speed: game_speed, + system: time_control_system, + }); + if (game_clock === "flexible" && game_speed !== "correspondence") { + size_speed_options.push({ + size: board_size, + speed: game_speed, + system: time_control_system === "fischer" ? "byoyomi" : "fischer", + }); + } + } else { + for (const size in multiple_sizes) { + if (multiple_sizes[size as keyof typeof multiple_sizes]) { + for (const speed_system in multiple_speeds) { + if (multiple_speeds[speed_system as keyof typeof multiple_speeds]) { + const [speed, system] = speed_system.split("-"); + size_speed_options.push({ size, speed, system } as any); + } + } + } + } + + // shuffle the options so we aren't biasing towards the same settings all the time + size_speed_options.sort(() => Math.random() - 0.5); + } const preferences: AutomatchPreferences = { uuid: uuid(), @@ -205,12 +251,6 @@ export function QuickMatch(): JSX.Element { condition: "required", value: "japanese", }, - time_control: { - condition: game_clock === "flexible" ? "preferred" : "required", - value: { - system: time_control_system, - }, - }, handicap: { condition: handicaps === "standard" ? "preferred" : "required", value: handicaps === "disabled" ? "disabled" : "enabled", @@ -236,6 +276,8 @@ export function QuickMatch(): JSX.Element { refresh, automatch_manager, setCorrespondenceSpinner, + multiple_sizes, + multiple_speeds, ]); const playComputer = React.useCallback(() => { @@ -405,6 +447,70 @@ export function QuickMatch(): JSX.Element { const search_active = !!automatch_manager.active_live_automatcher || correspondence_spinner || bot_spinner; + function isSizeActive(size: Size) { + if (game_clock === "multiple") { + return multiple_sizes[size]; + } else { + return board_size === size; + } + } + + function isSpeedSystemActive(speed: JGOFTimeControlSpeed, system: "fischer" | "byoyomi") { + if (game_clock === "multiple") { + return multiple_speeds[`${speed as "blitz" | "rapid" | "live"}-${system}`]; + } else { + return game_speed === speed && time_control_system === system; + } + } + + function toggleSpeedSystem(speed: JGOFTimeControlSpeed, system: "fischer" | "byoyomi") { + if (game_clock === "multiple") { + const new_speeds = { + ...multiple_speeds, + [`${speed as "blitz" | "rapid" | "live"}-${system}`]: + !multiple_speeds[`${speed as "blitz" | "rapid" | "live"}-${system}`], + }; + delete (new_speeds as any)["correspondence-fischer"]; + delete (new_speeds as any)["correspondence-byoyomi"]; + + if (Object.values(new_speeds).filter((x) => x).length > 0) { + setMultipleSpeeds(new_speeds); + } + } else { + setGameSpeed(speed); + setTimeControlSystem(system); + } + } + + function toggleSize(size: Size) { + if (game_clock === "multiple") { + const new_sizes = { + ...multiple_sizes, + [size]: !multiple_sizes[size], + }; + + if (Object.values(new_sizes).filter((x) => x).length > 0) { + setMultipleSizes(new_sizes); + } + } else { + setBoardSize(size); + } + } + + // nothing selected? Select what we last had selected + if (game_clock === "multiple") { + if (Object.values(multiple_sizes).filter((x) => x).length === 0) { + toggleSize(board_size); + } + if (Object.values(multiple_speeds).filter((x) => x).length === 0) { + if (game_speed !== "correspondence") { + toggleSpeedSystem(game_speed, time_control_system); + } else { + toggleSpeedSystem("rapid", time_control_system); + } + } + } + // Construction of the pane we need to show... return ( <> @@ -418,11 +524,11 @@ export function QuickMatch(): JSX.Element {
{(["9x9", "13x13", "19x19"] as Size[]).map((s) => (
-
+ {game_clock === "multiple" && ( +
+ {_("Select all the settings you are comfortable playing with.")} +
+ )} {( ["blitz", "rapid", "live", "correspondence"] as JGOFTimeControlSpeed[] ).map((speed) => { @@ -480,16 +593,6 @@ export function QuickMatch(): JSX.Element { >
{opt.time_estimate} - {/* - - {opt.fischer.time_estimate || opt.time_estimate} - - {opt.byoyomi?.time_estimate && ( - - {opt.byoyomi.time_estimate} - - )} - */}
{ - setGameSpeed(speed); - setTimeControlSystem("fischer"); + toggleSpeedSystem(speed, "fischer"); }} > {shortDurationString(opt.fischer.initial_time)} @@ -533,14 +638,12 @@ export function QuickMatch(): JSX.Element {