<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.                  *
//  **************************************************************************

#include "AliRICHCluster.h"  //class header
#include <TMinuit.h>         //Solve()
#include <AliStack.h>        //FindCfm(), Solve()
#include <TParticle.h>       //FindCfm()
#include <TClonesArray.h>    //Solve() Test()

ClassImp(AliRICHCluster)
//__________________________________________________________________________________________________
void AliRICHCluster::CoG()
{
// Calculates naive cluster position as a center of gravity of its digits.
// Arguments: none
//   Returns: shape of the cluster i.e. the box which fully contains the cluster
  if(fDigs==0) return;                                  //no digits in this cluster
  fX=fY=0;                                              //set cluster position to (0,0) to start to collect contributions
  for(Int_t iDig=0;iDig<fDigs->GetEntriesFast();iDig++){//digits loop
    AliRICHDigit *pDig=(AliRICHDigit*)fDigs->At(iDig);  //get pointer to next digit
    TVector pad=pDig->Pad(); Double_t q=pDig->Qdc();    //get pad adn QDC of this digit
    TVector2 x2=AliRICHParam::Pad2Loc(pad);             //calculate center of the pad in LORS
    fX += x2.X()*q;fY +=x2.Y()*q;                       //sum up digit centers weighted by QDC
  }//digits loop
  fX/=fQdc;fY/=fQdc;                                    //final center of gravity

  TVector2 center = AliRICHParam::Pad2Loc(AliRICHParam::Loc2Pad(TVector2(fX,fY)));//center of the pad containing calculated cluster position
  fX += AliRICHParam::CogCorr(fX-center.X());                                     //correct cluster position for sinoid

  fStatus=kCoG;
}//CoG()
//__________________________________________________________________________________________________
void AliRICHCluster::FitFunc(Int_t &iNpars, Double_t *, Double_t &chi2, Double_t *par, Int_t )
{
// Cluster fit function
// par[0]=x par[1]=y par[2]=q for the first Mathieson shape
// par[3]=x par[4]=y par[5]=q for the second Mathieson shape and so on up to iNpars/3 Mathieson shapes
// We need to calculate QpadExp - QpadMathieson summup over all pads of the cluster
// Here QpadExp is a actual charge of the pad, QpadMathieson is calculated charge of the pad induced by all Mathiesons
// Arguments: iNpars - number of parameters which is number of local maxima of cluster * 3
//            chi2   - function result to be minimised
//            par   - parameters array of size iNpars
//   Returns: none
  AliRICHCluster *pClu=(AliRICHCluster*)gMinuit->GetObjectFit();
  Int_t iNmathiesons = iNpars/3;

  TVector2 curMathiesonPos;
  chi2 = 0;
  for(Int_t i=0;i<pClu->Size();i++){                                            //loop on all pads of the cluster
    TVector    pad          = pClu->Dig(i)->Pad();
    Double_t dQpadExp       = pClu->Dig(i)->Qdc();
    Double_t dQpadMathieson = 0;
    for(Int_t j=0;j<iNmathiesons;j++){                                          //Mathiesons loop as all of them may contribute to this pad
      curMathiesonPos.Set(par[3*j],par[3*j+1]);                                 //get position of current Mathieson
      dQpadMathieson += par[3*j+2]*AliRICHParam::FracQdc(curMathiesonPos,pad);  //sums up contributions to the current pad from all Mathiesons
    }
    chi2 += TMath::Power((dQpadMathieson-dQpadExp),2);                          //
  }                                                                             //loop on all pads of the cluster
}//FitFunction()
//__________________________________________________________________________________________________
void AliRICHCluster::Print(Option_t* opt)const
{
//Print current cluster
  const char *status=0;
  switch(fStatus){
    case      kFormed: status="formed"     ;break;
    case    kUnfolded: status="unfolded"   ;break;
    case         kCoG: status="coged"      ;break;
    case       kEmpty: status="empty"      ;break;
  }
  Printf("%s cs=%2i, Size=%2i (x=%7.3f cm,y=%7.3f cm,Q=%4i qdc), %s",
         opt,fCham,Size(),fX,fY,fQdc,status);
  for(Int_t i=0;i<Size();i++) Dig(i)->Print();
}//Print()
//__________________________________________________________________________________________________
Int_t AliRICHCluster::Solve(TClonesArray *pCluLst,Bool_t isTryUnfold)
{
//This methode is invoked when the cluster is formed to solve it. Solve the cluster means to try to unfold the cluster
//into the local maxima number of clusters. This methode is invoked by AliRICHRconstructor::Dig2Clu() on cluster by cluster basis.
//At this point, cluster contains a list of digits, cluster charge and size is precalculated in AddDigit(), position is preset to (-1,-1) in ctor,
//status is preset to kFormed in AddDigit(), chamber-sector info is preseted to actual values in AddDigit()
//Method first finds number of local maxima and if it's more then one tries to unfold this cluster into local maxima number of clusters
//Arguments: pCluLst     - cluster list pointer where to add new cluster(s)
//           isTryUnfold - flag to switch on/off unfolding
//  Returns: number of local maxima of original cluster

//Phase 0. Initialise TMinuit
  const Int_t kMaxLocMax=6;                                                            //max allowed number of loc max for fitting
  TMinuit *pMinuit = new TMinuit(3*kMaxLocMax);                                        //init MINUIT with this number of parameters (3 params per mathieson)
  pMinuit->SetObjectFit((TObject*)this);  pMinuit->SetFCN(AliRICHCluster::FitFunc);    //set fit function
  Double_t aArg=-1,parStart,parStep,parLow,parHigh;     Int_t iErrFlg;                 //tmp vars for TMinuit
  pMinuit->mnexcm("SET PRI",&aArg,1,iErrFlg);                                          //suspend all printout from TMinuit
  pMinuit->mnexcm("SET NOW",&aArg,0,iErrFlg);                                          //suspend all warning printout from TMinuit
//Phase 1. Find number of local maxima. Strategy is to check if the current pad has QDC more then all neigbours
  Int_t iLocMaxCnt=0;
  for(Int_t iDig1=0;iDig1<Size();iDig1++) {                                             //first digits loop
    AliRICHDigit *pDig1 = Dig(iDig1);                                                   //take next digit
    Int_t iHowManyMoreCnt = 0;                                                          //counts how many neighbouring pads has QDC more then current one
    for(Int_t iDig2=0;iDig2<Size();iDig2++) {                                           //loop on all digits again
      AliRICHDigit *pDig2 = Dig(iDig2);                                                 //take second digit to compare with the first one
      if(iDig1==iDig2) continue;                                                        //the same digit, no need to compare
      Int_t dist = TMath::Sign(Int_t(pDig1->PadX()-pDig2->PadX()),1)+TMath::Sign(Int_t(pDig1->PadY()-pDig2->PadY()),1);//distance between pads
      if(dist==1)                                                                       //means dig2 is a neighbour of dig1
         if(pDig2->Qdc()>=pDig1->Qdc()) iHowManyMoreCnt++;                              //count number of pads with Q more then Q of current pad
    }//second digits loop
    if(iHowManyMoreCnt==0&&iLocMaxCnt<=kMaxLocMax){                                     //this pad has Q more then any neighbour so it's local maximum
        TVector2 x2=AliRICHParam::Pad2Loc(pDig1->Pad());                                //take pad center position and use it as parameter for current Mathienson shape
        pMinuit->mnparm(3*iLocMaxCnt  ,Form("x%i",iLocMaxCnt),parStart=x2.X()      ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        pMinuit->mnparm(3*iLocMaxCnt+1,Form("y%i",iLocMaxCnt),parStart=x2.Y()      ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        pMinuit->mnparm(3*iLocMaxCnt+2,Form("q%i",iLocMaxCnt),parStart=pDig1->Qdc(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        iLocMaxCnt++;
    }//if this pad is local maximum
  }//first digits loop
//Phase 2. Fit loc max number of Mathiesons or add this current cluster to the list
  Int_t iCluCnt=pCluLst->GetEntriesFast();                                          //get current number of clusters already stored in the list by previous operations
  if(isTryUnfold==kTRUE && iLocMaxCnt<=kMaxLocMax){                                        //resonable number of local maxima to fit and user requested it
    pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg);                                     //start fitting
    Double_t fitX,fitY,fitQ,d1,d2,d3; TString sName;                                //vars to get results from TMinuit
    for(Int_t i=0;i<iLocMaxCnt;i++){//local maxima loop
      pMinuit->mnpout(3*i   ,sName,  fitX, d1 , d2, d3, iErrFlg);
      pMinuit->mnpout(3*i+1 ,sName,  fitY, d1 , d2, d3, iErrFlg);
      pMinuit->mnpout(3*i+2 ,sName,  fitQ, d1 , d2, d3, iErrFlg);
      new ((*pCluLst)[iCluCnt++]) AliRICHCluster(C(),fitX,fitY,(Int_t)fitQ);	    //add new unfolded clusters
    }//local maxima loop
  }else{//do not unfold since number of loc max is unresonably high or user's baned unfolding
    CoG();
    new ((*pCluLst)[iCluCnt++]) AliRICHCluster(*this);  //add this raw cluster
  }
  delete pMinuit;
  return iLocMaxCnt;
}//Solve()
//__________________________________________________________________________________________________
void AliRICHCluster::Test(Double_t x,Double_t y,Double_t e,Bool_t isTryUnfold)
{
//This is to test all cluster functionality
//Uses AddDigit() to add a predifined pad structure and then calls Solve
  TVector2 hitX2(x,y);
  Int_t iQtot=AliRICHParam::TotQdc(hitX2,e);
  if(iQtot==0){
    Printf("Provided hit position out of sensitive area");
    return;
  }
  TVector area=AliRICHParam::Loc2Area(hitX2);
  TVector pad(2);
  AliRICHCluster clu;
  for(pad[1]=area[1];pad[1]<=area[3];pad[1]++){//affected pads loop first y
    for(pad[0]=area[0];pad[0]<=area[2];pad[0]++){//then x
      Double_t dQpad=iQtot*AliRICHParam::FracQdc(hitX2,pad);//charge fraction from Mathieson centered at x to pad
      clu.DigAdd(new AliRICHDigit(pad,dQpad));
    }//affected pads loop
  }
  clu.CoG();  clu.Print("Initial cluster:");
  TClonesArray *pCluLst=new TClonesArray("AliRICHCluster",1);
  clu.Solve(pCluLst,isTryUnfold);
  Printf("Initial hit    :  (%.2f,%.2f) Qtot=%i E=%.2f eV",x,y,iQtot,e*1e9);
  ((AliRICHCluster *)pCluLst->At(0))->Print("Solved cluster:");

  delete pCluLst; clu.Reset();
}//Test()
//__________________________________________________________________________________________________
void AliRICHCluster::Test()
{
//Test cluster builder by a number of predefined digit patterns
//Arguments: none
//  Returns: none
  AliRICHCluster clu; Int_t ch,padx,pady,qdc; TClonesArray *pCluLst=new TClonesArray("AliRICHCluster",10);
  Printf("2 digits vertical cluster");
  clu.DigAdd(new AliRICHDigit(AliRICHDigit::P2A(ch=1,padx=3,pady=3),qdc=101));
  clu.DigAdd(new AliRICHDigit(AliRICHDigit::P2A(ch=1,padx=3,pady=4),qdc=202));

  clu.Print("Formed cluster:");
  clu.Solve(pCluLst,kTRUE);
  pCluLst->Print();
  delete pCluLst;
}
<commit_msg>Fix to avoid problems in the fit of clusters (K.Shileev)<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.                  *
//  **************************************************************************

#include "AliRICHCluster.h"  //class header
#include <TMinuit.h>         //Solve()
#include <AliStack.h>        //FindCfm(), Solve()
#include <TParticle.h>       //FindCfm()
#include <TClonesArray.h>    //Solve() Test()

ClassImp(AliRICHCluster)
//__________________________________________________________________________________________________
void AliRICHCluster::CoG()
{
// Calculates naive cluster position as a center of gravity of its digits.
// Arguments: none
//   Returns: shape of the cluster i.e. the box which fully contains the cluster
  if(fDigs==0) return;                                  //no digits in this cluster
  fX=fY=0;                                              //set cluster position to (0,0) to start to collect contributions
  for(Int_t iDig=0;iDig<fDigs->GetEntriesFast();iDig++){//digits loop
    AliRICHDigit *pDig=(AliRICHDigit*)fDigs->At(iDig);  //get pointer to next digit
    TVector pad=pDig->Pad(); Double_t q=pDig->Qdc();    //get pad adn QDC of this digit
    TVector2 x2=AliRICHParam::Pad2Loc(pad);             //calculate center of the pad in LORS
    fX += x2.X()*q;fY +=x2.Y()*q;                       //sum up digit centers weighted by QDC
  }//digits loop
  fX/=fQdc;fY/=fQdc;                                    //final center of gravity

  TVector2 center = AliRICHParam::Pad2Loc(AliRICHParam::Loc2Pad(TVector2(fX,fY)));//center of the pad containing calculated cluster position
  fX += AliRICHParam::CogCorr(fX-center.X());                                     //correct cluster position for sinoid

  fStatus=kCoG;
}//CoG()
//__________________________________________________________________________________________________
void AliRICHCluster::FitFunc(Int_t &iNpars, Double_t *, Double_t &chi2, Double_t *par, Int_t )
{
// Cluster fit function
// par[0]=x par[1]=y par[2]=q for the first Mathieson shape
// par[3]=x par[4]=y par[5]=q for the second Mathieson shape and so on up to iNpars/3 Mathieson shapes
// We need to calculate QpadExp - QpadMathieson summup over all pads of the cluster
// Here QpadExp is a actual charge of the pad, QpadMathieson is calculated charge of the pad induced by all Mathiesons
// Arguments: iNpars - number of parameters which is number of local maxima of cluster * 3
//            chi2   - function result to be minimised
//            par   - parameters array of size iNpars
//   Returns: none
  AliRICHCluster *pClu=(AliRICHCluster*)gMinuit->GetObjectFit();
  Int_t iNmathiesons = iNpars/3;

  TVector2 curMathiesonPos;
  chi2 = 0;
  for(Int_t i=0;i<pClu->Size();i++){                                            //loop on all pads of the cluster
    TVector    pad          = pClu->Dig(i)->Pad();
    Double_t dQpadExp       = pClu->Dig(i)->Qdc();
    Double_t dQpadMathieson = 0;
    for(Int_t j=0;j<iNmathiesons;j++){                                          //Mathiesons loop as all of them may contribute to this pad
      curMathiesonPos.Set(par[3*j],par[3*j+1]);                                 //get position of current Mathieson
      dQpadMathieson += par[3*j+2]*AliRICHParam::FracQdc(curMathiesonPos,pad);  //sums up contributions to the current pad from all Mathiesons
    }
    chi2 += TMath::Power((dQpadMathieson-dQpadExp),2);                          //
  }                                                                             //loop on all pads of the cluster
}//FitFunction()
//__________________________________________________________________________________________________
void AliRICHCluster::Print(Option_t* opt)const
{
//Print current cluster
  const char *status=0;
  switch(fStatus){
    case      kFormed: status="formed"     ;break;
    case    kUnfolded: status="unfolded"   ;break;
    case         kCoG: status="coged"      ;break;
    case       kEmpty: status="empty"      ;break;
  }
  Printf("%s cs=%2i, Size=%2i (x=%7.3f cm,y=%7.3f cm,Q=%4i qdc), %s",
         opt,fCham,Size(),fX,fY,fQdc,status);
  for(Int_t i=0;i<Size();i++) Dig(i)->Print();
}//Print()
//__________________________________________________________________________________________________
Int_t AliRICHCluster::Solve(TClonesArray *pCluLst,Bool_t isTryUnfold)
{
//This methode is invoked when the cluster is formed to solve it. Solve the cluster means to try to unfold the cluster
//into the local maxima number of clusters. This methode is invoked by AliRICHRconstructor::Dig2Clu() on cluster by cluster basis.
//At this point, cluster contains a list of digits, cluster charge and size is precalculated in AddDigit(), position is preset to (-1,-1) in ctor,
//status is preset to kFormed in AddDigit(), chamber-sector info is preseted to actual values in AddDigit()
//Method first finds number of local maxima and if it's more then one tries to unfold this cluster into local maxima number of clusters
//Arguments: pCluLst     - cluster list pointer where to add new cluster(s)
//           isTryUnfold - flag to switch on/off unfolding
//  Returns: number of local maxima of original cluster

//Phase 0. Initialise TMinuit
  const Int_t kMaxLocMax=6;                                                            //max allowed number of loc max for fitting
  TMinuit *pMinuit = new TMinuit(3*kMaxLocMax);                                        //init MINUIT with this number of parameters (3 params per mathieson)
  pMinuit->SetObjectFit((TObject*)this);  pMinuit->SetFCN(AliRICHCluster::FitFunc);    //set fit function
  Double_t aArg=-1,parStart,parStep,parLow,parHigh;     Int_t iErrFlg;                 //tmp vars for TMinuit
  pMinuit->mnexcm("SET PRI",&aArg,1,iErrFlg);                                          //suspend all printout from TMinuit
  pMinuit->mnexcm("SET NOW",&aArg,0,iErrFlg);                                          //suspend all warning printout from TMinuit
//Phase 1. Find number of local maxima. Strategy is to check if the current pad has QDC more then all neigbours
  Int_t iLocMaxCnt=0;
  for(Int_t iDig1=0;iDig1<Size();iDig1++) {                                             //first digits loop
    AliRICHDigit *pDig1 = Dig(iDig1);                                                   //take next digit
    Int_t iHowManyMoreCnt = 0;                                                          //counts how many neighbouring pads has QDC more then current one
    for(Int_t iDig2=0;iDig2<Size();iDig2++) {                                           //loop on all digits again
      if(iDig1==iDig2) continue;                                                        //the same digit, no need to compare
      AliRICHDigit *pDig2 = Dig(iDig2);                                                 //take second digit to compare with the first one
      Int_t dist = TMath::Sign(Int_t(pDig1->PadX()-pDig2->PadX()),1)+TMath::Sign(Int_t(pDig1->PadY()-pDig2->PadY()),1);//distance between pads
      if(dist==1)                                                                       //means dig2 is a neighbour of dig1
         if(pDig2->Qdc()>=pDig1->Qdc()) iHowManyMoreCnt++;                              //count number of pads with Q more then Q of current pad
    }//second digits loop
    if(iHowManyMoreCnt==0&&iLocMaxCnt<kMaxLocMax){                                     //this pad has Q more then any neighbour so it's local maximum
        TVector2 x2=AliRICHParam::Pad2Loc(pDig1->Pad());                                //take pad center position and use it as parameter for current Mathienson shape
        pMinuit->mnparm(3*iLocMaxCnt  ,Form("x%i",iLocMaxCnt),parStart=x2.X()      ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        pMinuit->mnparm(3*iLocMaxCnt+1,Form("y%i",iLocMaxCnt),parStart=x2.Y()      ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        pMinuit->mnparm(3*iLocMaxCnt+2,Form("q%i",iLocMaxCnt),parStart=pDig1->Qdc(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
        iLocMaxCnt++;
    }//if this pad is local maximum
  }//first digits loop
//Phase 2. Fit loc max number of Mathiesons or add this current cluster to the list
  Int_t iCluCnt=pCluLst->GetEntriesFast();                                          //get current number of clusters already stored in the list by previous operations
  if(isTryUnfold==kTRUE && iLocMaxCnt<kMaxLocMax){                                        //resonable number of local maxima to fit and user requested it
    pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg);                                     //start fitting
    Double_t fitX,fitY,fitQ,d1,d2,d3; TString sName;                                //vars to get results from TMinuit
    for(Int_t i=0;i<iLocMaxCnt;i++){//local maxima loop
      pMinuit->mnpout(3*i   ,sName,  fitX, d1 , d2, d3, iErrFlg);
      pMinuit->mnpout(3*i+1 ,sName,  fitY, d1 , d2, d3, iErrFlg);
      pMinuit->mnpout(3*i+2 ,sName,  fitQ, d1 , d2, d3, iErrFlg);
      new ((*pCluLst)[iCluCnt++]) AliRICHCluster(C(),fitX,fitY,(Int_t)fitQ);	    //add new unfolded clusters
    }//local maxima loop
  }else{//do not unfold since number of loc max is unresonably high or user's baned unfolding
    CoG();
    new ((*pCluLst)[iCluCnt++]) AliRICHCluster(*this);  //add this raw cluster
  }
  delete pMinuit;
  return iLocMaxCnt;
}//Solve()
//__________________________________________________________________________________________________
void AliRICHCluster::Test(Double_t x,Double_t y,Double_t e,Bool_t isTryUnfold)
{
//This is to test all cluster functionality
//Uses AddDigit() to add a predifined pad structure and then calls Solve
  TVector2 hitX2(x,y);
  Int_t iQtot=AliRICHParam::TotQdc(hitX2,e);
  if(iQtot==0){
    Printf("Provided hit position out of sensitive area");
    return;
  }
  TVector area=AliRICHParam::Loc2Area(hitX2);
  TVector pad(2);
  AliRICHCluster clu;
  for(pad[1]=area[1];pad[1]<=area[3];pad[1]++){//affected pads loop first y
    for(pad[0]=area[0];pad[0]<=area[2];pad[0]++){//then x
      Double_t dQpad=iQtot*AliRICHParam::FracQdc(hitX2,pad);//charge fraction from Mathieson centered at x to pad
      clu.DigAdd(new AliRICHDigit(pad,dQpad));
    }//affected pads loop
  }
  clu.CoG();  clu.Print("Initial cluster:");
  TClonesArray *pCluLst=new TClonesArray("AliRICHCluster",1);
  clu.Solve(pCluLst,isTryUnfold);
  Printf("Initial hit    :  (%.2f,%.2f) Qtot=%i E=%.2f eV",x,y,iQtot,e*1e9);
  ((AliRICHCluster *)pCluLst->At(0))->Print("Solved cluster:");

  delete pCluLst; clu.Reset();
}//Test()
//__________________________________________________________________________________________________
void AliRICHCluster::Test()
{
//Test cluster builder by a number of predefined digit patterns
//Arguments: none
//  Returns: none
  AliRICHCluster clu; Int_t ch,padx,pady,qdc; TClonesArray *pCluLst=new TClonesArray("AliRICHCluster",10);
  Printf("2 digits vertical cluster");
  clu.DigAdd(new AliRICHDigit(AliRICHDigit::P2A(ch=1,padx=3,pady=3),qdc=101));
  clu.DigAdd(new AliRICHDigit(AliRICHDigit::P2A(ch=1,padx=3,pady=4),qdc=202));

  clu.Print("Formed cluster:");
  clu.Solve(pCluLst,kTRUE);
  pCluLst->Print();
  delete pCluLst;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <fstream>

#include <spine/HTTP.h>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/algorithm/string.hpp>

#include <macgyver/ThreadPool.h>

typedef Fmi::ThreadPool::ThreadPool<> pool;

using namespace std;

namespace fs = boost::filesystem;

namespace ip = boost::asio::ip;

namespace bp = boost::posix_time;

namespace po = boost::program_options;

pair<string, string> parseStatus(const boost::iterator_range<char*>& message)
{
  std::vector<boost::iterator_range<std::string::const_iterator> > headerTokens;
  vector<string> statusLineTokens(3);

  auto header_boundary = boost::algorithm::find_first(message, "\r\n\r\n");

  auto header_range = boost::make_iterator_range(message.begin(), header_boundary.begin());
  boost::algorithm::split(
      headerTokens, header_range, boost::is_any_of("\r\n"), boost::token_compress_on);

  if (headerTokens.empty())
  {
    return pair<string, string>();
  }

  auto startIt = headerTokens.begin();
  boost::algorithm::split(statusLineTokens, *startIt, boost::is_space(), boost::token_compress_on);

  string messageBody = string(header_boundary.end(), message.end());

  boost::algorithm::replace_all(messageBody, "\n", " ");
  boost::algorithm::replace_all(messageBody, "\r", " ");

  string code;
  try
  {
    code = statusLineTokens.at(1);
  }
  catch (...)
  {
    return pair<string, string>();
  }

  return make_pair(code, messageBody);
}

struct Request
{
  Request(string host, unsigned short port, string URI) : hostName(host), port(port), URI(URI) {}
  friend ostream& operator<<(ostream& stream, const Request& theReq)
  {
    stream << theReq.hostName << ":" << theReq.port << theReq.URI;
    return stream;
  }

  string hostName;

  unsigned short port;

  string URI;
};

struct Result
{
  Result(bp::ptime resTime, string URI, bp::time_duration duration, string status, string response)
      : resTime(resTime), URI(URI), duration(duration), status(status), response(response)
  {
  }

  friend ostream& operator<<(ostream& stream, const Result& theRes)
  {
    stream << theRes.resTime << "###" << theRes.URI << "###"
           << bp::to_simple_string(theRes.duration) << "###" << theRes.status << "###"
           << theRes.response;
    return stream;
  }

  bp::ptime resTime;

  string URI;

  bp::time_duration duration;

  string status;

  string response;
};

class Tester
{
 public:
  Tester(const string& requestFile,
         unsigned int threads,
         const string& hostname,
         unsigned short port)
      : itsHostName(hostname),
        itsPort(port),
        itsRequestFilePath(requestFile),
        itsThreadPool(new pool(threads)),
        itsSignals(itsIO),
        itsCurrentResultInd(0),
        itsPrintResults(false)
  {
    if (!fs::exists(itsRequestFilePath))
    {
      throw runtime_error("Request file not found");
    }

    readReqFile();

    itsResults.reserve(itsRequests.size());

    // Fill the pool prior to starting
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      itsThreadPool->schedule(boost::bind(&Tester::performRequest, this, req));
    }

    itsSignals.add(SIGQUIT);

    itsSignals.async_wait(boost::bind(&Tester::handleSignal, this, _1, _2));

    itsTimer.reset(new boost::asio::deadline_timer(itsIO));

    itsThread.reset(
        new boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(itsIO))));
  }

  ~Tester()
  {
    if (itsThreadPool != NULL)
    {
      delete itsThreadPool;
      itsThreadPool = NULL;
    }
  }

  void run()
  {
    itsTimer->expires_from_now(bp::seconds(5));

    itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));

    itsThreadPool->start();

    itsThreadPool->join();
  }

  void printResults()
  {
    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    BOOST_FOREACH (const auto& res, itsResults)
    {
      cout << res << endl;
    }
  }

  bool getPrintResults() { return itsPrintResults; }
  void dumpRequests()
  {
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      cout << req << endl;
    }
  }

  void probeRemote()
  {
    ip::tcp::resolver resolver(itsIO);

    ip::tcp::resolver::query query(itsHostName, to_string((long long unsigned int)itsPort));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET / HTTP/1.0\r\n\r\n";

    // Send request
    boost::asio::write(socket, boost::asio::buffer(reqString));

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string tmp;
    string response;
    size =
        boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));

    // If no exceptions are thrown, the remote is succesfully contacted
  }

 private:
  const string itsHostName;

  unsigned int itsPort;

  fs::path itsRequestFilePath;

  pool* itsThreadPool;

  boost::asio::io_service itsIO;

  boost::asio::signal_set itsSignals;

  long itsCurrentResultInd;

  boost::scoped_ptr<boost::thread> itsThread;

  boost::scoped_ptr<boost::asio::deadline_timer> itsTimer;

  vector<Request> itsRequests;

  vector<Result> itsResults;

  boost::mutex itsResultMutex;

  bool itsPrintResults;

  void readReqFile()
  {
    ifstream inFile(itsRequestFilePath.string());

    string line;

    if (inFile.is_open())
    {
      while (getline(inFile, line))
      {
        boost::algorithm::replace_all(line, " ", "+");  //(At least spaces must be encoded
        itsRequests.emplace_back(itsHostName, itsPort, line);
      }

      // Shuffle the requests
      random_shuffle(itsRequests.begin(), itsRequests.end());
    }

    inFile.close();
  }

  void handleSignal(const boost::system::error_code& err, int signal_number)
  {
    itsIO.stop();
    itsThreadPool->shutdown();
    if (signal_number == 3)  // SigQuit should print results
    {
      itsPrintResults = true;
    }
  }

  void printProgress(const boost::system::error_code& err)
  {
    if (err != boost::asio::error::operation_aborted)
    {
      std::vector<Result> theseResults;
      {
        boost::lock_guard<boost::mutex> lock(itsResultMutex);
        theseResults.assign(itsResults.begin() + itsCurrentResultInd, itsResults.end());
        itsCurrentResultInd = itsResults.size();
      }

      if (!theseResults.empty())
      {
        std::size_t reqs = theseResults.size();

        long average_duration = 0;

        BOOST_FOREACH (const auto& res, theseResults)
        {
          average_duration += res.duration.total_milliseconds();
        }

        average_duration /= reqs;

        std::cerr << bp::second_clock::local_time() << " Completed " << reqs
                  << " requests with average response time of " << average_duration << " ms."
                  << std::endl;
      }
      else
      {
        std::cerr << bp::second_clock::local_time() << " No completed requests in this time slice"
                  << std::endl;
      }

      itsTimer->expires_from_now(bp::seconds(5));
      itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));
    }
  }

  void performRequest(Request theReq)
  {
    ip::tcp::resolver resolver(itsIO);
    ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

    // Send request
    auto before = bp::microsec_clock::universal_time();
    boost::system::error_code err;
    boost::asio::write(socket, boost::asio::buffer(reqString), err);

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string errorCode;
    string response;
    if (!err)
    {
      size = boost::asio::read(
          socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8), err);
      auto parsedResult =
          parseStatus(boost::make_iterator_range(retArray.begin(), retArray.begin() + size));
      errorCode = parsedResult.first;
      response = parsedResult.second;
    }
    else
    {
      // Don't include erroneus connects
      return;
    }

    auto after = bp::microsec_clock::universal_time();
    // This request is done

    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    itsResults.emplace_back(before, theReq.URI, after - before, errorCode, response);
  }
};

