diff --git a/build.xml b/build.xml index 8c8f4a5..0a8da96 100644 --- a/build.xml +++ b/build.xml @@ -50,7 +50,7 @@ - + diff --git a/src/ch/epfl/lca/sc250/PlayerProgram.java b/src/ch/epfl/lca/sc250/PlayerProgram.java new file mode 100644 index 0000000..366697a --- /dev/null +++ b/src/ch/epfl/lca/sc250/PlayerProgram.java @@ -0,0 +1,21 @@ +package ch.epfl.lca.sc250; + + +public class PlayerProgram { + TCPClient tcpC; + UDPServer udpS; + ServentServer svS; + ServentClient svC; + + public PlayerProgram ( ) { + tcpC = new TCPClient("in3sun23.epfl.ch", 13370, "x-way"); + } + + public void launch ( ) { + } + + public static void main ( String[] args ) { + PlayerProgram p = new PlayerProgram(); + p.launch(); + } +} diff --git a/src/ch/epfl/lca/sc250/ServentServer.java b/src/ch/epfl/lca/sc250/ServentServer.java index d432e23..eea17a5 100644 --- a/src/ch/epfl/lca/sc250/ServentServer.java +++ b/src/ch/epfl/lca/sc250/ServentServer.java @@ -11,42 +11,51 @@ */ public class ServentServer { - public static void main(String[] args) throws IOException { + public static void main(String[] args) { + ServentServer s = new ServentServer(); + } + + public ServentServer ( ) { // Open a Socket and listen on incoming offer requests. // - boolean result; - String message; - ServerSocket knockSock; - Socket sock; - int targetport = 13371; - BufferedReader inReader; - DataOutputStream outStream; - - knockSock = new ServerSocket(targetport); + try { + boolean result; + String message; + ServerSocket knockSock; + Socket sock; + int targetport = 13371; + BufferedReader inReader; + DataOutputStream outStream; + + knockSock = new ServerSocket(targetport); - while ( true ) { + while ( true ) { - sock = knockSock.accept(); + sock = knockSock.accept(); - outStream = new DataOutputStream(sock.getOutputStream()); - inReader = new BufferedReader(new InputStreamReader(sock.getInputStream())); + outStream = new DataOutputStream(sock.getOutputStream()); + inReader = new BufferedReader(new InputStreamReader(sock.getInputStream())); - message = inReader.readLine(); + message = inReader.readLine(); - String[] parsed = message.split(", "); + String[] parsed = message.split(", "); - // We suppose we got and parsed an offer, we then want the pop-up to display - result = getOfferResult(sock.getInetAddress().toString(), parsed[0], parsed[1]); + // We suppose we got and parsed an offer, we then want the pop-up to display + result = getOfferResult(sock.getInetAddress().toString(), parsed[0], parsed[1]); - if(result) { - System.out.println("Yes"); - outStream.writeBytes("Yes\n"); - } else { - System.out.println("No"); - outStream.writeBytes("No\n"); + if(result) { + System.out.println("Yes"); + outStream.writeBytes("Yes\n"); + } else { + System.out.println("No"); + outStream.writeBytes("No\n"); + } + + sock.close(); } - - sock.close(); + } catch ( IOException e ) { + System.out.println("IO-Error"); + e.printStackTrace(); } } diff --git a/src/ch/epfl/lca/sc250/TCPClient.java b/src/ch/epfl/lca/sc250/TCPClient.java index a6411d3..e0954c2 100644 --- a/src/ch/epfl/lca/sc250/TCPClient.java +++ b/src/ch/epfl/lca/sc250/TCPClient.java @@ -22,32 +22,41 @@ public static void main ( String[] args ) { - CnFrameTCP gui = new CnFrameTCP("TP 4: TCP Part"); - //Boolean finished = false; - try { - TCPClient tc = new TCPClient(gui, "in3sun23.epfl.ch", 13370, "x-way"); - - BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in)); - + TCPClient tc = new TCPClient("in3sun23.epfl.ch", 13370, "x-way"); tc.join(); - - /*while ( !finished ) { - - String outBuff = stdin.readLine(); - outs.writeBytes(outBuff); - }*/ - + tc.loop(); tc.leave(); + } - } catch ( IOException ioe ) { - System.out.println("IO-Error"); - gui.appendText("IO-Error"); + void loop ( ) { + + boolean finished = false; + + BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in)); + + while ( !finished ) { + + try { + String cmd = consoleReader.readLine(); + + if ( cmd.trim().equals("Bye Bye") ) { + finished = true; + } + + write(cmd); + gui.appendText(cmd); + gui.appendText(read()); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); + } } } - TCPClient ( CnFrameTCP gui, String targethost, int targetport, String name ) throws IOException { - this.gui = gui; + TCPClient ( String targethost, int targetport, String name ) { + gui = new CnFrameTCP("TCPClient"); this.targethost = targethost; this.targetport = targetport; this.name = name; @@ -57,22 +66,60 @@ } catch ( UnknownHostException uhe ) { System.out.println("Unknown host"); gui.appendText("Unknown host"); + uhe.printStackTrace(); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); } - outs = new DataOutputStream(sock.getOutputStream()); - - inr = new BufferedReader(new InputStreamReader(sock.getInputStream())); + try { + outs = new DataOutputStream(sock.getOutputStream()); + inr = new BufferedReader(new InputStreamReader(sock.getInputStream())); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); + } } - public void join ( ) throws IOException { - outs.writeBytes("Hello: " + name + "\n"); - System.out.println(inr.readLine()); - gui.appendText(inr.readLine()); + public void join ( ) { + write("Hello: " + name + "\n"); + String t = read(); + System.out.println(t); + gui.appendText(t); } - public void leave ( ) throws IOException { - sock.close(); + public void leave ( ) { + try { + sock.close(); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); + } System.out.println("Connection closed."); gui.appendText("Connection closed."); } + + public void write ( String s ) { + try { + outs.writeBytes(s); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); + } + } + + public String read ( ) { + try { + return inr.readLine(); + } catch ( IOException e ) { + System.err.println("IOError"); + gui.appendText("IO-Error"); + e.printStackTrace(); + return ""; + } + } } diff --git a/src/ch/epfl/lca/sc250/UDPServer.java b/src/ch/epfl/lca/sc250/UDPServer.java index db0ebac..9a76665 100644 --- a/src/ch/epfl/lca/sc250/UDPServer.java +++ b/src/ch/epfl/lca/sc250/UDPServer.java @@ -11,13 +11,12 @@ private CnFrameUDP gui; public static void main ( String[] args ) { - CnFrameUDP gui = new CnFrameUDP("Title of the window"); - UDPServer udpS = new UDPServer(gui); + UDPServer udpS = new UDPServer(); udpS.loop(); } - UDPServer ( CnFrameUDP gui ) { - this.gui = gui; + UDPServer ( ) { + gui = new CnFrameUDP("UDPServer"); try { sock = new DatagramSocket(13371); } catch ( SocketException se ) { diff --git a/src/ch/epfl/lca/sc250/gui/CnFrameTCP.java b/src/ch/epfl/lca/sc250/gui/CnFrameTCP.java index 644b0fc..412e698 100644 --- a/src/ch/epfl/lca/sc250/gui/CnFrameTCP.java +++ b/src/ch/epfl/lca/sc250/gui/CnFrameTCP.java @@ -55,15 +55,15 @@ * @param textToAppend */ public void appendText(String textToAppend) { - textArea.append(super.getCurrentTime() + " : " + textToAppend); - textArea.setCaretPosition(textArea.getText().length()); - } - - /** - * Clear the TextArea. - * - */ - public void clearTextArea() { - textArea.replaceRange("", 0, textArea.getText().length()); - } + textArea.append(super.getCurrentTime() + " : " + textToAppend); + textArea.setCaretPosition(textArea.getText().length()); + } + + /** + * Clear the TextArea. + * + */ + public void clearTextArea() { + textArea.replaceRange("", 0, textArea.getText().length()); + } } diff --git a/src/ch/epfl/lca/sc250/gui/finalgui/CellRenderer.java b/src/ch/epfl/lca/sc250/gui/finalgui/CellRenderer.java new file mode 100644 index 0000000..4b38067 --- /dev/null +++ b/src/ch/epfl/lca/sc250/gui/finalgui/CellRenderer.java @@ -0,0 +1,32 @@ +package ch.epfl.lca.sc250.gui.finalgui; + +import java.awt.Component; + +import javax.swing.JTable; +import javax.swing.SwingConstants; +import javax.swing.table.DefaultTableCellRenderer; + +/** + * This Class is used to overwrite the Default Cell Renderer in the JTable used in CnFrameUDP + * + * @author trefois + */ +public class CellRenderer extends DefaultTableCellRenderer { + + /** + * Generated serialID by Eclipse + */ + private static final long serialVersionUID = 6305609864454156868L; + + /** + * Overwrites getTableCellRendererComponent + *
Puts Horizontal Alignement to CENTER + */ + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + this.setHorizontalAlignment(SwingConstants.CENTER); + return this; + } + +} diff --git a/src/ch/epfl/lca/sc250/gui/finalgui/CnFrameMain.java b/src/ch/epfl/lca/sc250/gui/finalgui/CnFrameMain.java new file mode 100644 index 0000000..c1161b0 --- /dev/null +++ b/src/ch/epfl/lca/sc250/gui/finalgui/CnFrameMain.java @@ -0,0 +1,390 @@ +/** + * + */ +package ch.epfl.lca.sc250.gui.finalgui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Vector; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.table.DefaultTableModel; + +/** + * @author Trefex + * + */ +public class CnFrameMain extends JFrame { + + /** + * + */ + private static final long serialVersionUID = 8746287051727486324L; + /** + * Vector containing the table rows data + */ + private Vector tableRows; + + /** + * Vector containing the column names. Filled with addColumns. + */ + private Vector columns; + + /** + * Array containing the column names + */ + private static final String[] columnNames = {"Received At", "User ID", "IP Address", "Letters"}; + + /** + * tableModel used by the Table + */ + private DefaultTableModel tableModel; + + /** + * The table used to display the broadcast messages + */ + private JTable broadcastTable; + /** + * The TextArea used to display the messages + */ + private JTextArea textArea; + /** + * The TextArea used to display the messages + */ + private JTextArea textAreaP2P; + /** + * TextField of the IP + */ + private JTextField ipAdressTextField; + /** + * TextField of the Amount of Money + */ + private JTextField amountMoneyTextField; + /** + * TextField of the position of the letter + */ + private JTextField letterPosition; + /** + * Button used to send the request + */ + private JButton sendMessage; + /** + * Instance of the main Program which is of type ITCPSender + */ + private ITCPSender tcpSender = null; + Thread loaderThread; + + /** + * + * @param windowTitle + */ + public CnFrameMain(String windowTitle) { + setTitle(windowTitle); + + // Set Behaviour when "x" is clicked. + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + // Get Screen Dimensions + Dimension windowSize = Toolkit.getDefaultToolkit().getScreenSize(); + setBounds(50, 50, windowSize.width - 200, windowSize.height - 200); + + getContentPane().setLayout(new BorderLayout()); + + JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, createUDPPanel(), createP2PPanel()); + + JSplitPane sp2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, sp, createTCPPanel()); + + add(sp2, BorderLayout.CENTER); + + + setVisible(true); + } + + /** + * Retrieves the current time in the following format: dd/MMM/yyyy HH:mm:ss + * @return The String representation of the current Date + */ + public String getCurrentTime() { + DateFormat dateFormat = new SimpleDateFormat("dd / MMMM / yyyy -- HH:mm:ss"); + java.util.Date date = new java.util.Date(); + return dateFormat.format(date); + } + + + + /** + * Constructs a CnFrameUDP Instance with title windowTitle + * @param windowTitle The Title if the window + */ + public JPanel createUDPPanel() { + + // Create new JPanel + JPanel centerPanel = new JPanel(); + + // Fill the columns Vector + addColumns(columnNames); + + tableModel = new DefaultTableModel(); + tableModel.setDataVector(tableRows, columns); + + // create new JPanel + broadcastTable = new JTable(tableModel); + broadcastTable.getColumnModel().getColumn(0).setCellRenderer(new CellRenderer()); + broadcastTable.getColumnModel().getColumn(1).setCellRenderer(new CellRenderer()); + broadcastTable.getColumnModel().getColumn(2).setCellRenderer(new CellRenderer()); + broadcastTable.getColumnModel().getColumn(3).setCellRenderer(new CellRenderer()); + + // Add ScrollBar to the broadcastTable + JScrollPane scrollPane = new JScrollPane(broadcastTable); + centerPanel.add(scrollPane); + + return centerPanel; + } + + /** + * Fill the column name vector + * @param columnNames the array of Strings to fill the vector with + */ + private void addColumns(String[] columnNames) { + // Init tableRows and columns Vectors + tableRows = new Vector(); + columns = new Vector(); + + for (int i = 0; i < columnNames.length; i++) + columns.addElement((String) columnNames[i]); + } + + /** + * Adds a row to the JTable + * @param broadcastIP The IP from the broadcast message + * @param letters The Letters + */ + private void addRow(String broadcastIP, String userID, String letters) { + Vector tempVector = new Vector(); + tempVector.addElement(getCurrentTime()); + tempVector.addElement(userID); + tempVector.addElement(broadcastIP); + tempVector.addElement(letters); + tableRows.addElement(tempVector); + broadcastTable.addNotify(); + } + + /** + * Modifies the GUI by appending the broadcast Message + * @param broadcastIP the IP extracted from the broadcast UDP Message + * @param broadcastLetters the letters from the UDP Broadcast + */ + public void appendBroadcastMessage(String broadcastIP, String userID, String broadcastLetters) { + addRow(broadcastIP, userID, broadcastLetters); + } + + /** + * Clears the Table + * + */ + public void clearTable() { + tableRows.clear(); + broadcastTable.addNotify(); + } + + + /** + * Constructs a CnFrameTCP Instance with title windowTitle + * @param windowTitle + */ + public JPanel createTCPPanel() { + JPanel centerPanel = new JPanel(); + + textArea = new JTextArea(); + textArea.setEditable(false); + + JScrollPane scrollPane = new JScrollPane(textArea); + + centerPanel.setLayout(new GridLayout(1, 1)); + centerPanel.add(scrollPane); + + return centerPanel; + } + + /** + * Append Text to the textArea + * @param textToAppend + */ + public void appendText(String textToAppend) { + textArea.append(getCurrentTime() + " : " + textToAppend); + textArea.setCaretPosition(textArea.getText().length()); + } + + /** + * Clear the TextArea. + * + */ + public void clearTextArea() { + textArea.replaceRange("", 0, textArea.getText().length()); + } + + /** + * Constructs a CnFrameP2P Instance with title windowTitle + * @param windowTitle + */ + public JPanel createP2PPanel() { + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + JPanel centerPanel = new JPanel(); + + textAreaP2P = new JTextArea(); + textAreaP2P.setEditable(false); + + JScrollPane scrollPane = new JScrollPane(textAreaP2P); + + centerPanel.setLayout(new GridLayout(1, 1)); + centerPanel.add(scrollPane); + + // put the centerPanel to the Center + mainPanel.add(centerPanel, BorderLayout.CENTER); + + JPanel topPanel = new JPanel(); + topPanel.setLayout(new FlowLayout()); + + topPanel.add(new JLabel("IP Address: ")); + ipAdressTextField = new JTextField(); + topPanel.add(ipAdressTextField); + ipAdressTextField.setPreferredSize(new java.awt.Dimension(78, 20)); + + + topPanel.add(new JLabel("Money: ")); + amountMoneyTextField = new JTextField(); + topPanel.add(amountMoneyTextField); + amountMoneyTextField.setPreferredSize(new java.awt.Dimension(49, 20)); + + + topPanel.add(new JLabel("Position: ")); + letterPosition = new JTextField(); + topPanel.add(letterPosition); + letterPosition.setPreferredSize(new java.awt.Dimension(56, 20)); + + + sendMessage = new JButton(); + topPanel.add(sendMessage); + sendMessage.setText("Send Request"); + sendMessage.setActionCommand("Send"); + NonBlockingLoadAction nonBlocker = new NonBlockingLoadAction(); + sendMessage.addActionListener(nonBlocker); + //sendMessage.addActionListener(this); + + mainPanel.add(topPanel, BorderLayout.NORTH); + return mainPanel; + + } + + /** + * Append Text to the textArea + * @param textToAppend + */ + public void appendTextP2P(String textToAppend) { + textAreaP2P.append(getCurrentTime() + " : " + textToAppend); + textAreaP2P.setCaretPosition(textAreaP2P.getText().length()); + } + + /** + * Clear the TextArea. + */ + public void clearTextAreaP2P() { + textAreaP2P.replaceRange("", 0, textAreaP2P.getText().length()); + } + + /** + * This method is called when an Answer is received from the other Player. + *
It then is displayed in the GUI, and the GUI is reset. + * @param communication + */ + public void receivedMessage(String communication) { + appendTextP2P(communication + "\n"); + ipAdressTextField.setEnabled(true); + amountMoneyTextField.setEnabled(true); + letterPosition.setEnabled(true); + sendMessage.setText("Send Request"); + NonBlockingLoadAction nonBlocker = new NonBlockingLoadAction(); + sendMessage.addActionListener(nonBlocker); + //sendMessage.addActionListener(this); + sendMessage.setEnabled(true); + ipAdressTextField.setText(""); + amountMoneyTextField.setText(""); + letterPosition.setText(""); + appendTextP2P("----- Communication Completed --------\n"); + } + + /** + * Used to work with the Interface + * @param tcpSender + */ + public void setTcpSender(ITCPSender tcpSender) { + this.tcpSender = tcpSender; + } + + /** + * When an offer is received, display a Confirm Dialog where the user can choose Yes or No + * @param IP The IP we got the offer from + * @param amount The amount the other player gives us for a letter + * @param position The position of the letter he wants to buy + * @return True or False + */ + public boolean getOfferResult(String IP, String amount, String position) { + boolean chosenValue = false; + String msgToDisplay = "Buyer from IP: " + IP + "\nWants to buy Letter at Position " + position + " for " + amount + "$"; + int returnValue = JOptionPane.showConfirmDialog(null, msgToDisplay, "You got an Offer !", JOptionPane.YES_NO_OPTION); + if(returnValue == JOptionPane.OK_OPTION) { + chosenValue = true; + } else { + chosenValue = false; + } + return chosenValue; + } + + class NonBlockingLoadAction extends AbstractAction implements Runnable { + /** + * + */ + private static final long serialVersionUID = 4493869112678216390L; + // note that this doesn't offer a means of being interrupted + // so it refuses second launch instead + public void actionPerformed (ActionEvent e) { + if (loaderThread != null) + return; + loaderThread = new Thread ((Runnable) this); + loaderThread.start(); + + } + public void run() { + if (tcpSender == null) + return; + appendTextP2P("IP: " + ipAdressTextField.getText() + " - Buy For: " + amountMoneyTextField.getText() + " - Position: " + letterPosition.getText() + "\n"); + ipAdressTextField.setEnabled(false); + amountMoneyTextField.setEnabled(false); + letterPosition.setEnabled(false); + sendMessage.setText("Waiting ..."); + sendMessage.removeActionListener(this); + sendMessage.setEnabled(false); + + tcpSender.sendMessage(ipAdressTextField.getText(), amountMoneyTextField.getText(), letterPosition.getText()); + loaderThread = null; + + } + } +} diff --git a/src/ch/epfl/lca/sc250/gui/finalgui/ITCPSender.java b/src/ch/epfl/lca/sc250/gui/finalgui/ITCPSender.java new file mode 100644 index 0000000..5c45909 --- /dev/null +++ b/src/ch/epfl/lca/sc250/gui/finalgui/ITCPSender.java @@ -0,0 +1,17 @@ +package ch.epfl.lca.sc250.gui.finalgui; + +/** + * This interface needs to be implemented by TP7 in order to work. + * @author Christophe Trefois + * + */ +public interface ITCPSender { + /** + * This method is supposed to send a msg over a TCP Socket to the other Player. + * + * @param ipAddress IP Address we want to make a request to + * @param moneyAmount The amount of money we offer on the letter + * @param letterPosition The position of the letter that we want to buy + */ + public void sendMessage(String ipAddress, String moneyAmount, String letterPosition); +} diff --git a/src/testingPackage/GuiNewFrameTest.java b/src/testingPackage/GuiNewFrameTest.java new file mode 100644 index 0000000..50a1f93 --- /dev/null +++ b/src/testingPackage/GuiNewFrameTest.java @@ -0,0 +1,35 @@ +package testingPackage; + +import ch.epfl.lca.sc250.gui.finalgui.CnFrameMain; +import ch.epfl.lca.sc250.gui.finalgui.ITCPSender; + +/** + * @author Trefex + * + */ +public class GuiNewFrameTest implements ITCPSender { + + private CnFrameMain mygui; + + public GuiNewFrameTest(String windowTitle) { + mygui = new CnFrameMain(windowTitle); + mygui.setTcpSender(this); + } + + /** + * @param args + */ + public static void main(String[] args) { + new GuiNewFrameTest("TP8 - Networking"); + } + + public void sendMessage(String ipAddress, String moneyAmount, String letterPosition) { + try { + Thread.sleep(10000); + mygui.receivedMessage("We Accept Your Offer"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +}