2024-02-11 08:39:09 +00:00
|
|
|
package Assignments.A1.view;
|
|
|
|
|
|
|
|
import Assignments.A1.models.Board;
|
|
|
|
import Assignments.A1.models.BoardGenerator;
|
|
|
|
import Assignments.A1.models.BoardNode;
|
2024-02-11 22:42:05 +00:00
|
|
|
import Assignments.A1.models.helper.Solver;
|
|
|
|
import Assignments.A1.solving_algorithms.PriorityTraversal;
|
|
|
|
import Assignments.A1.solving_algorithms.comparators.AStar;
|
|
|
|
import Assignments.A1.solving_algorithms.comparators.BFS;
|
2024-02-11 21:45:30 +00:00
|
|
|
import Assignments.A1.solving_algorithms.DFS;
|
2024-02-11 22:42:05 +00:00
|
|
|
import Assignments.A1.solving_algorithms.comparators.UCS;
|
2024-02-11 08:39:09 +00:00
|
|
|
import javafx.beans.property.*;
|
2024-02-12 02:32:29 +00:00
|
|
|
import javafx.scene.control.Alert;
|
2024-02-11 09:08:58 +00:00
|
|
|
import javafx.scene.control.TreeItem;
|
2024-02-11 08:39:09 +00:00
|
|
|
|
2024-02-11 10:09:07 +00:00
|
|
|
import java.util.Date;
|
2024-02-11 21:45:30 +00:00
|
|
|
import java.util.Stack;
|
2024-02-11 10:09:07 +00:00
|
|
|
|
2024-02-11 08:39:09 +00:00
|
|
|
public class MainViewModel {
|
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
/* Private Fields used to bind */
|
2024-02-12 02:57:52 +00:00
|
|
|
private final StringProperty currentBoardProperty, algSpeedProperty, iterationCounter;
|
|
|
|
private final BooleanProperty expanded, DFS, UCS, BFS, AStar, solvingAlgErr, genBoardErr, disclaimer, openPerf, runPerf;
|
2024-02-11 08:39:09 +00:00
|
|
|
private BoardNode current = new BoardNode(new Board(), null);
|
2024-02-11 09:08:58 +00:00
|
|
|
private TreeItem<BoardNode> solvedRootNode = null;
|
2024-02-12 02:32:29 +00:00
|
|
|
|
|
|
|
/* Private Fields used for traversing/creating nodes. */
|
2024-02-11 10:09:07 +00:00
|
|
|
private BoardNode solvedRootBoardNode = null;
|
2024-02-12 02:57:52 +00:00
|
|
|
private final long[][] hasRanPerformance;
|
2024-02-12 02:32:29 +00:00
|
|
|
private String selectedAlg;
|
2024-02-11 08:39:09 +00:00
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
/**
|
|
|
|
* Initializes all the Properties and initial values for any fields.
|
|
|
|
*
|
|
|
|
* @precondition none
|
|
|
|
* @postcondition a VM is created.
|
|
|
|
*/
|
2024-02-11 08:39:09 +00:00
|
|
|
public MainViewModel() {
|
|
|
|
this.currentBoardProperty = new SimpleStringProperty();
|
|
|
|
this.algSpeedProperty = new SimpleStringProperty();
|
2024-02-11 21:45:30 +00:00
|
|
|
this.disclaimer = new SimpleBooleanProperty();
|
2024-02-11 10:09:07 +00:00
|
|
|
this.expanded = new SimpleBooleanProperty();
|
2024-02-12 02:32:29 +00:00
|
|
|
this.openPerf = new SimpleBooleanProperty();
|
|
|
|
this.runPerf = new SimpleBooleanProperty();
|
2024-02-11 08:39:09 +00:00
|
|
|
this.DFS = new SimpleBooleanProperty();
|
|
|
|
this.UCS = new SimpleBooleanProperty();
|
|
|
|
this.BFS = new SimpleBooleanProperty();
|
|
|
|
this.AStar = new SimpleBooleanProperty();
|
2024-02-12 02:32:29 +00:00
|
|
|
this.iterationCounter = new SimpleStringProperty();
|
2024-02-11 08:39:09 +00:00
|
|
|
|
|
|
|
this.solvingAlgErr = new SimpleBooleanProperty();
|
|
|
|
this.genBoardErr = new SimpleBooleanProperty();
|
|
|
|
this.solvingAlgErr.set(false);
|
|
|
|
this.genBoardErr.set(false);
|
2024-02-12 02:32:29 +00:00
|
|
|
|
|
|
|
this.hasRanPerformance = new long[4][102];
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
/**
|
2024-02-12 02:57:52 +00:00
|
|
|
* Generates the board and sets the board on view to new board.
|
2024-02-12 02:32:29 +00:00
|
|
|
*
|
2024-02-12 02:57:52 +00:00
|
|
|
* @precondition none
|
|
|
|
* @postcondition none
|
2024-02-12 02:32:29 +00:00
|
|
|
*/
|
2024-02-11 08:39:09 +00:00
|
|
|
public void generateBoard() {
|
|
|
|
this.current = new BoardNode(BoardGenerator.generateBoard(), null);
|
|
|
|
currentBoardProperty.set(this.current.board.toString());
|
|
|
|
}
|
|
|
|
|
2024-02-12 02:57:52 +00:00
|
|
|
/**
|
|
|
|
* Solves the current board by checking for which alg is selected, then will solve that board
|
|
|
|
* with the given alg that implements the Solver interface.
|
|
|
|
*
|
|
|
|
* @precondition menuItem != null && (board != solver || board != null)
|
|
|
|
* @postcondition the board is solved.
|
|
|
|
*/
|
2024-02-11 08:39:09 +00:00
|
|
|
public void solveBoard() {
|
|
|
|
if (selectedAlg == null || selectedAlg.isEmpty()) {
|
|
|
|
this.solvingAlgErr.setValue(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.solvingAlgErr.setValue(false);
|
|
|
|
if (current.board.equals(new Board())) {
|
|
|
|
this.genBoardErr.setValue(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.genBoardErr.setValue(false);
|
|
|
|
|
|
|
|
Solver solver = null;
|
|
|
|
if (DFS.getValue()) {
|
2024-02-11 21:45:30 +00:00
|
|
|
solver = new DFS();
|
2024-02-11 08:39:09 +00:00
|
|
|
} else if (UCS.getValue()) {
|
2024-02-11 22:42:05 +00:00
|
|
|
solver = new PriorityTraversal(new UCS());
|
2024-02-11 08:39:09 +00:00
|
|
|
} else if (BFS.getValue()) {
|
2024-02-11 22:42:05 +00:00
|
|
|
solver = new PriorityTraversal(new BFS());
|
2024-02-11 08:39:09 +00:00
|
|
|
} else if (AStar.getValue()) {
|
2024-02-11 22:42:05 +00:00
|
|
|
solver = new PriorityTraversal(new AStar());
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|
2024-02-12 02:32:29 +00:00
|
|
|
|
2024-02-11 10:09:07 +00:00
|
|
|
Date start = new Date();
|
2024-02-11 08:39:09 +00:00
|
|
|
BoardNode solved = solver.traverse(this.current.board);
|
2024-02-11 10:09:07 +00:00
|
|
|
Date end = new Date();
|
|
|
|
long runtime = end.getTime() - start.getTime();
|
|
|
|
this.algSpeedProperty.setValue(String.valueOf(runtime));
|
|
|
|
|
2024-02-11 09:08:58 +00:00
|
|
|
currentBoardProperty.setValue(solved.board.toString());
|
|
|
|
BoardNode root = solved;
|
|
|
|
while (root.parent != null) {
|
|
|
|
root = root.parent;
|
|
|
|
}
|
2024-02-11 10:09:07 +00:00
|
|
|
this.solvedRootNode = rebuildTree(root, this.expanded.getValue());
|
|
|
|
this.solvedRootBoardNode = root;
|
2024-02-11 21:45:30 +00:00
|
|
|
this.current = solved;
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 02:57:52 +00:00
|
|
|
/**
|
|
|
|
* Sets the values of the data using the View's Property files and Bindings.
|
|
|
|
*
|
|
|
|
* @precondition none
|
|
|
|
* @postcondition none
|
|
|
|
*
|
|
|
|
* @param value the menu item value.
|
|
|
|
*/
|
|
|
|
public void setSelectedAlg(String value) {
|
|
|
|
this.selectedAlg = value;
|
|
|
|
this.DFS.set(value.equals("DFS"));
|
|
|
|
this.UCS.set(value.equals("UCS"));
|
|
|
|
this.BFS.set(value.equals("BFS"));
|
|
|
|
this.AStar.set(value.equals("AStar"));
|
|
|
|
|
|
|
|
this.disclaimer.setValue(value.equals("DFS"));
|
|
|
|
this.openPerf.setValue(this.hasRanPerformance[convertValueToInt(value)][0] == 1);
|
|
|
|
this.runPerf.setValue(this.hasRanPerformance[convertValueToInt(value)][0] == 0);
|
|
|
|
if (this.hasRanPerformance[convertValueToInt(value)][0] == 0) {
|
|
|
|
this.iterationCounter.set("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs through the selected algorithm and will run it 100 times. It will collect data from these runs
|
|
|
|
* and store them. It will then allow you to view the data in a new windows and the button will appear.
|
|
|
|
*
|
|
|
|
* @precondition none
|
|
|
|
* @postcondition the performance is taken.
|
|
|
|
*/
|
|
|
|
public void runPerformanceCheck() {
|
|
|
|
Solver solver = null;
|
|
|
|
int alg = -1;
|
|
|
|
if (this.selectedAlg.equals("DFS") && this.hasRanPerformance[0][0] == 0) {
|
|
|
|
solver = new DFS();
|
|
|
|
alg = 0;
|
|
|
|
} else if (this.selectedAlg.equals("UCS") && this.hasRanPerformance[1][0] == 0) {
|
|
|
|
solver = new PriorityTraversal(new UCS());
|
|
|
|
alg = 1;
|
|
|
|
} else if (this.selectedAlg.equals("BFS") && this.hasRanPerformance[2][0] == 0) {
|
|
|
|
solver = new PriorityTraversal(new BFS());
|
|
|
|
alg = 2;
|
|
|
|
} else if (this.selectedAlg.equals("AStar") && this.hasRanPerformance[3][0] == 0) {
|
|
|
|
solver = new PriorityTraversal(new AStar());
|
|
|
|
alg = 3;
|
|
|
|
}
|
|
|
|
int averageNodes = 0;
|
|
|
|
if (solver != null) {
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
|
|
Board board = BoardGenerator.generateBoard();
|
|
|
|
System.out.println(board);
|
|
|
|
long start = new Date().getTime();
|
|
|
|
BoardNode node = solver.traverse(board);
|
|
|
|
long end = new Date().getTime();
|
|
|
|
System.out.println(node.board + "\n");
|
|
|
|
if (node != null) {
|
|
|
|
this.hasRanPerformance[alg][i + 2] = end - start;
|
|
|
|
this.currentBoardProperty.setValue(node.board.toString());
|
|
|
|
averageNodes += solver.getNumOfNodes();
|
|
|
|
updateDisplay();
|
|
|
|
} else {
|
|
|
|
this.hasRanPerformance[alg][i+2] = -1;
|
|
|
|
}
|
|
|
|
iterationCounter.setValue("Performing Analysis Iteration: " + (i+1) + "/100");
|
|
|
|
}
|
|
|
|
this.hasRanPerformance[alg][0] = 1;
|
|
|
|
this.hasRanPerformance[alg][1] = averageNodes;
|
|
|
|
this.runPerf.setValue(false);
|
|
|
|
this.openPerf.setValue(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < this.hasRanPerformance[alg].length; i++) {
|
|
|
|
System.out.println(this.hasRanPerformance[alg][i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens the performance files that were previously generated. Is only visible when performance is already generated.
|
|
|
|
*
|
|
|
|
* @precondition performance == generated
|
|
|
|
* @postcondition performance is displayed in Alert.
|
|
|
|
*/
|
2024-02-12 02:32:29 +00:00
|
|
|
public void openPerf() {
|
|
|
|
long totalTime = 0;
|
|
|
|
int success = 0;
|
|
|
|
long shortest = 1000000;
|
|
|
|
long longest = -1;
|
|
|
|
for (int i = 2; i < this.hasRanPerformance[convertValueToInt(this.selectedAlg)].length; i++) {
|
|
|
|
long current = this.hasRanPerformance[convertValueToInt(this.selectedAlg)][i];
|
|
|
|
if (current != -1) {
|
|
|
|
success++;
|
|
|
|
totalTime += current;
|
|
|
|
if (current < shortest) {
|
|
|
|
shortest = current;
|
|
|
|
}
|
|
|
|
if (longest < current) {
|
|
|
|
longest = current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
long average = totalTime / (long) success;
|
2024-02-11 08:39:09 +00:00
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
Alert perf = new Alert(Alert.AlertType.INFORMATION);
|
2024-02-11 08:39:09 +00:00
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
perf.setTitle(this.selectedAlg + " Performance Report");
|
|
|
|
perf.setHeaderText(success + "/" + 100 + " Succeeded.");
|
|
|
|
String results = "Shortest Run: " + shortest + "ms\n" +
|
|
|
|
"Longest Run: " + longest + "ms\n" +
|
2024-02-12 02:57:52 +00:00
|
|
|
"Average Time: " + average + "ms" + "\n" +
|
|
|
|
"Average Nodes: " + (this.hasRanPerformance[convertValueToInt(this.selectedAlg)][1]/success);
|
2024-02-12 02:32:29 +00:00
|
|
|
perf.setContentText(results);
|
|
|
|
perf.show();
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 02:57:52 +00:00
|
|
|
/**
|
|
|
|
* Is used to update the display with the current board.
|
|
|
|
*
|
|
|
|
* @precondition none
|
|
|
|
* @postcondition the dispaly is updated.
|
|
|
|
*/
|
2024-02-12 02:32:29 +00:00
|
|
|
public void updateDisplay() {
|
|
|
|
TreeItem<BoardNode> newRoot = null;
|
|
|
|
newRoot = this.rebuildTree(this.solvedRootBoardNode, this.expanded.getValue());
|
|
|
|
this.solvedRootNode = newRoot;
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
/* Getters for bindings */
|
|
|
|
|
|
|
|
public TreeItem<BoardNode> getSolvedRootNode() {
|
|
|
|
return solvedRootNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty DFSProperty() {
|
|
|
|
return DFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty UCSProperty() {
|
|
|
|
return UCS;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty BFSProperty() {
|
|
|
|
return BFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty AStarProperty() {
|
|
|
|
return AStar;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty solvingAlgErrProperty() {
|
|
|
|
return solvingAlgErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty genBoardErrProperty() {
|
|
|
|
return genBoardErr;
|
|
|
|
}
|
2024-02-11 08:39:09 +00:00
|
|
|
|
2024-02-11 10:09:07 +00:00
|
|
|
public boolean getExpanded() {
|
|
|
|
return expanded.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty expandedProperty() {
|
|
|
|
return expanded;
|
|
|
|
}
|
|
|
|
|
|
|
|
public StringProperty algSpeedProperty() {
|
|
|
|
return algSpeedProperty;
|
|
|
|
}
|
2024-02-11 21:45:30 +00:00
|
|
|
|
2024-02-12 02:32:29 +00:00
|
|
|
public StringProperty iterationCounterProperty() {
|
|
|
|
return iterationCounter;
|
|
|
|
}
|
|
|
|
|
2024-02-11 21:45:30 +00:00
|
|
|
public boolean isDisclaimer() {
|
|
|
|
return disclaimer.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty disclaimerProperty() {
|
|
|
|
return disclaimer;
|
|
|
|
}
|
2024-02-12 02:32:29 +00:00
|
|
|
|
|
|
|
public BooleanProperty openPerfProperty() {
|
|
|
|
return openPerf;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BooleanProperty runPerfProperty() {
|
|
|
|
return runPerf;
|
|
|
|
}
|
2024-02-12 02:57:52 +00:00
|
|
|
|
|
|
|
public StringProperty getCurrentBoardProperty() {
|
|
|
|
return this.currentBoardProperty;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* End of Public Methods. Private Fields Only */
|
|
|
|
|
|
|
|
private TreeItem<BoardNode> rebuildTree(BoardNode root, boolean expanded) {
|
|
|
|
if (this.selectedAlg != null) {
|
|
|
|
if (this.selectedAlg.equals("DFS")) {
|
|
|
|
Stack<BoardNode> generations = new Stack<>();
|
|
|
|
BoardNode temp = this.current;
|
|
|
|
while (temp != null) {
|
|
|
|
generations.push(temp);
|
|
|
|
temp = temp.parent;
|
|
|
|
}
|
|
|
|
TreeItem<BoardNode> rootItem = new TreeItem<>(root);
|
|
|
|
TreeItem<BoardNode> currItem = rootItem;
|
|
|
|
while (!generations.isEmpty()) {
|
|
|
|
TreeItem<BoardNode> child = new TreeItem<>(generations.pop());
|
|
|
|
currItem.getChildren().add(child);
|
|
|
|
currItem.setExpanded(expanded);
|
|
|
|
currItem = child;
|
|
|
|
}
|
|
|
|
return rootItem;
|
|
|
|
} else {
|
|
|
|
TreeItem<BoardNode> treeItem = new TreeItem<>(root);
|
|
|
|
for (BoardNode child : root.children) {
|
|
|
|
TreeItem<BoardNode> childItem = rebuildTree(child, expanded);
|
|
|
|
treeItem.getChildren().add(childItem);
|
|
|
|
}
|
|
|
|
treeItem.setExpanded(expanded);
|
|
|
|
|
|
|
|
return treeItem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new TreeItem<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private int convertValueToInt(String value) {
|
|
|
|
if (value.equals("DFS")) return 0;
|
|
|
|
if (value.equals("UCS")) return 1;
|
|
|
|
if (value.equals("BFS")) return 2;
|
|
|
|
return 3;
|
|
|
|
}
|
2024-02-11 08:39:09 +00:00
|
|
|
}
|