package apps.server.visualization;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import server.event.ServerNewGameStateEvent;
import util.game.Game;
import util.game.GameRepository;
import util.observer.Event;
import util.observer.Observer;
import util.statemachine.MachineState;
import util.statemachine.StateMachine;
import util.statemachine.implementation.prover.ProverMachineState;
import util.statemachine.implementation.prover.cache.CachedProverStateMachine;
import util.xhtml.GameStateRenderPanel;
@SuppressWarnings("serial")
public final class VisualizationPanel extends JPanel implements Observer
{
private final Game theGame;
private final VisualizationPanel myThis;
private JTabbedPane tabs = new JTabbedPane();
public VisualizationPanel(Game theGame)
{
this.theGame = theGame;
this.myThis = this;
this.add(tabs);
}
private int stepCount = 1;
public void observe(Event event)
{
if (event instanceof ServerNewGameStateEvent)
{
MachineState s = ((ServerNewGameStateEvent)event).getState();
RenderThread rt = new RenderThread(s, stepCount++);
rt.start();
}
}
private class RenderThread extends Thread {
private final MachineState s;
private final int stepNum;
public RenderThread(MachineState s, int stepNum) {
this.s = s;
this.stepNum = stepNum;
}
@Override
public void run()
{
JPanel newPanel = null;
try {
// NOTE: This controls whether we use the legacy local stylesheet
// visualizations or the newer web-hosted visualizations. Ultimately
// we want to convert the legacy stylesheets to web-hosted versions
// and then phase out the legacy local system. For now, we will try
// to use a web-hosted visualization, and fall back to a local one
// if the web-hosted visualization isn't available.
if (theGame.getStylesheet() == null) {
String XML = s.toMatchXML();
String XSL = GameStateRenderPanel.getXSLfromFile(theGame.getKey());
newPanel = new VizContainerPanel(XML, XSL, true, myThis);
} else {
String XML = s.toXML();
String XSL = theGame.getStylesheet();
newPanel = new VizContainerPanel(XML, XSL, false, myThis);
}
} catch(Exception ex) {}
if(newPanel != null) {
// Add the rendered panel as a new tab
boolean atEnd = (tabs.getSelectedIndex() == tabs.getTabCount()-1);
try {
for(int i = tabs.getTabCount(); i < stepNum; i++)
tabs.add(new Integer(i+1).toString(), new JPanel());
tabs.setComponentAt(stepNum-1, newPanel);
tabs.setTitleAt(stepNum-1, new Integer(stepNum).toString());
if(atEnd) {
tabs.setSelectedIndex(tabs.getTabCount()-1);
}
} catch(Exception ex) {
System.err.println("Adding rendered visualization panel failed for: " + theGame.getKey());
}
}
}
}
// Simple test that loads the nineBoardTicTacToe game and visualizes
// a randomly-played match, to demonstrate that visualization works.
public static void main(String args[]) {
JFrame frame = new JFrame("Visualization Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game theGame = GameRepository.getDefaultRepository().getGame("chess");
VisualizationPanel theVisual = new VisualizationPanel(theGame);
frame.setPreferredSize(new Dimension(1200, 900));
frame.getContentPane().add(theVisual);
frame.pack();
frame.setVisible(true);
StateMachine theMachine = new CachedProverStateMachine();
theMachine.initialize(theGame.getRules());
try {
MachineState theCurrentState = theMachine.getInitialState();
do {
theVisual.observe(new ServerNewGameStateEvent((ProverMachineState)theCurrentState));
theCurrentState = theMachine.getRandomNextState(theCurrentState);
Thread.sleep(2750);
System.out.println("StateModel: " + theCurrentState);
} while(!theMachine.isTerminal(theCurrentState));
theVisual.observe(new ServerNewGameStateEvent((ProverMachineState)theCurrentState));
} catch (Exception e) {
e.printStackTrace();
}
}
}