Skip to content

Commit

Permalink
Add support for selecting multiple acceptable size/time settings
Browse files Browse the repository at this point in the history
  • Loading branch information
anoek committed Dec 6, 2024
1 parent 38b80e0 commit 0f74538
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 57 deletions.
6 changes: 5 additions & 1 deletion src/lib/automatch_manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
11 changes: 10 additions & 1 deletion src/lib/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,23 @@ 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",
"automatch.bot": 0,
"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,
Expand Down
15 changes: 0 additions & 15 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
6 changes: 2 additions & 4 deletions src/views/Play/CustomGames.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,8 @@ export function CustomGames(): JSX.Element {
.join(",")}
</span>

<span className={m.time_control.condition + " cell"}>
{m.time_control.condition === "no-preference"
? pgettext("Automatch: no preference", "No preference")
: timeControlSystemText(m.time_control.value.system)}
<span className={m.size_speed_options[0].system + " cell"}>
{timeControlSystemText(m.size_speed_options[0].system)}
</span>

<span className={m.handicap.condition + " cell"}>
Expand Down
11 changes: 9 additions & 2 deletions src/views/Play/QuickMatch.styl
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@
}

.speed-options {
margin-bottom: 2rem;
//margin-bottom: 2rem;
}

.opponent-options {
Expand Down Expand Up @@ -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) {
Expand Down
171 changes: 137 additions & 34 deletions src/views/Play/QuickMatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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(),
Expand All @@ -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",
Expand All @@ -236,6 +276,8 @@ export function QuickMatch(): JSX.Element {
refresh,
automatch_manager,
setCorrespondenceSpinner,
multiple_sizes,
multiple_speeds,
]);

const playComputer = React.useCallback(() => {
Expand Down Expand Up @@ -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 (
<>
Expand All @@ -418,11 +524,11 @@ export function QuickMatch(): JSX.Element {
<div style={{ textAlign: "center" }}>
{(["9x9", "13x13", "19x19"] as Size[]).map((s) => (
<button
className={"btn" + (s === board_size ? " active" : "")}
className={"btn" + (isSizeActive(s) ? " active" : "")}
key={s}
disabled={search_active}
onClick={() => {
setBoardSize(s);
toggleSize(s);
}}
>
{s}
Expand Down Expand Up @@ -455,15 +561,22 @@ export function QuickMatch(): JSX.Element {
value={game_clock_options.find((o) => o.value === game_clock)}
onChange={(opt) => {
if (opt) {
setGameClock(opt.value as "flexible" | "exact");
setGameClock(opt.value as "flexible" | "exact" | "multiple");
if (opt.value === "multiple") {
setOpponent("human");
}
}
}}
options={game_clock_options}
components={{ Option: RenderOptionWithDescription }}
/>
</div>

<div className="speed-options">
{game_clock === "multiple" && (
<div className="multiple-options-description">
{_("Select all the settings you are comfortable playing with.")}
</div>
)}
{(
["blitz", "rapid", "live", "correspondence"] as JGOFTimeControlSpeed[]
).map((speed) => {
Expand All @@ -480,16 +593,6 @@ export function QuickMatch(): JSX.Element {
>
<div className="game-speed-title">
<span className="description">{opt.time_estimate}</span>
{/*
<span className="description">
{opt.fischer.time_estimate || opt.time_estimate}
</span>
{opt.byoyomi?.time_estimate && (
<span className="description">
{opt.byoyomi.time_estimate}
</span>
)}
*/}
</div>
<div
className={
Expand All @@ -502,15 +605,17 @@ export function QuickMatch(): JSX.Element {
<button
className={
"time-control-button" +
(game_speed === speed &&
time_control_system === "fischer"
(isSpeedSystemActive(speed, "fischer")
? " active"
: "")
}
disabled={search_active}
disabled={
search_active ||
(game_clock === "multiple" &&
speed === "correspondence")
}
onClick={() => {
setGameSpeed(speed);
setTimeControlSystem("fischer");
toggleSpeedSystem(speed, "fischer");
}}
>
{shortDurationString(opt.fischer.initial_time)}
Expand All @@ -533,14 +638,12 @@ export function QuickMatch(): JSX.Element {
<button
className={
"time-control-button" +
(game_speed === speed &&
time_control_system === "byoyomi"
(isSpeedSystemActive(speed, "byoyomi")
? " active"
: "")
}
onClick={() => {
setGameSpeed(speed);
setTimeControlSystem("byoyomi");
toggleSpeedSystem(speed, "byoyomi");
}}
disabled={search_active}
>
Expand Down Expand Up @@ -621,10 +724,10 @@ export function QuickMatch(): JSX.Element {
className={
"opponent-option-container " +
(opponent === "bot" ? "active" : "") +
(search_active ? " disabled" : "")
(search_active || game_clock === "multiple" ? " disabled" : "")
}
onClick={() => {
if (search_active) {
if (search_active || game_clock === "multiple") {
return;
}
setOpponent("bot");
Expand Down

0 comments on commit 0f74538

Please sign in to comment.