@Test public void testStep() throws Exception { Blueprint b = Blueprint.simpleBlueprint( DifferentiatedGoodType.CAPITAL, 1, DifferentiatedGoodType.CAPITAL, 1); MacroII localMacroII = new MacroII(1); localMacroII.schedule = mock(Schedule.class); // put in a fake schedule so we avoid steppables firing at random Firm f = new Firm(localMacroII); Plant localCRS = new Plant(b, new Firm(localMacroII)); localCRS.setPlantMachinery( new CRSExponentialMachinery(DifferentiatedGoodType.CAPITAL, f, 0, localCRS, 1f, 1f)); f.addPlant(localCRS); SalesDepartmentAllAtOnce stub = mock(SalesDepartmentAllAtOnce.class); when(stub.isSelling(any(Good.class))).thenReturn(Boolean.TRUE); localCRS.getOwner().registerSaleDepartment(stub, DifferentiatedGoodType.CAPITAL); // fake sales // department so that you don't try selling the stuff you build localCRS.setCostStrategy(new EmptyCostStrategy()); try { localCRS.getModel(); localCRS.getModel().getPhaseScheduler().step(localCRS.getModel()); assertEquals(localCRS.getStatus(), PlantStatus.WAITING_FOR_WORKERS); localCRS.addWorker(new Person(localCRS.getModel())); localCRS.addWorker(new Person(localCRS.getModel())); localCRS.getModel().getPhaseScheduler().step(localCRS.getModel()); assertEquals(localCRS.getStatus(), PlantStatus.WAITING_FOR_INPUT); localCRS .getOwner() .receive( Good.getInstanceOfDifferentiatedGood( DifferentiatedGoodType.CAPITAL, drs.getOwner(), 1), drs.getOwner()); localCRS.getModel().getPhaseScheduler().step(localCRS.getModel()); assertEquals( localCRS.getStatus(), PlantStatus.READY); // you should automatically start production! } catch (Exception e) { fail("Can't throw exceptions now"); } }
/** * This is called when somebody is fired/quit/removed from the plant. So far it's purely * decorative (tells the network if the GUI is on) * * @param employer the employer * @param employee the employee */ public void registerFiring(EconomicAgent employer, EconomicAgent employee) { // with no GUI, forget about it if (!MacroII.hasGUI()) return; boolean removedSuccessfully = network.removeEdges(employer, employee); assert removedSuccessfully; }
/** * tells the market that the model is starting up, and it would be a good idea to start the data * collector. It also schedules a final cleanup step to update gui if needed * * @param model */ public void start(MacroII model) { marketData.start(model, this); if (priceSeries != null) { Steppable guiUpdater = new Steppable() { @Override public void step(SimState simState) { if (!marketData.isActive()) return; final Double newPrice = marketData.getLatestObservation(MarketDataType.CLOSING_PRICE); final Double newVolume = marketData.getLatestObservation(MarketDataType.VOLUME_TRADED); final Double day = new Double(marketData.getLastObservedDay()); // if(newPrice >=0 Platform.runLater( new Runnable() { @Override public void run() { System.out.println( newPrice + "--- " + day + ", " + priceSeries.getData().size()); priceSeries.getData().add(new XYChart.Data<Number, Number>(day, newPrice)); volumeSeries.getData().add(new XYChart.Data<Number, Number>(day, newVolume)); } }); model.scheduleTomorrow(ActionOrder.CLEANUP_DATA_GATHERING, this, Priority.FINAL); panel.repaint(); } }; model.scheduleSoon(ActionOrder.CLEANUP_DATA_GATHERING, guiUpdater, Priority.FINAL); } }
/** * Remove a buyer from the registry as they exit the market * * @param buyer buyer exiting the market */ public void deregisterBuyer(EconomicAgent buyer) { boolean isNew = buyers.remove(buyer); assert isNew; // make sure it wasn't there before! if (MacroII.hasGUI()) { // todo logtodo network.removeAgent(buyer); } }
@Test public void testUrgencyFull() throws NoSuchFieldException, IllegalAccessException { // we are going to check that prices change when urgency change // the only stub is the market Market market = mock(Market.class); when(market.getLastPrice()).thenReturn(50); // so last price is 50 model.schedule = mock( Schedule .class); // we also mock the schedule to avoid the inventory control from spamming // buy orders in the schedule when(market.getGoodType()).thenReturn(UndifferentiatedGoodType.GENERIC); Firm f = new Firm(model); PurchasesDepartment dept = PurchasesDepartment.getPurchasesDepartment( 100, f, market, FixedInventoryControl.class, UrgentPriceFollowerStrategy.class, null, null) .getDepartment(); // when there is nobody to search just go at random. Field field = PurchasesDepartment.class.getDeclaredField("pricingStrategy"); field.setAccessible(true); BidPricingStrategy pricing = (BidPricingStrategy) field.get(dept); // assuming the fixed inventory control wants 6 // right now it's danger for (int i = 0; i < 10; i++) assertEquals(pricing.maxPrice(UndifferentiatedGoodType.GENERIC), 60); // barely for (int i = 0; i < 3; i++) f.receive(Good.getInstanceOfUndifferentiatedGood(UndifferentiatedGoodType.GENERIC), null); for (int i = 0; i < 10; i++) assertEquals(pricing.maxPrice(UndifferentiatedGoodType.GENERIC), 50); // acceptable for (int i = 0; i < 3; i++) f.receive(Good.getInstanceOfUndifferentiatedGood(UndifferentiatedGoodType.GENERIC), null); for (int i = 0; i < 10; i++) assertEquals(pricing.maxPrice(UndifferentiatedGoodType.GENERIC), 40); // too much for (int i = 0; i < 30; i++) f.receive(Good.getInstanceOfUndifferentiatedGood(UndifferentiatedGoodType.GENERIC), null); for (int i = 0; i < 10; i++) assertEquals(pricing.maxPrice(UndifferentiatedGoodType.GENERIC), 25); }
/** * This is called onyl if the GUI is on, and only to show the trade on the network * * @param sender the agent giving up the goods * @param receiver the agent receiving the goods * @param g what kind of good? * @param quantity how much is exchanged? */ private void registerTradeOnNetwork( EconomicAgent sender, EconomicAgent receiver, GoodType g, int quantity) { // if graphing is not active, don't bother assert MacroII.hasGUI(); assert network.containsAgent(sender); assert network.containsAgent(receiver); // if both are registered network.registerInventoryDelivery(sender, receiver, g, quantity); }
/** * Remove a seller from the registry as they exit the market * * @param seller seller exiting the market */ public void deregisterSeller(EconomicAgent seller) { boolean isNew = sellers.remove(seller); assert isNew; // make sure it wasn't there before! if (MacroII.hasGUI()) { // todo logtodo // remove agent to the network network.removeAgent(seller); } }
/** * Add a buyer to the registry as they enter the market * * @param buyer buyer entering the market */ public void registerBuyer(EconomicAgent buyer) { boolean isNew = buyers.add(buyer); // addSalesDepartmentListener it to the set assert isNew; // make sure it wasn't there before! // record it, if necessary if (MacroII.hasGUI()) { // todo logtodo network.addAgent(buyer); } }
/** * During weekends the market stores the volume * * @param model the simstate */ public void weekEnd(MacroII model) { lastWeekVolume = weeklyVolume; // if(!getGoodType().isLabor()) // volume.add(new Week(model.getWeeksPassed(), (int) (model.getWeeksPassed() / // model.getWeekLength())),weeklyVolume); //addSalesDepartmentListener it to the weeks weeklyVolume = 0; // if there is GUI, clear the network if (MacroII.hasGUI()) { network.weekEnd(); // todo logtodo } }
private void startSteppables(final MacroII model) { final DailyGoodTree goodTree = this; // two steppables: // FIRST: during production you consume everything you had, and create new goods to sell model.scheduleSoon( ActionOrder.PRODUCTION, new Steppable() { @Override public void step(SimState state) { if (!isActive()) return; eatEverythingAndRemoveQuotes(); // create new goods createNewGoods(goodTree); assert hasAny(market.getGoodType()); // reschedule this model.scheduleTomorrow(ActionOrder.PRODUCTION, this); } }); // second, during trade, start by selling at least one good model.scheduleSoon( ActionOrder.TRADE, new Steppable() { @Override public void step(SimState state) { if (!isActive()) { return; } sellIfPossible(market); model.scheduleTomorrow(ActionOrder.TRADE, this); } }); }
@Test public void testProduce() throws Exception { macro.schedule = new Schedule(); // create a real schedule, please. assertTrue(crs.getModel().schedule.scheduleComplete()); // the schedule should be empty! assertTrue(!crs.getOwner().hasAny(DifferentiatedGoodType.CAPITAL)); assertTrue(crs.getOwner().hasHowMany(DifferentiatedGoodType.CAPITAL) == 0); crs.getModel().schedule.reset(); crs.getModel() .schedule .scheduleOnce( Schedule.EPOCH, new Person(crs.getModel())); // this is to have the steppable not at time -1 crs.setCostStrategy(new EmptyCostStrategy()); // crs.completeProductionRunNow(); crs.startProductionRun(); // System.out.println(crs.getModel().schedule.getTime()); assertEquals(crs.getStatus(), PlantStatus.READY); assertTrue(crs.getOwner().hasAny(DifferentiatedGoodType.CAPITAL)); assertTrue(crs.getOwner().hasHowMany(DifferentiatedGoodType.CAPITAL) == 2); // here we produced 2 crs.setBlueprint( Blueprint.simpleBlueprint( DifferentiatedGoodType.CAPITAL, 2, DifferentiatedGoodType.CAPITAL, 1)); // dumb technology to test inputs crs.startProductionRun(); assertEquals(crs.getStatus(), PlantStatus.READY); assertTrue( crs.getOwner().hasAny(DifferentiatedGoodType.CAPITAL)); // should still have the stuff assertTrue( crs.getOwner().hasHowMany(DifferentiatedGoodType.CAPITAL) == 1); // burned two, made one crs.startProductionRun(); assertEquals(crs.getStatus(), PlantStatus.WAITING_FOR_INPUT); assertTrue(crs.getOwner().hasAny(DifferentiatedGoodType.CAPITAL)); // no change! assertTrue(crs.getOwner().hasHowMany(DifferentiatedGoodType.CAPITAL) == 1); // check that the counts are right Assert.assertEquals(crs.getOwner().getTodayConsumption(DifferentiatedGoodType.CAPITAL), 2); Assert.assertEquals(crs.getOwner().getTodayProduction(DifferentiatedGoodType.CAPITAL), 3); }
protected Market(GoodType goodType) { this.goodType = goodType; // if the market is a labor market, buyers hire and sellers get hired. Otherwise buyers receive // and sellers earn if (goodType.isLabor()) policy = new SimpleHiringTradePolicy(); else policy = SimpleGoodTradePolicy.getInstance(); buyers = FXCollections.observableSet(new HashSet<>()); sellers = FXCollections.observableSet(new HashSet<>()); marketData = new MarketData(); // build the gui inspector if (MacroII.hasGUI()) { marketInspector = buildInspector(); } }
/** * This method is called whenever two agents agree on an exchange. It can be called by the market * or the agents themselves. * * @param buyer the buyer * @param seller the seller * @param good the good being exchanged * @param price the price */ public PurchaseResult trade( EconomicAgent buyer, EconomicAgent seller, Good good, int price, Quote buyerQuote, Quote sellerQuote) { Preconditions.checkArgument(buyer != seller, "buyer and seller are the same person!"); assert getBuyers().contains(buyer) : buyer.toString() + " ----- " + buyers; assert getSellers().contains(seller); double sellerCost = good.getLastValidPrice(); // record the price of the good BEFORE it is traded, so we can // learn its markup PurchaseResult result = policy.trade(buyer, seller, good, price, buyerQuote, sellerQuote, this); if (result == PurchaseResult.SUCCESS) { // record lastPrice = price; lastMarkup = (price - sellerCost) / sellerCost; todaySumOfClosingPrices += price; lastFilledAsk = sellerQuote.getPriceQuoted(); lastFilledBid = buyerQuote.getPriceQuoted(); weeklyVolume++; todayVolume++; // tell the listeners! for (TradeListener tl : tradeListeners) tl.tradeEvent(buyer, seller, good, price, sellerQuote, buyerQuote); // if there is GUI tell the records if (MacroII.hasGUI()) { // record it on the timeline // todo logtodo // register it on the network! registerTradeOnNetwork(seller, buyer, good.getType(), 1); } } return result; }
protected TabbedInspector buildInspector() { // create the network network = new ExchangeNetwork(getGoodType()); // if there is no GUI, forget about it Preconditions.checkState(MacroII.hasGUI()); // can't be called otherwise! TabbedInspector toReturn = new TabbedInspector(true); toReturn.setName(toString() + " inspector"); /** * ******************************************* Prices ****************************************** */ // switching to JavaFX for fun and profit // set up the chart panel = new JFXPanel(); NumberAxis xAxis = new NumberAxis(); NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Day"); yAxis.setLabel("Price"); final LineChart<Number, Number> priceChart = new LineChart<>(xAxis, yAxis); priceChart.setAnimated(true); // set up the series priceSeries = new XYChart.Series<>(); priceSeries.setName("LastClosingPrice"); // now make the price update whenever data updates! // use steppable to update priceChart.getData().add(priceSeries); Platform.runLater( new Runnable() { @Override public void run() { panel.setScene(new Scene(priceChart)); } }); // we are going to add the new JPanel IN the new inspector closingPriceInspector = new Inspector() { @Override public void updateInspector() { SwingUtilities.invokeLater( new Runnable() { public void run() { repaint(); } }); } }; closingPriceInspector.setVolatile(true); closingPriceInspector.setLayout(new BorderLayout()); // this centers it closingPriceInspector.add(panel); toReturn.addInspector(closingPriceInspector, "Closing price"); /** * ******************************************* VOLUME ****************************************** */ // switching to JavaFX for fun and profit // set up the chart final JFXPanel panel2 = new JFXPanel(); xAxis = new NumberAxis(); yAxis = new NumberAxis(); xAxis.setLabel("Day"); yAxis.setLabel("Volume"); final LineChart<Number, Number> volumeChart = new LineChart<>(xAxis, yAxis); volumeChart.setAnimated(true); volumeChart.setCreateSymbols(false); // set up the series volumeSeries = new XYChart.Series<Number, Number>(); volumeSeries.setName("Daily Volume Traded"); volumeChart.getData().add(volumeSeries); Platform.runLater( new Runnable() { @Override public void run() { panel2.setScene(new Scene(volumeChart)); } }); // we are going to add the new JPanel IN the new inspector Inspector closingVolumeInspector = new Inspector() { @Override public void updateInspector() { SwingUtilities.invokeLater( new Runnable() { public void run() { repaint(); } }); } }; closingVolumeInspector.setVolatile(true); closingVolumeInspector.setLayout(new BorderLayout()); // this centers it closingVolumeInspector.add(panel2); toReturn.addInspector(closingVolumeInspector, "Volume"); /** * ******************************************* TIMELINE * ****************************************** */ // todo logtodo /** * ************************************************* Network * ************************************************* */ Inspector networkInspector = new Inspector() { @Override public void updateInspector() { SwingUtilities.invokeLater( new Runnable() { public void run() { repaint(); } }); } }; networkInspector.setLayout(new BorderLayout()); // add the visualization networkInspector.add(network.getVisualization()); toReturn.addInspector(networkInspector, "Network"); return toReturn; }
@Before public void setUp() throws Exception { Blueprint b = new Blueprint.Builder() .output(DifferentiatedGoodType.CAPITAL, 2) .build(); // create a simple output macro = new MacroII(1); macro.schedule = mock(Schedule.class); // put in a fake schedule so we avoid steppables firing at random Firm f = new Firm(macro); crs = new Plant(b, new Firm(macro)); crs.setPlantMachinery( new CRSExponentialMachinery(DifferentiatedGoodType.CAPITAL, f, 0, crs, 1f, 1f)); irs = new Plant(b, new Firm(macro)); irs.setPlantMachinery( new IRSExponentialMachinery(DifferentiatedGoodType.CAPITAL, f, 0, irs, 1f, 1f)); drs = new Plant(b, new Firm(macro)); drs.setPlantMachinery( new DRSExponentialMachinery(DifferentiatedGoodType.CAPITAL, f, 0, drs, 1f, 1f)); Person w1 = new Person(macro); Person w2 = new Person(macro); crs.addWorker(w1); crs.addWorker(w2); w1.hired(crs.getOwner(), 9999999); w2.hired(crs.getOwner(), 9999999); w1 = new Person(macro); w2 = new Person(macro); irs.addWorker(w1); irs.addWorker(w2); w1.hired(crs.getOwner(), 9999999); w2.hired(crs.getOwner(), 9999999); w1 = new Person(macro); w2 = new Person(macro); drs.addWorker(w1); drs.addWorker(w2); w1.hired(crs.getOwner(), 9999999); w2.hired(crs.getOwner(), 9999999); SalesDepartmentAllAtOnce stub = mock(SalesDepartmentAllAtOnce.class); crs.getOwner() .registerSaleDepartment( stub, DifferentiatedGoodType .CAPITAL); // fake sales department so that you don't sell the stuff you // completeProductionRunNow irs.getOwner() .registerSaleDepartment( stub, DifferentiatedGoodType .CAPITAL); // fake sales department so that you don't sell the stuff you // completeProductionRunNow drs.getOwner() .registerSaleDepartment( stub, DifferentiatedGoodType .CAPITAL); // fake sales department so that you don't sell the stuff you // completeProductionRunNow when(stub.isSelling(any(Good.class))).thenReturn(Boolean.TRUE); crs.setCostStrategy(new EmptyCostStrategy()); irs.setCostStrategy(new EmptyCostStrategy()); drs.setCostStrategy(new EmptyCostStrategy()); }
@Test public void testTotalInputs() { Blueprint b = Blueprint.simpleBlueprint(DifferentiatedGoodType.CAPITAL, 1, BEEF, 1); MacroII localMacroII = mock(MacroII.class); PhaseScheduler scheduler = mock(PhaseScheduler.class); when(localMacroII.getCurrentPhase()).thenReturn(ActionOrder.PRODUCTION); when(localMacroII.getPhaseScheduler()).thenReturn(scheduler); when(localMacroII.getWeekLength()).thenReturn(7f); Firm f = new Firm(localMacroII); Plant localCRS = new Plant(b, new Firm(localMacroII)); localCRS.setPlantMachinery( new LinearConstantMachinery(DifferentiatedGoodType.CAPITAL, f, 0, localCRS)); f.addPlant(localCRS); localCRS.addWorker(new Person(localCRS.getModel())); localCRS.addWorker(new Person(localCRS.getModel())); localCRS .getOwner() .registerSaleDepartment( mock(SalesDepartmentAllAtOnce.class), BEEF); // fake sales department so that you don't sell the stuff you // completeProductionRunNow localCRS.setCostStrategy(new InputCostStrategy(localCRS)); // initially they should be set up to 0 assertEquals(localCRS.getThisWeekInputCosts(), 0); assertEquals(localCRS.getLastWeekInputCosts(), 0); // now when I step you, you should say you are waiting for inputs localCRS.getModel(); localCRS.step(localMacroII); assertEquals(localCRS.getStatus(), PlantStatus.WAITING_FOR_INPUT); assertEquals(localCRS.getThisWeekInputCosts(), 0); // input costs should still be 0 assertEquals(localCRS.getLastWeekInputCosts(), 0); // now I give you one input that costs 10$ localCRS .getOwner() .receive( Good.getInstanceOfDifferentiatedGood( DifferentiatedGoodType.CAPITAL, drs.getOwner(), 10), drs.getOwner()); localCRS.step(localCRS.getModel()); assertEquals(localCRS.getThisWeekInputCosts(), 10); // input costs should still now be 10 assertEquals(localCRS.getLastWeekInputCosts(), 0); // I'll give you another and force you to step again localCRS .getOwner() .receive( Good.getInstanceOfDifferentiatedGood( DifferentiatedGoodType.CAPITAL, drs.getOwner(), 10), drs.getOwner()); localCRS.step(localCRS.getModel()); assertEquals(localCRS.getThisWeekInputCosts(), 20); // input costs should still now be 20 assertEquals(localCRS.getLastWeekInputCosts(), 0); // with weekend it should reset this week and make lastweekinput costs equal 20 localCRS.weekEnd(7); assertEquals(localCRS.getThisWeekInputCosts(), 0); // reset to 0 assertEquals(localCRS.getLastWeekInputCosts(), 20); // now it's 20 // try one more time localCRS .getOwner() .receive( Good.getInstanceOfDifferentiatedGood( DifferentiatedGoodType.CAPITAL, drs.getOwner(), 10), drs.getOwner()); localCRS.step(localCRS.getModel()); assertEquals(localCRS.getThisWeekInputCosts(), 10); // input costs should now be 10 assertEquals(localCRS.getLastWeekInputCosts(), 20); // this should be stuck at 20 // new weekend, forget 20$ and reset this week localCRS.weekEnd(14); assertEquals(localCRS.getThisWeekInputCosts(), 0); // reset to 0 assertEquals(localCRS.getLastWeekInputCosts(), 10); // now it's 10 // another weekend, everything is at 0 localCRS.weekEnd(0); assertEquals(localCRS.getThisWeekInputCosts(), 0); // reset to 0 assertEquals(localCRS.getLastWeekInputCosts(), 0); // now it's 10 }