summaryrefslogtreecommitdiff
path: root/src/javaChat
diff options
context:
space:
mode:
authorO'Shea <osheas1@wit.edu>2020-12-10 14:03:54 -0500
committerO'Shea <osheas1@wit.edu>2020-12-10 14:03:54 -0500
commitcca61c9f562d2c9e2be13ec16abe134d209b54e3 (patch)
tree3f957b579c45d0536e7e1740acdb0cdbc773f9f4 /src/javaChat
parent690bbba9550e2644e48db44fb94d4df86494a34e (diff)
Final implementation, ready for presentation!
Diffstat (limited to 'src/javaChat')
-rw-r--r--src/javaChat/ChatClient.java94
-rw-r--r--src/javaChat/ChatServer.java237
-rw-r--r--src/javaChat/ClientGUI.java97
-rw-r--r--src/javaChat/UserInterface.java288
4 files changed, 0 insertions, 716 deletions
diff --git a/src/javaChat/ChatClient.java b/src/javaChat/ChatClient.java
deleted file mode 100644
index 9560b49..0000000
--- a/src/javaChat/ChatClient.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package javaChat;
-
-import java.net.* ;
-
-import javax.swing.JFrame ;
-
-import java.io.* ;
-
-public class ChatClient
- {
-
- /**
- *
- *
- * @param args
- * @throws IOException
- */
- public static void main( String[] args ) throws IOException
- {
-
- // Get server IP
- BufferedReader keyboard = new BufferedReader( new InputStreamReader( System.in ) ) ;
- System.out.print( "\nPlease enter the IP of the desired server: " ); // GUI: IP BOX
-
- String serverIP = keyboard.readLine() ;
-
- // Open your connection to a server, at port 6789
- Socket socket = new Socket( serverIP , 6789 ) ;
-
- // Create communication streams
- DataInputStream dataStreamIn = new DataInputStream( socket.getInputStream() ) ;
- DataOutputStream dataStreamOut = new DataOutputStream( socket.getOutputStream() ) ;
-
- // Establish connection, make user-name
- System.out.print( "\nConnection established,\nPlease enter a username: " ) ;
- String username = keyboard.readLine() ;
- dataStreamOut.writeUTF( username ) ;
-
- /////////////////////////
- //// Program Running ////
- /////////////////////////
-
- // Thread for sending messages
- Thread sendMessage = new Thread(new Runnable()
- {
- @Override
- public void run()
- {
- System.out.print( "\n-= Type /help for a list of commands =-" ) ;
- while( true )
- {
- try
- {
- String messageOut = keyboard.readLine() ;
- dataStreamOut.writeUTF( messageOut ) ;
- }
- catch( IOException x )
- {
- x.printStackTrace() ;
- System.exit( 0 ) ;
- }
- }
- }
- }) ;
-
- // Thread for receiving messages
- Thread receiveMessage = new Thread( new Runnable()
- {
-
- @Override
- public void run()
- {
- while( true )
- {
- try
- {
- String messageIn = dataStreamIn.readUTF() ;
- System.out.printf( "%n%s\n", messageIn ) ;
- }
- catch( IOException x )
- {
- x.printStackTrace() ;
- System.exit( 0 ) ;
- }
- }
- }
- });
-
- // Begin threads
- sendMessage.start() ;
- receiveMessage.start() ;
- }
- }
- // end class ChatClient \ No newline at end of file
diff --git a/src/javaChat/ChatServer.java b/src/javaChat/ChatServer.java
deleted file mode 100644
index 22c5575..0000000
--- a/src/javaChat/ChatServer.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package javaChat;
-
-import java.net.* ;
-import java.util.* ;
-import java.io.* ;
-
-public class ChatServer
- {
-
- // List of all active users in Server
- static ArrayList<ClientHandler> userList = new ArrayList<>() ;
-
- /**
- * Accepts Client requests to join chat server, and
- * creates new thread for each individual client.
- *
- * @param args
- * @throws IOException
- */
- public static void main( String[] args ) throws IOException
- {
-
- // Register service on port 6789
- ServerSocket serverSocket = new ServerSocket( 6789 ) ;
- Socket socket = null ;
-
- System.out.println( "\nServer established. Awaiting connections..." ) ;
-
- // Accept client requests
- while( true )
- {
- socket = serverSocket.accept() ;
-
- DataOutputStream dataStreamOut = new DataOutputStream( socket.getOutputStream() ) ;
- DataInputStream dataStreamIn = new DataInputStream ( socket.getInputStream() ) ;
-
- System.out.println( "\nClient connection detected, requesting username..." ) ;
- String username = dataStreamIn.readUTF() ;
-
- ClientHandler handle = new ClientHandler( socket, username, dataStreamOut, dataStreamIn ) ;
-
- System.out.println( "\nCreating new thread...\n" ) ;
- Thread thread = new Thread( handle ) ;
-
- userList.add( handle ) ;
-
- thread.start() ;
-
- }
- }
-
- }
- // end class ChatClient
-
-
-
-
- // This class manages the actual messages being sent around
- @SuppressWarnings( "javadoc" )
- class ClientHandler implements Runnable
- {
-
- Socket socket ;
- String username ;
- final DataOutputStream dataStreamOut ;
- final DataInputStream dataStreamIn ;
- boolean loggedIn ;
- private ArrayList<ClientHandler> userList ;
-
-
- /**
- * Constructor
- * @param s : client socket
- * @param user : client's user-name
- * @param dos : data stream to client
- * @param dis : data stream from client
- */
- public ClientHandler( Socket s, String user,
- DataOutputStream dos,
- DataInputStream dis )
- {
- this.username = user ;
- this.socket = s ;
- this.dataStreamOut = dos ;
- this.dataStreamIn = dis ;
- this.loggedIn = true ;
-
- }
-
- @Override
- public void run()
- {
-
- // Note the connection of the new user
- String announcement = String.format( "-= User \"%s\" has successfully connected =-\n", this.username ) ;
- System.out.println( announcement ) ;
-
- // Distribute announcement to entire server
- distributeAll( announcement ) ;
-
- // Message management
- String message = "" ;
- while( true )
- {
- // Read incoming messages
- try
- {
- message = this.dataStreamIn.readUTF() ;
- }
- catch ( IOException x )
- {
- x.printStackTrace() ;
- }
-
- // Check message for user commands, returns TRUE is user quits
- if( commands(message, this) )
- {
- break ;
- }
-
- // Print the message server-side
- message = String.format( "%s: %s", this.username, message ) ;
- System.out.println( message ) ;
-
- // Distribute the message to all users
- sendMessage( message ) ;
- // end try
-
- }
-
- try
- {
- this.loggedIn = false ;
- this.socket.close() ;
- }
- catch( IOException x )
- {
- x.printStackTrace() ;
- }
- }
-
-
- // This method manages the usage of user-commands
- public boolean commands(String message, ClientHandler user)
- {
- String[] commands = new String[] {"/help", "/quit", "/userlist"} ;
-
- try {
-
- // Quit command terminates connection, with an announcement
- if( message.equals( "/quit" ))
- {
- String announcement = String.format( "\n-= \"%s\" has disconnected =- \n", user.username ) ;
- System.out.println( announcement ) ;
- distributeAll( announcement ) ;
- return true ;
- }
-
- if( message.equals( "/userlist" ) )
- {
- user.dataStreamOut.writeUTF( "Current list of users in the server: " ) ;
- for( ClientHandler users : ChatServer.userList )
- {
- if( !users.loggedIn )
- {
- continue ;
- }
-
- user.dataStreamOut.writeUTF( users.username ) ;
-
- }
- }
-
- if( message.contentEquals( "/help" ) )
- {
- user.dataStreamOut.writeUTF( "\nAll available commands: " );
- for(int i = 0; i < commands.length; i++ )
- {
- user.dataStreamOut.writeUTF( commands[i] );
- }
-
- user.dataStreamOut.writeUTF( "\n" ) ;
- }
- }
-
- catch( IOException x )
- {
- System.out.println( x ) ;
- }
-
- return false ;
- }
-
-
- // Convenience method to send messages (but not to the user that's sending the message)
- private void sendMessage(String message)
- {
- try
- {
- for( ClientHandler users : ChatServer.userList )
- {
- if( !users.loggedIn || users.equals( this ) )
- {
- continue ;
- }
- users.dataStreamOut.writeUTF( "> " + message ) ;
- }
- }
- catch ( IOException x )
- {
- x.printStackTrace() ;
- }
- }
-
-
- // Convenience method to distribute messages to all clients (announcements)
- private void distributeAll(String message)
- {
- try
- {
- for( ClientHandler users : ChatServer.userList )
- {
- if( !users.loggedIn )
- {
- continue ;
- }
- users.dataStreamOut.writeUTF( message ) ;
- }
- }
- catch ( IOException x )
- {
- x.printStackTrace() ;
- }
- }
-
- }
- // end class ClientHandler \ No newline at end of file
diff --git a/src/javaChat/ClientGUI.java b/src/javaChat/ClientGUI.java
deleted file mode 100644
index 3b98486..0000000
--- a/src/javaChat/ClientGUI.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package javaChat;
-
-import java.net.* ;
-import java.io.* ;
-
-/**
- *
- *
- * @author osheas1
- * @version 1.0.0 2020-12-07 Initial implementation
- *
- */
-public class ClientGUI
- {
-
- public static void main( String[] args ) throws IOException
- {
-
- UserInterface login = new UserInterface() ;
- login.setVisible( true );
-
- boolean done = false ;
- while( !done )
- {
- done = login.isDone() ;
- System.out.print("");
- }
-
- String ip = login.getIP() ;
- String username = login.getUsername() ;
-
- // Open your connection to a server, at port 6789
- Socket socket = new Socket( ip , 6789 ) ;
-
- // Create communication streams
- DataInputStream dataStreamIn = new DataInputStream( socket.getInputStream() ) ;
- DataOutputStream dataStreamOut = new DataOutputStream( socket.getOutputStream() ) ;
-
- BufferedReader keyboard = new BufferedReader( new InputStreamReader( System.in ) ) ;
-
- dataStreamOut.writeUTF( username ) ;
-
- // Thread for sending messages
- Thread sendMessage = new Thread(new Runnable()
- {
- @Override
- public void run()
- {
- System.out.print( "\n-= Type /help for a list of commands =-" ) ;
- while( true )
- {
- try
- {
- String messageOut = keyboard.readLine() ;
- dataStreamOut.writeUTF( messageOut ) ;
- }
- catch( IOException x )
- {
- x.printStackTrace() ;
- System.exit( 0 ) ;
- }
- }
- }
- }) ;
-
- // Thread for receiving messages
- Thread receiveMessage = new Thread( new Runnable()
- {
-
- @Override
- public void run()
- {
- while( true )
- {
- try
- {
- String messageIn = dataStreamIn.readUTF() ;
- System.out.printf( "%n%s\n", messageIn ) ;
- }
- catch( IOException x )
- {
- x.printStackTrace() ;
- System.exit( 0 ) ;
- }
- }
- }
- });
-
- // Begin threads
- sendMessage.start() ;
- receiveMessage.start() ;
-
-
- }
-
- }
- // end class ClientGUI \ No newline at end of file
diff --git a/src/javaChat/UserInterface.java b/src/javaChat/UserInterface.java
deleted file mode 100644
index 1d8f906..0000000
--- a/src/javaChat/UserInterface.java
+++ /dev/null
@@ -1,288 +0,0 @@
-package javaChat;
-
-import java.awt.* ;
-import java.util.* ;
-import javax.swing.* ;
-
-public class UserInterface extends javax.swing.JFrame {
-
-
- String ip ;
- String username ;
- boolean done ;
-
-/**
- * Creates new form loginFrame
- */
-public UserInterface() {
- initComponents();
-}
-
-/**
- * This method is called from within the constructor to initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is always
- * regenerated by the Form Editor.
- */
-@SuppressWarnings("unchecked")
-// <editor-fold defaultstate="collapsed" desc="Generated Code">
-private void initComponents()
- {
-
- jTextField1 = new javax.swing.JTextField();
- jLabel1 = new javax.swing.JLabel();
- jLabel2 = new javax.swing.JLabel();
- jTextField2 = new javax.swing.JTextField();
- jButton1 = new javax.swing.JButton();
- jSlider1 = new javax.swing.JSlider();
- jSlider2 = new javax.swing.JSlider();
- jSlider3 = new javax.swing.JSlider();
- jSlider4 = new javax.swing.JSlider();
-
- setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
- setTitle("Java Chat");
- setAlwaysOnTop(true);
- setBackground(new java.awt.Color(255, 255, 255));
- setForeground(java.awt.Color.white);
- setResizable(false);
-
- jTextField1.setEditable(false);
- jTextField1.setHorizontalAlignment(javax.swing.JTextField.CENTER);
- jTextField1.setText("0.0.0.0");
-
- jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
- jLabel1.setText("Enter Server's I.P. Address:");
-
- jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
- jLabel2.setText("Enter your desired username:");
-
- jTextField2.setHorizontalAlignment(javax.swing.JTextField.CENTER);
- jTextField2.setActionCommand("<Not Set>");
-
- jButton1.setText("Connect");
- jButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
- jButton1.setOpaque(false);
- jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
- public void mouseClicked(java.awt.event.MouseEvent evt) {
- jButton1MouseClicked(evt);
- }
- });
-
- jSlider1.setMaximum(999);
- jSlider1.setOrientation(javax.swing.JSlider.VERTICAL);
- jSlider1.setValue(0);
- jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
- public void stateChanged(javax.swing.event.ChangeEvent evt) {
- jSlider1StateChanged(evt);
- }
- });
-
- jSlider2.setMaximum(999);
- jSlider2.setOrientation(javax.swing.JSlider.VERTICAL);
- jSlider2.setValue(0);
- jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
- public void stateChanged(javax.swing.event.ChangeEvent evt) {
- jSlider2StateChanged(evt);
- }
- });
-
- jSlider3.setMaximum(999);
- jSlider3.setOrientation(javax.swing.JSlider.VERTICAL);
- jSlider3.setValue(0);
- jSlider3.addChangeListener(new javax.swing.event.ChangeListener() {
- public void stateChanged(javax.swing.event.ChangeEvent evt) {
- jSlider3StateChanged(evt);
- }
- });
-
- jSlider4.setMaximum(999);
- jSlider4.setOrientation(javax.swing.JSlider.VERTICAL);
- jSlider4.setValue(0);
- jSlider4.addChangeListener(new javax.swing.event.ChangeListener() {
- public void stateChanged(javax.swing.event.ChangeEvent evt) {
- jSlider4StateChanged(evt);
- }
- });
-
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
- getContentPane().setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGap(60, 60, 60)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addGroup(layout.createSequentialGroup()
- .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addGap(18, 18, 18)
- .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
- .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(18, 18, 18)
- .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE))))
- .addGroup(layout.createSequentialGroup()
- .addGap(162, 162, 162)
- .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 60, Short.MAX_VALUE)
- .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(jSlider4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(56, 56, 56))
- );
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGap(24, 24, 24)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
- .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
- .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(jSlider4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addContainerGap(40, Short.MAX_VALUE))
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(jLabel1))
- .addGap(36, 36, 36)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(jLabel2))
- .addGap(28, 28, 28)
- .addComponent(jButton1)
- .addGap(30, 30, 30))))
- );
-
- pack();
- }// </editor-fold>
-
-private void jButton1MouseClicked(java.awt.event.MouseEvent evt)
- {
- ip = jTextField1.getText() ;
- username = jTextField2.getText() ;
- //System.out.printf( "IP: %s \nUsername: %s\n", ip, username ) ;
-
-
- done = true ;
- setVisible( false ) ;
- dispose() ;
-
- }
-
-private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt)
- {
- Integer a = jSlider1.getValue() ;
- Integer b = jSlider2.getValue() ;
- Integer c = jSlider3.getValue() ;
- Integer d = jSlider4.getValue() ;
-
- String ip = String.format("%s.%s.%s.%s", a, b, c, d) ;
-
- jTextField1.setText( ip.toString() ) ;
- }
-
-private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt)
- {
- Integer a = jSlider1.getValue() ;
- Integer b = jSlider2.getValue() ;
- Integer c = jSlider3.getValue() ;
- Integer d = jSlider4.getValue() ;
-
- String ip = String.format("%s.%s.%s.%s", a, b, c, d) ;
-
- jTextField1.setText( ip.toString() ) ;
- }
-
-private void jSlider3StateChanged(javax.swing.event.ChangeEvent evt)
- {
- Integer a = jSlider1.getValue() ;
- Integer b = jSlider2.getValue() ;
- Integer c = jSlider3.getValue() ;
- Integer d = jSlider4.getValue() ;
-
- String ip = String.format("%s.%s.%s.%s", a, b, c, d) ;
-
- jTextField1.setText( ip.toString() ) ;
- }
-
-private void jSlider4StateChanged(javax.swing.event.ChangeEvent evt)
- {
- Integer a = jSlider1.getValue() ;
- Integer b = jSlider2.getValue() ;
- Integer c = jSlider3.getValue() ;
- Integer d = jSlider4.getValue() ;
-
- String ip = String.format("%s.%s.%s.%s", a, b, c, d) ;
-
- jTextField1.setText( ip.toString() ) ;
- }
-
-/**
- * @param args the command line arguments
- */
-public static void main(String args[]) {
- /* Set the Nimbus look and feel */
- //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
- /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
- * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
- */
- try {
- for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
- if ("Nimbus".equals(info.getName())) {
- javax.swing.UIManager.setLookAndFeel(info.getClassName());
- break;
- }
- }
- } catch (ClassNotFoundException ex) {
- java.util.logging.Logger.getLogger(UserInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
- } catch (InstantiationException ex) {
- java.util.logging.Logger.getLogger(UserInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
- } catch (IllegalAccessException ex) {
- java.util.logging.Logger.getLogger(UserInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
- } catch (javax.swing.UnsupportedLookAndFeelException ex) {
- java.util.logging.Logger.getLogger(UserInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
- }
- //</editor-fold>
-
- /* Create and display the form */
- java.awt.EventQueue.invokeLater(new Runnable() {
- public void run() {
- new UserInterface().setVisible(true);
- }
- });
-}
-
-
-public String getIP()
- {
- return ip ;
- }
-
-public String getUsername()
- {
- return username ;
- }
-
-public boolean isDone()
- {
- return done ;
- }
-
-// Variables declaration - do not modify
-private javax.swing.JButton jButton1;
-private javax.swing.JLabel jLabel1;
-private javax.swing.JLabel jLabel2;
-private javax.swing.JSlider jSlider1;
-private javax.swing.JSlider jSlider2;
-private javax.swing.JSlider jSlider3;
-private javax.swing.JSlider jSlider4;
-private javax.swing.JTextField jTextField1;
-private javax.swing.JTextField jTextField2;
-// End of variables declaration
-}