content: package com.aicontest.visualizer;
  
  import java.awt.Color;
  import java.awt.Frame;
  import java.awt.GraphicsConfiguration;
  import java.awt.GraphicsDevice;
  import java.awt.Panel;
  import java.awt.event.WindowEvent;
  import java.awt.event.WindowListener;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintStream;
  import java.net.URI;
  import java.net.URISyntaxException;
  
  import org.mozilla.javascript.NativeArray;
  import org.mozilla.javascript.ScriptableObject;
  import org.mozilla.javascript.Undefined;
  
  import com.aicontest.visualizer.js.dom.HTMLDocument;
  import com.aicontest.visualizer.js.dom.XMLHttpRequest;
  
  public class Main implements IVisualizerUser, WindowListener {
  
  	private static Boolean decorated;
  	private static int width = 640;
  	private static int height = 640;
  	private Panel visualizerPanel;
  	private Frame frame;
  	private Visualizer visualizer;
  	private HTMLDocument document;
  	private VideoCapture videoCapture;
  
  	public static void main(String[] args) {
  		try {
  			if (args.length == 0) {
  				System.out.println("Reading live stream from stdin...");
  				new Main();
  			} else {
  				String fileName = null;
  				VideoOptions video = null;
  				boolean moreOptions = true;
  				BotInputOptions botInput = null;
  				for (String arg : args) {
  					if (moreOptions && arg.startsWith("--")) {
  						try {
  							if (arg.equals("--")) {
  								moreOptions = false;
  							} else if (arg.equals("--help")) {
  								printHelp(System.out);
  								System.exit(0);
  							} else if (arg.startsWith("--video=")) {
  								String vidArgString = arg.substring(8);
  								video = new VideoOptions(vidArgString);
  							} else if (arg.startsWith("--botinput=")) {
  								String argString = arg.substring(11);
  								botInput = new BotInputOptions(argString);
  							} else if (arg.startsWith("--decorated=")) {
  								decorated = Boolean.parseBoolean(arg
  										.substring(12));
  							} else if (arg.startsWith("--width=")) {
  								width = Math.max(1,
  										Integer.parseInt(arg.substring(8)));
  							} else if (arg.startsWith("--height=")) {
  								height = Math.max(1,
  										Integer.parseInt(arg.substring(9)));
  							} else {
  								invalidOption(arg);
  							}
  						} catch (Exception e) {
  							invalidOption(arg);
  						}
  					} else if (moreOptions && arg.startsWith("-")) {
  						if (arg.equals("-h")) {
  							printHelp(System.out);
  							System.exit(0);
  						} else {
  							invalidOption(arg);
  						}
  					} else if (fileName == null) {
  						fileName = arg;
  					} else {
  						printHelp(System.err);
  						System.err
  								.println("(You seem to have tried more than one file name.)");
  						System.exit(1);
  					}
  				}
  				if (fileName == null) {
  					printHelp(System.err);
  					System.err.println("(The visualizer needs a file name.)");
  					System.exit(1);
  				}
  				new Main(fileName, video, botInput);
  			}
  		} catch (Exception e) {
  			e.printStackTrace();
  			System.exit(1);
  		}
  	}
  
  	private static void invalidOption(String arg) {
  		printHelp(System.err);
  		System.err.println("(Invalid option: " + arg + ")");
  		System.exit(1);
  	}
  
  	private static void printHelp(PrintStream out) {
  		out.println("Syntax: <options> filename");
  		out.println("Options:");
  		out.println("                  -h / --help : Prints this help.");
  		out.println("                --width=<int> : Set the display width in pixels.");
  		out.println("               --height=<int> : Set the display height in pixels.");
  		out.println("     --decorated=[true/false] : Enables or disable GUI elements around the visualizer.");
  		out.println("          --video=<fpt>,<fmt> : Enable video output mode at");
  		out.println("                                <fpt> frames per turn using");
  		out.println("                                <ext> as file extension.");
  		out.println("--botinput=<player>,<turn(s)> : Generate bot intput for a replay.");
  		out.println("                                <player> name of the bot");
  		out.println("                                <turn(s)> A single turn number or a range like 1-1000.");
  		out.println();
  		out.println("Video images will be numbered 00000000.<fmt> to 99999999.<fmt>.");
  		out.println("Example call that generates ten frames per turn without user interface:");
  		out.println("  --width=1280 --height=720 --decorated=false --video=10,png example.replay");
  		out.println("MPEG-4 encoding with ffmpeg at the default 25 FPS (results in 2.5 turns per second):");
  		out.println("  ffmpeg -i %08d.png movie.mp4");
  	}
  
  	private ScriptableObject init(boolean resizable)
  			throws InstantiationException, IllegalAccessException, IOException {
  		visualizer = new Visualizer(this, width, height, resizable);
  		document = visualizer.getDomWindow().getDocument();
  		ScriptableObject options = visualizer.construct("Options", null);
  		options.put("data_dir", options, "/");
  		if (decorated != null) {
  			options.put("decorated", options, decorated);
  		}
  		return options;
  	}
  
  	private ScriptableObject construct(ScriptableObject options, Object config,
  			VideoOptions video) throws IOException {
  		// in video recording mode we want no user interaction
  		if (video != null) {
  			options.put("interactive", options, false);
  			options.put("loop", options, false);
  		}
  		ScriptableObject vis = visualizer.construct("Visualizer", new Object[] {
  				document, options, Undefined.instance, Undefined.instance,
  				config });
  		if (video != null) {
  			videoCapture = new VideoCapture(visualizer, frame,
  					video.getFormat());
  			ScriptableObject.defineProperty(visualizer.global, "video",
  					videoCapture, ScriptableObject.DONTENUM);
  			visualizer.invoke(vis, "javaVideoOutput",
  					new Object[] { video.getFpt() });
  		}
  		return vis;
  	}
  
  	public Main(String replay, VideoOptions video, BotInputOptions botInput)
  			throws InstantiationException, IllegalAccessException, IOException,
  			URISyntaxException {
  		if (replay.endsWith(".stream")) {
  			if (video != null) {
  				System.err
  						.println("Cannot record videos for logged streaming replays. Use a storage format replay instead.");
  				System.exit(1);
  			} else if (botInput != null) {
  				System.err
  						.println("Cannot create bot input from logged streaming replays. Use a storage format replay instead.");
  				System.exit(1);
  			} else {
  				startStream(new FileInputStream(replay));
  			}
  		} else {
  			if (botInput != null) {
  				startBotInput(replay, botInput);
  			} else if (botInput == null || video != null) {
  				startReplay(replay, video);
  			}
  		}
  	}
  
  	private void startStream(InputStream inputStream)
  			throws InstantiationException, IllegalAccessException, IOException {
  		ScriptableObject options = init(true);
  		ScriptableObject vis = construct(options, Undefined.instance, null);
  		new Stream(vis, visualizer, inputStream, "stream");
  		visualizer.loop();
  	}
  
  	private void startReplay(String replay, VideoOptions video)
  			throws URISyntaxException, InstantiationException,
  			IllegalAccessException, IOException {
  		URI uri = replayStringToUri(replay);
  		ScriptableObject options = init(video == null);
  		ScriptableObject vis = construct(options, Undefined.instance, video);
  		visualizer.invoke(vis, "loadReplayDataFromURI", new Object[] { uri });
  		visualizer.loop();
  	}
  
  	private void startBotInput(String replaySource, BotInputOptions botInput)
  			throws URISyntaxException, InstantiationException,
  			IllegalAccessException, IOException {
  		WebWrapper ww = new WebWrapper(getJavaScriptPath());
  		ww.loadProgram(getProgram());
  		ww.runProgram();
  		URI uri = replayStringToUri(replaySource);
  		XMLHttpRequest xhr = new XMLHttpRequest();
  		xhr.open("GET", uri.toString());
  		try {
  			xhr.send();
  		} catch (IOException e) {
  			System.err.println("Could not load " + replaySource + ": " + e);
  			System.exit(1);
  		}
  		String replayStr = xhr.getResponseText();
  		ScriptableObject replay = ww.construct("Replay",
  				new Object[] { replayStr });
  		ScriptableObject meta = (ScriptableObject) replay.get("meta", replay);
  		NativeArray playernames = (NativeArray) meta.get("playernames", meta);
  		int userIndex = playernames.indexOf(botInput.getPlayer());
  		if (userIndex == -1) {
  			System.err.println(botInput.getPlayer()
  					+ " does not exist in the replay");
  			System.exit(1);
  		} else if (botInput.getMin() < 1
  				|| botInput.getMax() > (Double) replay.get("duration", replay)
  				|| botInput.getMin() > botInput.getMax()) {
  			System.err.println("You requested turns " + botInput.getMin() + "-"
  					+ botInput.getMax() + ", but the range is 1-"
  					+ ((Double) replay.get("duration", replay)).intValue());
  		}
  		String result = (String) ww.invoke(
  				replay,
  				"generateBotInput",
  				new Object[] { userIndex, botInput.getMin() - 1,
  						botInput.getMax() - 1 });
  		System.out.print(result);
  	}
  
  	private URI replayStringToUri(String replay) throws URISyntaxException {
  		URI uri = null;
  		try {
  			uri = new URI(replay);
  		} catch (URISyntaxException e) {
  		}
  		if (uri == null || uri.getScheme() == null) {
  			uri = new URI("file", replay, null);
  		}
  		return uri;
  	}
  
  	public Main() throws IOException, InstantiationException,
  			IllegalAccessException {
  		startStream(System.in);
  	}
  
  	@Override
  	public String getJavaScriptPath() {
  		return "../../js";
  	}
  
  	@Override
  	public IProgram getProgram() {
  		final Ants ants = new Ants();
  		return ants;
  	}
  
  	@Override
  	public void setVisualizerPanel(Panel visualizerPanel, boolean resizable) {
  		this.visualizerPanel = visualizerPanel;
  		frame = new Frame("Ants Visualizer");
  		frame.setBackground(Color.WHITE);
  		frame.add(visualizerPanel);
  		frame.pack();
  		frame.setLocationByPlatform(true);
  		frame.addWindowListener(this);
  		frame.setResizable(resizable);
  		frame.setVisible(true);
  	}
  
  	@Override
  	public boolean setFullScreen(boolean enable) {
  		GraphicsConfiguration winGfxConf = frame.getGraphicsConfiguration();
  		GraphicsDevice dev = winGfxConf.getDevice();
  		Frame fsWin = (Frame) dev.getFullScreenWindow();
  		if (fsWin == null && enable) {
  			frame.setVisible(false);
  			fsWin = new Frame();
  			fsWin.setUndecorated(true);
  			fsWin.add(visualizerPanel);
  			fsWin.setVisible(true);
  			winGfxConf.getDevice().setFullScreenWindow(fsWin);
  		} else if (fsWin != null && !enable) {
  			fsWin.dispose();
  			winGfxConf.getDevice().setFullScreenWindow(null);
  			frame.add(visualizerPanel);
  			frame.setVisible(true);
  		}
  		return enable;
  	}
  
  	@Override
  	public void windowOpened(WindowEvent e) {
  	}
  
  	@Override
  	public void windowClosing(WindowEvent e) {
  		visualizer.exit();
  		if (videoCapture != null) {
  			videoCapture.quit();
  		}
  		e.getWindow().dispose();
  	}
  
  	@Override
  	public void windowClosed(WindowEvent e) {
  	}
  
  	@Override
  	public void windowIconified(WindowEvent e) {
  	}
  
  	@Override
  	public void windowDeiconified(WindowEvent e) {
  	}
  
  	@Override
  	public void windowActivated(WindowEvent e) {
  	}
  
  	@Override
  	public void windowDeactivated(WindowEvent e) {
  	}
  }
  