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