From d740f0951d2369e35e1b3153f2b39ec6dd4319cc Mon Sep 17 00:00:00 2001 From: ayushmaanbhav Date: Mon, 23 Mar 2015 16:28:06 +0530 Subject: [PATCH] Introduced real bidding whereas the code in the master branch operates on Monte Carlo simulation and there is no real bidding. Introduced many new features !!! --- src/client/BackgroundAnimation.java | 417 ----------- src/client/BroadcastClient.java | 74 -- src/client/ButtonColumn.java | 225 ------ src/client/Cashier.java | 333 --------- src/client/ChatClient.java | 55 -- src/client/ChatWindow.java | 70 -- src/client/Client.java | 269 ------- src/client/Companies.java | 48 -- src/client/Company.java | 23 - src/client/HintPasswordField.java | 35 - src/client/HintTextField.java | 35 - src/client/LoginAction.java | 110 --- src/client/LookAndFeel.java | 20 - src/client/Main.java | 564 -------------- src/client/NewsPane.java | 64 -- src/client/RankingClient.java | 35 - src/client/RankingWindow.java | 29 - src/client/RegisterAction.java | 111 --- src/client/RibbonPane.java | 65 -- src/client/ShareValuesChangeListener.java | 6 - src/client/test.java | 7 - .../client/BackgroundAnimation.java | 381 ++++++++++ .../jstockmart/client/BroadcastClient.java | 94 +++ .../jstockmart/client/Cashier.java | 446 +++++++++++ .../jstockmart/client/ChatClient.java | 42 ++ .../jstockmart/client/ChatWindow.java | 79 ++ .../jstockmart/client/Client.java | 244 ++++++ .../jstockmart/client/Companies.java | 57 ++ .../jstockmart/client/Company.java | 53 ++ .../jstockmart/client/GraphPanel.java | 222 ++++++ .../jstockmart/client/HistogramPanel.java | 111 +++ .../jstockmart/client/LoginAction.java | 96 +++ .../ayushmaanbhav/jstockmart/client/Main.java | 667 +++++++++++++++++ .../jstockmart/client/NewsPane.java | 56 ++ .../jstockmart/client/RankingClient.java | 54 ++ .../jstockmart/client/RankingWindow.java | 29 + .../jstockmart/client/Receiver.java | 139 ++++ .../jstockmart/client/RegisterAction.java | 96 +++ .../jstockmart/client/RibbonPane.java | 63 ++ .../client/ShareValuesChangeListener.java | 5 + .../ayushmaanbhav/jstockmart/client/Test.java | 117 +++ .../jstockmart/client/TestMain.java | 5 + .../jstockmart/data/burnstown-dam.regular.ttf | Bin 0 -> 41508 bytes .../jstockmart/data/companies.txt | 21 + .../ayushmaanbhav/jstockmart/data/logo.png | Bin 0 -> 177262 bytes .../ayushmaanbhav/jstockmart/data/logo2.png | Bin 0 -> 91114 bytes .../ayushmaanbhav/jstockmart/data/logo3.png} | Bin .../ayushmaanbhav/jstockmart/data/logo4.png} | Bin .../jstockmart/data/manifest.txt | 2 + .../jstockmart/data/manifest2.txt | 7 + .../ayushmaanbhav/jstockmart/data/money.txt | 1 + src/com/ayushmaanbhav/jstockmart/data/reg.txt | 75 ++ .../jstockmart/server/BroadcastServer.java | 82 +++ .../jstockmart/server/ChatServer.java | 53 ++ .../jstockmart/server/Company.java | 75 ++ .../jstockmart/server/GraphPanel.java | 250 +++++++ .../jstockmart/server/HistogramPanel.java | 94 +++ .../jstockmart/server/MatchingEngine.java | 354 +++++++++ .../jstockmart/server/Orders.java | 157 ++++ .../jstockmart/server/OrdersPanel.java | 169 +++++ .../jstockmart/server/RankingServer.java | 147 ++++ .../jstockmart/server/Server.java | 693 ++++++++++++++++++ .../jstockmart/server/ShareMarket.java | 172 +++++ .../jstockmart/server/StockMart.java | 513 +++++++++++++ .../jstockmart/server/UserDatabase.java | 159 ++++ .../jstockmart/server/UserSharesManager.java | 38 + .../jstockmart/user/Commands.java | 32 + .../ayushmaanbhav/jstockmart/user/Shares.java | 66 ++ .../ayushmaanbhav/jstockmart/user/User.java | 206 ++++++ .../user/UserDataChangedListener.java | 2 +- .../jstockmart/utils/ButtonColumn.java | 198 +++++ .../jstockmart/utils/HintPasswordField.java | 38 + .../jstockmart/utils/HintTextField.java | 37 + .../jstockmart/utils/Histogram.java | 148 ++++ .../jstockmart/utils/LookAndFeel.java | 18 + .../jstockmart/utils/RandomGenerator.java | 18 + .../jstockmart/utils/TrippleArrayList.java | 115 +++ src/server/BroadcastServer.java | 49 -- src/server/ChatServer.java | 44 -- src/server/Company.java | 43 -- src/server/JRealTimeDemo.java | 290 -------- src/server/LookAndFeel.java | 20 - src/server/PseudoRealTimeData.java | 233 ------ src/server/RankingServer.java | 110 --- src/server/RegList.java | 150 ---- src/server/Server.java | 647 ---------------- src/server/ShareMarket.java | 140 ---- src/server/StockMart.java | 351 --------- src/server/companies.txt | 21 - src/server/money.txt | 1 - src/server/reg.txt | 1 - src/user/Shares.java | 27 - src/user/User.java | 173 ----- 93 files changed, 6995 insertions(+), 4896 deletions(-) delete mode 100644 src/client/BackgroundAnimation.java delete mode 100644 src/client/BroadcastClient.java delete mode 100644 src/client/ButtonColumn.java delete mode 100644 src/client/Cashier.java delete mode 100644 src/client/ChatClient.java delete mode 100644 src/client/ChatWindow.java delete mode 100644 src/client/Client.java delete mode 100644 src/client/Companies.java delete mode 100644 src/client/Company.java delete mode 100644 src/client/HintPasswordField.java delete mode 100644 src/client/HintTextField.java delete mode 100644 src/client/LoginAction.java delete mode 100644 src/client/LookAndFeel.java delete mode 100644 src/client/Main.java delete mode 100644 src/client/NewsPane.java delete mode 100644 src/client/RankingClient.java delete mode 100644 src/client/RankingWindow.java delete mode 100644 src/client/RegisterAction.java delete mode 100644 src/client/RibbonPane.java delete mode 100644 src/client/ShareValuesChangeListener.java delete mode 100644 src/client/test.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/BackgroundAnimation.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/BroadcastClient.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Cashier.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/ChatClient.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/ChatWindow.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Client.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Companies.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Company.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/GraphPanel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/HistogramPanel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/LoginAction.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Main.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/NewsPane.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/RankingClient.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/RankingWindow.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Receiver.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/RegisterAction.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/RibbonPane.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/ShareValuesChangeListener.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/Test.java create mode 100644 src/com/ayushmaanbhav/jstockmart/client/TestMain.java create mode 100644 src/com/ayushmaanbhav/jstockmart/data/burnstown-dam.regular.ttf create mode 100644 src/com/ayushmaanbhav/jstockmart/data/companies.txt create mode 100644 src/com/ayushmaanbhav/jstockmart/data/logo.png create mode 100644 src/com/ayushmaanbhav/jstockmart/data/logo2.png rename src/{client/logo2.png => com/ayushmaanbhav/jstockmart/data/logo3.png} (100%) rename src/{client/logo.png => com/ayushmaanbhav/jstockmart/data/logo4.png} (100%) create mode 100644 src/com/ayushmaanbhav/jstockmart/data/manifest.txt create mode 100644 src/com/ayushmaanbhav/jstockmart/data/manifest2.txt create mode 100644 src/com/ayushmaanbhav/jstockmart/data/money.txt create mode 100644 src/com/ayushmaanbhav/jstockmart/data/reg.txt create mode 100644 src/com/ayushmaanbhav/jstockmart/server/BroadcastServer.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/ChatServer.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/Company.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/GraphPanel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/HistogramPanel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/MatchingEngine.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/Orders.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/OrdersPanel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/RankingServer.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/Server.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/ShareMarket.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/StockMart.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/UserDatabase.java create mode 100644 src/com/ayushmaanbhav/jstockmart/server/UserSharesManager.java create mode 100644 src/com/ayushmaanbhav/jstockmart/user/Commands.java create mode 100644 src/com/ayushmaanbhav/jstockmart/user/Shares.java create mode 100644 src/com/ayushmaanbhav/jstockmart/user/User.java rename src/{ => com/ayushmaanbhav/jstockmart}/user/UserDataChangedListener.java (67%) create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/ButtonColumn.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/HintPasswordField.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/HintTextField.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/Histogram.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/LookAndFeel.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/RandomGenerator.java create mode 100644 src/com/ayushmaanbhav/jstockmart/utils/TrippleArrayList.java delete mode 100644 src/server/BroadcastServer.java delete mode 100644 src/server/ChatServer.java delete mode 100644 src/server/Company.java delete mode 100644 src/server/JRealTimeDemo.java delete mode 100644 src/server/LookAndFeel.java delete mode 100644 src/server/PseudoRealTimeData.java delete mode 100644 src/server/RankingServer.java delete mode 100644 src/server/RegList.java delete mode 100644 src/server/Server.java delete mode 100644 src/server/ShareMarket.java delete mode 100644 src/server/StockMart.java delete mode 100644 src/server/companies.txt delete mode 100644 src/server/money.txt delete mode 100644 src/server/reg.txt delete mode 100644 src/user/Shares.java delete mode 100644 src/user/User.java diff --git a/src/client/BackgroundAnimation.java b/src/client/BackgroundAnimation.java deleted file mode 100644 index ba30b10..0000000 --- a/src/client/BackgroundAnimation.java +++ /dev/null @@ -1,417 +0,0 @@ -package client; - -import java.awt.AlphaComposite; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Composite; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagLayout; -import java.awt.HeadlessException; -import java.awt.Image; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.LayoutManager2; -import java.awt.Paint; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionAdapter; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import java.awt.font.FontRenderContext; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Rectangle2D; -import java.awt.geom.RoundRectangle2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.imageio.ImageIO; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSeparator; -import javax.swing.JSlider; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -public class BackgroundAnimation extends JPanel { - - private CurvesPanel curves; - - public BackgroundAnimation() throws HeadlessException { - //super("Stack Layout"); - - buildContentPane(); - // buildDebugControls(); - - startAnimation(); - - //setSize(640, 400); - //setLocationRelativeTo(null); - - //setDefaultCloseOperation(EXIT_ON_CLOSE); - } - - private void startAnimation() { - Timer timer = new Timer(50, new ActionListener() { - public void actionPerformed(ActionEvent e) { - curves.animate(); - curves.repaint(); - } - }); - timer.start(); - } - - private void buildContentPane() { - //JPanel pane = new JPanel(); - setOpaque(false); - setLayout(new StackLayout()); - - GradientPanel gradient = new GradientPanel(); - //chooser = new AvatarChooser(); - curves = new CurvesPanel(); - - add(gradient, StackLayout.TOP); - //add(chooser, StackLayout.TOP); - add(curves, StackLayout.TOP); - - } - - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - } catch (IllegalAccessException ex) { - ex.printStackTrace(); - } catch (InstantiationException ex) { - ex.printStackTrace(); - } catch (UnsupportedLookAndFeelException ex) { - ex.printStackTrace(); - } - - SwingUtilities.invokeLater(new Runnable() { - public void run() { - BackgroundAnimation tester = new BackgroundAnimation(); - tester.setVisible(true); - } - }); - } -} - -class CurvesPanel extends JPanel { - protected RenderingHints hints; - - protected int counter = 0; - - protected Color start = new Color(255, 255, 255, 200); - - protected Color end = new Color(255, 255, 255, 0); - - public CurvesPanel() { - this(new BorderLayout()); - } - - public CurvesPanel(LayoutManager manager) { - super(manager); - hints = createRenderingHints(); - } - - protected RenderingHints createRenderingHints() { - RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - hints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - return hints; - } - - public void animate() { - counter++; - } - - @Override - public boolean isOpaque() { - return false; - } - - @Override - protected void paintComponent(Graphics g) { - Graphics2D g2 = (Graphics2D) g; - - RenderingHints oldHints = g2.getRenderingHints(); - g2.setRenderingHints(hints); - - float width = getWidth(); - float height = getHeight(); - - g2.translate(0, -30); - - drawCurve(g2, 20.0f, -10.0f, 20.0f, -10.0f, width / 2.0f - 40.0f, 10.0f, 0.0f, -5.0f, - width / 2.0f + 40, 1.0f, 0.0f, 5.0f, 50.0f, 5.0f, false); - - g2.translate(0, 30); - g2.translate(0, height - 60); - - drawCurve(g2, 30.0f, -15.0f, 50.0f, 15.0f, width / 2.0f - 40.0f, 1.0f, 15.0f, -25.0f, - width / 2.0f, 1.0f / 2.0f, 0.0f, 25.0f, 15.0f, 9.0f, false); - - g2.translate(0, -height + 60); - - drawCurve(g2, height - 35.0f, -5.0f, height - 50.0f, 10.0f, width / 2.0f - 40.0f, 1.0f, - height - 35.0f, -25.0f, width / 2.0f, 1.0f / 2.0f, height - 20.0f, 25.0f, 25.0f, 7.0f, true); - - g2.setRenderingHints(oldHints); - } - - protected void drawCurve(Graphics2D g2, float y1, float y1_offset, float y2, float y2_offset, - float cx1, float cx1_offset, float cy1, float cy1_offset, float cx2, float cx2_offset, - float cy2, float cy2_offset, float thickness, float speed, boolean invert) { - float width = getWidth(); - - float offset = (float) Math.sin(counter / (speed * Math.PI)); - - float start_x = 0.0f; - float start_y = offset * y1_offset + y1; - float end_x = width; - float end_y = offset * y2_offset + y2; - - float ctrl1_x = offset * cx1_offset + cx1; - float ctrl1_y = offset * cy1_offset + cy1; - float ctrl2_x = offset * cx2_offset + cx2; - float ctrl2_y = offset * cy2_offset + cy2; - - GeneralPath thickCurve = new GeneralPath(); - thickCurve.moveTo(start_x, start_y); - thickCurve.curveTo(ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, end_x, end_y); - thickCurve.lineTo(end_x, end_y + thickness); - thickCurve.curveTo(ctrl2_x, ctrl2_y + thickness, ctrl1_x, ctrl1_y + thickness, start_x, start_y - + thickness); - thickCurve.lineTo(start_x, start_y); - - Rectangle bounds = thickCurve.getBounds(); - if (!bounds.intersects(g2.getClipBounds())) { - return; - } - - GradientPaint painter = new GradientPaint(0, bounds.y, invert ? end : start, 0, bounds.y - + bounds.height, invert ? start : end); - - Paint oldPainter = g2.getPaint(); - g2.setPaint(painter); - g2.fill(thickCurve); - - g2.setPaint(oldPainter); - } -} - -class GradientPanel extends JPanel { - protected BufferedImage gradientImage; - - protected Color gradientStart = Color.GRAY.brighter();//new Color(204, 249, 124); - - protected Color gradientEnd = Color.GRAY;//new Color(174, 222, 94); - - public GradientPanel() { - this(new BorderLayout()); - } - - public GradientPanel(LayoutManager layout) { - super(layout); - addComponentListener(new GradientCacheManager()); - } - - @Override - protected void paintComponent(Graphics g) { - createImageCache(); - - if (gradientImage != null) { - g.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), null); - } - } - - protected void createImageCache() { - int width = 2; - int height = getHeight(); - - if (width == 0 || height == 0) { - return; - } - - if (gradientImage == null || width != gradientImage.getWidth() - || height != gradientImage.getHeight()) { - - gradientImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - - Graphics2D g2 = gradientImage.createGraphics(); - GradientPaint painter = new GradientPaint(0, 0, gradientEnd, 0, height / 2, gradientStart); - g2.setPaint(painter); - - Rectangle2D rect = new Rectangle2D.Double(0, 0, width, height / 2.0); - g2.fill(rect); - - painter = new GradientPaint(0, height / 2, gradientStart, 0, height, gradientEnd); - g2.setPaint(painter); - - rect = new Rectangle2D.Double(0, (height / 2.0) - 1.0, width, height); - g2.fill(rect); - - g2.dispose(); - } - } - - private void disposeImageCache() { - synchronized (gradientImage) { - gradientImage.flush(); - gradientImage = null; - } - } - - private class GradientCacheManager implements ComponentListener { - public void componentResized(ComponentEvent e) { - } - - public void componentMoved(ComponentEvent e) { - } - - public void componentShown(ComponentEvent e) { - } - - public void componentHidden(ComponentEvent e) { - disposeImageCache(); - } - } -} - -class StackLayout implements LayoutManager2 { - public static final String BOTTOM = "bottom"; - - public static final String TOP = "top"; - - private List components = new LinkedList(); - - public void addLayoutComponent(Component comp, Object constraints) { - synchronized (comp.getTreeLock()) { - if (BOTTOM.equals(constraints)) { - components.add(0, comp); - } else if (TOP.equals(constraints)) { - components.add(comp); - } else { - components.add(comp); - } - } - } - - public void addLayoutComponent(String name, Component comp) { - addLayoutComponent(comp, TOP); - } - - public void removeLayoutComponent(Component comp) { - synchronized (comp.getTreeLock()) { - components.remove(comp); - } - } - - public float getLayoutAlignmentX(Container target) { - return 0.5f; - } - - public float getLayoutAlignmentY(Container target) { - return 0.5f; - } - - public void invalidateLayout(Container target) { - } - - public Dimension preferredLayoutSize(Container parent) { - synchronized (parent.getTreeLock()) { - int width = 0; - int height = 0; - - for (Component comp : components) { - Dimension size = comp.getPreferredSize(); - width = Math.max(size.width, width); - height = Math.max(size.height, height); - } - - Insets insets = parent.getInsets(); - width += insets.left + insets.right; - height += insets.top + insets.bottom; - - return new Dimension(width, height); - } - } - - public Dimension minimumLayoutSize(Container parent) { - synchronized (parent.getTreeLock()) { - int width = 0; - int height = 0; - - for (Component comp : components) { - Dimension size = comp.getMinimumSize(); - width = Math.max(size.width, width); - height = Math.max(size.height, height); - } - - Insets insets = parent.getInsets(); - width += insets.left + insets.right; - height += insets.top + insets.bottom; - - return new Dimension(width, height); - } - } - - public Dimension maximumLayoutSize(Container target) { - return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - public void layoutContainer(Container parent) { - synchronized (parent.getTreeLock()) { - int width = parent.getWidth(); - int height = parent.getHeight(); - - Rectangle bounds = new Rectangle(0, 0, width, height); - - int componentsCount = components.size(); - - for (int i = 0; i < componentsCount; i++) { - Component comp = components.get(i); - comp.setBounds(bounds); - parent.setComponentZOrder(comp, componentsCount - i - 1); - } - } - } -} \ No newline at end of file diff --git a/src/client/BroadcastClient.java b/src/client/BroadcastClient.java deleted file mode 100644 index a3f9902..0000000 --- a/src/client/BroadcastClient.java +++ /dev/null @@ -1,74 +0,0 @@ -package client; -import java.io.*; -import java.net.*; -import java.util.*; -import javax.swing.*; -import java.text.*; -public class BroadcastClient extends Thread -{ - StringBuffer sb; - DecimalFormat twoDForm; - ShareValuesChangeListener svcl; - public BroadcastClient(StringBuffer s) - { - sb=s; - svcl=null; - Companies.comp=new ArrayList(); - twoDForm = new DecimalFormat("#.##"); - } - public void run(String poo) - { - try{ - StringBuffer fin=new StringBuffer(); - try{ - final String rec[]=poo.split("="); - final String mtr[]=rec[0].split(";"); - final String str[]=rec[1].split(";"); - final List clist=new ArrayList(); - for(int i=0;ib) - fin.append("\u25b2"); //This is some text! - else if(a0.0) - fin.append(twoDForm.format(c)); - else if(c<0.0) - fin.append(twoDForm.format(-c)); - fin.append(" "); - } - sb.delete(0,sb.length()); - sb.append(fin.toString()); - SwingUtilities.invokeLater(new Runnable(){ - public void run() - { - try{ - if(Main.imglabel2!=null) - Main.imglabel2.setText("
Sensex: "+mtr[1]+"
Time Left: "+mtr[0]+"
"); - }catch(Exception bb){bb.printStackTrace();} - try{ - svcl.valuesChanged(); - for(int i=0;i((float)0.9)) - { - alphaChanger.stop(); - jd.setVisible(false); - ii=0; - } - try{ - AWTUtilities.setWindowOpacity(jd,Float.valueOf((float)(1-ii))); - }catch(Exception m){} - } - }); - Client client; - User user; - JLabel cash,jlab,tot; - double total=0; - Company comp; - JTextField jtf; - Shares pp; - String cmp; - JRadioButton b2,b1; - static boolean closee=false; - Timer timer = new Timer(250,new ActionListener() { - public void actionPerformed(ActionEvent e) - { - if(closee) - { - timer.stop(); - jd.setVisible(false); - closee=false; - } - comp=Companies.getCompanyWithName(cmp); - cash.setText("Cash Avail : "+twoDForm.format(user.getCurrentMoney())); - jlab.setText("Company : "+cmp+" , C.M.P. : "+twoDForm.format(comp.mktvalue)); - try - { - int ent=Integer.parseInt(jtf.getText()); - if(b1.isSelected()) - { - total=Double.valueOf(twoDForm.format(ent*comp.mktvalue*1.02)); - if(total>user.getCurrentMoney()) - tot.setForeground(Color.red); - else - tot.setForeground(Color.black); - } - else - if(b2.isSelected()) - { - total=Double.valueOf(twoDForm.format(ent*comp.mktvalue*0.98)); - if(ent>pp.qty) - tot.setForeground(Color.red); - else - tot.setForeground(Color.black); - } - }catch(Exception v) - { - total=0; - tot.setForeground(Color.red); - } - tot.setText("Total Cash Req./Rec.*: "+twoDForm.format(total)); - } - }); - public Cashier(Client c,User u) - { - client=c; - user=u; - } - void showDialog(String c,final int bs,final Shares shr) - { - cmp=c; - pp=shr; - jd=new JDialog(); - jd.setUndecorated(true); - comp=Companies.getCompanyWithName(cmp); - JPanel pan=new JPanel(){ - @Override - protected void paintComponent(Graphics grphcs) { - Graphics2D g2d = (Graphics2D) grphcs; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); - GradientPaint gp = new GradientPaint(0, 0,getBackground().brighter(), 0, getHeight(),getBackground().darker()); - g2d.setPaint(gp); - g2d.fillRect(0, 0, getWidth(), getHeight()); - super.paintComponent(grphcs); - } - }; - pan.setLayout(new GridBagLayout()); - jlab=new JLabel("Company : "+cmp+" , C.M.P. : "+twoDForm.format(comp.mktvalue)); - JLabel op=new JLabel("Operation : "); - tot=new JLabel("Total Cash Req./Rec.:"+twoDForm.format(total)); - b1=new JRadioButton("Buy"); - b2=new JRadioButton("Sell"); - if(bs==0) - b1.setSelected(true); - else - b2.setSelected(true); - ButtonGroup grp=new ButtonGroup(); - grp.add(b1);grp.add(b2); - final JLabel qty=new JLabel("Quantity : "); - jtf=new JTextField(10); - jtf.setText("0"); - cash=new JLabel("Cash Avail : "+twoDForm.format(user.getCurrentMoney())); - final JButton jb1=new JButton("Place Order"); - final JButton jb2=new JButton("Cancel"); - jb2.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e) - { - timer.stop(); - jd.setVisible(false); - } - }); - jb1.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e) - { - int noofs=0; - try{ - noofs=Integer.parseInt(jtf.getText()); - }catch(Exception ee){ - jtf.setForeground(Color.red); - qty.setForeground(Color.red); - return; - } - if(noofs<=0) - { - jtf.setForeground(Color.red); - qty.setForeground(Color.red); - return; - } - if(b2.isSelected() && noofs>shr.qty) - { - jtf.setForeground(Color.red); - qty.setForeground(Color.red); - return; - } - if(b1.isSelected() && noofs*comp.mktvalue>user.getCurrentMoney()) - { - jtf.setForeground(Color.red); - qty.setForeground(Color.red); - return; - } - jtf.setForeground(Color.black); - qty.setForeground(Color.black); - tot.setForeground(Color.black); - jtf.setEnabled(false); - jb1.setEnabled(false); - jb2.setEnabled(false); - b1.setEnabled(false); - b2.setEnabled(false); - final int kk=noofs; - new Thread(){ - public void run(){ - String cmd; - if(b1.isSelected()) - cmd="buy"; - else - cmd="sell"; - User usr; - try{ - client.placeOrder(user,cmd,comp,kk,shr.id); - }catch(Exception ff) - { - client.placeOrder(user,cmd,comp,kk,-1); - } - //user.changeData(usr); - timer.stop(); - alphaChanger.start(); - } - }.start(); - } - }); - JLabel cc1=new JLabel("-> *Transaction charges : 2% of the total cash transactioned."); - JLabel cc2=new JLabel("-> Order will be executed 30-40 secs after it is placed."); - JLabel cc3=new JLabel("-> Order can be canceled within 10 secs after it is placed."); - GridBagConstraints gbc=new GridBagConstraints(); - gbc.gridx=0; - gbc.gridy=0; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(jlab,gbc); - gbc.gridx=0; - gbc.gridy=1; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(op,gbc); - gbc.gridx=1; - gbc.gridy=1; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(b1,gbc); - gbc.gridx=2; - gbc.gridy=1; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(b2,gbc); - gbc.gridx=0; - gbc.gridy=2; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(qty,gbc); - gbc.gridx=1; - gbc.gridy=2; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=2; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(jtf,gbc); - gbc.gridx=0; - gbc.gridy=3; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(tot,gbc); - gbc.gridx=0; - gbc.gridy=4; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(cash,gbc); - gbc.gridx=0; - gbc.gridy=5; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(jb1,gbc); - gbc.gridx=1; - gbc.gridy=5; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=1; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(jb2,gbc); - gbc.gridx=0; - gbc.gridy=6; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(cc1,gbc); - gbc.gridx=0; - gbc.gridy=7; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(cc2,gbc); - gbc.gridx=0; - gbc.gridy=8; - gbc.fill=GridBagConstraints.NONE; - gbc.gridwidth=3; - gbc.gridheight=1; - gbc.ipadx=0; - gbc.ipady=0; - gbc.anchor=GridBagConstraints.LINE_START; - //gbc.insets=new Insets(0,0,100,0); - pan.add(cc3,gbc); - pan.setOpaque(false); - pan.setBorder(new CompoundBorder(BorderFactory.createLineBorder(Color.black, 1),BorderFactory.createEmptyBorder(5,5,5,5))); - jd.setContentPane(pan); - timer.start(); - jd.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); - jd.pack(); - jd.setLocationRelativeTo(null); - jd.setVisible(true); - } -} \ No newline at end of file diff --git a/src/client/ChatClient.java b/src/client/ChatClient.java deleted file mode 100644 index 64b5ae0..0000000 --- a/src/client/ChatClient.java +++ /dev/null @@ -1,55 +0,0 @@ -package client; -import java.io.*; -import java.net.*; -import java.util.*; -import javax.swing.*; -public class ChatClient extends Thread -{ - JTextArea jta; - public ChatClient(JTextArea ja) - { - jta=ja; - } - public void run(String hh) - { - try{ - StringBuffer fin=new StringBuffer(" "); - final String str=hh.trim(); - SwingUtilities.invokeLater(new Runnable(){ - public void run() - { - String s[]=str.split(";"); - if(s.length<2) - return; - else - { - if(!s[1].equals("-1")) - jta.setText(jta.getText()+"\n"+s[1]); - if(!s[0].equals("-1")) - { - String ff[]=s[0].split(":"); - String jj=""; - for(int i=0;i> ("+u.getChat()+" characters remainimg)"); - jtf=new JTextField(); - jta=new JTextArea(); - jta.setFont(new Font("Lucida Sans Unicode",Font.PLAIN,12)); - jta.setLineWrap(true); - jta.setEditable(false); - jta.setForeground(Color.green.darker()); - //jtf.setEnabled(false); - jtf.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - final String s = jtf.getText(); - if (!s.equals("")) - { - jtf.setText(""); - new Thread(){ - public void run(){ - try - { - remain=sendString(s); - u.setChat(Integer.parseInt(remain)); - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - jlab.setText("<> ("+u.getChat()+" characters remainimg)"); - } - }); - }catch(Exception mm){} - if(u.getChat()<=0) - JOptionPane.showMessageDialog(null,"Sorry, You have finished your chat limit.","Error:",JOptionPane.PLAIN_MESSAGE); - } - }.start(); - } - } - }); - JScrollPane jsp=new JScrollPane(jta,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - add(jlab,BorderLayout.NORTH); - add(jsp,BorderLayout.CENTER); - add(jtf,BorderLayout.SOUTH); - try{ - jta.setText(cc.getChatHistory(user.getName(),user.getPassword())); - }catch(Exception mmm){} - ChatClient cser=new ChatClient(jta); - //cser.start(); - client.cc=cser; - } - String sendString(String s) - { - return cc.sendChat(s,user.getName(),user.getPassword()); - } -} \ No newline at end of file diff --git a/src/client/Client.java b/src/client/Client.java deleted file mode 100644 index caf66e0..0000000 --- a/src/client/Client.java +++ /dev/null @@ -1,269 +0,0 @@ -package client; -import java.io.*; -import java.net.*; -import java.util.*; -import javax.swing.*; -import user.*; - -public class Client { - private boolean connected = false; - Socket socket = null; - PrintWriter out = null; - //BufferedReader in = null; - ObjectInputStream in; - String domain; - Object reply; - volatile int commID=0; - Client ccl; - int usrD; - Main m; - BroadcastClient bc=null; - RankingClient rc=null; - ChatClient cc=null; - Receiver rec; - - public Client(Main mm) - { - ccl=this; - reply=null; - m=mm; - } - - class Receiver extends Thread - { - ObjectInputStream in; - List rev; - public Receiver(ObjectInputStream i) - { - in=i; - rev=new ArrayList(); - } - public void run() - { - while(connected) - { - try{ - Object obj = in.readObject(); - if(obj.toString().equals("101")) - { - connected=false; - in.close(); - out.close(); - socket.close(); - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - Cashier.closee=true; - JOptionPane.showMessageDialog(null,"Disconnected from server.","Error:",JOptionPane.PLAIN_MESSAGE); - m.getAppletContext().showDocument(m.getDocumentBase(), "_self"); - } - }); - } - else if(obj.toString().equals("102")) - { - reply=obj; - ccl.interrupt(); - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - Cashier.closee=true; - JOptionPane.showMessageDialog(null,"Server Not Running.","Error:",JOptionPane.PLAIN_MESSAGE); - } - }); - } - else if(obj.toString().split("::")[0].equals("broadcast")) - { - bc.run(obj.toString().substring(obj.toString().indexOf("::")+2)); - } - else if(obj.toString().split("::")[0].equals("chat")) - { - cc.run(obj.toString().substring(obj.toString().indexOf("::")+2)); - } - else if(obj.toString().split("::")[0].equals("rank")) - { - rc.run(obj.toString().substring(obj.toString().indexOf("::")+2)); - } - else - { - User hhh=null; - try - { - hhh=(User)obj; - if(usrD==1) - { - reply=obj; - ccl.interrupt(); - } - else - { - m.ur.changeData((User)obj); - } - }catch(Exception p) - { - reply=obj; - ccl.interrupt(); - } - } - try{ - Thread.sleep(500); - }catch(Exception n){} - }catch(Exception m){} - } - } - } - - public void connect(String user,String pass) { - if (!connected) - { - try { - socket = new Socket(domain,4446); - out = new PrintWriter(socket.getOutputStream(), true); - //in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - in=new ObjectInputStream(socket.getInputStream()); - } catch (java.net.UnknownHostException e) { - System.err.println("Don't know about host"); - return; - } catch (IOException e) { - System.err.println("Couldn't get I/O for the connection to"); - return; - } - this.connected = true; - rec=new Receiver(in); - rec.start(); - commID=0; - } - } - - String login(String domain,String user,String pass) - { - int cmdID=commID++; - this.domain=domain; - connect(user,pass); - try{ - out.println(cmdID+";login:"+user+":"+pass); - out.flush(); - String rep=(String)receiveReply(0); - return rep.split(":")[0]; - }catch(Exception r){ - r.printStackTrace();} - return null; - } - - String register(String domain,String regno,String user,String pass) - { - int cmdID=commID++; - this.domain=domain; - connect(user,pass); - try{ - out.println(cmdID+";reg:"+regno+":"+user+":"+pass); - out.flush(); - String rep=(String)receiveReply(0); - disconnect(); - return rep.split(":")[0]; - }catch(Exception r){r.printStackTrace();} - return null; - } - - public void disconnect() - { - int cmdID=commID++; - this.connected = false; - try { - out.println(cmdID+";logout"); - out.flush(); - in.close(); - out.close(); - socket.close(); - } catch (IOException ex) { - System.err.println("Server stop failed."); - } - } - - User getUserDetails(String user,String pass) - { - int cmdID=commID++; - connect(user,pass); - try{ - usrD=1; - out.println(cmdID+";gud"); - out.flush(); - User vv=(User)receiveReply(0); - usrD=0; - return vv; - }catch(Exception r){ - r.printStackTrace();} - return null; - } - - String sendChat(String s,String user,String pass) - { - int cmdID=commID++; - connect(user,pass); - try{ - out.println(cmdID+";chat:"+s.trim()); - out.flush(); - return (String)receiveReply(0); - }catch(Exception r){ - r.printStackTrace();} - return null; - } - - String getChatHistory(String user,String pass) - { - int cmdID=commID++; - connect(user,pass); - try{ - out.println(cmdID+";chath"); - out.flush(); - return (String)receiveReply(0); - }catch(Exception r){ - r.printStackTrace();} - return null; - } - - void placeOrder(final User user,String cmd,Company comp,int qty,int id) - { - int cmdID=commID++; - connect(user.getName(),user.getPassword()); - try{ - out.println(cmdID+";"+cmd+":"+comp.name+":"+Integer.toString(qty)+":"+id); - out.flush(); - Shares pen=(Shares)receiveReply(0); - user.getPendingShares().add(pen); - user.dataChanged(); - }catch(Exception r){ - r.printStackTrace();} - } - - String cancelShares(String user,String pass,int id,int sellid) - { - int cmdID=commID++; - connect(user,pass); - try{ - out.println(cmdID+";cancel:"+id+":"+sellid); - out.flush(); - return (String)receiveReply(0); - }catch(Exception r){ - r.printStackTrace();} - return null; - } - - boolean loop; - Object receiveReply(int cmdID) - { - loop=true; - int i=0; - while(loop && i<=300) - { - try - { - Thread.sleep(100); - i++; - }catch(Exception m){} - } - return reply; - } - - void interrupt() - { - loop=false; - } -} \ No newline at end of file diff --git a/src/client/Companies.java b/src/client/Companies.java deleted file mode 100644 index 4fd92fc..0000000 --- a/src/client/Companies.java +++ /dev/null @@ -1,48 +0,0 @@ -package client; - -import java.util.*; -class Companies -{ - static List comp; - static Double sensex; - static Company getCompanyWithName(String name) - { - for(int i=0;i
Sensex: 
Time Left:
"); - imglabel2.setHorizontalTextPosition(JLabel.LEFT); - imglabel2.setVerticalTextPosition(JLabel.BOTTOM); - add.add(imglabel2,BorderLayout.CENTER); - gbc.gridx=0; - gbc.gridy=1; - gbc.fill=GridBagConstraints.HORIZONTAL; - gbc.gridwidth=5; - gbc.gridheight=2; - gbc.ipadx=0; - gbc.ipady=0; - gbc.insets=new Insets(20,40,0,0); - gbc.anchor=GridBagConstraints.PAGE_START; - gbc.weightx=1.0; - gbc.weighty=1.0; - mpane.add(add,gbc); - - JTabbedPane jtp=new JTabbedPane(); - jtp.setPreferredSize(new Dimension((getWidth()*5)/8,(getHeight()*6)/10)); - userpane=new JPanel[3]; - - dtm=new DefaultTableModel[3]; - dtm[0]=new DefaultTableModel(columnNames1,0); - dtm[1]=new DefaultTableModel(columnNames2,0); - dtm[2]=new DefaultTableModel(columnNames3,0); - - - table=new JTable[3]; - JScrollPane jspt[]=new JScrollPane[3]; - mon=new JLabel[3]; - - cash=new Cashier(client,ur); - table[0]=new JTable(dtm[0]) - { - public boolean isCellEditable(int row, int col) - { - if(col==7) - return true; - return false; - } - public boolean isCellSelected(int row, int col) - { - return false; - } - }; - table[1]=new JTable(dtm[1]) - { - public boolean isCellEditable(int row, int col) - { - if(col==6) - return true; - return false; - } - public boolean isCellSelected(int row, int col) - { - return false; - } - }; - table[2]=new JTable(dtm[2]) - { - public boolean isCellEditable(int row, int col) - { - if(col==4) - return true; - return false; - } - public boolean isCellSelected(int row, int col) - { - return false; - } - }; - - for(int i=0;i<3;i++) - { - table[i].setDragEnabled(false); - table[i].setRowSelectionAllowed(false); - table[i].setColumnSelectionAllowed(false); - //table.setShowHorizontalLines(true); - //table.setShowVerticalLines(true); - table[i].setRowHeight(30); - table[i].getTableHeader().setReorderingAllowed(false); - table[i].setFillsViewportHeight(true); - jspt[i]=new JScrollPane(table[i]); - userpane[i]=new JPanel(new BorderLayout()); - userpane[i].add(jspt[i],BorderLayout.CENTER); - mon[i]=new JLabel("Avail. Cash : "+twoDForm.format(user.getCurrentMoney())); - mon[i].setFont(new Font("Tempus Sans ITC",Font.BOLD,20)); - userpane[i].add(mon[i],BorderLayout.SOUTH); - } - - delete = new AbstractAction() - { - public void actionPerformed(ActionEvent e) - { - JTable table = (JTable)e.getSource(); - final int row = Integer.valueOf(e.getActionCommand()); - if(table==main.table[0]) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - cash.showDialog((String)main.table[0].getValueAt(row,1),1,ur.getCurrentShares().get(row)); - } - }); - } - else - if(table==main.table[1]) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - cash.showDialog((String)main.table[1].getValueAt(row,1),0,null); - } - }); - } - else - if(table==main.table[2]) - { - int res=JOptionPane.showConfirmDialog(null,"Are you sure ?","Confirm:",JOptionPane.YES_NO_OPTION,JOptionPane.PLAIN_MESSAGE); - if(res==JOptionPane.YES_OPTION) - { - new Thread(){ - public void run(){ - final String res=client.cancelShares(ur.getName(),ur.getPassword(),ur.getPendingShares().get(row).id,ur.getPendingShares().get(row).sellid); - if(res.equals("0")) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Sorry your cancellation period is over.","Error:",JOptionPane.PLAIN_MESSAGE); - } - }); - } - else if(res.equals("1")) - { - ur.getPendingShares().get(row).status="Cancelling"; - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - updateTables(); - } - }); - } - } - }.start(); - } - } - } - }; - /*ButtonColumn b=new ButtonColumn(table[0], delete, 7); - ButtonColumn b2=new ButtonColumn(table[1], delete, 6); - ButtonColumn b3=new ButtonColumn(table[2], delete, 4);*/ - jtp.add("Holdings",userpane[0]); - jtp.add("Watchlist",userpane[1]); - jtp.add("Transactions",userpane[2]); - gbc.gridx=0; - gbc.gridy=3; - gbc.fill=GridBagConstraints.HORIZONTAL; - gbc.gridwidth=5; - gbc.gridheight=5; - gbc.ipadx=0; - gbc.ipady=0; - gbc.insets=new Insets(0,40,60,0); - gbc.anchor=GridBagConstraints.PAGE_END; - gbc.weightx=1.0; - gbc.weighty=1.0; - mpane.add(jtp,gbc); - jtp.repaint(); - udcl=new UserDataChangedListener(){ - public void userDataChanged(User user) - { - updateTables(); - } - }; - user.addUserDataChangeListener(udcl); - svcl=new ShareValuesChangeListener(){ - public void valuesChanged() - { - updateTables(); - } - }; - rb.addShareValuesChangeListener(svcl); - } - DefaultTableCellRenderer dtr=new DefaultTableCellRenderer(){ - public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) { - if(value.toString().indexOf("-")!=-1) - { - value=value.toString()+" \u25bc"; - } - else - { - value=value.toString()+" \u25b2"; - } - Component c = super.getTableCellRendererComponent(table, value,isSelected, hasFocus,row, column); - if(value.toString().indexOf("-")!=-1) - { - c.setForeground(Color.red); - } - else - { - c.setForeground(Color.green); - } - return c; - } - }; - void updateTables() - { - try{ - for(int i=0;i<3;i++) - { - mon[i].setText("Avail. Cash : "+twoDForm.format(ur.getCurrentMoney())); - mon[i].repaint(); - } - }catch(Exception mm){mm.printStackTrace();} - try{ - java.util.List ss=ur.getCurrentShares(); - Object data[][]=new Object[ss.size()][8]; - for(int i=0;i ss=ur.getPendingShares(); - Object data[][]=new Object[ss.size()][5]; - for(int i=0;i
News : 
"); - l.setFont(new Font("Arial",Font.BOLD,13)); - l.setOpaque(false); - setSize(getWidth(),30); - add(l,BorderLayout.CENTER); - } - protected void paintComponent(Graphics grphcs) { - Graphics2D g2d = (Graphics2D) grphcs; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); - GradientPaint gp = new GradientPaint(0, 0,getBackground().brighter(), 0, getHeight(),getBackground().darker()); - g2d.setPaint(gp); - g2d.fillRect(0, 0, getWidth(), getHeight()); - super.paintComponent(grphcs); - } - void startAnimation() - { - loop=0; - t.start(); - } - void stopAnimation() - { - loop=0; - t.stop(); - } - public void actionPerformed(ActionEvent e) - { - if(sb.length()>200) - { - l.setText("
News : "+sb.substring(0,200)+"
"); - sb.append(sb.charAt(0)); - sb.delete(0,1); - loop++; - if(loop>sb.length()) - { - sb=new StringBuffer(temp); - loop=0; - } - } - else - { - sb=new StringBuffer(temp); - loop=0; - } - } -} \ No newline at end of file diff --git a/src/client/RankingClient.java b/src/client/RankingClient.java deleted file mode 100644 index 981ff2c..0000000 --- a/src/client/RankingClient.java +++ /dev/null @@ -1,35 +0,0 @@ -package client; -import java.io.*; -import java.net.*; -import java.util.*; -import javax.swing.*; -public class RankingClient extends Thread -{ - JTextPane jta; - public RankingClient(JTextPane ja) - { - jta=ja; - } - public void run(String hh) - { - try{ - StringBuffer fin=new StringBuffer(" "); - String str[]=hh.trim().split(":"); - String f=""; - for(int i=0;i\n"; - } - final String h=f; - SwingUtilities.invokeLater(new Runnable(){ - public void run() - { - jta.setText(h); - } - }); - }catch(Exception e) - { - e.printStackTrace(); - } - } -} diff --git a/src/client/RankingWindow.java b/src/client/RankingWindow.java deleted file mode 100644 index 7f3f42c..0000000 --- a/src/client/RankingWindow.java +++ /dev/null @@ -1,29 +0,0 @@ -package client; -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import javax.swing.text.*; -import user.*; - -class RankingWindow extends JPanel -{ - JTextPane jta; - public RankingWindow(Client cc) - { - setLayout(new BorderLayout()); - JLabel jlab=new JLabel("<>"); - jta=new JTextPane(); - StyledDocument doc = jta.getStyledDocument(); - SimpleAttributeSet center = new SimpleAttributeSet(); - StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); - doc.setParagraphAttributes(0, doc.getLength(), center, false); - jta.setFont(new Font("Lucida Sans Unicode",Font.BOLD,14)); - jta.setEditable(false); - jta.setForeground(Color.red.darker()); - JScrollPane jsp=new JScrollPane(jta,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - add(jlab,BorderLayout.NORTH); - add(jsp,BorderLayout.CENTER); - RankingClient cser=new RankingClient(jta); - cc.rc=cser; - } -} \ No newline at end of file diff --git a/src/client/RegisterAction.java b/src/client/RegisterAction.java deleted file mode 100644 index a9a75e0..0000000 --- a/src/client/RegisterAction.java +++ /dev/null @@ -1,111 +0,0 @@ -package client; -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import java.io.BufferedInputStream; -import javax.swing.border.*; -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -class RegisterAction implements ActionListener -{ - HintTextField reg,user; - HintPasswordField pass; - String domain; - Client client; - public RegisterAction(HintTextField r,HintTextField u,HintPasswordField p,String d,Client c) - { - reg=r; - user=u; - pass=p; - domain=d; - client =c; - } - public void actionPerformed(ActionEvent e) - { - Pattern p1=Pattern.compile("[a-z0-9_]{3,16}"); - Pattern p2=Pattern.compile("[a-z0-9_]{6,18}"); - if(!p1.matcher(reg.getText()).matches()) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Incorect registration no.\nThe registration no. should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.","Error:",JOptionPane.PLAIN_MESSAGE); - user.setText(""); - } - }); - return; - } - if(!p1.matcher(user.getText()).matches()) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Incorrect username.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.","Error:",JOptionPane.PLAIN_MESSAGE); - user.setText(""); - } - }); - return; - } - if(!p2.matcher(pass.getText()).matches()) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Incorrect password.\nA password should be of length {6-18} and can contain\nletters(a-z), numbers and underscores","Error:",JOptionPane.PLAIN_MESSAGE); - pass.setText(""); - } - }); - return; - } - if(domain.equals("domain")) - { - domain=JOptionPane.showInputDialog("Enter domain."); - } - if(domain==null || domain.equals("")) - return; - new Thread(){ - public void run() - { - String rep=client.register(domain,reg.getText(),user.getText(),pass.getText()); - if(rep==null) - return; - if(rep.equals("1")) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Server Replies: Reg Successful","Registration",JOptionPane.PLAIN_MESSAGE); - } - }); - // regestered - } - else if(rep.equals("3")) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Server Replies: Username already exists.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.","Error:",JOptionPane.PLAIN_MESSAGE); - user.setText(""); - } - }); - return; - } - else if(rep.equals("2")) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Server Replies: Incorect registration no.\nThe registration no. should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.","Error:",JOptionPane.PLAIN_MESSAGE); - reg.setText(""); - } - }); - return; - } - else if(rep.equals("4")) - { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - JOptionPane.showMessageDialog(null,"Server Replies: Already registered.","Error:",JOptionPane.PLAIN_MESSAGE); - } - }); - return; - } - } - }.start(); - } -} \ No newline at end of file diff --git a/src/client/RibbonPane.java b/src/client/RibbonPane.java deleted file mode 100644 index 79e9519..0000000 --- a/src/client/RibbonPane.java +++ /dev/null @@ -1,65 +0,0 @@ -package client; -import javax.swing.*; -import java.awt.event.*; -import java.awt.*; -class RibbonPane extends JPanel implements ActionListener -{ - StringBuffer sb,temp; - BroadcastClient bc; - Timer t; - int loop; - JLabel l; - final String wel=" StockMart Anwesha'13 "; - public RibbonPane(int tm,Client cc) - { - sb=new StringBuffer(wel); - temp=new StringBuffer(wel); - bc=new BroadcastClient(temp); - cc.bc=bc; - t=new Timer(tm,this); - setOpaque(false); - l=new JLabel(wel); - l.setFont(new Font("Arial",Font.BOLD,13)); - l.setOpaque(false); - add(l); - } - protected void paintComponent(Graphics grphcs) { - Graphics2D g2d = (Graphics2D) grphcs; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); - GradientPaint gp = new GradientPaint(0, 0,getBackground().brighter(), 0, getHeight(),getBackground().darker()); - g2d.setPaint(gp); - g2d.fillRect(0, 0, getWidth(), getHeight()); - super.paintComponent(grphcs); - } - void startAnimation() - { - loop=0; - t.start(); - //bc.start(); - } - void stopAnimation() - { - loop=0; - t.stop(); - //bc.interrupt(); - } - public void actionPerformed(ActionEvent e) - { - if(sb.length()>260) - { - l.setText("
"+sb.substring(0,260).replace("\u25b2","\u25b2").replace("\u25bc","\u25bc")+"
");
-            sb.append(sb.charAt(0));
-            sb.delete(0,1);
-            loop++;
-            if(loop>sb.length())
-            {
-                sb=new StringBuffer(temp);
-                loop=0;
-            }
-        }
-    }
-    void addShareValuesChangeListener(ShareValuesChangeListener svcl)
-    {
-        bc.svcl=svcl;
-    }
-}
\ No newline at end of file
diff --git a/src/client/ShareValuesChangeListener.java b/src/client/ShareValuesChangeListener.java
deleted file mode 100644
index 3572653..0000000
--- a/src/client/ShareValuesChangeListener.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package client;
-
-interface ShareValuesChangeListener
-{
-    public void valuesChanged();
-}
\ No newline at end of file
diff --git a/src/client/test.java b/src/client/test.java
deleted file mode 100644
index 4d169f2..0000000
--- a/src/client/test.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package client;
-class test
-{
-    public void run()
-    {
-    }
-}
\ No newline at end of file
diff --git a/src/com/ayushmaanbhav/jstockmart/client/BackgroundAnimation.java b/src/com/ayushmaanbhav/jstockmart/client/BackgroundAnimation.java
new file mode 100644
index 0000000..32c8be3
--- /dev/null
+++ b/src/com/ayushmaanbhav/jstockmart/client/BackgroundAnimation.java
@@ -0,0 +1,381 @@
+package com.ayushmaanbhav.jstockmart.client;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.HeadlessException;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.LayoutManager2;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+@SuppressWarnings("serial")
+public class BackgroundAnimation extends JPanel {
+
+	private CurvesPanel curves;
+
+	public BackgroundAnimation() throws HeadlessException {
+		// super("Stack Layout");
+
+		buildContentPane();
+		// buildDebugControls();
+
+		startAnimation();
+
+		// setSize(640, 400);
+		// setLocationRelativeTo(null);
+
+		// setDefaultCloseOperation(EXIT_ON_CLOSE);
+	}
+
+	Timer timer;
+	public void startAnimation() {
+		timer = new Timer(50, new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				curves.animate();
+				curves.repaint();
+			}
+		});
+		timer.start();
+	}
+
+	public void stopAnimation() {
+		timer.stop();
+	}
+
+	private void buildContentPane() {
+		// JPanel pane = new JPanel();
+		setDoubleBuffered(true);
+		setOpaque(false);
+		setLayout(new StackLayout());
+
+		GradientPanel gradient = new GradientPanel();
+		// chooser = new AvatarChooser();
+		curves = new CurvesPanel();
+
+		add(gradient, StackLayout.TOP);
+		// add(chooser, StackLayout.TOP);
+		add(curves, StackLayout.TOP);
+
+	}
+
+	public static void main(String[] args) {
+		try {
+			UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
+		} catch (ClassNotFoundException ex) {
+			ex.printStackTrace();
+		} catch (IllegalAccessException ex) {
+			ex.printStackTrace();
+		} catch (InstantiationException ex) {
+			ex.printStackTrace();
+		} catch (UnsupportedLookAndFeelException ex) {
+			ex.printStackTrace();
+		}
+
+		SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				BackgroundAnimation tester = new BackgroundAnimation();
+				tester.setVisible(true);
+			}
+		});
+	}
+}
+
+@SuppressWarnings("serial")
+class CurvesPanel extends JPanel {
+	protected RenderingHints hints;
+
+	protected int counter = 0;
+
+	protected Color start = new Color(255, 255, 255, 200);
+
+	protected Color end = new Color(255, 255, 255, 0);
+
+	public CurvesPanel() {
+		this(new BorderLayout());
+	}
+
+	public CurvesPanel(LayoutManager manager) {
+		super(manager);
+		hints = createRenderingHints();
+	}
+
+	protected RenderingHints createRenderingHints() {
+		RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+		hints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+		hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+		return hints;
+	}
+
+	public void animate() {
+		counter++;
+	}
+
+	@Override
+	public boolean isOpaque() {
+		return false;
+	}
+
+	@Override
+	protected void paintComponent(Graphics g) {
+		Graphics2D g2 = (Graphics2D) g;
+
+		RenderingHints oldHints = g2.getRenderingHints();
+		g2.setRenderingHints(hints);
+
+		float width = getWidth();
+		float height = getHeight();
+
+		g2.translate(0, -30);
+
+		drawCurve(g2, 20.0f, -10.0f, 20.0f, -10.0f, width / 2.0f - 40.0f, 10.0f, 0.0f, -5.0f, width / 2.0f + 40, 1.0f, 0.0f, 5.0f, 50.0f, 5.0f, false);
+
+		g2.translate(0, 30);
+		g2.translate(0, height - 60);
+
+		drawCurve(g2, 30.0f, -15.0f, 50.0f, 15.0f, width / 2.0f - 40.0f, 1.0f, 15.0f, -25.0f, width / 2.0f, 1.0f / 2.0f, 0.0f, 25.0f, 15.0f, 9.0f, false);
+
+		g2.translate(0, -height + 60);
+
+		drawCurve(g2, height - 35.0f, -5.0f, height - 50.0f, 10.0f, width / 2.0f - 40.0f, 1.0f, height - 35.0f, -25.0f, width / 2.0f, 1.0f / 2.0f, height - 20.0f, 25.0f, 25.0f, 7.0f, true);
+
+		g2.setRenderingHints(oldHints);
+	}
+
+	protected void drawCurve(Graphics2D g2, float y1, float y1_offset, float y2, float y2_offset, float cx1, float cx1_offset, float cy1, float cy1_offset, float cx2, float cx2_offset, float cy2, float cy2_offset, float thickness, float speed, boolean invert) {
+		float width = getWidth();
+
+		float offset = (float) Math.sin(counter / (speed * Math.PI));
+
+		float start_x = 0.0f;
+		float start_y = offset * y1_offset + y1;
+		float end_x = width;
+		float end_y = offset * y2_offset + y2;
+
+		float ctrl1_x = offset * cx1_offset + cx1;
+		float ctrl1_y = offset * cy1_offset + cy1;
+		float ctrl2_x = offset * cx2_offset + cx2;
+		float ctrl2_y = offset * cy2_offset + cy2;
+
+		GeneralPath thickCurve = new GeneralPath();
+		thickCurve.moveTo(start_x, start_y);
+		thickCurve.curveTo(ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, end_x, end_y);
+		thickCurve.lineTo(end_x, end_y + thickness);
+		thickCurve.curveTo(ctrl2_x, ctrl2_y + thickness, ctrl1_x, ctrl1_y + thickness, start_x, start_y + thickness);
+		thickCurve.lineTo(start_x, start_y);
+
+		Rectangle bounds = thickCurve.getBounds();
+		if (!bounds.intersects(g2.getClipBounds())) {
+			return;
+		}
+
+		GradientPaint painter = new GradientPaint(0, bounds.y, invert ? end : start, 0, bounds.y + bounds.height, invert ? start : end);
+
+		Paint oldPainter = g2.getPaint();
+		g2.setPaint(painter);
+		g2.fill(thickCurve);
+
+		g2.setPaint(oldPainter);
+	}
+}
+
+@SuppressWarnings("serial")
+class GradientPanel extends JPanel {
+	protected BufferedImage gradientImage;
+
+	protected Color gradientStart = Color.GRAY.brighter();// new Color(204, 249,
+															// 124);
+
+	protected Color gradientEnd = Color.GRAY;// new Color(174, 222, 94);
+
+	public GradientPanel() {
+		this(new BorderLayout());
+	}
+
+	public GradientPanel(LayoutManager layout) {
+		super(layout);
+		addComponentListener(new GradientCacheManager());
+	}
+
+	@Override
+	protected void paintComponent(Graphics g) {
+		createImageCache();
+
+		if (gradientImage != null) {
+			g.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), null);
+		}
+	}
+
+	protected void createImageCache() {
+		int width = 2;
+		int height = getHeight();
+
+		if (width == 0 || height == 0) {
+			return;
+		}
+
+		if (gradientImage == null || width != gradientImage.getWidth() || height != gradientImage.getHeight()) {
+
+			gradientImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+
+			Graphics2D g2 = gradientImage.createGraphics();
+			GradientPaint painter = new GradientPaint(0, 0, gradientEnd, 0, height / 2, gradientStart);
+			g2.setPaint(painter);
+
+			Rectangle2D rect = new Rectangle2D.Double(0, 0, width, height / 2.0);
+			g2.fill(rect);
+
+			painter = new GradientPaint(0, height / 2, gradientStart, 0, height, gradientEnd);
+			g2.setPaint(painter);
+
+			rect = new Rectangle2D.Double(0, (height / 2.0) - 1.0, width, height);
+			g2.fill(rect);
+
+			g2.dispose();
+		}
+	}
+
+	private void disposeImageCache() {
+		synchronized (gradientImage) {
+			gradientImage.flush();
+			gradientImage = null;
+		}
+	}
+
+	private class GradientCacheManager implements ComponentListener {
+		public void componentResized(ComponentEvent e) {
+		}
+
+		public void componentMoved(ComponentEvent e) {
+		}
+
+		public void componentShown(ComponentEvent e) {
+		}
+
+		public void componentHidden(ComponentEvent e) {
+			disposeImageCache();
+		}
+	}
+}
+
+class StackLayout implements LayoutManager2 {
+	public static final String BOTTOM = "bottom";
+
+	public static final String TOP = "top";
+
+	private List components = new LinkedList();
+
+	public void addLayoutComponent(Component comp, Object constraints) {
+		synchronized (comp.getTreeLock()) {
+			if (BOTTOM.equals(constraints)) {
+				components.add(0, comp);
+			} else if (TOP.equals(constraints)) {
+				components.add(comp);
+			} else {
+				components.add(comp);
+			}
+		}
+	}
+
+	public void addLayoutComponent(String name, Component comp) {
+		addLayoutComponent(comp, TOP);
+	}
+
+	public void removeLayoutComponent(Component comp) {
+		synchronized (comp.getTreeLock()) {
+			components.remove(comp);
+		}
+	}
+
+	public float getLayoutAlignmentX(Container target) {
+		return 0.5f;
+	}
+
+	public float getLayoutAlignmentY(Container target) {
+		return 0.5f;
+	}
+
+	public void invalidateLayout(Container target) {
+	}
+
+	public Dimension preferredLayoutSize(Container parent) {
+		synchronized (parent.getTreeLock()) {
+			int width = 0;
+			int height = 0;
+
+			for (Component comp : components) {
+				Dimension size = comp.getPreferredSize();
+				width = Math.max(size.width, width);
+				height = Math.max(size.height, height);
+			}
+
+			Insets insets = parent.getInsets();
+			width += insets.left + insets.right;
+			height += insets.top + insets.bottom;
+
+			return new Dimension(width, height);
+		}
+	}
+
+	public Dimension minimumLayoutSize(Container parent) {
+		synchronized (parent.getTreeLock()) {
+			int width = 0;
+			int height = 0;
+
+			for (Component comp : components) {
+				Dimension size = comp.getMinimumSize();
+				width = Math.max(size.width, width);
+				height = Math.max(size.height, height);
+			}
+
+			Insets insets = parent.getInsets();
+			width += insets.left + insets.right;
+			height += insets.top + insets.bottom;
+
+			return new Dimension(width, height);
+		}
+	}
+
+	public Dimension maximumLayoutSize(Container target) {
+		return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+	}
+
+	public void layoutContainer(Container parent) {
+		synchronized (parent.getTreeLock()) {
+			int width = parent.getWidth();
+			int height = parent.getHeight();
+
+			Rectangle bounds = new Rectangle(0, 0, width, height);
+
+			int componentsCount = components.size();
+
+			for (int i = 0; i < componentsCount; i++) {
+				Component comp = components.get(i);
+				comp.setBounds(bounds);
+				parent.setComponentZOrder(comp, componentsCount - i - 1);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/com/ayushmaanbhav/jstockmart/client/BroadcastClient.java b/src/com/ayushmaanbhav/jstockmart/client/BroadcastClient.java
new file mode 100644
index 0000000..24b63b0
--- /dev/null
+++ b/src/com/ayushmaanbhav/jstockmart/client/BroadcastClient.java
@@ -0,0 +1,94 @@
+package com.ayushmaanbhav.jstockmart.client;
+
+import java.util.*;
+import javax.swing.*;
+import java.text.*;
+public class BroadcastClient extends Thread {
+	StringBuffer sb;
+	DecimalFormat twoDForm;
+	int hj = 0;
+	ShareValuesChangeListener svcl;
+	int id;
+	
+	public BroadcastClient(StringBuffer s) {
+		id = 0;
+		sb = s;
+		svcl = null;
+		Companies.comp = new ArrayList();
+		twoDForm = new DecimalFormat("#.##");
+	}
+	
+	public void run(String poo) {
+		try {
+			StringBuffer fin = new StringBuffer();
+			final String rec[] = poo.split("=");
+			final String ids[] = rec[0].split("#");
+			int recid = Integer.parseInt(ids[0]);
+			if(recid <= id) {
+				return;
+			} else {
+				id = recid;
+			}
+			final String mtr[] = ids[1].split(";");
+			final String str[] = rec[1].split(";");
+			for (int i = 0; i < str.length; i++) {
+				String str2[] = str[i].split(":");
+				
+				int company_id = Integer.parseInt(new String(str2[0]));
+				String company_name = new String(str2[1]);
+				double mktvalue = Double.parseDouble(str2[2]);
+				double initial_value = Double.parseDouble(str2[3]);
+				double highest_value = Double.parseDouble(str2[4]);
+				double lowest_value = Double.parseDouble(str2[5]);
+				double price_precision = Double.parseDouble(str2[6]);
+				
+				Companies.updateValues(company_id, company_name, mktvalue, initial_value, highest_value, lowest_value, price_precision);
+				
+				fin.append(str2[1]);
+				fin.append(" : ");
+				fin.append(twoDForm.format(mktvalue));
+				if (mktvalue > initial_value)
+					fin.append("\u25b2"); // This
+											// is some text!
+				else if (mktvalue < initial_value)
+					fin.append("\u25bc");
+				double c = mktvalue - initial_value;
+				if (c > 0.0)
+					fin.append(twoDForm.format(c));
+				else if (c < 0.0)
+					fin.append(twoDForm.format(-c));
+				fin.append("        ");
+			}
+			sb.delete(0, sb.length());
+			sb.append(fin.toString());
+			SwingUtilities.invokeLater(new Runnable() {
+				public void run() {
+					try {
+						if (Main.imglabel2 != null)
+							Main.imglabel2.setText("
Sensex: " + mtr[1] + "
Time Left: " + mtr[0] + "
"); + } catch (Exception bb) { + bb.printStackTrace(); + } + try { + if (hj == 0) { + GraphPanel.mainPanel.setScores(); + Main.jtp.setEnabledAt(3, true); + HistogramPanel.mainPanel.updateComboBox(Companies.comp); + Main.jtp.setEnabledAt(4, true); + hj = 1; + } else { + GraphPanel.mainPanel.repaint(); + } + } catch (Exception e) { + } + try { + svcl.valuesChanged(); + } catch (Exception e) { + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/client/Cashier.java b/src/com/ayushmaanbhav/jstockmart/client/Cashier.java new file mode 100644 index 0000000..2dc8829 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Cashier.java @@ -0,0 +1,446 @@ +package com.ayushmaanbhav.jstockmart.client; + +import javax.swing.*; +import java.awt.*; +import javax.swing.border.*; +import java.awt.event.*; +import java.text.*; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.sun.awt.AWTUtilities; + +@SuppressWarnings("restriction") +class Cashier { + JDialog jd; + float ii = 0; + DecimalFormat twoDForm = new DecimalFormat("#.##"); + Timer alphaChanger = new Timer(50, new ActionListener() { + private float incrementer = .10f; + @Override + public void actionPerformed(ActionEvent e) { + ii = ii + incrementer; + if (ii > ((float) 0.9)) { + alphaChanger.stop(); + jd.setVisible(false); + ii = 0; + } + try { + AWTUtilities.setWindowOpacity(jd, Float.valueOf((float) (1 - ii))); + } catch (Exception m) { + } + } + }); + Client client; + User user; + JLabel cash, jlab, tot; + double total = 0; + Company comp; + JTextField jtf; + SpinnerNumberModel spinnermodel; + JSpinner.NumberEditor jspne; + JSpinner jsp; + Shares pp; + String cmp; + JRadioButton b2, b1; + JRadioButton b3, b4; + static boolean closee = false; + + Timer timer = new Timer(250, new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (closee) { + timer.stop(); + jd.setVisible(false); + closee = false; + } + comp = Companies.getCompanyWithName(cmp); + cash.setText("Cash Avail : " + twoDForm.format(user.getCurrentMoney())); + jlab.setText("Company : " + cmp + " , C.M.P. : " + twoDForm.format(comp.mktvalue)); + + if (!b4.isSelected()) { + spinnermodel = new SpinnerNumberModel((double) comp.mktvalue, 1.0, comp.mktvalue * 100, (double) comp.price_precision); + jsp.setModel(spinnermodel); + jsp.setEditor(jspne); + } + + try { + int ent = Integer.parseInt(jtf.getText()); + double price = Double.parseDouble(twoDForm.format(Double.parseDouble(jsp.getValue().toString()))); + if (b3.isSelected()) { + if (b1.isSelected()) { + total = Double.valueOf(twoDForm.format(ent * comp.mktvalue * 1.02)); + if (total > user.getCurrentMoney()) + tot.setForeground(Color.red); + else + tot.setForeground(Color.black); + } else if (b2.isSelected()) { + total = Double.valueOf(twoDForm.format(ent * comp.mktvalue)); + if (ent > pp.qty) + tot.setForeground(Color.red); + else + tot.setForeground(Color.black); + } + } else if (b4.isSelected()) { + if (b1.isSelected()) { + total = Double.valueOf(twoDForm.format(ent * price * 1.02)); + if (total > user.getCurrentMoney()) + tot.setForeground(Color.red); + else + tot.setForeground(Color.black); + } else if (b2.isSelected()) { + total = Double.valueOf(twoDForm.format(ent * price)); + if (ent > pp.qty) + tot.setForeground(Color.red); + else + tot.setForeground(Color.black); + } + } + } catch (Exception v) { + v.printStackTrace(); + total = 0; + tot.setForeground(Color.red); + } + tot.setText("Expected Cash Req./Rec.*: " + twoDForm.format(total)); + } + }); + + public Cashier(Client c, User u) { + client = c; + user = u; + } + + @SuppressWarnings("serial") + void showDialog(String c, final int bs, final Shares shr) { + cmp = c; + pp = shr; + jd = new JDialog(); + jd.setUndecorated(true); + comp = Companies.getCompanyWithName(cmp); + JPanel pan = new JPanel() { + @Override + protected void paintComponent(Graphics grphcs) { + Graphics2D g2d = (Graphics2D) grphcs; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, getBackground().brighter(), 0, getHeight(), getBackground().darker()); + g2d.setPaint(gp); + g2d.fillRect(0, 0, getWidth(), getHeight()); + super.paintComponent(grphcs); + } + }; + pan.setLayout(new GridBagLayout()); + jlab = new JLabel("Company : " + cmp + " , C.M.P. : " + twoDForm.format(comp.mktvalue)); + JLabel op = new JLabel("Operation : "); + tot = new JLabel("Expected Cash Req./Rec.:" + twoDForm.format(total)); + + b1 = new JRadioButton("Buy"); + b2 = new JRadioButton("Sell"); + if (bs == 0) + b1.setSelected(true); + else + b2.setSelected(true); + ButtonGroup grp = new ButtonGroup(); + grp.add(b1); + grp.add(b2); + + final JLabel cost = new JLabel("Limit Price : "); + if (b1.isSelected()) { + cost.setText("Upper Price Limit : "); + } else { + cost.setText("Lower Price Limit : "); + } + + spinnermodel = new SpinnerNumberModel((double) comp.mktvalue, 1.0, comp.mktvalue * 100, (double) comp.price_precision); + jsp = new JSpinner(spinnermodel); + jspne = new JSpinner.NumberEditor(jsp, "#.##"); + jspne.getTextField().setEditable(false); + jsp.setEditor(jspne); + jsp.setEnabled(false); + + ActionListener grplis = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (b1.isSelected()) { + cost.setText("Upper Price Limit : "); + } else { + cost.setText("Lower Price Limit : "); + } + } + }; + b1.addActionListener(grplis); + b2.addActionListener(grplis); + + b3 = new JRadioButton("Market Order"); + b4 = new JRadioButton("Limit Order"); + b3.setSelected(true); + ButtonGroup grp2 = new ButtonGroup(); + grp2.add(b3); + grp2.add(b4); + ActionListener grp2lis = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (b3.isSelected()) { + jsp.setEnabled(false); + } else { + jsp.setEnabled(true); + } + } + }; + b3.addActionListener(grp2lis); + b4.addActionListener(grp2lis); + + final JLabel qty = new JLabel("Quantity : "); + jtf = new JTextField(10); + jtf.setText("0"); + + cash = new JLabel("Cash Avail : " + twoDForm.format(user.getCurrentMoney())); + final JButton jb1 = new JButton("Place Order"); + final JButton jb2 = new JButton("Cancel"); + jb2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + timer.stop(); + jd.setVisible(false); + } + }); + jb1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int noofs = 0; + // System.out.println(jsp.getValue().toString()); + final double price = Double.parseDouble(twoDForm.format(Double.parseDouble(jsp.getValue().toString()))); + try { + noofs = Integer.parseInt(jtf.getText()); + } catch (Exception ee) { + jtf.setForeground(Color.red); + qty.setForeground(Color.red); + return; + } + if (noofs <= 0) { + jtf.setForeground(Color.red); + qty.setForeground(Color.red); + return; + } + if (b2.isSelected() && noofs > shr.qty) { + jtf.setForeground(Color.red); + qty.setForeground(Color.red); + return; + } + if (b1.isSelected() && noofs * comp.mktvalue > user.getCurrentMoney()) { + jtf.setForeground(Color.red); + qty.setForeground(Color.red); + return; + } + jtf.setForeground(Color.black); + qty.setForeground(Color.black); + tot.setForeground(Color.black); + jtf.setEnabled(false); + jb1.setEnabled(false); + jb2.setEnabled(false); + b1.setEnabled(false); + b2.setEnabled(false); + b3.setEnabled(false); + b4.setEnabled(false); + jsp.setEnabled(false); + final int kk = noofs; + new Thread() { + public void run() { + String cmd; + if (b1.isSelected()) + cmd = Commands.BUY; + else + cmd = Commands.SELL; + if (b3.isSelected()) + cmd += Commands.MARKET_ORDER; + else + cmd += Commands.LIMIT_ORDER; + + try { + client.placeOrder(user, cmd, comp, price, kk, shr.id); + } catch (Exception ff) { + client.placeOrder(user, cmd, comp, price, kk, -1); + } + timer.stop(); + alphaChanger.start(); + } + }.start(); + } + }); + JLabel cc1 = new JLabel("-> *Transaction charges : 2% of the total cash transactioned."); + JLabel cc2 = new JLabel("-> Red Text indicates warning that your order might fail."); + JLabel cc3 = new JLabel("-> Order can be placed either as a market order or limit order."); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(jlab, gbc); + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(op, gbc); + gbc.gridx = 1; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(b1, gbc); + gbc.gridx = 2; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(b2, gbc); + gbc.gridx = 1; + gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(b3, gbc); + gbc.gridx = 2; + gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(b4, gbc); + gbc.gridx = 0; + gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(qty, gbc); + gbc.gridx = 1; + gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 2; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(jtf, gbc); + gbc.gridx = 0; + gbc.gridy = 4; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(cost, gbc); + gbc.gridx = 1; + gbc.gridy = 4; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 2; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(jsp, gbc); + gbc.gridx = 0; + gbc.gridy = 5; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(tot, gbc); + gbc.gridx = 0; + gbc.gridy = 6; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(cash, gbc); + gbc.gridx = 0; + gbc.gridy = 7; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(jb1, gbc); + gbc.gridx = 1; + gbc.gridy = 7; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(jb2, gbc); + gbc.gridx = 0; + gbc.gridy = 8; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(cc1, gbc); + gbc.gridx = 0; + gbc.gridy = 9; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(cc2, gbc); + gbc.gridx = 0; + gbc.gridy = 10; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 3; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.LINE_START; + // gbc.insets=new Insets(0,0,100,0); + pan.add(cc3, gbc); + pan.setOpaque(false); + pan.setBorder(new CompoundBorder(BorderFactory.createLineBorder(Color.black, 1), BorderFactory.createEmptyBorder(5, 5, 5, 5))); + jd.setContentPane(pan); + timer.start(); + jd.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); + jd.pack(); + jd.setLocationRelativeTo(null); + jd.setVisible(true); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/ChatClient.java b/src/com/ayushmaanbhav/jstockmart/client/ChatClient.java new file mode 100644 index 0000000..d3adbe7 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/ChatClient.java @@ -0,0 +1,42 @@ +package com.ayushmaanbhav.jstockmart.client; + +import javax.swing.*; +public class ChatClient extends Thread { + JTextArea jta; + public ChatClient(JTextArea ja) { + jta = ja; + } + public void run(String hh) { + try { + // StringBuffer fin=new StringBuffer(" "); + final String str = hh.trim(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + String s[] = str.split(";"); + if (s.length < 2) + return; + else { + if (!s[1].equals("-1")) + jta.setText(jta.getText() + "\n" + s[1]); + if (!s[0].equals("-1")) { + String ff[] = s[0].split(":"); + String jj = ""; + for (int i = 0; i < ff.length; i++) { + jj += ff[i] + " "; + } + NewsPane.temp.delete(0, NewsPane.temp.length()); + NewsPane.temp.append(jj); + while (NewsPane.temp.length() <= 200) { + NewsPane.temp.append(" "); + } + } else { + NewsPane.temp.delete(0, NewsPane.temp.length()); + } + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/client/ChatWindow.java b/src/com/ayushmaanbhav/jstockmart/client/ChatWindow.java new file mode 100644 index 0000000..0ce5c90 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/ChatWindow.java @@ -0,0 +1,79 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import com.ayushmaanbhav.jstockmart.user.*; + +import java.awt.*; +import java.awt.event.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +@SuppressWarnings("serial") +class ChatWindow extends JPanel { + JTextField jtf; + JTextArea jta; + JLabel jlab; + Client cc; + User user; + String remain; + BlockingQueue queue; + + public ChatWindow(final User u, Client client) { + user = u; + cc = client; + setLayout(new BorderLayout()); + jlab = new JLabel("<> (" + u.getChat() + " characters remainimg)"); + jtf = new JTextField(); + jta = new JTextArea(); + jta.setFont(new Font("Calibri", Font.PLAIN, 13)); + jta.setLineWrap(true); + jta.setEditable(false); + jta.setForeground(Color.green.darker()); + // jtf.setEnabled(false); + jtf.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String s = jtf.getText().trim(); + if (!s.equals("")) { + jtf.setText(""); + queue.offer(s); + } + } + }); + queue = new LinkedBlockingQueue(); + new Thread() { + public void run() { + while (true) { + try { + String message = queue.take(); + remain = sendString(message); + u.setChat(Integer.parseInt(remain)); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + jlab.setText("<> (" + u.getChat() + " characters remainimg)"); + } + }); + } catch (Exception mm) { + mm.printStackTrace(); + } + if (u.getChat() <= 0) + JOptionPane.showMessageDialog(null, "Sorry, You have finished your chat limit.", "Error:", JOptionPane.PLAIN_MESSAGE); + } + } + }.start(); + JScrollPane jsp = new JScrollPane(jta, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + add(jlab, BorderLayout.NORTH); + add(jsp, BorderLayout.CENTER); + add(jtf, BorderLayout.SOUTH); + try { + jta.setText(cc.getChatHistory(user.getName(), user.getPassword())); + } catch (Exception mmm) { + } + ChatClient cser = new ChatClient(jta); + // cser.start(); + client.cc = cser; + } + + synchronized String sendString(String s) { + return cc.sendChat(s, user.getName(), user.getPassword()); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/Client.java b/src/com/ayushmaanbhav/jstockmart/client/Client.java new file mode 100644 index 0000000..eda4c29 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Client.java @@ -0,0 +1,244 @@ +package com.ayushmaanbhav.jstockmart.client; +import java.io.*; +import java.net.*; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +public class Client { + boolean connected = false; + Socket socket = null; + PrintWriter out = null; + // BufferedReader in = null; + ObjectInputStream in; + String domain; + static boolean testing = true; + volatile int commID = 0; + Client ccl; + int usrD; + Main m; + TestMain maain; + BroadcastClient bc = null; + RankingClient rc = null; + ChatClient cc = null; + Receiver rec; + + public Client(Main mm, TestMain maaii) { + ccl = this; + m = mm; + maain = maaii; + commID = 0; + } + + public void connect(String user, String pass) { + if (!connected) { + try { + socket = new Socket(domain, 4446); + out = new PrintWriter(socket.getOutputStream(), true); + in = new ObjectInputStream(socket.getInputStream()); + } catch (java.net.UnknownHostException e) { + System.err.println("Don't know about host"); + return; + } catch (IOException e) { + System.err.println("Couldn't get I/O for the connection to"); + return; + } + this.connected = true; + rec = new Receiver(ccl); + rec.start(); + } + } + + String login(String domain, String user, String pass) { + int cmdID = commID++; + this.domain = domain; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.LOG_IN + ":" + user + ":" + pass); + out.println(cmdID + ";" + Commands.LOG_IN + ":" + user + ":" + pass); + out.flush(); + String rep = (String) receiveReply(cmdID); + return rep.split(":")[0]; + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + String register(String domain, String regno, String user, String pass) { + int cmdID = commID++; + this.domain = domain; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.REGISTER + ":" + regno + ":" + user + ":" + pass); + out.println(cmdID + ";" + Commands.REGISTER + ":" + regno + ":" + user + ":" + pass); + out.flush(); + String rep = (String) receiveReply(cmdID); + disconnect(); + return rep.split(":")[0]; + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + public void disconnect() { + int cmdID = commID++; + this.connected = false; + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.LOG_OUT); + out.println(cmdID + ";" + Commands.LOG_OUT); + out.flush(); + in.close(); + out.close(); + socket.close(); + } catch (IOException ex) { + System.err.println("Server stop failed."); + } + } + + User getUserDetails(String user, String pass) { + int cmdID = commID++; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.GET_USER_DETAILS); + usrD = 1; + out.println(cmdID + ";" + Commands.GET_USER_DETAILS); + out.flush(); + User vv = (User) receiveReply(cmdID); + usrD = 0; + return vv; + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + String sendChat(String s, String user, String pass) { + int cmdID = commID++; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.SEND_CHAT_MESSAGE + ":" + s.trim()); + out.println(cmdID + ";" + Commands.SEND_CHAT_MESSAGE + ":" + s.trim()); + out.flush(); + return (String) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + String getChatHistory(String user, String pass) { + int cmdID = commID++; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.GET_CHAT_HISTORY); + out.println(cmdID + ";" + Commands.GET_CHAT_HISTORY); + out.flush(); + return (String) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + void placeOrder(final User user, String cmd, Company comp, double cost_limit, int qty_limit, int id) { + int cmdID = commID++; + connect(user.getName(), user.getPassword()); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + cmd + ":" + comp.name + ":" + Integer.toString(qty_limit) + ":" + Double.toString(cost_limit) + ":" + id); + out.println(cmdID + ";" + cmd + ":" + comp.name + ":" + Integer.toString(qty_limit) + ":" + Double.toString(cost_limit) + ":" + id); + out.flush(); + Shares pen = (Shares) receiveReply(cmdID); + user.getPendingShares().add(pen); + user.dataChanged(); + } catch (Exception r) { + r.printStackTrace(); + } + } + + String cancelShares(String user, String pass, int id, int sellid) { + int cmdID = commID++; + connect(user, pass); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.CANCEL_ORDER + ":" + id + ":" + sellid); + out.println(cmdID + ";" + Commands.CANCEL_ORDER + ":" + id + ":" + sellid); + out.flush(); + return (String) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + java.util.List getHistory(String comp, int count) { + int cmdID = commID++; + // connect(user.getName(),user.getPassword()); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.GET_COMPANY_HISTORY + ":" + comp + ":" + Integer.toString(count)); + out.println(cmdID + ";" + Commands.GET_COMPANY_HISTORY + ":" + comp + ":" + Integer.toString(count)); + out.flush(); + return (java.util.List) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + TrippleArrayList getCompanyStats(String comp) { + int cmdID = commID++; + // connect(user.getName(),user.getPassword()); + try { + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.GET_COMPANY_STATS + ":" + comp); + out.println(cmdID + ";" + Commands.GET_COMPANY_STATS + ":" + comp); + out.flush(); + return (TrippleArrayList) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + String getSendCompanyStatsPeriodically(String comp) { + int cmdID = commID++; + // connect(user.getName(),user.getPassword()); + try { + if (comp == null) + comp = "-1"; + if (testing) + System.out.println("Command: " + cmdID + ";" + Commands.SEND_PERIODIC_STATS + ":" + comp); + out.println(cmdID + ";" + Commands.SEND_PERIODIC_STATS + ":" + comp); + out.flush(); + return (String) receiveReply(cmdID); + } catch (Exception r) { + r.printStackTrace(); + } + return null; + } + + Object receiveReply(int cmdID) { + Object obj = null; + while (obj == null) { + try { + obj = rec.rev.take(cmdID); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (testing) + System.out.println("Got: " + cmdID + " : " + obj.toString() + " : " + Thread.currentThread()); + return obj; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/Companies.java b/src/com/ayushmaanbhav/jstockmart/client/Companies.java new file mode 100644 index 0000000..3516620 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Companies.java @@ -0,0 +1,57 @@ +package com.ayushmaanbhav.jstockmart.client; + +import java.util.*; +class Companies { + static List comp; + static Double sensex; + + static Company getCompanyWithName(String name) { + for (int i = 0; i < comp.size(); i++) { + if (comp.get(i).name.equalsIgnoreCase(name)) + return comp.get(i); + } + return null; + } + + static Company getCompanyWithId(int id) { + for (int i = 0; i < comp.size(); i++) { + if (comp.get(i).id == id) + return comp.get(i); + } + return null; + } + + static void updateValues(int id, String name, double m, double i, double h, double l, double p_precision) { + try { + getCompanyWithId(id).updateData(m, h, l, p_precision); + } catch (Exception e) { + comp.add(new Company(id, name, m, i, h, l, p_precision)); + } + } + + static void updateValues(int id, double m, double p_precision) throws Exception { + try { + getCompanyWithId(id).updateData(m, p_precision); + } catch (Exception e) { + throw new Exception("company does not exist"); + } + } + + static void updateValues(int id, double m) throws Exception { + try { + getCompanyWithId(id).updateData(m); + } catch (Exception e) { + throw new Exception("company does not exist"); + } + } + + static void removeDuplicates() { + for (int i = 0; i < comp.size(); i++) { + for (int j = 0; j < comp.size(); j++) { + if (comp.get(i).id == comp.get(j).id) { + comp.remove(j); + } + } + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/Company.java b/src/com/ayushmaanbhav/jstockmart/client/Company.java new file mode 100644 index 0000000..b3e16df --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Company.java @@ -0,0 +1,53 @@ +package com.ayushmaanbhav.jstockmart.client; +import java.util.*; + +class Company { + String name; + int id, yy; + Double inivalue, mktvalue, low, high, price_precision; + List sharevalue; + + public Company(int ii, String n, double m, double i, double hi, double lo, double p_precision) { + name = new String(n); + sharevalue = new ArrayList(); + mktvalue = m; + sharevalue.add(m); + inivalue = i; + low = lo; + high = hi; + id = ii; + price_precision = p_precision; + yy = 0; + } + + public void updateData(double m, double hi, double lo, double p_precision) { + mktvalue = m; + price_precision = p_precision; + try { + // if (m != sharevalue.get(sharevalue.size() - 1)) + sharevalue.add(m); + } catch (Exception ml) { + } + low = lo; + high = hi; + } + + public void updateData(double m, double p_precision) { + mktvalue = m; + price_precision = p_precision; + try { + // if (m != sharevalue.get(sharevalue.size() - 1)) + sharevalue.add(m); + } catch (Exception ml) { + } + } + + public void updateData(double m) { + mktvalue = m; + try { + // if (m != sharevalue.get(sharevalue.size() - 1)) + sharevalue.add(m); + } catch (Exception ml) { + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/GraphPanel.java b/src/com/ayushmaanbhav/jstockmart/client/GraphPanel.java new file mode 100644 index 0000000..9b80d0a --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/GraphPanel.java @@ -0,0 +1,222 @@ +package com.ayushmaanbhav.jstockmart.client; + +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; + +@SuppressWarnings("serial") +public class GraphPanel extends JPanel { + + // private int width = 800; + // private int heigth = 600; + private int padding = 25; + private int labelPadding = 25; + private Color lineColor = new Color(44, 102, 230, 180); + private Color pointColor = new Color(100, 100, 100, 180); + private Color gridColor = new Color(200, 200, 200, 200); + private static final Stroke GRAPH_STROKE = new BasicStroke(2f); + private int pointWidth = 4; + private int numberYDivisions = 10; + private static List scores; + + public GraphPanel() { + } + + @Override + protected void paintComponent(Graphics g) { + for (int i = 0; i < Companies.comp.size(); i++) { + if (Companies.comp.get(i).name.equals((String) comp.getSelectedItem())) { + scores = Companies.comp.get(i).sharevalue; + break; + } + } + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1); + double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore()); + + List graphPoints = new ArrayList<>(); + for (int i = 0; i < scores.size(); i++) { + int x1, y1; + x1 = (int) (i * xScale + padding + labelPadding); + y1 = (int) ((getMaxScore() - scores.get(i)) * yScale + padding); + graphPoints.add(new Point(x1, y1)); + } + + // draw white background + g2.setColor(Color.WHITE); + g2.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding - labelPadding); + g2.setColor(Color.BLACK); + + // create hatch marks and grid lines for y axis. + for (int i = 0; i < numberYDivisions + 1; i++) { + int x0 = padding + labelPadding; + int x1 = pointWidth + padding + labelPadding; + int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding); + int y1 = y0; + if (scores.size() > 0) { + g2.setColor(gridColor); + g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1); + g2.setColor(Color.BLACK); + String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + ""; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(yLabel); + g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3); + } + g2.drawLine(x0, y0, x1, y1); + } + + // and for x axis + for (int i = 0; i < scores.size(); i++) { + if (scores.size() > 1) { + int x0, x1, y0, y1; + x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding; + x1 = x0; + y0 = getHeight() - padding - labelPadding; + y1 = y0 - pointWidth; + if ((i % ((int) (((scores.size()) / 20.0)) + 1)) == 0) { + g2.setColor(gridColor); + g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding); + g2.setColor(Color.BLACK); + String xLabel = i / 2 + "m"; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(xLabel); + if (i % 2 == 0) + g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3); + } + g2.drawLine(x0, y0, x1, y1); + } + } + + // create x and y axes + g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding); + g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding); + + Stroke oldStroke = g2.getStroke(); + g2.setColor(lineColor); + g2.setStroke(GRAPH_STROKE); + for (int i = 0; i < graphPoints.size() - 1; i++) { + int x1 = graphPoints.get(i).x; + int y1 = graphPoints.get(i).y; + int x2 = graphPoints.get(i + 1).x; + int y2 = graphPoints.get(i + 1).y; + g2.drawLine(x1, y1, x2, y2); + } + + g2.setStroke(oldStroke); + g2.setColor(pointColor); + for (int i = 0; i < graphPoints.size(); i++) { + if (i >= scores.size()) + g2.setColor(Color.RED); + int x = graphPoints.get(i).x - pointWidth / 2; + int y = graphPoints.get(i).y - pointWidth / 2; + int ovalW = pointWidth; + int ovalH = pointWidth; + g2.fillOval(x, y, ovalW, ovalH); + } + } + + // @Override + // public Dimension getPreferredSize() { + // return new Dimension(width, heigth); + // } + private double getMinScore() { + double minScore = Double.MAX_VALUE; + for (Company score1 : Companies.comp) { + for (Double score2 : score1.sharevalue) { + minScore = Math.min(minScore, score2); + } + } + return 0; + } + + private double getMaxScore() { + double maxScore = Double.MIN_VALUE; + for (Company score1 : Companies.comp) { + for (Double score2 : score1.sharevalue) { + maxScore = Math.max(maxScore, score2); + } + } + return maxScore; + } + + @SuppressWarnings("unchecked") + public void setScores() { + comp.removeAllItems(); + for (int i = 0; i < Companies.comp.size(); i++) + comp.addItem(Companies.comp.get(i).name); + try { + comp.setSelectedIndex(0); + } catch (Exception o) { + } + invalidate(); + this.repaint(); + } + + public List getScores() { + return scores; + } + + @SuppressWarnings("rawtypes") + static JComboBox comp; + static JPanel frame; + static GraphPanel mainPanel; + static Client client; + static Company comm = null; + @SuppressWarnings("rawtypes") + public static JPanel main(Client cl) { + client = cl; + comp = new JComboBox(); + comp.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + comp.setEnabled(false); + for (int i = 0; i < Companies.comp.size(); i++) { + if (Companies.comp.get(i).name.equals((String) comp.getSelectedItem())) { + comm = Companies.comp.get(i); + break; + } + } + if (comm.yy == 0) { + new Thread() { + public void run() { + List ret = client.getHistory(comm.name, comm.sharevalue.size()); + if (ret != null) { + if (ret.size() > 0) + comm.sharevalue = ret; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + mainPanel.repaint(); + comp.setEnabled(true); + comp.requestFocus(); + } + }); + } + } + }.start(); + comm.yy = 1; + } else { + mainPanel.repaint(); + comp.setEnabled(true); + comp.requestFocus(); + } + } + } + }); + comp.setLightWeightPopupEnabled(false); + mainPanel = new GraphPanel(); + mainPanel.setScores(); + // mainPanel.setPreferredSize(new Dimension(800, 500)); + // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame = new JPanel(); + frame.setLayout(new BorderLayout()); + frame.add(comp, BorderLayout.NORTH); + frame.add(mainPanel, BorderLayout.CENTER); + return frame; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/HistogramPanel.java b/src/com/ayushmaanbhav/jstockmart/client/HistogramPanel.java new file mode 100644 index 0000000..c9748a3 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/HistogramPanel.java @@ -0,0 +1,111 @@ +package com.ayushmaanbhav.jstockmart.client; + +import java.awt.BorderLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Collections; +import java.util.List; + +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import com.ayushmaanbhav.jstockmart.utils.Histogram; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +public class HistogramPanel extends JPanel { + private static final long serialVersionUID = 1L; + + private TrippleArrayList scores; + + public HistogramPanel(TrippleArrayList scores) { + this.scores = scores; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + Histogram.paintHistogram(g2, getHeight(), getWidth(), scores); + } + + public void setScores(TrippleArrayList arr) { + if (arr != null) { + if (arr.size() > 0) { + Collections.sort(arr); + arr.add(0, 0, 0.0, 0); + arr.add(0, 0.0, 0); + } + } + this.scores = arr; + } + + public TrippleArrayList getScores() { + return scores; + } + + @SuppressWarnings("unchecked") + public void updateComboBox(List score) { + comp.removeItemListener(item); + comp.removeAllItems(); + for (int i = 0; i < score.size(); i++) + comp.addItem(score.get(i).name); + try { + comp.setSelectedIndex(0); + updatePanel(); + } catch (Exception o) { + } + comp.addItemListener(item); + } + + void updatePanel() { + comp.setEnabled(false); + new Thread() { + public void run() { + TrippleArrayList arr = client.getCompanyStats((String) comp.getSelectedItem()); + if (arr != null) { + setScores(arr); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + mainPanel.repaint(); + comp.setEnabled(true); + comp.requestFocus(); + } + }); + } + } + }.start(); + } + + @SuppressWarnings("rawtypes") + static JComboBox comp; + static ItemListener item; + static JPanel frame; + static HistogramPanel mainPanel; + static Client client; + @SuppressWarnings("rawtypes") + public static JPanel main(Client cl) { + client = cl; + comp = new JComboBox(); + item = new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + mainPanel.updatePanel(); + } + } + }; + comp.addItemListener(item); + comp.setLightWeightPopupEnabled(false); + mainPanel = new HistogramPanel(new TrippleArrayList()); + // mainPanel.setScores(Companies.comp); + // mainPanel.setPreferredSize(new Dimension(800, 500)); + // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame = new JPanel(); + frame.setLayout(new BorderLayout()); + frame.add(comp, BorderLayout.NORTH); + frame.add(mainPanel, BorderLayout.CENTER); + return frame; + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/client/LoginAction.java b/src/com/ayushmaanbhav/jstockmart/client/LoginAction.java new file mode 100644 index 0000000..b0abd5d --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/LoginAction.java @@ -0,0 +1,96 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import java.awt.event.*; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.ayushmaanbhav.jstockmart.utils.*; + +import java.util.regex.Pattern; + +class LoginAction implements ActionListener { + HintTextField user; + HintPasswordField pass; + String domain; + Client client; + Main main; + public LoginAction(Main mm, HintTextField u, HintPasswordField p, String d, Client c) { + user = u; + pass = p; + domain = d; + client = c; + main = mm; + } + public void actionPerformed(ActionEvent e) { + Pattern p1 = Pattern.compile("[a-z0-9_]{3,16}"); + Pattern p2 = Pattern.compile("[a-z0-9_]{6,18}"); + if (!p1.matcher(user.getText()).matches()) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Incorrect username.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + } + }); + return; + } + if (!p2.matcher(pass.getText()).matches()) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Incorrect password.\nA password should be of length {6-18} and can contain\nletters(a-z), numbers and underscores", "Error:", JOptionPane.PLAIN_MESSAGE); + pass.setText(""); + } + }); + return; + } + if (domain.equals("domain")) { + domain = JOptionPane.showInputDialog("Enter domain."); + } + if (domain == null || domain.equals("")) + return; + new Thread() { + public void run() { + String us = user.getText(); + String pa = pass.getText(); + String rep = client.login(domain, us, pa); + if (rep == null) + return; + if (rep.equals("0")) { + final User user = (User) client.getUserDetails(us, pa); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + main.proceedLogin(user); + } + }); + } else if (rep.equals("1")) { + client.disconnect(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Incorrect username.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + } + }); + return; + } else if (rep.equals("2")) { + client.disconnect(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Incorrect password.\nA password should be of length {6-18} and can contain\nletters(a-z), numbers and underscores", "Error:", JOptionPane.PLAIN_MESSAGE); + pass.setText(""); + } + }); + return; + } else if (rep.equals("11")) { + client.disconnect(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Sorry you have been banned from playing this game ! Please contact the admmin.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + pass.setText(""); + } + }); + return; + } + } + }.start(); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/Main.java b/src/com/ayushmaanbhav/jstockmart/client/Main.java new file mode 100644 index 0000000..0777d68 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Main.java @@ -0,0 +1,667 @@ +package com.ayushmaanbhav.jstockmart.client; + +import javax.swing.*; +import javax.swing.table.*; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.border.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicInternalFrameUI; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.ayushmaanbhav.jstockmart.utils.ButtonColumn; +import com.ayushmaanbhav.jstockmart.utils.HintPasswordField; +import com.ayushmaanbhav.jstockmart.utils.HintTextField; +import com.ayushmaanbhav.jstockmart.utils.LookAndFeel; + +import java.text.*; + +@SuppressWarnings("serial") +public class Main extends JFrame { + String dir, domain; + Image img, img2; + int maxWidth; + JPanel mpane; + Client client = null; + JInternalFrame internalFrame; + JPanel imgpane; + Graphics gd; + Main main = this; + HintTextField user; + HintPasswordField pass; + JPanel jp1, jp, jp2; + GridBagLayout gbll; + JLabel username; + GridBagConstraints gbc; + @SuppressWarnings("rawtypes") + JComboBox jcb; + ChatWindow chat; + RankingWindow rank; + UserDataChangedListener udcl; + DefaultTableModel dtm[]; + static JLabel mon[]; + ShareValuesChangeListener svcl; + static User ur = null; + final static String location = "com/ayushmaanbhav/jstockmart/data/"; + + public static void main(String args[]) { + Main m = new Main(); + m.init(args); + } + + int getWidth1() { + return getWidth() - 20; + } + + int getHeight1() { + return getHeight() - 20; + } + + protected void loadAppletParameters(String args[]) { + domain = args[0]; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void createGUI() { + // Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screenSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); + setSize(screenSize.width, screenSize.height); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + if (JOptionPane.showConfirmDialog(main, "Are you sure you want to quit?", "Confirm exit.", JOptionPane.OK_OPTION, 0, new ImageIcon("")) != 0) { + return; + } + stop(); + } + }); + LookAndFeel.set(); + gbll = new GridBagLayout(); + mpane = new JPanel(gbll); + mpane.setOpaque(false); + mpane.setBackground(Color.WHITE); + mpane.setBorder(new EtchedBorder()); + setGlassPane(mpane); + + jp = new JPanel(new BorderLayout()) { + @Override + protected void paintComponent(Graphics grphcs) { + Graphics2D g2d = (Graphics2D) grphcs; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, getBackground().brighter(), 0, getHeight(), getBackground().darker()); + g2d.setPaint(gp); + g2d.fillRect(0, 0, getWidth(), getHeight()); + super.paintComponent(grphcs); + } + }; + jp.setOpaque(false); + user = new HintTextField("Username"); + user.setColumns(18); + pass = new HintPasswordField("Password"); + pass.setColumns(18); + JButton login = new JButton("Login"); + login.setMnemonic(KeyEvent.VK_ENTER); + login.addActionListener(new LoginAction(main, user, pass, domain, client)); + username = new JLabel("Username"); + jcb = new JComboBox(new String[]{"Home", "Rules", "Logout"}); // help + // setting + jcb.setLightWeightPopupEnabled(false); + jcb.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int sel = jcb.getSelectedIndex(); + if (sel == 1) { + try { + String url = "http://" + domain + "/rules/index.html"; + String os = System.getProperty("os.name").toLowerCase(); + Runtime rt = Runtime.getRuntime(); + + if (os.indexOf("win") >= 0) { + + // this doesn't support showing urls in the form of + // "page.html#nameLink" + rt.exec("rundll32 url.dll,FileProtocolHandler " + url); + + } else if (os.indexOf("mac") >= 0) { + + rt.exec("open " + url); + + } else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) { + + // Do a best guess on unix until we get a platform + // independent way + // Build a list of browsers to try, in this order. + String[] browsers = {"epiphany", "firefox", "mozilla", "konqueror", "netscape", "opera", "links", "lynx"}; + + // Build a command string which looks like + // "browser1 "url" || browser2 "url" ||..." + StringBuffer cmd = new StringBuffer(); + for (int i = 0; i < browsers.length; i++) + cmd.append((i == 0 ? "" : " || ") + browsers[i] + " \"" + url + "\" "); + + rt.exec(new String[]{"sh", "-c", cmd.toString()}); + } + // main.getAppletContext().showDocument(new URL(), + // "_blank"); + } catch (Exception ee) { + ee.printStackTrace(); + } + } else if (sel == 2) { + main.stop(); + // main.getAppletContext().showDocument(main.getDocumentBase(), + // "_self"); + } + } + }); + JLabel space = new JLabel(" "); + space.setOpaque(false); + JLabel space2 = new JLabel(" "); + space2.setOpaque(false); + + jp2 = new JPanel(new FlowLayout()); + jp2.setOpaque(false); + jp2.add(username); + jp2.add(jcb); + jp2.add(space2); + + jp1 = new JPanel(new FlowLayout()); + jp1.setOpaque(false); + jp1.add(user); + jp1.add(pass); + jp1.add(login); + jp1.add(space); + + JPanel developer = new JPanel(new GridBagLayout()); + JLabel tit = new JLabel(" StockMart "); + tit.setOpaque(false); + try { + tit.setFont(titleFont); + tit.setForeground(Color.gray.darker().darker().darker()); + } catch (Exception bb) { + bb.printStackTrace(); + } + GridBagConstraints gbc1 = new GridBagConstraints(); + gbc1.gridx = 0; + gbc1.gridy = 0; + gbc1.gridwidth = 1; + gbc1.gridheight = 1; + developer.add(tit, gbc1); + JLabel subtit = new JLabel(" Developed by: Ayush Jain (ayushmaanbhav1008@gmail.com), Contribute here: https://github.com/ayushmaanbhav/stockmart"); + subtit.setOpaque(false); + try { + subtit.setFont(calibri); + subtit.setForeground(Color.black); + } catch (Exception bb) { + bb.printStackTrace(); + } + gbc1.gridx = 0; + gbc1.gridy = 1; + gbc1.gridwidth = 2; + gbc1.gridheight = 1; + developer.add(subtit, gbc1); + developer.setOpaque(false); + jp.add(developer, BorderLayout.WEST); + jp.add(jp1, BorderLayout.EAST); + jp.setBorder(new BevelBorder(BevelBorder.RAISED)); + jp.setPreferredSize(new Dimension(mpane.getWidth(), 45)); + gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = 8; + gbc.gridheight = 1; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.anchor = GridBagConstraints.PAGE_START; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + mpane.add(jp, gbc); + + HintTextField regno = new HintTextField("Registration No."); + regno.setColumns(10); + // textField.setMaximumSize( .getPreferredSize() ); + HintTextField ruser = new HintTextField("Username"); + ruser.setColumns(10); + HintPasswordField rpass = new HintPasswordField("Password"); + rpass.setColumns(10); + JButton register = new JButton("Register"); + register.addActionListener(new RegisterAction(regno, ruser, rpass, domain, client)); + + JPanel regpane = new JPanel() { + @Override + protected void paintComponent(Graphics grphcs) { + Graphics2D g2d = (Graphics2D) grphcs; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, getBackground().brighter(), 0, getHeight(), getBackground().darker()); + g2d.setPaint(gp); + g2d.fillRect(0, 0, getWidth(), getHeight()); + super.paintComponent(grphcs); + } + }; + regpane.setOpaque(false); + regpane.setLayout(new BoxLayout(regpane, BoxLayout.PAGE_AXIS)); + regpane.setBorder(new EmptyBorder(10, 20, 10, 20)); // tlbr + regpane.add(Box.createRigidArea(new Dimension(0, 5))); + regpane.add(regno); + regpane.add(Box.createRigidArea(new Dimension(0, 5))); + regpane.add(ruser); + regpane.add(Box.createRigidArea(new Dimension(0, 5))); + regpane.add(rpass); + regpane.add(Box.createRigidArea(new Dimension(0, 5))); + regpane.add(register); + regpane.add(Box.createRigidArea(new Dimension(0, 5))); + + internalFrame = new JInternalFrame("Register:", false, false, false, false); + internalFrame.setContentPane(regpane); + internalFrame.pack(); + + unmovable(internalFrame); + + imgpane = new JPanel(); + imgpane.setOpaque(false); + JLabel imglabel = new JLabel(); + imglabel.setSize((int) (.384 * (double) getWidth1()), (int) (.79 * (double) getHeight1())); + imglabel.setOpaque(false); + imglabel.setIcon(new ImageIcon(img.getScaledInstance(imglabel.getWidth(), imglabel.getHeight(), Image.SCALE_SMOOTH))); + imgpane.add(imglabel); + + gbc.gridx = 6; + gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridheight = 3; + gbc.ipadx = 200; + gbc.ipady = 55; + gbc.anchor = GridBagConstraints.CENTER; + gbc.insets = new Insets(0, 0, 100, 0); + mpane.add(internalFrame, gbc); + + gbc.gridx = 1; + gbc.gridy = 2; + gbc.fill = GridBagConstraints.BOTH; + gbc.gridwidth = 2; + gbc.gridheight = 7; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.insets = new Insets(0, 10, 30, 0); + mpane.add(imgpane, gbc); + + tester = new BackgroundAnimation(); + JPanel anipane = new JPanel(); + anipane.setLayout(new BoxLayout(anipane, BoxLayout.Y_AXIS)); + anipane.add(Box.createRigidArea(new Dimension(0, 45))); + anipane.add(tester); + + rb = new RibbonPane(140, client); + rb.setPreferredSize(new Dimension(mpane.getWidth(), 28)); + anipane.add(rb); + setContentPane(anipane); + mpane.setVisible(true); + internalFrame.setVisible(true); + try { + internalFrame.setSelected(true); + } catch (Exception v) { + }; + rb.startAnimation(); + } + RibbonPane rb; + BackgroundAnimation tester; + + void unmovable(JInternalFrame jif) { + BasicInternalFrameUI ui = (BasicInternalFrameUI) jif.getUI(); + Component north = ui.getNorthPane(); + MouseMotionListener[] actions = (MouseMotionListener[]) north.getListeners(MouseMotionListener.class); + for (int i = 0; i < actions.length; i++) + north.removeMouseMotionListener(actions[i]); + } + + Font titleFont = null; + Font tempus = null; + Font arial = null; + Font calibri = null; + public void init(String args[]) { + loadAppletParameters(args); + try { + calibri = new Font("Calibri", Font.PLAIN, 11); + arial = new Font("Arial", Font.BOLD, 18); + tempus = new Font("Tempus Sans ITC", Font.BOLD, 20); + titleFont = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getClassLoader().getResourceAsStream(location + "burnstown-dam.regular.ttf")).deriveFont(Font.PLAIN, 25); + img = new ImageIcon(this.getClass().getClassLoader().getResource(location + "logo.png")).getImage(); + img2 = new ImageIcon(this.getClass().getClassLoader().getResource(location + "logo2.png")).getImage(); + } catch (Exception m) { + m.printStackTrace(); + } + client = new Client(this, null); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createGUI(); + main.setVisible(true); + } + }); + } catch (Exception e) { + e.printStackTrace(); + System.err.println("createGUI didn't successfully complete"); + } + } + + static DecimalFormat twoDForm = new DecimalFormat("#.##"); + JTable table[]; + JPanel add; + NewsPane news; + JLabel sensex, spon, time; + JPanel userpane[]; + static JLabel imglabel2 = null; + Cashier cash; + final String[] columnNames1 = {"SrNo.", "Company", "Quantity", "C.M.P.", "Mkt Value", "Gain/Loss", "Abs Return(%)", "Action"}; + final String[] columnNames2 = {"SrNo.", "Company", "C.M.P.", "% Change", "Low", "High", "Action"}; + final String[] columnNames3 = {"SrNo.", "Company", "Type", "Price Limit", "Quantity (Limit)", "Status", "Action"}; + Action delete; + static JTabbedPane jtp; + void proceedLogin(User user) { + tester.stopAnimation(); + ur = user; + username.setFont(tempus); + username.setText(user.getName() + " "); + mpane.remove(internalFrame); + jp.remove(jp1); + mpane.remove(imgpane); + mpane.repaint(); + + news = new NewsPane(); + news.startAnimation(); + JSplitPane jsp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new RankingWindow(client), new ChatWindow(user, client)); + jsp.setPreferredSize(new Dimension(getWidth1() / 4, getHeight1() - 120)); + gbc.gridx = 6; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.VERTICAL; // VERTICAL + gbc.gridwidth = 2; + gbc.gridheight = 9; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.insets = new Insets(0, 0, 40, 20); + gbc.anchor = GridBagConstraints.FIRST_LINE_END; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + mpane.add(jsp, gbc); + jp.add(jp2, BorderLayout.EAST); + jsp.setDividerLocation((getHeight1() - 120) / 2); + JPanel add = new JPanel(); + // add.setOpaque(false); + add.setPreferredSize(new Dimension((getWidth1() * 5) / 8, (getHeight1() * 17) / 100)); + add.setMaximumSize(new Dimension((getWidth1() * 5) / 8, (getHeight1() * 17) / 100)); + add.setLayout(new BorderLayout()); + add.add(news, BorderLayout.SOUTH); + add.setBorder(new BevelBorder(BevelBorder.RAISED)); + imglabel2 = new JLabel(); + imglabel2.setSize((int) add.getPreferredSize().getWidth() + 50, (int) add.getPreferredSize().getHeight() - 25); + imglabel2.setOpaque(false); + imglabel2.setIcon(new ImageIcon(img2.getScaledInstance(imglabel2.getWidth(), imglabel2.getHeight(), Image.SCALE_SMOOTH))); + imglabel2.setFont(arial); + imglabel2.setText("
Sensex: 
Time Left:
"); + imglabel2.setHorizontalTextPosition(JLabel.LEFT); + imglabel2.setVerticalTextPosition(JLabel.BOTTOM); + add.add(imglabel2, BorderLayout.CENTER); + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = 5; + gbc.gridheight = 2; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.insets = new Insets(20, 40, 0, 0); + gbc.anchor = GridBagConstraints.PAGE_START; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + mpane.add(add, gbc); + + jtp = new JTabbedPane(); + jtp.setPreferredSize(new Dimension((getWidth1() * 5) / 8, (getHeight1() * 6) / 10)); + userpane = new JPanel[5]; + + dtm = new DefaultTableModel[3]; + dtm[0] = new DefaultTableModel(columnNames1, 0); + dtm[1] = new DefaultTableModel(columnNames2, 0); + dtm[2] = new DefaultTableModel(columnNames3, 0); + + table = new JTable[3]; + JScrollPane jspt[] = new JScrollPane[3]; + mon = new JLabel[3]; + + cash = new Cashier(client, ur); + table[0] = new JTable(dtm[0]) { + public boolean isCellEditable(int row, int col) { + if (col == 7) + return true; + return false; + } + public boolean isCellSelected(int row, int col) { + return false; + } + }; + table[1] = new JTable(dtm[1]) { + public boolean isCellEditable(int row, int col) { + if (col == 6) + return true; + return false; + } + public boolean isCellSelected(int row, int col) { + return false; + } + }; + table[2] = new JTable(dtm[2]) { + public boolean isCellEditable(int row, int col) { + if (col == 6) + return true; + return false; + } + public boolean isCellSelected(int row, int col) { + return false; + } + }; + + for (int i = 0; i < 3; i++) { + table[i].setDragEnabled(false); + table[i].setRowSelectionAllowed(false); + table[i].setColumnSelectionAllowed(false); + // table.setShowHorizontalLines(true); + // table.setShowVerticalLines(true); + table[i].setRowHeight(30); + table[i].getTableHeader().setReorderingAllowed(false); + table[i].setFillsViewportHeight(true); + jspt[i] = new JScrollPane(table[i]); + userpane[i] = new JPanel(new BorderLayout()); + userpane[i].add(jspt[i], BorderLayout.CENTER); + mon[i] = new JLabel("Avail. Cash : " + twoDForm.format(user.getCurrentMoney())); + mon[i].setFont(tempus); + userpane[i].add(mon[i], BorderLayout.SOUTH); + } + + userpane[3] = GraphPanel.main(client); + userpane[4] = HistogramPanel.main(client); + + delete = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + JTable table = (JTable) e.getSource(); + final int row = Integer.valueOf(e.getActionCommand()); + if (table == main.table[0]) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + cash.showDialog((String) main.table[0].getValueAt(row, 1), 1, ur.getCurrentShares().get(row)); + } + }); + } else if (table == main.table[1]) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + cash.showDialog((String) main.table[1].getValueAt(row, 1), 0, null); + } + }); + } else if (table == main.table[2]) { + int res = JOptionPane.showConfirmDialog(null, "Are you sure ?", "Confirm:", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); + if (res == JOptionPane.YES_OPTION) { + new Thread() { + public void run() { + final String res = client.cancelShares(ur.getName(), ur.getPassword(), ur.getPendingShares().get(row).id, ur.getPendingShares().get(row).sellid); + if (res.equals("0")) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Sorry your cancellation period is over.", "Error:", JOptionPane.PLAIN_MESSAGE); + } + }); + } else if (res.equals("1")) { + ur.getPendingShares().get(row).status = "Cancelled"; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + updateTables(); + } + }); + } + } + }.start(); + } + } + } + }; + /* + * ButtonColumn b=new ButtonColumn(table[0], delete, 7); ButtonColumn + * b2=new ButtonColumn(table[1], delete, 6); ButtonColumn b3=new + * ButtonColumn(table[2], delete, 4); + */ + jtp.add("Your Holdings", userpane[0]); + jtp.add("Watchlist", userpane[1]); + jtp.add("Your Orders", userpane[2]); + jtp.add("Company Overview", userpane[3]); + + jtp.add("Order Stats", userpane[4]); + jtp.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + String temp = null; + if (jtp.getSelectedIndex() == 4) { + temp = (String) HistogramPanel.comp.getSelectedItem(); + } + final String company = temp; + new Thread() { + public void run() { + client.getSendCompanyStatsPeriodically(company); + } + }.start(); + } + }); + + jtp.setEnabledAt(3, false); + jtp.setEnabledAt(4, false); + gbc.gridx = 0; + gbc.gridy = 3; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = 5; + gbc.gridheight = 5; + gbc.ipadx = 0; + gbc.ipady = 0; + gbc.insets = new Insets(0, 40, 60, 0); + gbc.anchor = GridBagConstraints.PAGE_END; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + mpane.add(jtp, gbc); + jtp.repaint(); + udcl = new UserDataChangedListener() { + public void userDataChanged(User user) { + updateTables(); + } + }; + user.addUserDataChangeListener(udcl); + svcl = new ShareValuesChangeListener() { + public void valuesChanged() { + updateTables(); + } + }; + rb.addShareValuesChangeListener(svcl); + } + DefaultTableCellRenderer dtr = new DefaultTableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value.toString().indexOf("-") != -1) { + value = value.toString() + " \u25bc"; + } else { + value = value.toString() + " \u25b2"; + } + Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (value.toString().indexOf("-") != -1) { + c.setForeground(Color.red); + } else { + c.setForeground(Color.green); + } + return c; + } + }; + void updateTables() { + try { + for (int i = 0; i < 3; i++) { + mon[i].setText("Avail. Cash : " + twoDForm.format(ur.getCurrentMoney()) + " Rank: " + RankingClient.rank); + mon[i].repaint(); + } + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + java.util.List ss = ur.getCurrentShares(); + Object data[][] = new Object[ss.size()][8]; + for (int i = 0; i < ss.size(); i++) { + data[i] = new Object[]{Integer.toString(i + 1), ss.get(i).company, ss.get(i).qty, twoDForm.format(Companies.getCompanyWithName(ss.get(i).company).mktvalue), twoDForm.format(ss.get(i).qty * Companies.getCompanyWithName(ss.get(i).company).mktvalue), twoDForm.format(ss.get(i).qty * Companies.getCompanyWithName(ss.get(i).company).mktvalue - ss.get(i).qty * ss.get(i).cost), twoDForm.format(((Companies.getCompanyWithName(ss.get(i).company).mktvalue - ss.get(i).cost) * 100) / ss.get(i).cost), "Sell"}; + } + dtm[0].setDataVector(data, columnNames1); + new ButtonColumn(table[0], delete, 7); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + Object data[][] = new Object[Companies.comp.size()][7]; + for (int i = 0; i < Companies.comp.size(); i++) { + data[i] = new Object[]{Integer.toString(i + 1), Companies.comp.get(i).name, twoDForm.format(Companies.comp.get(i).mktvalue), twoDForm.format((Companies.comp.get(i).mktvalue - Companies.comp.get(i).inivalue) * 100 / Companies.comp.get(i).inivalue), twoDForm.format(Companies.comp.get(i).low), twoDForm.format(Companies.comp.get(i).high), "Buy"}; + } + dtm[1].setDataVector(data, columnNames2); + new ButtonColumn(table[1], delete, 6); + table[1].getColumnModel().getColumn(3).setCellRenderer(dtr); + table[1].repaint(); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + java.util.List ss = ur.getPendingShares(); + Object data[][] = new Object[ss.size()][7]; + for (int i = 0; i < ss.size(); i++) { + String type = "", costLimit = "Not Applicable"; + switch (ss.get(i).type) { + case 0 : + type = "Market Buy Order"; + break; + case 1 : + type = "Market Sell Order"; + break; + case 2 : + type = "Limit Buy Order"; + costLimit = String.valueOf(ss.get(i).cost_limit); + break; + case 3 : + type = "Limit Sell Order"; + costLimit = String.valueOf(ss.get(i).cost_limit); + break; + } + data[i] = new Object[]{Integer.toString(i + 1), ss.get(i).company, type, costLimit, ss.get(i).qty_limit, ss.get(i).status, "Cancel"}; + } + dtm[2].setDataVector(data, columnNames3); + new ButtonColumn(table[2], delete, 6); + } catch (Exception mm) { + mm.printStackTrace(); + } + } + public void stop() { + try { + if (client != null) + client.disconnect(); + } finally { + System.exit(0); + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/NewsPane.java b/src/com/ayushmaanbhav/jstockmart/client/NewsPane.java new file mode 100644 index 0000000..649cc41 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/NewsPane.java @@ -0,0 +1,56 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import java.awt.event.*; +import java.awt.*; +@SuppressWarnings("serial") +class NewsPane extends JPanel implements ActionListener { + static StringBuffer temp; + StringBuffer sb; + Timer t; + int loop; + JLabel l; + public NewsPane() { + sb = new StringBuffer(""); + temp = new StringBuffer(""); + t = new Timer(140, this); + setOpaque(false); + setLayout(new BorderLayout()); + l = new JLabel("
News : 
"); + l.setFont(new Font("Calibri", Font.BOLD, 13)); + l.setOpaque(false); + setSize(getWidth(), 30); + add(l, BorderLayout.CENTER); + } + protected void paintComponent(Graphics grphcs) { + Graphics2D g2d = (Graphics2D) grphcs; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, getBackground().brighter(), 0, getHeight(), getBackground().darker()); + g2d.setPaint(gp); + g2d.fillRect(0, 0, getWidth(), getHeight()); + super.paintComponent(grphcs); + } + void startAnimation() { + loop = 0; + t.start(); + } + void stopAnimation() { + loop = 0; + t.stop(); + } + public void actionPerformed(ActionEvent e) { + if (sb.length() > 200) { + l.setText("
News : " + sb.substring(0, 200) + "
"); + sb.append(sb.charAt(0)); + sb.delete(0, 1); + loop++; + if (loop > sb.length()) { + sb = new StringBuffer(temp); + loop = 0; + } + } else { + sb = new StringBuffer(temp); + loop = 0; + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/RankingClient.java b/src/com/ayushmaanbhav/jstockmart/client/RankingClient.java new file mode 100644 index 0000000..a593a98 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/RankingClient.java @@ -0,0 +1,54 @@ +package com.ayushmaanbhav.jstockmart.client; + +import javax.swing.*; + +public class RankingClient extends Thread { + JTextPane jta; + JScrollPane jspp; + static String rank = ""; + public RankingClient(JTextPane ja, JScrollPane o) { + jta = ja; + jspp = o; + rank = ""; + } + public void run(String hh) { + try { + // StringBuffer fin=new StringBuffer(" "); + String str[] = hh.trim().split(":"); + String f = ""; + int uu = 0; + for (int i = 0; i < str.length; i++) { + int iii = str[i].indexOf('-'); + f += (i + 1) + ") " + str[i].substring(0, iii) + " -> " + str[i].substring(iii+1) + "\n"; + if (uu == 0 && str[i].indexOf(Main.ur.getName()) != -1) { + uu = 1; + rank = (i + 1) + " Score: " + str[i].substring(iii + 1); + } + } + final String h = f; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + jta.setText(h); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + jspp.getVerticalScrollBar().setValue(0); + } + }); + try { + for (int i = 0; i < 3; i++) { + Main.mon[i].setText("Avail. Cash : " + Main.twoDForm.format(Main.ur.getCurrentMoney()) + " Rank: " + rank); + Main.mon[i].repaint(); + } + } catch (Exception mm) { + mm.printStackTrace(); + } + } catch (Exception e) { + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/client/RankingWindow.java b/src/com/ayushmaanbhav/jstockmart/client/RankingWindow.java new file mode 100644 index 0000000..1876438 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/RankingWindow.java @@ -0,0 +1,29 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import java.awt.*; + +import javax.swing.text.*; + +@SuppressWarnings("serial") +class RankingWindow extends JPanel { + JTextPane jta; + JScrollPane jsp; + public RankingWindow(Client cc) { + setLayout(new BorderLayout()); + JLabel jlab = new JLabel("<>"); + jta = new JTextPane(); + StyledDocument doc = jta.getStyledDocument(); + SimpleAttributeSet center = new SimpleAttributeSet(); + StyleConstants.setAlignment(center, StyleConstants.ALIGN_LEFT); + doc.setParagraphAttributes(0, doc.getLength(), center, false); + jta.setFont(new Font("Calibri", Font.PLAIN, 13)); + jta.setEditable(false); + jta.setForeground(Color.red.darker()); + jsp = new JScrollPane(jta, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + add(jlab, BorderLayout.NORTH); + add(jsp, BorderLayout.CENTER); + RankingClient cser = new RankingClient(jta, jsp); + cc.rc = cser; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/Receiver.java b/src/com/ayushmaanbhav/jstockmart/client/Receiver.java new file mode 100644 index 0000000..4779a42 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/Receiver.java @@ -0,0 +1,139 @@ +package com.ayushmaanbhav.jstockmart.client; + +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.thavam.util.concurrent.BlockingHashMap; +import org.thavam.util.concurrent.BlockingMap; + +import com.ayushmaanbhav.jstockmart.user.Commands; +import com.ayushmaanbhav.jstockmart.user.User; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +public class Receiver extends Thread { + @SuppressWarnings("rawtypes") + BlockingMap rev; + Client client; + + @SuppressWarnings("rawtypes") + public Receiver(Client client) { + this.client = client; + rev = new BlockingHashMap(); + setPriority(MAX_PRIORITY); + } + + @SuppressWarnings("unchecked") + public void run() { + while (client.connected) { + try { + Object obj = client.in.readObject(); + if (Client.testing) + System.out.println("Got Obj: " + obj.toString()); + if (obj instanceof String) { + String recString = (String) obj; + if (recString.equals(Commands.UNKNOWN_COMMAND)) { + client.connected = false; + client.in.close(); + client.out.close(); + client.socket.close(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Cashier.closee = true; + JOptionPane.showMessageDialog(null, "Disconnected from server. Please Restart", "Error:", JOptionPane.PLAIN_MESSAGE); + try { + client.m.stop(); + } catch (Exception w) { + } + } + }); + } else if (recString.equals(Commands.SERVER_NOT_RUNNING)) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Cashier.closee = true; + JOptionPane.showMessageDialog(null, "Server Not Running.", "Error:", JOptionPane.PLAIN_MESSAGE); + } + }); + } else { + String command[] = recString.split("::"); + if (command[0].equals(Commands.BROADCAST)) { + if (client.bc != null) + client.bc.run(command[1]); + } else if (command[0].equals(Commands.CHAT_AND_NEWS)) { + if (client.cc != null) + client.cc.run(command[1]); + } else if (command[0].equals(Commands.FINAL_RANKINGS)) { + String hhh = command[1]; + final JDialog jd = new JDialog(); + jd.setUndecorated(false); + JPanel pan = new JPanel(new BorderLayout()); + JLabel ppp = new JLabel(); + ppp.setFont(new Font("Calibri", Font.BOLD, 20)); + ppp.setText("
Thanks for playing !!!
1st: " + hhh.split(":")[0] + "
2nd: " + hhh.split(":")[1] + "
3rd: " + hhh.split(":")[2] + "
"); + pan.add(ppp, BorderLayout.CENTER); + JButton ok = new JButton("Ok"); + ok.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jd.setVisible(false); + try { + client.m.stop(); + } catch (Exception w) { + } + } + }); + pan.add(ok, BorderLayout.SOUTH); + jd.setContentPane(pan); + jd.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); + jd.pack(); + jd.setLocationRelativeTo(null); + jd.setVisible(true); + } else if (command[0].equals(Commands.RANKS)) { + if (client.rc != null) + client.rc.run(command[1]); + } else { + try { + int cmdID = Integer.parseInt(recString); + obj = client.in.readObject(); + rev.offer(cmdID, obj); + } catch (Exception ppp) { + ppp.printStackTrace(); + if (Client.testing) + System.out.println("Shit: " + recString + " : " + Thread.currentThread()); + } + } + } + } else if (obj instanceof User) { + try { + Main.ur.changeData((User) obj); + } catch (Exception w) { + try { + client.maain.ur.changeData((User) obj); + } catch (Exception ppp) { + ppp.printStackTrace(); + } + } + } else if (obj instanceof TrippleArrayList) { + HistogramPanel.mainPanel.setScores((TrippleArrayList) obj); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + HistogramPanel.mainPanel.repaint(); + } + }); + } + } catch (Exception m) { + m.printStackTrace(); + client.disconnect(); + break; + } + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/RegisterAction.java b/src/com/ayushmaanbhav/jstockmart/client/RegisterAction.java new file mode 100644 index 0000000..d07885a --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/RegisterAction.java @@ -0,0 +1,96 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import com.ayushmaanbhav.jstockmart.utils.HintPasswordField; +import com.ayushmaanbhav.jstockmart.utils.HintTextField; + +import java.awt.event.*; +import java.util.regex.Pattern; + +class RegisterAction implements ActionListener { + HintTextField reg, user; + HintPasswordField pass; + String domain; + Client client; + public RegisterAction(HintTextField r, HintTextField u, HintPasswordField p, String d, Client c) { + reg = r; + user = u; + pass = p; + domain = d; + client = c; + } + public void actionPerformed(ActionEvent e) { + Pattern p1 = Pattern.compile("[a-z0-9_]{3,16}"); + Pattern p2 = Pattern.compile("[a-z0-9_]{6,18}"); + if (!p1.matcher(reg.getText()).matches()) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Incorect registration no.\nThe registration no. should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + } + }); + return; + } + if (!p1.matcher(user.getText()).matches()) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Incorrect username.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + } + }); + return; + } + if (!p2.matcher(pass.getText()).matches()) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Incorrect password.\nA password should be of length {6-18} and can contain\nletters(a-z), numbers and underscores", "Error:", JOptionPane.PLAIN_MESSAGE); + pass.setText(""); + } + }); + return; + } + if (domain.equals("domain")) { + domain = JOptionPane.showInputDialog("Enter domain."); + } + if (domain == null || domain.equals("")) + return; + new Thread() { + public void run() { + String rep = client.register(domain, reg.getText(), user.getText(), pass.getText()); + if (rep == null) + return; + if (rep.equals("1")) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Reg Successful", "Registration", JOptionPane.PLAIN_MESSAGE); + } + }); + // regestered + } else if (rep.equals("3")) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Username already exists.\nA username should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + user.setText(""); + } + }); + return; + } else if (rep.equals("2")) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Incorect registration no.\nThe registration no. should be of length {3-16} and can contain\nletters(a-z), numbers and underscores.", "Error:", JOptionPane.PLAIN_MESSAGE); + reg.setText(""); + } + }); + return; + } else if (rep.equals("4")) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, "Server Replies: Already registered.", "Error:", JOptionPane.PLAIN_MESSAGE); + } + }); + return; + } + } + }.start(); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/client/RibbonPane.java b/src/com/ayushmaanbhav/jstockmart/client/RibbonPane.java new file mode 100644 index 0000000..99396d1 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/client/RibbonPane.java @@ -0,0 +1,63 @@ +package com.ayushmaanbhav.jstockmart.client; +import javax.swing.*; + +import java.awt.event.*; +import java.awt.*; +@SuppressWarnings("serial") +class RibbonPane extends JPanel implements ActionListener { + StringBuffer sb, temp; + BroadcastClient bc; + Timer t; + int loop; + JLabel l; + final String wel = " StockMart - Disable proxy in java in control panel and in your browser too.... Register with your AnweshaID or you will be disqualified..... "; + public RibbonPane(int tm, Client cc) { + sb = new StringBuffer(wel); + temp = new StringBuffer(wel); + bc = new BroadcastClient(temp); + cc.bc = bc; + t = new Timer(tm, this); + setOpaque(false); + l = new JLabel(wel); + l.setFont(new Font("Arial", Font.BOLD, 13)); + l.setOpaque(false); + add(l); + setDoubleBuffered(true); + } + protected void paintComponent(Graphics grphcs) { + Graphics2D g2d = (Graphics2D) grphcs; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, getBackground().brighter(), 0, getHeight(), getBackground().darker()); + g2d.setPaint(gp); + g2d.fillRect(0, 0, getWidth(), getHeight()); + super.paintComponent(grphcs); + } + void startAnimation() { + loop = 0; + t.start(); + // bc.start(); + } + void stopAnimation() { + loop = 0; + t.stop(); + // bc.interrupt(); + } + public void actionPerformed(ActionEvent e) { + if (sb.length() > 260) { + l.setText("
" + sb.substring(0, 260).replace("\u25b2", "\u25b2").replace("\u25bc", "\u25bc") + "
");
+			sb.append(sb.charAt(0));
+			sb.delete(0, 1);
+			loop++;
+			if (loop > sb.length()) {
+				sb = new StringBuffer(temp);
+				loop = 0;
+			}
+		} else {
+			while (sb.length() <= 260)
+				sb.append(' ');
+		}
+	}
+	void addShareValuesChangeListener(ShareValuesChangeListener svcl) {
+		bc.svcl = svcl;
+	}
+}
\ No newline at end of file
diff --git a/src/com/ayushmaanbhav/jstockmart/client/ShareValuesChangeListener.java b/src/com/ayushmaanbhav/jstockmart/client/ShareValuesChangeListener.java
new file mode 100644
index 0000000..322964e
--- /dev/null
+++ b/src/com/ayushmaanbhav/jstockmart/client/ShareValuesChangeListener.java
@@ -0,0 +1,5 @@
+package com.ayushmaanbhav.jstockmart.client;
+
+interface ShareValuesChangeListener {
+	public void valuesChanged();
+}
\ No newline at end of file
diff --git a/src/com/ayushmaanbhav/jstockmart/client/Test.java b/src/com/ayushmaanbhav/jstockmart/client/Test.java
new file mode 100644
index 0000000..457ea58
--- /dev/null
+++ b/src/com/ayushmaanbhav/jstockmart/client/Test.java
@@ -0,0 +1,117 @@
+package com.ayushmaanbhav.jstockmart.client;
+import java.io.*;
+
+import com.ayushmaanbhav.jstockmart.user.*;
+class Test {
+	int i;
+	BufferedWriter bw;
+	public void main(final String d, final int n) throws IOException {
+		// bw = new BufferedWriter(new FileWriter("test_client_log.txt"));
+		for (i = 0; i < n; i++) {
+			new TestMain() {
+				String regn, un, pass;
+				public void run() {
+					try {
+						// Main m = new Main();
+						// m.domain = d;
+						Client client = new Client(null, this);
+						regn = "robotregno" + (int) (Math.random() * 10000);
+						un = "robotuser" + (int) (Math.random() * 10000);
+						pass = "robotpass" + (int) (Math.random() * 10000);
+						if (!client.register(d, regn, un, pass).equals("1"))
+							return;
+						if (!client.login(d, un, pass).equals("0"))
+							return;
+						ur = (User) client.getUserDetails(un, pass);
+						/*
+						 * m.udcl=new UserDataChangedListener(){ public void
+						 * userDataChanged(User user) { //updateTables(); } };
+						 * m.svcl=new ShareValuesChangeListener(){ public void
+						 * valuesChanged() { //updateTables(); } };
+						 */
+						// m.cash=new Cashier(client,m.ur);
+						client.bc = new BroadcastClient(new StringBuffer());
+						client.rc = null;
+						client.cc = null;
+						while (true) {
+							try {
+								double r = Math.random();
+								// bw.write(un+" "+r);
+								if (r >= 0.0 && r < 0.4375 && Companies.comp.size() > 0) {
+									// bw.write(un+" buying");
+									int id = (int) (Math.random() * Companies.comp.size());
+									Company c = Companies.getCompanyWithId(id);
+									double money = Math.random() * ur.getCurrentMoney();
+									int noofshares = (int) (money / c.mktvalue);
+									if (noofshares > 0) {
+										client.placeOrder(ur, "buy", c, 100, noofshares, c.id);
+										/*
+										 * bw.write(un+" placing buy order: "+c.name
+										 * +noofshares+"\n"); bw.flush();
+										 */
+									}
+								} else if (r >= 0.4375 && r < 0.875 && ur.getCurrentShares().size() > 0) {
+									// bw.write(un+" selling");
+									int id = (int) (Math.random() * ur.getCurrentShares().size());
+									Company c = Companies.getCompanyWithName(ur.getCurrentShares().get(id).company);
+									int noofshares = (int) (Math.random() * ur.getCurrentShares().get(id).qty);
+									if (noofshares > 0) {
+										client.placeOrder(ur, "sell", c, 100, noofshares, ur.getCurrentShares().get(id).id);
+										/*
+										 * bw.write(un+" placing sell order: "+c.
+										 * name+noofshares+"\n"); bw.flush();
+										 */
+									}
+								} else if (r >= 0.875 && r < 0.9 && ur.getPendingShares().size() > 0) {
+									// bw.write(un+" canceling");
+									int id = (int) (Math.random() * ur.getPendingShares().size());
+									client.cancelShares(un, pass, ur.getPendingShares().get(id).id, ur.getPendingShares().get(id).sellid);
+									/*
+									 * bw.write(un+" corder placed"+"\n");
+									 * bw.flush();
+									 */
+								} else if (r >= 0.9 && r < 0.925) {
+									// bw.write(un+" chatting");
+									client.sendChat("hi " + pp++, un, pass);
+									/*
+									 * bw.write(un+" chatted"+"\n"); bw.flush();
+									 */
+								} else {
+									/*
+									 * bw.write(un+" idle"+"\n"); bw.flush();
+									 */
+								}
+								try {
+									Thread.sleep((long) (Math.random() * 3000));
+								} catch (Exception r2) {
+								}
+							} catch (Exception r1) {
+								r1.printStackTrace();
+							}
+						}
+					} catch (Exception r4) {
+						try {
+							/*
+							 * bw.write(un+" : "+r4.getMessage()+"\n");
+							 * bw.flush();
+							 */
+						} catch (Exception jjj) {
+						}
+					}
+				}
+				int pp = 0;
+			}.start();
+			try {
+				Thread.sleep(100);
+			} catch (Exception r2) {
+			}
+		}
+	}
+	public static void main(String args[]) {
+		try {
+			Test t = new Test();
+			t.main("127.0.0.1", 100);
+		} catch (IOException ff) {
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/com/ayushmaanbhav/jstockmart/client/TestMain.java b/src/com/ayushmaanbhav/jstockmart/client/TestMain.java
new file mode 100644
index 0000000..8d0b8c2
--- /dev/null
+++ b/src/com/ayushmaanbhav/jstockmart/client/TestMain.java
@@ -0,0 +1,5 @@
+package com.ayushmaanbhav.jstockmart.client;
+import com.ayushmaanbhav.jstockmart.user.*;
+public abstract class TestMain extends Thread {
+	User ur;
+}
diff --git a/src/com/ayushmaanbhav/jstockmart/data/burnstown-dam.regular.ttf b/src/com/ayushmaanbhav/jstockmart/data/burnstown-dam.regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..4bd40868f235081bcc5d6175c2ed620ccf84f9a7
GIT binary patch
literal 41508
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
QinDLWRnGc*R|
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⪻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
Hpz!|&)o~}D

literal 0
HcmV?d00001

diff --git a/src/com/ayushmaanbhav/jstockmart/data/logo2.png b/src/com/ayushmaanbhav/jstockmart/data/logo2.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2e0bf541e6bf0f1039d6c7298494618e03edf1b
GIT binary patch
literal 91114
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%0DC*nXcJ*Ht8g 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 com; + int close; + int id; + BlockingQueue queue; + Server server; + static boolean sendFullDetails; + + public BroadcastServer(String name, List c, Server s) throws IOException { + super(name); + setPriority(9); + com = c; + server = s; + queue = new LinkedBlockingQueue(); + } + + static DecimalFormat twoDForm = new DecimalFormat("#.##"); + public void run() { + sendFullDetails = true; + close = 0; + while (true) { + if (close == 1) + break; + try { + id = queue.take(); + int temp = (int) (StockMart.totTime * 60 - (new Date().getTime() - StockMart.startDate.getTime()) / 1000); + int hrs = temp / 3600; + int mins = ((temp / 60) % 60); + StringBuffer dString = new StringBuffer(); + dString.append(Commands.BROADCAST); + dString.append("::"); + dString.append(String.valueOf(id++)); + dString.append("#"); + dString.append(hrs); + dString.append(":"); + dString.append(mins / 10 == 0 ? "0" : ""); + dString.append(mins); + dString.append(";"); + dString.append(twoDForm.format(ShareMarket.sensex)); + dString.append("="); + for (int i = 0; i < com.size(); i++) { + Company c = com.get(i); + // if (!c.bankrupt) { + dString.append(String.valueOf(i)); + dString.append(":"); + dString.append(c.name); + dString.append(":"); + dString.append(String.valueOf(c.sharevalue.get(c.sharevalue.size() - 1))); + dString.append(":"); + dString.append(String.valueOf(c.sharevalue.get(0))); + dString.append(":"); + dString.append(String.valueOf(c.getHighest())); + dString.append(":"); + dString.append(String.valueOf(c.getLowest())); + dString.append(":"); + dString.append(String.valueOf(c.price_precision)); + dString.append(";"); + // } + } + sendFullDetails = false; + server.sendMulti(dString.toString(), 5); + server.sendPeriodicStats(5); + /* + * try { sleep(SECONDS); } catch (InterruptedException e) { } + */ + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/ChatServer.java b/src/com/ayushmaanbhav/jstockmart/server/ChatServer.java new file mode 100644 index 0000000..9be2236 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/ChatServer.java @@ -0,0 +1,53 @@ +package com.ayushmaanbhav.jstockmart.server; +import java.io.*; +import java.util.*; + +import com.ayushmaanbhav.jstockmart.user.Commands; + +public class ChatServer extends Thread { + Server server; + StringBuffer chaat; + BufferedWriter bw; + public ChatServer(Server s) throws IOException { + setPriority(Thread.MIN_PRIORITY); + server = s; + chaat = new StringBuffer(); + try { + bw = new BufferedWriter(new FileWriter("appdata/chat.txt")); + } catch (Exception mm) { + } + } + + public void run() { + while (true) { + try { + StringBuffer toSend = new StringBuffer(); + toSend.append(Commands.CHAT_AND_NEWS); + toSend.append("::"); + if (StockMart.newsfeed.equals("")) + toSend.append("-1"); + else + toSend.append(StockMart.newsfeed); + toSend.append(";"); + if (chaat.toString().equals("")) + toSend.append("-1"); + else + toSend.append(chaat); + chaat.setLength(0); + server.sendMulti(toSend.toString(), Thread.MIN_PRIORITY); + try { + bw.write(new Date().toString() + ":" + toSend + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + sleep(30000); + } catch (InterruptedException e1) { + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/Company.java b/src/com/ayushmaanbhav/jstockmart/server/Company.java new file mode 100644 index 0000000..4912b39 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/Company.java @@ -0,0 +1,75 @@ +package com.ayushmaanbhav.jstockmart.server; +import java.util.*; +import java.io.*; +class Company { + String name; + volatile ArrayList sharevalue, futurevalues; + volatile int sharessold, nooflimitbidsmatched, totalshares, tsharessold, sharessoldpast; + volatile Date d; + volatile double perchange, W, rate, vol, highest, lowest, phighest, plowest, price_precision, pprice_precision; + boolean bankrupt; + BufferedWriter bw; + + @SuppressWarnings("serial") + public Company(String n, List l, int sd, int tot, double rate1, double vol1) { + rate = rate1; + vol = vol1; + name = n; + highest = 0; + phighest = plowest = -1; + lowest = Integer.MAX_VALUE; + sharevalue = new ArrayList() { + @Override + public boolean add(Double value) { + if (lowest > value) { + plowest = lowest; + lowest = value; + } + if (highest < value) { + phighest = highest; + highest = value; + } + return super.add(value); + } + }; + sharevalue.add(l.get(0)); + futurevalues = new ArrayList(); + sharessold = sd; + nooflimitbidsmatched = 0; + totalshares = tot; + tsharessold = 0; + bankrupt = false; + W = 0; + pprice_precision = 0; + price_precision = MatchingEngine.getHighestPrecision(this); + try { + bw = new BufferedWriter(new FileWriter("appdata/companydata/" + name + ".txt")); + } catch (Exception mm) { + } + } + /* + * public Company(String n) { name=n; sharevalue=new ArrayList(); + * sharessold=0; } + */ + public void updateFile() { + try { + bw.write(d.toString() + ":" + name + ":" + sharevalue.get(sharevalue.size() - 1) + ":" + perchange + ":" + sharessoldpast + ":" + tsharessold + ":" + totalshares + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } + + public double getHighest() { + return highest; + } + + public double getLowest() { + return lowest; + } + + public void setPricePrecision(double price_precision) { + this.pprice_precision = this.price_precision; + this.price_precision = price_precision; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/GraphPanel.java b/src/com/ayushmaanbhav/jstockmart/server/GraphPanel.java new file mode 100644 index 0000000..2ba91c0 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/GraphPanel.java @@ -0,0 +1,250 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; + +@SuppressWarnings("serial") +public class GraphPanel extends JPanel { + + // private int width = 800; + // private int heigth = 600; + private int padding = 25; + private int labelPadding = 25; + private Color lineColor = new Color(44, 102, 230, 180); + private Color pointColor = new Color(100, 100, 100, 180); + private Color gridColor = new Color(200, 200, 200, 200); + private static final Stroke GRAPH_STROKE = new BasicStroke(2f); + private int pointWidth = 4; + private int numberYDivisions = 10; + private static List score; + private static List scores, future; + + public GraphPanel(List scores) { + GraphPanel.score = scores; + } + + @Override + protected void paintComponent(Graphics g) { + for (int i = 0; i < score.size(); i++) { + if (score.get(i).name.equals((String) comp.getSelectedItem())) { + scores = score.get(i).sharevalue; + future = score.get(i).futurevalues; + frame.setTitle(score.get(i).name); + break; + } + } + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() + future.size() - 1); + double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore()); + + List graphPoints = new ArrayList<>(); + for (int i = 0; i < scores.size() + future.size(); i++) { + int x1, y1; + if (i < scores.size()) { + x1 = (int) (i * xScale + padding + labelPadding); + y1 = (int) ((getMaxScore() - scores.get(i)) * yScale + padding); + } else { + x1 = (int) (i * xScale + padding + labelPadding); + y1 = (int) ((getMaxScore() - future.get(i - scores.size())) * yScale + padding); + } + graphPoints.add(new Point(x1, y1)); + } + + // draw white background + g2.setColor(Color.WHITE); + g2.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding - labelPadding); + g2.setColor(Color.BLACK); + + // create hatch marks and grid lines for y axis. + for (int i = 0; i < numberYDivisions + 1; i++) { + int x0 = padding + labelPadding; + int x1 = pointWidth + padding + labelPadding; + int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding); + int y1 = y0; + if (scores.size() + future.size() > 0) { + g2.setColor(gridColor); + g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1); + g2.setColor(Color.BLACK); + String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + ""; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(yLabel); + g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3); + } + g2.drawLine(x0, y0, x1, y1); + } + + // and for x axis + for (int i = 0; i < scores.size() + future.size(); i++) { + if (scores.size() + future.size() > 1) { + int x0, x1, y0, y1; + x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() + future.size() - 1) + padding + labelPadding; + x1 = x0; + y0 = getHeight() - padding - labelPadding; + y1 = y0 - pointWidth; + if ((i % ((int) (((scores.size() + future.size()) / 20.0)) + 1)) == 0) { + g2.setColor(gridColor); + g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding); + g2.setColor(Color.BLACK); + String xLabel = i / 2 + "m"; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(xLabel); + if (i % 2 == 0) + g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3); + } + g2.drawLine(x0, y0, x1, y1); + } + } + + // create x and y axes + g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding); + g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding); + + Stroke oldStroke = g2.getStroke(); + g2.setColor(lineColor); + g2.setStroke(GRAPH_STROKE); + for (int i = 0; i < graphPoints.size() - 1; i++) { + int x1 = graphPoints.get(i).x; + int y1 = graphPoints.get(i).y; + int x2 = graphPoints.get(i + 1).x; + int y2 = graphPoints.get(i + 1).y; + g2.drawLine(x1, y1, x2, y2); + } + + g2.setStroke(oldStroke); + g2.setColor(pointColor); + for (int i = 0; i < graphPoints.size(); i++) { + if (i >= scores.size()) + g2.setColor(Color.RED); + int x = graphPoints.get(i).x - pointWidth / 2; + int y = graphPoints.get(i).y - pointWidth / 2; + int ovalW = pointWidth; + int ovalH = pointWidth; + g2.fillOval(x, y, ovalW, ovalH); + } + } + + // @Override + // public Dimension getPreferredSize() { + // return new Dimension(width, heigth); + // } + private double getMinScore() { + double minScore = Double.MAX_VALUE; + for (Company score1 : score) { + for (Double score2 : score1.sharevalue) { + minScore = Math.min(minScore, score2); + } + for (Double score2 : score1.futurevalues) { + minScore = Math.min(minScore, score2); + } + } + return 0; + } + + private double getMaxScore() { + double maxScore = Double.MIN_VALUE; + for (Company score1 : score) { + for (Double score2 : score1.sharevalue) { + maxScore = Math.max(maxScore, score2); + } + for (Double score2 : score1.futurevalues) { + maxScore = Math.max(maxScore, score2); + } + } + return maxScore; + } + + @SuppressWarnings("unchecked") + public void setScores(List score) { + GraphPanel.score = score; + comp.removeAllItems(); + for (int i = 0; i < score.size(); i++) + comp.addItem(score.get(i).name); + try { + comp.setSelectedIndex(0); + scores = score.get(0).sharevalue; + } catch (Exception o) { + } + invalidate(); + this.repaint(); + } + + public List getScores() { + return scores; + } + + @SuppressWarnings("rawtypes") + static JComboBox comp; + static JFrame frame; + static JTextField comp1, comp2; + static GraphPanel mainPanel; + public static void main() { + SwingUtilities.invokeLater(new Runnable() { + @SuppressWarnings("rawtypes") + public void run() { + comp = new JComboBox(); + comp1 = new JTextField(40); + comp2 = new JTextField(40); + comp1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < score.size(); i++) { + if (score.get(i).name.equals((String) comp.getSelectedItem())) { + score.get(i).rate = Double.parseDouble(comp1.getText()); + break; + } + } + } + }); + comp2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < score.size(); i++) { + if (score.get(i).name.equals((String) comp.getSelectedItem())) { + score.get(i).vol = Double.parseDouble(comp2.getText()); + break; + } + } + } + }); + comp.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + for (int i = 0; i < score.size(); i++) { + if (score.get(i).name.equals((String) comp.getSelectedItem())) { + comp1.setText("" + score.get(i).rate); + comp2.setText("" + score.get(i).vol); + break; + } + } + mainPanel.repaint(); + comp.requestFocus(); + } + } + }); + // Random random = new Random(); + // int maxDataPoints = 40; + // int maxScore = 10; + mainPanel = new GraphPanel(null); + mainPanel.setScores(ShareMarket.companies); + mainPanel.setPreferredSize(new Dimension(800, 500)); + frame = new JFrame("DrawGraph"); + // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(comp, BorderLayout.NORTH); + JPanel op = new JPanel(new BorderLayout()); + op.add(comp1, BorderLayout.WEST); + op.add(comp2, BorderLayout.EAST); + //frame.getContentPane().add(op, BorderLayout.SOUTH); + frame.getContentPane().add(mainPanel, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + }); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/HistogramPanel.java b/src/com/ayushmaanbhav/jstockmart/server/HistogramPanel.java new file mode 100644 index 0000000..fad0b23 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/HistogramPanel.java @@ -0,0 +1,94 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Collections; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import com.ayushmaanbhav.jstockmart.utils.Histogram; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +public class HistogramPanel extends JPanel { + private static final long serialVersionUID = 1L; + + private TrippleArrayList scores; + + public HistogramPanel(TrippleArrayList scores) { + this.scores = scores; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + Histogram.paintHistogram(g2, getHeight(), getWidth(), scores); + } + + public void setScores(TrippleArrayList scores) { + this.scores = scores; + } + + public TrippleArrayList getScores() { + return scores; + } + + void updatePanel() { + comp.setEnabled(false); + new Thread() { + public void run() { + TrippleArrayList arr = new TrippleArrayList(Orders.getLimitOrderStatsOfCompany((String) comp.getSelectedItem())); + if (arr != null) { + if (arr.size() > 0) { + Collections.sort(arr); + arr.add(0, 0, 0.0, 0); + arr.add(0, 0.0, 0); + } + setScores(arr); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + mainPanel.repaint(); + comp.setEnabled(true); + // comp.requestFocus(); + } + }); + } + } + }.start(); + } + + @SuppressWarnings("rawtypes") + static JComboBox comp; + static JFrame frame; + static HistogramPanel mainPanel; + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void main() { + comp = new JComboBox(); + for (int i = 0; i < ShareMarket.companies.size(); i++) + comp.addItem(ShareMarket.companies.get(i).name); + comp.setSelectedIndex(0); + comp.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + mainPanel.updatePanel(); + } + } + }); + comp.setLightWeightPopupEnabled(false); + mainPanel = new HistogramPanel(new TrippleArrayList()); + mainPanel.setPreferredSize(new Dimension(800, 500)); + frame = new JFrame(); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(comp, BorderLayout.NORTH); + frame.getContentPane().add(mainPanel, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/MatchingEngine.java b/src/com/ayushmaanbhav/jstockmart/server/MatchingEngine.java new file mode 100644 index 0000000..b19c176 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/MatchingEngine.java @@ -0,0 +1,354 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.util.ArrayList; +import java.util.Date; + +import com.ayushmaanbhav.jstockmart.user.Shares; +import com.ayushmaanbhav.jstockmart.user.User; + +public class MatchingEngine { + + private static double LTP; + + /* + * The rule is basically to match market orders first because they have to + * be executed immediately. I first get all the market orders and execute + * them at the LTP (Last Traded Price) which is also the CMP (Current Market + * Price). If any market orders are remaining then we match them with limit + * orders. The concept to understand in the limit order matching is that we + * are always biased towards the buyers. We try to profit them. Why ? This + * is because we consider sellers to be clever. You will see this in real + * markets also. They put the price much higher than the actual price and + * then they lower it on bargaining. They know the psychology of their + * customers. To sum up, most of the time sellers profit on the prices they + * set. So we always trade the limit orders on seller's price even if the + * buyer's limit price is higher. One case is special though in which the + * buyer's limit price is higher than the market price or LTP and the seller + * wishes to sell his shares on the market price so he places a market + * order. Now in this case we trade the orders on the market price or LTP + * for the same reasons explained above. + */ + static void matchOrders() { + double avg = 0; + for (int i = 0; i < ShareMarket.companies.size(); i++) { + Company com = ShareMarket.companies.get(i); + double LTP = com.sharevalue.get(com.sharevalue.size() - 1); + MatchingEngine.LTP = LTP; + + // get market orders of this company + ArrayList buyOrders = Orders.getOrders(Orders.MARKET_BUY_ORDER, com.name); + ArrayList sellOrders = Orders.getOrders(Orders.MARKET_SELL_ORDER, com.name); + + // match market orders first + while (buyOrders.size() > 0 && sellOrders.size() > 0) { + Shares s1 = buyOrders.get(0); + Shares s2 = sellOrders.get(0); + Shares s3 = MatchingEngine.matchMarketMarketOrders(s1, s2, com, LTP); + if (s3 == null) { + Orders.remove(s1); + buyOrders.remove(s1); + Orders.remove(s2); + sellOrders.remove(s2); + } else if (s3 == s1) { + Orders.remove(s1); + buyOrders.remove(s1); + } else if (s3 == s2) { + Orders.remove(s2); + sellOrders.remove(s2); + } + } + + // if any market orders are remaining then match them with limit + // orders + if (buyOrders.size() > 0) { + sellOrders = Orders.getOrders(Orders.LIMIT_SELL_ORDER, com.name); + while (buyOrders.size() > 0 && sellOrders.size() > 0) { + Shares s1 = buyOrders.get(0); + double min_diff = Double.MAX_VALUE; + Shares s2 = null; + for (Shares temp : sellOrders) { + double diff = Math.abs(temp.cost_limit - LTP); + if (diff < min_diff) { + min_diff = diff; + s2 = temp; + } + } + Shares s3 = MatchingEngine.matchMarketLimitOrders(s1, s2, com); + if (s3 == null) { + Orders.remove(s1); + buyOrders.remove(s1); + Orders.remove(s2); + sellOrders.remove(s2); + } else if (s3 == s1) { + Orders.remove(s1); + buyOrders.remove(s1); + } else if (s3 == s2) { + Orders.remove(s2); + sellOrders.remove(s2); + } + } + buyOrders = Orders.getOrders(Orders.LIMIT_BUY_ORDER, com.name); + } else if (sellOrders.size() > 0) { + buyOrders = Orders.getOrders(Orders.LIMIT_BUY_ORDER, com.name); + while (buyOrders.size() > 0 && sellOrders.size() > 0) { + Shares s2 = sellOrders.get(0); + Shares s1 = null; + double tradingPrice = LTP; + for (int loop = 0; loop < buyOrders.size(); loop++) { + if (buyOrders.get(loop).cost_limit >= LTP) { + s1 = buyOrders.get(loop); + break; + } + } + if (s1 == null) { + double min_diff = Double.MAX_VALUE; + for (Shares temp : buyOrders) { + double diff = Math.abs(temp.cost_limit - LTP); + if (diff < min_diff) { + min_diff = diff; + s1 = temp; + tradingPrice = s1.cost_limit; + } + } + } + Shares s3 = MatchingEngine.matchLimitMarketOrders(s1, s2, com, tradingPrice); + if (s3 == null) { + Orders.remove(s1); + buyOrders.remove(s1); + Orders.remove(s2); + sellOrders.remove(s2); + } else if (s3 == s1) { + Orders.remove(s1); + buyOrders.remove(s1); + } else if (s3 == s2) { + Orders.remove(s2); + sellOrders.remove(s2); + } + } + sellOrders = Orders.getOrders(Orders.LIMIT_SELL_ORDER, com.name); + } else { + buyOrders = Orders.getOrders(Orders.LIMIT_BUY_ORDER, com.name); + sellOrders = Orders.getOrders(Orders.LIMIT_SELL_ORDER, com.name); + } + + // match limit orders + int loop1 = 0, loop2 = 0; + while (loop1 < buyOrders.size() && sellOrders.size() > 0) { + Shares s1 = buyOrders.get(loop1); + Shares s2 = null; + for (loop2 = 0; loop2 < sellOrders.size(); loop2++) { + if (sellOrders.get(loop2).cost_limit <= s1.cost_limit) { + s2 = sellOrders.get(loop2); + break; + } + } + if (s2 == null) { + loop1++; + continue; + } + Shares s3 = MatchingEngine.matchLimitLimitOrders(s1, s2, com); + if (s3 == null) { + Orders.remove(s1); + loop1++; + Orders.remove(s2); + sellOrders.remove(s2); + } else if (s3 == s1) { + Orders.remove(s1); + loop1++; + } else if (s3 == s2) { + Orders.remove(s2); + sellOrders.remove(s2); + } + } + + com.sharevalue.add(MatchingEngine.LTP); + com.d = new Date(); + + try { + com.perchange = Double.valueOf(ShareMarket.twoDForm.format((com.sharevalue.get(com.sharevalue.size() - 1) - com.sharevalue.get(com.sharevalue.size() - 2)) * 100 / com.sharevalue.get(com.sharevalue.size() - 2))); + } catch (Exception mm) { + com.perchange = 0; + } + if (com.sharevalue.get(com.sharevalue.size() - 1) <= 0.0) { + com.bankrupt = true; + } + avg += com.sharevalue.get(com.sharevalue.size() - 1); + com.tsharessold += com.sharessold; + com.sharessoldpast = com.sharessold; + com.sharessold = 0; + com.setPricePrecision(MatchingEngine.calculatePrecision(com)); + } + ShareMarket.sensex = Double.valueOf(ShareMarket.twoDForm.format(avg / ShareMarket.companies.size())); + } + private static Shares matchMarketMarketOrders(Shares buyOrder, Shares sellOrder, Company comp, double LTP) { + return matchOrders(buyOrder, sellOrder, comp, LTP); + } + + private static Shares matchMarketLimitOrders(Shares buyOrder, Shares sellOrder, Company comp) { + return matchOrders(buyOrder, sellOrder, comp, sellOrder.cost_limit); + } + + private static Shares matchLimitMarketOrders(Shares buyOrder, Shares sellOrder, Company comp, double tradingPrice) { + return matchOrders(buyOrder, sellOrder, comp, tradingPrice); + } + + private static Shares matchLimitLimitOrders(Shares buyOrder, Shares sellOrder, Company comp) { + return matchOrders(buyOrder, sellOrder, comp, sellOrder.cost_limit); + } + + private static Shares matchOrders(Shares buyOrder, Shares sellOrder, Company comp, double tradingPrice) { + User buyer = buyOrder.user; + User seller = sellOrder.user; + synchronized (buyer) { + synchronized (seller) { + if (!buyOrder.notCanceled || buyer.isBanned() || !buyer.getPendingShares().contains(buyOrder)) { + buyOrder.status = "Canceled"; + return buyOrder; + } + + if (!sellOrder.notCanceled || seller.isBanned() || !seller.getPendingShares().contains(sellOrder)) { + sellOrder.status = "Canceled"; + return sellOrder; + } + + try { + assert tradingPrice > 0.0; + } catch (AssertionError e) { + e.printStackTrace(); + return new Shares(); + } + + double tot_price = Double.parseDouble(StockMart.twoDForm.format(tradingPrice * 1.02)); + + int min_shares = Math.min(buyOrder.qty_limit, sellOrder.qty_limit); + + int buyersAukaad = (int) (buyer.getCurrentMoney() / tot_price); + min_shares = Math.min(min_shares, buyersAukaad); + if (min_shares == 0) { + buyOrder.status = "Failed (Not Enough Money)"; + return buyOrder; + } + + Shares sellersCurrentShares = null; + for (int z = 0; z < seller.getCurrentShares().size(); z++) { + if (seller.getCurrentShares().get(z).company.equalsIgnoreCase(comp.name)) { + sellersCurrentShares = seller.getCurrentShares().get(z); + break; + } + } + + if (sellersCurrentShares == null || sellersCurrentShares.qty <= 0) { + sellOrder.status = "Failed (Not Enough Shares)"; + return sellOrder; + } + + min_shares = Math.min(min_shares, sellersCurrentShares.qty); + + boolean remove_buyer = false, remove_seller = false; + + // buyer gets shares + buyer.setCurrentMoney(buyer.getCurrentMoney() - Double.parseDouble(StockMart.twoDForm.format(tot_price * min_shares))); + comp.sharessold += min_shares; + if (min_shares == buyOrder.qty_limit) { + buyOrder.status = "Completed"; + remove_buyer = true; + } else if (min_shares == buyersAukaad) { + buyOrder.status = "Completed Partially (Not Enough Money)"; + remove_buyer = true; + } else { + buyOrder.status = "Completed Partially, Rest Pending"; + buyOrder.qty_limit -= min_shares; + } + int y = 0; + for (int z = 0; z < buyer.getCurrentShares().size(); z++) { + if (buyer.getCurrentShares().get(z).company.equalsIgnoreCase(comp.name)) { + buyer.getCurrentShares().get(z).cost = Double.parseDouble(StockMart.twoDForm.format((buyer.getCurrentShares().get(z).cost * buyer.getCurrentShares().get(z).qty + tradingPrice * min_shares) / (min_shares + buyer.getCurrentShares().get(z).qty))); + buyer.getCurrentShares().get(z).qty += min_shares; + buyer.getCurrentShares().get(z).buyed = new Date(); + y++; + break; + } + } + if (y == 0) { + Shares sh = new Shares(buyOrder); + sh.buyed = new Date(); + sh.cost = tradingPrice; + sh.qty = min_shares; + buyer.getCurrentShares().add(sh); + } + + // seller gets money + seller.setCurrentMoney(seller.getCurrentMoney() + Double.parseDouble(StockMart.twoDForm.format(tradingPrice * min_shares))); + if (min_shares == sellOrder.qty_limit) { + sellOrder.status = "Completed"; + remove_seller = true; + } else if (sellersCurrentShares.qty == min_shares) { + sellOrder.status = "Completed Partially (Not Enough Shares)"; + remove_seller = true; + } else { + sellOrder.status = "Completed Partially, Rest Pending"; + sellOrder.qty_limit -= min_shares; + } + if (sellersCurrentShares.qty - min_shares > 0) { + sellersCurrentShares.cost = Double.parseDouble(StockMart.twoDForm.format((sellersCurrentShares.cost * sellersCurrentShares.qty - tradingPrice * min_shares) / (sellersCurrentShares.qty - min_shares))); + sellersCurrentShares.qty -= min_shares; + } else { + seller.getCurrentShares().remove(sellersCurrentShares); + } + + MatchingEngine.LTP = tradingPrice; + + if (buyOrder.type == Orders.LIMIT_BUY_ORDER && sellOrder.type == Orders.LIMIT_SELL_ORDER) { + comp.nooflimitbidsmatched++; + } + + try { + ShareMarket.server.sendMessage(buyer, 5); + ShareMarket.server.sendMessage(seller, 5); + } catch (Exception hh) { + hh.printStackTrace(); + } + + if (remove_buyer && remove_seller) { + return null; + } else if (remove_buyer) { + return buyOrder; + } else if (remove_seller) { + return sellOrder; + } else { + System.out.println("Warning: neither buyer nor seller removed."); + return new Shares(); + } + } + } + } + + static double calculatePrecision(Company com) { + double mktvalue = com.sharevalue.get(com.sharevalue.size() - 1); + int noofdigits = noOfDigits((int) mktvalue); + int nooflimitorders = Orders.getNoOfLimitOrders(com.name); + if (com.nooflimitbidsmatched > 10 && nooflimitorders < 10) { + return Double.parseDouble(ShareMarket.twoDForm.format(Math.pow(10, noofdigits - 2) / 8)); + } else if (com.nooflimitbidsmatched > 5 && nooflimitorders < 10) { + return Double.parseDouble(ShareMarket.twoDForm.format(Math.pow(10, noofdigits - 2) / 4)); + } else if (com.nooflimitbidsmatched > 0 && nooflimitorders < 50) { + return Double.parseDouble(ShareMarket.twoDForm.format(Math.pow(10, noofdigits - 2) / 2)); + } else { + return Double.parseDouble(ShareMarket.twoDForm.format(Math.pow(10, noofdigits - 2))); + } + } + + static double getHighestPrecision(Company com) { + double mktvalue = com.sharevalue.get(com.sharevalue.size() - 1); + int noofdigits = noOfDigits((int) mktvalue); + return Double.parseDouble(ShareMarket.twoDForm.format(Math.pow(10, noofdigits - 2) / 8)); + } + + static int noOfDigits(int n) { + int i = 0; + while ((n = n / 10) > 0) { + i++; + } + return i; + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/Orders.java b/src/com/ayushmaanbhav/jstockmart/server/Orders.java new file mode 100644 index 0000000..6be1480 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/Orders.java @@ -0,0 +1,157 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.util.*; + +import com.ayushmaanbhav.jstockmart.user.Shares; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +class Orders { + public final static int MARKET_BUY_ORDER = 0; + public final static int MARKET_SELL_ORDER = 1; + public final static int LIMIT_BUY_ORDER = 2; + public final static int LIMIT_SELL_ORDER = 3; + + public static ArrayList limitBuyOrders, limitSellOrders; + public static ArrayList marketBuyOrders, marketSellOrders; + public static HashMap> stats; + + public Orders() { + limitBuyOrders = new ArrayList(); + limitSellOrders = new ArrayList(); + marketBuyOrders = new ArrayList(); + marketSellOrders = new ArrayList(); + stats = new HashMap>(ShareMarket.companies.size()); + for (Company comp : ShareMarket.companies) { + stats.put(comp.name, new TrippleArrayList()); + } + } + + public static boolean remove(Shares s) { + return limitBuyOrders.remove(s) || limitSellOrders.remove(s) || marketBuyOrders.remove(s) || marketSellOrders.remove(s); + } + + public static Shares remove(Integer id, Integer sellid, String status) { + for (Shares share : marketBuyOrders) { + if (share.id == id && share.sellid == sellid) { + marketBuyOrders.remove(share); + share.status = status; + return share; + } + } + for (Shares share : marketSellOrders) { + if (share.id == id && share.sellid == sellid) { + marketSellOrders.remove(share); + share.status = status; + return share; + } + } + for (Shares share : limitBuyOrders) { + if (share.id == id && share.sellid == sellid) { + limitBuyOrders.remove(share); + share.status = status; + return share; + } + } + for (Shares share : limitSellOrders) { + if (share.id == id && share.sellid == sellid) { + limitSellOrders.remove(share); + share.status = status; + return share; + } + } + return null; + } + + public static boolean contain(Shares s) { + return limitBuyOrders.contains(s) || limitSellOrders.contains(s) || marketBuyOrders.contains(s) || marketSellOrders.contains(s); + } + + public static ArrayList getOrders(int type, String comName) { + ArrayList list = new ArrayList(); + if (type == MARKET_BUY_ORDER) { + for (Shares share : marketBuyOrders) { + if (share.company.equals(comName)) + list.add(share); + } + } else if (type == MARKET_SELL_ORDER) { + for (Shares share : marketSellOrders) { + if (share.company.equals(comName)) + list.add(share); + } + } else if (type == LIMIT_BUY_ORDER) { + for (Shares share : limitBuyOrders) { + if (share.company.equals(comName)) + list.add(share); + } + } else if (type == LIMIT_SELL_ORDER) { + for (Shares share : limitSellOrders) { + if (share.company.equals(comName)) + list.add(share); + } + } + return list; + } + + public static void calculateLimitOrderStats() { + for (Company com : ShareMarket.companies) { + TrippleArrayList arr = stats.get(com.name); + arr.clear(); + for (Shares share : limitBuyOrders) { + if (share.company.equals(com.name)) { + int index = arr.containsSecondElement(share.cost_limit); + if (index != -1) + arr.setFirstElement(index, arr.getFirstElement(index) + share.qty_limit); + else + arr.add(share.qty_limit, share.cost_limit, 0); + } + } + for (Shares share : limitSellOrders) { + if (share.company.equals(com.name)) { + int index = arr.containsSecondElement(share.cost_limit); + if (index != -1) + arr.setThirdElement(index, arr.getThirdElement(index) + share.qty_limit); + else + arr.add(0, share.cost_limit, share.qty_limit); + } + } + } + } + + public static TrippleArrayList getLimitOrderStatsOfCompany(String comName) { + for (String key : stats.keySet()) { + if (key.equalsIgnoreCase(comName)) + return stats.get(key); + } + return new TrippleArrayList(); + } + + public static int getNoOfLimitOrders(String comName) { + int n = 0; + for (Shares share : limitBuyOrders) { + if (share.company.equals(comName)) + n++; + } + for (Shares share : limitSellOrders) { + if (share.company.equals(comName)) + n++; + } + return n; + } + + public static void printQueues() { + System.out.println("\nStatus of all the queues:"); + System.out.print("Limit Buy Orders: "); + System.out.println(limitBuyOrders.toString()); + System.out.print("Limit Sell Orders: "); + System.out.println(limitSellOrders.toString()); + System.out.print("Market Buy Orders: "); + System.out.println(marketBuyOrders.toString()); + System.out.print("Market Sell Orders: "); + System.out.println(marketSellOrders.toString()); + System.out.println("Stats:"); + for (Company c : ShareMarket.companies) { + System.out.print(c.name + ": "); + System.out.println(getLimitOrderStatsOfCompany(c.name).toString()); + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/OrdersPanel.java b/src/com/ayushmaanbhav/jstockmart/server/OrdersPanel.java new file mode 100644 index 0000000..6be2d88 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/OrdersPanel.java @@ -0,0 +1,169 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; + +import com.ayushmaanbhav.jstockmart.user.Shares; +import com.ayushmaanbhav.jstockmart.utils.ButtonColumn; + +public class OrdersPanel { + static JFrame frame; + static DefaultTableModel dtm; + static Action delete; + static JTable orders; + static String[] colNames = {"ID", "Sell ID", "User", "Curr Money", "No. of shares", "Ordered", "Type", "Limit Price", "Qty Limit", "Status", "Cancel"}; + static JScrollPane jspt; + static JComboBox combo; + static JButton refresh; + static JPanel panel; + + @SuppressWarnings("serial") + public static void main() { + dtm = new DefaultTableModel(colNames, 0); + orders = new JTable(dtm) { + public boolean isCellEditable(int row, int col) { + if (col == 10) + return true; + return false; + } + public boolean isCellSelected(int row, int col) { + return false; + } + }; + orders.setDragEnabled(false); + orders.setRowSelectionAllowed(false); + orders.setColumnSelectionAllowed(false); + // table.setShowHorizontalLines(true); + // table.setShowVerticalLines(true); + orders.setRowHeight(30); + orders.getTableHeader().setReorderingAllowed(false); + orders.setFillsViewportHeight(true); + jspt = new JScrollPane(orders); + delete = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + final int row = Integer.valueOf(e.getActionCommand()); + int res = JOptionPane.showConfirmDialog(null, "Are you sure ?", "Confirm:", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); + if (res == JOptionPane.YES_OPTION) { + Shares ss = Orders.remove((Integer) orders.getValueAt(row, 0), (Integer) orders.getValueAt(row, 1), "Canceled by Admin"); + if (ss != null) + ShareMarket.server.sendMessage(ss.user, 5); + } + } + }; + combo = new JComboBox(); + for (int i = 0; i < ShareMarket.companies.size(); i++) + combo.addItem(ShareMarket.companies.get(i).name); + combo.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + update((String) combo.getSelectedItem()); + } + } + }); + refresh = new JButton("Refresh"); + refresh.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + update((String) combo.getSelectedItem()); + } + }); + frame = new JFrame("Orders"); + panel = (JPanel) frame.getContentPane(); + panel.setLayout(new BorderLayout()); + panel.setPreferredSize(new Dimension(800, 500)); + panel.add(combo, BorderLayout.NORTH); + panel.add(jspt, BorderLayout.CENTER); + panel.add(refresh, BorderLayout.SOUTH); + frame.pack(); + frame.setVisible(true); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + combo.setSelectedIndex(0); + combo.requestFocus(); + } + }); + } + + public static void update(final String company) { + new Thread() { + public void run() { + Company comp = null; + for (Company temp : ShareMarket.companies) { + if (temp.name.equals(company)) { + comp = temp; + break; + } + } + ArrayList arr = new ArrayList(); + arr.add(new Object[]{"LIMIT_BUY_ORDERS:", null, null, null, null, null, null, null, null, null, null}); + ArrayList shares = Orders.getOrders(Orders.LIMIT_BUY_ORDER, comp.name); + for (Shares ss : shares) { + int noofshares = 0; + for (Shares pp : ss.user.getCurrentShares()) + if (pp.company.equals(comp.name)) + noofshares += pp.qty; + arr.add(new Object[]{ss.id, ss.sellid, ss.user.getName(), ss.user.getCurrentMoney(), noofshares, String.valueOf((ss.ordered.getTime() - StockMart.startDate.getTime()) / 60000) + " mins", "LIMIT_BUY_ORDER", ss.cost_limit, ss.qty_limit, ss.status, "Cancel"}); + } + arr.add(new Object[]{"LIMIT_SELL_ORDERS:", null, null, null, null, null, null, null, null, null, null}); + shares = Orders.getOrders(Orders.LIMIT_SELL_ORDER, comp.name); + for (Shares ss : shares) { + int noofshares = 0; + for (Shares pp : ss.user.getCurrentShares()) + if (pp.company.equals(comp.name)) + noofshares += pp.qty; + arr.add(new Object[]{ss.id, ss.sellid, ss.user.getName(), ss.user.getCurrentMoney(), noofshares, String.valueOf((ss.ordered.getTime() - StockMart.startDate.getTime()) / 60000) + " mins", "LIMIT_SELL_ORDER", ss.cost_limit, ss.qty_limit, ss.status, "Cancel"}); + } + arr.add(new Object[]{"MARKET_BUY_ORDERS:", null, null, null, null, null, null, null, null, null, null}); + shares = Orders.getOrders(Orders.MARKET_BUY_ORDER, comp.name); + for (Shares ss : shares) { + int noofshares = 0; + for (Shares pp : ss.user.getCurrentShares()) + if (pp.company.equals(comp.name)) + noofshares += pp.qty; + arr.add(new Object[]{ss.id, ss.sellid, ss.user.getName(), ss.user.getCurrentMoney(), noofshares, String.valueOf((ss.ordered.getTime() - StockMart.startDate.getTime()) / 60000) + " mins", "MARKET_BUY_ORDER", "N.A.", ss.qty_limit, ss.status, "Cancel"}); + } + arr.add(new Object[]{"MARKET_SELL_ORDERS:", null, null, null, null, null, null, null, null, null, null}); + shares = Orders.getOrders(Orders.MARKET_SELL_ORDER, comp.name); + for (Shares ss : shares) { + int noofshares = 0; + for (Shares pp : ss.user.getCurrentShares()) + if (pp.company.equals(comp.name)) + noofshares += pp.qty; + arr.add(new Object[]{ss.id, ss.sellid, ss.user.getName(), ss.user.getCurrentMoney(), noofshares, String.valueOf((ss.ordered.getTime() - StockMart.startDate.getTime()) / 60000) + " mins", "MARKET_SELL_ORDER", "N.A.", ss.qty_limit, ss.status, "Cancel"}); + } + final Object obj[][] = new Object[arr.size()][]; + for (int i = 0; i < arr.size(); i++) { + obj[i] = arr.get(i); + } + arr.clear(); + arr = null; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + dtm.setDataVector(obj, colNames); + new ButtonColumn(orders, delete, 10); + combo.requestFocus(); + } + }); + } + }.start(); + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/RankingServer.java b/src/com/ayushmaanbhav/jstockmart/server/RankingServer.java new file mode 100644 index 0000000..d44e245 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/RankingServer.java @@ -0,0 +1,147 @@ +package com.ayushmaanbhav.jstockmart.server; +import java.io.*; +import java.util.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.text.*; + +import javax.swing.*; + +import com.ayushmaanbhav.jstockmart.user.*; + +public class RankingServer extends Thread { + private long SECONDS = 30000; + List com; + Server server; + int close; + BufferedWriter bw; + BlockingQueue queue; + static boolean startWaiting = false; + + public RankingServer(String name, List c, Server s) throws IOException { + super(name); + setPriority(8); + com = c; + startWaiting = false; + server = s; + queue = new LinkedBlockingQueue(); + try { + bw = new BufferedWriter(new FileWriter("appdata/rank.txt")); + } catch (Exception mm) { + } + } + + DecimalFormat twoDForm = new DecimalFormat("#.##"); + public void run() { + close = 0; + while (true) { + if (close == 1) + break; + try { + StringBuffer dString = new StringBuffer(); + dString.append(Commands.RANKS); + dString.append("::"); + rankUsers(); + for (int i = UserDatabase.userList.size() - 1; i >= 0; i--) { + User user = UserDatabase.userList.get(i); + if (!user.isBanned()) { + dString.append(user.getName()); + dString.append("-"); + dString.append(twoDForm.format(user.getScore())); + dString.append(":"); + } + } + // final String sss=dString; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + StringBuffer jj = new StringBuffer(); + for (int i = UserDatabase.userList.size() - 1; i >= 0; i--) { + User user = UserDatabase.userList.get(i); + jj.append(UserDatabase.userList.size() - i); + jj.append(" ) "); + jj.append(user.getName()); + jj.append("->"); + jj.append(twoDForm.format(user.getScore())); + jj.append("\n"); + } + StockMart.ranks.setText(jj.toString()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + StockMart.jkps.getVerticalScrollBar().setValue(0); + } + }); + } + }); + server.sendMulti(dString.toString(), Thread.MIN_PRIORITY); + try { + bw.write(new Date().toString() + ":" + dString + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + if (startWaiting) { + queue.take(); + } else { + try { + sleep(SECONDS); + } catch (InterruptedException e) { + } + } + } catch (Exception e) { + e.printStackTrace(); + return; + } + } + } + + synchronized void rankUsers() { + calculateScores(); + sortUsers(); + } + + synchronized private void calculateScores() { + synchronized (UserDatabase.userList) { + synchronized (com) { + for (int i = 0; i < UserDatabase.userList.size(); i++) { + User key = UserDatabase.userList.get(i); + key.setScore(calculateUserScore(key)); + } + } + } + } + + synchronized private void sortUsers() { + synchronized (UserDatabase.userList) { + for (int i = 0; i < UserDatabase.userList.size(); i++) { + User key = UserDatabase.userList.get(i); + int j; + for (j = i - 1; j >= 0; j--) { + if ((UserDatabase.userList.get(j).getScore() > key.getScore() && !UserDatabase.userList.get(j).isBanned()) || key.isBanned()) + UserDatabase.userList.set(j + 1, UserDatabase.userList.get(j)); + else + break; + } + UserDatabase.userList.set(j + 1, key); + } + + } + } + + synchronized private double calculateUserScore(User u) { + synchronized (u) { + double mon = Double.valueOf(twoDForm.format(u.getCurrentMoney())); + double score = mon; + List list = u.getCurrentShares(); + for (int i = 0; i < list.size(); i++) { + String name = list.get(i).company; + for (int j = 0; j < com.size(); j++) { + if (com.get(j).name.equalsIgnoreCase(name)) { + score = score + Double.valueOf(twoDForm.format(com.get(j).sharevalue.get(com.get(j).sharevalue.size() - 1) * list.get(i).qty)); + break; + } + } + } + return Double.valueOf(twoDForm.format(score)); + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/Server.java b/src/com/ayushmaanbhav/jstockmart/server/Server.java new file mode 100644 index 0000000..7e13531 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/Server.java @@ -0,0 +1,693 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.io.*; + +import javax.swing.*; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.ayushmaanbhav.jstockmart.utils.TrippleArrayList; + +import java.net.*; +import java.util.*; +import java.util.concurrent.*; + +public class Server { + + private ServerSocket serverSocket; + private boolean started; + private Thread serverThread; + volatile int clientCount; + ChatServer chat; + static StringBuffer chatHist; + List companies; + List clientList; + volatile static int id = 0; + + abstract class Thread1 extends Thread { + volatile protected User user; + abstract public void sendMessage(Object mess, int priority); + } + + public Server(List comp) throws IOException { + companies = comp; + serverSocket = new ServerSocket(4446, 20000); + serverSocket.setReuseAddress(true); + chat = new ChatServer(this); + clientList = new ArrayList(); + clientCount = 0; + chatHist = new StringBuffer(); + } + + // This server starts on a seperate thread so you can still do other things + // on the server program + public void startServer() { + if (!started) { + started = true; + serverThread = new Thread() { + public void run() { + while (Server.this.started) { + Socket clientSocket = null; + try { + clientSocket = serverSocket.accept(); + openClient(clientSocket); + try { + Thread.sleep(50); + } catch (Exception n) { + } + } catch (SocketException e) { + System.err.println("Server closed."); + } catch (IOException e) { + System.err.println("Accept failed."); + } + } + } + }; + serverThread.setPriority(7); + serverThread.start(); + chat.start(); + } + } + + @SuppressWarnings("deprecation") + public void stopServer() { + this.started = false; + serverThread.interrupt(); + try { + serverSocket.close(); + } catch (IOException ex) { + System.err.println("Server stop failed."); + } + chat.stop(); + } + + synchronized public void sendMulti(String mess, int priority) { + String copy = new String(mess); + for (int i = 0; i < clientList.size(); i++) { + if (clientList.get(i).isAlive()) + clientList.get(i).sendMessage(copy, priority); + else + clientList.remove(i--); + } + } + + synchronized public void sendPeriodicStats(int priority) { + for (Company comp : ShareMarket.companies) { + Object message = new TrippleArrayList(Orders.getLimitOrderStatsOfCompany(comp.name)); + for (int i = 0; i < clientList.size(); i++) { + if (clientList.get(i).isAlive() && clientList.get(i).user != null && clientList.get(i).user.sendStats != null && clientList.get(i).user.sendStats.equalsIgnoreCase(comp.name)) + clientList.get(i).sendMessage(message, priority); + } + } + } + + synchronized public void sendMessage(User user, int priority) { + for (int i = 0; i < clientList.size(); i++) { + if (clientList.get(i).user.checkName(user.getName())) { + if (clientList.get(i).isAlive()) + clientList.get(i).sendMessage(new User(user), priority); + else + clientList.remove(i--); + break; + } + } + } + + public void openClient(final Socket socket) { + clientCount++; + Thread1 g = new Thread1() { + BufferedWriter bw; + BufferedReader in; + ObjectOutputStream objout; + volatile protected boolean loggedIn = false; + Object obj = new Object(); + + public void run() { + user = null; + try { + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + objout = new ObjectOutputStream(socket.getOutputStream()); + String inputLine = null; + do { + try { + inputLine = (String) in.readLine(); + } catch (IOException e) { + break; + } + processCommand(inputLine); + } while (in != null && inputLine != null); + objout.close(); + in.close(); + socket.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + void processCommand(final String command1) { + final String cmdid = command1.split(";")[0]; + String command = command1.toLowerCase().split(";")[1]; + String cmmd[] = command.split(":"); + for (int i = 0; i < cmmd.length; i++) + cmmd[i] = cmmd[i].trim(); + + if (cmmd[0].equals(Commands.REGISTER)) { + int res = UserDatabase.registerUser(cmmd[1], cmmd[2], cmmd[3]); + if (res == 1) { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("1:rs")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String(res + ":wrn")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + try { + in.close(); + objout.close(); + socket.close(); + return; + } catch (Exception e) { + in = null; + objout = null; + return; + } + } else if (cmmd[0].equals(Commands.LOG_IN)) { + int res = UserDatabase.validate(cmmd[1], cmmd[2]); + if (res == 0 && !UserDatabase.getUser(cmmd[1], cmmd[2]).isBanned()) { + user = UserDatabase.getUser(cmmd[1], cmmd[2]); + loggedIn = true; + try { + bw = new BufferedWriter(new FileWriter("appdata/userdata/" + user.getName() + ".txt", true)); + } catch (Exception mm) { + } + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("0:s")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + bw.write(new Date().toString() + ":loggedin\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + BroadcastServer.sendFullDetails = true; + } else { + if (user != null) { + loggedIn = false; + } + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String(res + ":f")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + in.close(); + objout.close(); + socket.close(); + return; + } catch (Exception e) { + in = null; + objout = null; + return; + } + } + } else if (cmmd[0].equals(Commands.LOG_OUT)) { + if (user != null) { + loggedIn = false; + } + clientCount--; + clientList.remove(this); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("1")); + objout.flush(); + + } catch (Exception e) { + } + } + try { + bw.write(new Date().toString() + ":loggedout\n"); + bw.flush(); + bw.close(); + bw = null; + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + in.close(); + objout.close(); + socket.close(); + return; + } catch (Exception e) { + in = null; + objout = null; + return; + } + } else if (user != null && loggedIn && !user.isBanned()) { + if (cmmd[0].equals(Commands.GET_USER_DETAILS)) { + try { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new User(user)); + objout.flush(); + + clientList.add(this); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.SEND_CHAT_MESSAGE)) { + // System.out.println("got chat"); + if (user.chatEnabled && user.getChat() >= 0) { + if (user.getChat() - command1.substring(command1.indexOf(":") + 1).length() >= 0) { + user.setChat(user.getChat() - command1.substring(command1.indexOf(":") + 1).length()); + chatHist.append("<"); + chatHist.append(user.getName()); + chatHist.append("> : "); + chatHist.append(command1.substring(command1.indexOf(":") + 1)); + chatHist.append("\n"); + chat.chaat.append("<"); + chat.chaat.append(user.getName()); + chat.chaat.append("> : "); + chat.chaat.append(command1.substring(command1.indexOf(":") + 1)); + chat.chaat.append("\n");; + new Thread() { + public void run() { + chat.interrupt(); + } + }.start(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + StockMart.chat.setText(chatHist.toString()); + } + }); + } + } + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(Integer.toString(user.getChat())); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (cmmd[0].equals(Commands.GET_CHAT_HISTORY)) { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String(chatHist.toString())); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (cmmd[0].equals(Commands.SEND_FULL_BROADCAST)) { + synchronized (obj) { + try { + BroadcastServer.sendFullDetails = true; + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("1")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (cmmd[0].equals(Commands.SEND_PERIODIC_STATS)) { + try { + user.sendStats = cmmd[1].trim(); + if (cmmd[1].trim().equals("-1")) + user.sendStats = null; + } catch (Exception e) { + e.printStackTrace(); + } + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("1")); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (cmmd[0].equals(Commands.GET_COMPANY_STATS)) { + try { + TrippleArrayList arr = Orders.getLimitOrderStatsOfCompany(cmmd[1].trim()); + if (user.sendStats != null) + user.sendStats = cmmd[1].trim(); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new TrippleArrayList(arr)); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.GET_COMPANY_HISTORY)) { + try { + Company comp = null; + for (int k = 0; k < companies.size(); k++) { + if (companies.get(k).name.equalsIgnoreCase(cmmd[1].trim())) { + comp = companies.get(k); + break; + } + } + if (comp != null && Integer.parseInt(cmmd[2].trim()) != comp.sharevalue.size()) { + synchronized (obj) { + try { + objout.flush(); + objout.reset(); + objout.writeObject(new String(cmdid)); + ArrayList al = new ArrayList(comp.sharevalue); + objout.writeObject(al); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new ArrayList()); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } else if (StockMart.started) { + if (cmmd[0].equals(Commands.LIMIT_BUY_ORDER)) { + final Shares share = new Shares(); + share.type = Orders.LIMIT_BUY_ORDER; + share.company = command1.split(":")[1].trim(); + share.qty_limit = Integer.parseInt(cmmd[2]); + share.cost_limit = Double.parseDouble(cmmd[3]); + share.id = id++; + share.cost = -1.0; + share.sellid = -1; + share.buyed = null; + share.ordered = new Date(); + share.status = "Shares Pending"; + share.notCanceled = true; + share.user = user; + + Orders.limitBuyOrders.add(share); + + try { + user.getPendingShares().add(share); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(share); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + bw.write(new Date().toString() + ":buyl:" + share.id + ":" + share.company + ":" + share.qty_limit + ":" + share.cost_limit + ":" + share.status + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.MARKET_BUY_ORDER)) { + final Shares share = new Shares(); + share.type = Orders.MARKET_BUY_ORDER; + share.company = command1.split(":")[1].trim(); + share.qty_limit = Integer.parseInt(cmmd[2]); + share.id = id++; + share.cost = -1.0; + share.sellid = -1; + share.buyed = null; + share.ordered = new Date(); + share.status = "Shares Pending"; + share.notCanceled = true; + share.user = user; + + // System.out.println("made share"); + Orders.marketBuyOrders.add(share); + + try { + user.getPendingShares().add(share); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(share); + objout.flush(); + // System.out.println("sent share"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + bw.write(new Date().toString() + ":buym:" + share.id + ":" + share.company + ":" + share.qty_limit + ":" + share.cost_limit + ":" + share.status + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.LIMIT_SELL_ORDER)) { + final Shares share = new Shares(); + share.type = Orders.LIMIT_SELL_ORDER; + share.company = command1.split(":")[1].trim(); + share.qty_limit = Integer.parseInt(cmmd[2]); + share.cost_limit = Double.parseDouble(cmmd[3]); + share.id = Integer.parseInt(cmmd[4]); + share.sellid = id++; + share.cost = -1.0; + share.ordered = new Date(); + share.status = "Payment Pending"; + share.notCanceled = true; + share.user = user; + + Orders.limitSellOrders.add(share); + + try { + user.getPendingShares().add(share); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(share); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + bw.write(new Date().toString() + ":selll:" + share.id + ":" + share.sellid + ":" + share.company + ":" + share.qty_limit + ":" + share.cost_limit + ":" + share.status + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.MARKET_SELL_ORDER)) { + final Shares share = new Shares(); + share.type = Orders.MARKET_SELL_ORDER; + share.company = command1.split(":")[1].trim(); + share.qty_limit = Integer.parseInt(cmmd[2]); + share.id = Integer.parseInt(cmmd[4]); + share.sellid = id++; + share.cost = -1.0; + share.ordered = new Date(); + share.status = "Payment Pending"; + share.notCanceled = true; + share.user = user; + + Orders.marketSellOrders.add(share); + + try { + user.getPendingShares().add(share); + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(share); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + bw.write(new Date().toString() + ":sellm:" + share.id + ":" + share.sellid + ":" + share.company + ":" + share.qty_limit + ":" + share.cost_limit + ":" + share.status + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } else if (cmmd[0].equals(Commands.CANCEL_ORDER)) { + try { + int id = Integer.parseInt(cmmd[1]); + int sellid = Integer.parseInt(cmmd[2]); + Shares sh = null; + for (int i = 0; i < user.getPendingShares().size(); i++) { + if (user.getPendingShares().get(i).id == id && user.getPendingShares().get(i).sellid == sellid) { + sh = user.getPendingShares().get(i); + break; + } + } + + if (sh != null && Orders.contain(sh)) { + sh.notCanceled = false; + sh.status = "Cancelled"; + Orders.remove(sh); + + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("1")); + objout.flush(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String("0")); + objout.flush(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + try { + bw.write(new Date().toString() + ":cancel:" + sh.id + ":" + sh.sellid + ":" + sh.company + ":" + sh.qty_limit + ":" + sh.cost_limit + ":" + sh.status + "\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } catch (Exception ef) { + ef.printStackTrace(); + } + } + } else { + synchronized (obj) { + try { + objout.writeObject(new String(cmdid)); + objout.writeObject(new String(Commands.SERVER_NOT_RUNNING)); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } else { + clientCount--; + clientList.remove(this); + try { + loggedIn = false; + synchronized (obj) { + try { + System.out.println(command1); + objout.writeObject(new String(Commands.UNKNOWN_COMMAND)); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + in.close(); + objout.close(); + socket.close(); + user = null; + return; + } catch (Exception e) { + in = null; + objout = null; + return; + } + } + } + boolean firsttime = true; + BlockingQueue toSend = new LinkedBlockingQueue(); + Thread sender; + public void sendMessage(Object mess, int priority) { + try { + sender.setPriority(priority); + } catch (Exception m) { + } + toSend.offer(mess); + // System.out.println("offered: " + mess.toString()); + if (firsttime && loggedIn) { + sender = new Thread() { + public void run() { + while (loggedIn) { + Object object = null; + try { + object = toSend.take(); + } catch (Exception e) { + e.printStackTrace(); + } + if (object != null) { + synchronized (obj) { + try { + objout.writeObject(object); + objout.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }; + sender.setPriority(Thread.NORM_PRIORITY); + sender.start(); + firsttime = false; + } + } + }; + g.setPriority(Thread.NORM_PRIORITY); + g.start(); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/ShareMarket.java b/src/com/ayushmaanbhav/jstockmart/server/ShareMarket.java new file mode 100644 index 0000000..9ab7675 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/ShareMarket.java @@ -0,0 +1,172 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.util.*; +import java.io.*; +import java.text.*; + +import javax.swing.*; + +class ShareMarket { + volatile static List companies; + static Server server; + BroadcastServer bserver; + RankingServer rserver; + volatile static double sensex; + boolean testing = false; + Orders orderbook; + Thread calculations; + final int SLEEP = 30000; + volatile int loopp = 1; + static DecimalFormat twoDForm = new DecimalFormat("#.##"); + BufferedWriter bw; + double T, N; + + void initialise() { + companies = new ArrayList(); + loadCompanies(); + UserDatabase.loadList(); + try { + bw = new BufferedWriter(new FileWriter("appdata/sharemarket.txt")); + } catch (Exception mm) { + } + } + + void startApp() { + orderbook = new Orders(); + try { + bw.write(new Date().toString() + ":app started\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + server = new Server(companies); + } catch (Exception m) { + m.printStackTrace(); + } + server.startServer(); + try { + bserver = new BroadcastServer("Share Market Broadcast", companies, server); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + rserver = new RankingServer("Share Market Ranks Broadcast", companies, server); + } catch (Exception mm) { + mm.printStackTrace(); + } + rserver.start(); + } + + void start() { + try { + bw.write(new Date().toString() + ":market started\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + loopp = 0; + bserver.start(); + bserver.queue.clear(); + bserver.queue.offer(loopp); + RankingServer.startWaiting = true; + calculations = new Thread() { + public void run() { + T = StockMart.totTime; + N = (int) (T * 2); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + StockMart.updateCompanyTable(); + /* + * if(GraphPanel.frame.isVisible()) + * GraphPanel.mainPanel.repaint(); + */ + } catch (Exception r) { + r.printStackTrace(); + } + } + }); + while (StockMart.started) { + try { + Thread.sleep(SLEEP); + } catch (Exception mm) { + } + Orders.calculateLimitOrderStats(); + if (testing) + Orders.printQueues(); + synchronized (companies) { + MatchingEngine.matchOrders(); + } + bserver.queue.offer(++loopp); + rserver.queue.offer(loopp); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + StockMart.updateCompanyTable(); + if (GraphPanel.frame.isVisible()) + GraphPanel.mainPanel.repaint(); + if (HistogramPanel.frame.isVisible()) + HistogramPanel.mainPanel.updatePanel(); + } catch (Exception r) { + r.printStackTrace(); + } + } + }); + for (int i = 0; i < companies.size(); i++) { + companies.get(i).updateFile(); + } + } + } + }; + calculations.setPriority(Thread.MAX_PRIORITY); + calculations.start(); + } + + void loadCompanies() { + try { + BufferedReader br = new BufferedReader(new FileReader("companies.txt")); + String str; + while ((str = br.readLine()) != null) { + String s[] = str.trim().split(":"); + List l = new ArrayList(); + l.add(Double.parseDouble(s[1])); + // companies.add(new + // Company(s[0],l,0,Integer.parseInt(s[2]),Double.parseDouble(s[3]),Double.parseDouble(s[4]))); + companies.add(new Company(s[0], l, 0, 0, 0.0005, 0.03162277660168379331998893544433)); + } + br.close(); + } catch (Exception m) { + m.printStackTrace(); + } + } + + @SuppressWarnings("deprecation") + void stop() { + try { + bw.write(new Date().toString() + ":market stopped\n"); + bw.flush(); + } catch (Exception mm) { + mm.printStackTrace(); + } + try { + server.stopServer(); + } catch (Exception m) { + } + try { + bserver.close = 1; + bserver.queue.offer(loopp); + } catch (Exception m) { + } + try { + RankingServer.startWaiting = false; + rserver.close = 1; + rserver.queue.offer(1); + } catch (Exception m) { + } + try { + calculations.stop(); + } catch (Exception m) { + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/server/StockMart.java b/src/com/ayushmaanbhav/jstockmart/server/StockMart.java new file mode 100644 index 0000000..cac3504 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/StockMart.java @@ -0,0 +1,513 @@ +package com.ayushmaanbhav.jstockmart.server; + +import javax.swing.*; +import javax.swing.table.*; + +import com.ayushmaanbhav.jstockmart.user.*; +import com.ayushmaanbhav.jstockmart.utils.LookAndFeel; + +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.Date; + +class StockMart { + static JPanel puser, mpanel; + static JLabel userd, sensex; + static JTextArea chat, ranks, news; + static JScrollPane jkps; + static JTable usertable, comptable; + static DefaultTableModel dtmu, dtmc; + static JTextField cht, ucht, addmoney, tt; + static JCheckBox chatEnabled; + @SuppressWarnings("rawtypes") + static JComboBox users; + static JFrame jf; + static String newsfeed = ""; + static ShareMarket shr; + static JButton server, post, changep, banu, checkRN; + static String colusr[] = new String[]{"SrNo.", "Company", "Price (Limit)", "Quantity (Limit)", "Ordered/Buyed", "Mkt Value/Type", "Status", "Gain/Loss"}; + static String[] columnNames2 = {"Srno.", "Company", "C.M.P.", "%Change", "Low", "High", "Stock Traded", "Total Stock Traded", "Total Stock"}; + static DecimalFormat twoDForm = new DecimalFormat("#.##"); + static boolean started = false, checkRegNo = true; + static int totTime; + static User uuu; + static Date startDate; + @SuppressWarnings("serial") + static DefaultTableCellRenderer dtr = new DefaultTableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value.toString().indexOf("-") != -1) { + value = value.toString() + " \u25bc"; + } else { + value = value.toString() + " \u25b2"; + } + Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (value.toString().indexOf("-") != -1) { + c.setForeground(Color.red); + } else { + c.setForeground(Color.green); + } + return c; + } + }; + static Timer timer2 = new Timer(1000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + int secs = (int) (totTime * 60 - (new Date().getTime() - startDate.getTime()) / 1000); + int hrs = secs / 3600; + int mins = (secs / 60) - hrs * 60; + sensex.setText("Sensex: " + ShareMarket.sensex + " Time Left: " + hrs + ":" + mins); + if (hrs <= 0 && mins <= 0) { + started = false; + server.setText("Start"); + // shr.stop(); + timer2.stop(); + finalize1(); + } + } catch (Exception bb) { + } + } + }); + static Timer timer = new Timer(10000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + uuu = UserDatabase.getUserWithName((String) users.getSelectedItem()); + userd.setText("
User->RegNo: " + uuu.getRegNo() + ";Name: " + uuu.getName() + ";Password: " + uuu.getPassword() + "
Money: " + twoDForm.format(uuu.getCurrentMoney()) + ";Chat: " + uuu.getChat() + "
"); + // ucht.setText(uuu.getChat()+""); + chatEnabled.setSelected(uuu.chatEnabled); + if (!uuu.isBanned()) + banu.setText("Ban User"); + else + banu.setText("Unban User"); + refreshUserTable(uuu); + } catch (Exception n) { + users.removeItem((String) users.getSelectedItem()); + } + } + }); + + public static void refreshUserTable(User u) { + Object obj[][] = new Object[u.getCurrentShares().size() + u.getPendingShares().size() + 1][8]; + java.util.List ss = u.getCurrentShares(); + for (int i = 0; i < u.getCurrentShares().size(); i++) { + Company comp = null; + for (int j = 0; j < ShareMarket.companies.size(); j++) { + if (ShareMarket.companies.get(j).name.equals(ss.get(i).company)) { + comp = ShareMarket.companies.get(j); + break; + } + } + obj[i] = new Object[]{Integer.toString(i + 1), ss.get(i).company, twoDForm.format(ss.get(i).cost), ss.get(i).qty, String.valueOf((ss.get(i).buyed.getTime() - startDate.getTime()) / 60000) + " mins", twoDForm.format(ss.get(i).qty * comp.sharevalue.get(comp.sharevalue.size() - 1)), ss.get(i).status, twoDForm.format(ss.get(i).qty * comp.sharevalue.get(comp.sharevalue.size() - 1) - ss.get(i).qty * ss.get(i).cost)}; + } + obj[u.getCurrentShares().size()] = new Object[]{null, null, null, null, null, null, null, null}; + ss = u.getPendingShares(); + for (int i = 0; i < u.getPendingShares().size(); i++) { + String type = "", costLimit = "Not Applicable"; + switch (ss.get(i).type) { + case Orders.MARKET_BUY_ORDER : + type = "Market Buy Order"; + break; + case Orders.MARKET_SELL_ORDER : + type = "Market Sell Order"; + break; + case Orders.LIMIT_BUY_ORDER : + type = "Limit Buy Order"; + costLimit = String.valueOf(ss.get(i).cost_limit); + break; + case Orders.LIMIT_SELL_ORDER : + type = "Limit Sell Order"; + costLimit = String.valueOf(ss.get(i).cost_limit); + break; + } + obj[i + u.getCurrentShares().size() + 1] = new Object[]{Integer.toString(i + 1), ss.get(i).company, costLimit, ss.get(i).qty_limit, String.valueOf((ss.get(i).ordered.getTime() - startDate.getTime()) / 60000) + " mins", type, ss.get(i).status, null}; + } + dtmu.setDataVector(obj, colusr); + } + + public static void updateCompanyTable() { + try { + Object data[][] = new Object[ShareMarket.companies.size()][9]; + for (int i = 0; i < ShareMarket.companies.size(); i++) { + data[i] = new Object[]{Integer.toString(i + 1), ShareMarket.companies.get(i).name, twoDForm.format(ShareMarket.companies.get(i).sharevalue.get(ShareMarket.companies.get(i).sharevalue.size() - 1)), twoDForm.format(ShareMarket.companies.get(i).perchange), twoDForm.format(ShareMarket.companies.get(i).getLowest()), twoDForm.format(ShareMarket.companies.get(i).getHighest()), ShareMarket.companies.get(i).sharessoldpast, ShareMarket.companies.get(i).tsharessold, ShareMarket.companies.get(i).totalshares}; + } + dtmc.setDataVector(data, columnNames2); + comptable.getColumnModel().getColumn(3).setCellRenderer(dtr); + comptable.repaint(); + } catch (Exception mm) { + mm.printStackTrace(); + } + } + + public static void main(String args[]) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + initialise(); + shr = new ShareMarket(); + shr.initialise(); + shr.startApp(); + timer.start(); + server.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!started) { + started = true; + startDate = new Date(); + totTime = Integer.parseInt(tt.getText()); + server.setText("Stop"); + shr.start(); + timer2.start(); + GraphPanel.main(); + HistogramPanel.main(); + OrdersPanel.main(); + } else { + started = false; + server.setText("Start"); + // shr.stop(); + timer2.stop(); + finalize1(); + // GraphPanel.frame.setVisible(false); + } + } + }); + } + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void finalize1() { + new Thread() { + public void run() { + shr.rserver.rankUsers(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + final JDialog jd = new JDialog(); + jd.setTitle("Confirm Final Rankings"); + jd.setUndecorated(false); + final JComboBox j1 = new JComboBox(), j2 = new JComboBox(), j3 = new JComboBox(); + for (int i = UserDatabase.userList.size() - 1; i >= 0; i--) { + j1.addItem(UserDatabase.userList.get(i).getName()); + j2.addItem(UserDatabase.userList.get(i).getName()); + j3.addItem(UserDatabase.userList.get(i).getName()); + } + try { + j1.setSelectedIndex(0); + j2.setSelectedIndex(1); + j3.setSelectedIndex(2); + } catch (Exception n) { + } + JPanel pan2 = new JPanel(new BorderLayout()); + pan2.add(j1, BorderLayout.NORTH); + pan2.add(j2, BorderLayout.CENTER); + pan2.add(j3, BorderLayout.SOUTH); + JLabel label = new JLabel("Confirm final rankings to send to users:"); + JPanel pan = new JPanel(new BorderLayout()); + pan.add(label, BorderLayout.NORTH); + pan.add(pan2, BorderLayout.CENTER); + JButton ok = new JButton("Ok"), can = new JButton("Cancel"); + ok.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ShareMarket.server.sendMulti(Commands.FINAL_RANKINGS + "::" + j1.getSelectedItem() + ":" + j2.getSelectedItem() + ":" + j3.getSelectedItem(), Thread.MIN_PRIORITY); + jd.setVisible(false); + } + }); + can.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jd.setVisible(false); + } + }); + JPanel pan3 = new JPanel(new BorderLayout()); + pan3.add(can, BorderLayout.EAST); + pan3.add(ok, BorderLayout.WEST); + pan.add(pan3, BorderLayout.SOUTH); + jd.setContentPane(pan); + jd.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); + jd.pack(); + jd.setLocationRelativeTo(null); + jd.setVisible(true); + } + }); + } + }.start(); + } + + @SuppressWarnings({"rawtypes", "serial"}) + public static void initialise() { + LookAndFeel.set(); + jf = new JFrame("StockMart"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mpanel = (JPanel) jf.getContentPane(); + mpanel.setLayout(new BorderLayout()); + post = new JButton("Post"); + post.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + newsfeed = news.getText().trim().replace("\n", ":"); + ShareMarket.server.chat.interrupt(); + } catch (Exception ppp) { + } + } + }); + server = new JButton("Start"); + userd = new JLabel("User-> RegNo: Name: Password: Money: Chat: "); + userd.setPreferredSize(new Dimension(300, 25)); + sensex = new JLabel("Sensex: Time Left: "); + tt = new JTextField(5); + tt.setText("120"); + news = new JTextArea(5, 30); + chat = new JTextArea(5, 30); + chat.setFont(new Font("Calibri", Font.PLAIN, 14)); + chat.setForeground(Color.green.darker()); + chat.setEditable(false); + chat.setLineWrap(true); + ranks = new JTextArea(5, 50); + ranks.setEditable(false); + ranks.setForeground(Color.red.darker()); + ranks.setFont(new Font("Calibri", Font.PLAIN, 14)); + ranks.setLineWrap(true); + cht = new JTextField(30); + ucht = new JTextField(10); + addmoney = new JTextField(10); + users = new JComboBox(); + chatEnabled = new JCheckBox("ChatEnabled", true); + dtmu = new DefaultTableModel(); + dtmc = new DefaultTableModel(); + usertable = new JTable(dtmu) { + public boolean isCellEditable(int r, int c) { + return false; + } + }; + comptable = new JTable(dtmc) { + public boolean isCellEditable(int r, int c) { + // if (c == 2) + // return true; + return false; + } + }; + /* + * dtmc.addTableModelListener(new TableModelListener() { public void + * tableChanged(TableModelEvent tme) { final int row = + * tme.getFirstRow(); try { if (tme.getColumn() == 2) { new Thread() { + * public void run() { try { if (JOptionPane.showConfirmDialog(jf, + * "Are you sure ?", "Confirm Value Change", JOptionPane.YES_NO_OPTION) + * == JOptionPane.YES_OPTION) + * ShareMarket.companies.get(row).futurevalues.add(0, + * Double.parseDouble( + * twoDForm.format(Double.valueOf(dtmc.getValueAt(row, + * 2).toString())))); } catch (Exception m) { m.printStackTrace(); } } + * }.start(); } } catch (Exception m) { m.printStackTrace(); } } }); + */ + usertable.setRowHeight(30); + usertable.getTableHeader().setReorderingAllowed(false); + usertable.setFillsViewportHeight(true); + comptable.setRowHeight(30); + comptable.getTableHeader().setReorderingAllowed(false); + comptable.setFillsViewportHeight(true); + JScrollPane jspu = new JScrollPane(usertable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + JScrollPane jspc = new JScrollPane(comptable); + + JPanel chatp = new JPanel(new BorderLayout()); + chatp.setPreferredSize(new Dimension(300, 300)); + chatp.add(new JScrollPane(chat, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); + chatp.add(cht, BorderLayout.SOUTH); + JPanel rr = new JPanel(new BorderLayout()); + rr.setPreferredSize(new Dimension(300, 250)); + jkps = new JScrollPane(ranks, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + rr.add(jkps, BorderLayout.CENTER); + JPanel rank = new JPanel(new BorderLayout()); + rank.setPreferredSize(new Dimension(600, 250)); + rank.add(chatp, BorderLayout.WEST); + rank.add(rr, BorderLayout.EAST); + + changep = new JButton("Change Password"); + banu = new JButton("Ban User"); + JButton deleteu = new JButton("Delete User"); + + JPanel jpaa = new JPanel(); + jpaa.setLayout(new FlowLayout(FlowLayout.LEFT)); + jpaa.add(changep); + jpaa.add(banu); + jpaa.add(deleteu); + jpaa.add(ucht); + jpaa.add(addmoney); + + JPanel jp = new JPanel(); + jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); // + // jp.setAlignmentX( Component.LEFT_ALIGNMENT ); + userd.setAlignmentX(Component.LEFT_ALIGNMENT); + users.setAlignmentX(Component.LEFT_ALIGNMENT); + jpaa.setAlignmentX(Component.LEFT_ALIGNMENT); + chatEnabled.setAlignmentX(Component.LEFT_ALIGNMENT); + jspu.setAlignmentX(Component.LEFT_ALIGNMENT); + jp.add(users); + jp.add(userd); + jp.add(jpaa); + // jp.add(changep); + // jp.add(ucht); + jp.add(chatEnabled); + jp.add(jspu); + + JPanel newspanel = new JPanel(new BorderLayout()); + newspanel.add(new JScrollPane(news, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); + newspanel.add(post, BorderLayout.EAST); + + puser = new JPanel(new BorderLayout()); + puser.add(rank, BorderLayout.NORTH); + puser.add(jp, BorderLayout.CENTER); + + checkRN = new JButton("UNCHKRegNo"); + checkRN.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + checkRegNo = !checkRegNo; + if (checkRegNo) + checkRN.setText("UNCHKRegNo"); + else + checkRN.setText("CHKRegNo"); + } catch (Exception jj) { + } + } + }); + JButton openGraphPanel = new JButton("Graph Panel"); + openGraphPanel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + if (started) + GraphPanel.frame.setVisible(true); + } catch (Exception jj) { + } + } + }); + JButton openHistogramPanel = new JButton("Histogram"); + openHistogramPanel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + if (started) + HistogramPanel.frame.setVisible(true); + } catch (Exception jj) { + } + } + }); + JButton openOrders = new JButton("Orders"); + openOrders.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + if (started) + OrdersPanel.frame.setVisible(true); + } catch (Exception jj) { + } + } + }); + + JPanel uu3 = new JPanel(new FlowLayout()); + uu3.add(openGraphPanel); + uu3.add(openHistogramPanel); + uu3.add(openOrders); + uu3.add(checkRN); + uu3.add(server); + + JPanel uu = new JPanel(new BorderLayout()); + uu.add(tt, BorderLayout.WEST); + uu.add(sensex, BorderLayout.CENTER); + uu.add(uu3, BorderLayout.EAST); + + JPanel qq = new JPanel(new BorderLayout()); + qq.add(jspc, BorderLayout.CENTER); + qq.add(newspanel, BorderLayout.SOUTH); + qq.add(uu, BorderLayout.NORTH); + + mpanel.add(qq, BorderLayout.CENTER); + mpanel.add(puser, BorderLayout.EAST); + + ucht.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + uuu.setChat(Integer.parseInt(ucht.getText().trim())); + } catch (Exception jj) { + } + } + }); + addmoney.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + new Thread() { + public void run() { + try { + int response = JOptionPane.showConfirmDialog(jf, "For only this user: " + uuu.getName() + "(YES) or to all users(NO) or cancel(CANCEL) ?", "Confirm Value Change", JOptionPane.YES_NO_CANCEL_OPTION); + if (response == JOptionPane.YES_OPTION) + uuu.setCurrentMoney(uuu.getCurrentMoney() + Integer.parseInt(addmoney.getText().trim())); + else if (response == JOptionPane.NO_OPTION) { + int mm = Integer.parseInt(addmoney.getText().trim()); + for (int l = 0; l < UserDatabase.userList.size(); l++) + UserDatabase.userList.get(l).setCurrentMoney(UserDatabase.userList.get(l).getCurrentMoney() + mm); + } + } catch (Exception m) { + m.printStackTrace(); + } + } + }.start(); + try { + uuu.setCurrentMoney(uuu.getCurrentMoney() + Integer.parseInt(ucht.getText().trim())); + } catch (Exception jj) { + } + } + }); + banu.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + if (!uuu.isBanned()) + uuu.setBanned(true); + else + uuu.setBanned(false); + } catch (Exception jj) { + } + } + }); + deleteu.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + UserDatabase.deleteUser(uuu); + } catch (Exception jj) { + } + } + }); + chatEnabled.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + uuu.chatEnabled = chatEnabled.isSelected(); + } catch (Exception jj) { + } + } + }); + changep.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String str = JOptionPane.showInputDialog("Enter new Password."); + if (str != null && !str.equals("")) + uuu.setPassword(str); + } catch (Exception jj) { + } + } + }); + cht.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + Server.chatHist.append(" : "); + Server.chatHist.append(cht.getText()); + Server.chatHist.append("\n"); + ShareMarket.server.chat.chaat.append(" : "); + ShareMarket.server.chat.chaat.append(cht.getText()); + ShareMarket.server.chat.chaat.append("\n"); + chat.setText(Server.chatHist.toString()); + cht.setText(""); + new Thread() { + public void run() { + ShareMarket.server.chat.interrupt(); + } + }.start(); + } catch (Exception jj) { + } + } + }); + jf.pack(); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/UserDatabase.java b/src/com/ayushmaanbhav/jstockmart/server/UserDatabase.java new file mode 100644 index 0000000..e42176e --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/UserDatabase.java @@ -0,0 +1,159 @@ +package com.ayushmaanbhav.jstockmart.server; +import java.util.*; +import java.io.*; + +import javax.swing.*; + +import com.ayushmaanbhav.jstockmart.user.*; +class UserDatabase { + volatile static protected List userList; + static protected List regno; + private static double money; + + static void loadList() { + userList = new ArrayList(); + regno = new ArrayList(); + try { + BufferedReader br = new BufferedReader(new FileReader("reg.txt")); + String str; + while ((str = br.readLine()) != null) { + str = str.trim().toLowerCase(); + regno.add(str); + } + br.close(); + } catch (Exception m) { + m.printStackTrace(); + } + + try { + BufferedReader br = new BufferedReader(new FileReader("money.txt")); + money = Double.parseDouble(ShareMarket.twoDForm.format(Double.parseDouble(br.readLine()))); + br.close(); + } catch (Exception e) { + } + } + + static void deleteUser(final User ur) { + for (int i = 0; i < userList.size(); i++) { + if (userList.get(i).checkName(ur.getName())) { + userList.remove(i); + break; + } + } + } + + static int registerUser(final String regno, final String name, String pass) { + boolean b = true; + synchronized (userList) { + if (StockMart.checkRegNo) { + b = false; + if (containsRegNo(regno)) + b = true; + } + if (b) { + for (int i = 0; i < userList.size(); i++) { + if (userList.get(i).checkName(name)) + if (userList.get(i).checkRegNo(regno)) + return 4; + else + return 3; + } + User temp = new User(regno, name, pass, 1000, money); + UserSharesManager.allotInitialShares(temp); + userList.add(temp); + temp = null; + SwingUtilities.invokeLater(new Runnable() { + @SuppressWarnings("unchecked") + public void run() { + StockMart.users.addItem(name); + } + }); + return 1; + } + return 2; + } + } + + static boolean containsRegNo(String reg) { + for (int i = 0; i < regno.size(); i++) { + if (regno.get(i).equals(reg)) + return true; + } + return false; + } + + static User getUserWithRegNo(String r) { + synchronized (userList) { + for (int i = 0; i < userList.size(); i++) { + if (userList.get(i).checkRegNo(r)) { + return userList.get(i); + } + } + } + return null; + } + + static User getUserWithName(String n) { + synchronized (userList) { + for (int i = 0; i < userList.size(); i++) { + if (userList.get(i).checkName(n)) { + return userList.get(i); + } + } + } + return null; + } + + static int validate(String n, String p) { + synchronized (userList) { + User user; + int value = 1; + try { + for (int i = 0; i < userList.size(); i++) { + user = userList.get(i); + if (user.isBanned()) + return 11; + if (user.checkName(n)) { + value = 2; + if (user.checkPassword(p)) { + return 0; + } + } + } + } catch (Exception e) { + } + return value; + } + } + + static User getUser(String n, String p) { + synchronized (userList) { + User user; + try { + for (int i = 0; i < userList.size(); i++) { + user = userList.get(i); + if (user.checkName(n)) { + if (user.checkPassword(p)) { + return user; + } + } + } + } catch (Exception e) { + } + } + return null; + } + + static User deleteUserWithName(String n) { + synchronized (userList) { + for (int i = 0; i < userList.size(); i++) { + if (userList.get(i).checkName(n)) { + User uu = userList.get(i); + userList.remove(i); + return uu; + } + } + } + return null; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/server/UserSharesManager.java b/src/com/ayushmaanbhav/jstockmart/server/UserSharesManager.java new file mode 100644 index 0000000..e46f2a7 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/server/UserSharesManager.java @@ -0,0 +1,38 @@ +package com.ayushmaanbhav.jstockmart.server; + +import java.util.Date; + +import com.ayushmaanbhav.jstockmart.user.Shares; +import com.ayushmaanbhav.jstockmart.user.User; +import com.ayushmaanbhav.jstockmart.utils.RandomGenerator; + +public class UserSharesManager { + static void allotInitialShares(User user) { + int size = ShareMarket.companies.size(); + if (size > 1) { + double limit = user.getCurrentMoney(); + RandomGenerator rg = new RandomGenerator(size); + double limitpercomp = (limit * 2) / size; + for (int i = 0; i < size / 2; i++) { + int index = rg.generateRandom(); + Company comp = ShareMarket.companies.get(index); + double mktvalue = comp.sharevalue.get(comp.sharevalue.size() - 1); + int noofshares = (int) (limitpercomp / mktvalue); + Shares share = new Shares(); + share.buyed = new Date(); + share.id = Server.id++; + share.type = Orders.MARKET_BUY_ORDER; + share.company = comp.name; + share.cost = mktvalue; + share.qty = noofshares; + share.status = "Initial Shares"; + user.getCurrentShares().add(share); + limit -= share.cost * share.qty; + comp.totalshares += share.qty; + } + user.setCurrentMoney(user.getCurrentMoney() + limit); + } else { + System.err.println("Companies not loaded !!"); + } + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/user/Commands.java b/src/com/ayushmaanbhav/jstockmart/user/Commands.java new file mode 100644 index 0000000..51bfe73 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/user/Commands.java @@ -0,0 +1,32 @@ +package com.ayushmaanbhav.jstockmart.user; + +public class Commands { + // client commands + public static final String LOG_IN = "login"; + public static final String REGISTER = "reg"; + public static final String LOG_OUT = "logout"; + public static final String GET_USER_DETAILS = "gud"; + public static final String SEND_CHAT_MESSAGE = "chat"; + public static final String GET_CHAT_HISTORY = "chath"; + public static final String BUY = "buy"; + public static final String SELL = "sell"; + public static final String LIMIT_ORDER = "limit"; + public static final String MARKET_ORDER = "market"; + public static final String MARKET_BUY_ORDER = BUY + MARKET_ORDER; + public static final String MARKET_SELL_ORDER = SELL + MARKET_ORDER; + public static final String LIMIT_BUY_ORDER = BUY + LIMIT_ORDER; + public static final String LIMIT_SELL_ORDER = SELL + LIMIT_ORDER; + public static final String CANCEL_ORDER = "cancel"; + public static final String GET_COMPANY_HISTORY = "getch"; + public static final String GET_COMPANY_STATS = "getcs"; + public static final String SEND_PERIODIC_STATS = "sendps"; + public static final String SEND_FULL_BROADCAST = "sendfb"; + + // server commands + public static final String BROADCAST = "broadcast"; + public static final String CHAT_AND_NEWS = "chat"; + public static final String FINAL_RANKINGS = "rankings"; + public static final String RANKS = "rank"; + public static final String UNKNOWN_COMMAND = "-101"; + public static final String SERVER_NOT_RUNNING = "-102"; +} diff --git a/src/com/ayushmaanbhav/jstockmart/user/Shares.java b/src/com/ayushmaanbhav/jstockmart/user/Shares.java new file mode 100644 index 0000000..31334be --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/user/Shares.java @@ -0,0 +1,66 @@ +package com.ayushmaanbhav.jstockmart.user; + +import java.io.*; +import java.util.*; + +public class Shares implements Serializable { + private static final long serialVersionUID = 1L; + volatile public String company, status; + volatile public int type, qty_limit; + volatile public double cost_limit; + volatile public int qty, id, buyid, sellid; + volatile public double cost; + public Date ordered, buyed; + public User user; + volatile public boolean notCanceled; + + public Shares() { + company = null; + status = null; + qty = 0; + type = -1; + cost_limit = 0; + qty_limit = 0; + id = -1; + user = null; + sellid = -1; + buyid = -1; + cost = 0.0; + ordered = null; + buyed = null; + notCanceled = true; + } + + public Shares(Shares s) { + try { + company = new String(s.company); + } catch (Exception k) { + company = null; + } + try { + status = new String(s.status); + } catch (Exception k) { + status = null; + } + qty = s.qty; + user = s.user; + id = s.id; + cost_limit = s.cost_limit; + type = s.type; + qty_limit = s.qty_limit; + buyid = s.buyid; + sellid = s.sellid; + cost = s.cost; + try { + ordered = (Date) s.ordered.clone(); + } catch (Exception k) { + ordered = null; + } + try { + buyed = (Date) s.buyed.clone(); + } catch (Exception k) { + buyed = null; + } + notCanceled = s.notCanceled; + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/user/User.java b/src/com/ayushmaanbhav/jstockmart/user/User.java new file mode 100644 index 0000000..ccd0e2e --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/user/User.java @@ -0,0 +1,206 @@ +package com.ayushmaanbhav.jstockmart.user; + +import java.io.*; +import java.util.*; +import javax.swing.*; + +public class User implements Serializable { + private static final long serialVersionUID = 1L; + volatile protected String name; + volatile protected String regno; + volatile protected String password; + volatile protected boolean loggedin = false; + volatile protected double money; + volatile protected List shares; + volatile protected List pendingshares; + // protected List history; + volatile protected UserDataChangedListener udcl; + protected User u; + volatile protected int chat; + volatile public boolean chatEnabled, banned; + volatile public String sendStats; + volatile public double score; + + public User(String r, String n, String p, int c, double money) { + chat = c; + name = n; + regno = r; + score = 0; + chatEnabled = true; + banned = false; + sendStats = null; + password = p; + udcl = null; + shares = new ArrayList(); + pendingshares = new ArrayList(); + // history=new ArrayList(); + this.money = money; + u = this; + } + + public User(User user) { + name = new String(user.getName()); + regno = new String(user.getRegNo()); + password = new String(user.getPassword()); + loggedin = user.isLoggedIn(); + money = user.getCurrentMoney(); + shares = new ArrayList(); + pendingshares = new ArrayList(); + for (int i = 0; i < user.getCurrentShares().size(); i++) + shares.add(new Shares(user.getCurrentShares().get(i))); + for (int i = 0; i < user.getPendingShares().size(); i++) + pendingshares.add(new Shares(user.getPendingShares().get(i))); + udcl = null; + sendStats = user.sendStats; + score = user.score; + chat = user.getChat(); + chatEnabled = user.chatEnabled; + banned = user.banned; + u = this; + } + + public void setChat(int c) { + chat = c; + } + + public void setBanned(boolean c) { + banned = c; + } + + public boolean isBanned() { + return banned; + } + + public double getScore() { + return score; + } + + public int getChat() { + return chat; + } + + public void addUserDataChangeListener(UserDataChangedListener u) { + udcl = u; + } + + public UserDataChangedListener removeUserDataChangeListener() { + UserDataChangedListener u = udcl; + udcl = null; + return u; + } + + public void invokeListener() { + dataChanged(); + } + + public void changeData(User user) { + name = user.getName(); + regno = user.getRegNo(); + password = user.getPassword(); + loggedin = user.isLoggedIn(); + money = user.getCurrentMoney(); + shares = user.getCurrentShares(); + pendingshares = user.getPendingShares(); + chat = user.getChat(); + chatEnabled = user.chatEnabled; + banned = user.banned; + sendStats = user.sendStats; + score = user.score; + u = this; + dataChanged(); + } + + public boolean checkName(String n) { + if (name.equals(n)) + return true; + return false; + } + + public boolean checkPassword(String p) { + if (password.equals(p)) + return true; + return false; + } + + public boolean checkRegNo(String r) { + if (regno.equals(r)) + return true; + return false; + } + + public void setLoggedIn(boolean set) { + loggedin = set; + } + + public boolean isLoggedIn() { + return loggedin; + } + + public String getRegNo() { + return regno; + } + + public void setRegNo(String r) { + regno = r; + dataChanged(); + } + + public void setScore(double sc) { + score = sc; + } + + public String getName() { + return name; + } + + public void setName(String n) { + name = n; + dataChanged(); + } + + public String getPassword() { + return password; + } + + public void setPassword(String p) { + password = p; + dataChanged(); + } + + public double getCurrentMoney() { + return money; + } + + public void setCurrentMoney(double m) { + money = m; + dataChanged(); + } + + public List getCurrentShares() { + return shares; + } + + /* + * public List getHistory() { return history; } + */ + public List getPendingShares() { + return pendingshares; + } + + public void setCurrentShares(List c) { + shares = c; + } + + public void setPendingShares(List c) { + pendingshares = c; + } + + public void dataChanged() { + if (udcl != null) + SwingUtilities.invokeLater(new Runnable() { + public void run() { + udcl.userDataChanged(u); + } + }); + } +} \ No newline at end of file diff --git a/src/user/UserDataChangedListener.java b/src/com/ayushmaanbhav/jstockmart/user/UserDataChangedListener.java similarity index 67% rename from src/user/UserDataChangedListener.java rename to src/com/ayushmaanbhav/jstockmart/user/UserDataChangedListener.java index b368307..7a57b60 100644 --- a/src/user/UserDataChangedListener.java +++ b/src/com/ayushmaanbhav/jstockmart/user/UserDataChangedListener.java @@ -1,4 +1,4 @@ -package user; +package com.ayushmaanbhav.jstockmart.user; public interface UserDataChangedListener { diff --git a/src/com/ayushmaanbhav/jstockmart/utils/ButtonColumn.java b/src/com/ayushmaanbhav/jstockmart/utils/ButtonColumn.java new file mode 100644 index 0000000..0801bf1 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/ButtonColumn.java @@ -0,0 +1,198 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.table.*; + +/** + * The ButtonColumn class provides a renderer and an editor that looks like a + * JButton. The renderer and editor will then be used for a specified column in + * the table. The TableModel will contain the String to be displayed on the + * button. + * + * The button can be invoked by a mouse click or by pressing the space bar when + * the cell has focus. Optionally a mnemonic can be set to invoke the button. + * When the button is invoked the provided Action is invoked. The source of the + * Action will be the table. The action command will contain the model row + * number of the button that was clicked. + * + */ +@SuppressWarnings("serial") +public class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener { + private JTable table; + private Action action; + private int mnemonic; + private Border originalBorder; + private Border focusBorder; + + private JButton renderButton; + private JButton editButton; + private Object editorValue; + private boolean isButtonColumnEditor; + + /** + * Create the ButtonColumn to be used as a renderer and editor. The renderer + * and editor will automatically be installed on the TableColumn of the + * specified column. + * + * @param table + * the table containing the button renderer/editor + * @param action + * the Action to be invoked when the button is invoked + * @param column + * the column to which the button renderer/editor is added + */ + public ButtonColumn(JTable table, Action action, int column) { + this.table = table; + this.action = action; + + renderButton = new JButton(); + editButton = new JButton(); + editButton.setFocusPainted(false); + editButton.addActionListener(this); + originalBorder = editButton.getBorder(); + setFocusBorder(new LineBorder(Color.GRAY)); + + TableColumnModel columnModel = table.getColumnModel(); + columnModel.getColumn(column).setCellRenderer(this); + columnModel.getColumn(column).setCellEditor(this); + table.addMouseListener(this); + } + + /** + * Get foreground color of the button when the cell has focus + * + * @return the foreground color + */ + public Border getFocusBorder() { + return focusBorder; + } + + /** + * The foreground color of the button when the cell has focus + * + * @param focusBorder + * the foreground color + */ + public void setFocusBorder(Border focusBorder) { + this.focusBorder = focusBorder; + editButton.setBorder(focusBorder); + } + + public int getMnemonic() { + return mnemonic; + } + + /** + * The mnemonic to activate the button when the cell has focus + * + * @param mnemonic + * the mnemonic + */ + public void setMnemonic(int mnemonic) { + this.mnemonic = mnemonic; + renderButton.setMnemonic(mnemonic); + editButton.setMnemonic(mnemonic); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (value == null) { + editButton.setText(""); + editButton.setIcon(null); + } else if (value instanceof Icon) { + editButton.setText(""); + editButton.setIcon((Icon) value); + } else { + editButton.setText(value.toString()); + editButton.setIcon(null); + } + + this.editorValue = value; + return editButton; + } + + @Override + public Object getCellEditorValue() { + return editorValue; + } + + // + // Implement TableCellRenderer interface + // + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (isSelected) { + renderButton.setForeground(table.getSelectionForeground()); + renderButton.setBackground(table.getSelectionBackground()); + } else { + renderButton.setForeground(table.getForeground()); + renderButton.setBackground(UIManager.getColor("Button.background")); + } + + if (hasFocus) { + renderButton.setBorder(focusBorder); + } else { + renderButton.setBorder(originalBorder); + } + + // renderButton.setText( (value == null) ? "" : value.toString() ); + if (value == null) { + renderButton.setText(""); + renderButton.setIcon(null); + } else if (value instanceof Icon) { + renderButton.setText(""); + renderButton.setIcon((Icon) value); + } else { + renderButton.setText(value.toString()); + renderButton.setIcon(null); + } + + return renderButton; + } + + // + // Implement ActionListener interface + // + /* + * The button has been pressed. Stop editing and invoke the custom Action + */ + public void actionPerformed(ActionEvent e) { + int row = table.convertRowIndexToModel(table.getEditingRow()); + fireEditingStopped(); + + // Invoke the Action + + ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row); + action.actionPerformed(event); + } + + // + // Implement MouseListener interface + // + /* + * When the mouse is pressed the editor is invoked. If you then then drag + * the mouse to another cell before releasing it, the editor is still + * active. Make sure editing is stopped when the mouse is released. + */ + public void mousePressed(MouseEvent e) { + if (table.isEditing() && table.getCellEditor() == this) + isButtonColumnEditor = true; + } + + public void mouseReleased(MouseEvent e) { + if (isButtonColumnEditor && table.isEditing()) + table.getCellEditor().stopCellEditing(); + + isButtonColumnEditor = false; + } + + public void mouseClicked(MouseEvent e) { + } + public void mouseEntered(MouseEvent e) { + } + public void mouseExited(MouseEvent e) { + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/utils/HintPasswordField.java b/src/com/ayushmaanbhav/jstockmart/utils/HintPasswordField.java new file mode 100644 index 0000000..c84a15d --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/HintPasswordField.java @@ -0,0 +1,38 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +import javax.swing.*; + +@SuppressWarnings("serial") +public class HintPasswordField extends JPasswordField implements FocusListener { + + private final String hint; + + public HintPasswordField(final String hint) { + super(hint); + this.hint = hint; + super.addFocusListener(this); + } + + @Override + public void focusGained(FocusEvent e) { + if (this.getText().isEmpty()) { + super.setText(""); + } + } + @Override + public void focusLost(FocusEvent e) { + if (this.getText().isEmpty()) { + super.setText(hint); + } + } + + @Override + public String getText() { + @SuppressWarnings("deprecation") + String typed = super.getText(); + return typed.equals(hint) ? "" : typed; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/utils/HintTextField.java b/src/com/ayushmaanbhav/jstockmart/utils/HintTextField.java new file mode 100644 index 0000000..84b8e59 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/HintTextField.java @@ -0,0 +1,37 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +import javax.swing.*; + +@SuppressWarnings("serial") +public class HintTextField extends JTextField implements FocusListener { + + private final String hint; + + public HintTextField(final String hint) { + super(hint); + this.hint = hint; + super.addFocusListener(this); + } + + @Override + public void focusGained(FocusEvent e) { + if (this.getText().isEmpty()) { + super.setText(""); + } + } + @Override + public void focusLost(FocusEvent e) { + if (this.getText().isEmpty()) { + super.setText(hint); + } + } + + @Override + public String getText() { + String typed = super.getText(); + return typed.equals(hint) ? "" : typed; + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/utils/Histogram.java b/src/com/ayushmaanbhav/jstockmart/utils/Histogram.java new file mode 100644 index 0000000..2677366 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/Histogram.java @@ -0,0 +1,148 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.util.ArrayList; +import java.util.List; + +public class Histogram { + private static int padding = 25; + private static int labelPadding = 25; + private static Color rectColor1 = new Color(255, 0, 0, 100); + private static Color rectColor2 = new Color(0, 255, 0, 100); + private static Color gridColor = new Color(200, 200, 200, 200); + private static final Stroke GRAPH_STROKE = new BasicStroke(2f); + private static int pointWidth = 4; + private static int numberYDivisions = 10; + + public static void paintHistogram(Graphics2D g2, int height, int width, TrippleArrayList scores) { + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + double xScale = ((double) width - (2 * padding) - labelPadding) / (scores.size() - 1); + double yScale = ((double) height - 2 * padding - labelPadding) / (getMaxScore(scores) - getMinScore(scores)); + + List graphPoints1 = new ArrayList<>(); + for (int i = 1; i < scores.size() - 1; i++) { + int x1 = (int) (i * xScale + padding + labelPadding); + int y1 = (int) ((getMaxScore(scores) - scores.getFirstElement(i)) * yScale + padding); + graphPoints1.add(new Point(x1, y1)); + } + + List graphPoints2 = new ArrayList<>(); + for (int i = 1; i < scores.size() - 1; i++) { + int x1 = (int) (i * xScale + padding + labelPadding); + int y1 = (int) ((getMaxScore(scores) - scores.getThirdElement(i)) * yScale + padding); + graphPoints2.add(new Point(x1, y1)); + } + + // draw white background + g2.setColor(Color.WHITE); + g2.fillRect(padding + labelPadding, padding, width - (2 * padding) - labelPadding, height - 2 * padding - labelPadding); + g2.setColor(Color.BLACK); + + // create hatch marks and grid lines for y axis. + for (int i = 0; i < numberYDivisions + 1; i++) { + int x0 = padding + labelPadding; + int x1 = pointWidth + padding + labelPadding; + int y0 = height - ((i * (height - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding); + int y1 = y0; + if (scores.size() > 0) { + g2.setColor(gridColor); + g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, width - padding, y1); + g2.setColor(Color.BLACK); + String yLabel = ((int) ((getMinScore(scores) + (getMaxScore(scores) - getMinScore(scores)) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + ""; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(yLabel); + g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3); + } + g2.drawLine(x0, y0, x1, y1); + } + + // and for x axis + for (int i = 0; i < scores.size(); i++) { + if (scores.size() > 1) { + int x0 = i * (width - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding; + int x1 = x0; + int y0 = height - padding - labelPadding; + int y1 = y0 - pointWidth; + if ((i % ((int) ((scores.size() / 20.0)) + 1)) == 0) { + g2.setColor(gridColor); + g2.drawLine(x0, height - padding - labelPadding - 1 - pointWidth, x1, padding); + g2.setColor(Color.BLACK); + String xLabel = Double.toString(scores.getSecondElement(i)); + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(xLabel); + g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3); + } + g2.drawLine(x0, y0, x1, y1); + } + } + + String legend1 = "Red Bars : Buy Orders "; + String legend2 = "Green Bars: Sell Orders"; + FontMetrics metrics = g2.getFontMetrics(); + int labelWidth = metrics.stringWidth(legend1); + g2.drawString(legend1, width - padding - labelWidth - 1, padding + metrics.getHeight() + 1); + labelWidth = metrics.stringWidth(legend2); + g2.drawString(legend2, width - padding - labelWidth - 1, padding + (metrics.getHeight() + 1) * 2); + + String legend4 = "Bid/Ask Price"; + String legend3 = "No. of orders"; + labelWidth = metrics.stringWidth(legend3); + g2.drawString(legend3, padding - labelWidth / 4, padding - metrics.getHeight() / 2); + labelWidth = metrics.stringWidth(legend4); + g2.drawString(legend4, width / 2 - labelWidth, height - padding + metrics.getHeight() - 1); + + // create x and y axes + g2.drawLine(padding + labelPadding, height - padding - labelPadding, padding + labelPadding, padding); + g2.drawLine(padding + labelPadding, height - padding - labelPadding, width - padding, height - padding - labelPadding); + + Stroke oldStroke = g2.getStroke(); + g2.setColor(rectColor1); + g2.setStroke(GRAPH_STROKE); + int rec_width = (width - padding * 2 - labelPadding) / (2 * (scores.size() - 1)) - 1; + for (int i = 0; i < graphPoints1.size(); i++) { + int x1 = graphPoints1.get(i).x; + int y1 = graphPoints1.get(i).y; + int rec_height = height - padding - labelPadding - y1; + // int x2 = graphPoints.get(i + 1).x; + // int y2 = graphPoints.get(i + 1).y; + g2.fillRect(x1 - rec_width / 2, y1, rec_width, rec_height); + // g2.drawLine(x1, y1, x2, y2); + } + g2.setColor(rectColor2); + for (int i = 0; i < graphPoints2.size(); i++) { + int x1 = graphPoints2.get(i).x; + int y1 = graphPoints2.get(i).y; + int rec_height = height - padding - labelPadding - y1; + // int x2 = graphPoints.get(i + 1).x; + // int y2 = graphPoints.get(i + 1).y; + g2.fillRect(x1 - rec_width / 2, y1, rec_width, rec_height); + // g2.drawLine(x1, y1, x2, y2); + } + g2.setStroke(oldStroke); + } + + private static double getMinScore(TrippleArrayList scores) { + int minScore = Integer.MAX_VALUE; + for (int i = 1; i < scores.size() - 1; i++) { + minScore = Math.min(minScore, scores.getThirdElement(i)); + minScore = Math.min(minScore, scores.getFirstElement(i)); + } + return minScore; + } + + private static double getMaxScore(TrippleArrayList scores) { + int maxScore = Integer.MIN_VALUE; + for (int i = 1; i < scores.size() - 1; i++) { + maxScore = Math.max(maxScore, scores.getThirdElement(i)); + maxScore = Math.max(maxScore, scores.getFirstElement(i)); + } + return maxScore + 2; + } +} diff --git a/src/com/ayushmaanbhav/jstockmart/utils/LookAndFeel.java b/src/com/ayushmaanbhav/jstockmart/utils/LookAndFeel.java new file mode 100644 index 0000000..004e6a8 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/LookAndFeel.java @@ -0,0 +1,18 @@ +package com.ayushmaanbhav.jstockmart.utils; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UIManager; +public class LookAndFeel { + public static void set() { + try { + for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + UIManager.setLookAndFeel(info.getClassName()); // com.sun.java.swing.plaf.windows.WindowsLookAndFeel + break; + } + } + } catch (Exception e) { + // If Nimbus is not available, you can set the GUI to another look + // and feel. + } + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/utils/RandomGenerator.java b/src/com/ayushmaanbhav/jstockmart/utils/RandomGenerator.java new file mode 100644 index 0000000..834c14a --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/RandomGenerator.java @@ -0,0 +1,18 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.util.ArrayList; + +public class RandomGenerator { + ArrayList arr; + + public RandomGenerator(int max) { + arr = new ArrayList(max); + for (int i = 0; i < max; i++) { + arr.add(i); + } + } + + public int generateRandom() { + return arr.remove((int) (Math.random() * arr.size())); + } +} \ No newline at end of file diff --git a/src/com/ayushmaanbhav/jstockmart/utils/TrippleArrayList.java b/src/com/ayushmaanbhav/jstockmart/utils/TrippleArrayList.java new file mode 100644 index 0000000..d0feaa8 --- /dev/null +++ b/src/com/ayushmaanbhav/jstockmart/utils/TrippleArrayList.java @@ -0,0 +1,115 @@ +package com.ayushmaanbhav.jstockmart.utils; + +import java.io.Serializable; +import java.util.ArrayList; + +public class TrippleArrayList, B extends Comparable, C extends Comparable> extends ArrayList.Tupple> implements Serializable { + private static final long serialVersionUID = 1L; + + public TrippleArrayList() { + } + + public TrippleArrayList(TrippleArrayList list) { + for (Tupple t : list) { + add(new Tupple(t)); + } + } + + public class Tupple implements Comparable, Serializable { + private static final long serialVersionUID = 1L; + A a; + B b; + C c; + + public Tupple(Tupple t) { + this.a = t.a; + this.b = t.b; + this.c = t.c; + } + + public Tupple(A a, B b, C c) { + this.a = a; + this.b = b; + this.c = c; + } + + public A getA() { + return a; + } + + public B getB() { + return b; + } + + public C getC() { + return c; + } + + @Override + public int compareTo(Tupple t) { + return b.compareTo(t.b); + } + } + + public boolean add(A a, B b, C c) { + return add(new Tupple(a, b, c)); + } + + public void add(int index, A a, B b, C c) { + add(index, new Tupple(a, b, c)); + } + + public int containsFirstElement(A a) { + for (int i = 0; i < size(); i++) { + if (get(i).a.compareTo(a) == 0) { + return i; + } + } + return -1; + } + + public int containsSecondElement(B b) { + for (int i = 0; i < size(); i++) { + if (get(i).b.compareTo(b) == 0) { + return i; + } + } + return -1; + } + + public int containsThirdElement(C c) { + for (int i = 0; i < size(); i++) { + if (get(i).c.compareTo(c) == 0) { + return i; + } + } + return -1; + } + + public A getFirstElement(int index) { + Tupple t = get(index); + return t.getA(); + } + + public B getSecondElement(int index) { + Tupple t = get(index); + return t.getB(); + } + + public C getThirdElement(int index) { + Tupple t = get(index); + return t.getC(); + } + + public void setFirstElement(int index, A a) { + get(index).a = a; + } + + public void setSecondElement(int index, B b) { + get(index).b = b; + } + + public void setThirdElement(int index, C c) { + get(index).c = c; + } +} diff --git a/src/server/BroadcastServer.java b/src/server/BroadcastServer.java deleted file mode 100644 index e04db5e..0000000 --- a/src/server/BroadcastServer.java +++ /dev/null @@ -1,49 +0,0 @@ -package server; -import java.io.*; -import java.net.*; -import java.util.*; -import java.text.*; - -public class BroadcastServer extends Thread -{ - private long SECONDS = 15000; - List com; - int close; - Server server; - - public BroadcastServer(String name,List c,Server s) throws IOException - { - super(name); - com=c; - server=s; - } - - static DecimalFormat twoDForm = new DecimalFormat("#.##"); - public void run() { - close=0; - while (!interrupted() && com.size()>0) - { - if(close==1) - break; - try - { - int hrs=((int)(StockMart.totTime*60-(new Date().getTime()-StockMart.startDate.getTime())/1000))/3600; - int mins=((((int)(StockMart.totTime*60-(new Date().getTime()-StockMart.startDate.getTime())/1000))/60)%60); - String dString="broadcast::"+hrs+":"+mins+";"+twoDForm.format(ShareMarket.sensex)+"="; - for(int i=0;i sharevalue; - volatile int sharessold,totalshares,tsharessold; - volatile double perchange; - public Company(String n, List l, int sd, int tot) - { - name=n; - sharevalue=l; - sharessold=sd; - totalshares=tot; - tsharessold=0; - } - /*public Company(String n) - { - name=n; - sharevalue=new ArrayList(); - sharessold=0; - }*/ - public double getHighest() - { - double h=sharevalue.get(0); - for(int i=1;ih) - h=sharevalue.get(i); - } - return h; - } - public double getLowest() - { - double l=sharevalue.get(0); - for(int i=1;iPropertyChangeEvents - * in the datamodel. JRealTimeDemo constructs the plot - * from basic sgt objects. - * - * @author Donald Denbo - * @version $Revision: 1.7 $, $Date: 2001/02/06 00:14:35 $ - * @since 2.0 - */ - -public class JRealTimeDemo extends JApplet implements PropertyChangeListener { - PseudoRealTimeData rtData_; - JPane pane_; - Layer layer_; - TimeAxis xbot_; - PlainAxis yleft_; - LinearTransform xt_, yt_; - boolean isStandalone = false; - BorderLayout borderLayout1 = new BorderLayout(); - JPanel buttonPanel = new JPanel(); - JButton startButton = new JButton(); - JButton stopButton = new JButton(); - JButton resetButton = new JButton(); - - /**Construct the applet*/ - public JRealTimeDemo() { - } - /**Initialize the applet*/ - public void init() { - /* - * Create the data source - */ - rtData_ = new PseudoRealTimeData("rtDataSource", "Sea Level"); - try { - jbInit(); - } - catch(Exception e) { - e.printStackTrace(); - } - /* - * add listener for data source. JRealTimeDemo is listening - * for rangeModified events - */ - rtData_.addPropertyChangeListener(this); - } - /**Component initialization*/ - private void jbInit() throws Exception { - this.setSize(new Dimension(800, 440)); - this.getContentPane().setLayout(borderLayout1); - startButton.setText("start"); - startButton.addActionListener(new JRealTimeDemo_startButton_actionAdapter(this)); - stopButton.setText("stop"); - stopButton.addActionListener(new JRealTimeDemo_stopButton_actionAdapter(this)); - resetButton.setText("reset"); - resetButton.addActionListener(new JRealTimeDemo_resetButton_actionAdapter(this)); - buttonPanel.setBorder(BorderFactory.createEtchedBorder()); - this.getContentPane().add(buttonPanel, BorderLayout.SOUTH); - buttonPanel.add(startButton, null); - buttonPanel.add(stopButton, null); - buttonPanel.add(resetButton, null); - // - // construct JPane - // - pane_ = new JPane("Real Time Data Demo", new Dimension(800, 400)); - pane_.setBatch(true); - pane_.setLayout(new StackedLayout()); - pane_.setBackground(Color.white); - /* - * xsize, ysize are the width and height in physical units - * of the Layer graphics region. - * - * xstart, xend are the start and end points for the X axis - * ystart, yend are the start and end points for the Y axis - */ - double xsize = 6.0; - double xstart = 0.6; - double xend = 5.5; - double ysize = 3.0; - double ystart = 0.6; - double yend = 2.75; - /* - * Create the layer and add it to the Pane. - */ - CartesianGraph graph; - /* - * Get x and y ranges from data source. - */ - SoTRange.GeoDate xrange = (SoTRange.GeoDate)rtData_.getXRange(); - SoTRange.Double yrange = (SoTRange.Double)rtData_.getYRange(); - - xt_ = new LinearTransform(xstart, xend, xrange.start, xrange.end); - yt_ = new LinearTransform(ystart, yend, yrange.start, yrange.end); - - layer_ = new Layer("Layer 1", new Dimension2D(xsize, ysize)); - pane_.add(layer_); - - SGLabel title = new SGLabel("title", - "Real Time Demo", - new Point2D.Double((xstart+xend)/2.0, - ysize-0.05)); - title.setAlign(SGLabel.TOP, SGLabel.CENTER); - title.setFont(new Font("Serif", Font.PLAIN, 14)); - title.setHeightP(0.25); - title.setColor(Color.blue.darker()); - layer_.addChild(title); - /* - * Create a CartesianGraph and set transforms. - */ - graph = new CartesianGraph("Time Graph"); - layer_.setGraph(graph); - graph.setXTransform(xt_); - graph.setYTransform(yt_); - /* - * Create the bottom axis, set its range in user units - * and its origin. Add the axis to the graph. - */ - SoTPoint origin = new SoTPoint(xrange.start, yrange.start); - xbot_ = new TimeAxis("Botton Axis", TimeAxis.AUTO); - xbot_.setRangeU(xrange); - xbot_.setLocationU(origin); - Font xbfont = new Font("Helvetica", Font.PLAIN, 14); - xbot_.setLabelFont(xbfont); - graph.addXAxis(xbot_); - /* - * Create the left axis, set its range in user units - * and its origin. Add the axis to the graph. - */ - String yLabel = "Latitude"; - - yleft_ = new PlainAxis("Left Axis"); - yleft_.setRangeU(yrange); - yleft_.setLocationU(origin); - yleft_.setLabelFont(xbfont); - SGLabel ytitle = new SGLabel("yaxis title", yLabel, - new Point2D.Double(0.0, 0.0)); - Font ytfont = new Font("Helvetica", Font.PLAIN, 14); - ytitle.setFont(ytfont); - ytitle.setHeightP(0.2); - yleft_.setTitle(ytitle); - graph.addYAxis(yleft_); - - LineAttribute attr = new LineAttribute(); - graph.setData(rtData_, attr); - - this.getContentPane().add(pane_, BorderLayout.CENTER); - if(!isStandalone) pane_.setBatch(false); - } - /**Start the applet*/ - public void start() { - } - /**Stop the applet*/ - public void stop() { - rtData_.stopData(); - } - /**Destroy the applet*/ - public void destroy() { - rtData_.stopData(); - } - /**Get Applet information*/ - public String getAppletInfo() { - return "Applet Information"; - } - /**Main method*/ - public static void main(String[] args) { - JRealTimeDemo applet = new JRealTimeDemo(); - applet.isStandalone = true; - JFrame frame = new JFrame(); - //EXIT_ON_CLOSE == 3 - frame.setDefaultCloseOperation(3); - frame.setTitle("Real Time Data Demo"); - frame.getContentPane().add(applet, BorderLayout.CENTER); - applet.init(); - applet.start(); - frame.setSize(800,440); - Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); - frame.setLocation((d.width - frame.getSize().width) / 2, - (d.height - frame.getSize().height) / 2); - frame.setVisible(true); - applet.pane_.setBatch(false); - } - - //static initializer for setting look & feel - static { - try { - //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } - catch(Exception e) { - } - } - - void startButton_actionPerformed(ActionEvent e) { - rtData_.startData(); - } - - void stopButton_actionPerformed(ActionEvent e) { - rtData_.stopData(); - } - - void resetButton_actionPerformed(ActionEvent e) { - rtData_.stopData(); - rtData_.resetData(); - resetRange(); - } - private void resetRange() { - /* - * A change in the range has occured. Get new range - * and set transforms, axes, and origin appropriately. - */ - pane_.setBatch(true); - SoTRange.GeoDate xrange = (SoTRange.GeoDate)rtData_.getXRange(); - SoTRange.Double yrange = (SoTRange.Double)rtData_.getYRange(); - SoTPoint origin = new SoTPoint(xrange.start, yrange.start); - xt_.setRangeU(xrange); - yt_.setRangeU(yrange); - xbot_.setRangeU(xrange); - xbot_.setLocationU(origin); - yleft_.setRangeU(yrange); - yleft_.setLocationU(origin); - pane_.setBatch(false); - } - public void propertyChange(PropertyChangeEvent evt) { - /** - * dataModified property is handled by CartesianGraph - * only need to look for rangeModified here to make sure - * range is properly updated - */ - if("rangeModified".equals(evt.getPropertyName())) { - resetRange(); - } - } -} -/* - * wrappers for button events created by JBuilder - */ -class JRealTimeDemo_startButton_actionAdapter implements ActionListener { - JRealTimeDemo adaptee; - - JRealTimeDemo_startButton_actionAdapter(JRealTimeDemo adaptee) { - this.adaptee = adaptee; - } - public void actionPerformed(ActionEvent e) { - adaptee.startButton_actionPerformed(e); - } -} - -class JRealTimeDemo_stopButton_actionAdapter implements ActionListener { - JRealTimeDemo adaptee; - - JRealTimeDemo_stopButton_actionAdapter(JRealTimeDemo adaptee) { - this.adaptee = adaptee; - } - public void actionPerformed(ActionEvent e) { - adaptee.stopButton_actionPerformed(e); - } -} - -class JRealTimeDemo_resetButton_actionAdapter implements ActionListener { - JRealTimeDemo adaptee; - - JRealTimeDemo_resetButton_actionAdapter(JRealTimeDemo adaptee) { - this.adaptee = adaptee; - } - public void actionPerformed(ActionEvent e) { - adaptee.resetButton_actionPerformed(e); - } -} diff --git a/src/server/LookAndFeel.java b/src/server/LookAndFeel.java deleted file mode 100644 index ad7d27b..0000000 --- a/src/server/LookAndFeel.java +++ /dev/null @@ -1,20 +0,0 @@ -package server; -import javax.swing.UIManager.LookAndFeelInfo; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -class LookAndFeel -{ - public static void set() - { - try { - for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - if ("Nimbus".equals(info.getName())) { - UIManager.setLookAndFeel(info.getClassName()); //com.sun.java.swing.plaf.windows.WindowsLookAndFeel - break; - } - } - } catch (Exception e) { - // If Nimbus is not available, you can set the GUI to another look and feel. - } - } -} \ No newline at end of file diff --git a/src/server/PseudoRealTimeData.java b/src/server/PseudoRealTimeData.java deleted file mode 100644 index 744dd57..0000000 --- a/src/server/PseudoRealTimeData.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * $Id: PseudoRealTimeData.java,v 1.6 2001/12/13 19:07:05 dwd Exp $ - * - * This software is provided by NOAA for full, free and open release. It is - * understood by the recipient/user that NOAA assumes no liability for any - * errors contained in the code. Although this software is released without - * conditions or restrictions in its use, it is expected that appropriate - * credit be given to its author and to the National Oceanic and Atmospheric - * Administration should the software be included by the recipient as an - * element in other product development. - */ -package server; - -import gov.noaa.pmel.sgt.SGLabel; -import gov.noaa.pmel.util.GeoDate; -import gov.noaa.pmel.sgt.dm.SGTLine; -import gov.noaa.pmel.sgt.dm.SGTData; -import gov.noaa.pmel.sgt.dm.SGTMetaData; -import gov.noaa.pmel.util.SoTRange; -import gov.noaa.pmel.util.IllegalTimeValue; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Date; - -import javax.swing.Timer; - -/** - * Generates a real-time data stream using SGTLine and - * javax.swing.Timer. PseudoRealTimeData - * generates PropertyCchangeEvents - * whenever data is added "dataModified" or the data range changes - * "rangeModified". The "dataModified" event is directly handled by - * sgt and the "rangeModified" event needs to be handled - * by the graphics application. - * - *

PseudoRealTimeData demonstrates how a class that - * implements the SGTLine interface can use the - * getXRange() and getYRange() methods to - * produce "nice" plots. This class updates the data each time step, - * but updates the range only after a day has passed. - * - * @author Donald Denbo - * @version $Revision: 1.6 $, $Date: 2001/12/13 19:07:05 $ - * @since 2.0 - */ - -public class PseudoRealTimeData implements SGTLine, ActionListener { - private SGTMetaData xMeta_; - private SGTMetaData yMeta_; - private SoTRange.GeoDate xRange_; - private SoTRange.Double yRange_; - private GeoDate[] xData_; - private double[] yData_; - private GeoDate tend_; - private int count_; - private String title_; - private SGLabel keyTitle_ = null; - private String id_; - private Timer timer_; - private PropertyChangeSupport changes_ = new PropertyChangeSupport(this); - private GeoDate ref_ = null; - // bufsize should be integral multiple of majorIncrement plus 1 - private int bufsize_ = 241; - private int offset_; - // offsetIncrement should be same as majorIncrement - private int offsetIncrement_ = 24; - - private double minorIncrement_ = 1.0; - private double majorIncrement_ = 24.0; - private int units_ = GeoDate.HOURS; - - private double A0_ = 1.0; - private double A1_ = 0.375; - private double A2_ = 0.2; - private double omega0_ = 0.251327412; - private double omega1_ = 0.3; - /** - * Constructor. - */ - public PseudoRealTimeData(String id, String title) { - xMeta_ = new SGTMetaData("Time", ""); - yMeta_ = new SGTMetaData("PseudoData", "Ps/day"); - title_ = title; - id_ = id; - timer_ = new Timer(200, this); - resetData(); - } - /** - * Get x data array. Always returns null. - */ - public double[] getXArray() { - return null; - } - /** - * Get y data values. Creates a copy of the buffer array. - */ - public double[] getYArray() { - if(count_ > 0) { - double[] temp = new double[count_+offset_]; - for(int i=0; i < count_+offset_; i++) { - temp[i] = yData_[i]; - } - return temp; - } else { - return null; - } - } - public GeoDate[] getTimeArray() { - if(count_ > 0) { - GeoDate[] temp = new GeoDate[count_+offset_]; - for(int i=0; i < count_+offset_; i++) { - temp[i] = xData_[i]; - } - return temp; - } else { - return null; - } - } - public SGTLine getAssociatedData() { - return null; - } - public boolean hasAssociatedData() { - return false; - } - public String getTitle() { - return title_; - } - public SGLabel getKeyTitle() { - return keyTitle_; - } - public String getId() { - return id_; - } - public SGTData copy() { - return null; - } - public boolean isXTime() { - return true; - } - public boolean isYTime() { - return false; - } - public SGTMetaData getXMetaData() { - return xMeta_; - } - public SGTMetaData getYMetaData() { - return yMeta_; - } - public SoTRange getXRange() { - return xRange_.copy(); - } - public SoTRange getYRange() { - return yRange_.copy(); - } - public void addPropertyChangeListener(PropertyChangeListener l) { - changes_.addPropertyChangeListener(l); - } - public void removePropertyChangeListener(PropertyChangeListener l) { - changes_.removePropertyChangeListener(l); - } - /** - * Start the timer and begin/continue generating property change events. - */ - public void startData() { - timer_.start(); - } - /** - * Stop the timer. - */ - public void stopData() { - timer_.stop(); - } - /** - * Reset the demonstration to the begining. - */ - public void resetData() { - xData_ = new GeoDate[bufsize_]; - yData_ = new double[bufsize_]; - try { - ref_ = new GeoDate("1999-01-01 00:00", "yyyy-MM-dd HH:mm"); - } catch (IllegalTimeValue e) { - e.printStackTrace(); - } - tend_ = new GeoDate(ref_); - // Add a little fudge to get last tic on the axis - tend_.increment(10.0, GeoDate.SECONDS); - yRange_ = new SoTRange.Double(-1.5, 1.5); - xRange_ = new SoTRange.GeoDate(new GeoDate(ref_), - tend_.increment(majorIncrement_, units_)); - xData_[0] = new GeoDate(ref_); - yData_[0] = 0.0; - count_ = 1; - offset_ = 0; - } - - /** - * Handle timer ActionEvents - *
Property Change: rangeModified and - * DataModified - */ - public void actionPerformed(ActionEvent e) { - if((count_+offset_) >= bufsize_) { - offset_ = offset_ - offsetIncrement_; - for(int i=0; i < bufsize_-offsetIncrement_; i++) { - xData_[i] = xData_[i+offsetIncrement_]; - yData_[i] = yData_[i+offsetIncrement_]; - } - xRange_.start = xData_[0]; - } - xData_[count_+offset_] = new GeoDate(ref_.increment(minorIncrement_, units_)); - yData_[count_+offset_] = tSeries(count_); - if(xData_[count_+offset_].after(tend_)) { - SoTRange.GeoDate oldRange = (SoTRange.GeoDate)xRange_.copy(); - /** - * compute new range - */ - tend_.increment(majorIncrement_, units_); - xRange_.end = tend_; - changes_.firePropertyChange("rangeModified", oldRange, xRange_); - } else { - changes_.firePropertyChange("dataModified", - new Integer(count_), - new Integer(count_+1)); - } - count_++; - } - - private double tSeries(int val) { - return A0_*Math.sin(omega0_*val)+A1_*Math.sin(omega1_*val)+A2_*Math.random(); - } -} diff --git a/src/server/RankingServer.java b/src/server/RankingServer.java deleted file mode 100644 index b679c3d..0000000 --- a/src/server/RankingServer.java +++ /dev/null @@ -1,110 +0,0 @@ -package server; -import java.io.*; -import java.net.*; -import java.util.*; -import user.*; -import java.text.*; -import javax.swing.*; - -public class RankingServer extends Thread -{ - private long SECONDS = 30000; - List com; - Server server; - int close; - - public RankingServer(String name,List c,Server s) throws IOException - { - super(name); - com=c; - server=s; - } - - DecimalFormat twoDForm = new DecimalFormat("#.##"); - public void run() { - close=0; - while (!interrupted()) - { - if(close==1) - break; - try - { - String dString="rank::"; - sortUsers(); - for(int i=RegList.userList.size()-1;i>=0;i--) - { - User user=RegList.userList.get(i); - if(!user.isBanned()) - dString+=user.getName()+"->"+twoDForm.format(getScore(user))+":"; - } - //final String sss=dString; - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - String jj=""; - for(int i=RegList.userList.size()-1;i>=0;i--) - { - User user=RegList.userList.get(i); - jj+=(RegList.userList.size()-i)+" ) "+user.getName()+"->"+twoDForm.format(getScore(user))+"\n"; - } - StockMart.ranks.setText(jj); - } - }); - server.sendMulti(dString); - try - { - sleep(SECONDS); - }catch(InterruptedException e){} - }catch(Exception e) - { - e.printStackTrace(); - return; - } - } - } - - void sortUsers() - { - synchronized(RegList.userList) - { - synchronized(com) - { - for(int i=0;i=0;j--) - { - if((getScore(RegList.userList.get(j))>getScore(key) && !RegList.userList.get(j).isBanned()) || key.isBanned()) - RegList.userList.set(j+1,RegList.userList.get(j)); - else - break; - } - RegList.userList.set(j+1,key); - } - } - } - } - - double getScore(User u) - { - synchronized(u) - { - double mon=Double.valueOf(twoDForm.format(u.getCurrentMoney())); - double score=mon; - List list=u.getCurrentShares(); - for(int i=0;i userList; - static protected List regno; - static void loadList() - { - userList=new ArrayList(); - regno=new ArrayList(); - try - { - BufferedReader br=new BufferedReader(new FileReader("reg.txt")); - String str; - while((str=br.readLine())!=null) - { - str=str.trim().toLowerCase(); - regno.add(str); - } - }catch(Exception m){ - m.printStackTrace();} - } - static int registerUser(final String regno,final String name,String pass) - { - synchronized(userList) - { - //if(containsRegNo(regno)) - { - for(int i=0;i companies; - List clientList; - - abstract class Thread1 extends Thread - { - abstract public void sendMessage(String mess); - } - - public Server(List comp) throws IOException { - companies=comp; - serverSocket = new ServerSocket(4446,20000); - serverSocket.setReuseAddress(true); - chat=new ChatServer(this); - clientList=new ArrayList(); - } - - // This server starts on a seperate thread so you can still do other things on the server program - public void startServer() { - if (!started) { - started = true; - serverThread = new Thread() { - public void run() { - while (Server.this.started) { - Socket clientSocket = null; - try { - clientSocket = serverSocket.accept(); - openClient(clientSocket); - try{ - Thread.sleep(10); - }catch(Exception n){} - } catch (SocketException e) { - System.err.println("Server closed."); - } catch (IOException e) { - System.err.println("Accept failed."); - } - } - } - }; - serverThread.start(); - chat.start(); - } - } - - public void stopServer() { - this.started = false; - serverThread.interrupt(); - try { - serverSocket.close(); - } catch (IOException ex) { - System.err.println("Server stop failed."); - } - } - - public void sendMulti(String mess) { - for(int i=0;i=0) - { - if(user.getChat()-command1.substring(command1.indexOf(":")+1).length()>=0) - { - //synchronized(chatHist) - //{ - user.setChat(user.getChat()-command1.substring(command1.indexOf(":")+1).length()); - str=user.getName()+":"+command1.substring(command1.indexOf(":")+1); - chatHist += "<"+user.getName()+"> : "+command1.substring(command1.indexOf(":")+1)+"\n"; - chat.chaat+="<"+user.getName()+"> : "+command1.substring(command1.indexOf(":")+1)+"\n"; - //} - final String ptr=str; - new Thread(){ - public void run() - { - chat.interrupt(); - } - }.start(); - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - StockMart.chat.setText(chatHist); - } - }); - } - } - try{ - objout.writeObject(Integer.toString(user.getChat())); - objout.flush(); - }catch(Exception e) - { - e.printStackTrace(); - } - } - else if(cmmd[0].equals("chath")) - { - try{ - objout.writeObject(chatHist); - objout.flush(); - }catch(Exception e) - { - e.printStackTrace(); - } - } - else if(StockMart.started) - { - if(cmmd[0].equals("buy")) - { - final Shares share=new Shares(); - share.company=command1.split(":")[1].trim(); - share.qty=Integer.parseInt(cmmd[2]); - share.id=id++; - share.cost=-1.0; - share.sellid=-1; - share.buyed=new Date(); - share.ordered=new Date(); - share.status="Shares Pending"; - share.notCanceled=true; - - Company comp=null; - for(int k=0;k0 && shar.qty>0 && sh.qty<=shar.qty && sh.cost!=-1.0) - { - shar.qty-=sh.qty; - comp.sharessold-=sh.qty; - sh.buyed=(Date)shar.buyed.clone(); - user.setCurrentMoney(user.getCurrentMoney()+Double.parseDouble(StockMart.twoDForm.format(sh.qty*sh.cost*0.98))); - sh.status="Payment Received"; - if(shar.qty<=0) - user.getCurrentShares().remove(shar); - } - else - { - sh.status="Failed (Nothing to sell)"; - } - }catch(Exception nn) - { - sh.status="Failed (Nothing to sell)"; - } - } - else - { - //comp.sharessold+=sh.qty; - sh.status="Canceled"; - } - } - } - try{ - objout.reset(); - objout.writeObject(user); - objout.flush(); - }catch(Exception e) - { - e.printStackTrace(); - } - } - }.start(); - - try{ - user.getPendingShares().add(share); - objout.writeObject(share); - objout.flush(); - }catch(Exception e) - { - e.printStackTrace(); - } - } - else if(cmmd[0].equals("cancel")) - { - try{ - int id=Integer.parseInt(cmmd[1]); - int sellid=Integer.parseInt(cmmd[2]); - Shares sh=null; - for(int i=0;i companies; - Server server; - BroadcastServer bserver; - RankingServer rserver; - static double sensex; - Thread calculations; - int SLEEP=30000; - DecimalFormat twoDForm = new DecimalFormat("#.##"); - - void initialise() - { - companies=new ArrayList(); - RegList.loadList(); - loadCompanies(); - } - void startApp() - { - try{ - server=new Server(companies); - }catch(Exception m) - { - m.printStackTrace(); - } - server.startServer(); - try{ - bserver=new BroadcastServer("Share Market Broadcast",companies,server); - }catch(Exception mm) - { - mm.printStackTrace(); - } - try{ - rserver=new RankingServer("Share Market Ranks Broadcast",companies,server); - }catch(Exception mm) - { - mm.printStackTrace(); - } - rserver.start(); - } - void start() - { - bserver.start(); - calculations=new Thread(){ - public void run() - { - while(!interrupted()) - { - synchronized(companies) - { - double d=0.0; - double e=0.0; - double f=0.0; - for(int j=0;j0.0) - com.sharevalue.add(newvalue); - else - { - //bankrupt - } - com.tsharessold+=com.sharessold; - com.sharessold=0; - } - sensex = Double.valueOf(twoDForm.format(e/f*100)); - } - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - StockMart.updateCompanyTable(); - } - }); - try{ - Thread.sleep(SLEEP); - }catch(Exception mm){} - } - } - }; - calculations.start(); - } - void loadCompanies() - { - try - { - BufferedReader br=new BufferedReader(new FileReader("companies.txt")); - String str; - while((str=br.readLine())!=null) - { - String s[]=str.trim().split(":"); - List l=new ArrayList(); - l.add(Double.parseDouble(s[1])); - companies.add(new Company(s[0],l,0,Integer.parseInt(s[2]))); - } - }catch(Exception m){ - m.printStackTrace();} - } - void stop() - { - try - { - server.stopServer(); - }catch(Exception m){} - try - { - bserver.close=1; - }catch(Exception m){} - try - { - rserver.close=1; - }catch(Exception m){} - try - { - calculations.stop(); - }catch(Exception m){} - } -} diff --git a/src/server/StockMart.java b/src/server/StockMart.java deleted file mode 100644 index 7273e85..0000000 --- a/src/server/StockMart.java +++ /dev/null @@ -1,351 +0,0 @@ -package server; -import javax.swing.*; -import javax.swing.table.*; -import javax.swing.event.*; -import java.awt.*; -import java.awt.event.*; -import java.text.*; -import java.util.Date; -import user.*; -import java.io.*; -class StockMart -{ - static JPanel puser,mpanel; - static JLabel userd,sensex; - static JTextArea chat,ranks,news; - static JTable usertable,comptable; - static DefaultTableModel dtmu,dtmc; - static JTextField cht,ucht,tt; - static JCheckBox chatEnabled; - static JComboBox users; - static String newsfeed=""; - static ShareMarket shr; - static JButton server,post,changep,banu; - static String colusr[]=new String[]{"SrNo.","Company","Quantity","C.M.P.","Mkt Value","Gain/Loss","Status"}; - static String[] columnNames2 = {"SrNo.","Company","C.M.P.","% Change","Low","High"}; - static DecimalFormat twoDForm = new DecimalFormat("#.##"); - static boolean started=false; - static int totTime; - static User uuu; - static Date startDate; - static DefaultTableCellRenderer dtr=new DefaultTableCellRenderer(){ - public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) { - if(value.toString().indexOf("-")!=-1) - { - value=value.toString()+" \u25bc"; - } - else - { - value=value.toString()+" \u25b2"; - } - Component c = super.getTableCellRendererComponent(table, value,isSelected, hasFocus,row, column); - if(value.toString().indexOf("-")!=-1) - { - c.setForeground(Color.red); - } - else - { - c.setForeground(Color.green); - } - return c; - } - }; - static Timer timer2=new Timer(1000,new ActionListener(){ - public void actionPerformed(ActionEvent e) - { - try{ - int secs = (int)(totTime*60-(new Date().getTime()-startDate.getTime())/1000); - int hrs = secs/3600; - int mins = (secs/60)-hrs*60; - sensex.setText("Sensex: "+ShareMarket.sensex+" Time Left: "+hrs+":"+mins); - if(secs<=0) - { - started=false; - server.setText("Start"); - //shr.stop(); - timer2.stop(); - } - }catch(Exception bb){} - } - }); - static Timer timer=new Timer(1000,new ActionListener(){ - public void actionPerformed(ActionEvent e) - { - try{ - uuu=RegList.getUserWithName((String)users.getSelectedItem()); - userd.setText("

User-> RegNo: "+uuu.getRegNo()+"      Name: "+uuu.getName()+"      Password: "+uuu.getPassword()+"
Money: "+twoDForm.format(uuu.getCurrentMoney())+" Chat: "+uuu.getChat()+"
"); - //ucht.setText(uuu.getChat()+""); - chatEnabled.setSelected(uuu.chatEnabled); - if(!uuu.isBanned()) - banu.setText("Ban this User"); - else - banu.setText("Unban this User"); - refreshUserTable(uuu); - }catch(Exception n) - { - } - } - }); - - public static void refreshUserTable(User u) - { - Object obj[][]=new Object[u.getCurrentShares().size()+u.getPendingShares().size()+1][7]; - java.util.List ss=u.getCurrentShares(); - for(int i=0;i RegNo: Name: Password: Money: Chat: "); - userd.setPreferredSize(new Dimension(300,25)); - sensex=new JLabel("Sensex: Time Left: "); - tt=new JTextField(5); - tt.setText("120"); - news=new JTextArea(5,30); - chat=new JTextArea(5,30); - chat.setFont(new Font("Lucida Sans Unicode",Font.PLAIN,15)); - chat.setForeground(Color.green.darker()); - chat.setEditable(false); - chat.setLineWrap(true); - ranks=new JTextArea(5,50); - ranks.setEditable(false); - ranks.setForeground(Color.red.darker()); - ranks.setFont(new Font("Lucida Sans Unicode",Font.BOLD,15)); - ranks.setLineWrap(true); - cht=new JTextField(30); - ucht=new JTextField(5); - users=new JComboBox(); - chatEnabled=new JCheckBox("ChatEnabled",true); - dtmu=new DefaultTableModel(); - dtmc=new DefaultTableModel(); - usertable=new JTable(dtmu){ - public boolean isCellEditable(int r,int c) - { - return false; - } - }; - comptable=new JTable(dtmc){ - public boolean isCellEditable(int r,int c) - { - if(c==2) - return true; - return false; - } - }; - dtmc.addTableModelListener(new TableModelListener(){ - public void tableChanged(TableModelEvent tme) - { - final int row=tme.getFirstRow(); - try{ - if(tme.getColumn()==2) - shr.companies.get(row).sharevalue.add(Double.parseDouble(twoDForm.format(Double.valueOf(dtmc.getValueAt(row,2).toString())))); - }catch(Exception m) - { - m.printStackTrace(); - } - } - }); - usertable.setRowHeight(30); - usertable.getTableHeader().setReorderingAllowed(false); - usertable.setFillsViewportHeight(true); - comptable.setRowHeight(30); - comptable.getTableHeader().setReorderingAllowed(false); - comptable.setFillsViewportHeight(true); - JScrollPane jspu=new JScrollPane(usertable); - JScrollPane jspc=new JScrollPane(comptable); - - JPanel chatp=new JPanel(new BorderLayout()); - chatp.setPreferredSize(new Dimension(300,300)); - chatp.add(new JScrollPane(chat,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER); - chatp.add(cht,BorderLayout.SOUTH); - JPanel rr=new JPanel(new BorderLayout()); - rr.setPreferredSize(new Dimension(300,250)); - rr.add(new JScrollPane(ranks,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER); - JPanel rank=new JPanel(new BorderLayout()); - rank.setPreferredSize(new Dimension(600,250)); - rank.add(chatp,BorderLayout.WEST); - rank.add(rr,BorderLayout.EAST); - - changep=new JButton("Change Password"); - banu=new JButton("Ban this User"); - - JPanel jpaa=new JPanel(); - jpaa.setLayout(new BorderLayout()); - jpaa.add(changep,BorderLayout.EAST); - jpaa.add(banu,BorderLayout.WEST); - jpaa.add(ucht,BorderLayout.CENTER); - - JPanel jp=new JPanel(); - jp.setLayout(new BoxLayout(jp,BoxLayout.Y_AXIS)); - jp.add(users); - jp.add(userd); - jp.add(jpaa); - //jp.add(changep); - //jp.add(ucht); - jp.add(chatEnabled); - jp.add(jspu); - - JPanel newspanel=new JPanel(new BorderLayout()); - newspanel.add(new JScrollPane(news,JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER); - newspanel.add(post,BorderLayout.EAST); - - puser=new JPanel(new BorderLayout()); - puser.add(rank,BorderLayout.NORTH); - puser.add(jp,BorderLayout.CENTER); - - JPanel uu=new JPanel(new BorderLayout()); - uu.add(tt,BorderLayout.WEST); - uu.add(sensex,BorderLayout.CENTER); - uu.add(server,BorderLayout.EAST); - - JPanel qq=new JPanel(new BorderLayout()); - qq.add(jspc,BorderLayout.CENTER); - qq.add(newspanel,BorderLayout.SOUTH); - qq.add(uu,BorderLayout.NORTH); - - mpanel.add(qq,BorderLayout.CENTER); - mpanel.add(puser,BorderLayout.EAST); - - ucht.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - try{ - uuu.setChat(Integer.parseInt(ucht.getText().trim())); - }catch(Exception jj){} - } - }); - banu.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - try{ - if(!uuu.isBanned()) - uuu.setBanned(true); - else - uuu.setBanned(false); - }catch(Exception jj){} - } - }); - chatEnabled.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - try{ - uuu.chatEnabled=chatEnabled.isSelected(); - }catch(Exception jj){} - } - }); - changep.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - try{ - String str=JOptionPane.showInputDialog("Enter new Password."); - if(str!=null && !str.equals("")) - uuu.setPassword(str); - }catch(Exception jj){} - } - }); - cht.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - try{ - final String msg="ADMIN:"+cht.getText(); - shr.server.chatHist+=" : "+cht.getText()+"\n"; - shr.server.chat.chaat+=" : "+cht.getText()+"\n"; - chat.setText(shr.server.chatHist); - cht.setText(""); - new Thread(){ - public void run() - { - shr.server.chat.interrupt(); - } - }.start(); - }catch(Exception jj){} - } - }); - jf.pack(); - jf.setVisible(true); - } -} \ No newline at end of file diff --git a/src/server/companies.txt b/src/server/companies.txt deleted file mode 100644 index 09021aa..0000000 --- a/src/server/companies.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reliance:1000 -Microsoft:2000 -Maruti:650 -Hero:1200 -Leopard:500 -Honda:890 -Gagandeep Steels:770 -Bank of Baroda:300 -Tata Docomo:560 -Air India:896 -Pepsi:234 -Tata Tea:465 -Samsung:723 -Yamaha:452 -Punjab National Bank:489 -BSNL:654 -Asian Paints:720 -Dell:213 -Sony:754 -LG:328 -Whirlpool:578 \ No newline at end of file diff --git a/src/server/money.txt b/src/server/money.txt deleted file mode 100644 index e37d32a..0000000 --- a/src/server/money.txt +++ /dev/null @@ -1 +0,0 @@ -1000 \ No newline at end of file diff --git a/src/server/reg.txt b/src/server/reg.txt deleted file mode 100644 index 041c7a2..0000000 --- a/src/server/reg.txt +++ /dev/null @@ -1 +0,0 @@ -1101cs09 \ No newline at end of file diff --git a/src/user/Shares.java b/src/user/Shares.java deleted file mode 100644 index fc0b6ad..0000000 --- a/src/user/Shares.java +++ /dev/null @@ -1,27 +0,0 @@ -package user; -import java.io.*; -import java.util.*; - -public class Shares implements Serializable -{ - volatile public String company,status; - volatile public int qty,id,sellid; - volatile public double cost; - public Date ordered,buyed; - volatile public boolean notCanceled; - public Shares() - { - } - public Shares(Shares s) - { - company=new String(s.company); - status=new String(s.status); - qty=s.qty; - id=s.id; - sellid=s.sellid; - cost=s.cost; - ordered=(Date)s.ordered.clone(); - buyed=(Date)s.buyed.clone(); - notCanceled=s.notCanceled; - } -} diff --git a/src/user/User.java b/src/user/User.java deleted file mode 100644 index 3b65ee1..0000000 --- a/src/user/User.java +++ /dev/null @@ -1,173 +0,0 @@ -package user; -import java.io.*; -import java.util.*; -import javax.swing.*; -public class User implements Serializable -{ - volatile protected String name; - volatile protected String regno; - volatile protected String password; - volatile protected boolean loggedin=false; - volatile protected double money; - volatile protected List shares; - volatile protected List pendingshares; - //protected List history; - volatile protected UserDataChangedListener udcl; - protected User u; - volatile protected int chat; - volatile public boolean chatEnabled,banned; - public User(String r,String n,String p,int c) - { - chat=c; - name=n; - regno=r; - chatEnabled=true; - banned=false; - password=p; - udcl=null; - shares=new ArrayList(); - pendingshares=new ArrayList(); - //history=new ArrayList(); - try{ - BufferedReader br=new BufferedReader(new FileReader("money.txt")); - money=Integer.parseInt(br.readLine()); - }catch(Exception e){} - u=this; - } - public void setChat(int c) - { - chat=c; - } - public void setBanned(boolean c) - { - banned=c; - } - public boolean isBanned() - { - return banned; - } - public int getChat() - { - return chat; - } - public void addUserDataChangeListener(UserDataChangedListener u) - { - udcl=u; - } - public UserDataChangedListener removeUserDataChangeListener() - { - UserDataChangedListener u=udcl; - udcl=null; - return u; - } - public void invokeListener() - { - dataChanged(); - } - public void changeData(User user) - { - name=user.getName(); - regno=user.getRegNo(); - password=user.getPassword(); - loggedin=user.isLoggedIn(); - money=user.getCurrentMoney(); - shares=user.getCurrentShares(); - pendingshares=user.getPendingShares(); - chat=user.getChat(); - chatEnabled=user.chatEnabled; - u=this; - dataChanged(); - } - public boolean checkName(String n) - { - if(name.equals(n)) - return true; - return false; - } - public boolean checkPassword(String p) - { - if(password.equals(p)) - return true; - return false; - } - public boolean checkRegNo(String r) - { - if(regno.equals(r)) - return true; - return false; - } - public void setLoggedIn(boolean set) - { - loggedin=set; - } - public boolean isLoggedIn() - { - return loggedin; - } - public String getRegNo() - { - return regno; - } - public void setRegNo(String r) - { - regno=r; - dataChanged(); - } - public String getName() - { - return name; - } - public void setName(String n) - { - name=n; - dataChanged(); - } - public String getPassword() - { - return password; - } - public void setPassword(String p) - { - password=p; - dataChanged(); - } - public double getCurrentMoney() - { - return money; - } - public void setCurrentMoney(double m) - { - money=m; - dataChanged(); - } - public List getCurrentShares() - { - return shares; - } - /*public List getHistory() - { - return history; - }*/ - public List getPendingShares() - { - return pendingshares; - } - public void setCurrentShares(List c) - { - shares=c; - } - public void setPendingShares(List c) - { - pendingshares=c; - } - public void dataChanged() - { - if(udcl!=null) - SwingUtilities.invokeLater(new Runnable(){ - public void run() - { - udcl.userDataChanged(u); - } - }); - } -} \ No newline at end of file