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");
}
}