package edu.hawaii.ics.yucheng; import java.awt.Dimension; import java.awt.Toolkit; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; /** * A dialog frame that shows information about a graph and its solution. */ @SuppressWarnings("serial") class InformationFrame extends JFrame { /** The battery level. */ private int myBattery; /** The string builder. */ private StringBuilder myBuilder; /** The graph. */ private final Graph myGraph; /** The vertex index. */ private int myIndex; /** A flag indicating if the solver was canceled. */ private final boolean myIsCanceled; /** A flag indicating if the solver is working. */ private final boolean myIsWorking; /** The priority sum. */ private int myPriority; /** The solution. */ private final GraphSolution mySolution; /** The current vertex visited. */ private Vertex myVertex; /** The flag indicating if the device was on at the current vertex. */ private boolean myWorking; /** * Initializes a new instance of the class. * * @param graph The graph. * * @param solution The solution. * * @param isWorking A flag indicating if the solver is working. * * @param isCanceled A flag indicating if the solver was canceled. */ public InformationFrame(final Graph graph, final GraphSolution solution, final boolean isWorking, final boolean isCanceled) { myGraph = graph; mySolution = solution; myIsWorking = isWorking; myIsCanceled = isCanceled; setTitle("Graph Details"); setSize(640, 480); // Center the popup window in the screen. final Toolkit toolkit = Toolkit.getDefaultToolkit(); final Dimension size = toolkit.getScreenSize(); final int x = (size.width - 640) / 2; final int y = (size.height - 480) / 2; setLocation(x, y); // Create a text area for the graph details. final JTextArea area = new JTextArea(); area.setTabSize(6); area.setLineWrap(true); area.setWrapStyleWord(true); area.setCaretPosition(0); add(new JScrollPane(area)); // Add the graph detail. myBuilder = new StringBuilder(); buildIntroduction(); buildObstacles(); buildPriorities(); buildConsumptions(); if (mySolution == null) myBuilder.append("\nThis graph has not yet been solved."); else buildSolution(); area.setText(myBuilder.toString()); area.setCaretPosition(0); myBuilder = null; } /** * Builds the battery consumption table. */ private void buildConsumptions() { myBuilder.append("\nThe graph contains the following energy " + "consumption values:\n\n"); buildDivider(); for (int j = 0; j < myGraph.height; j++) { for (int i = 0; i < myGraph.width - 1; i++) myBuilder.append(myGraph.consumption(i, j) + "\t"); myBuilder.append(myGraph.consumption(myGraph.width - 1, j) + "\n"); } buildDivider(); } /** * Builds a divider. */ private void buildDivider() { for (int i = 0; i < myGraph.width * 6 - 5; i++) myBuilder.append("-"); myBuilder.append("\n"); } /** * Builds the introduction section. */ private void buildIntroduction() { if (myGraph.url == null) myBuilder.append("This graph was generated randomly. "); else myBuilder.append("This graph was downloaded from:\n\n" + myGraph.url + "\n\n"); myBuilder.append("This graph is a " + myGraph.height + "x" + myGraph.width + " mesh. The base is at (" + myGraph.base + "), and the initial battery capacity is " + myGraph.capacity + "."); } /** * Builds the obstacles table. */ private void buildObstacles() { myBuilder.append(" The graph contains the following obstacles:\n\n"); buildDivider(); for (int j = 0; j < myGraph.height; j++) { for (int i = 0; i < myGraph.width - 1; i++) myBuilder.append(myGraph.isObstacle(i, j) ? "X\t" : ".\t"); final boolean isObstacle = myGraph.isObstacle(myGraph.width - 1, j); myBuilder.append(isObstacle ? "X\n" : ".\n"); } buildDivider(); } /** * Builds the priorities table. */ private void buildPriorities() { myBuilder.append("\nThe graph contains the following priorities:\n\n"); buildDivider(); for (int j = 0; j < myGraph.height; j++) { for (int i = 0; i < myGraph.width - 1; i++) myBuilder.append(myGraph.priority(i, j) + "\t"); myBuilder.append(myGraph.priority(myGraph.width - 1, j) + "\n"); } buildDivider(); } /** * Builds the solution section. */ private void buildSolution() { if (myIsWorking) myBuilder.append("\nThis graph is in the process of being solved, and " + "the best solution has not yet been found with certainty. The " + "best solution found so far follows."); else if (myIsCanceled) myBuilder.append("\nThe attempt to solve this graph was canceled " + "before it was able to complete. The best solution found " + "prior to this point follows."); else myBuilder.append("\nThis graph has been solved."); myBuilder.append(" The sum of the priorities of the visited vertices " + "is " + mySolution.goodness + "."); if (mySolution.sequenceLength() == 0) { myBuilder.append(" No vertices are visited in this solution."); return; } buildSolutionTableHeader(); buildSolutionTable(); } /** * Builds the solution table. */ private void buildSolutionTable() { myIndex = 0; myPriority = 0; myBattery = myGraph.capacity; myWorking = false; for (int j = 0; j < mySolution.departureLength() - 1; j++) { myIndex++; myVertex = mySolution.departureAt(j); myBattery--; buildSolutionTableRow(false); } myWorking = true; for (int j = 0; j < mySolution.sequenceLength(); j++) { myIndex++; myVertex = mySolution.sequenceAt(j); myBattery -= 1 + myGraph.consumption(myVertex.x, myVertex.y); myPriority += myGraph.priority(myVertex.x, myVertex.y); buildSolutionTableRow(false); } myWorking = false; for (int j = 1; j < mySolution.arrivalLength(); j++) { myIndex++; myVertex = mySolution.arrivalAt(j); myBattery--; buildSolutionTableRow(j + 1 == mySolution.arrivalLength()); } myIndex = 0; myPriority = 0; myBattery = 0; myVertex = null; } /** * Builds the solution table header. */ private void buildSolutionTableHeader() { myBuilder.append(" The following table lists each vertex visited along " + "with the condition of the device at that vertex. The " + "columns of the table are as follows:\n" + "\n i vertex number in path" + "\n Wi device working flag (on or off)" + "\n Vi vertex location in the graph" + "\n Pi priority of this vertex" + "\n Bi battery consumption of this vertex" + "\n P sum of priorities after visiting this vertex" + "\n B battery remaining after visiting this vertex" + "\n % battery percentage after visiting this vertex" + "\n\ni\tWi\tVi\tPi\tBi\tP\tB\t%\n" + "-----\t-----\t-----\t-----\t-----\t-----\t-----\t-----\n"); } /** * Builds a row in the solution table. * * @param lastRow True indicates this is the last row. */ private void buildSolutionTableRow(final boolean lastRow) { myBuilder.append(myIndex + "\t" + (myWorking ? "on" : "off") + "\t" + myVertex); if (!lastRow) { myBuilder.append("\t"); if (!myWorking) myBuilder.append("(0)\t(1)\t"); else { final int priority = myGraph.priority(myVertex.x, myVertex.y); final int consumption = myGraph.consumption(myVertex.x, myVertex.y); myBuilder.append(priority + "\t" + consumption + "\t"); } final int percent = myBattery * 100 / myGraph.capacity; myBuilder.append(myPriority + "\t" + myBattery + "\t" + percent); } myBuilder.append("\n"); } }