/** write out the data from the profile to the stream */
  public void writeProfile(PeerProfile profile, OutputStream out) throws IOException {
    String groups = null;
    if (_context.profileOrganizer().isFailing(profile.getPeer())) {
      groups = "Failing";
    } else if (!_context.profileOrganizer().isHighCapacity(profile.getPeer())) {
      groups = "Standard";
    } else {
      if (_context.profileOrganizer().isFast(profile.getPeer())) groups = "Fast, High Capacity";
      else groups = "High Capacity";

      if (_context.profileOrganizer().isWellIntegrated(profile.getPeer()))
        groups = groups + ", Integrated";
    }

    StringBuilder buf = new StringBuilder(512);
    buf.append("########################################################################")
        .append(NL);
    buf.append("# Profile for peer ").append(profile.getPeer().toBase64()).append(NL);
    if (_us != null) buf.append("# as calculated by ").append(_us.toBase64()).append(NL);
    buf.append("#").append(NL);
    buf.append("# Speed: ").append(profile.getSpeedValue()).append(NL);
    buf.append("# Capacity: ").append(profile.getCapacityValue()).append(NL);
    buf.append("# Integration: ").append(profile.getIntegrationValue()).append(NL);
    buf.append("# Groups: ").append(groups).append(NL);
    buf.append("#").append(NL);
    buf.append("########################################################################")
        .append(NL);
    buf.append("##").append(NL);
    add(buf, "speedBonus", profile.getSpeedBonus(), "Manual adjustment to the speed score");
    add(
        buf,
        "capacityBonus",
        profile.getCapacityBonus(),
        "Manual adjustment to the capacity score");
    add(
        buf,
        "integrationBonus",
        profile.getIntegrationBonus(),
        "Manual adjustment to the integration score");
    addDate(
        buf,
        "firstHeardAbout",
        profile.getFirstHeardAbout(),
        "When did we first get a reference to this peer?");
    addDate(
        buf,
        "lastHeardAbout",
        profile.getLastHeardAbout(),
        "When did we last get a reference to this peer?");
    addDate(
        buf,
        "lastHeardFrom",
        profile.getLastHeardFrom(),
        "When did we last get a message from the peer?");
    addDate(
        buf,
        "lastSentToSuccessfully",
        profile.getLastSendSuccessful(),
        "When did we last send the peer a message successfully?");
    addDate(
        buf,
        "lastFailedSend",
        profile.getLastSendFailed(),
        "When did we last fail to send a message to the peer?");
    add(
        buf,
        "tunnelTestTimeAverage",
        profile.getTunnelTestTimeAverage(),
        "Moving average as to how fast the peer replies");
    add(buf, "tunnelPeakThroughput", profile.getPeakThroughputKBps(), "KBytes/sec");
    add(buf, "tunnelPeakTunnelThroughput", profile.getPeakTunnelThroughputKBps(), "KBytes/sec");
    add(buf, "tunnelPeakTunnel1mThroughput", profile.getPeakTunnel1mThroughputKBps(), "KBytes/sec");
    buf.append(NL);

    out.write(buf.toString().getBytes());

    if (profile.getIsExpanded()) {
      // only write out expanded data if, uh, we've got it
      profile.getTunnelHistory().store(out);
      // profile.getReceiveSize().store(out, "receiveSize");
      // profile.getSendSuccessSize().store(out, "sendSuccessSize");
      profile.getTunnelCreateResponseTime().store(out, "tunnelCreateResponseTime");
      profile.getTunnelTestResponseTime().store(out, "tunnelTestResponseTime");
    }

    if (profile.getIsExpandedDB()) {
      profile.getDBHistory().store(out);
      profile.getDbIntroduction().store(out, "dbIntroduction");
      profile.getDbResponseTime().store(out, "dbResponseTime");
    }
  }