package game; import java.util.ArrayList; import java.util.Iterator; import org.w3c.dom.Document; import input.InputReader; import actor.BuyingAgent; import data.Derivative; import data.Price; import data.DerivativeType; import output.StoreFileWriter; /** * object to represent the store of available derivatives * * @author Rukmal Fernando * @author Hardik Kotecha * @author Radhika Srinivasan */ public class Store implements output.XMLizable { private static ArrayList derivatives; // derivatives available in store for purchase private static StoreFileWriter sfw; // writer for store xml private static Store reference; // reference to Store singleton public static float minDerPriceToBuy=0.9f; private static final boolean DEBUG = false; /** * private default constructor */ private Store() { reference = null; } /** * constructor * * @param pDerivatives : ArrayList */ public Store( ArrayList pDerivatives ) { getStore().setDerivatives( pDerivatives ); } /** * Initialize a new Store if one does not exist * @return Store */ public static Store getStore() { if( reference == null ) // if no store exists return new Store(); // return a new store else // if a store exists return reference; // return the existing store } /*======================================================================== | getters and setters +-----------------------------------------------------------------------*/ /** * set the list of the derivatives to the given list * * @param pDerivatise : ArrayList of Derivative */ void setDerivatives( ArrayList pDerivatives ) { derivatives = pDerivatives; } /** * get the derivatives in the store * * @return ArrayList */ public static ArrayList getDerivatives() { return derivatives; } /*----------------------------------------------------------------------- | end getters and setters +======================================================================*/ /** * generate the xml representation of a store * * @return String */ public String generateXML() { Iterator derivativesIterator = derivatives.iterator(); //create an iterator for derivatives String ret = new String( "\n" ); //store opening tag while ( derivativesIterator.hasNext() ) //while there are more derivatives to iterate over { Derivative tmp = derivativesIterator.next(); //get the next derivative ret = ret.concat( tmp.generateXML() ); //generate the xml for that derivative and append it } ret = ret.concat( "" ); //add closing tag return ret; } /** * print the XML representation of this class to the console */ public void print() { System.out.println( generateXML() ); } /** * write the contents of this store object to the store XML */ public static void writeStore() { String storeXML = getStore().generateXML(); sfw = StoreFileWriter.initialize(); // get the StoreFileWriter singleton sfw.writeFile( storeXML ); // write the generated XML to the File } /** * read the store in the blackboard */ public static void readStore() { try { if(DEBUG) System.out.println("Parsing store.xml"); InputReader xmlReader = InputReader.initialize(); Document storeDoc = xmlReader.prepareDocument( Config.getBlackBoardPath() + "/store.xml" ); if(DEBUG) System.out.println("Loaded store.xml as DOM"); reference = xmlReader.parseStore( storeDoc ); if(DEBUG) System.out.println("Finished parsing store.xml"); } catch( Exception e ) { e.printStackTrace(); } } /** * add the given derivative to the store * * @param pDerivative */ public static void add( Derivative pDerivative ) { getDerivatives().add( pDerivative ); } /** * see if current derivative is currently the cheapest of its type * * @param pDerivatise : ArrayList of Derivative * @return boolean */ private static boolean anythingCheaper( Derivative pDerivative ) { boolean foundCheaper = false; Price derivativePrice = pDerivative.getPrice(); DerivativeType derivativeType = pDerivative.getType(); Iterator storeIterator = getDerivatives().iterator(); while ( storeIterator.hasNext() && !foundCheaper ) { Derivative currentDerivative = storeIterator.next(); Price currentDerivativePrice = currentDerivative.getPrice(); DerivativeType currentDerivativeType = currentDerivative.getType(); boolean sameType = derivativeType.equals( currentDerivativeType ); boolean lowerPrice = ( currentDerivativePrice.compareTo( derivativePrice ) < 0 ); if ( sameType && lowerPrice ) { foundCheaper = true; } } return foundCheaper; } /** * find derivatives given player must deliver raw materials for * * @param pName : player name * @return ArrayList */ public static ArrayList findDerivativesThatNeedRawMaterials( String pName ) { ArrayList derivativesThatNeedRawMaterials = new ArrayList(); Iterator storeIterator = getDerivatives().iterator(); while ( storeIterator.hasNext() ) { Derivative currentDerivative = storeIterator.next(); if ( currentDerivative.needRawMaterial() && currentDerivative.sameCreator( pName ) ) { derivativesThatNeedRawMaterials.add( currentDerivative ); } } return derivativesThatNeedRawMaterials; } /** * find derivatives given player must deliver finished products for * * @param pName : player name * @return ArrayList */ public static ArrayList findDerivativesThatNeedFinishedProducts( String pName ) { ArrayList derivativesThatNeedFinishedProducts = new ArrayList(); Iterator storeIterator = getDerivatives().iterator(); while ( storeIterator.hasNext() ) { Derivative currentDerivative = storeIterator.next(); String derivativeBuyer = currentDerivative.getBoughtBy(); if ( currentDerivative.needFinishedProduct() && pName.compareTo( derivativeBuyer ) == 0 ) { derivativesThatNeedFinishedProducts.add( currentDerivative ); } } return derivativesThatNeedFinishedProducts; } /** * find the derivative matching the given one and update it, return success * * @param pDerivative : Derivative * @return boolean */ public static boolean updateDerivative( Derivative pDerivative ) { String updatedDerivativeName = pDerivative.getName(); boolean foundDerivative = false; for ( int i = 0 ; i < getDerivatives().size() && !foundDerivative ; i++ ) { Derivative currentDerivative = getDerivatives().get( i ); String derivativeName = currentDerivative.getName(); if ( updatedDerivativeName.compareTo( derivativeName ) == 0 ) { getDerivatives().set( i, pDerivative ); foundDerivative = true; } } return foundDerivative; } /** * determines if the given type exists in the store */ public static boolean containsType( DerivativeType pType ) { Iterator storeIterator = getDerivatives().iterator(); boolean found = false; while ( storeIterator.hasNext() ) { Derivative current = storeIterator.next(); if ( pType.equals( current.getType() ) ) found = true; } return found; } /** * return a list of taken raw material types */ public static ArrayList findTakenTypes() { ArrayList takenTypes = new ArrayList(); Iterator storeIterator = getDerivatives().iterator(); while ( storeIterator.hasNext() ) { Derivative currentDerivative = storeIterator.next(); DerivativeType currentDerivativeType = currentDerivative.getType(); takenTypes.add( currentDerivativeType ); } return takenTypes; } /** * remove the given derivative from the store and return success of operation * * @param pDerivativeName : String * @return boolean */ public static boolean removeDerivative( String pDerivativeName ) { boolean foundDerivative = false; for ( int i = 0 ; i < getDerivatives().size() && !foundDerivative ; i++ ) { Derivative currentDerivative = getDerivatives().get( i ); String derivativeName = currentDerivative.getName(); if ( pDerivativeName.compareTo( derivativeName ) == 0 ) { getDerivatives().remove( i ); foundDerivative = true; } } return foundDerivative; } /** * determine if the store is empty * * @return boolean */ public static boolean isEmpty() { return getDerivatives().isEmpty(); } /** * look at store and select derivatives to buy * * @param pPlayerName : String * @return ArrayList */ public static ArrayList checkForDerivativesToBuy( String pPlayerName ) { ArrayList derivativesToBuy = new ArrayList(); Iterator storeIterator = getDerivatives().iterator(); float bestProfit = -2; Derivative bestProfitDerivative = null; // added by Radhika to check cheapest derivative minDerPriceToBuy = 0.9f; long startTime = System.currentTimeMillis(); boolean canReprice = true; while ( storeIterator.hasNext() ) { Derivative currentDerivative = storeIterator.next(); if ( !currentDerivative.purchased() && !currentDerivative.sameCreator( pPlayerName ) ) { // This is something that can be bought BuyingAgent ba = new BuyingAgent(); float wcProfit = ba.checkDerivative( currentDerivative ); if (bestProfit < wcProfit) { bestProfit = wcProfit; bestProfitDerivative = currentDerivative; } if ( wcProfit > 0 ) { derivativesToBuy.add( currentDerivative ); } // Keep track of minimum price in store for selling if (minDerPriceToBuy > currentDerivative.getPrice().getValue()) { minDerPriceToBuy = currentDerivative.getPrice().getValue(); } // See if this derivative can be repriced. if (System.currentTimeMillis() - startTime > 15000) { // 15 seconds over // Dont reprice anymore System.out.println("PANIC: Abort reprice eval"); canReprice = false; } else { Derivative repriceTest = new Derivative(pPlayerName, new Price(1), currentDerivative.getType()); repriceTest.adjustForDelivery(true); repriceTest.adjustForFinishing(); float repricedQuality = repriceTest.getFinishedProduct().getQuality().getValue().floatValue(); if (repricedQuality > currentDerivative.getPrice().getValue() - 0.01) { // This can NOT be repriced //System.out.println("Can NOT reprice " + currentDerivative.getName() + " at " + repricedQuality + " instead of " + currentDerivative.getPrice().getValue()); canReprice = false; } else { //System.out.println("Can reprice " + currentDerivative.getName() + " at " + repricedQuality + " instead of " + currentDerivative.getPrice().getValue()); } } } } // Add the least loss derivative to the list if it is still empty, and // something must be bought and all derivatives in the store can not be // repriced if ( derivativesToBuy.isEmpty() && (bestProfitDerivative != null)) { if (canReprice) { System.out.println("CHOOSING TO REPRICE"); } else { derivativesToBuy.add( bestProfitDerivative ); } } return derivativesToBuy; } /** * Rebuild cheapest derivatives at lower price and return them * make sure they have not been purchased and that the creator is not the * given creator. * Note: While the price for these might be too high, it usually makes no sense for us to 'own' * a bunch of bad derivatives. We will therefore generally prefer to buy a single derivative * that has a minimal loss versus put a bunch of bad derivatives on the market with our name on it. * * @param pPlayerName : String * @return ArrayList */ public static ArrayList rebuildDerivatives( String pPlayerName ) { ArrayList rebuiltDerivatives = new ArrayList(); Iterator storeIterator = getDerivatives().iterator(); while ( storeIterator.hasNext() ) { Derivative currentDerivative = storeIterator.next(); Float oldPrice = currentDerivative.getPrice().getValue(); // if nothing cheaper in store with same type as current derivative, // rebuild this derivative at slightly cheaper price if ( !anythingCheaper( currentDerivative ) && !currentDerivative.purchased() && !currentDerivative.sameCreator( pPlayerName ) ) { Derivative rebuilt = currentDerivative.reprice( pPlayerName ); Float newPrice = rebuilt.getPrice().getValue(); System.out.println("Rebuilt " + currentDerivative.getName() + " from " + oldPrice.floatValue() + " to " + newPrice.floatValue()); rebuiltDerivatives.add( rebuilt ); } } return rebuiltDerivatives; } }