<commit_before>
#include "SystemAudacity.h"
#include <Jumpropes/Functions.h>

AudacityRover::SystemAudacity::SystemAudacity() : OpenALRF::SystemLinux()
{
}

bool AudacityRover::SystemAudacity::HasValidActiveNetwork()
{
   bool HasNetwork = false;

   auto list = Jumpropes::ListNetworkInterfaces();
   for (auto netif : list)
   {
      std::cout << netif.IP.ip.getValue() << std::endl;

      if (!netif.IP.ip.startsWith_ansi("127.") && !netif.IP.ip.startsWith_ansi("0.") && !netif.IP.ip.startsWith_ansi("169.254."))
      {
         HasNetwork = true;
         break;
      }
   }
   std::cout << "-----" << std::endl;

   return HasNetwork;
}

std::string AudacityRover::SystemAudacity::GetStatusInfo()
{
   return std::string();
}
<commit_msg>so that's why<commit_after>
#include "SystemAudacity.h"
#include <Jumpropes/Functions.h>

AudacityRover::SystemAudacity::SystemAudacity() : OpenALRF::SystemLinux()
{
}

bool AudacityRover::SystemAudacity::HasValidActiveNetwork()
{
   bool HasNetwork = false;

   // note for RaspberryPi; you need to remove the 127.0.1.1 line in the /etc/hosts file as it will confuse this into thinking that's the only IP address we have
   auto list = Jumpropes::ListNetworkInterfaces();
   for (auto netif : list)
   {
      if (!netif.IP.ip.startsWith_ansi("127.") && !netif.IP.ip.startsWith_ansi("0.") && !netif.IP.ip.startsWith_ansi("169.254."))
      {
         HasNetwork = true;
         break;
      }
   }

   return HasNetwork;
}