void testRequest(Request theReq)
{
  boost::asio::io_service itsIO;
  ip::tcp::resolver resolver(itsIO);
  ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
  auto end_iterator = resolver.resolve(query);

  ip::tcp::socket socket(itsIO);
  boost::asio::connect(socket, end_iterator);

  string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

  boost::asio::write(socket, boost::asio::buffer(reqString));

  boost::array<char, 512> retArray;

  // Read until retArray is full
  auto size =
      boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));
  // This request is done

  std::cout << string(retArray.begin(), retArray.begin() + size) << std::endl;
}

int main(int argc, const char* argv[])
{
  unsigned int threads;
  string host;
  unsigned short port;
  string suite_file;

  po::options_description desc("Allowed Options");

  desc.add_options()("help,h", "Print this help")(
      "host,H", po::value<string>(&host)->default_value("brainstormgw.fmi.fi"), "Host")(
      "port,p", po::value<unsigned short>(&port)->default_value(80), "Port")(
      "suite,s", po::value<string>(&suite_file), "File from which to read the suite")(
      "threads,t", po::value<unsigned int>(&threads)->default_value(5), "Number of worker threads");

  po::variables_map vmap;

  po::store(po::command_line_parser(argc, argv).options(desc).run(), vmap);

  po::notify(vmap);

  if (vmap.count("help"))
  {
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;
    return 1;
  }

  if (vmap.count("suite") == 0)
  {
    std::cout << "Please provide the test suite file" << std::endl;
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;

    return 1;
  }

  Tester theTester(vmap["suite"].as<string>(),
                   vmap["threads"].as<unsigned int>(),
                   vmap["host"].as<string>(),
                   vmap["port"].as<unsigned short>());

  std::cerr << "Probing the remote..." << std::endl;

  theTester.probeRemote();

  std::cerr << "Succesfully probed, running test..." << std::endl;

  theTester.run();

  if (theTester.getPrintResults())
  {
    theTester.printResults();
  }
}
<commit_msg>Replaced boost::scoped_ptr with std::unique_ptr<commit_after>#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <fstream>

