// ------------------------------------------------------------------------ // ------------------------------------------------------------------------ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.Toolkit; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ public class Display extends JFrame { // -------------------------------------------------------------------- private static int columns; private static int rows; private static Socket out_socket; private static Socket in_socket; private static ServerSocket ss; private static PrintWriter toServer; private static BufferedReader fromServer; private static int client_id = -1; private static DisplayPanel panel; // -------------------------------------------------------------------- public static void main (String[] args) { if (args.length != 2) { System.err.println ("Usage: java -jar Display.jar server port"); System.exit (-1); } Display theDisplay = new Display (args[0], Integer.parseInt (args[1])); try { while (true) { // get server time from server String input = fromServer.readLine (); int time = Integer.parseInt (input); panel.setTime (time); // get message from server input = fromServer.readLine (); int total_number_of_agents = input.length () / 3; panel.setBugCount (total_number_of_agents); panel.clearBugs (); for (int i = 0; i < total_number_of_agents; i++) { int col = input.charAt (3 * i) - 32; int row = input.charAt (3 * i + 1) - 32; int dir = (input.charAt (3 * i + 2) - 32) % 4; int spec = (input.charAt (3 * i + 2) - 32) / 4; panel.addBug (col, row, dir, spec); } panel.repaint (); // send acknowledgment toServer.print ("ok\n"); toServer.flush (); } } catch (Exception e) { System.err.println (e.getMessage ()); } // These should go somewhere but I am not sure where // try // { // fromServer.close (); // in_socket.close (); // ss.close (); // toServer.close (); // out_socket.close (); // } // catch (Exception e) // { // System.err.println (e.getMessage ()); // } } // -------------------------------------------------------------------- public Display ( String host_name, int host_port ) { super ("Bugs World Display"); if (! Connect_To_Server (host_name, host_port)) { System.exit (-2); } panel = new DisplayPanel (columns, rows); getContentPane ().add (panel); pack (); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); show (); } // -------------------------------------------------------------------- private static boolean Connect_To_Server ( String host_name, int host_port ) { try { String hn = InetAddress.getByName ( InetAddress.getByName (host_name).getHostAddress ()). getHostName (); System.out.println ("Trying to connect to " + hn + ":" + host_port); out_socket = new Socket (hn, host_port); toServer = new PrintWriter ( new OutputStreamWriter (out_socket.getOutputStream ())); ss = new ServerSocket (0); String hc = InetAddress.getLocalHost ().getHostAddress (); int pc = ss.getLocalPort (); // System.out.println ("Sending local host and port info " + // hc + ":" + pc); toServer.print (hc + "\n" + pc + "\ntrue\n"); toServer.flush (); System.out.println ("Waiting for reverse connection"); in_socket = ss.accept (); fromServer = new BufferedReader ( new InputStreamReader (in_socket.getInputStream ())); // get client id from server String input = fromServer.readLine (); client_id = Integer.parseInt (input); if (client_id == -1) { System.out.println ( "Connection refused: too many connections"); } else { System.out.println ( "Connection established: displaying game"); // get world columns and rows from server input = fromServer.readLine (); columns = Integer.parseInt (input); input = fromServer.readLine (); rows = Integer.parseInt (input); // send acknowledgment toServer.print ("ok\n"); toServer.flush (); } } catch (Exception e) { System.err.println (e.getMessage ()); } finally { return client_id != -1; } } // -------------------------------------------------------------------- } // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ class DisplayPanel extends JPanel { // -------------------------------------------------------------------- public static final int CELL_SIZE = 32; public static final int WINDOW_MARGIN = 10; public static final int STAT_WIDTH = 300; public static final int NORTH = 0; public static final int EAST = 1; public static final int SOUTH = 2; public static final int WEST = 3; // -------------------------------------------------------------------- private static int columns; private static int rows; private static int time; private static int bugCount; private static int maxBugCount; private static List bugs = Collections.synchronizedList (new LinkedList ()); private static Stat[] stats = new Stat[10]; private static Image[] images = new Image[10]; private static Color[] colors = new Color[10]; // -------------------------------------------------------------------- class Stat { public int min; public int max; public int current; } // -------------------------------------------------------------------- class Bug { public int c; public int r; public int d; public int s; public Bug (int c, int r, int d, int s) { this.c = c; this.r = r; this.d = d; this.s = s; } } // -------------------------------------------------------------------- public DisplayPanel (int c, int r) { super (); columns = c; rows = r; setPreferredSize ( new Dimension ( columns * CELL_SIZE + 2 * WINDOW_MARGIN + STAT_WIDTH, rows * CELL_SIZE + 2 * WINDOW_MARGIN)); setBackground (Color.white); // load bug images MediaTracker tracker = new MediaTracker (this); for (int i = 0; i < 10; i++) { images[i] = Toolkit.getDefaultToolkit ().getImage ( getClass ().getResource ("images/bug" + i + ".gif")); tracker.addImage (images[i], i); stats[i] = new Stat (); } try { tracker.waitForAll (); } catch (InterruptedException e) {} // scale bug images for (int i = 0; i < 10; i++) { images[i] = images[i].getScaledInstance ( CELL_SIZE-1, CELL_SIZE-1, Image.SCALE_SMOOTH); } // load bug colors colors[0] = new Color (193, 0, 0); colors[1] = new Color (161, 0, 255); colors[2] = new Color (0, 255, 0); colors[3] = new Color (255, 96, 0); colors[4] = new Color (255, 0, 0); colors[5] = new Color (161, 0, 0); colors[6] = new Color (64, 64, 0); colors[7] = new Color (64, 0, 129); colors[8] = new Color (64, 0, 0); colors[9] = new Color (255, 161, 0); } // -------------------------------------------------------------------- public void paintComponent (Graphics g) { super.paintComponent (g); synchronized (bugs) { drawGrid (g); Iterator it = bugs.iterator (); while (it.hasNext ()) { Bug b = (Bug) it.next (); drawBug (g, b.c, b.r, b.d, b.s); } drawStats (g); } } // -------------------------------------------------------------------- public void setTime (int time) { this.time = time; } // -------------------------------------------------------------------- public void setBugCount (int bugCount) { this.bugCount = bugCount; if (bugCount > maxBugCount) { maxBugCount = bugCount; } } // -------------------------------------------------------------------- public void clearBugs () { bugs.clear (); for (int i=0; i < 10; i++) { stats[i].current = 0; } } // -------------------------------------------------------------------- public void addBug (int c, int r, int d, int s) { Bug b = new Bug (c, r, d, s); bugs.add (b); stats[s].current++; } // -------------------------------------------------------------------- private void drawGrid (Graphics g) { for (int i = 0; i <= rows; i++) { g.drawLine (WINDOW_MARGIN, WINDOW_MARGIN + CELL_SIZE * i, WINDOW_MARGIN + CELL_SIZE * columns, WINDOW_MARGIN + CELL_SIZE * i); } for (int i = 0; i <= columns; i++) { g.drawLine (WINDOW_MARGIN + CELL_SIZE * i, WINDOW_MARGIN, WINDOW_MARGIN + CELL_SIZE * i, WINDOW_MARGIN + CELL_SIZE * rows); } } // -------------------------------------------------------------------- private void drawBug (Graphics g, int c, int r, int d, int s) { int x, y; Graphics2D g2 = (Graphics2D) g; switch (d) { case NORTH : { x = WINDOW_MARGIN + CELL_SIZE * ( c - 1 ) + 1; y = WINDOW_MARGIN + CELL_SIZE * ( rows - r ) + 1; g2.translate ((double) x, (double) y); g2.drawImage (images[s%10], 0, 0, null); g2.translate (-(double) x, -(double) y); } break; case EAST : { x = WINDOW_MARGIN + CELL_SIZE * c; y = WINDOW_MARGIN + CELL_SIZE * ( rows - r ) + 1; g2.translate ((double) x, (double) y); g2.rotate (Math.PI / 2.0); g2.drawImage (images[s%10], 0, 0, null); g2.rotate (-Math.PI / 2.0); g2.translate (-(double) x, -(double) y); } break; case SOUTH : { x = WINDOW_MARGIN + CELL_SIZE * c; y = WINDOW_MARGIN + CELL_SIZE * ( rows - r + 1 ); g2.translate ((double) x, (double) y); g2.rotate (Math.PI); g2.drawImage (images[s%10], 0, 0, null); g2.rotate (-Math.PI); g2.translate (-(double) x, -(double) y); } break; case WEST : { x = WINDOW_MARGIN + CELL_SIZE * ( c - 1 ) + 1; y = WINDOW_MARGIN + CELL_SIZE * ( rows - r + 1 ); g2.translate ((double) x, (double) y); g2.rotate (3.0 * Math.PI / 2.0); g2.drawImage (images[s%10], 0, 0, null); g2.rotate (-3.0 * Math.PI / 2.0); g2.translate (-(double) x, -(double) y); } break; } } // -------------------------------------------------------------------- private void drawStats (Graphics g) { int left = columns * CELL_SIZE + 2 * WINDOW_MARGIN; int x = left + 25; int y = 30; int inc = 35; int maxBarWidth = 100; int barHeight = inc - 5; g.drawString ("Server time: " + time, x, y); y += 20; g.drawString ("Number of bugs: " + bugCount, x, y); for (int i = 0; i < 10; i++) { if (stats[i].current > 0) { if (stats[i].current > stats[i].max) { stats[i].max = stats[i].current; } if ((stats[i].current < stats[i].min) || (stats[i].min == 0)) { stats[i].min = stats[i].current; } y += inc; g.drawString ("Species " + i + ":", x, y+5); g.drawRect (x + 64, y - 16, maxBarWidth+1, barHeight+1); g.setColor (colors[i]); g.fillRect (x + 65, y - 15, maxBarWidth * stats[i].current / maxBugCount, barHeight); g.setColor (Color.BLACK); g.fillRect ( x + 65 + maxBarWidth * stats[i].min / maxBugCount - 1, y - 15, 2, barHeight); g.fillRect ( x + 65 + maxBarWidth * stats[i].max / maxBugCount - 1, y - 15, 2, barHeight); g.drawString ( stats[i].min + ":" + stats[i].current + ":" + stats[i].max, x + maxBarWidth + 70, y+5); } } } // -------------------------------------------------------------------- } // ------------------------------------------------------------------------ // ------------------------------------------------------------------------