std::string AudacityRover::SystemAudacity::GetStatusInfo()
{
   return std::string();
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <Riostream.h>

#include <TDirectory.h>

#include "AliRunLoader.h"
#include <AliESD.h>
#include "AliLog.h"
#include "AliT0Loader.h"
#include <TClonesArray.h>
#include "AliT0RecPoint.h"
#include "AliRawReader.h"
#include "AliT0RawReader.h"
#include "AliT0digit.h"
#include "AliT0Reconstructor.h"
#include "AliT0Parameters.h"
#include "AliT0Calibrator.h"
#include "AliCDBLocal.h"
#include "AliCDBStorage.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"

#include <TArrayI.h>
#include <TGraph.h>

ClassImp(AliT0Reconstructor)

  AliT0Reconstructor:: AliT0Reconstructor(): AliReconstructor(),
			fDigits(NULL),
			fTree(0x0),
			fZposition(0)

{
 AliDebug(1,"Start reconstructor ");
}
//____________________________________________________________________

AliT0Reconstructor::AliT0Reconstructor(const AliT0Reconstructor &r):
  fDigits(NULL),
  fTree(0x0),
  fZposition(0)

{
  //
  // AliT0Reconstructor copy constructor
  //

  ((AliT0Reconstructor &) r).Copy(*this);

}

//_____________________________________________________________________________
AliT0Reconstructor &AliT0Reconstructor::operator=(const AliT0Reconstructor &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliT0Reconstructor &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________

void AliT0Reconstructor::Reconstruct(TTree*digitsTree, TTree*clustersTree) const

{
// T0 digits reconstruction
// T0RecPoint writing

  Float_t  timeDelayLED[24];
  Float_t zdetA,zdetC;
  TObjArray slewingLEDrec;
  TObjArray walk;

  TArrayI * timeCFD = new TArrayI(24);
  TArrayI * timeLED = new TArrayI(24);
  TArrayI * chargeQT0 = new TArrayI(24);
  TArrayI * chargeQT1 = new TArrayI(24);

  AliT0Parameters* param = AliT0Parameters::Instance();
  param->Init();
  AliT0Calibrator *calib=new AliT0Calibrator();

  Int_t mV2Mip = param->GetmV2Mip();
  //mV2Mip = param->GetmV2Mip();
  Int_t channelWidth = param->GetChannelWidth() ;

  for (Int_t i=0; i<24; i++){
    TGraph* gr = param ->GetSlewRec(i);
    slewingLEDrec.AddAtAndExpand(gr,i) ;
  }
  zdetC = param->GetZposition(0);
  zdetA  = param->GetZposition(1);

  AliDebug(1,Form("Start DIGITS reconstruction "));

  TBranch *brDigits=digitsTree->GetBranch("T0");
  AliT0digit *fDigits = new AliT0digit() ;
  if (brDigits) {
    brDigits->SetAddress(&fDigits);
  }else{
    cerr<<"EXEC Branch T0 digits not found"<<endl;
    return;
  }

  digitsTree->GetEvent(0);
  digitsTree->GetEntry(0);
  brDigits->GetEntry(0);
  fDigits->GetTimeCFD(*timeCFD);
  fDigits->GetTimeLED(*timeLED);
  fDigits->GetQT0(*chargeQT0);
  fDigits->GetQT1(*chargeQT1);

  Float_t besttimeA=999999;
  Float_t besttimeC=999999;
  Int_t pmtBestA=99999;
  Int_t pmtBestC=99999;
  Float_t timeDiff=999999, meanTime=0;

   AliT0RecPoint* frecpoints= new AliT0RecPoint ();
   clustersTree->Branch( "T0", "AliT0RecPoint" ,&frecpoints, 405,1);

  Float_t time[24], adc[24];
  for (Int_t ipmt=0; ipmt<24; ipmt++) {
    if(timeCFD->At(ipmt)>0 ){
      Int_t qt0= chargeQT0->At(ipmt);
      Int_t qt1= chargeQT1->At(ipmt);
      if((qt1-qt0)>0)  adc[ipmt] = TMath::Exp( Double_t (channelWidth*(qt1-qt0)/1000));
      time[ipmt] = channelWidth * (calib-> WalkCorrection( ipmt,qt1 , timeCFD->At(ipmt) ) ) ;

      //LED
      Double_t sl = (timeLED->At(ipmt) - timeCFD->At(ipmt)- (1000.*timeDelayLED[ipmt]/channelWidth))*channelWidth;
      Double_t qt=((TGraph*)slewingLEDrec.At(ipmt))->Eval(sl/1000.);
      frecpoints->SetTime(ipmt,time[ipmt]);
      frecpoints->SetAmp(ipmt,adc[ipmt]);
      frecpoints->SetAmpLED(ipmt,qt);
    }
    else {
      time[ipmt] = 0;
      adc[ipmt] = 0;
    }
  }

  for (Int_t ipmt=0; ipmt<12; ipmt++){
    if(time[ipmt] > 1 ) {
      if(time[ipmt]<besttimeC){
	besttimeC=time[ipmt]; //timeC
	pmtBestC=ipmt;
      }
    }
  }
  for ( Int_t ipmt=12; ipmt<24; ipmt++){
    if(time[ipmt] > 1) {
      if(time[ipmt]<besttimeA) {
	besttimeA=time[ipmt]; //timeA
        pmtBestA=ipmt;}
    }
  }
  if(besttimeA !=999999)  frecpoints->SetTimeBestA(Int_t(besttimeA));
  if( besttimeC != 999999 ) frecpoints->SetTimeBestC(Int_t(besttimeC));
  AliDebug(1,Form(" besttimeA %f ps,  besttimeC %f ps",besttimeA, besttimeC));
  Float_t c = 0.0299792; // cm/ps
  Float_t vertex = 0;
  if(besttimeA !=999999 && besttimeC != 999999 ){
    timeDiff = besttimeC - besttimeA;
    meanTime = (besttimeA + besttimeC)/2.;
    vertex = c*(timeDiff)/2.; //-(lenr-lenl))/2;
    AliDebug(1,Form("  timeDiff %f ps,  meanTime %f ps, vertex %f cm",timeDiff, meanTime,vertex ));
    frecpoints->SetVertex(vertex);
    frecpoints->SetMeanTime(Int_t(meanTime));

  }
  clustersTree->Fill();
}

//_______________________________________________________________________

void AliT0Reconstructor::Reconstruct(AliRawReader* rawReader, TTree*recTree) const
{
// T0 raw ->
// T0RecPoint writing

    //Q->T-> coefficients !!!! should be asked!!!
  Float_t  timeDelayLED[24];
  Float_t zdetA,zdetC;
  TObjArray slewingLEDrec;
  TObjArray walk;

  TArrayI * timeCFD = new TArrayI(24);
  TArrayI * timeLED = new TArrayI(24);
  TArrayI * chargeQT0 = new TArrayI(24);
  TArrayI * chargeQT1 = new TArrayI(24);

   AliT0RawReader myrawreader(rawReader);
   if (!myrawreader.Next())
     AliDebug(1,Form(" no raw data found!! %i", myrawreader.Next()));
   Int_t allData[110][5];
   for (Int_t i=0; i<110; i++) {
     allData[i][0]=myrawreader.GetData(i,0);
   }

  AliT0Parameters* param = AliT0Parameters::Instance();
  param->Init();
  AliT0Calibrator *calib=new AliT0Calibrator();

  Int_t mV2Mip = param->GetmV2Mip();
  //mV2Mip = param->GetmV2Mip();
  Int_t channelWidth = param->GetChannelWidth() ;

  for (Int_t i=0; i<24; i++){
    TGraph* gr = param ->GetSlewRec(i);
    slewingLEDrec.AddAtAndExpand(gr,i) ;
  }

  zdetC = param->GetZposition(0);
  zdetA  = param->GetZposition(1);

   for (Int_t in=0; in<24; in++)
     {
       timeLED->AddAt(allData[in+1][0],in);
       timeCFD->AddAt(allData[in+25][0],in);
       chargeQT1->AddAt(allData[in+55][0],in);
       chargeQT0->AddAt(allData[in+79][0],in);
       AliDebug(10, Form(" readed Raw %i %i %i %i %i", in, timeLED->At(in),timeCFD->At(in),chargeQT0->At(in),chargeQT1->At(in)));
     }

  Float_t besttimeA=999999;
  Float_t besttimeC=999999;
  Int_t pmtBestA=99999;
  Int_t pmtBestC=99999;
  Float_t timeDiff=999999, meanTime=0;

  AliT0RecPoint* frecpoints= new AliT0RecPoint ();

  recTree->Branch( "T0", "AliT0RecPoint" ,&frecpoints, 405,1);

  Float_t time[24], adc[24];
  for (Int_t ipmt=0; ipmt<24; ipmt++) {
    if(timeCFD->At(ipmt)>0 ){
      Int_t qt0= chargeQT0->At(ipmt);
      Int_t qt1= chargeQT1->At(ipmt);
      if((qt1-qt0)>0)  adc[ipmt] = TMath::Exp( Double_t (channelWidth*(qt1-qt0)/1000));
      time[ipmt] = channelWidth * (calib-> WalkCorrection( ipmt,qt1 , timeCFD->At(ipmt) ) ) ;
      Double_t sl = (timeLED->At(ipmt) - timeCFD->At(ipmt)- (1000.*timeDelayLED[ipmt]/channelWidth))*channelWidth;
      Double_t qt=((TGraph*)slewingLEDrec.At(ipmt))->Eval(sl/1000.);
      frecpoints->SetTime(ipmt,time[ipmt]);
      frecpoints->SetAmp(ipmt,adc[ipmt]);
      frecpoints->SetAmpLED(ipmt,qt);
    }
    else {
      time[ipmt] = 0;
      adc[ipmt] = 0;
    }
  }

  for (Int_t ipmt=0; ipmt<12; ipmt++){
    if(time[ipmt] > 1 ) {
      if(time[ipmt]<besttimeC){
	besttimeC=time[ipmt]; //timeC
	pmtBestC=ipmt;
      }
    }
  }
  for ( Int_t ipmt=12; ipmt<24; ipmt++){
    if(time[ipmt] > 1) {
      if(time[ipmt]<besttimeA) {
	besttimeA=time[ipmt]; //timeA
        pmtBestA=ipmt;}
    }
  }
  if(besttimeA !=999999)  frecpoints->SetTimeBestA(Int_t(besttimeA));
  if( besttimeC != 999999 ) frecpoints->SetTimeBestC(Int_t(besttimeC));
  AliDebug(1,Form(" besttimeA %f ps,  besttimeC %f ps",besttimeA, besttimeC));
  Float_t c = 0.0299792; // cm/ps
  Float_t vertex = 0;
  if(besttimeA !=999999 && besttimeC != 999999 ){
    timeDiff = besttimeC - besttimeA;
    meanTime = (besttimeA + besttimeC)/2.;
    vertex = c*(timeDiff)/2.; //-(lenr-lenl))/2;
    AliDebug(1,Form("  timeDiff %f ps,  meanTime %f ps, vertex %f cm",timeDiff, meanTime,vertex ));
    frecpoints->SetVertex(vertex);
    frecpoints->SetMeanTime(Int_t(meanTime));

  }
  recTree->Fill();
}
//____________________________________________________________

void AliT0Reconstructor::FillESD(AliRunLoader* runLoader, AliESD *pESD) const
{

  /***************************************************
  Resonstruct digits to vertex position
  ****************************************************/

  if (!runLoader) {
    AliError("Reconstruct >> No run loader");
    return;
  }

  AliDebug(1,Form("Start FillESD T0"));

  AliT0Loader* pStartLoader = (AliT0Loader*) runLoader->GetLoader("T0Loader");

  pStartLoader->LoadRecPoints("READ");

  TTree *treeR = pStartLoader->TreeR();

   AliT0RecPoint* frecpoints= new AliT0RecPoint ();
    if (!frecpoints) {
    AliError("Reconstruct Fill ESD >> no recpoints found");
    return;
  }

  AliDebug(1,Form("Start FillESD T0"));
  TBranch *brRec = treeR->GetBranch("T0");
  if (brRec) {
    brRec->SetAddress(&frecpoints);
  }else{
    cerr<<"EXEC Branch T0 rec not found"<<endl;
    // exit(111);
    return;
  }

    brRec->GetEntry(0);
    Float_t timeStart, Zposition, amp[24], time[24];
    Int_t mean0 = 12450;
    Int_t i;
    Zposition = frecpoints -> GetVertex();
    timeStart = frecpoints -> GetMeanTime() - mean0;
    for ( i=0; i<24; i++) {
       time[i] = Float_t (frecpoints -> GetTime(i)) / 1000.; // ps to ns
      amp[i] = frecpoints -> GetAmp(i);
    }
    pESD->SetT0zVertex(Zposition); //vertex Z position
    pESD->SetT0(timeStart);        // interaction time
    pESD->SetT0time(time);         // best TOF on each PMT
    pESD->SetT0amplitude(amp);     // number of particles(MIPs) on each PMT
    cout<<" ESD >> "<<Zposition<<" "<<timeStart<<endl;

    pStartLoader->UnloadRecPoints();

} // vertex in 3 sigma

<commit_msg>memory leak eliminated<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <Riostream.h>

#include <TDirectory.h>

#include "AliRunLoader.h"
#include <AliESD.h>
#include "AliLog.h"
#include "AliT0Loader.h"
#include "AliT0RecPoint.h"
#include "AliRawReader.h"
#include "AliT0RawReader.h"
#include "AliT0digit.h"
#include "AliT0Reconstructor.h"
#include "AliT0Parameters.h"
#include "AliT0Calibrator.h"
#include "AliCDBLocal.h"
#include "AliCDBStorage.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"

#include <TArrayI.h>
#include <TGraph.h>
//#include <TGeoManager.h>
//#include <TClonesArray.h>
//#include <TString.h>
//#include <TGeoPNEntry.h>
//#include <TGeoPhysicalNode.h>
//#include  <TGeoHMatrix.h>

ClassImp(AliT0Reconstructor)

  AliT0Reconstructor:: AliT0Reconstructor(): AliReconstructor(),
					     fZposition(0)

{
 AliDebug(1,"Start reconstructor ");
}
//____________________________________________________________________

AliT0Reconstructor::AliT0Reconstructor(const AliT0Reconstructor &r):
  fZposition(0)

{
  //
  // AliT0Reconstructor copy constructor
  //

  ((AliT0Reconstructor &) r).Copy(*this);

}

//_____________________________________________________________________________
AliT0Reconstructor &AliT0Reconstructor::operator=(const AliT0Reconstructor &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliT0Reconstructor &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________

void AliT0Reconstructor::Reconstruct(TTree*digitsTree, TTree*clustersTree) const

{
// T0 digits reconstruction
// T0RecPoint writing

  Float_t  timeDelayLED[24];
  Float_t zdetA,zdetC;
  TObjArray slewingLEDrec;
  TObjArray walk;

  TArrayI * timeCFD = new TArrayI(24);
  TArrayI * timeLED = new TArrayI(24);
  TArrayI * chargeQT0 = new TArrayI(24);
  TArrayI * chargeQT1 = new TArrayI(24);

  AliT0Parameters* param = AliT0Parameters::Instance();
  param->Init();
  AliT0Calibrator *calib=new AliT0Calibrator();

  Int_t mV2Mip = param->GetmV2Mip();
  //mV2Mip = param->GetmV2Mip();
  Int_t channelWidth = param->GetChannelWidth() ;

  for (Int_t i=0; i<24; i++){
    TGraph* gr = param ->GetSlewRec(i);
    slewingLEDrec.AddAtAndExpand(gr,i) ;
  }
  zdetC = param->GetZposition(0);
  zdetA  = param->GetZposition(1);

  AliDebug(1,Form("Start DIGITS reconstruction "));

  TBranch *brDigits=digitsTree->GetBranch("T0");
  AliT0digit *fDigits = new AliT0digit() ;
  if (brDigits) {
    brDigits->SetAddress(&fDigits);
  }else{
    cerr<<"EXEC Branch T0 digits not found"<<endl;
    return;
  }

  digitsTree->GetEvent(0);
  digitsTree->GetEntry(0);
  brDigits->GetEntry(0);
  fDigits->GetTimeCFD(*timeCFD);
  fDigits->GetTimeLED(*timeLED);
  fDigits->GetQT0(*chargeQT0);
  fDigits->GetQT1(*chargeQT1);

  Float_t besttimeA=999999;
  Float_t besttimeC=999999;
  Int_t pmtBestA=99999;
  Int_t pmtBestC=99999;
  Float_t timeDiff=999999, meanTime=0;

   AliT0RecPoint* frecpoints= new AliT0RecPoint ();
   clustersTree->Branch( "T0", "AliT0RecPoint" ,&frecpoints, 405,1);

  Float_t time[24], adc[24];
  for (Int_t ipmt=0; ipmt<24; ipmt++) {
    if(timeCFD->At(ipmt)>0 ){
      Int_t qt0= chargeQT0->At(ipmt);
      Int_t qt1= chargeQT1->At(ipmt);
      if((qt1-qt0)>0)  adc[ipmt] = TMath::Exp( Double_t (channelWidth*(qt1-qt0)/1000));
      time[ipmt] = channelWidth * (calib-> WalkCorrection( ipmt,qt1 , timeCFD->At(ipmt) ) ) ;

      //LED
      Double_t sl = (timeLED->At(ipmt) - timeCFD->At(ipmt)- (1000.*timeDelayLED[ipmt]/channelWidth))*channelWidth;
      Double_t qt=((TGraph*)slewingLEDrec.At(ipmt))->Eval(sl/1000.);
      frecpoints->SetTime(ipmt,time[ipmt]);
      frecpoints->SetAmp(ipmt,adc[ipmt]);
      frecpoints->SetAmpLED(ipmt,qt);
    }
    else {
      time[ipmt] = 0;
      adc[ipmt] = 0;
    }
  }

  for (Int_t ipmt=0; ipmt<12; ipmt++){
    if(time[ipmt] > 1 ) {
      if(time[ipmt]<besttimeC){
	besttimeC=time[ipmt]; //timeC
	pmtBestC=ipmt;
      }
    }
  }
  for ( Int_t ipmt=12; ipmt<24; ipmt++){
    if(time[ipmt] > 1) {
      if(time[ipmt]<besttimeA) {
	besttimeA=time[ipmt]; //timeA
        pmtBestA=ipmt;}
    }
  }
  if(besttimeA !=999999)  frecpoints->SetTimeBestA(Int_t(besttimeA));
  if( besttimeC != 999999 ) frecpoints->SetTimeBestC(Int_t(besttimeC));
  AliDebug(1,Form(" besttimeA %f ps,  besttimeC %f ps",besttimeA, besttimeC));
  Float_t c = 0.0299792; // cm/ps
  Float_t vertex = 0;
  if(besttimeA !=999999 && besttimeC != 999999 ){
    timeDiff = besttimeC - besttimeA;
    meanTime = (besttimeA + besttimeC)/2.;
    vertex = c*(timeDiff)/2.; //-(lenr-lenl))/2;
    AliDebug(1,Form("  timeDiff %f ps,  meanTime %f ps, vertex %f cm",timeDiff, meanTime,vertex ));
    frecpoints->SetVertex(vertex);
    frecpoints->SetMeanTime(Int_t(meanTime));

  }
  clustersTree->Fill();

  delete timeCFD;
  delete timeLED;
  delete chargeQT0;
  delete chargeQT1;
}

//_______________________________________________________________________

void AliT0Reconstructor::Reconstruct(AliRawReader* rawReader, TTree*recTree) const
{
// T0 raw ->
// T0RecPoint writing

    //Q->T-> coefficients !!!! should be asked!!!
  Float_t  timeDelayLED[24];
  Float_t zdetA,zdetC;
  TObjArray slewingLEDrec;
  TObjArray walk;

  TArrayI * timeCFD = new TArrayI(24);
  TArrayI * timeLED = new TArrayI(24);
  TArrayI * chargeQT0 = new TArrayI(24);
  TArrayI * chargeQT1 = new TArrayI(24);

   AliT0RawReader myrawreader(rawReader);
   if (!myrawreader.Next())
     AliDebug(1,Form(" no raw data found!! %i", myrawreader.Next()));
   Int_t allData[110][5];
   for (Int_t i=0; i<110; i++) {
     allData[i][0]=myrawreader.GetData(i,0);
   }

  AliT0Parameters* param = AliT0Parameters::Instance();
  param->Init();
  AliT0Calibrator *calib=new AliT0Calibrator();

  Int_t mV2Mip = param->GetmV2Mip();
  //mV2Mip = param->GetmV2Mip();
  Int_t channelWidth = param->GetChannelWidth() ;

  for (Int_t i=0; i<24; i++){
    TGraph* gr = param ->GetSlewRec(i);
    slewingLEDrec.AddAtAndExpand(gr,i) ;
  }

    zdetC = param->GetZposition(0);
    zdetA  = param->GetZposition(1);
    //  zdetC=GetZdet("C");
    // zdetA=GetZdet("A");
  cout<<" !!!!!  zdetC "<<zdetC<<"  zdetA "<< zdetA<<endl;
   for (Int_t in=0; in<24; in++)
     {
       timeLED->AddAt(allData[in+1][0],in);
       timeCFD->AddAt(allData[in+25][0],in);
       chargeQT1->AddAt(allData[in+55][0],in);
       chargeQT0->AddAt(allData[in+79][0],in);
       AliDebug(10, Form(" readed Raw %i %i %i %i %i", in, timeLED->At(in),timeCFD->At(in),chargeQT0->At(in),chargeQT1->At(in)));
     }

  Float_t besttimeA=999999;
  Float_t besttimeC=999999;
  Int_t pmtBestA=99999;
  Int_t pmtBestC=99999;
  Float_t timeDiff=999999, meanTime=0;

  AliT0RecPoint* frecpoints= new AliT0RecPoint ();

  recTree->Branch( "T0", "AliT0RecPoint" ,&frecpoints, 405,1);

  Float_t time[24], adc[24];
  for (Int_t ipmt=0; ipmt<24; ipmt++) {
    if(timeCFD->At(ipmt)>0 ){
      Int_t qt0= chargeQT0->At(ipmt);
      Int_t qt1= chargeQT1->At(ipmt);
      if((qt1-qt0)>0)  adc[ipmt] = TMath::Exp( Double_t (channelWidth*(qt1-qt0)/1000));
      time[ipmt] = channelWidth * (calib-> WalkCorrection( ipmt,qt1 , timeCFD->At(ipmt) ) ) ;
      Double_t sl = (timeLED->At(ipmt) - timeCFD->At(ipmt)- (1000.*timeDelayLED[ipmt]/channelWidth))*channelWidth;
      Double_t qt=((TGraph*)slewingLEDrec.At(ipmt))->Eval(sl/1000.);
      frecpoints->SetTime(ipmt,time[ipmt]);
      frecpoints->SetAmp(ipmt,adc[ipmt]);
      frecpoints->SetAmpLED(ipmt,qt);
    }
    else {
      time[ipmt] = 0;
      adc[ipmt] = 0;
    }
  }

  for (Int_t ipmt=0; ipmt<12; ipmt++){
    if(time[ipmt] > 1 ) {
      if(time[ipmt]<besttimeC){
	besttimeC=time[ipmt]; //timeC
	pmtBestC=ipmt;
      }
    }
  }
  for ( Int_t ipmt=12; ipmt<24; ipmt++){
    if(time[ipmt] > 1) {
      if(time[ipmt]<besttimeA) {
	besttimeA=time[ipmt]; //timeA
        pmtBestA=ipmt;}
    }
  }
  if(besttimeA !=999999)  frecpoints->SetTimeBestA(Int_t(besttimeA));
  if( besttimeC != 999999 ) frecpoints->SetTimeBestC(Int_t(besttimeC));
  AliDebug(1,Form(" besttimeA %f ps,  besttimeC %f ps",besttimeA, besttimeC));
  Float_t c = 0.0299792; // cm/ps
  Float_t vertex = 0;
  if(besttimeA !=999999 && besttimeC != 999999 ){
    timeDiff = besttimeC - besttimeA;
    meanTime = (besttimeA + besttimeC)/2.;
    vertex = c*(timeDiff)/2.; //-(lenr-lenl))/2;
    AliDebug(1,Form("  timeDiff %f ps,  meanTime %f ps, vertex %f cm",timeDiff, meanTime,vertex ));
    frecpoints->SetVertex(vertex);
    frecpoints->SetMeanTime(Int_t(meanTime));

  }
  recTree->Fill();

  delete timeCFD;
  delete timeLED;
  delete chargeQT0;
  delete chargeQT1;

}
//____________________________________________________________

void AliT0Reconstructor::FillESD(AliRunLoader* runLoader, AliESD *pESD) const
{

  /***************************************************
  Resonstruct digits to vertex position
  ****************************************************/

  if (!runLoader) {
    AliError("Reconstruct >> No run loader");
    return;
  }

  AliDebug(1,Form("Start FillESD T0"));

  AliT0Loader* pStartLoader = (AliT0Loader*) runLoader->GetLoader("T0Loader");

  pStartLoader->LoadRecPoints("READ");

  TTree *treeR = pStartLoader->TreeR();

   AliT0RecPoint* frecpoints= new AliT0RecPoint ();
    if (!frecpoints) {
    AliError("Reconstruct Fill ESD >> no recpoints found");
    return;
  }

  AliDebug(1,Form("Start FillESD T0"));
  TBranch *brRec = treeR->GetBranch("T0");
  if (brRec) {
    brRec->SetAddress(&frecpoints);
  }else{
    cerr<<"EXEC Branch T0 rec not found"<<endl;
    // exit(111);
    return;
  }

    brRec->GetEntry(0);
    Float_t timeStart, Zposition, amp[24], time[24];
    Int_t mean0 = 12450;
    Int_t i;
    Zposition = frecpoints -> GetVertex();
    timeStart = frecpoints -> GetMeanTime() - mean0;
    for ( i=0; i<24; i++) {
       time[i] = Float_t (frecpoints -> GetTime(i)) / 1000.; // ps to ns
      amp[i] = frecpoints -> GetAmp(i);
    }
    pESD->SetT0zVertex(Zposition); //vertex Z position
    pESD->SetT0(timeStart);        // interaction time
    pESD->SetT0time(time);         // best TOF on each PMT
    pESD->SetT0amplitude(amp);     // number of particles(MIPs) on each PMT
    cout<<" ESD >> "<<Zposition<<" "<<timeStart<<endl;

    pStartLoader->UnloadRecPoints();

} // vertex in 3 sigma

<|endoftext|>


<commit_before><commit_msg>minor fix<commit_after><|endoftext|>


<commit_before>// Copyright 2004-present Facebook. All Rights Reserved.

#include <array>
#include <chrono>
#include <memory>
#include <thread>

#include <folly/Memory.h>
#include <folly/io/IOBuf.h>
#include <folly/io/async/ScopedEventBaseThread.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "MockStats.h"
#include "src/ReactiveSocket.h"
#include "test/InlineConnection.h"
#include "test/MockRequestHandler.h"
#include "test/ReactiveStreamsMocksCompat.h"

using namespace ::testing;
using namespace ::reactivesocket;

class ClientSideConcurrencyTest : public testing::Test {
 public:
  ClientSideConcurrencyTest() {
    auto clientConn = folly::make_unique<InlineConnection>();
    auto serverConn = folly::make_unique<InlineConnection>();
    clientConn->connectTo(*serverConn);

    clientSock = ReactiveSocket::fromClientConnection(
        std::move(clientConn),
        // No interactions on this mock, the client will not accept any
        // requests.
        folly::make_unique<StrictMock<MockRequestHandler>>(),
        ConnectionSetupPayload("", "", Payload()));

    auto serverHandler = folly::make_unique<StrictMock<MockRequestHandler>>();
    auto& serverHandlerRef = *serverHandler;

    EXPECT_CALL(serverHandlerRef, handleSetupPayload_(_));

    serverSock = ReactiveSocket::fromServerConnection(
        std::move(serverConn), std::move(serverHandler));

    EXPECT_CALL(clientInput, onSubscribe_(_))
        .WillOnce(Invoke([&](Subscription* sub) {
          clientInputSub = sub;
          // request is called from the thread1
          // but delivered on thread2
          thread1.getEventBase()->runInEventBaseThreadAndWait(
              [&]() { sub->request(2); });
        }));
    // The request reaches the other end and triggers new responder to be set
    // up.
    EXPECT_CALL(serverHandlerRef, handleRequestResponse_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestStream_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestSubscription_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestChannel_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          clientTerminatesInteraction_ = false;
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());

          EXPECT_CALL(serverInput, onSubscribe_(_))
              .WillOnce(Invoke([&](Subscription* sub) {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
                serverInputSub = sub;
                sub->request(2);
              }));
          EXPECT_CALL(serverInput, onNext_(_))
              .WillOnce(Invoke([&](Payload& payload) {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
                serverInputSub->cancel();
              }));
          EXPECT_CALL(serverInput, onComplete_()).WillOnce(Invoke([&]() {
            EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          }));

          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);

          return &serverInput;
        }));

    EXPECT_CALL(serverOutputSub, request_(_))
        // The server delivers them immediately.
        .WillOnce(Invoke([&](size_t) {
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          serverOutput->onNext(Payload(originalPayload->clone()));
        }));
    EXPECT_CALL(clientInput, onNext_(_))
        // Client receives the payload. We will complete the interaction
        .WillOnce(Invoke([&](Payload&) {
          // cancel is called from the thread1
          // but delivered on thread2
          if (clientTerminatesInteraction_) {
            thread1.getEventBase()->runInEventBaseThreadAndWait(
                [&]() { clientInputSub->cancel(); });
          }
        }));

    EXPECT_CALL(serverOutputSub, cancel_()).WillOnce(Invoke([&]() {
      EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
      serverOutput->onComplete();
    }));

    EXPECT_CALL(clientInput, onComplete_());
  }

  std::unique_ptr<ReactiveSocket> clientSock;
  std::unique_ptr<ReactiveSocket> serverSock;

  const std::unique_ptr<folly::IOBuf> originalPayload{
      folly::IOBuf::copyBuffer("foo")};

  StrictMock<UnmanagedMockSubscriber<Payload>> clientInput;
  Subscription* clientInputSub{nullptr};

  Subscriber<Payload>* serverOutput{nullptr};
  StrictMock<UnmanagedMockSubscription> serverOutputSub;

  StrictMock<UnmanagedMockSubscriber<Payload>> serverInput;
  Subscription* serverInputSub;

  folly::ScopedEventBaseThread thread1;
  folly::ScopedEventBaseThread thread2;

  bool clientTerminatesInteraction_{true};
};