#include <spine/HTTP.h>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/algorithm/string.hpp>

#include <macgyver/ThreadPool.h>

typedef Fmi::ThreadPool::ThreadPool<> pool;

using namespace std;

namespace fs = boost::filesystem;

namespace ip = boost::asio::ip;

namespace bp = boost::posix_time;

namespace po = boost::program_options;

pair<string, string> parseStatus(const boost::iterator_range<char*>& message)
{
  std::vector<boost::iterator_range<std::string::const_iterator> > headerTokens;
  vector<string> statusLineTokens(3);

  auto header_boundary = boost::algorithm::find_first(message, "\r\n\r\n");

  auto header_range = boost::make_iterator_range(message.begin(), header_boundary.begin());
  boost::algorithm::split(
      headerTokens, header_range, boost::is_any_of("\r\n"), boost::token_compress_on);

  if (headerTokens.empty())
  {
    return pair<string, string>();
  }

  auto startIt = headerTokens.begin();
  boost::algorithm::split(statusLineTokens, *startIt, boost::is_space(), boost::token_compress_on);

  string messageBody = string(header_boundary.end(), message.end());

  boost::algorithm::replace_all(messageBody, "\n", " ");
  boost::algorithm::replace_all(messageBody, "\r", " ");

  string code;
  try
  {
    code = statusLineTokens.at(1);
  }
  catch (...)
  {
    return pair<string, string>();
  }

  return make_pair(code, messageBody);
}

