Skip to content

Commit

Permalink
UI responsiveness (RodrigoDLPontes#249)
Browse files Browse the repository at this point in the history
* Add invalid input responses to Brute Force

* Add invalid input responses to Boyer Moore

* Add invalid input responses to KMP

* Add invalid input responses to Rabin Karp

* Fix text alignment issue in StackArray popping

Popped element now displays in same location as pushed elements rather than being concatenated to the label string, which causes alignment issues

* Fix text alignment issue in popping for StackLL, QueueArray, QueueLL

* Fix various inconsistencies in Dequeues

* Add invalid input responses to BuildHeap

* Fix Load Factor text alignment & input

Even though the text box allowed for 5 digits of precision for load factor, only a 1 or 2-digit number was considered valid in the code. I reduced the text box to 3 digits (I see no reason for more) and fixed the validation code.

* Prettier formatting

* Make LF inputs/display consistent in both HashMaps

* Add invalid input responses to Graph algos

* Add invalid input responses to sorts

* Add invalid input responses & length display to LCS

* Fix info label clear on HeapSort start

* Clear button resets text input fields

* Make text input fields persistent when algo is run

This change makes it so input fields for pattern matching and sorts will retain the data typed into them, allowing for easier re-runs and editing. The fields will be cleared when the clear button is pressed.

* Add Clear button to LCS

* Prettier formatting

* Fix resetAll calls in HashMaps

* Add Length of LCS label & fix redundancy

* Fix nextIndex increment in Deque/Queue/Stack Arrays
  • Loading branch information
luciankt authored May 25, 2023
1 parent 6ba3088 commit 5f44986
Show file tree
Hide file tree
Showing 37 changed files with 806 additions and 334 deletions.
3 changes: 3 additions & 0 deletions src/algo/AVL.js
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,9 @@ export default class AVL extends Algorithm {
}

clear() {
this.insertField.value = '';
this.deleteField.value = '';
this.findField.value = '';
this.commands = [];
this.recClear(this.treeRoot);
this.treeRoot = null;
Expand Down
3 changes: 3 additions & 0 deletions src/algo/ArrayList.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,9 @@ export default class ArrayList extends Algorithm {
}

clearAll() {
this.addValueField.value = '';
this.addIndexField.value = '';
this.removeField.value = '';
this.commands = [];
for (let i = 0; i < this.size; i++) {
this.cmd(act.setText, this.arrayID[i], '');
Expand Down
18 changes: 11 additions & 7 deletions src/algo/BFS.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,22 @@ export default class BFS extends Graph {

startCallback() {
if (this.startField.value !== '') {
let startvalue = this.startField.value;
let startValue = this.startField.value;
this.startField.value = '';
startvalue = startvalue.toUpperCase().charCodeAt(0) - 65;
if (startvalue >= 0 && startvalue < this.size) {
this.implementAction(this.doBFS.bind(this), startvalue);
}
startValue = startValue.toUpperCase();
this.implementAction(this.doBFS.bind(this), startValue);
}
}

doBFS(startVetex) {
doBFS(startValue) {
this.commands = [];
let vertex = startValue.charCodeAt(0) - 65;

// User input validation
if (vertex < 0 || vertex >= this.size) {
this.cmd(act.setText, this.infoLabelID, startValue + ' is not a vertex in the graph');
return this.commands;
}

this.clear();

Expand All @@ -187,7 +192,6 @@ export default class BFS extends Graph {

this.rebuildEdges();

let vertex = startVetex;
this.cmd(
act.setText,
this.infoLabelID,
Expand Down
3 changes: 3 additions & 0 deletions src/algo/BST.js
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,9 @@ export default class BST extends Algorithm {
}

clear() {
this.insertField.value = '';
this.deleteField.value = '';
this.findField.value = '';
this.commands = [];
this.clearOldObjects();

Expand Down
3 changes: 3 additions & 0 deletions src/algo/BTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ export default class BTree extends Algorithm {
}

clearTree() {
this.insertField.value = '';
this.deleteField.value = '';
this.findField.value = '';
this.commands = [];
this.deleteTree(this.treeRoot);
this.treeRoot = null;
Expand Down
60 changes: 41 additions & 19 deletions src/algo/BoyerMoore.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import Algorithm, {
} from './Algorithm.js';
import { act } from '../anim/AnimationMain';

const INFO_MSG_X = 25;
const INFO_MSG_Y = 15;

const ARRAY_START_X = 100;
const ARRAY_START_Y = 60;

Expand Down Expand Up @@ -132,6 +135,9 @@ export default class BoyerMoore extends Algorithm {
this.comparisonCountID = this.nextIndex++;
this.periodLabelID = this.nextIndex++;

this.infoLabelID = this.nextIndex++;
this.cmd(act.createLabel, this.infoLabelID, '', INFO_MSG_X, INFO_MSG_Y, 0);

this.lastTableCode = [
['procedure BoyerMooreLastTable(pattern):'],
[' lastTable ← map from character to integer'],
Expand Down Expand Up @@ -232,33 +238,23 @@ export default class BoyerMoore extends Algorithm {
// this.failureTableCharacterID = [];
// this.failureTableValueID = [];
this.comparisonCountID = this.nextIndex++;
this.infoLabelID = this.nextIndex++;
this.periodLabelID = this.nextIndex++;
this.compCount = 0;
this.period = 1;
}

findCallback() {
if (
this.textField.value !== '' &&
this.patternField.value !== '' &&
this.textField.value.length >= this.patternField.value.length
) {
this.implementAction(this.clear.bind(this));
const text = this.textField.value;
const pattern = this.patternField.value;
this.textField.value = '';
this.patternField.value = '';
this.implementAction(this.find.bind(this), text, pattern);
}
this.implementAction(this.clear.bind(this), true);
const text = this.textField.value;
const pattern = this.patternField.value;
this.implementAction(this.find.bind(this), text, pattern);
}

buildLastOccurrenceTableCallback() {
if (this.patternField.value !== '') {
this.implementAction(this.clear.bind(this));
const pattern = this.patternField.value;
this.patternField.value = '';
this.implementAction(this.onlyBuildLastOccurrenceTable.bind(this), 0, pattern);
}
this.implementAction(this.clear.bind(this), true);
const pattern = this.patternField.value;
this.implementAction(this.onlyBuildLastOccurrenceTable.bind(this), 0, pattern);
}

clearCallback() {
Expand All @@ -276,6 +272,19 @@ export default class BoyerMoore extends Algorithm {
}
this.commands = [];

// User input validation
if (!text || !pattern) {
this.cmd(act.setText, this.infoLabelID, 'Text and pattern must not be empty');
return this.commands;
} else if (text.length < pattern.length) {
this.cmd(
act.setText,
this.infoLabelID,
'Pattern is longer than text, no matches exist',
);
return this.commands;
}

const maxRows = this.getMaxRows(text, pattern);
if (maxRows <= 14) {
this.cellSize = 30;
Expand Down Expand Up @@ -553,6 +562,13 @@ export default class BoyerMoore extends Algorithm {

onlyBuildLastOccurrenceTable(textLength, pattern) {
this.commands = [];

// User input validation
if (!pattern) {
this.cmd(act.setText, this.infoLabelID, 'Pattern must not be empty');
return this.commands;
}

this.cellSize = 30;
this.buildLastTable(textLength, pattern);
return this.commands;
Expand Down Expand Up @@ -893,7 +909,7 @@ export default class BoyerMoore extends Algorithm {
return failureTable;
}

clear() {
clear(keepInput) {
this.commands = [];
for (let i = 0; i < this.textRowID.length; i++) {
this.cmd(act.delete, this.textRowID[i]);
Expand Down Expand Up @@ -937,9 +953,15 @@ export default class BoyerMoore extends Algorithm {
// this.cmd(act.delete, this.failureTableValueID[i]);
// }

if (!keepInput) {
this.textField.value = '';
this.patternField.value = '';
}

this.compCount = 0;
this.cmd(act.setText, this.comparisonCountID, '');
this.cmd(act.setText, this.periodLabelID, '');
this.cmd(act.setText, this.infoLabelID, '');
this.lastTableCharacterID = [];
this.lastTableValueID = [];
this.failureTableCharacterID = [];
Expand Down
47 changes: 33 additions & 14 deletions src/algo/BruteForce.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import Algorithm, {
} from './Algorithm.js';
import { act } from '../anim/AnimationMain';

const INFO_MSG_X = 25;
const INFO_MSG_Y = 15;

const ARRAY_START_X = 100;
const ARRAY_START_Y = 60;

Expand Down Expand Up @@ -107,8 +110,10 @@ export default class BruteForce extends Algorithm {
['end procedure'],
];

this.comparisonCountID = this.nextIndex++;
this.infoLabelID = this.nextIndex++;
this.cmd(act.createLabel, this.infoLabelID, '', INFO_MSG_X, INFO_MSG_Y, 0, 0);

this.comparisonCountID = this.nextIndex++;
this.compCount = 0;
this.cmd(act.createLabel, this.comparisonCountID, '', COMP_COUNT_X, COMP_COUNT_Y, 0);

Expand All @@ -122,23 +127,16 @@ export default class BruteForce extends Algorithm {
this.textRowID = [];
this.comparisonMatrixID = [];
this.comparisonCountID = this.nextIndex++;
this.infoLabelID = this.nextIndex++;
this.compCount = 0;
this.codeID = [];
}

findCallback() {
if (
this.textField.value !== '' &&
this.patternField.value !== '' &&
this.textField.value.length >= this.patternField.value.length
) {
this.implementAction(this.clear.bind(this));
const text = this.textField.value;
const pattern = this.patternField.value;
this.textField.value = '';
this.patternField.value = '';
this.implementAction(this.find.bind(this), text, pattern);
}
this.implementAction(this.clear.bind(this), true);
const text = this.textField.value;
const pattern = this.patternField.value;
this.implementAction(this.find.bind(this), text, pattern);
}

clearCallback() {
Expand All @@ -148,6 +146,19 @@ export default class BruteForce extends Algorithm {
find(text, pattern) {
this.commands = [];

// User input validation
if (!text || !pattern) {
this.cmd(act.setText, this.infoLabelID, 'Text and pattern must not be empty');
return this.commands;
} else if (text.length < pattern.length) {
this.cmd(
act.setText,
this.infoLabelID,
'Pattern is longer than text, no matches exist',
);
return this.commands;
}

const maxRows = text.length - pattern.length + 1;
if (maxRows <= 14) {
this.cellSize = 30;
Expand Down Expand Up @@ -304,7 +315,7 @@ export default class BruteForce extends Algorithm {
return this.commands;
}

clear() {
clear(keepInput) {
this.commands = [];
for (let i = 0; i < this.textRowID.length; i++) {
this.cmd(act.delete, this.textRowID[i]);
Expand All @@ -315,11 +326,19 @@ export default class BruteForce extends Algorithm {
this.cmd(act.delete, this.comparisonMatrixID[i][j]);
}
}

if (!keepInput) {
this.textField.value = '';
this.patternField.value = '';
}

this.comparisonMatrixID = [];
this.removeCode(this.codeID);
this.codeID = [];
this.compCount = 0;
this.cmd(act.setText, this.comparisonCountID, '');
this.cmd(act.setText, this.infoLabelID, '');

return this.commands;
}

Expand Down
47 changes: 35 additions & 12 deletions src/algo/BubbleSort.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import { act } from '../anim/AnimationMain';

const MAX_ARRAY_SIZE = 18;

const INFO_MSG_X = 25;
const INFO_MSG_Y = 15;

const ARRAY_START_X = 100;
const ARRAY_START_Y = 130;
const ARRAY_ELEM_WIDTH = 50;
Expand Down Expand Up @@ -107,6 +110,9 @@ export default class BubbleSort extends Algorithm {
this.iPointerID = this.nextIndex++;
this.jPointerID = this.nextIndex++;

this.infoLabelID = this.nextIndex++;
this.cmd(act.createLabel, this.infoLabelID, '', INFO_MSG_X, INFO_MSG_Y, 0);

this.comparisonCountID = this.nextIndex++;
this.compCount = 0;
this.cmd(
Expand Down Expand Up @@ -163,6 +169,7 @@ export default class BubbleSort extends Algorithm {
this.iPointerID = this.nextIndex++;
this.jPointerID = this.nextIndex++;
this.comparisonCountID = this.nextIndex++;
this.infoLabelID = this.nextIndex++;
this.swapCountID = this.nextIndex++;
this.codeID = this.addCodeToCanvasBase(this.code, CODE_START_X, CODE_START_Y);
if (!lastSwapEnabled) {
Expand All @@ -176,15 +183,8 @@ export default class BubbleSort extends Algorithm {

sortCallback() {
const list = this.listField.value.split(',').filter(x => x !== '');
if (
this.listField.value !== '' &&
list.length <= MAX_ARRAY_SIZE &&
list.map(Number).filter(x => x > 999 || Number.isNaN(x)).length <= 0
) {
this.implementAction(this.clear.bind(this));
this.listField.value = '';
this.implementAction(this.sort.bind(this), list);
}
this.implementAction(this.clear.bind(this), true);
this.implementAction(this.sort.bind(this), list);
}

clearCallback() {
Expand All @@ -209,7 +209,7 @@ export default class BubbleSort extends Algorithm {
lastSwapEnabled = !lastSwapEnabled;
}

clear() {
clear(keepInput) {
this.commands = [];

for (let i = 0; i < this.arrayID.length; i++) {
Expand All @@ -221,17 +221,40 @@ export default class BubbleSort extends Algorithm {
this.compCount = 0;
this.swapCount = 0;
this.displayData = [];
if (!keepInput) this.listField.value = '';
this.cmd(act.setText, this.infoLabelID, '');
this.cmd(act.setText, this.comparisonCountID, 'Comparison Count: ' + this.compCount);
this.cmd(act.setText, this.swapCountID, 'Swap Count: ' + this.swapCount);
return this.commands;
}

sort(params) {
sort(list) {
this.commands = [];

// User input validation
if (!list.length) {
this.cmd(act.setText, this.infoLabelID, 'Data must contain integers such as "3,1,2"');
return this.commands;
} else if (list.length > MAX_ARRAY_SIZE) {
this.cmd(
act.setText,
this.infoLabelID,
`Data cannot contain more than ${MAX_ARRAY_SIZE} numbers (you put ${list.length})`,
);
return this.commands;
} else if (list.map(Number).filter(x => x > 999 || Number.isNaN(x)).length) {
this.cmd(
act.setText,
this.infoLabelID,
'Data cannot contain non-numeric values or numbers >999',
);
return this.commands;
}

this.highlight(0, 0);

this.arrayID = [];
this.arrayData = params
this.arrayData = list
.map(Number)
.filter(x => !Number.isNaN(x))
.slice(0, MAX_ARRAY_SIZE);
Expand Down
Loading

0 comments on commit 5f44986

Please sign in to comment.