Skip to content

Commit 67086f2

Browse files
author
Oskar Widmark
committed
feat: algorithm options
1 parent 6f1025e commit 67086f2

File tree

7 files changed

+238
-35
lines changed

7 files changed

+238
-35
lines changed

src/App.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ResetFunction,
99
Operator,
1010
SortType,
11+
AlgorithmOptions,
1112
} from './types';
1213
import { SortingAlgorithms } from './sorting-algorithms';
1314
import {
@@ -22,6 +23,7 @@ import {
2223
INIT_COLUMN_NUMBER,
2324
INIT_SWAP_TIME,
2425
INIT_COMPARE_TIME,
26+
DEFAULT_ALGORITHM_OPTIONS,
2527
} from './constants';
2628
import { SortAppBar } from './AppBar';
2729
import { CanvasController } from './canvas-controller';
@@ -52,6 +54,7 @@ class App extends React.Component<Props> {
5254
shouldHighlightSwaps: boolean;
5355
shouldHighlightComparisons: boolean;
5456
shouldPlaySound: boolean;
57+
algorithmOptions: AlgorithmOptions;
5558
};
5659
canvasController: CanvasController;
5760

@@ -80,6 +83,7 @@ class App extends React.Component<Props> {
8083
shouldHighlightSwaps: true,
8184
shouldHighlightComparisons: false,
8285
shouldPlaySound: false,
86+
algorithmOptions: DEFAULT_ALGORITHM_OPTIONS,
8387
};
8488

8589
this.resetPresets = {
@@ -142,7 +146,7 @@ class App extends React.Component<Props> {
142146
try {
143147
await this.sortingAlgorithms.getSortingAlgorithm(
144148
this.state.chosenSortAlg,
145-
)(arr);
149+
)(arr, this.state.algorithmOptions);
146150
} catch (e) {
147151
console.error('Sorting interrupted! Reason: ', e);
148152
}
@@ -313,6 +317,15 @@ class App extends React.Component<Props> {
313317
this.props.stopSounds();
314318
};
315319

320+
setAlgorithmOption = (
321+
key: keyof AlgorithmOptions,
322+
value: AlgorithmOptions[typeof key],
323+
) => {
324+
this.setState((prevState: typeof this.state) => ({
325+
algorithmOptions: { ...prevState.algorithmOptions, [key]: value },
326+
}));
327+
};
328+
316329
render() {
317330
return (
318331
<div className="App">
@@ -358,6 +371,8 @@ class App extends React.Component<Props> {
358371
changeSwapTime={this.changeSwapTime}
359372
changeCompareTime={this.changeCompareTime}
360373
columnNbr={this.state.columnNbr}
374+
algorithmOptions={this.state.algorithmOptions}
375+
setAlgorithmOption={this.setAlgorithmOption}
361376
/>
362377
</div>
363378
</div>

src/Options.tsx

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import {
2+
FormControl,
3+
Typography,
4+
MenuItem,
5+
Grid2,
6+
TextField,
7+
} from '@mui/material';
8+
import { AlgorithmOptions, SortName } from './types';
9+
import { useCallback, useState } from 'react';
10+
11+
const getAlgorithmOptionFields = (
12+
sortName: SortName,
13+
): (keyof AlgorithmOptions)[] => {
14+
switch (sortName) {
15+
case SortName.BitonicSort:
16+
return ['type'];
17+
case SortName.RadixSortLSD:
18+
case SortName.RadixSortMSD:
19+
return ['base'];
20+
case SortName.CombSort:
21+
return ['shrinkFactor'];
22+
default:
23+
return [];
24+
}
25+
};
26+
27+
const isValidOption = (field: keyof AlgorithmOptions, value: unknown) => {
28+
switch (field) {
29+
case 'base':
30+
return Number(value) >= 2 && Number.isInteger(Number(value));
31+
case 'shrinkFactor':
32+
return Number(value) > 1;
33+
default:
34+
return true;
35+
}
36+
};
37+
38+
const ALGORITHM_OPTION_LABELS: Record<keyof AlgorithmOptions, string> = {
39+
type: 'Type',
40+
base: 'Base',
41+
shrinkFactor: 'Shrink Factor',
42+
};
43+
44+
const ALGORITHM_OPTION_TEXT_FIELD_TYPES: Record<
45+
keyof AlgorithmOptions,
46+
string
47+
> = {
48+
type: 'select',
49+
base: 'number',
50+
shrinkFactor: 'number',
51+
};
52+
53+
const ALGORITHM_OPTION_VALUES: Record<
54+
keyof AlgorithmOptions,
55+
AlgorithmOptions[keyof AlgorithmOptions][]
56+
> = {
57+
type: ['iterative', 'recursive'],
58+
base: [],
59+
shrinkFactor: [],
60+
};
61+
62+
const ALGORITHM_OPTION_VALUE_LABELS: Record<
63+
AlgorithmOptions[keyof AlgorithmOptions],
64+
string
65+
> = {
66+
iterative: 'Iterative',
67+
recursive: 'Recursive',
68+
};
69+
70+
interface OptionsProps {
71+
chosenSortAlg: SortName;
72+
algorithmOptions: AlgorithmOptions;
73+
setAlgorithmOption: (
74+
key: keyof AlgorithmOptions,
75+
value: AlgorithmOptions[typeof key],
76+
) => void;
77+
}
78+
79+
export function Options({
80+
chosenSortAlg,
81+
algorithmOptions,
82+
setAlgorithmOption,
83+
}: OptionsProps): React.ReactElement | null {
84+
const [nonValidatedOptions, setNonValidatedOptions] =
85+
useState<AlgorithmOptions>({ ...algorithmOptions });
86+
87+
const handleOptionChange = useCallback(
88+
(
89+
field: keyof AlgorithmOptions,
90+
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
91+
) => {
92+
setNonValidatedOptions({
93+
...nonValidatedOptions,
94+
[field]: event.target.value,
95+
});
96+
97+
if (isValidOption(field, event.target.value)) {
98+
setAlgorithmOption(
99+
field,
100+
event.target.value as AlgorithmOptions[typeof field],
101+
);
102+
}
103+
},
104+
[nonValidatedOptions, setAlgorithmOption],
105+
);
106+
107+
const algorithmOptionFields = getAlgorithmOptionFields(chosenSortAlg);
108+
if (algorithmOptionFields.length === 0) {
109+
return null;
110+
}
111+
112+
return (
113+
<div>
114+
<Typography align="left" variant="h6" color="textSecondary" gutterBottom>
115+
Options
116+
</Typography>
117+
<Grid2 container spacing={2}>
118+
{algorithmOptionFields.map((field) => (
119+
<FormControl component="fieldset">
120+
<TextField
121+
select={ALGORITHM_OPTION_TEXT_FIELD_TYPES[field] === 'select'}
122+
label={ALGORITHM_OPTION_LABELS[field]}
123+
value={nonValidatedOptions[field]}
124+
onChange={(event) => handleOptionChange(field, event)}
125+
error={!isValidOption(field, nonValidatedOptions[field])}
126+
size="small"
127+
sx={{ width: 120 }}
128+
type={
129+
ALGORITHM_OPTION_TEXT_FIELD_TYPES[field] === 'select'
130+
? undefined
131+
: ALGORITHM_OPTION_TEXT_FIELD_TYPES[field]
132+
}
133+
>
134+
{Object.values(ALGORITHM_OPTION_VALUES[field]).map((v) => (
135+
<MenuItem key={v} value={v}>
136+
<Typography
137+
align="left"
138+
variant="body1"
139+
color="textSecondary"
140+
>
141+
{ALGORITHM_OPTION_VALUE_LABELS[v] ?? v}
142+
</Typography>
143+
</MenuItem>
144+
))}
145+
</TextField>
146+
</FormControl>
147+
))}
148+
</Grid2>
149+
</div>
150+
);
151+
}

src/SideDrawer.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Slider,
99
SelectChangeEvent,
1010
} from '@mui/material';
11-
import { SortName, ResetPreset } from './types';
11+
import { SortName, ResetPreset, AlgorithmOptions } from './types';
1212
import { timeScale } from './utils';
1313
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
1414
import {
@@ -18,6 +18,7 @@ import {
1818
POWERS_OF_TWO,
1919
} from './constants';
2020
import { useEffect } from 'react';
21+
import { Options } from './Options';
2122

2223
interface SideDrawerProps {
2324
areSettingsOpen: boolean;
@@ -30,6 +31,11 @@ interface SideDrawerProps {
3031
resetPreset: ResetPreset;
3132
chooseResetPreset: (event: SelectChangeEvent<ResetPreset>) => void;
3233
columnNbr: number;
34+
algorithmOptions: AlgorithmOptions;
35+
setAlgorithmOption: (
36+
key: keyof AlgorithmOptions,
37+
value: AlgorithmOptions[typeof key],
38+
) => void;
3339
}
3440

3541
export function SideDrawer({
@@ -43,10 +49,10 @@ export function SideDrawer({
4349
resetPreset,
4450
chooseResetPreset,
4551
areSettingsOpen,
52+
algorithmOptions,
53+
setAlgorithmOption,
4654
}: SideDrawerProps) {
47-
const isBitonicSort =
48-
chosenSortAlg === SortName.IterBitonicSort ||
49-
chosenSortAlg === SortName.RecBitonicSort;
55+
const isBitonicSort = chosenSortAlg === SortName.BitonicSort;
5056

5157
useEffect(() => {
5258
// Bitonic Sort requires a power of two
@@ -91,6 +97,11 @@ export function SideDrawer({
9197
</Select>
9298
</FormControl>
9399
</div>
100+
<Options
101+
chosenSortAlg={chosenSortAlg}
102+
algorithmOptions={algorithmOptions}
103+
setAlgorithmOption={setAlgorithmOption}
104+
/>
94105
<div>
95106
<Typography
96107
align="left"

src/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
import { AlgorithmOptions } from './types';
2+
13
export const INIT_SWAP_TIME = 1;
24
export const INIT_COMPARE_TIME = 1;
35
export const INIT_COLUMN_NUMBER = 100;
46
export const HIGHLIGHT_COLOR = '#FFFFFF';
57
export const POWERS_OF_TWO = [8, 16, 32, 64, 128, 256, 512, 1024];
8+
export const DEFAULT_ALGORITHM_OPTIONS: AlgorithmOptions = {
9+
type: 'iterative',
10+
base: 4,
11+
shrinkFactor: 1.3,
12+
};

0 commit comments

Comments
 (0)