struct Request
{
  Request(string host, unsigned short port, string URI) : hostName(host), port(port), URI(URI) {}
  friend ostream& operator<<(ostream& stream, const Request& theReq)
  {
    stream << theReq.hostName << ":" << theReq.port << theReq.URI;
    return stream;
  }

  string hostName;

  unsigned short port;

  string URI;
};

struct Result
{
  Result(bp::ptime resTime, string URI, bp::time_duration duration, string status, string response)
      : resTime(resTime), URI(URI), duration(duration), status(status), response(response)
  {
  }

  friend ostream& operator<<(ostream& stream, const Result& theRes)
  {
    stream << theRes.resTime << "###" << theRes.URI << "###"
           << bp::to_simple_string(theRes.duration) << "###" << theRes.status << "###"
           << theRes.response;
    return stream;
  }

  bp::ptime resTime;

  string URI;

  bp::time_duration duration;

  string status;

  string response;
};

class Tester
{
 public:
  Tester(const string& requestFile,
         unsigned int threads,
         const string& hostname,
         unsigned short port)
      : itsHostName(hostname),
        itsPort(port),
        itsRequestFilePath(requestFile),
        itsThreadPool(new pool(threads)),
        itsSignals(itsIO),
        itsCurrentResultInd(0),
        itsPrintResults(false)
  {
    if (!fs::exists(itsRequestFilePath))
    {
      throw runtime_error("Request file not found");
    }

    readReqFile();

    itsResults.reserve(itsRequests.size());

    // Fill the pool prior to starting
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      itsThreadPool->schedule(boost::bind(&Tester::performRequest, this, req));
    }

    itsSignals.add(SIGQUIT);

    itsSignals.async_wait(boost::bind(&Tester::handleSignal, this, _1, _2));

    itsTimer.reset(new boost::asio::deadline_timer(itsIO));

    itsThread.reset(
        new boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(itsIO))));
  }

  ~Tester()
  {
    if (itsThreadPool != NULL)
    {
      delete itsThreadPool;
      itsThreadPool = NULL;
    }
  }

  void run()
  {
    itsTimer->expires_from_now(bp::seconds(5));

    itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));

    itsThreadPool->start();

    itsThreadPool->join();
  }

  void printResults()
  {
    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    BOOST_FOREACH (const auto& res, itsResults)
    {
      cout << res << endl;
    }
  }

  bool getPrintResults() { return itsPrintResults; }
  void dumpRequests()
  {
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      cout << req << endl;
    }
  }

  void probeRemote()
  {
    ip::tcp::resolver resolver(itsIO);

    ip::tcp::resolver::query query(itsHostName, to_string((long long unsigned int)itsPort));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET / HTTP/1.0\r\n\r\n";

    // Send request
    boost::asio::write(socket, boost::asio::buffer(reqString));

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string tmp;
    string response;
    size =
        boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));

    // If no exceptions are thrown, the remote is succesfully contacted
  }

 private:
  const string itsHostName;

  unsigned int itsPort;

  fs::path itsRequestFilePath;

  pool* itsThreadPool;

  boost::asio::io_service itsIO;

  boost::asio::signal_set itsSignals;

  long itsCurrentResultInd;

  std::unique_ptr<boost::thread> itsThread;

  std::unique_ptr<boost::asio::deadline_timer> itsTimer;

  vector<Request> itsRequests;

  vector<Result> itsResults;

  boost::mutex itsResultMutex;

  bool itsPrintResults;

  void readReqFile()
  {
    ifstream inFile(itsRequestFilePath.string());

    string line;

    if (inFile.is_open())
    {
      while (getline(inFile, line))
      {
        boost::algorithm::replace_all(line, " ", "+");  //(At least spaces must be encoded
        itsRequests.emplace_back(itsHostName, itsPort, line);
      }

      // Shuffle the requests
      random_shuffle(itsRequests.begin(), itsRequests.end());
    }

    inFile.close();
  }

  void handleSignal(const boost::system::error_code& err, int signal_number)
  {
    itsIO.stop();
    itsThreadPool->shutdown();
    if (signal_number == 3)  // SigQuit should print results
    {
      itsPrintResults = true;
    }
  }

  void printProgress(const boost::system::error_code& err)
  {
    if (err != boost::asio::error::operation_aborted)
    {
      std::vector<Result> theseResults;
      {
        boost::lock_guard<boost::mutex> lock(itsResultMutex);
        theseResults.assign(itsResults.begin() + itsCurrentResultInd, itsResults.end());
        itsCurrentResultInd = itsResults.size();
      }

      if (!theseResults.empty())
      {
        std::size_t reqs = theseResults.size();

        long average_duration = 0;

        BOOST_FOREACH (const auto& res, theseResults)
        {
          average_duration += res.duration.total_milliseconds();
        }

        average_duration /= reqs;

        std::cerr << bp::second_clock::local_time() << " Completed " << reqs
                  << " requests with average response time of " << average_duration << " ms."
                  << std::endl;
      }
      else
      {
        std::cerr << bp::second_clock::local_time() << " No completed requests in this time slice"
                  << std::endl;
      }

      itsTimer->expires_from_now(bp::seconds(5));
      itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));
    }
  }

  void performRequest(Request theReq)
  {
    ip::tcp::resolver resolver(itsIO);
    ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

    // Send request
    auto before = bp::microsec_clock::universal_time();
    boost::system::error_code err;
    boost::asio::write(socket, boost::asio::buffer(reqString), err);

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string errorCode;
    string response;
    if (!err)
    {
      size = boost::asio::read(
          socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8), err);
      auto parsedResult =
          parseStatus(boost::make_iterator_range(retArray.begin(), retArray.begin() + size));
      errorCode = parsedResult.first;
      response = parsedResult.second;
    }
    else
    {
      // Don't include erroneus connects
      return;
    }

    auto after = bp::microsec_clock::universal_time();
    // This request is done

    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    itsResults.emplace_back(before, theReq.URI, after - before, errorCode, response);
  }
};

void testRequest(Request theReq)
{
  boost::asio::io_service itsIO;
  ip::tcp::resolver resolver(itsIO);
  ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
  auto end_iterator = resolver.resolve(query);

  ip::tcp::socket socket(itsIO);
  boost::asio::connect(socket, end_iterator);

  string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

  boost::asio::write(socket, boost::asio::buffer(reqString));

  boost::array<char, 512> retArray;

  // Read until retArray is full
  auto size =
      boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));
  // This request is done

  std::cout << string(retArray.begin(), retArray.begin() + size) << std::endl;
}

