Skip to content

Commit 7875259

Browse files
committed
modify header and add notif for when path not found
1 parent dc407e3 commit 7875259

20 files changed

+347
-70
lines changed

path-finding/src/AlgorithmReducer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
export const ALGO_ACTIONS = {
22
IS_SEARCHING: "IS_SEARCHING",
33
IS_CREATING_MAZE: "IS_CREATING_MAZE",
4+
FOUND_PATH: "FOUND_PATH",
45
};
56
// this state represents( but does not manage) the state of the algorithms so the header can change accordingly
67
export const initialState = {
78
isSearching: false,
89
isCreatingMaze: false,
10+
foundPath: true,
911
};
1012

1113
export default function algoReducer(state, action) {
@@ -20,6 +22,8 @@ export default function algoReducer(state, action) {
2022
...state,
2123
isCreatingMaze: action.payload,
2224
};
25+
case ALGO_ACTIONS.FOUND_PATH:
26+
return { ...state, foundPath: action.payload };
2327
default:
2428
console.error("no matching action types");
2529
}

path-finding/src/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import Grid from "./Grid/Grid";
22
import Header from "./Header/Header";
3+
import Tutorial from "./Tutorial/Tutorial";
34

45
function App() {
56
return (
67
<div className="App">
8+
<Tutorial />
79
<Header />
810
<Grid />
911
</div>

path-finding/src/Cell/Cell.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export function CellSquareState(props) {
8080
function CellSquare({ state }) {
8181
const { cell } = state;
8282
return (
83-
<div
83+
<button
8484
className={`cell ${
8585
cell.cellType === CELL_TYPES.START || cell.cellType === CELL_TYPES.END
8686
? "main"
@@ -92,6 +92,6 @@ function CellSquare({ state }) {
9292
cellTypeOnMouseDown = cell.cellType;
9393
determineCellType(cellTypeOnMouseDown, cell);
9494
}}
95-
></div>
95+
></button>
9696
);
9797
}

path-finding/src/Header/Header.js

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,29 @@ import dijkstrasSearch from "../PathFindingAlgos/DijkstrasAlgorithm";
44
import breadthFirstSearch from "../PathFindingAlgos/BreadthFirstSearch";
55
import bestFirstSearch from "../PathFindingAlgos/BestFirstSearch";
66
import startRecursiveDivision from "../MazeAlgos/RecursiveDivision";
7+
import closeIcon from "./Icons/close-icon.png";
78
import { searchVars, pathFind } from "../Search";
89
import { gridCl } from "../Grid/Grid";
9-
import { mazeVars, createMaze } from "../Maze";
10-
import algoReducer, { initialState } from "../AlgorithmReducer";
10+
import { createMaze } from "../Maze";
11+
import algoReducer, { ALGO_ACTIONS, initialState } from "../AlgorithmReducer";
1112
import { clamp } from "../UtilityFuncs";
1213
import "./header.css";
1314

1415
function Header() {
16+
// this reducer changes state during pathfinding and allows this header to rerender.
1517
const [state, dispatch] = useReducer(algoReducer, initialState);
1618

1719
const [canCrossDiagonals, setCanCrossDiagonals] = useState(true);
1820
const [animationInterval, setAnimationInterval] = useState(15);
19-
const [missingCell, setMissingCell] = useState(false);
2021

2122
const executePathFinding = (algorithm) => {
2223
if (gridCl.startCell != null && gridCl.endCell != null) {
2324
pathFind(canCrossDiagonals, dispatch, algorithm);
24-
} else {
25-
setMissingCell(true);
2625
}
2726
};
28-
2927
return (
3028
<section className="header">
3129
<div className="main">
32-
<section id="instructions">
33-
<button>Tutorial</button>
34-
</section>
3530
<div>
3631
<div className="input-with-prepending">
3732
<h5>Animation Interval (ms)</h5>
@@ -42,14 +37,12 @@ function Header() {
4237
let interval = clamp(
4338
parseFloat(evt.target.value),
4439
searchVars.minSearchTime,
45-
searchVars.maxSearchTime
40+
Number.MAX_VALUE
4641
);
47-
setAnimationInterval(interval);
4842
searchVars.searchAnimationTime = interval;
4943
}
44+
setAnimationInterval(evt.target.value);
5045
}}
51-
min={searchVars.minSearchTime}
52-
max={searchVars.maxSearchTime}
5346
type="number"
5447
/>
5548
</div>
@@ -66,14 +59,17 @@ function Header() {
6659
<span className="slider round"></span>
6760
</div>
6861
</div>
69-
<button
70-
onClick={() => createMaze(startRecursiveDivision, dispatch)}
71-
className={
72-
state.isSearching || state.isCreatingMaze ? "disabled" : ""
73-
}
74-
>
75-
Create Maze
76-
</button>
62+
<section>
63+
<h4>Create Obstacles</h4>
64+
<button
65+
onClick={() => createMaze(startRecursiveDivision, dispatch)}
66+
className={
67+
state.isSearching || state.isCreatingMaze ? "disabled" : ""
68+
}
69+
>
70+
Create Maze
71+
</button>
72+
</section>
7773
<section className="algorithms">
7874
<h4>Pathfinding Algorithms</h4>
7975
<button
@@ -113,9 +109,7 @@ function Header() {
113109
<h4>Clearing Options</h4>
114110
<button
115111
onClick={() => {
116-
if (!searchVars.isSearching && !mazeVars.isCreatingMaze) {
117-
gridCl.clearEntireGrid();
118-
}
112+
gridCl.clearEntireGrid();
119113
}}
120114
className={
121115
state.isSearching || state.isCreatingMaze ? "disabled" : ""
@@ -125,9 +119,7 @@ function Header() {
125119
</button>
126120
<button
127121
onClick={() => {
128-
if (!mazeVars.isCreatingMaze && !searchVars.isSearching) {
129-
gridCl.clearWalls();
130-
}
122+
gridCl.clearWalls();
131123
}}
132124
className={
133125
state.isCreatingMaze || searchVars.isSearching ? "disabled" : ""
@@ -137,9 +129,7 @@ function Header() {
137129
</button>
138130
<button
139131
onClick={() => {
140-
if (searchVars.isSearching) {
141-
searchVars.stopSearch = true;
142-
}
132+
searchVars.stopSearch = true;
143133
}}
144134
type="button"
145135
className={state.isSearching ? "" : "disabled"}
@@ -148,12 +138,16 @@ function Header() {
148138
</button>
149139
</section>
150140
</div>
151-
<div
152-
className={`notif ${missingCell ? "appear" : ""}`}
153-
onClose={() => setMissingCell(false)}
154-
>
141+
<div className={`notif ${state.foundPath === true ? "" : "appear"}`}>
155142
<div>
156-
<h4>You are missing a start or end cell</h4>
143+
<h4>No path was found!</h4>
144+
<button
145+
onClick={() => {
146+
dispatch({ type: ALGO_ACTIONS.FOUND_PATH, payload: true });
147+
}}
148+
>
149+
<img src={closeIcon} alt="Close" />
150+
</button>
157151
</div>
158152
</div>
159153
</section>
Binary file not shown.
-1.31 KB
Binary file not shown.
526 Bytes
Loading

path-finding/src/Header/header.css

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.disabled {
2+
pointer-events: none;
3+
}
4+
15
.header {
26
padding-top: 2vh;
37
background-color: #a1c4fd;
@@ -14,7 +18,7 @@
1418
.header > .main {
1519
display: flex;
1620
padding-bottom: 2vh;
17-
21+
align-items: center;
1822
justify-content: space-around;
1923
}
2024

@@ -25,29 +29,46 @@
2529

2630
.notif {
2731
display: flex;
28-
justify-content: center;
32+
justify-content: space-around;
2933
}
3034

3135
.notif > div {
3236
display: none;
3337
justify-content: center;
3438
align-items: center;
3539

40+
padding: 10px 30px;
3641
border-radius: 10px;
42+
3743
background-color: rgb(240, 105, 105);
38-
width: 30vw;
39-
height: 10%;
44+
width: 20vw;
45+
min-width: fit-content;
46+
height: 5vh;
4047
}
4148

42-
.notif.appear {
49+
.notif.appear > div {
4350
display: flex;
51+
position: relative;
52+
margin-bottom: 1vh;
4453
}
4554

46-
#click-instructions > h4 {
47-
line-height: 1.6em;
55+
.notif.appear > div > button {
56+
position: absolute;
57+
border: none;
58+
background: transparent;
59+
color: white;
60+
top: -5px;
61+
right: -30px;
62+
}
63+
64+
.notif.appear > div > button > img {
65+
width: 20px;
66+
min-width: 20px;
67+
height: 20px;
4868
}
4969

5070
.header button {
71+
height: fit-content;
5172
min-width: 80px;
5273

5374
font-weight: 400;
@@ -115,3 +136,11 @@
115136
height: 20px;
116137
width: 20px;
117138
}
139+
140+
@media only screen and (max-width: 775px) {
141+
.header > .main {
142+
display: flex;
143+
flex-direction: column;
144+
align-items: center;
145+
}
146+
}

path-finding/src/Search.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { timer } from "./UtilityFuncs";
55
export const searchVars = {
66
isSearching: false,
77
stopSearch: false,
8-
maxSearchTime: 3000,
98
minSearchTime: 1,
109
pathAnimationTime: 10,
1110
searchAnimationTime: 15,
@@ -24,44 +23,56 @@ export function retracePath(start, end) {
2423
return path;
2524
}
2625

27-
/*Starts a given pathfinding algorithm and draws the path if found.
26+
/*
2827
2928
@param {Function} varDispatch - dispatch function used to change state for the Header component
3029
@param {Function} searching - the searching algorithm to run
3130
*/
32-
export async function pathFind(canCrossDiagonals, varDispatch, search) {
31+
32+
/** Starts a given pathfinding algorithm and draws the path if found.
33+
*
34+
* @param {Boolean} canCrossDiagonals - whether the searching algorithm can cross diagonals.
35+
* @param {Function} headerDispatch - dispatch function used to change state for the Header component
36+
* @param {Function} search - the searching algorithm to run.
37+
* @returns
38+
*/
39+
export async function pathFind(canCrossDiagonals, headerDispatch, search) {
3340
if (searchVars.isSearching || mazeVars.isCreatingMaze) {
3441
return;
3542
}
3643

3744
searchVars.isSearching = true;
38-
varDispatch({ type: ALGO_ACTIONS.IS_SEARCHING, payload: true });
45+
headerDispatch({ type: ALGO_ACTIONS.IS_SEARCHING, payload: true });
3946

4047
// execute promise to search that should resolve a path
4148
var path = await searching(canCrossDiagonals, search).catch((err) => {
4249
// if the promise was rejected the log the error
4350
console.log("error in search");
4451
console.error(err);
4552
});
53+
54+
// no path was found
4655
if (path == null) {
47-
endSearch(varDispatch);
56+
endSearch(headerDispatch, false);
4857
return;
4958
}
5059
await drawPath(path).catch((err) => {
5160
console.error(err);
5261
});
5362

54-
endSearch(varDispatch);
63+
endSearch(headerDispatch, true);
5564
}
5665

57-
/*Ends the searching algorithm and resets state.
58-
59-
@param {Function} varDispatch - dispatch function used to change state for the Header component
60-
*/
61-
function endSearch(varDispatch) {
66+
/** Ends the searching algorithm and resets state.
67+
*
68+
* @param {Function} headerDispatch - dispatch function used to change state for the Header component
69+
* @param {Boolean} foundPath - whether a path was found or not
70+
*/
71+
function endSearch(headerDispatch, foundPath) {
6272
searchVars.isSearching = false;
6373
searchVars.stopSearch = false;
64-
varDispatch({ type: ALGO_ACTIONS.IS_SEARCHING, payload: false });
74+
headerDispatch({ type: ALGO_ACTIONS.IS_SEARCHING, payload: false });
75+
headerDispatch({ type: ALGO_ACTIONS.FOUND_PATH, payload: foundPath });
6576
}
6677

6778
async function drawPath(path) {
@@ -81,7 +92,6 @@ function searching(canCrossDiagonals, search) {
8192
resolve(res);
8293
})
8394
.catch((err) => {
84-
console.log("Woops");
8595
reject(err);
8696
});
8797
});
Loading

0 commit comments

Comments
 (0)