TEST_F(ClientSideConcurrencyTest, RequestResponseTest) {
  clientSock->requestResponse(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ClientSideConcurrencyTest, RequestStreamTest) {
  clientSock->requestStream(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ClientSideConcurrencyTest, RequestSubscriptionTest) {
  clientSock->requestSubscription(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ClientSideConcurrencyTest, RequestChannelTest) {
  auto& clientOutput =
      clientSock->requestChannel(clientInput, *thread2.getEventBase());

  StrictMock<UnmanagedMockSubscription> clientOutputSub;
  EXPECT_CALL(clientOutputSub, request_(1)).WillOnce(Invoke([&](size_t) {
    thread1.getEventBase()->runInEventBaseThread([&]() {
      // first payload for the server RequestHandler
      clientOutput.onNext(Payload(originalPayload->clone()));
    });
  }));
  EXPECT_CALL(clientOutputSub, request_(2)).WillOnce(Invoke([&](size_t) {
    // second payload for the server input subscriber
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, cancel_()).WillOnce(Invoke([&]() {
    thread1.getEventBase()->runInEventBaseThread(
        [&]() { clientOutput.onComplete(); });
  }));

  thread1.getEventBase()->runInEventBaseThreadAndWait(
      [&]() { clientOutput.onSubscribe(clientOutputSub); });

  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

class ServerSideConcurrencyTest : public testing::Test {
 public:
  ServerSideConcurrencyTest() {
    auto clientConn = folly::make_unique<InlineConnection>();
    auto serverConn = folly::make_unique<InlineConnection>();
    clientConn->connectTo(*serverConn);

    clientSock = ReactiveSocket::fromClientConnection(
        std::move(clientConn),
        // No interactions on this mock, the client will not accept any
        // requests.
        folly::make_unique<StrictMock<MockRequestHandler>>(),
        ConnectionSetupPayload("", "", Payload()));

    auto serverHandler =
        folly::make_unique<StrictMock<MockRequestHandlerBase>>();
    auto& serverHandlerRef = *serverHandler;

    EXPECT_CALL(serverHandlerRef, handleSetupPayload_(_));

    serverSock = ReactiveSocket::fromServerConnection(
        std::move(serverConn), std::move(serverHandler));

    EXPECT_CALL(clientInput, onSubscribe_(_))
        .WillOnce(Invoke([&](Subscription* sub) {
          clientInputSub = sub;
          sub->request(2);
        }));
    // The request reaches the other end and triggers new responder to be set
    // up.
    EXPECT_CALL(serverHandlerRef, handleRequestResponse_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              // TODO: should onSubscribe be queued and also called from
              // thread1?
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestStream_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestSubscription_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestChannel_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              clientTerminatesInteraction_ = false;

              EXPECT_CALL(serverInput, onSubscribe_(_))
                  .WillOnce(Invoke([&](Subscription* sub) {
                    serverInputSub = sub;
                    thread1.getEventBase()->runInEventBaseThreadAndWait(
                        [&]() { sub->request(2); });
                  }));
              EXPECT_CALL(serverInput, onNext_(_))
                  .WillOnce(Invoke([&](Payload& payload) {
                    thread1.getEventBase()->runInEventBaseThreadAndWait(
                        [&]() { serverInputSub->cancel(); });
                  }));
              EXPECT_CALL(serverInput, onComplete_()).WillOnce(Invoke([&]() {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
              }));

              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);

              return &serverInput;
            }));

    EXPECT_CALL(serverOutputSub, request_(_))
        // The server delivers them immediately.
        .WillOnce(Invoke([&](size_t) {
          thread1.getEventBase()->runInEventBaseThreadAndWait([&]() {
            serverOutput->onNext(Payload(originalPayload->clone()));
          });
        }));
    EXPECT_CALL(clientInput, onNext_(_))
        // Client receives the payload. We will complete the interaction
        .WillOnce(Invoke([&](Payload&) {
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          // cancel is called from the thread1
          // but delivered on thread2
          if (clientTerminatesInteraction_) {
            clientInputSub->cancel();
          }
        }));

    EXPECT_CALL(serverOutputSub, cancel_()).WillOnce(Invoke([&]() {
      EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
      serverOutput->onComplete();
    }));

    EXPECT_CALL(clientInput, onComplete_());
  }

  std::unique_ptr<ReactiveSocket> clientSock;
  std::unique_ptr<ReactiveSocket> serverSock;

  const std::unique_ptr<folly::IOBuf> originalPayload{
      folly::IOBuf::copyBuffer("foo")};

  StrictMock<UnmanagedMockSubscriber<Payload>> clientInput;
  Subscription* clientInputSub{nullptr};

  Subscriber<Payload>* serverOutput{nullptr};
  StrictMock<UnmanagedMockSubscription> serverOutputSub;

  StrictMock<UnmanagedMockSubscriber<Payload>> serverInput;
  Subscription* serverInputSub;

  folly::ScopedEventBaseThread thread1;
  folly::ScopedEventBaseThread thread2;

  bool clientTerminatesInteraction_{true};
};

TEST_F(ServerSideConcurrencyTest, RequestResponseTest) {
  clientSock->requestResponse(Payload(originalPayload->clone()), clientInput);
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ServerSideConcurrencyTest, RequestStreamTest) {
  clientSock->requestStream(Payload(originalPayload->clone()), clientInput);
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ServerSideConcurrencyTest, RequestSubscriptionTest) {
  clientSock->requestSubscription(
      Payload(originalPayload->clone()), clientInput);
  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

TEST_F(ServerSideConcurrencyTest, RequestChannelTest) {
  auto& clientOutput = clientSock->requestChannel(clientInput);

  StrictMock<UnmanagedMockSubscription> clientOutputSub;
  EXPECT_CALL(clientOutputSub, request_(1)).WillOnce(Invoke([&](size_t n) {
    // first payload for the server RequestHandler
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, request_(2)).WillOnce(Invoke([&](size_t n) {
    EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
    // second payload for the server input subscriber
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, cancel_()).WillOnce(Invoke([&]() {
    EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
    clientOutput.onComplete();
  }));

  clientOutput.onSubscribe(clientOutputSub);

  // give the second thread a change to execute the code
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
<commit_msg>fixing leaking tests<commit_after>// Copyright 2004-present Facebook. All Rights Reserved.

#include <array>
#include <chrono>
#include <memory>
#include <thread>
#include <condition_variable>

#include <folly/Memory.h>
#include <folly/io/IOBuf.h>
#include <folly/io/async/ScopedEventBaseThread.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "MockStats.h"
#include "src/ReactiveSocket.h"
#include "test/InlineConnection.h"
#include "test/MockRequestHandler.h"
#include "test/ReactiveStreamsMocksCompat.h"

using namespace ::testing;
using namespace ::reactivesocket;

class ClientSideConcurrencyTest : public testing::Test {
 public:
  ClientSideConcurrencyTest() {
    auto clientConn = folly::make_unique<InlineConnection>();
    auto serverConn = folly::make_unique<InlineConnection>();
    clientConn->connectTo(*serverConn);

    clientSock = ReactiveSocket::fromClientConnection(
        std::move(clientConn),
        // No interactions on this mock, the client will not accept any
        // requests.
        folly::make_unique<StrictMock<MockRequestHandler>>(),
        ConnectionSetupPayload("", "", Payload()));

    auto serverHandler = folly::make_unique<StrictMock<MockRequestHandler>>();
    auto& serverHandlerRef = *serverHandler;

    EXPECT_CALL(serverHandlerRef, handleSetupPayload_(_));

    serverSock = ReactiveSocket::fromServerConnection(
        std::move(serverConn), std::move(serverHandler));

    EXPECT_CALL(clientInput, onSubscribe_(_))
        .WillOnce(Invoke([&](Subscription* sub) {
          clientInputSub = sub;
          // request is called from the thread1
          // but delivered on thread2
          thread1.getEventBase()->runInEventBaseThreadAndWait(
              [&]() { sub->request(2); });
        }));
    // The request reaches the other end and triggers new responder to be set
    // up.
    EXPECT_CALL(serverHandlerRef, handleRequestResponse_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestStream_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestSubscription_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);
        }));
    EXPECT_CALL(serverHandlerRef, handleRequestChannel_(_, _))
        .Times(AtMost(1))
        .WillOnce(Invoke([&](Payload& request, Subscriber<Payload>* response) {
          clientTerminatesInteraction_ = false;
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());

          EXPECT_CALL(serverInput, onSubscribe_(_))
              .WillOnce(Invoke([&](Subscription* sub) {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
                serverInputSub = sub;
                sub->request(2);
              }));
          EXPECT_CALL(serverInput, onNext_(_))
              .WillOnce(Invoke([&](Payload& payload) {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
                serverInputSub->cancel();
              }));
          EXPECT_CALL(serverInput, onComplete_()).WillOnce(Invoke([&]() {
            EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          }));

          serverOutput = response;
          serverOutput->onSubscribe(serverOutputSub);

          return &serverInput;
        }));

    EXPECT_CALL(serverOutputSub, request_(_))
        // The server delivers them immediately.
        .WillOnce(Invoke([&](size_t) {
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          serverOutput->onNext(Payload(originalPayload->clone()));
        }));
    EXPECT_CALL(clientInput, onNext_(_))
        // Client receives the payload. We will complete the interaction
        .WillOnce(Invoke([&](Payload&) {
          // cancel is called from the thread1
          // but delivered on thread2
          if (clientTerminatesInteraction_) {
            thread1.getEventBase()->runInEventBaseThreadAndWait(
                [&]() { clientInputSub->cancel(); });
          }
        }));

    EXPECT_CALL(serverOutputSub, cancel_()).WillOnce(Invoke([&]() {
      EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
      serverOutput->onComplete();
    }));

    EXPECT_CALL(clientInput, onComplete_()).WillOnce(Invoke([&]() {
      if (!clientTerminatesInteraction_) {
        clientInputSub->cancel();
      }
      done();
    }));
  }

  void done() {
    std::unique_lock<std::mutex> lock(mtx);
    isDone_ = true;
    cv.notify_one();
  }

  void wainUntilDone() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock,[&](){return isDone_;});
  }

  std::unique_ptr<ReactiveSocket> clientSock;
  std::unique_ptr<ReactiveSocket> serverSock;

  const std::unique_ptr<folly::IOBuf> originalPayload{
      folly::IOBuf::copyBuffer("foo")};

  StrictMock<UnmanagedMockSubscriber<Payload>> clientInput;
  Subscription* clientInputSub{nullptr};

  Subscriber<Payload>* serverOutput{nullptr};
  StrictMock<UnmanagedMockSubscription> serverOutputSub;

  StrictMock<UnmanagedMockSubscriber<Payload>> serverInput;
  Subscription* serverInputSub;

  folly::ScopedEventBaseThread thread1;
  folly::ScopedEventBaseThread thread2;

  bool clientTerminatesInteraction_{true};

  std::mutex mtx;
  std::condition_variable cv;
  bool isDone_{false};
};

TEST_F(ClientSideConcurrencyTest, RequestResponseTest) {
  clientSock->requestResponse(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  wainUntilDone();
}

TEST_F(ClientSideConcurrencyTest, RequestStreamTest) {
  clientSock->requestStream(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  wainUntilDone();
}

TEST_F(ClientSideConcurrencyTest, RequestSubscriptionTest) {
  clientSock->requestSubscription(
      Payload(originalPayload->clone()), clientInput, *thread2.getEventBase());
  wainUntilDone();
}

TEST_F(ClientSideConcurrencyTest, RequestChannelTest) {
  auto& clientOutput =
      clientSock->requestChannel(clientInput, *thread2.getEventBase());

  StrictMock<UnmanagedMockSubscription> clientOutputSub;
  EXPECT_CALL(clientOutputSub, request_(1)).WillOnce(Invoke([&](size_t) {
    thread1.getEventBase()->runInEventBaseThread([&]() {
      // first payload for the server RequestHandler
      clientOutput.onNext(Payload(originalPayload->clone()));
    });
  }));
  EXPECT_CALL(clientOutputSub, request_(2)).WillOnce(Invoke([&](size_t) {
    // second payload for the server input subscriber
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, cancel_()).WillOnce(Invoke([&]() {
    thread1.getEventBase()->runInEventBaseThread(
        [&]() {
          clientOutput.onComplete();
        });
  }));

  thread1.getEventBase()->runInEventBaseThreadAndWait(
      [&]() { clientOutput.onSubscribe(clientOutputSub); });

  wainUntilDone();
}

class ServerSideConcurrencyTest : public testing::Test {
 public:
  ServerSideConcurrencyTest() {
    auto clientConn = folly::make_unique<InlineConnection>();
    auto serverConn = folly::make_unique<InlineConnection>();
    clientConn->connectTo(*serverConn);

    clientSock = ReactiveSocket::fromClientConnection(
        std::move(clientConn),
        // No interactions on this mock, the client will not accept any
        // requests.
        folly::make_unique<StrictMock<MockRequestHandler>>(),
        ConnectionSetupPayload("", "", Payload()));

    auto serverHandler =
        folly::make_unique<StrictMock<MockRequestHandlerBase>>();
    auto& serverHandlerRef = *serverHandler;

    EXPECT_CALL(serverHandlerRef, handleSetupPayload_(_));

    serverSock = ReactiveSocket::fromServerConnection(
        std::move(serverConn), std::move(serverHandler));

    EXPECT_CALL(clientInput, onSubscribe_(_))
        .WillOnce(Invoke([&](Subscription* sub) {
          clientInputSub = sub;
          sub->request(2);
        }));
    // The request reaches the other end and triggers new responder to be set
    // up.
    EXPECT_CALL(serverHandlerRef, handleRequestResponse_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              // TODO: should onSubscribe be queued and also called from
              // thread1?
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestStream_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestSubscription_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);
            }));
    EXPECT_CALL(serverHandlerRef, handleRequestChannel_(_, _))
        .Times(AtMost(1))
        .WillOnce(
            Invoke([&](Payload& request, SubscriberFactory& subscriberFactory) {
              clientTerminatesInteraction_ = false;

              EXPECT_CALL(serverInput, onSubscribe_(_))
                  .WillOnce(Invoke([&](Subscription* sub) {
                    serverInputSub = sub;
                    thread1.getEventBase()->runInEventBaseThreadAndWait(
                        [&]() { sub->request(2); });
                  }));
              EXPECT_CALL(serverInput, onNext_(_))
                  .WillOnce(Invoke([&](Payload& payload) {
                    thread1.getEventBase()->runInEventBaseThreadAndWait(
                        [&]() { serverInputSub->cancel(); });
                  }));
              EXPECT_CALL(serverInput, onComplete_()).WillOnce(Invoke([&]() {
                EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
              }));

              serverOutput =
                  &subscriberFactory.createSubscriber(*thread2.getEventBase());
              serverOutput->onSubscribe(serverOutputSub);

              return &serverInput;
            }));

    EXPECT_CALL(serverOutputSub, request_(_))
        // The server delivers them immediately.
        .WillOnce(Invoke([&](size_t) {
          thread1.getEventBase()->runInEventBaseThreadAndWait([&]() {
            serverOutput->onNext(Payload(originalPayload->clone()));
          });
        }));
    EXPECT_CALL(clientInput, onNext_(_))
        // Client receives the payload. We will complete the interaction
        .WillOnce(Invoke([&](Payload&) {
          EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
          // cancel is called from the thread1
          // but delivered on thread2
          if (clientTerminatesInteraction_) {
            clientInputSub->cancel();
          }
        }));

    EXPECT_CALL(serverOutputSub, cancel_()).WillOnce(Invoke([&]() {
      EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
      serverOutput->onComplete();
    }));

    EXPECT_CALL(clientInput, onComplete_()).WillOnce(Invoke([&]() {
      if (!clientTerminatesInteraction_) {
        clientInputSub->cancel();
      }
      done();
    }));
  }

  void done() {
    std::unique_lock<std::mutex> lock(mtx);
    isDone_ = true;
    cv.notify_one();
  }

  void wainUntilDone() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock,[&](){return isDone_;});
  }

  std::unique_ptr<ReactiveSocket> clientSock;
  std::unique_ptr<ReactiveSocket> serverSock;

  const std::unique_ptr<folly::IOBuf> originalPayload{
      folly::IOBuf::copyBuffer("foo")};

  StrictMock<UnmanagedMockSubscriber<Payload>> clientInput;
  Subscription* clientInputSub{nullptr};

  Subscriber<Payload>* serverOutput{nullptr};
  StrictMock<UnmanagedMockSubscription> serverOutputSub;

  StrictMock<UnmanagedMockSubscriber<Payload>> serverInput;
  Subscription* serverInputSub;

  folly::ScopedEventBaseThread thread1;
  folly::ScopedEventBaseThread thread2;

  bool clientTerminatesInteraction_{true};

  std::mutex mtx;
  std::condition_variable cv;
  bool isDone_{false};
};

TEST_F(ServerSideConcurrencyTest, RequestResponseTest) {
  clientSock->requestResponse(Payload(originalPayload->clone()), clientInput);
  wainUntilDone();
}

TEST_F(ServerSideConcurrencyTest, RequestStreamTest) {
  clientSock->requestStream(Payload(originalPayload->clone()), clientInput);
  wainUntilDone();
}

TEST_F(ServerSideConcurrencyTest, RequestSubscriptionTest) {
  clientSock->requestSubscription(
      Payload(originalPayload->clone()), clientInput);
  wainUntilDone();
}

TEST_F(ServerSideConcurrencyTest, RequestChannelTest) {
  auto& clientOutput = clientSock->requestChannel(clientInput);

  StrictMock<UnmanagedMockSubscription> clientOutputSub;
  EXPECT_CALL(clientOutputSub, request_(1)).WillOnce(Invoke([&](size_t n) {
    // first payload for the server RequestHandler
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, request_(2)).WillOnce(Invoke([&](size_t n) {
    EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
    // second payload for the server input subscriber
    clientOutput.onNext(Payload(originalPayload->clone()));
  }));
  EXPECT_CALL(clientOutputSub, cancel_()).WillOnce(Invoke([&]() {
    EXPECT_TRUE(thread2.getEventBase()->isInEventBaseThread());
    clientOutput.onComplete();
  }));

  clientOutput.onSubscribe(clientOutputSub);

  wainUntilDone();
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <stdexcept>
#include "neural_network_trainer.h"

using namespace JNF_NEAT;
using namespace std;

NeuralNetworkTrainer::NeuralNetworkTrainer(vector<shared_ptr<IBody>> population, TrainingParameters parameters) :
	parameters(move(parameters)),
	populationSize(population.size()),
	bodies(move(population))
{
	CreateInitialOrganisms();
}

auto NeuralNetworkTrainer::ResetPopulationToTeachableState() -> void {
	for (auto& sp : species) {
		sp.ResetToTeachableState();
	}
}

auto NeuralNetworkTrainer::TrainUntilFitnessEquals(double fitnessToReach) -> void {
	if (loggingEnabled) {
		logger.CreateLoggingDirs();
	}
	LetGenerationLive();
	while (GetFittestOrganism().GetOrCalculateRawFitness() < (fitnessToReach - 1e-6)) {
		TrainGenerationAndLog();
	}
}

auto NeuralNetworkTrainer::TrainUntilGenerationEquals(size_t generationsToTrain) -> void {
	if (loggingEnabled) {
		logger.CreateLoggingDirs();
	}
	generationsToTrain += generationsPassed;
	LetGenerationLive();
	while (generationsPassed < generationsToTrain) {
		TrainGenerationAndLog();
	}
}

auto NeuralNetworkTrainer::GetTrainedNeuralNetwork() -> TrainedNeuralNetwork {
	return TrainedNeuralNetwork(GetFittestOrganism().GetGenome());
}

auto NeuralNetworkTrainer::CreateInitialOrganisms() -> void {
	Genome standardGenes(parameters);
	for (auto currTrainer : bodies) {
		NeuralNetwork network(standardGenes);
		Organism organism(currTrainer, move(network));
		FillOrganismIntoSpecies(move(organism));
	}
}

auto NeuralNetworkTrainer::TrainGenerationAndLog() -> void {
	Repopulate();
	LetGenerationLive();
	generationsPassed++;
	if (loggingEnabled) {
		logger.LogGeneration(generationsPassed, GetJSON());
	}
}

auto NeuralNetworkTrainer::GetFittestOrganism() -> Organism& {
	if (species.empty()) {
		throw out_of_range("Your population is empty");
	}
	auto CompareSpecies = [&](Species& lhs, Species& rhs) {
		return lhs.GetFittestOrganism().GetOrCalculateFitness() < rhs.GetFittestOrganism().GetOrCalculateFitness();
	};

	sort(species.begin(), species.end(), CompareSpecies);
	return species.front().GetFittestOrganism();
}

auto NeuralNetworkTrainer::LetGenerationLive() -> void {
	for (auto& sp : species) {
		sp.LetPopulationLive();
	}
}

auto NeuralNetworkTrainer::PrepareSpeciesForPopulation() -> void {
	AnalyzeAndClearSpeciesPopulation();
	DeleteStagnantSpecies();
}

auto NeuralNetworkTrainer::FillOrganismIntoSpecies(Organism&& organism) -> void {
	bool isCompatibleWithExistingSpecies = false;
	for (auto& currSpecies : species) {
		if (currSpecies.IsCompatible(organism.GetGenome())) {
			currSpecies.AddOrganism(move(organism));
			isCompatibleWithExistingSpecies = true;
			break;
		}
	}
	if (!isCompatibleWithExistingSpecies) {
		Species newSpecies(move(organism));
		species.push_back(move(newSpecies));
	}
}

auto NeuralNetworkTrainer::AnalyzeAndClearSpeciesPopulation() -> void {
	for (auto& currSpecies : species) {
		currSpecies.AnalyzeAndClearPopulation();
	}
}

auto NeuralNetworkTrainer::DeleteStagnantSpecies() -> void {
	auto IsStagnant = [](Species& species) {
		return species.IsStagnant();
	};
	auto removePos = remove_if(species.begin(), species.end(), IsStagnant);
	// Let at least one species survive
	if (!species.empty() && removePos == species.begin()) {
		++removePos;
	}
	species.erase(removePos, species.end());
}

auto NeuralNetworkTrainer::DeleteEmptySpecies() -> void {
	species.erase(
		remove_if(species.begin(), species.end(), [](const Species& s) {return s.IsEmpty(); }),
		species.end()
	);
}

auto NeuralNetworkTrainer::Repopulate() -> void {
	PrepareSpeciesForPopulation();
	auto DidChanceOccure = [](float chance) {
		auto num = rand() % 1000;
		return num < int(1000.0f * chance);
	};

	for (auto& trainer : bodies) {
		Species* sp = &SelectSpeciesToBreed();
		auto& father = sp->GetOrganismToBreed();
		if (DidChanceOccure(parameters.advanced.reproduction.chanceForInterspecialReproduction)) {
			sp = &SelectSpeciesToBreed();
		}
		auto& mother = sp->GetOrganismToBreed();
		auto childNeuralNetwork(move(father.BreedWith(mother)));
		Organism child(trainer, move(childNeuralNetwork));
		FillOrganismIntoSpecies(move(child));
	}
	DeleteEmptySpecies();
	ResetPopulationToTeachableState();
	// TODO jnf Add Concurrency
}

auto NeuralNetworkTrainer::SelectSpeciesToBreed() -> Species& {
	// TODO jnf: Switch to stochastic universal sampling
	if (species.empty()) {
		throw out_of_range("There are no species");
	}
	double totalSpeciesFitness = 0.0;
	for (auto& s : species) {
		totalSpeciesFitness += s.GetFittestOrganism().GetOrCalculateFitness();
	}
	if (totalSpeciesFitness == 0) {
		return species[rand() % species.size()];
	}
	double chance = 0.0;
	auto GetChanceForSpecies = [&chance, &totalSpeciesFitness](Species& species) {
		return chance + (species.GetFittestOrganism().GetOrCalculateFitness() / totalSpeciesFitness);
	};
	while (true) {
		for (auto& s : species) {
			double randNum = (double)(rand() % 10'000) / 9'999.0;
			chance = GetChanceForSpecies(s);
			if (randNum < chance) {
				return s;
			}
		}
	}
}

auto NeuralNetworkTrainer::GetJSON() const -> string {
	string s("{\"populationSize\":");
	s += to_string(populationSize);
	s += ",";
	s += "\"generationsPassed\":";
	s += to_string(generationsPassed);
	s += ",";
	s += "\"species\":[";
	for (size_t i = 0; i < species.size() - 1; ++i) {
		s += species[i].GetJSON();
		s += ",";
	}
	s += species.back().GetJSON();
	s += "]}";
	return s;
}
<commit_msg>Minor reformating<commit_after>#include <algorithm>
#include <stdexcept>
#include "neural_network_trainer.h"

using namespace JNF_NEAT;
using namespace std;

NeuralNetworkTrainer::NeuralNetworkTrainer(vector<shared_ptr<IBody>> population, TrainingParameters parameters) :
	parameters(move(parameters)),
	populationSize(population.size()),
	bodies(move(population))
{
	CreateInitialOrganisms();
}

auto NeuralNetworkTrainer::TrainUntilFitnessEquals(double fitnessToReach) -> void {
	if (loggingEnabled) {
		logger.CreateLoggingDirs();
	}
	LetGenerationLive();
	while (GetFittestOrganism().GetOrCalculateRawFitness() < (fitnessToReach - 1e-6)) {
		TrainGenerationAndLog();
	}
}

auto NeuralNetworkTrainer::TrainUntilGenerationEquals(size_t generationsToTrain) -> void {
	if (loggingEnabled) {
		logger.CreateLoggingDirs();
	}
	generationsToTrain += generationsPassed;
	LetGenerationLive();
	while (generationsPassed < generationsToTrain) {
		TrainGenerationAndLog();
	}
}

auto NeuralNetworkTrainer::GetTrainedNeuralNetwork() -> TrainedNeuralNetwork {
	return TrainedNeuralNetwork(GetFittestOrganism().GetGenome());
}

auto NeuralNetworkTrainer::CreateInitialOrganisms() -> void {
	Genome standardGenes(parameters);
	for (auto currTrainer : bodies) {
		NeuralNetwork network(standardGenes);
		Organism organism(currTrainer, move(network));
		FillOrganismIntoSpecies(move(organism));
	}
}

auto NeuralNetworkTrainer::TrainGenerationAndLog() -> void {
	Repopulate();
	LetGenerationLive();
	generationsPassed++;
	if (loggingEnabled) {
		logger.LogGeneration(generationsPassed, GetJSON());
	}
}

auto NeuralNetworkTrainer::GetFittestOrganism() -> Organism& {
	if (species.empty()) {
		throw out_of_range("Your population is empty");
	}
	auto CompareSpecies = [&](Species& lhs, Species& rhs) {
		return lhs.GetFittestOrganism().GetOrCalculateFitness() < rhs.GetFittestOrganism().GetOrCalculateFitness();
	};

	sort(species.begin(), species.end(), CompareSpecies);
	return species.front().GetFittestOrganism();
}

auto NeuralNetworkTrainer::LetGenerationLive() -> void {
	for (auto& sp : species) {
		sp.LetPopulationLive();
	}
}

auto NeuralNetworkTrainer::FillOrganismIntoSpecies(Organism&& organism) -> void {
	bool isCompatibleWithExistingSpecies = false;
	for (auto& currSpecies : species) {
		if (currSpecies.IsCompatible(organism.GetGenome())) {
			currSpecies.AddOrganism(move(organism));
			isCompatibleWithExistingSpecies = true;
			break;
		}
	}
	if (!isCompatibleWithExistingSpecies) {
		Species newSpecies(move(organism));
		species.push_back(move(newSpecies));
	}
}

auto NeuralNetworkTrainer::AnalyzeAndClearSpeciesPopulation() -> void {
	for (auto& currSpecies : species) {
		currSpecies.AnalyzeAndClearPopulation();
	}
}

auto NeuralNetworkTrainer::DeleteStagnantSpecies() -> void {
	auto IsStagnant = [](Species& species) {
		return species.IsStagnant();
	};
	auto removePos = remove_if(species.begin(), species.end(), IsStagnant);
	// Let at least one species survive
	if (!species.empty() && removePos == species.begin()) {
		++removePos;
	}
	species.erase(removePos, species.end());
}

auto NeuralNetworkTrainer::Repopulate() -> void {
	PrepareSpeciesForPopulation();
	auto DidChanceOccure = [](float chance) {
		auto num = rand() % 1000;
		return num < int(1000.0f * chance);
	};

	for (auto& body : bodies) {
		Species* sp = &SelectSpeciesToBreed();
		auto& father = sp->GetOrganismToBreed();
		if (DidChanceOccure(parameters.advanced.reproduction.chanceForInterspecialReproduction)) {
			sp = &SelectSpeciesToBreed();
		}
		auto& mother = sp->GetOrganismToBreed();
		auto childNeuralNetwork(move(father.BreedWith(mother)));
		Organism child(body, move(childNeuralNetwork));
		FillOrganismIntoSpecies(move(child));
	}
	DeleteEmptySpecies();
	ResetPopulationToTeachableState();
	// TODO jnf Add Concurrency
}

auto NeuralNetworkTrainer::PrepareSpeciesForPopulation() -> void
{
	AnalyzeAndClearSpeciesPopulation();
	DeleteStagnantSpecies();
}

auto NeuralNetworkTrainer::DeleteEmptySpecies() -> void
{
	species.erase(
		remove_if(species.begin(), species.end(), [](const Species& s) {return s.IsEmpty(); }),
		species.end()
		);
}

auto NeuralNetworkTrainer::ResetPopulationToTeachableState() -> void
{
	for (auto& sp : species) {
		sp.ResetToTeachableState();
	}
}

auto NeuralNetworkTrainer::SelectSpeciesToBreed() -> Species& {
	// TODO jnf: Switch to stochastic universal sampling
	if (species.empty()) {
		throw out_of_range("There are no species");
	}
	double totalSpeciesFitness = 0.0;
	for (auto& s : species) {
		totalSpeciesFitness += s.GetFittestOrganism().GetOrCalculateFitness();
	}
	if (totalSpeciesFitness == 0) {
		return species[rand() % species.size()];
	}
	double chance = 0.0;
	auto GetChanceForSpecies = [&chance, &totalSpeciesFitness](Species& species) {
		return chance + (species.GetFittestOrganism().GetOrCalculateFitness() / totalSpeciesFitness);
	};
	while (true) {
		for (auto& s : species) {
			double randNum = (double)(rand() % 10'000) / 9'999.0;
			chance = GetChanceForSpecies(s);
			if (randNum < chance) {
				return s;
			}
		}
	}
}

auto NeuralNetworkTrainer::GetJSON() const -> string {
	string s("{\"populationSize\":");
	s += to_string(populationSize);
	s += ",";
	s += "\"generationsPassed\":";
	s += to_string(generationsPassed);
	s += ",";
	s += "\"species\":[";
	for (size_t i = 0; i < species.size() - 1; ++i) {
		s += species[i].GetJSON();
		s += ",";
	}
	s += species.back().GetJSON();
	s += "]}";
	return s;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Ana Huaman <ahuaman3@gatech.edu>
 * Date: 03-08-2012
 *
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 **
 * @file World.cpp
 */

#include <iostream>
#include "World.h"
#include <kinematics/BodyNode.h>
#include <kinematics/Shape.h>
#include <collision/CollisionSkeleton.h>
#include <integration/EulerIntegrator.h>
#include <dynamics/ContactDynamics.h>
#include <dynamics/SkeletonDynamics.h>
#include <robotics/Robot.h>
#include <robotics/Object.h>

using namespace Eigen;

namespace robotics {

  /**
   * @function World
   * @brief Constructor
   */
  World::World()
  {
    mRobots.resize(0);
    mObjects.resize(0);
    mSkeletons.resize(0);
    mIndices.push_back(0);

    mGravity = Eigen::Vector3d(0, 0, -9.81);
    mTimeStep = 0.001;
  }

  /**
   * @function ~World
   * @brief Destructor
   */
  World::~World() {
    for( size_t i = 0; i < mRobots.size(); ++i ) {
      delete mRobots[i];
    }
    mRobots.clear();

    for( size_t i = 0; i < mObjects.size(); ++i ) {
      delete mObjects[i];
    }
    mObjects.clear();

    mSkeletons.clear();
  }

  void World::rebuildCollision()
  {
    // for(unsigned int i = 0; i < mSkeletons.size(); i++)
    //   mSkeletons[i]->initDynamics();
    mCollisionHandle = new dynamics::ContactDynamics(mSkeletons, mTimeStep);
  }

  /**
   * @function addRobot
   * @brief Add a pointer to a new robot in the World
   */
  int World::addRobot( Robot* _robot ) {
    // add item
    mRobots.push_back( _robot );
    mSkeletons.push_back( _robot );

    _robot->initDynamics();

    mIndices.push_back(mIndices.back() + _robot->getNumDofs());
    mDofs.push_back(_robot->getPose());
    mDofVels.push_back(_robot->getQDotVector());

    if(!_robot->getImmobileState()) {
      _robot->computeDynamics(mGravity, mDofVels.back(), false); // Not sure if we need this
    }

    // create collision dynamics object
    // rebuildCollision();

    assert(mObjects.size() + mRobots.size() == mSkeletons.size());

    return mRobots.size();
  }

  /**
   * @function addObject
   * @brief Add a pointer to a new object in the World
   */
  int World::addObject( Object* _object ) {
    // add item
    mObjects.push_back( _object );
    mSkeletons.push_back( _object );
    mIndices.push_back(mIndices.back() + _object->getNumDofs());

    _object->initDynamics();

    mIndices.push_back(mIndices.back() + _object->getNumDofs());
    mDofs.push_back(_object->getPose());
    mDofVels.push_back(_object->getQDotVector());

    if(!_object->getImmobileState()) {
      _object->computeDynamics(mGravity, mDofVels.back(), false); // Not sure if we need this
    }

    // create collision dynanmics object
    // rebuildCollision();

    assert(mObjects.size() + mRobots.size() == mSkeletons.size());

    return mObjects.size();
  }

  /**
   * @function printInfo
   * @brief Print info w.r.t. robots and objects in World
   */
  void World::printInfo() {

    std::cout << "*  World Info * " << std::endl;
    std::cout << "----------------------" << std::endl;

    //-- Robots
    for( size_t i = 0; i < mRobots.size(); ++i ) {
      std::cout << "* Robot["<<i<<"]: "<< mRobots[i]->getName()<<" : "<< mRobots[i]->getNumDofs() <<" DOFs " << std::endl;
    }
    //-- Objects
    for( size_t i = 0; i < mObjects.size(); ++i ) {
      std::cout << "* Object["<<i<<"]: "<< mObjects[i]->getName() << std::endl;
    }

  }

  /**
   * @function getObject
   */
  Object* World::getObject( int _i ) {
    return mObjects[_i];
  }

  /**
   * @function getRobot
   */
  Robot* World::getRobot( int _i ) {
    return mRobots[_i];
  }

  /**
   * @function getSkeleton
   */
  dynamics::SkeletonDynamics* World::getSkeleton( int _i ) {
    return mSkeletons[_i];
  }

  bool World::checkCollision(bool checkAllCollisions) {
    return mCollisionHandle->getCollisionChecker()->checkCollision(checkAllCollisions, false);
  }

  void World::step() {
    mIntegrator.integrate(this, mTimeStep);
    mTime += mTimeStep;
  }

  VectorXd World::getState() {
    VectorXd state(mIndices.back() * 2);
    for (int i = 0; i < getNumSkeletons(); i++) {
      int start = mIndices[i] * 2;
      int size = mDofs[i].size();
      state.segment(start, size) = mDofs[i];
      state.segment(start + size, size) = mDofVels[i];
    }
    return state;
  }

  VectorXd World::evalDeriv() {
    // compute dynamic equations
    for (int i = 0; i < getNumSkeletons(); i++) {
        if (getSkeleton(i)->getImmobileState()) {
            // need to update node transformation for collision
            getSkeleton(i)->setPose(mDofs[i], true, false);
        } else {
            // need to update first derivatives for collision
            getSkeleton(i)->setPose(mDofs[i], false, true);
            getSkeleton(i)->computeDynamics(mGravity, mDofVels[i], true);
        }
    }
    // compute contact forces
    mCollisionHandle->applyContactForces();

    // compute derivatives for integration
    VectorXd deriv = VectorXd::Zero(mIndices.back() * 2);
    for (int i = 0; i < getNumSkeletons(); i++) {
        // skip immobile objects in forward simulation
        if (getSkeleton(i)->getImmobileState())
            continue;
        int start = mIndices[i] * 2;
        int size = mDofs[i].size();
        VectorXd qddot = getSkeleton(i)->getMassMatrix().fullPivHouseholderQr().solve(
            - getSkeleton(i)->getCombinedVector() + getSkeleton(i)->getExternalForces()
            + mCollisionHandle->getConstraintForce(i) + getSkeleton(i)->getInternalForces());

        getSkeleton(i)->clampRotation(mDofs[i], mDofVels[i]);
        deriv.segment(start, size) = mDofVels[i] + (qddot * mTimeStep); // set velocities
        deriv.segment(start + size, size) = qddot; // set qddot (accelerations)
    }
    return deriv;
}

void World::setState(VectorXd newState) {
    for (int i = 0; i < getNumSkeletons(); i++) {
        int start = mIndices[i] * 2;
        int size = mDofs[i].size();
        mDofs[i] = newState.segment(start, size);
        mDofVels[i] = newState.segment(start + size, size);
    }
}

} // end namespace robotics

// Local Variables:
// c-basic-offset: 2
// End:
<commit_msg>Fix bug in World<commit_after>/*
 * Copyright (c) 2012, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Ana Huaman <ahuaman3@gatech.edu>
 * Date: 03-08-2012
 *
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 **
 * @file World.cpp
 */

#include <iostream>
#include "World.h"
#include <kinematics/BodyNode.h>
#include <kinematics/Shape.h>
#include <collision/CollisionSkeleton.h>
#include <integration/EulerIntegrator.h>
#include <dynamics/ContactDynamics.h>
#include <dynamics/SkeletonDynamics.h>
#include <robotics/Robot.h>
#include <robotics/Object.h>

using namespace Eigen;

namespace robotics {

  /**
   * @function World
   * @brief Constructor
   */
  World::World()
  {
    mRobots.resize(0);
    mObjects.resize(0);
    mSkeletons.resize(0);
    mIndices.push_back(0);

    mGravity = Eigen::Vector3d(0, 0, -9.81);
    mTimeStep = 0.001;
  }

  /**
   * @function ~World
   * @brief Destructor
   */
  World::~World() {
    for( size_t i = 0; i < mRobots.size(); ++i ) {
      delete mRobots[i];
    }
    mRobots.clear();

    for( size_t i = 0; i < mObjects.size(); ++i ) {
      delete mObjects[i];
    }
    mObjects.clear();

    mSkeletons.clear();
  }

  void World::rebuildCollision()
  {
    // for(unsigned int i = 0; i < mSkeletons.size(); i++)
    //   mSkeletons[i]->initDynamics();
    mCollisionHandle = new dynamics::ContactDynamics(mSkeletons, mTimeStep);
  }

  /**
   * @function addRobot
   * @brief Add a pointer to a new robot in the World
   */
  int World::addRobot( Robot* _robot ) {
    // add item
    mRobots.push_back( _robot );
    mSkeletons.push_back( _robot );

    _robot->initDynamics();

    mIndices.push_back(mIndices.back() + _robot->getNumDofs());
    mDofs.push_back(_robot->getPose());
    mDofVels.push_back(_robot->getQDotVector());

    if(!_robot->getImmobileState()) {
      _robot->computeDynamics(mGravity, mDofVels.back(), false); // Not sure if we need this
    }

    // create collision dynamics object
    // rebuildCollision();

    assert(mObjects.size() + mRobots.size() == mSkeletons.size());

    return mRobots.size();
  }

  /**
   * @function addObject
   * @brief Add a pointer to a new object in the World
   */
  int World::addObject( Object* _object ) {
    // add item
    mObjects.push_back( _object );
    mSkeletons.push_back( _object );

    _object->initDynamics();

    mIndices.push_back(mIndices.back() + _object->getNumDofs());
    mDofs.push_back(_object->getPose());
    mDofVels.push_back(_object->getQDotVector());

    if(!_object->getImmobileState()) {
      _object->computeDynamics(mGravity, mDofVels.back(), false); // Not sure if we need this
    }

    // create collision dynanmics object
    // rebuildCollision();

    assert(mObjects.size() + mRobots.size() == mSkeletons.size());

    return mObjects.size();
  }

  /**
   * @function printInfo
   * @brief Print info w.r.t. robots and objects in World
   */
  void World::printInfo() {

    std::cout << "*  World Info * " << std::endl;
    std::cout << "----------------------" << std::endl;

    //-- Robots
    for( size_t i = 0; i < mRobots.size(); ++i ) {
      std::cout << "* Robot["<<i<<"]: "<< mRobots[i]->getName()<<" : "<< mRobots[i]->getNumDofs() <<" DOFs " << std::endl;
    }
    //-- Objects
    for( size_t i = 0; i < mObjects.size(); ++i ) {
      std::cout << "* Object["<<i<<"]: "<< mObjects[i]->getName() << std::endl;
    }

  }

  /**
   * @function getObject
   */
  Object* World::getObject( int _i ) {
    return mObjects[_i];
  }

  /**
   * @function getRobot
   */
  Robot* World::getRobot( int _i ) {
    return mRobots[_i];
  }

  /**
   * @function getSkeleton
   */
  dynamics::SkeletonDynamics* World::getSkeleton( int _i ) {
    return mSkeletons[_i];
  }

  bool World::checkCollision(bool checkAllCollisions) {
    return mCollisionHandle->getCollisionChecker()->checkCollision(checkAllCollisions, false);
  }

  void World::step() {
    mIntegrator.integrate(this, mTimeStep);
    mTime += mTimeStep;
  }

  VectorXd World::getState() {
    VectorXd state(mIndices.back() * 2);
    for (int i = 0; i < getNumSkeletons(); i++) {
      int start = mIndices[i] * 2;
      int size = mDofs[i].size();
      state.segment(start, size) = mDofs[i];
      state.segment(start + size, size) = mDofVels[i];
    }
    return state;
  }

  VectorXd World::evalDeriv() {
    // compute dynamic equations
    for (int i = 0; i < getNumSkeletons(); i++) {
        if (getSkeleton(i)->getImmobileState()) {
            // need to update node transformation for collision
            getSkeleton(i)->setPose(mDofs[i], true, false);
        } else {
            // need to update first derivatives for collision
            getSkeleton(i)->setPose(mDofs[i], false, true);
            getSkeleton(i)->computeDynamics(mGravity, mDofVels[i], true);
        }
    }
    // compute contact forces
    mCollisionHandle->applyContactForces();

    // compute derivatives for integration
    VectorXd deriv = VectorXd::Zero(mIndices.back() * 2);
    for (int i = 0; i < getNumSkeletons(); i++) {
        // skip immobile objects in forward simulation
        if (getSkeleton(i)->getImmobileState())
            continue;
        int start = mIndices[i] * 2;
        int size = mDofs[i].size();
        VectorXd qddot = getSkeleton(i)->getMassMatrix().fullPivHouseholderQr().solve(
            - getSkeleton(i)->getCombinedVector() + getSkeleton(i)->getExternalForces()
            + mCollisionHandle->getConstraintForce(i) + getSkeleton(i)->getInternalForces());

        getSkeleton(i)->clampRotation(mDofs[i], mDofVels[i]);
        deriv.segment(start, size) = mDofVels[i] + (qddot * mTimeStep); // set velocities
        deriv.segment(start + size, size) = qddot; // set qddot (accelerations)
    }
    return deriv;
}

void World::setState(VectorXd newState) {
    for (int i = 0; i < getNumSkeletons(); i++) {
        int start = mIndices[i] * 2;
        int size = mDofs[i].size();
        mDofs[i] = newState.segment(start, size);
        mDofVels[i] = newState.segment(start + size, size);
    }
}

} // end namespace robotics

// Local Variables:
// c-basic-offset: 2
// End:
<|endoftext|>


<commit_before>/*
 *  Copyright 2018 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/strings/string_builder.h"

#include <stdarg.h>
#include <cstring>

#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"

namespace rtc {

SimpleStringBuilder::SimpleStringBuilder(rtc::ArrayView<char> buffer)
    : buffer_(buffer) {
  buffer_[0] = '\0';
  RTC_DCHECK(IsConsistent());
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(const char* str) {
  return Append(str);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(char ch) {
  return Append(&ch, 1);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(const std::string& str) {
  return Append(str.c_str(), str.length());
}

// Numeric conversion routines.
//
// We use std::[v]snprintf instead of std::to_string because:
// * std::to_string relies on the current locale for formatting purposes,
//   and therefore concurrent calls to std::to_string from multiple threads
//   may result in partial serialization of calls
// * snprintf allows us to print the number directly into our buffer.
// * avoid allocating a std::string (potential heap alloc).
// TODO(tommi): Switch to std::to_chars in C++17.

SimpleStringBuilder& SimpleStringBuilder::operator<<(int i) {
  return AppendFormat("%d", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(unsigned i) {
  return AppendFormat("%u", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long i) {  // NOLINT
  return AppendFormat("%ld", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long long i) {  // NOLINT
  return AppendFormat("%lld", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(
    unsigned long i) {  // NOLINT
  return AppendFormat("%lu", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(
    unsigned long long i) {  // NOLINT
  return AppendFormat("%llu", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(float f) {
  return AppendFormat("%g", f);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(double f) {
  return AppendFormat("%g", f);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long double f) {
  return AppendFormat("%Lg", f);
}

SimpleStringBuilder& SimpleStringBuilder::AppendFormat(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  const int len =
      std::vsnprintf(&buffer_[size_], buffer_.size() - size_, fmt, args);
  if (len >= 0) {
    const size_t chars_added = rtc::SafeMin(len, buffer_.size() - 1 - size_);
    size_ += chars_added;
    RTC_DCHECK_EQ(len, chars_added) << "Buffer size was insufficient";
  } else {
    // This should never happen, but we're paranoid, so re-write the
    // terminator in case vsnprintf() overwrote it.
    RTC_NOTREACHED();
    buffer_[size_] = '\0';
  }
  va_end(args);
  RTC_DCHECK(IsConsistent());
  return *this;
}

SimpleStringBuilder& SimpleStringBuilder::Append(const char* str,
                                                 size_t length) {
  const size_t chars_added =
      rtc::strcpyn(&buffer_[size_], buffer_.size() - size_, str, length);
  size_ += chars_added;
  RTC_DCHECK_EQ(chars_added, length == SIZE_UNKNOWN ? std::strlen(str) : length)
      << "Buffer size was insufficient";
  RTC_DCHECK(IsConsistent());
  return *this;
}

StringBuilder& StringBuilder::AppendFormat(const char* fmt, ...) {
  va_list args, copy;
  va_start(args, fmt);
  va_copy(copy, args);
  const int predicted_length = std::vsnprintf(nullptr, 0, fmt, copy);
  va_end(copy);

  RTC_DCHECK_GE(predicted_length, 0);
  if (predicted_length > 0) {
    const size_t size = str_.size();
    str_.resize(size + predicted_length);
    // Pass "+ 1" to vsnprintf to include space for the '\0'.
    const int actual_length =
        std::vsnprintf(&str_[size], predicted_length + 1, fmt, args);
    RTC_DCHECK_GE(actual_length, 0);
  }
  va_end(args);
  return *this;
}

}  // namespace rtc
<commit_msg>Add <cstdio> include to string_builder.cc to support Android NDK r17<commit_after>/*
 *  Copyright 2018 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/strings/string_builder.h"

#include <stdarg.h>
#include <cstdio>
#include <cstring>

#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"

namespace rtc {

SimpleStringBuilder::SimpleStringBuilder(rtc::ArrayView<char> buffer)
    : buffer_(buffer) {
  buffer_[0] = '\0';
  RTC_DCHECK(IsConsistent());
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(const char* str) {
  return Append(str);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(char ch) {
  return Append(&ch, 1);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(const std::string& str) {
  return Append(str.c_str(), str.length());
}

// Numeric conversion routines.
//
// We use std::[v]snprintf instead of std::to_string because:
// * std::to_string relies on the current locale for formatting purposes,
//   and therefore concurrent calls to std::to_string from multiple threads
//   may result in partial serialization of calls
// * snprintf allows us to print the number directly into our buffer.
// * avoid allocating a std::string (potential heap alloc).
// TODO(tommi): Switch to std::to_chars in C++17.

SimpleStringBuilder& SimpleStringBuilder::operator<<(int i) {
  return AppendFormat("%d", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(unsigned i) {
  return AppendFormat("%u", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long i) {  // NOLINT
  return AppendFormat("%ld", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long long i) {  // NOLINT
  return AppendFormat("%lld", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(
    unsigned long i) {  // NOLINT
  return AppendFormat("%lu", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(
    unsigned long long i) {  // NOLINT
  return AppendFormat("%llu", i);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(float f) {
  return AppendFormat("%g", f);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(double f) {
  return AppendFormat("%g", f);
}

SimpleStringBuilder& SimpleStringBuilder::operator<<(long double f) {
  return AppendFormat("%Lg", f);
}

SimpleStringBuilder& SimpleStringBuilder::AppendFormat(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  const int len =
      std::vsnprintf(&buffer_[size_], buffer_.size() - size_, fmt, args);
  if (len >= 0) {
    const size_t chars_added = rtc::SafeMin(len, buffer_.size() - 1 - size_);
    size_ += chars_added;
    RTC_DCHECK_EQ(len, chars_added) << "Buffer size was insufficient";
  } else {
    // This should never happen, but we're paranoid, so re-write the
    // terminator in case vsnprintf() overwrote it.
    RTC_NOTREACHED();
    buffer_[size_] = '\0';
  }
  va_end(args);
  RTC_DCHECK(IsConsistent());
  return *this;
}

SimpleStringBuilder& SimpleStringBuilder::Append(const char* str,
                                                 size_t length) {
  const size_t chars_added =
      rtc::strcpyn(&buffer_[size_], buffer_.size() - size_, str, length);
  size_ += chars_added;
  RTC_DCHECK_EQ(chars_added, length == SIZE_UNKNOWN ? std::strlen(str) : length)
      << "Buffer size was insufficient";
  RTC_DCHECK(IsConsistent());
  return *this;
}

StringBuilder& StringBuilder::AppendFormat(const char* fmt, ...) {
  va_list args, copy;
  va_start(args, fmt);
  va_copy(copy, args);
  const int predicted_length = std::vsnprintf(nullptr, 0, fmt, copy);
  va_end(copy);

  RTC_DCHECK_GE(predicted_length, 0);
  if (predicted_length > 0) {
    const size_t size = str_.size();
    str_.resize(size + predicted_length);
    // Pass "+ 1" to vsnprintf to include space for the '\0'.
    const int actual_length =
        std::vsnprintf(&str_[size], predicted_length + 1, fmt, args);
    RTC_DCHECK_GE(actual_length, 0);
  }
  va_end(args);
  return *this;
}

}  // namespace rtc
<|endoftext|>