int main(int argc, const char* argv[])
{
  unsigned int threads;
  string host;
  unsigned short port;
  string suite_file;

  po::options_description desc("Allowed Options");

  desc.add_options()("help,h", "Print this help")(
      "host,H", po::value<string>(&host)->default_value("brainstormgw.fmi.fi"), "Host")(
      "port,p", po::value<unsigned short>(&port)->default_value(80), "Port")(
      "suite,s", po::value<string>(&suite_file), "File from which to read the suite")(
      "threads,t", po::value<unsigned int>(&threads)->default_value(5), "Number of worker threads");

  po::variables_map vmap;

  po::store(po::command_line_parser(argc, argv).options(desc).run(), vmap);

  po::notify(vmap);

  if (vmap.count("help"))
  {
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;
    return 1;
  }

  if (vmap.count("suite") == 0)
  {
    std::cout << "Please provide the test suite file" << std::endl;
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;

    return 1;
  }

  Tester theTester(vmap["suite"].as<string>(),
                   vmap["threads"].as<unsigned int>(),
                   vmap["host"].as<string>(),
                   vmap["port"].as<unsigned short>());

  std::cerr << "Probing the remote..." << std::endl;

  theTester.probeRemote();

  std::cerr << "Succesfully probed, running test..." << std::endl;

  theTester.run();

  if (theTester.getPrintResults())
  {
    theTester.printResults();
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: CenterViewFocusModule.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-03 15:50:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "precompiled_sd.hxx"

#include "CenterViewFocusModule.hxx"

#include "framework/ConfigurationController.hxx"
#include "framework/FrameworkHelper.hxx"
#include "framework/ViewShellWrapper.hxx"

#include "DrawController.hxx"
#include "ViewShellBase.hxx"
#include "ViewShellManager.hxx"
#include "strings.hrc"
#include "sdresid.hxx"

#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONTROLLERMANAGER_HPP_
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCONTROLLER_HPP_
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#endif

#include <toolkit/awt/vclxdevice.hxx>
#include <sfx2/viewfrm.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;

using ::rtl::OUString;
using ::sd::framework::FrameworkHelper;

namespace sd { namespace framework {

//===== CenterViewFocusModule ====================================================

CenterViewFocusModule::CenterViewFocusModule (Reference<frame::XController>& rxController)
    : CenterViewFocusModuleInterfaceBase(MutexOwner::maMutex),
      mbValid(false),
      mxViewController(),
      mxConfigurationController(),
      mpBase(NULL),
      mbNewViewCreated(false)
{
    Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY);
    if (xControllerManager.is())
    {
        mxViewController = xControllerManager->getViewController();
        mxConfigurationController = xControllerManager->getConfigurationController();

        // Tunnel through the controller to obtain a ViewShellBase.
        Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY);
        if (xTunnel.is())
        {
            ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
                xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
            if (pController != NULL)
                mpBase = pController->GetViewShellBase();
        }

        // Check, if all required objects do exist.
        if (mxViewController.is()
            && mxConfigurationController.is()
            && mpBase!=NULL)
        {
            mbValid = true;
        }
    }

    if (mbValid)
    {
        mxConfigurationController->addConfigurationChangeListener(
            this,
            FrameworkHelper::msConfigurationUpdateEndEvent,
            Any());
        mxConfigurationController->addConfigurationChangeListener(
            this,
            FrameworkHelper::msResourceActivationEvent,
            Any());
    }
}

CenterViewFocusModule::~CenterViewFocusModule (void)
{
}

void SAL_CALL CenterViewFocusModule::disposing (void)
{
    if (mxConfigurationController.is())
        mxConfigurationController->removeConfigurationChangeListener(this);

    mbValid = false;
    mxViewController = NULL;
    mxConfigurationController = NULL;
    mpBase = NULL;
}

void SAL_CALL CenterViewFocusModule::notifyConfigurationChange (
    const ConfigurationChangeEvent& rEvent)
    throw (RuntimeException)
{
    if (mbValid)
    {
        if (rEvent.Type.equals(FrameworkHelper::msConfigurationUpdateEndEvent))
        {
            ConfigurationUpdateEnd();
        }
        else if (rEvent.Type.equals(FrameworkHelper::msResourceActivationEvent))
        {
            if (rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix))
                mbNewViewCreated = true;
        }
    }
}

void CenterViewFocusModule::ConfigurationUpdateEnd (void)
{
    if (mbNewViewCreated)
    {
        mbNewViewCreated = false;
        // Make the center pane the active one.  Tunnel through the
        // controller to obtain a ViewShell pointer.
        Reference<XView> xView (mxViewController->getFirstViewForAnchor(
            FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL)));
        Reference<lang::XUnoTunnel> xTunnel (xView, UNO_QUERY);
        if (xTunnel.is() && mpBase!=NULL)
        {
            ViewShellWrapper* pViewShellWrapper = reinterpret_cast<ViewShellWrapper*>(
                xTunnel->getSomething(ViewShellWrapper::getUnoTunnelId()));
            if (pViewShellWrapper != NULL)
            {
                ::boost::shared_ptr<ViewShell> pViewShell = pViewShellWrapper->GetViewShell();
                if (pViewShell.get() != NULL)
                    mpBase->GetViewShellManager().MoveToTop(*pViewShell);
            }
        }
    }
}

void SAL_CALL CenterViewFocusModule::disposing (
    const lang::EventObject& rEvent)
    throw (RuntimeException)
{
    if (mxConfigurationController.is())
        if (rEvent.Source == mxConfigurationController)
        {
            mbValid = false;
            mxConfigurationController = NULL;
            mxViewController = NULL;
            mpBase = NULL;
        }
}

} } // end of namespace sd::framework
<commit_msg>INTEGRATION: CWS presenterview (1.2.22); FILE MERGED 2007/07/10 14:24:33 af 1.2.22.2: #i18486# Converted several members of ViewShellBase to shared_ptrs. 2007/06/19 08:01:42 af 1.2.22.1: #i18486# Adaption to recent framework API changes.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: CenterViewFocusModule.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 13:37:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "precompiled_sd.hxx"

#include "CenterViewFocusModule.hxx"

#include "framework/ConfigurationController.hxx"
#include "framework/FrameworkHelper.hxx"
#include "framework/ViewShellWrapper.hxx"

#include "DrawController.hxx"
#include "ViewShellBase.hxx"
#include "ViewShellManager.hxx"
#include "strings.hrc"
#include "sdresid.hxx"

#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONTROLLERMANAGER_HPP_
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCONTROLLER_HPP_
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#endif

#include <toolkit/awt/vclxdevice.hxx>
#include <sfx2/viewfrm.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;

using ::rtl::OUString;
using ::sd::framework::FrameworkHelper;

namespace sd { namespace framework {

//===== CenterViewFocusModule ====================================================

CenterViewFocusModule::CenterViewFocusModule (Reference<frame::XController>& rxController)
    : CenterViewFocusModuleInterfaceBase(MutexOwner::maMutex),
      mbValid(false),
      mxConfigurationController(),
      mpBase(NULL),
      mbNewViewCreated(false)
{
    Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY);
    if (xControllerManager.is())
    {
        mxConfigurationController = xControllerManager->getConfigurationController();

        // Tunnel through the controller to obtain a ViewShellBase.
        Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY);
        if (xTunnel.is())
        {
            ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
                xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
            if (pController != NULL)
                mpBase = pController->GetViewShellBase();
        }

        // Check, if all required objects do exist.
        if (mxConfigurationController.is() && mpBase!=NULL)
        {
            mbValid = true;
        }
    }

    if (mbValid)
    {
        mxConfigurationController->addConfigurationChangeListener(
            this,
            FrameworkHelper::msConfigurationUpdateEndEvent,
            Any());
        mxConfigurationController->addConfigurationChangeListener(
            this,
            FrameworkHelper::msResourceActivationEvent,
            Any());
    }
}

CenterViewFocusModule::~CenterViewFocusModule (void)
{
}

void SAL_CALL CenterViewFocusModule::disposing (void)
{
    if (mxConfigurationController.is())
        mxConfigurationController->removeConfigurationChangeListener(this);

    mbValid = false;
    mxConfigurationController = NULL;
    mpBase = NULL;
}

void SAL_CALL CenterViewFocusModule::notifyConfigurationChange (
    const ConfigurationChangeEvent& rEvent)
    throw (RuntimeException)
{
    if (mbValid)
    {
        if (rEvent.Type.equals(FrameworkHelper::msConfigurationUpdateEndEvent))
        {
            HandleNewView(rEvent.Configuration);
        }
        else if (rEvent.Type.equals(FrameworkHelper::msResourceActivationEvent))
        {
            if (rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix))
                mbNewViewCreated = true;
        }
    }
}

void CenterViewFocusModule::HandleNewView (
    const Reference<XConfiguration>& rxConfiguration)
{
    if (mbNewViewCreated)
    {
        mbNewViewCreated = false;
        // Make the center pane the active one.  Tunnel through the
        // controller to obtain a ViewShell pointer.

        Sequence<Reference<XResourceId> > xViewIds (rxConfiguration->getResources(
            FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL),
            FrameworkHelper::msViewURLPrefix,
            AnchorBindingMode_DIRECT));
        Reference<XView> xView;
        if (xViewIds.getLength() > 0)
            xView = Reference<XView>(
                mxConfigurationController->getResource(xViewIds[0]),UNO_QUERY);
        Reference<lang::XUnoTunnel> xTunnel (xView, UNO_QUERY);
        if (xTunnel.is() && mpBase!=NULL)
        {
            ViewShellWrapper* pViewShellWrapper = reinterpret_cast<ViewShellWrapper*>(
                xTunnel->getSomething(ViewShellWrapper::getUnoTunnelId()));
            if (pViewShellWrapper != NULL)
            {
                ::boost::shared_ptr<ViewShell> pViewShell = pViewShellWrapper->GetViewShell();
                if (pViewShell.get() != NULL)
                    mpBase->GetViewShellManager()->MoveToTop(*pViewShell);
            }
        }
    }
}

void SAL_CALL CenterViewFocusModule::disposing (
    const lang::EventObject& rEvent)
    throw (RuntimeException)
{
    if (mxConfigurationController.is())
        if (rEvent.Source == mxConfigurationController)
        {
            mbValid = false;
            mxConfigurationController = NULL;
            mpBase = NULL;
        }
}

} } // end of namespace sd::framework
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PythonMacros.h"
#include "PythonEnvironment.h"
#include "SceneLoaderPY.h"

#include <sofa/simulation/Simulation.h>
#include <SofaSimulationCommon/xml/NodeElement.h>
#include <SofaSimulationCommon/FindByTypeVisitor.h>

#include <sstream>

#include "PythonMainScriptController.h"
#include "PythonEnvironment.h"
#include "PythonFactory.h"

using namespace sofa::core::objectmodel;

