/**
   * 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;
  }
  /**
   * Called by a buyer that wants to buy directly from this agent, not going through the market.
   *
   * @param buyerQuote the quote (including the offer price) of the buyer
   * @param sellerQuote the quote (including the offer price) of the seller; I expect the buyer to
   *     have achieved this through asked for an offer function
   * @return a purchaseResult including whether the trade was succesful and if so the final price
   */
  @Override
  public PurchaseResult shopHere(Quote buyerQuote, Quote sellerQuote) {
    int finalPrice = market.price(sellerQuote.getPriceQuoted(), buyerQuote.getPriceQuoted());
    assert sellerQuote.getGood() != null;
    assert this.has(sellerQuote.getGood());

    // exchange hostages
    market.trade(
        buyerQuote.getAgent(), this, sellerQuote.getGood(), finalPrice, buyerQuote, sellerQuote);
    this.logEvent(
        this,
        MarketEvents.SOLD,
        this.getModel().getCurrentSimulationTimeInMillis(),
        "price: " + finalPrice + ", through buyFromHere()"); // sold a good
    assert !this.has(sellerQuote.getGood());

    PurchaseResult toReturn = PurchaseResult.SUCCESS;
    toReturn.setPriceTrade(finalPrice);
    return toReturn;
  }
 /**
  * A buyer asks the sales department for the price they are willing to sell one of their good.
  *
  * @param buyer the economic agent that asks you that
  * @return a price quoted or -1 if there are no quotes
  */
 @Override
 public Quote askedForASaleQuote(EconomicAgent buyer, GoodType type) {
   Good good = peekGood(type);
   if (good != null) return Quote.newSellerQuote(this, saleQuote, good);
   else return Quote.emptySellQuote(null);
 }