/**
  * This method is mainly to cancel replace an order. We find the original order in the books, then
  * we renew its information. then we push it back to the financial.book as a new order.
  */
 public String cxrOrder(OrderCxRImpl changeOrder) {
   // get the id of the cancel replace order
   String orderID = changeOrder.getOrderId();
   // find the order in the financial.book
   NewOrderImpl renewOrder = lookUpOrder(orderID);
   // renew the order, then push it back into the financial.book as a new order
   String orderSymbol = renewOrder.getSymbol();
   if (renewOrder != null && changeOrder.getSize() != 0) {
     // renew the size of the order
     renewOrder.size = changeOrder.getSize();
     // renew the price of the order
     renewOrder.limitPrice = changeOrder.getLimitPrice();
     // get the bidbook and askbook of that certain symbol
     Hashtable<Double, LinkedList<NewOrderImpl>> tempbid =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     Hashtable<Double, LinkedList<NewOrderImpl>> tempask =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     if (bid.containsKey(orderSymbol)) {
       tempbid = bid.get(orderSymbol);
     }
     if (ask.containsKey(orderSymbol)) {
       tempask = ask.get(orderSymbol);
     }
     // add the changed order back to the books.
     addNewOrder(renewOrder, orderSymbol, tempbid, tempask);
   }
   // return the symbol of the cancel and replace order.
   return orderSymbol;
 }
  /**
   * This method is mainly to add a new order into the certain bidbook or askbook , which
   * named @param myNewOrder the method returns nothing, but has side effect of changing that
   * bidbook or askbook. Once get a new order, first check it is a bid order or an ask order. If the
   * size of the order is positive, then it is a bid order, otherwise, it is a ask order. Then you
   * judge the price of the order. If the price shows Double.NaN,it means this is a marketprice
   * order, in another words, any price is okay for this order to make a deal. After that i make a
   * deal if the situation is allowed. If there is no trade can be done, then push the order into
   * the according financial.book.
   */
  public void addNewOrder(
      NewOrderImpl myNewOrder,
      String symbol,
      Hashtable<Double, LinkedList<NewOrderImpl>> bidbook,
      Hashtable<Double, LinkedList<NewOrderImpl>> askbook) {
    // myprice is a double, which is the limitprice of the input myNewOrder.
    double myprice = myNewOrder.getLimitPrice();
    // temp is a linkedlist with the object NewOrderImpl, which is intended to be used as the list
    // contains the orders which the new order could be traded with.
    LinkedList<NewOrderImpl> temp = new LinkedList<NewOrderImpl>();
    // to judge if myNewOrder is a bid order.
    if (myNewOrder.size >= 0) {
      // to judge if myNewOrder is with marketprice.
      if (myprice == Double.NaN) {

        // get the best ask price, named marketprice.
        Double marketprice = getLowestAsk(askbook);
        // get the ask orders in askbook which price the marketprice, also meaning these orders have
        // the priority to trade with the new order.
        LinkedList<NewOrderImpl> asktrade = askbook.get(marketprice);
        /**
         * The trade part As long as the new order with markerprice hasn't been traded all, we find
         * the ask orders with current best ask price to share its size. Like been written below, if
         * the size of the order we get first is smaller than the remaining size of the new order,
         * then done the trade, and decrease the size of the new order, and then find the next best
         * ask order to trade. if the size of the best ask order is larger than the remaining size
         * of the new order, then done the trade, and cut the share of the best ask order. If the
         * orders in asktrade is all be traded, but there is still some shares in new order, we get
         * the next best ask price, and get a new list of orders with that price. We recursively do
         * the steps above, until the new order is traded completely.
         */
        while (myNewOrder.size != 0) {
          if (asktrade != null) {
            NewOrderImpl firstOrder = asktrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              asktrade.removeFirst();
            }
          } else {
            marketprice = getHighestBid(bidbook);
            asktrade = bidbook.get(marketprice);
          }
        }
      }
      // if myNewOrder is with limitprice
      else {
        // get the current best ask price, which named marketprice
        Double marketprice = getLowestAsk(askbook);
        // to check if there is some ask orders can be traded with the new order right now, which
        // means the best ask price is smaller than the limit price of new order.
        if (marketprice <= myprice) {
          // build a new linked list to contain the orders with the best price to be traded with the
          // new order.
          LinkedList<NewOrderImpl> asktrade = new LinkedList<NewOrderImpl>();
          /**
           * The trade part As long as the new order with markerprice hasn't been traded all, we
           * find the ask orders with current best ask price to share its size. Like been written
           * below, if the size of the order we get first is smaller than the remaining size of the
           * new order, then done the trade, and decrease the size of the new order, and then find
           * the next best ask order to trade. if the size of the best ask order is larger than the
           * remaining size of the new order, then done the trade, and cut the share of the best ask
           * order. then we get the latest best ask price. We recursively do the steps above, unless
           * the new order's size come to zero or there is no ask order can be traded with the new
           * order.
           */
          while (myNewOrder.size != 0 && marketprice <= myprice) {
            asktrade = askbook.get(marketprice);
            NewOrderImpl firstOrder = asktrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              asktrade.removeFirst();
            }
            marketprice = getLowestAsk(askbook);
          }
          // if after the trade above, the new order is still not empty, then put it into the bid
          // financial.book.
          if (myNewOrder.size != 0) {
            if (bidbook.containsKey(myprice)) {
              temp = bidbook.get(myprice);
            }
            temp.push(myNewOrder);
            bidbook.put(myprice, temp);
          }
        }
        // if there is no order can be traded with the new order, just put it into the bid
        // financial.book.
        else {
          if (bidbook.containsKey(myprice)) {
            temp = bidbook.get(myprice);
          }
          temp.push(myNewOrder);
          bidbook.put(myprice, temp);
        }
      }
    }
    // if the new order is a ask order.
    else {
      // to judge if myNewOrder is with marketprice.
      if (myprice == Double.NaN) {

        // get the best bid price, named marketprice.
        Double marketprice = getHighestBid(bidbook);
        // get the bid orders in bidbook which price the marketprice, also meaning these orders have
        // the priority to trade with the new order.
        LinkedList<NewOrderImpl> bidtrade = bidbook.get(marketprice);
        /**
         * The trade part As long as the new order with markerprice hasn't been traded all, we find
         * the bid orders with current best bid price to share its size. Like been written below, if
         * the size of the order we get first is smaller than the remaining size of the new order,
         * then done the trade, and decrease the size of the new order. if the size of the best bid
         * order is larger than the remaining size of the new order, then done the trade, and cut
         * the share of the best bid order. If the orders in bidtrade is all be traded, but there is
         * still some shares in new order, we get the next best bid price, and get a new list of
         * orders with that price. We recursively do the steps above, until the new order is traded
         * completely.
         */
        while (myNewOrder.size != 0) {
          if (bidtrade != null) {
            NewOrderImpl firstOrder = bidtrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              bidtrade.removeFirst();
            }
          } else {
            marketprice = getHighestBid(bidbook);
            bidtrade = bidbook.get(marketprice);
          }
        }
      }
      // if myNewOrder is with limitprice
      else {
        // get the current best bid price, which named marketprice
        Double marketprice = getHighestBid(bidbook);
        // to check if there is some bid orders can be traded with the new order right now, which
        // means the best bid price is larger than the limit price of new order.
        if (marketprice >= myprice) {
          // build a new linked list to contain the orders with the best price to be traded with the
          // new order.
          LinkedList<NewOrderImpl> bidtrade = new LinkedList<NewOrderImpl>();
          /**
           * The trade part As long as the new order with markerprice hasn't been traded all, we
           * find the bid orders with current best bid price to share its size. Like been written
           * below, if the size of the order we get first is smaller than the remaining size of the
           * new order, then done the trade, and decrease the size of the new order. if the size of
           * the best bid order is larger than the remaining size of the new order, then done the
           * trade, and cut the share of the best bid order. then we get the latest best bid price.
           * We recursively do the steps above, unless the new order's size come to zero or there is
           * no bid order can be traded with the new order.
           */
          while (myNewOrder.size != 0 && marketprice >= myprice) {
            bidtrade = bidbook.get(marketprice);
            NewOrderImpl firstOrder = bidtrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              bidtrade.removeFirst();
            }
            marketprice = getHighestBid(bidbook);
          }
          // if after the trade above, the new order is still not empty, then put it into the ask
          // financial.book.
          if (myNewOrder.size != 0) {
            if (askbook.containsKey(myprice)) {
              temp = askbook.get(myprice);
            }
            temp.push(myNewOrder);
            askbook.put(myprice, temp);
          }
        }
        // if there is no order can be traded with the new order, just put it into the ask
        // financial.book.
        else {
          if (askbook.containsKey(myprice)) {
            temp = askbook.get(myprice);
          }
          temp.push(myNewOrder);
          askbook.put(myprice, temp);
        }
      }
    }
    bid.put(symbol, bidbook);
    ask.put(symbol, askbook);
  }
 /**
  * This result method is to get all things done by using the method build above. It get all the
  * orders and deal with them. Every time right after one oder has been solved, it will print out
  * the best bid price and ask price for the name that the message belonged to.
  */
 public static void result(Iterator<Message> myiter, Boolean flag) {
   // get a new book
   book book = new book();
   // this recursion will not end until the mylist is empty.
   while (myiter.hasNext()) {
     // if the next item in mylist is a new Order.
     Object mymessage = myiter.next();
     // be prepared to get the certain bidbook and askbook
     Hashtable<Double, LinkedList<NewOrderImpl>> tempbid =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     Hashtable<Double, LinkedList<NewOrderImpl>> tempask =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     // if the next item is a new order
     if (mymessage instanceof NewOrderImpl) {
       // make the order a NewOrderImpl
       NewOrderImpl myneworder = (NewOrderImpl) mymessage;
       // get the symbol of the order
       String mysymbol = myneworder.getSymbol();
       // if the bidbook of the symbol is already built, fetch the bidbook
       if (bid.containsKey(mysymbol)) {
         tempbid = bid.get(mysymbol);
       }
       // if the askbook of the symbol is already build, fetch the askbook
       if (ask.containsKey(mysymbol)) {
         tempask = ask.get(mysymbol);
       }
       // add the new order into the books.
       book.addNewOrder(myneworder, mysymbol, tempbid, tempask);
       // if the flag is true, print out the information
       if (flag) {
         // if there is no bid orders in that bidbook, return Double.MIN_VALUE, and print out that
         // there is no bid orders.
         if (book.getHighestBid(tempbid) == Double.MIN_VALUE)
           System.out.println(mysymbol + " Best Bid Price:  no bid orders");
         // else print out the best bid price
         else System.out.println(mysymbol + " Best Bid Price:  " + book.getHighestBid(tempbid));
         // if there is no ask orders in that askbook, return Double.MAX_VALUE, and print out that
         // there is no ask orders.
         if (book.getLowestAsk(tempask) == Double.MAX_VALUE)
           System.out.println(mysymbol + " Best Ask Price:  no ask orders");
         // else print out the best ask price
         else System.out.println(mysymbol + " Best Ask Price:  " + book.getLowestAsk(tempask));
       }
     }
     // if the next item in mylist is a Order CxR.
     else if (mymessage instanceof OrderCxRImpl) {
       // make the item a OrderCxRImpl, then use the cxrOrder method to deal the order, and get its
       // symbol
       String mysymbol = book.cxrOrder((OrderCxRImpl) mymessage);
       // fetch the bidbook and askbook of that symbol
       tempbid = bid.get(mysymbol);
       tempask = ask.get(mysymbol);
       // if the flag is true, print out the information
       if (flag) {
         // if there is no bid orders in that bidbook, return Double.MIN_VALUE, and print out that
         // there is no bid orders.
         if (book.getHighestBid(tempbid) == Double.MIN_VALUE)
           System.out.println(mysymbol + " Best Bid Price:  no bid orders");
         // else print out the best bid price
         else System.out.println(mysymbol + " Best Bid Price:  " + book.getHighestBid(tempbid));
         // if there is no ask orders in that askbook, return Double.MAX_VALUE, and print out that
         // there is no ask orders.
         if (book.getLowestAsk(tempask) == Double.MAX_VALUE)
           System.out.println(mysymbol + " Best Ask Price:  no ask orders");
         // else print out the best ask price
         else System.out.println(mysymbol + " Best Ask Price:  " + book.getLowestAsk(tempask));
       }
     }
   }
 }
 /**
  * This method is mainly to look up an order which is already in one bidbook or askbook, according
  * to its unique id. For I do not know which book is this order in, one certain symbol's bidbook
  * or askbook. So I need to go though all the bid book in bid and all the ask book in ask to find
  * it. I choose first to look up in all the bidbook, if there is nothing return, then look up in
  * all the askbook. What I actually do is to look up every key in the book, and traverse the
  * linkedlist with that key. When I go through the linkedlist with all the order, i match their id
  * with the id I am looking for. As soon as i find the matching one, i remove the order from the
  * financial.book, and return the order i found.
  */
 public NewOrderImpl lookUpOrder(String id) {
   // get all the key in bid
   Set<String> keys = bid.keySet();
   Hashtable<Double, LinkedList<NewOrderImpl>> temptable =
       new Hashtable<Double, LinkedList<NewOrderImpl>>();
   // go through all the key in bid
   for (String key : keys) {
     // get the book of that symbol.
     temptable = bid.get(key);
     // the temp linkedlist is to store the linkedlist i will be traverse.
     LinkedList<NewOrderImpl> temp;
     // the replaceOrder is the order which matches the id and to be returned.
     // the tmp is the order which used to get from the linkedlist to compare with the id i need.
     NewOrderImpl replaceOrder, tmp;
     // get all the keys in bidbook, so i can traverse all of it.
     Set<Double> tablekey = temptable.keySet();
     // I traverse all the key, and put the value to the key into the linkedlist temp.
     for (Double key2 : tablekey) {
       temp = temptable.get(key2);
       // i build an iterator to traverse the linkedlist temp
       for (Iterator<NewOrderImpl> it = temp.iterator(); it.hasNext(); ) {
         tmp = it.next();
         // to compare all the orders in temp, to see if there is an order matches the id.
         if (tmp.getOrderId().equals(id)) {
           // found one
           replaceOrder = tmp;
           // remove it from the financial.book
           temp.remove(tmp);
           temptable.put(key2, temp);
           bid.put(key, temptable);
           // return the result.
           return replaceOrder;
         }
       }
     }
   }
   // get all the key in ask
   keys = ask.keySet();
   // go through all the key in ask
   for (String key : keys) {
     // get the askbook of certain symbol
     temptable = ask.get(key);
     // the temp linkedlist is to store the linkedlist i will be traverse.
     LinkedList<NewOrderImpl> temp;
     // the replaceOrder is the order which matches the id and to be returned.
     // the tmp is the order which used to get from the linkedlist to compare with the id i need.
     NewOrderImpl replaceOrder, tmp;
     // get all the keys in askbook, so i can traverse all of it.
     Set<Double> tablekey = temptable.keySet();
     // I traverse all the key, and put the value to the key into the linkedlist temp.
     for (Double key2 : tablekey) {
       temp = temptable.get(key2);
       // i build an iterator to traverse the linkedlist temp
       for (Iterator<NewOrderImpl> it = temp.iterator(); it.hasNext(); ) {
         tmp = it.next();
         // to compare all the orders in temp, to see if there is an order matches the id.
         if (tmp.getOrderId().equals(id)) {
           // found one
           replaceOrder = tmp;
           // remove it from the financial.book
           temp.remove(tmp);
           temptable.put(key2, temp);
           ask.put(key, temptable);
           // return the result.
           return replaceOrder;
         }
       }
     }
   }
   // did not find the order neither in bid financial.book nor in ask financial.book, so return
   // null.
   return null;
 }