namespace sofa
{

namespace simulation
{

std::string SceneLoaderPY::OurHeader;

void SceneLoaderPY::setHeader(const std::string& header)
{
    OurHeader = header;
}

bool SceneLoaderPY::canLoadFileExtension(const char *extension)
{
    std::string ext = extension;
    std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
    return (ext=="py" || ext=="pyscn");
}

bool SceneLoaderPY::canWriteFileExtension(const char *extension)
{
    return canLoadFileExtension(extension);
}

/// get the file type description
std::string SceneLoaderPY::getFileTypeDesc()
{
    return "Python Scenes";
}

/// get the list of file extensions
void SceneLoaderPY::getExtensionList(ExtensionList* list)
{
    list->clear();
    list->push_back("pyscn");
    list->push_back("py");
}

sofa::simulation::Node::SPtr SceneLoaderPY::load(const char *filename)
{
    return loadSceneWithArguments(filename);
}

sofa::simulation::Node::SPtr SceneLoaderPY::loadSceneWithArguments(const char *filename, const std::vector<std::string>& arguments)
{
    if(!OurHeader.empty() && 0 != PyRun_SimpleString(OurHeader.c_str()))
    {
        SP_MESSAGE_ERROR( "header script run error." )
        return NULL;
    }

    PythonEnvironment::runString("createScene=None");
    PythonEnvironment::runString("createSceneAndController=None");

    PythonEnvironment::runString(std::string("__file__=\"") + filename + "\"");

    // We go the the current file's directory so that all relative path are correct
    helper::system::SetDirectory chdir ( filename );

    notifyLoadingScene();
    if(!PythonEnvironment::runFile(helper::system::SetDirectory::GetFileName(filename).c_str(), arguments))
    {
        // LOAD ERROR
        SP_MESSAGE_ERROR( "scene script load error." )
        return NULL;
    }

    PyObject* pDict = PyModule_GetDict(PyImport_AddModule("__main__"));

    // pFunc is also a borrowed reference
    PyObject *pFunc = PyDict_GetItemString(pDict, "createScene");
    if (PyCallable_Check(pFunc))
    {
        Node::SPtr rootNode = Node::create("root");
        SP_CALL_MODULEFUNC(pFunc, "(O)", sofa::PythonFactory::toPython(rootNode.get()))

        return rootNode;
    }
    else
    {
        PyObject *pFunc = PyDict_GetItemString(pDict, "createSceneAndController");
        if (PyCallable_Check(pFunc))
        {
            Node::SPtr rootNode = Node::create("root");
            SP_CALL_MODULEFUNC(pFunc, "(O)", sofa::PythonFactory::toPython(rootNode.get()))

            rootNode->addObject( core::objectmodel::New<component::controller::PythonMainScriptController>( filename ) );

            return rootNode;
        }
    }

    SP_MESSAGE_ERROR( "cannot create Scene, no \"createScene(rootNode)\" nor \"createSceneAndController(rootNode)\" module method found." )
    return NULL;
}

bool SceneLoaderPY::loadTestWithArguments(const char *filename, const std::vector<std::string>& arguments)
{
    if(!OurHeader.empty() && 0 != PyRun_SimpleString(OurHeader.c_str()))
    {
        SP_MESSAGE_ERROR( "header script run error." )
        return false;
    }

    PythonEnvironment::runString("createScene=None");
    PythonEnvironment::runString("createSceneAndController=None");

    PythonEnvironment::runString(std::string("__file__=\"") + filename + "\"");

    // it runs the unecessary SofaPython script but it is not a big deal
    if(!PythonEnvironment::runFile(filename,arguments))
    {
        // LOAD ERROR
        SP_MESSAGE_ERROR( "script load error." )
        return false;
    }

    PyObject* pDict = PyModule_GetDict(PyImport_AddModule("__main__"));

    // pFunc is also a borrowed reference
    PyObject *pFunc = PyDict_GetItemString(pDict, "run");
    if (PyCallable_Check(pFunc))
    {
        PyObject *res = PyObject_CallObject(pFunc,0);
        printPythonExceptions();

        if( !res )
        {
            SP_MESSAGE_ERROR( "Python test 'run' function does not return any value" )
            return false;
        }
        else if( !PyBool_Check(res) )
        {
            SP_MESSAGE_ERROR( "Python test 'run' function does not return a boolean" )
            Py_DECREF(res);
            return false;
        }

        bool result = ( res == Py_True );
        Py_DECREF(res);

        return result;
    }
    else
    {
        SP_MESSAGE_ERROR( "Python test has no 'run'' function" )
        return false;
    }
}

void SceneLoaderPY::write(Node* node, const char *filename)
{
    exportPython( node, filename );
}

//////////////////////////////////////////////////////////////////////////////

static const std::string s_tab = "    ";

inline void printBaseHeader( std::ostream& out, Node* node )
{
    out << "import Sofa\n\n\n";
    out << "def createScene(root):\n";

    out << s_tab << "root.dt = " << node->getDt() << std::endl;
    const Context::Vec3& g = node->getGravity();
    out << s_tab << "root.gravity = [" << g[0] << "," << g[1] << "," << g[2] << "]" << std::endl;
}

void exportPython( Node* node, const char* fileName )
{
    if ( !node ) return;

    if ( fileName!=NULL )
    {
        std::ofstream out( fileName );

        printBaseHeader( out, node );

        PythonExporterVisitor print( out );
        node->execute( print );
    }
    else
    {
        printBaseHeader( std::cout, node );

        PythonExporterVisitor print( std::cout );
        node->execute( print );
    }
}

///////////////////////////////////////////////////////////////////////////////

template<class T>
void PythonExporterVisitor::processObject( T obj, const std::string& nodeVariable )
{
    std::string classname = obj->getClassName();
    std::string templatename = obj->getTemplateName();

    m_out << s_tab << nodeVariable << ".createObject( '" << classname <<"', template='" << templatename << "'";

    obj->writeDatas( m_out, ", " );

    m_out << ")" << std::endl;
}

Visitor::Result PythonExporterVisitor::processNodeTopDown(Node* node)
{
    m_out << "\n\n";

    m_variableIndex++;

    sofa::helper::vector< core::objectmodel::BaseNode* > parents = node->getParents();

    std::string nodeName = node->getName();
    std::stringstream nodeVariable;

    if( !parents.empty() ) // not root
    {
        nodeVariable << nodeName << "_Node" << m_variableIndex;
        m_mapNodeVariable[node] = nodeVariable.str();

        const std::string& parentVariable = m_mapNodeVariable[parents[0]];

        m_out << s_tab << nodeVariable.str() << " = "<<parentVariable<<".createChild( '"<<nodeName <<"' )" << std::endl;
    }
    else
    {
        nodeVariable << "root";
        m_mapNodeVariable[node] = nodeVariable.str();
    }

    for (Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it)
    {
        sofa::core::objectmodel::BaseObject* obj = it->get();
        this->processObject( obj, nodeVariable.str() );
    }

    return RESULT_CONTINUE;
}

void PythonExporterVisitor::processNodeBottomUp(Node* node)
{
    sofa::helper::vector< core::objectmodel::BaseNode* > parents = node->getParents();

    const std::string& nodeVariable = m_mapNodeVariable[node];

    // add all its parents to a multinode
    for( size_t i = 1 ; i<parents.size() ; ++ i)
    {
        const std::string& parentVariable = m_mapNodeVariable[parents[i]];

        m_out << s_tab << parentVariable << ".addChild(" << nodeVariable << ")\n";
    }
}

} // namespace simulation

} // namespace sofa

<commit_msg>[SofaPython] gil sofapyloader too<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PythonMacros.h"
#include "PythonEnvironment.h"
#include "SceneLoaderPY.h"

#include <sofa/simulation/Simulation.h>
#include <SofaSimulationCommon/xml/NodeElement.h>
#include <SofaSimulationCommon/FindByTypeVisitor.h>

#include <sstream>

#include "PythonMainScriptController.h"
#include "PythonEnvironment.h"
#include "PythonFactory.h"

using namespace sofa::core::objectmodel;

