/// <summary> /// Testing method for the encoder and decode functions. /// </summary> public static void EncodeDecodeTest() { DateTime now = new DateTime(); Publisher p = new Publisher(1); Random rdm = new Random(); Bookstore bookstore = new Bookstore(1); for (int i = 0; i < 20; i++) { now = DateTime.Now; OrderObject o = new OrderObject ( i, //senderId (Int32)(rdm.NextDouble() * 10000), //cardNo i, //receiverId (Int32)(rdm.NextDouble() * 200), //amount (Int32)(rdm.NextDouble() * 100), //unitPrice now, //timestamp, DateTime.Now.Millisecond ); string str = bookstore.Encoder(o); Console.WriteLine("The OrderObject's actual contents were: " + o.getBookStoreId() + "," + o.getCardNo().ToString() + "," + o.getPublisherId() + "," + o.getAmount().ToString() + "," + o.getUnitPrice().ToString() + "," + o.getTimestamp().ToString()); Console.WriteLine("The string created by the encoder was: " + str); o = p.getDecoder().decode(str); Console.WriteLine("The Decoder created another OrderObject from the string created by the encoder whose contents were: \n" + o.getBookStoreId() + "," + o.getCardNo().ToString() + "," + o.getPublisherId() + "," + o.getAmount().ToString() + "," + o.getUnitPrice().ToString() + "," + o.getTimestamp().ToString() + "\n"); System.Threading.Thread.Sleep(50); } }
/// <summary> /// Test method for the pricing model. /// </summary> public static void TestPricingModel() { DateTime now = new DateTime(); Publisher p = new Publisher(1); Random rdm = new Random(); for (int i = 0; i < 20; i++) { now = DateTime.Now; OrderObject o = new OrderObject(i, (Int32)(rdm.NextDouble() * 10000), i, (Int32)(rdm.NextDouble() * 200), 100, now, DateTime.Now.Millisecond); double price = Math.Round(p.getModeler().calcPrice(o), 2); Console.WriteLine("ObjectOrder " + o.getBookStoreId() + " paid $" + price.ToString() + ". The number of books in the order was " + o.getAmount() + ". The number of orders in the recent orders " + "queue was " + p.getModeler().getQueue().Count + ". " + "The Publisher has " + p.getBooks().ToString() + " books.\n"); o.setUnitPrice(price); System.Threading.Thread.Sleep((Int32)(rdm.NextDouble() * 1000)); } Console.WriteLine("There are " + p.getModeler().getQueue().Count.ToString() + " in the recent orders queue.\n"); foreach (OrderObject order in p.getModeler().getQueue()) { Console.WriteLine("Order " + order.getBookStoreId() + " paid $" + order.getUnitPrice().ToString() + ".\n"); } }
//Thread entry point for OrderProcessing object public static void OrderProcessingThread(OrderObject obj) { //Validate the credit card number if (obj.getCardNo() > 6000 || obj.getCardNo() < 5000) { Console.WriteLine("OrderProcessingThread found an invalid credit card number, order not processed."); return; } //Calculate total price double totalPrice = obj.getAmount() * obj.getUnitPrice() //Unit price multiplied by total quantity of books ordered + obj.getAmount() * obj.getUnitPrice() * TAX_RATE //Add tax rate + (obj.getBookStoreId() * SHIPPING_PREMIUM); //Add shipping cost, assumed higher numbered bookstores are further away //Initiate event signifying order was processed orderComplete(obj.getBookStoreId(), obj.getPublisherId(), obj.getAmount(), obj.getUnitPrice(), totalPrice, obj.getTicks(), DateTime.Now.Ticks); }
// Encoder -- turns OrderObject into a CSV string public String Encoder(OrderObject order) { String orderStr = null; // build CSV String orderStr = order.getBookStoreId().ToString();; orderStr += "," + order.getCardNo().ToString(); orderStr += "," + order.getPublisherId().ToString(); orderStr += "," + order.getAmount().ToString(); orderStr += "," + order.getUnitPrice().ToString(); orderStr += "," + order.getTimestamp(); orderStr += "," + order.getTicks().ToString(); return(orderStr); // return the encoded string just created. }
/// <summary> /// runPublisher -- This method is the method that will be executed in the thread. /// The publisher does: /// 1) Check the multicell buffer for orders /// 2) if order, then read, and processed by executing a OrderProcess Thread /// 3) Check warehouse for book quality /// 4) calcuate the new price /// 5) Schedule an event on price if the reduction is greater thatn 25% /// 6) Sleep thread for 50ms /// 7) repeat. /// </summary> public void runPublisher() { String bufferedString = String.Empty; Int32 count = 0; while (p < 20) { bufferedString = Program.mcb.getOneCell(name); if (!String.IsNullOrEmpty(bufferedString)) { //Take string from multicell buffer and convert to OrderObject OrderObject obj = decoder.decode(bufferedString); //Make sure there are enough books in the publisher to complete order decrementBooks(obj.getAmount()); //Generate thread to process order Thread oProc = new Thread(() => OrderProcessing.OrderProcessingThread(obj)); oProc.Start(); //Used if publisher had to restock books and a price drop resulted if (books == RESTOCK_AMT) { count = 0; if (name == 1) { currentPrice = modeler.calcPrice(obj); //Calculate new price and store in local variable Program.GV.set_Pub1_Price(currentPrice); //Push new price up to the global variable priceCutEvent(currentPrice, name); //Issue price cut event } else { currentPrice = modeler.calcPrice(obj); //Calculate new price and store in local variable Program.GV.set_Pub2_Price(currentPrice); //Push new price up to the global variable priceCutEvent(currentPrice, name); //Issue price cut event } } //Used if no restock was performed else { count = 0; if (name == 1) { double temp = currentPrice; currentPrice = modeler.calcPrice(obj); //Calculate new price and store in local variable Program.GV.set_Pub1_Price(currentPrice); //Push local price to global variable //Issue a price cut event if the price dropped by 25% if ((1 - currentPrice / temp) >= .25) { priceCutEvent(currentPrice, name); } } else { double temp = currentPrice; currentPrice = modeler.calcPrice(obj); //Calculate new price and store in local variable Program.GV.set_Pub2_Price(currentPrice); if (1 - (currentPrice / temp) >= .25) { currentPrice = Program.GV.get_Pub2_Price(); priceCutEvent(currentPrice, name); } } } } count++; if (count == 3) { if (name == 1) { setNumBooks(RESTOCK_AMT); currentPrice = modeler.getUnitPrice(); Program.GV.set_Pub1_Price(currentPrice); } else { setNumBooks(RESTOCK_AMT); currentPrice = modeler.getUnitPrice(); Program.GV.set_Pub2_Price(currentPrice); } } Thread.Sleep(SLEEP_TIME); } }
// EVENT HANDLERS /// <summary> /// /// Event handler for Book Sale broadcasted by publisher thread /// /// </summary> /// <param name="price"></param> /// <param name="PubNum"></param> public void BookSale(double price, Int32 PubNum) { // books are on sale for a price. // see if I want to buy at that price OrderObject newOrder = CreateOrder(PubNum); if (StoreNumber == 0) // Every store will get this event but I only need noe store to write it out!! { Console.WriteLine(" ***************** BOOK SALE from Publisher # {0} Price{1:C} *******************\n", PubNum, price); } if (newOrder != null) { String eOrder = Encoder(newOrder); // add to multicell buffer BufferString mybString = new BufferString(); mybString.setBufferString(eOrder, PubNum); Program.mcb.setOneCell(mybString); // order the books. Console.WriteLine("\t\t ^^^ order created for store {0} for {1} books", StoreNumber, newOrder.getAmount()); } else { Console.WriteLine("\t\t *** No order created for store {0}", StoreNumber); } }