namespace sofa
{

namespace simulation
{

std::string SceneLoaderPY::OurHeader;

void SceneLoaderPY::setHeader(const std::string& header)
{
    OurHeader = header;
}

bool SceneLoaderPY::canLoadFileExtension(const char *extension)
{
    std::string ext = extension;
    std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
    return (ext=="py" || ext=="pyscn");
}

bool SceneLoaderPY::canWriteFileExtension(const char *extension)
{
    return canLoadFileExtension(extension);
}

/// get the file type description
std::string SceneLoaderPY::getFileTypeDesc()
{
    return "Python Scenes";
}

/// get the list of file extensions
void SceneLoaderPY::getExtensionList(ExtensionList* list)
{
    list->clear();
    list->push_back("pyscn");
    list->push_back("py");
}

sofa::simulation::Node::SPtr SceneLoaderPY::load(const char *filename)
{
    return loadSceneWithArguments(filename);
}

sofa::simulation::Node::SPtr SceneLoaderPY::loadSceneWithArguments(const char *filename, const std::vector<std::string>& arguments)
{
    PythonEnvironment::gil lock(__func__);
    if(!OurHeader.empty() && 0 != PyRun_SimpleString(OurHeader.c_str()))
    {
        SP_MESSAGE_ERROR( "header script run error." )
        return NULL;
    }

    PythonEnvironment::runString("createScene=None");
    PythonEnvironment::runString("createSceneAndController=None");

    PythonEnvironment::runString(std::string("__file__=\"") + filename + "\"");

    // We go the the current file's directory so that all relative path are correct
    helper::system::SetDirectory chdir ( filename );

    notifyLoadingScene();
    if(!PythonEnvironment::runFile(helper::system::SetDirectory::GetFileName(filename).c_str(), arguments))
    {
        // LOAD ERROR
        SP_MESSAGE_ERROR( "scene script load error." )
        return NULL;
    }

    PyObject* pDict = PyModule_GetDict(PyImport_AddModule("__main__"));

    // pFunc is also a borrowed reference
    PyObject *pFunc = PyDict_GetItemString(pDict, "createScene");
    if (PyCallable_Check(pFunc))
    {
        Node::SPtr rootNode = Node::create("root");
        SP_CALL_MODULEFUNC(pFunc, "(O)", sofa::PythonFactory::toPython(rootNode.get()))

        return rootNode;
    }
    else
    {
        PyObject *pFunc = PyDict_GetItemString(pDict, "createSceneAndController");
        if (PyCallable_Check(pFunc))
        {
            Node::SPtr rootNode = Node::create("root");
            SP_CALL_MODULEFUNC(pFunc, "(O)", sofa::PythonFactory::toPython(rootNode.get()))

            rootNode->addObject( core::objectmodel::New<component::controller::PythonMainScriptController>( filename ) );

            return rootNode;
        }
    }

    SP_MESSAGE_ERROR( "cannot create Scene, no \"createScene(rootNode)\" nor \"createSceneAndController(rootNode)\" module method found." )
    return NULL;
}

bool SceneLoaderPY::loadTestWithArguments(const char *filename, const std::vector<std::string>& arguments)
{
    PythonEnvironment::gil lock(__func__);
    if(!OurHeader.empty() && 0 != PyRun_SimpleString(OurHeader.c_str()))
    {
        SP_MESSAGE_ERROR( "header script run error." )
        return false;
    }

    PythonEnvironment::runString("createScene=None");
    PythonEnvironment::runString("createSceneAndController=None");

    PythonEnvironment::runString(std::string("__file__=\"") + filename + "\"");

    // it runs the unecessary SofaPython script but it is not a big deal
    if(!PythonEnvironment::runFile(filename,arguments))
    {
        // LOAD ERROR
        SP_MESSAGE_ERROR( "script load error." )
        return false;
    }

    PyObject* pDict = PyModule_GetDict(PyImport_AddModule("__main__"));

    // pFunc is also a borrowed reference
    PyObject *pFunc = PyDict_GetItemString(pDict, "run");
    if (PyCallable_Check(pFunc))
    {
        PyObject *res = PyObject_CallObject(pFunc,0);
        printPythonExceptions();

        if( !res )
        {
            SP_MESSAGE_ERROR( "Python test 'run' function does not return any value" )
            return false;
        }
        else if( !PyBool_Check(res) )
        {
            SP_MESSAGE_ERROR( "Python test 'run' function does not return a boolean" )
            Py_DECREF(res);
            return false;
        }

        bool result = ( res == Py_True );
        Py_DECREF(res);

        return result;
    }
    else
    {
        SP_MESSAGE_ERROR( "Python test has no 'run'' function" )
        return false;
    }
}

void SceneLoaderPY::write(Node* node, const char *filename)
{
    exportPython( node, filename );
}

//////////////////////////////////////////////////////////////////////////////

static const std::string s_tab = "    ";

inline void printBaseHeader( std::ostream& out, Node* node )
{
    out << "import Sofa\n\n\n";
    out << "def createScene(root):\n";

    out << s_tab << "root.dt = " << node->getDt() << std::endl;
    const Context::Vec3& g = node->getGravity();
    out << s_tab << "root.gravity = [" << g[0] << "," << g[1] << "," << g[2] << "]" << std::endl;
}

void exportPython( Node* node, const char* fileName )
{
    if ( !node ) return;

    if ( fileName!=NULL )
    {
        std::ofstream out( fileName );

        printBaseHeader( out, node );

        PythonExporterVisitor print( out );
        node->execute( print );
    }
    else
    {
        printBaseHeader( std::cout, node );

        PythonExporterVisitor print( std::cout );
        node->execute( print );
    }
}

///////////////////////////////////////////////////////////////////////////////

template<class T>
void PythonExporterVisitor::processObject( T obj, const std::string& nodeVariable )
{
    std::string classname = obj->getClassName();
    std::string templatename = obj->getTemplateName();

    m_out << s_tab << nodeVariable << ".createObject( '" << classname <<"', template='" << templatename << "'";

    obj->writeDatas( m_out, ", " );

    m_out << ")" << std::endl;
}

Visitor::Result PythonExporterVisitor::processNodeTopDown(Node* node)
{
    m_out << "\n\n";

    m_variableIndex++;

    sofa::helper::vector< core::objectmodel::BaseNode* > parents = node->getParents();

    std::string nodeName = node->getName();
    std::stringstream nodeVariable;

    if( !parents.empty() ) // not root
    {
        nodeVariable << nodeName << "_Node" << m_variableIndex;
        m_mapNodeVariable[node] = nodeVariable.str();

        const std::string& parentVariable = m_mapNodeVariable[parents[0]];

        m_out << s_tab << nodeVariable.str() << " = "<<parentVariable<<".createChild( '"<<nodeName <<"' )" << std::endl;
    }
    else
    {
        nodeVariable << "root";
        m_mapNodeVariable[node] = nodeVariable.str();
    }

    for (Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it)
    {
        sofa::core::objectmodel::BaseObject* obj = it->get();
        this->processObject( obj, nodeVariable.str() );
    }

    return RESULT_CONTINUE;
}

void PythonExporterVisitor::processNodeBottomUp(Node* node)
{
    sofa::helper::vector< core::objectmodel::BaseNode* > parents = node->getParents();

    const std::string& nodeVariable = m_mapNodeVariable[node];

    // add all its parents to a multinode
    for( size_t i = 1 ; i<parents.size() ; ++ i)
    {
        const std::string& parentVariable = m_mapNodeVariable[parents[i]];

        m_out << s_tab << parentVariable << ".addChild(" << nodeVariable << ")\n";
    }
}

} // namespace simulation

} // namespace sofa

<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
        if (n == 1) {
            return {0};
        }

        unordered_map<int, unordered_set<int>> neighbors;
        for (const auto& e : edges) {
            int u, v;
            tie(u, v) = e;
            neighbors[u].emplace(v);
            neighbors[v].emplace(u);
        }

        vector<int> pre_level, cur_level;
        unordered_set<int> unvisited;
        for (int i = 0; i < n; ++i) {
            if (neighbors[i].size() == 1) {  // A leaf.
                pre_level.emplace_back(i);
            }
            unvisited.emplace(i);
        }

        // A graph can have 2 MHTs at most.
        // BFS from the leaves until the number
        // of the unvisited nodes is less than 3.
        while (unvisited.size() > 2) {
            cur_level.clear();
            for (const auto& u : pre_level) {
                unvisited.erase(u);
                for (const auto& v : neighbors[u]) {
                    if (unvisited.count(v)) {
                        neighbors[v].erase(u);
                        if (neighbors[v].size() == 1) {
                            cur_level.emplace_back(v);
                        }
                    }
                }
            }
            swap(pre_level, cur_level);
        }
        vector<int> res(unvisited.begin(), unvisited.end());
        return res;
    }
};
<commit_msg>Update minimum-height-trees.cpp<commit_after>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
        if (n == 1) {
            return {0};
        }

        unordered_map<int, unordered_set<int>> neighbors;
        for (const auto& e : edges) {
            int u, v;
            tie(u, v) = e;
            neighbors[u].emplace(v);
            neighbors[v].emplace(u);
        }

        vector<int> pre_level, cur_level;
        unordered_set<int> unvisited;
        for (int i = 0; i < n; ++i) {
            if (neighbors[i].size() == 1) {  // A leaf.
                pre_level.emplace_back(i);
            }
            unvisited.emplace(i);
        }

        // A graph can have 2 MHTs at most.
        // BFS from the leaves until the number
        // of the unvisited nodes is less than 3.
        while (unvisited.size() > 2) {
            cur_level.clear();
            for (const auto& u : pre_level) {
                unvisited.erase(u);
                for (const auto& v : neighbors[u]) {
                    if (unvisited.count(v)) {
                        neighbors[v].erase(u);
                        if (neighbors[v].size() == 1) {
                            cur_level.emplace_back(v);
                        }
                    }
                }
            }
            swap(pre_level, cur_level);
        }

        vector<int> res(unvisited.begin(), unvisited.end());
        return res;
    }
};
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////
/// @file      drawBox.cpp
/// @author    Chris L Baker (clb) <chris@chimail.net>
/// @date      2014.05.20
/// @brief     Simple example for using the draw lib
///
/// @attention Copyright (C) 2014
/// @attention All rights reserved
/////////////////////////////////////////////////////////////////

/// The main draw object
#include <DDDisplayInterface/DisplayInterface.h>

/// The things to include for drawing
#include <DDDisplayObjects/Grids.h>    // for ground()
#include <DDDisplayObjects/Triads.h>   // for the world origin
#include <DDDisplayObjects/Colors.h>   // gets various colors
#include <DDDisplayObjects/Capsules.h> // to draw the actual box
#include <DDDisplayObjects/HeadsUpDisplay.h> // flashing awesome

/// std stuff
#include <thread>

int main()
{
    // draws a "standard" grid on the ground (z=0 plane)
    d3::di().add( "Ground", d3::ground() );

    // draws an rgb triad at the origin
    d3::di().add( "Origin", d3::origin() );

    // create a simple HUD
    static const float width(0.13), height(0.07);
    static const d3::HeadsUpDisplay::Position position(d3::HeadsUpDisplay::Position::CENTER);
    static const std::string initText("AWESOME");
    d3::HeadsUpDisplay hud(width, height, position, initText);
    hud.setBackgroundColor(d3::black());

    // add the hud to the display
    d3::di().add( "HUD", d3::get(hud) );

    // create a little thread to "flash" the hud
    std::thread thrd
        ([&]()
         {
             while ( d3::di().running() )
             {
                 // we are messing directly with things in the render thread -
                 // make sure we lock the display interface
                 if ( d3::di().try_lock() )
                 {
                     hud.show(not hud.isShown());
                     d3::di().unlock();
                 }

                 // flash at about 2Hz
                 usleep(500000);
             }
         });

    // create the box as a set of capsules
    static const double radius(0.1);
    d3::CapsuleVec_t capsules;

    // The bottom square
    capsules.push_back({{-1.0, -1.0, -1.0}, { 1.0, -1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0, -1.0}, { 1.0,  1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0, -1.0}, {-1.0,  1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0, -1.0}, {-1.0, -1.0, -1.0}, radius, d3::nextColor()});

    // The top square
    capsules.push_back({{-1.0, -1.0,  1.0}, { 1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0,  1.0}, { 1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0,  1.0}, {-1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0,  1.0}, {-1.0, -1.0,  1.0}, radius, d3::nextColor()});

    // Joins the top to the bottom
    capsules.push_back({{-1.0, -1.0, -1.0}, {-1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0, -1.0}, { 1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0, -1.0}, { 1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0, -1.0}, {-1.0,  1.0,  1.0}, radius, d3::nextColor()});

    // add the capsules to the display
    d3::di().add( "box", d3::get(capsules) );

    // wait for the drawing to close
    d3::di().blockForClose();

    return EXIT_SUCCESS;
};
<commit_msg>Why doesn't my compiler know about usleep?  Changed to std::this_thread::sleep_for and seems to work...<commit_after>/////////////////////////////////////////////////////////////////
/// @file      drawBox.cpp
/// @author    Chris L Baker (clb) <chris@chimail.net>
/// @date      2014.05.20
/// @brief     Simple example for using the draw lib
///
/// @attention Copyright (C) 2014
/// @attention All rights reserved
/////////////////////////////////////////////////////////////////

/// The main draw object
#include <DDDisplayInterface/DisplayInterface.h>

/// The things to include for drawing
#include <DDDisplayObjects/Grids.h>    // for ground()
#include <DDDisplayObjects/Triads.h>   // for the world origin
#include <DDDisplayObjects/Colors.h>   // gets various colors
#include <DDDisplayObjects/Capsules.h> // to draw the actual box
#include <DDDisplayObjects/HeadsUpDisplay.h> // flashing awesome

/// std stuff
#include <chrono>
#include <thread>

int main()
{
    // draws a "standard" grid on the ground (z=0 plane)
    d3::di().add( "Ground", d3::ground() );

    // draws an rgb triad at the origin
    d3::di().add( "Origin", d3::origin() );

    // create a simple HUD
    static const float width(0.13), height(0.07);
    static const d3::HeadsUpDisplay::Position position(d3::HeadsUpDisplay::Position::CENTER);
    static const std::string initText("AWESOME");
    d3::HeadsUpDisplay hud(width, height, position, initText);
    hud.setBackgroundColor(d3::black());

    // add the hud to the display
    d3::di().add( "HUD", d3::get(hud) );

    // create a little thread to "flash" the hud
    std::thread thrd
        ([&]()
         {
             while ( d3::di().running() )
             {
                 // we are messing directly with things in the render thread -
                 // make sure we lock the display interface
                 if ( d3::di().try_lock() )
                 {
                     hud.show(not hud.isShown());
                     d3::di().unlock();
                 }

                 // flash at about 2Hz
                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
             }
         });

    // create the box as a set of capsules
    static const double radius(0.1);
    d3::CapsuleVec_t capsules;

    // The bottom square
    capsules.push_back({{-1.0, -1.0, -1.0}, { 1.0, -1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0, -1.0}, { 1.0,  1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0, -1.0}, {-1.0,  1.0, -1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0, -1.0}, {-1.0, -1.0, -1.0}, radius, d3::nextColor()});

    // The top square
    capsules.push_back({{-1.0, -1.0,  1.0}, { 1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0,  1.0}, { 1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0,  1.0}, {-1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0,  1.0}, {-1.0, -1.0,  1.0}, radius, d3::nextColor()});

    // Joins the top to the bottom
    capsules.push_back({{-1.0, -1.0, -1.0}, {-1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0, -1.0, -1.0}, { 1.0, -1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{ 1.0,  1.0, -1.0}, { 1.0,  1.0,  1.0}, radius, d3::nextColor()});
    capsules.push_back({{-1.0,  1.0, -1.0}, {-1.0,  1.0,  1.0}, radius, d3::nextColor()});

    // add the capsules to the display
    d3::di().add( "box", d3::get(capsules) );

    // wait for the drawing to close
    d3::di().blockForClose();

    return EXIT_SUCCESS;
};
<|endoftext|>


<commit_before>// Time:  O(p), p is number of positions
// Space: O(p)

// Using unordered_map.
class Solution {
public:
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<int> numbers;
        int number = 0;
        const vector<pair<int, int>> directions{{0, -1}, {0, 1},
                                                {-1, 0}, {1, 0}};
        unordered_map<int, int> set;
        for (const auto& position : positions) {
            const auto& node = make_pair(position.first, position.second);
            set[node_id(node, n)] = node_id(node, n);
            ++number;

            for (const auto& d : directions) {
                const auto& neighbor = make_pair(position.first + d.first,
                                                 position.second + d.second);
                if (neighbor.first >= 0 && neighbor.first < m &&
                    neighbor.second >= 0 && neighbor.second < n &&
                    set.find(node_id(neighbor, n)) != set.end()) {
                    if (find_set(node_id(node, n), &set) !=
                        find_set(node_id(neighbor, n), &set)) {
                        // Merge different islands.
                        union_set(&set, node_id(node, n), node_id(neighbor, n));
                        --number;
                    }
                }
            }
            numbers.emplace_back(number);
        }

        return numbers;
    }

    int node_id(const pair<int, int>& node, const int n) {
        return node.first * n + node.second;
    }

    int find_set(int x, unordered_map<int, int> *set) {
       if ((*set)[x] != x) {
           (*set)[x] = find_set((*set)[x], set);  // path compression.
       }
       return (*set)[x];
    }

    void union_set(unordered_map<int, int> *set, const int x, const int y) {
        int x_root = find_set(x, set), y_root = find_set(y, set);
        (*set)[min(x_root, y_root)] = max(x_root, y_root);
    }
};

// Time:  O(p), p is number of positions
// Space: O(m * n)
// Using vector.
class Solution2 {
public:
    /**
     * @param n an integer
     * @param m an integer
     * @param operators an array of point
     * @return an integer array
     */
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<int> numbers;
        int number = 0;
        const vector<pair<int, int>> directions{{0, -1}, {0, 1},
                                                {-1, 0}, {1, 0}};
        vector<int> set(m * n, -1);
        for (const auto& position : positions) {
            const auto& node = make_pair(position.first, position.second);
            set[node_id(node, n)] = node_id(node, n);
            ++number;

            for (const auto& d : directions) {
                const auto& neighbor = make_pair(position.first + d.first,
                                                 position.second + d.second);
                if (neighbor.first >= 0 && neighbor.first < m &&
                    neighbor.second >= 0 && neighbor.second < n &&
                    set[node_id(neighbor, n)] != -1) {
                    if (find_set(node_id(node, n), &set) !=
                        find_set(node_id(neighbor, n), &set)) {
                        // Merge different islands.
                        union_set(&set, node_id(node, n), node_id(neighbor, n));
                        --number;
                    }
                }
            }
            numbers.emplace_back(number);
        }

        return numbers;
    }

    int node_id(const pair<int, int>& node, const int m) {
        return node.first * m + node.second;
    }

    int find_set(int x, vector<int> *set) {
        int parent = x;
        while ((*set)[parent] != parent) {
            parent = (*set)[parent];
        }
        while ((*set)[x] != x) {
            int tmp = (*set)[x];
            (*set)[x] = parent;
            x = tmp;
        }
        return parent;
    }

    void union_set(vector<int> *set, const int x, const int y) {
        int x_root = find_set(x, set), y_root = find_set(y, set);
        (*set)[min(x_root, y_root)] = max(x_root, y_root);
    }
};
<commit_msg>Update number-of-islands-ii.cpp<commit_after>// Time:  O(k * log(m * n)), k is the length of the positions
// Space: O(k)

// Using unordered_map.
class Solution {
public:
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<int> numbers;
        int number = 0;
        const vector<pair<int, int>> directions{{0, -1}, {0, 1},
                                                {-1, 0}, {1, 0}};
        unordered_map<int, int> set;
        for (const auto& position : positions) {
            const auto& node = make_pair(position.first, position.second);
            set[node_id(node, n)] = node_id(node, n);
            ++number;

            for (const auto& d : directions) {
                const auto& neighbor = make_pair(position.first + d.first,
                                                 position.second + d.second);
                if (neighbor.first >= 0 && neighbor.first < m &&
                    neighbor.second >= 0 && neighbor.second < n &&
                    set.find(node_id(neighbor, n)) != set.end()) {
                    if (find_set(node_id(node, n), &set) !=
                        find_set(node_id(neighbor, n), &set)) {
                        // Merge different islands.
                        union_set(&set, node_id(node, n), node_id(neighbor, n));
                        --number;
                    }
                }
            }
            numbers.emplace_back(number);
        }

        return numbers;
    }

    int node_id(const pair<int, int>& node, const int n) {
        return node.first * n + node.second;
    }

    int find_set(int x, unordered_map<int, int> *set) {
       if ((*set)[x] != x) {
           (*set)[x] = find_set((*set)[x], set);  // path compression.
       }
       return (*set)[x];
    }

    void union_set(unordered_map<int, int> *set, const int x, const int y) {
        int x_root = find_set(x, set), y_root = find_set(y, set);
        (*set)[min(x_root, y_root)] = max(x_root, y_root);
    }
};

// Time:  O(k * log(m * n)), k is the length of the positions
// Space: O(m * n)
// Using vector.
class Solution2 {
public:
    /**
     * @param n an integer
     * @param m an integer
     * @param operators an array of point
     * @return an integer array
     */
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<int> numbers;
        int number = 0;
        const vector<pair<int, int>> directions{{0, -1}, {0, 1},
                                                {-1, 0}, {1, 0}};
        vector<int> set(m * n, -1);
        for (const auto& position : positions) {
            const auto& node = make_pair(position.first, position.second);
            set[node_id(node, n)] = node_id(node, n);
            ++number;

            for (const auto& d : directions) {
                const auto& neighbor = make_pair(position.first + d.first,
                                                 position.second + d.second);
                if (neighbor.first >= 0 && neighbor.first < m &&
                    neighbor.second >= 0 && neighbor.second < n &&
                    set[node_id(neighbor, n)] != -1) {
                    if (find_set(node_id(node, n), &set) !=
                        find_set(node_id(neighbor, n), &set)) {
                        // Merge different islands.
                        union_set(&set, node_id(node, n), node_id(neighbor, n));
                        --number;
                    }
                }
            }
            numbers.emplace_back(number);
        }

        return numbers;
    }

    int node_id(const pair<int, int>& node, const int m) {
        return node.first * m + node.second;
    }

    int find_set(int x, vector<int> *set) {
        int parent = x;
        while ((*set)[parent] != parent) {
            parent = (*set)[parent];
        }
        while ((*set)[x] != x) {
            int tmp = (*set)[x];
            (*set)[x] = parent;
            x = tmp;
        }
        return parent;
    }

    void union_set(vector<int> *set, const int x, const int y) {
        int x_root = find_set(x, set), y_root = find_set(y, set);
        (*set)[min(x_root, y_root)] = max(x_root, y_root);
    }
};
<|endoftext|>