<commit_before>//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
//      ----------------------------------------------------------------
//                      K600 Spectrometer (iThemba Labs)
//      ----------------------------------------------------------------
//
//      Github repository: https://www.github.com/KevinCWLi/K600
//
//      Main Author:    K.C.W. Li
//
//      email: likevincw@gmail.com
//

#include "RunAction.hh"
#include "Analysis.hh"

#include "G4Run.hh"
#include "G4RunManager.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

RunAction::RunAction()
: G4UserRunAction()
{
    // set printing event number per each event
    G4RunManager::GetRunManager()->SetPrintProgress(1);

    // Create analysis manager
    // The choice of analysis technology is done via selectin of a namespace
    // in Analysis.hh
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    G4cout << "Using " << analysisManager->GetType() << G4endl;

    // Create directories
    //analysisManager->SetHistoDirectoryName("histograms");
    //analysisManager->SetNtupleDirectoryName("ntuple");
    analysisManager->SetVerboseLevel(1);
    //analysisManager->SetFirstHistoId(1);

    // Book histograms, ntuple
    //

    // Creating 1D histograms
    /*
     ////    TIARA DETECTORS, Histograms 1-6
     analysisManager->CreateH1("CvsE_TIARA1","TIARA 1 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA2","TIARA 2 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA3","TIARA 3 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA4","TIARA 4 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA5","TIARA 5 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA_EA","Entire TIARA Array - Counts versus Energy", 10000, 0., 10000.);

     ////    PADDLE DETECTORS, Histograms 7-9
     analysisManager->CreateH1("CvsE_PADDLE1","PADDLE 1 - Counts versus Energy", 1000, 0., 100.);
     analysisManager->CreateH1("CvsE_PADDLE2","PADDLE 2 - Counts versus Energy", 1000, 0., 100.);
     analysisManager->CreateH1("CvsE_PADDLE3","PADDLE 3 - Counts versus Energy", 1000, 0., 100.);

     ////    CLOVER DETECTORS, Histograms 10-19
     analysisManager->CreateH1("CvsE_CLOVER1","CLOVER 1 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER2","CLOVER 2 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER3","CLOVER 3 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER4","CLOVER 4 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER5","CLOVER 5 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER6","CLOVER 6 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER7","CLOVER 7 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER8","CLOVER 8 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER9","CLOVER 9 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER_EA","Entire CLOVER Array - Counts versus Energy", 3000, 0., 3000.);

     // Creating 2D histograms

     ////    PADDLE DETECTORS, Histograms 1-6
     analysisManager->CreateH2("PvsE_PADDLE1","PADDLE 1 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("PvsE_PADDLE2","PADDLE 2 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("PvsE_PADDLE3","PADDLE 3 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("EvsTOF_PADDLE1","PADDLE 1 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     analysisManager->CreateH2("EvsTOF_PADDLE2","PADDLE 2 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     analysisManager->CreateH2("EvsTOF_PADDLE3","PADDLE 3 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     */

    ////////////////////////////////////////////////////
    //                  DataTreeSim
    ////////////////////////////////////////////////////

    // Creating ntuple
    analysisManager->CreateNtuple("DataTreeSim", "K600 Spectrometer - Coincident Events");

    /*
    ////    VDC Detectors
    analysisManager->CreateNtupleDColumn(0, "VDC1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "VDC1_Y");
    analysisManager->CreateNtupleDColumn(0, "VDC1_ThetaFP");
    analysisManager->CreateNtupleDColumn(0, "VDC1_ThetaSCAT");

    analysisManager->CreateNtupleDColumn(0, "VDC2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "VDC2_Y");
    analysisManager->CreateNtupleDColumn(0, "VDC2_ThetaFP");
    analysisManager->CreateNtupleDColumn(0, "VDC2_ThetaSCAT");

    ////    "True points of traversal"
    ////    VDC1
    analysisManager->CreateNtupleDColumn(0, "X1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "X1_Ypos");
    analysisManager->CreateNtupleDColumn(0, "U1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "U1_Ypos");
    ////    VDC2
    analysisManager->CreateNtupleDColumn(0, "X2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "X2_Ypos");
    analysisManager->CreateNtupleDColumn(0, "U2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "U2_Ypos");
    */

    ////    TIARA Detectors
    analysisManager->CreateNtupleIColumn(0, "TIARANo");
    analysisManager->CreateNtupleIColumn(0, "TIARA_RowNo");
    analysisManager->CreateNtupleIColumn(0, "TIARA_SectorNo");

    analysisManager->CreateNtupleDColumn(0, "TIARAE");
    analysisManager->CreateNtupleDColumn(0, "Theta");
    analysisManager->CreateNtupleDColumn(0, "Phi");

    //analysisManager->CreateNtupleDColumn("TIARANo[2]");
    //analysisManager->CreateNtupleDColumn("TIARA_RowNo[2]");
    //analysisManager->CreateNtupleDColumn("TIARA_SectorNo[2]");
    //analysisManager->CreateNtupleDColumn(0, "TIARA_t[1]");

    /*
     ////    PADDLE Detectors
     analysisManager->CreateNtupleDColumn(0, "pad1_E");
     analysisManager->CreateNtupleDColumn(0, "pad1_tof");
     analysisManager->CreateNtupleDColumn(0, "pad2_E");
     analysisManager->CreateNtupleDColumn(0, "pad2_tof");

     ////    HAGAR Detector
     analysisManager->CreateNtupleDColumn("HAGAR_E");
     //analysisManager->CreateNtupleDColumn("HAGAR_t");
     */

    analysisManager->FinishNtuple(0);

    ////////////////////////////////////////////////////////////
    //                  GeometryAnalysisTree
    ////////////////////////////////////////////////////////////

    // Creating ntuple
    analysisManager->CreateNtuple("GeometryAnalysisTree", "K600 Spectrometer - GeometryAnalysis");

    ////    TIARA Detectors
    analysisManager->CreateNtupleIColumn(1, "TIARANo");
    analysisManager->CreateNtupleIColumn(1, "TIARA_RowNo");
    analysisManager->CreateNtupleIColumn(1, "TIARA_SectorNo");
    analysisManager->CreateNtupleDColumn(1, "Theta");
    analysisManager->CreateNtupleDColumn(1, "Phi");

    analysisManager->FinishNtuple(1);

    ////////////////////////////////////////////////////////////
    //                  Input Variable Tree
    ////////////////////////////////////////////////////////////

    // Creating ntuple
    analysisManager->CreateNtuple("InputVariableTree", "K600 Spectrometer - InputVariable");

    ////    Initial Particle Angular Distributions
    analysisManager->CreateNtupleDColumn(2, "ThetaDist");
    analysisManager->CreateNtupleDColumn(2, "PhiDist");

    analysisManager->FinishNtuple(2);

}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

RunAction::~RunAction()
{
    delete G4AnalysisManager::Instance();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void RunAction::BeginOfRunAction(const G4Run* /*run*/)
{
    //inform the runManager to save random number seed
    //G4RunManager::GetRunManager()->SetRandomNumberStore(true);

    // Get analysis manager
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();

    // Open an output file
    //
    G4String fileName = "K600Output";
    analysisManager->OpenFile(fileName);
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void RunAction::EndOfRunAction(const G4Run* /*run*/)
{

    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();

    /*
     // print histogram statistics
     //
     if( analysisManager->GetH1(1) ){
     G4cout << "\n ----> print histograms statistic ";
     if(isMaster) {
     G4cout << "for the entire run \n" << G4endl;
     }
     else {
     G4cout << "for the local thread \n" << G4endl;
     }

     G4cout << " EAbs : mean = "
     << G4BestUnit(analysisManager->GetH1(1)->mean(), "Energy")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(1)->rms(),  "Energy") << G4endl;

     G4cout << " EGap : mean = "
     << G4BestUnit(analysisManager->GetH1(2)->mean(), "Energy")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(2)->rms(),  "Energy") << G4endl;

     G4cout << " LAbs : mean = "
     << G4BestUnit(analysisManager->GetH1(3)->mean(), "Length")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(3)->rms(),  "Length") << G4endl;

     G4cout << " LGap : mean = "
     << G4BestUnit(analysisManager->GetH1(4)->mean(), "Length")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(4)->rms(),  "Length") << G4endl;

     }
     */

    // save histograms & ntuple
    //
    analysisManager->Write();
    analysisManager->CloseFile();

}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
<commit_msg>Modified Ntuple for the LEPS simulation<commit_after>//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
//      ----------------------------------------------------------------
//                      K600 Spectrometer (iThemba Labs)
//      ----------------------------------------------------------------
//
//      Github repository: https://www.github.com/KevinCWLi/K600
//
//      Main Author:    K.C.W. Li
//
//      email: likevincw@gmail.com
//

#include "RunAction.hh"
#include "Analysis.hh"

#include "G4Run.hh"
#include "G4RunManager.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

RunAction::RunAction()
: G4UserRunAction()
{
    // set printing event number per each event
    G4RunManager::GetRunManager()->SetPrintProgress(1);

    // Create analysis manager
    // The choice of analysis technology is done via selectin of a namespace
    // in Analysis.hh
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    G4cout << "Using " << analysisManager->GetType() << G4endl;

    // Create directories
    //analysisManager->SetHistoDirectoryName("histograms");
    //analysisManager->SetNtupleDirectoryName("ntuple");
    analysisManager->SetVerboseLevel(1);
    //analysisManager->SetFirstHistoId(1);

    // Book histograms, ntuple
    //

    // Creating 1D histograms
    /*
     ////    TIARA DETECTORS, Histograms 1-6
     analysisManager->CreateH1("CvsE_TIARA1","TIARA 1 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA2","TIARA 2 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA3","TIARA 3 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA4","TIARA 4 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA5","TIARA 5 - Counts versus Energy", 10000, 0., 10000.);
     analysisManager->CreateH1("CvsE_TIARA_EA","Entire TIARA Array - Counts versus Energy", 10000, 0., 10000.);

     ////    PADDLE DETECTORS, Histograms 7-9
     analysisManager->CreateH1("CvsE_PADDLE1","PADDLE 1 - Counts versus Energy", 1000, 0., 100.);
     analysisManager->CreateH1("CvsE_PADDLE2","PADDLE 2 - Counts versus Energy", 1000, 0., 100.);
     analysisManager->CreateH1("CvsE_PADDLE3","PADDLE 3 - Counts versus Energy", 1000, 0., 100.);

     ////    CLOVER DETECTORS, Histograms 10-19
     analysisManager->CreateH1("CvsE_CLOVER1","CLOVER 1 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER2","CLOVER 2 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER3","CLOVER 3 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER4","CLOVER 4 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER5","CLOVER 5 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER6","CLOVER 6 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER7","CLOVER 7 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER8","CLOVER 8 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER9","CLOVER 9 - Counts versus Energy", 3000, 0., 3000.);
     analysisManager->CreateH1("CvsE_CLOVER_EA","Entire CLOVER Array - Counts versus Energy", 3000, 0., 3000.);

     // Creating 2D histograms

     ////    PADDLE DETECTORS, Histograms 1-6
     analysisManager->CreateH2("PvsE_PADDLE1","PADDLE 1 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("PvsE_PADDLE2","PADDLE 2 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("PvsE_PADDLE3","PADDLE 3 - Position vs. Energy", 1400, -700., 700., 3, -3*(102/2), 3*(102/2));
     analysisManager->CreateH2("EvsTOF_PADDLE1","PADDLE 1 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     analysisManager->CreateH2("EvsTOF_PADDLE2","PADDLE 2 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     analysisManager->CreateH2("EvsTOF_PADDLE3","PADDLE 3 - Energy vs. Time of Flight", 300, 0., 500.*0.3, 40, 0., 40.);
     */

    ////////////////////////////////////////////////////
    //                  DataTreeSim
    ////////////////////////////////////////////////////

    // Creating ntuple
    analysisManager->CreateNtuple("DataTreeSim", "K600 Spectrometer - Coincident Events");

    /*
    ////    VDC Detectors
    analysisManager->CreateNtupleDColumn(0, "VDC1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "VDC1_Y");
    analysisManager->CreateNtupleDColumn(0, "VDC1_ThetaFP");
    analysisManager->CreateNtupleDColumn(0, "VDC1_ThetaSCAT");

    analysisManager->CreateNtupleDColumn(0, "VDC2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "VDC2_Y");
    analysisManager->CreateNtupleDColumn(0, "VDC2_ThetaFP");
    analysisManager->CreateNtupleDColumn(0, "VDC2_ThetaSCAT");

    ////    "True points of traversal"
    ////    VDC1
    analysisManager->CreateNtupleDColumn(0, "X1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "X1_Ypos");
    analysisManager->CreateNtupleDColumn(0, "U1_Xpos");
    analysisManager->CreateNtupleDColumn(0, "U1_Ypos");
    ////    VDC2
    analysisManager->CreateNtupleDColumn(0, "X2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "X2_Ypos");
    analysisManager->CreateNtupleDColumn(0, "U2_Xpos");
    analysisManager->CreateNtupleDColumn(0, "U2_Ypos");
    */

    ////    LEPS Detectors
    analysisManager->CreateNtupleIColumn("LEPS1_trig");
    analysisManager->CreateNtupleIColumn("LEPS2_trig");

    /*
    analysisManager->CreateNtupleIColumn(0, "LEPS3_trig");
    analysisManager->CreateNtupleIColumn(0, "LEPS4_trig");
    analysisManager->CreateNtupleIColumn(0, "LEPS5_trig");
    analysisManager->CreateNtupleIColumn(0, "LEPS6_trig");
    */

    /*
    analysisManager->CreateNtupleIColumn(0, "LEPS1_CrystalNo");
    analysisManager->CreateNtupleIColumn(0, "LEPS2_CrystalNo");
    analysisManager->CreateNtupleIColumn(0, "LEPS3_CrystalNo");
    analysisManager->CreateNtupleIColumn(0, "LEPS4_CrystalNo");
    analysisManager->CreateNtupleIColumn(0, "LEPS5_CrystalNo");
    analysisManager->CreateNtupleIColumn(0, "LEPS6_CrystalNo");
    */

    analysisManager->CreateNtupleDColumn("LEPS1_Energy");
    analysisManager->CreateNtupleDColumn("LEPS2_Energy");
    //analysisManager->CreateNtupleDColumn(0, "LEPS3_Energy");

    /*
    analysisManager->CreateNtupleDColumn(0, "LEPS3_Energy");
    analysisManager->CreateNtupleDColumn(0, "LEPS4_Energy");
    analysisManager->CreateNtupleDColumn(0, "LEPS5_Energy");
    analysisManager->CreateNtupleDColumn(0, "LEPS6_Energy");
    */

    ////    TIARA Detectors
    //analysisManager->CreateNtupleIColumn(0, "TIARANo");
    //analysisManager->CreateNtupleIColumn(0, "TIARA_RowNo");
    //analysisManager->CreateNtupleIColumn(0, "TIARA_SectorNo");

    //analysisManager->CreateNtupleDColumn(0, "TIARAE");
    //analysisManager->CreateNtupleDColumn(0, "Theta");
    //analysisManager->CreateNtupleDColumn(0, "Phi");

    //analysisManager->CreateNtupleDColumn("TIARANo[2]");
    //analysisManager->CreateNtupleDColumn("TIARA_RowNo[2]");
    //analysisManager->CreateNtupleDColumn("TIARA_SectorNo[2]");
    //analysisManager->CreateNtupleDColumn(0, "TIARA_t[1]");

    /*
     ////    PADDLE Detectors
     analysisManager->CreateNtupleDColumn(0, "pad1_E");
     analysisManager->CreateNtupleDColumn(0, "pad1_tof");
     analysisManager->CreateNtupleDColumn(0, "pad2_E");
     analysisManager->CreateNtupleDColumn(0, "pad2_tof");

     ////    HAGAR Detector
     analysisManager->CreateNtupleDColumn("HAGAR_E");
     //analysisManager->CreateNtupleDColumn("HAGAR_t");
     */

    analysisManager->FinishNtuple(0);

    ////////////////////////////////////////////////////////////
    //                  GeometryAnalysisTree
    ////////////////////////////////////////////////////////////

    // Creating ntuple

    analysisManager->CreateNtuple("GeometryAnalysisTree", "K600 Spectrometer - GeometryAnalysis");

    ////    TIARA Detectors
    analysisManager->CreateNtupleIColumn(1, "TIARANo");
    analysisManager->CreateNtupleIColumn(1, "TIARA_RowNo");
    analysisManager->CreateNtupleIColumn(1, "TIARA_SectorNo");
    analysisManager->CreateNtupleDColumn(1, "Theta");
    analysisManager->CreateNtupleDColumn(1, "Phi");

    analysisManager->FinishNtuple(1);

    ////////////////////////////////////////////////////////////
    //                  Input Variable Tree
    ////////////////////////////////////////////////////////////

    // Creating ntuple
    analysisManager->CreateNtuple("InputVariableTree", "K600 Spectrometer - InputVariable");

    ////    Initial Particle Angular Distributions
    analysisManager->CreateNtupleDColumn(2, "ThetaDist");
    analysisManager->CreateNtupleDColumn(2, "PhiDist");

    analysisManager->FinishNtuple(2);

}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

RunAction::~RunAction()
{
    delete G4AnalysisManager::Instance();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void RunAction::BeginOfRunAction(const G4Run* /*run*/)
{
    //inform the runManager to save random number seed
    //G4RunManager::GetRunManager()->SetRandomNumberStore(true);

    // Get analysis manager
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();

    // Open an output file
    //
    G4String fileName = "K600Output";
    analysisManager->OpenFile(fileName);
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void RunAction::EndOfRunAction(const G4Run* /*run*/)
{

    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();

    /*
     // print histogram statistics
     //
     if( analysisManager->GetH1(1) ){
     G4cout << "\n ----> print histograms statistic ";
     if(isMaster) {
     G4cout << "for the entire run \n" << G4endl;
     }
     else {
     G4cout << "for the local thread \n" << G4endl;
     }

     G4cout << " EAbs : mean = "
     << G4BestUnit(analysisManager->GetH1(1)->mean(), "Energy")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(1)->rms(),  "Energy") << G4endl;

     G4cout << " EGap : mean = "
     << G4BestUnit(analysisManager->GetH1(2)->mean(), "Energy")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(2)->rms(),  "Energy") << G4endl;

     G4cout << " LAbs : mean = "
     << G4BestUnit(analysisManager->GetH1(3)->mean(), "Length")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(3)->rms(),  "Length") << G4endl;

     G4cout << " LGap : mean = "
     << G4BestUnit(analysisManager->GetH1(4)->mean(), "Length")
     << " rms = "
     << G4BestUnit(analysisManager->GetH1(4)->rms(),  "Length") << G4endl;

     }
     */

    // save histograms & ntuple
    //
    analysisManager->Write();
    analysisManager->CloseFile();

}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
<|endoftext|>


<commit_before>// ScriptOp.cpp
/*
 * Copyright (c) 2010, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include <TopoDS_Edge.hxx>
#include "ScriptOp.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/HeeksObj.h"
#include "tinyxml/tinyxml.h"
#include "PythonStuff.h"
#include "MachineState.h"

#include <sstream>
#include <iomanip>

#include <BRepAdaptor_Curve.hxx>
#include <gp_Circ.hxx>
#include <BRepTools.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh.hxx>
#include <Poly_Polygon3D.hxx>

CScriptOp::CScriptOp( const CScriptOp & rhs ) : COp(rhs)
{
	m_str = rhs.m_str;
}

CScriptOp & CScriptOp::operator= ( const CScriptOp & rhs )
{
	if (this != &rhs)
	{
		COp::operator=( rhs );
		m_str = rhs.m_str;
	}

	return(*this);
}

const wxBitmap &CScriptOp::GetIcon()
{
	if(!m_active)return GetInactiveIcon();
	static wxBitmap* icon = NULL;
	if(icon == NULL)icon = new wxBitmap(wxImage(theApp.GetResFolder() + _T("/icons/scriptop.png")));
	return *icon;
}

/* static */ Python CScriptOp::OpenCamLibDefinition(TopoDS_Edge edge)
{
    Python python;

	BRepAdaptor_Curve curve(edge);
	switch (curve.GetType())
	{
		case GeomAbs_Line:
		{
			CNCPoint PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			CNCPoint PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);

			python << _T("ocl.Line(ocl.Point(") << PS.X(false) << _T(",") << PS.Y(false) << _T(",") << PS.Z(false) << _T("), ")
					<< _T("ocl.Point(") << PE.X(false) << _T(",") << PE.Y(false) << _T(",") << PE.Z(false) << _T("))");
		}
		break;

		case GeomAbs_Circle:
		{
			CNCPoint PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			CNCPoint PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);
			gp_Circ circle = curve.Circle();

            // Arc towards PE
            CNCPoint point(PE);
            CNCPoint centre( circle.Location() );
            bool l_bClockwise = (circle.Axis().Direction().Z() <= 0);

			python << _T("ocl.Arc(")
					<< _T("ocl.Point(") << PS.X(false) << _T(",") << PS.Y(false) << _T(",") << PS.Z(false) << _T("),") // Start
					<< _T("ocl.Point(") << PE.X(false) << _T(",") << PE.Y(false) << _T(",") << PE.Z(false) << _T("),") // End
					<< _T("ocl.Point(") << centre.X(false) << _T(",") << centre.Y(false) << _T(",") << centre.Z(false) << _T("),") // Centre
					<< (l_bClockwise?_T("True"):_T("False")) << _T(")"); // Direction
			break;
		}

		default:
		{
			// make lots of small lines
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);

			BRepTools::Clean(edge);
			double max_deviation_for_spline_to_arc = 0.001;
			BRepMesh::Mesh(edge, max_deviation_for_spline_to_arc);

			TopLoc_Location L;
			Handle(Poly_Polygon3D) Polyg = BRep_Tool::Polygon3D(edge, L);
			if (!Polyg.IsNull()) {
				const TColgp_Array1OfPnt& Points = Polyg->Nodes();
				Standard_Integer po;
				int i = 0;
				std::list<CNCPoint> interpolated_points;
				python << _T("ocl.Path(");
				CNCPoint previous;
				for (po = Points.Lower(); po <= Points.Upper(); po++, i++) {
					CNCPoint p = (Points.Value(po)).Transformed(L);
					interpolated_points.push_back(p);

					if (interpolated_points.size() == 1)
					{
						previous = p;
					}
					else
					{
						python << _T("ocl.Line(")
								<< _T("ocl.Point(") << previous.X(false) << _T(",") << previous.Y(false) << _T(",") << previous.Z(false) << _T(")")
								<< _T("ocl.Point(") << p.X(false) << _T(",") << p.Y(false) << _T(",") << p.Z(false) << _T(")")
								<< _T(")");
					}
				} // End for
				python << _T(")");	// End ocl.Path() definition
			} // End if - then
		}
		break;
	} // End switch

	return(python);
}

/**
	This method sorts and traverses the list of TopoDS_Edge objects arranging them into
	vectors of connected edges.  It also ensures that each edge's definition is swapped
	around so that moving from the edge's FirstParameter() to its LastParameter() correctly
	sets up the tool's location to start machining the next edge in the connected series.

	The resultant array of connected edge sequences should allow all edges in each sequence
	to be machined 'at depth'.
 */
/* static */ std::vector< std::vector<TopoDS_Edge> > CScriptOp::AggregateConnectedEdges( std::vector<TopoDS_Edge> & edges )
{
	std::vector<TopoDS_Edge> all_edges;
	std::copy( edges.begin(), edges.end(), std::inserter( all_edges, all_edges.begin() ));

	typedef std::vector<TopoDS_Edge> Series_t;
	typedef std::vector< Series_t > Chains_t;
	Chains_t chains;

/*
	while (all_edges.size() > 0)
	{
        Series_t used;
        for (Series_t::iterator itEdge = all_edges.begin(); itEdge != all_edges.end(); itEdge++)
        {
            if (used.size() == 0)
            {
                used.push_back(*itEdge);
            }
            else
            {
                // See if this edge connects with either end of the 'used' series.
                if (GetStart(
            }
        } // End for
	} // End while
*/

	return(chains);

} // End AggregateConnectedEdges() method

/**
    This method converts the list of objects into a set of nested classes that
    describe the geometry.  These classes will include definitions of these objects
    in terms of lines, arcs and points.  Any BSpline (or other) objects that are
 */
/* static */ Python CScriptOp::OpenCamLibDefinition(std::list<HeeksObj *> objects, Python object_title )
{
    Python python;

	if (objects.size() > 0)
	{
		python << _T("class ") << object_title << _T(":\n");

		python << _T("\tsketches = []\n");
		python << _T("\tpoints = []\n");
	}

    for (std::list<HeeksObj *>::iterator itObject = objects.begin(); itObject != objects.end(); itObject++)
    {
		std::vector<TopoDS_Edge> edges;
		switch ((*itObject)->GetType())
		{
		case PointType:
			double p[3];
			memset( p, 0, sizeof(p) );
			heeksCAD->VertexGetPoint( *itObject, p );
			python << _T("\tpoints.append(ocl.Point(") << p[0] << _T(",") << p[1] << _T(",") << p[2] << _T("))\n");
			break;

		case SketchType:
			if (! heeksCAD->ConvertSketchToEdges( *itObject, edges ))
			{
				Python empty;
				return(empty);
			}
			else
			{
				// The edges will already have been sorted.  We need to traverse them in order and separate
				// connected sequences of them.  As we start new connected sequences, we should check to see
				// if they connect back to their beginning and mark them as 'periodic'.
				if (edges.size() > 0)
				{
					python << _T("\tsketch_id_") << (int) (*itObject)->m_id << _T(" = ocl.Path()\n");
				}

				for (std::vector<TopoDS_Edge>::size_type offset = 0; offset < edges.size(); offset++)
				{
					python << _T("\tsketch_id_") << (int) (*itObject)->m_id << _T(".append(") << OpenCamLibDefinition(edges[offset]) << _T(")\n");
				}

				if (edges.size() > 0)
				{
					python << _T("\tsketches.append(")
							<< _T("sketch_id_") << (int) (*itObject)->m_id << _T(")\n");
				}
			} // End if - else
			break;
		} // End switch
    } // End for

    return(python);

}

Python CScriptOp::AppendTextToProgram(CMachineState *pMachineState)
{
	Python python;

	std::list<HeeksObj *> children;
	for (HeeksObj *child = GetFirstChild(); child != NULL; child = GetNextChild())
	{
	    children.push_back(child);
	}

	Python object_title;
	object_title << _T("script_op_id_") << (int) this->m_id;

	python << OpenCamLibDefinition(children, object_title);
	python << _T("\n");
	python << _T("graphics = ") << object_title << _T("()\n\n");

	python << m_str.c_str();

	if(python.Last() != _T('\n'))python.Append(_T('\n'));

	return python;
} // End AppendTextToProgram() method

ObjectCanvas* CScriptOp::GetDialog(wxWindow* parent)
{
	static TextCanvas* object_canvas = NULL;
	if(object_canvas == NULL)object_canvas = new TextCanvas(parent, &m_str);
	else
	{
		object_canvas->m_str = &m_str;
		object_canvas->SetWithObject(this);
	}
	return object_canvas;
}

HeeksObj *CScriptOp::MakeACopy(void)const
{
	return new CScriptOp(*this);
}

void CScriptOp::CopyFrom(const HeeksObj* object)
{
	if (object->GetType() == GetType())
	{
		operator=(*((CScriptOp*)object));
	}
}

bool CScriptOp::CanAddTo(HeeksObj* owner)
{
	return ((owner != NULL) && (owner->GetType() == OperationsType));
}

void CScriptOp::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element = new TiXmlElement( "ScriptOp" );
	root->LinkEndChild( element );
	element->SetAttribute("script", Ttc(m_str.c_str()));

	COp::WriteBaseXML(element);
}

// static member function
HeeksObj* CScriptOp::ReadFromXMLElement(TiXmlElement* element)
{
	CScriptOp* new_object = new CScriptOp;

	new_object->m_str = wxString(Ctt(element->Attribute("script")));

	// read common parameters
	new_object->ReadBaseXML(element);

	return new_object;
}

bool CScriptOp::operator==( const CScriptOp & rhs ) const
{
	if (m_str != rhs.m_str) return(false);

	return(COp::operator==(rhs));
}
<commit_msg>Fixed bug when the ScriptOp does not contain children<commit_after>// ScriptOp.cpp
/*
 * Copyright (c) 2010, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include <TopoDS_Edge.hxx>
#include "ScriptOp.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/HeeksObj.h"
#include "tinyxml/tinyxml.h"
#include "PythonStuff.h"
#include "MachineState.h"

#include <sstream>
#include <iomanip>

#include <BRepAdaptor_Curve.hxx>
#include <gp_Circ.hxx>
#include <BRepTools.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh.hxx>
#include <Poly_Polygon3D.hxx>

CScriptOp::CScriptOp( const CScriptOp & rhs ) : COp(rhs)
{
	m_str = rhs.m_str;
}

CScriptOp & CScriptOp::operator= ( const CScriptOp & rhs )
{
	if (this != &rhs)
	{
		COp::operator=( rhs );
		m_str = rhs.m_str;
	}

	return(*this);
}

const wxBitmap &CScriptOp::GetIcon()
{
	if(!m_active)return GetInactiveIcon();
	static wxBitmap* icon = NULL;
	if(icon == NULL)icon = new wxBitmap(wxImage(theApp.GetResFolder() + _T("/icons/scriptop.png")));
	return *icon;
}

/* static */ Python CScriptOp::OpenCamLibDefinition(TopoDS_Edge edge)
{
    Python python;

	BRepAdaptor_Curve curve(edge);
	switch (curve.GetType())
	{
		case GeomAbs_Line:
		{
			CNCPoint PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			CNCPoint PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);

			python << _T("ocl.Line(ocl.Point(") << PS.X(false) << _T(",") << PS.Y(false) << _T(",") << PS.Z(false) << _T("), ")
					<< _T("ocl.Point(") << PE.X(false) << _T(",") << PE.Y(false) << _T(",") << PE.Z(false) << _T("))");
		}
		break;

		case GeomAbs_Circle:
		{
			CNCPoint PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			CNCPoint PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);
			gp_Circ circle = curve.Circle();

            // Arc towards PE
            CNCPoint point(PE);
            CNCPoint centre( circle.Location() );
            bool l_bClockwise = (circle.Axis().Direction().Z() <= 0);

			python << _T("ocl.Arc(")
					<< _T("ocl.Point(") << PS.X(false) << _T(",") << PS.Y(false) << _T(",") << PS.Z(false) << _T("),") // Start
					<< _T("ocl.Point(") << PE.X(false) << _T(",") << PE.Y(false) << _T(",") << PE.Z(false) << _T("),") // End
					<< _T("ocl.Point(") << centre.X(false) << _T(",") << centre.Y(false) << _T(",") << centre.Z(false) << _T("),") // Centre
					<< (l_bClockwise?_T("True"):_T("False")) << _T(")"); // Direction
			break;
		}

		default:
		{
			// make lots of small lines
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(curve.FirstParameter(), PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(curve.LastParameter(), PE, VE);

			BRepTools::Clean(edge);
			double max_deviation_for_spline_to_arc = 0.001;
			BRepMesh::Mesh(edge, max_deviation_for_spline_to_arc);

			TopLoc_Location L;
			Handle(Poly_Polygon3D) Polyg = BRep_Tool::Polygon3D(edge, L);
			if (!Polyg.IsNull()) {
				const TColgp_Array1OfPnt& Points = Polyg->Nodes();
				Standard_Integer po;
				int i = 0;
				std::list<CNCPoint> interpolated_points;
				python << _T("ocl.Path(");
				CNCPoint previous;
				for (po = Points.Lower(); po <= Points.Upper(); po++, i++) {
					CNCPoint p = (Points.Value(po)).Transformed(L);
					interpolated_points.push_back(p);

					if (interpolated_points.size() == 1)
					{
						previous = p;
					}
					else
					{
						python << _T("ocl.Line(")
								<< _T("ocl.Point(") << previous.X(false) << _T(",") << previous.Y(false) << _T(",") << previous.Z(false) << _T(")")
								<< _T("ocl.Point(") << p.X(false) << _T(",") << p.Y(false) << _T(",") << p.Z(false) << _T(")")
								<< _T(")");
					}
				} // End for
				python << _T(")");	// End ocl.Path() definition
			} // End if - then
		}
		break;
	} // End switch

	return(python);
}

/**
	This method sorts and traverses the list of TopoDS_Edge objects arranging them into
	vectors of connected edges.  It also ensures that each edge's definition is swapped
	around so that moving from the edge's FirstParameter() to its LastParameter() correctly
	sets up the tool's location to start machining the next edge in the connected series.

	The resultant array of connected edge sequences should allow all edges in each sequence
	to be machined 'at depth'.
 */
/* static */ std::vector< std::vector<TopoDS_Edge> > CScriptOp::AggregateConnectedEdges( std::vector<TopoDS_Edge> & edges )
{
	std::vector<TopoDS_Edge> all_edges;
	std::copy( edges.begin(), edges.end(), std::inserter( all_edges, all_edges.begin() ));

	typedef std::vector<TopoDS_Edge> Series_t;
	typedef std::vector< Series_t > Chains_t;
	Chains_t chains;

/*
	while (all_edges.size() > 0)
	{
        Series_t used;
        for (Series_t::iterator itEdge = all_edges.begin(); itEdge != all_edges.end(); itEdge++)
        {
            if (used.size() == 0)
            {
                used.push_back(*itEdge);
            }
            else
            {
                // See if this edge connects with either end of the 'used' series.
                if (GetStart(
            }
        } // End for
	} // End while
*/

	return(chains);

} // End AggregateConnectedEdges() method

/**
    This method converts the list of objects into a set of nested classes that
    describe the geometry.  These classes will include definitions of these objects
    in terms of lines, arcs and points.  Any BSpline (or other) objects that are
 */
/* static */ Python CScriptOp::OpenCamLibDefinition(std::list<HeeksObj *> objects, Python object_title )
{
    Python python;

	if (objects.size() > 0)
	{
		python << _T("class ") << object_title << _T(":\n");

		python << _T("\tsketches = []\n");
		python << _T("\tpoints = []\n");
	}

    for (std::list<HeeksObj *>::iterator itObject = objects.begin(); itObject != objects.end(); itObject++)
    {
		std::vector<TopoDS_Edge> edges;
		switch ((*itObject)->GetType())
		{
		case PointType:
			double p[3];
			memset( p, 0, sizeof(p) );
			heeksCAD->VertexGetPoint( *itObject, p );
			python << _T("\tpoints.append(ocl.Point(") << p[0] << _T(",") << p[1] << _T(",") << p[2] << _T("))\n");
			break;

		case SketchType:
			if (! heeksCAD->ConvertSketchToEdges( *itObject, edges ))
			{
				Python empty;
				return(empty);
			}
			else
			{
				// The edges will already have been sorted.  We need to traverse them in order and separate
				// connected sequences of them.  As we start new connected sequences, we should check to see
				// if they connect back to their beginning and mark them as 'periodic'.
				if (edges.size() > 0)
				{
					python << _T("\tsketch_id_") << (int) (*itObject)->m_id << _T(" = ocl.Path()\n");
				}

				for (std::vector<TopoDS_Edge>::size_type offset = 0; offset < edges.size(); offset++)
				{
					python << _T("\tsketch_id_") << (int) (*itObject)->m_id << _T(".append(") << OpenCamLibDefinition(edges[offset]) << _T(")\n");
				}

				if (edges.size() > 0)
				{
					python << _T("\tsketches.append(")
							<< _T("sketch_id_") << (int) (*itObject)->m_id << _T(")\n");
				}
			} // End if - else
			break;
		} // End switch
    } // End for

    return(python);

}

Python CScriptOp::AppendTextToProgram(CMachineState *pMachineState)
{
	Python python;

	std::list<HeeksObj *> children;
	for (HeeksObj *child = GetFirstChild(); child != NULL; child = GetNextChild())
	{
	    children.push_back(child);
	}

    if (children.size() > 0)
    {
        Python object_title;
        object_title << _T("script_op_id_") << (int) this->m_id;

        python << OpenCamLibDefinition(children, object_title);
        python << _T("\n");
        python << _T("graphics = ") << object_title << _T("()\n\n");
    }

	python << m_str.c_str();

	if(python.Last() != _T('\n'))python.Append(_T('\n'));

	return python;
} // End AppendTextToProgram() method

ObjectCanvas* CScriptOp::GetDialog(wxWindow* parent)
{
	static TextCanvas* object_canvas = NULL;
	if(object_canvas == NULL)object_canvas = new TextCanvas(parent, &m_str);
	else
	{
		object_canvas->m_str = &m_str;
		object_canvas->SetWithObject(this);
	}
	return object_canvas;
}

HeeksObj *CScriptOp::MakeACopy(void)const
{
	return new CScriptOp(*this);
}

void CScriptOp::CopyFrom(const HeeksObj* object)
{
	if (object->GetType() == GetType())
	{
		operator=(*((CScriptOp*)object));
	}
}

bool CScriptOp::CanAddTo(HeeksObj* owner)
{
	return ((owner != NULL) && (owner->GetType() == OperationsType));
}

void CScriptOp::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element = new TiXmlElement( "ScriptOp" );
	root->LinkEndChild( element );
	element->SetAttribute("script", Ttc(m_str.c_str()));

	COp::WriteBaseXML(element);
}

// static member function
HeeksObj* CScriptOp::ReadFromXMLElement(TiXmlElement* element)
{
	CScriptOp* new_object = new CScriptOp;

	new_object->m_str = wxString(Ctt(element->Attribute("script")));

	// read common parameters
	new_object->ReadBaseXML(element);

	return new_object;
}

bool CScriptOp::operator==( const CScriptOp & rhs ) const
{
	if (m_str != rhs.m_str) return(false);

	return(COp::operator==(rhs));
}
<|endoftext|>


<commit_before>// Onut
#include <onut/Files.h>
#include <onut/Settings.h>
#include <onut/Window.h>

// STL
#include <fstream>

OSettingsRef oSettings = OMake<OSettings>();

namespace onut
{
    Settings::Settings()
    {
        m_isDirty = false;
        m_isRunning = false;
    }

    Settings::~Settings()
    {
    }

    void Settings::shutdownUserSettings()
    {
        if (m_isRunning)
        {
            m_isRunning = false;
            m_conditionVariable.notify_all();
            m_savingThread.join();
        }
    }

    void Settings::initUserSettings()
    {
        m_isRunning = true;

        // Load settings
        std::ifstream in(onut::getSavePath() + "usersettings.cfg");
        if (!in.fail())
        {
            std::string line;
            std::getline(in, line);
            std::string key;
            while (!in.eof())
            {
                if (!key.empty())
                {
                    m_userSettings[key] = line;
                    key.clear();
                }
                else
                {
                    key = line;
                }
                getline(in, line);
            }
            in.close();
        }

        // Start saving thread
        m_savingThread = std::thread([this]
        {
            std::unique_lock<std::mutex> locker(m_mutex);
            while (m_isRunning)
            {
                m_conditionVariable.wait(locker);
                if (!m_isDirty) continue;
                m_isDirty = false;

                // Wait a little bit more, maybe the user is doing a bunch of transactions at once
                locker.unlock();
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
                locker.lock();

                // Copy the map so there is not conflics
                auto userSettings = m_userSettings;
                locker.unlock();
                std::ofstream fic(onut::getSavePath() + "usersettings.cfg");
                if (!fic.fail())
                {
                    for (auto &kv : userSettings)
                    {
                        fic << kv.first << std::endl;
                        fic << kv.second << std::endl;
                    }
                    fic.close();
                }
                locker.lock();
            }
        });
    }

    void Settings::setResolution(const Resolution& resolution)
    {
        m_resolution = resolution;
    }

    void Settings::setRetroResolution(const Resolution& retroResolution)
    {
        m_retroResolution = retroResolution;
    }

    void Settings::setIsRetroMode(bool isRetroMode)
    {
        m_isRetroMode = isRetroMode;
    }

    void Settings::setGameName(const std::string& gameName)
    {
        m_gameName = gameName;
    }

    void Settings::setIsResizableWindow(bool isResizableWindow)
    {
        m_isResizableWindow = isResizableWindow;
    }

    void Settings::setBorderlessFullscreen(bool isBorderLessFullscreen)
    {
        m_isBorderLessFullscreen = isBorderLessFullscreen;
        if (oWindow)
        {
            oWindow->setFullscreen(m_isBorderLessFullscreen);
        }
    }

    void Settings::setIsFixedStep(bool isFixedStep)
    {
        m_isFixedStep = isFixedStep;
    }

    void Settings::setIsEditorMode(bool isEditorMode)
    {
        m_isFixedStep = isEditorMode ? true : m_isFixedStep;
        m_isEditorMode = isEditorMode;
    }

    void Settings::setStartMaximized(bool startMaximized)
    {
        m_startMaximized = startMaximized;
    }

    void Settings::setAppId(const std::string& appId)
    {
        m_appId = appId;
    }

    void Settings::setAppSecret(const std::string& appSecret)
    {
        m_appSecret = appSecret;
    }

    void Settings::setShowOnScreenLog(bool showOnScreenLog)
    {
        m_showOnScreenLog = showOnScreenLog;
    }

    void Settings::setMatchMakingAddress(const std::string& matchMakingAddress)
    {
        m_matchMakingAddress = matchMakingAddress;
    }

    void Settings::setMatchMakingPort(int matchMakingPort)
    {
        m_matchMakingPort = matchMakingPort;
    }

    void Settings::setShowFPS(bool showFPS)
    {
        m_showFPS = showFPS;
    }

    void Settings::setAutoLoadScripts(bool autoLoadScripts)
    {
        m_autoLoadScripts = autoLoadScripts;
    }

    void Settings::setAntiAliasing(bool antiAliasing)
    {
        m_antiAliasing = antiAliasing;
    }

    void Settings::setUserSettingDefault(const std::string& key, const std::string& value)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it == m_userSettings.end())
        {
            m_userSettings[key] = value;
            m_isDirty = true;
            m_conditionVariable.notify_one();
        }
    }

    void Settings::setUserSetting(const std::string& key, const std::string& value)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it != m_userSettings.end())
        {
            if (it->second == value)
            {
                return; // No change
            }
        }
        m_userSettings[key] = value;
        m_isDirty = true;
        m_conditionVariable.notify_one();
    }

    const std::string& Settings::getUserSetting(const std::string& key)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it == m_userSettings.end())
        {
            static std::string empty = "";
            return empty;
        }
        return it->second;
    }
}
<commit_msg>Fixed crash in settings<commit_after>// Onut
#include <onut/Files.h>
#include <onut/Settings.h>
#include <onut/Window.h>

// STL
#include <fstream>

OSettingsRef oSettings = OMake<OSettings>();

namespace onut
{
    Settings::Settings()
    {
        m_isDirty = false;
        m_isRunning = false;
    }

    Settings::~Settings()
    {
        shutdownUserSettings();
    }

    void Settings::shutdownUserSettings()
    {
        if (m_isRunning)
        {
            m_isRunning = false;
            m_conditionVariable.notify_all();
            m_savingThread.join();
        }
    }

    void Settings::initUserSettings()
    {
        m_isRunning = true;

        // Load settings
        std::ifstream in(onut::getSavePath() + "usersettings.cfg");
        if (!in.fail())
        {
            std::string line;
            std::getline(in, line);
            std::string key;
            while (!in.eof())
            {
                if (!key.empty())
                {
                    m_userSettings[key] = line;
                    key.clear();
                }
                else
                {
                    key = line;
                }
                getline(in, line);
            }
            in.close();
        }

        // Start saving thread
        m_savingThread = std::thread([this]
        {
            std::unique_lock<std::mutex> locker(m_mutex);
            while (m_isRunning)
            {
                m_conditionVariable.wait(locker);
                if (!m_isDirty) continue;
                m_isDirty = false;

                // Wait a little bit more, maybe the user is doing a bunch of transactions at once
                locker.unlock();
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
                locker.lock();

                // Copy the map so there is not conflics
                auto userSettings = m_userSettings;
                locker.unlock();
                std::ofstream fic(onut::getSavePath() + "usersettings.cfg");
                if (!fic.fail())
                {
                    for (auto &kv : userSettings)
                    {
                        fic << kv.first << std::endl;
                        fic << kv.second << std::endl;
                    }
                    fic.close();
                }
                locker.lock();
            }
        });
    }

    void Settings::setResolution(const Resolution& resolution)
    {
        m_resolution = resolution;
    }

    void Settings::setRetroResolution(const Resolution& retroResolution)
    {
        m_retroResolution = retroResolution;
    }

    void Settings::setIsRetroMode(bool isRetroMode)
    {
        m_isRetroMode = isRetroMode;
    }

    void Settings::setGameName(const std::string& gameName)
    {
        m_gameName = gameName;
    }

    void Settings::setIsResizableWindow(bool isResizableWindow)
    {
        m_isResizableWindow = isResizableWindow;
    }

    void Settings::setBorderlessFullscreen(bool isBorderLessFullscreen)
    {
        m_isBorderLessFullscreen = isBorderLessFullscreen;
        if (oWindow)
        {
            oWindow->setFullscreen(m_isBorderLessFullscreen);
        }
    }

    void Settings::setIsFixedStep(bool isFixedStep)
    {
        m_isFixedStep = isFixedStep;
    }

    void Settings::setIsEditorMode(bool isEditorMode)
    {
        m_isFixedStep = isEditorMode ? true : m_isFixedStep;
        m_isEditorMode = isEditorMode;
    }

    void Settings::setStartMaximized(bool startMaximized)
    {
        m_startMaximized = startMaximized;
    }

    void Settings::setAppId(const std::string& appId)
    {
        m_appId = appId;
    }

    void Settings::setAppSecret(const std::string& appSecret)
    {
        m_appSecret = appSecret;
    }

    void Settings::setShowOnScreenLog(bool showOnScreenLog)
    {
        m_showOnScreenLog = showOnScreenLog;
    }

    void Settings::setMatchMakingAddress(const std::string& matchMakingAddress)
    {
        m_matchMakingAddress = matchMakingAddress;
    }

    void Settings::setMatchMakingPort(int matchMakingPort)
    {
        m_matchMakingPort = matchMakingPort;
    }

    void Settings::setShowFPS(bool showFPS)
    {
        m_showFPS = showFPS;
    }

    void Settings::setAutoLoadScripts(bool autoLoadScripts)
    {
        m_autoLoadScripts = autoLoadScripts;
    }

    void Settings::setAntiAliasing(bool antiAliasing)
    {
        m_antiAliasing = antiAliasing;
    }

    void Settings::setUserSettingDefault(const std::string& key, const std::string& value)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it == m_userSettings.end())
        {
            m_userSettings[key] = value;
            m_isDirty = true;
            m_conditionVariable.notify_one();
        }
    }

    void Settings::setUserSetting(const std::string& key, const std::string& value)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it != m_userSettings.end())
        {
            if (it->second == value)
            {
                return; // No change
            }
        }
        m_userSettings[key] = value;
        m_isDirty = true;
        m_conditionVariable.notify_one();
    }

    const std::string& Settings::getUserSetting(const std::string& key)
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        auto it = m_userSettings.find(key);
        if (it == m_userSettings.end())
        {
            static std::string empty = "";
            return empty;
        }
        return it->second;
    }
}
<|endoftext|>


<commit_before>#include "maCrawler.h"
#include "maAdapt.h"
#include "maLayer.h"
#include <PCU.h>
#include <apfCavityOp.h>

namespace ma {

void syncLayer(Crawler* c, Crawler::Layer& layer)
{
  Mesh* m = c->adapter->mesh;
  PCU_Comm_Begin();
  for (size_t i = 0; i < layer.size(); ++i) {
    Entity* e = layer[i];
    if (m->isShared(e)) {
      apf::Copies remotes;
      m->getRemotes(e,remotes);
      APF_ITERATE(apf::Copies,remotes,it) {
        PCU_COMM_PACK(it->first,it->second);
        c->send(e, it->first);
      }
    }
  }
  PCU_Comm_Send();
  while (PCU_Comm_Listen()) {
    int from = PCU_Comm_Sender();
    while ( ! PCU_Comm_Unpacked()) {
      Entity* e;
      PCU_COMM_UNPACK(e);
      if (c->recv(e, from))
        layer.push_back(e);
    }
  }
}

static void crawlLayer(Crawler* c, Crawler::Layer& layer)
{
  Crawler::Layer nextLayer;
  for (size_t i = 0; i < layer.size(); ++i) {
    Entity* e = layer[i];
    Entity* e2 = c->crawl(e);
    if (e2)
      nextLayer.push_back(e2);
  }
  layer.swap(nextLayer);
}

void crawlLayers(Crawler* c)
{
  Crawler::Layer layer;
  c->begin(layer);
  while (PCU_Or( ! layer.empty())) {
    crawlLayer(c, layer);
    syncLayer(c, layer);
  }
  c->end();
}

void getDimensionBase(Adapt* a, int d, Crawler::Layer& base)
{
  Mesh* m = a->mesh;
  Iterator* it = m->begin(d);
  Entity* e;
  while ((e = m->iterate(it)))
    if (getFlag(a, e, LAYER_BASE))
      base.push_back(e);
  m->end(it);
}

Entity* getOtherVert(Mesh* m, Entity* v, Predicate& visited)
{
  Upward faces;
  m->getAdjacent(v, 2, faces);
  APF_ITERATE(Upward, faces, it) {
    if (m->getType(*it) != QUAD)
      continue;
    Entity* vs[4];
    m->getDownward(*it, 0, vs);
    int i = apf::findIn(vs, 4, v);
    int j = (i + 1) % 4;
    int k = (i - 1 + 4) % 4;
    if (!visited(vs[j]))
      return vs[j];
    if (!visited(vs[k]))
      return vs[k];
  }
  return 0;
}

Entity* getOtherEdge(Mesh* m, Entity* e, Predicate& visited)
{
  Upward faces;
  m->getAdjacent(e, 2, faces);
  APF_ITERATE(Upward, faces, it) {
    if (m->getType(*it) != QUAD)
      continue;
    Entity* es[4];
    m->getDownward(*it, 1, es);
    int i = apf::findIn(es, 4, e);
    int j = (i + 2) % 4;
    if (!visited(es[j]))
      return es[j];
  }
  return 0;
}

struct Tagger
{
  void init(Mesh* m_, Tag* t_)
  {
    m = m_;
    tag = t_;
  }
  int getNumber(Entity* v)
  {
    int n;
    m->getIntTag(v, tag, &n);
    return n;
  }
  void setNumber(Entity* v, int n)
  {
    m->setIntTag(v, tag, &n);
  }
  bool hasNumber(Entity* v)
  {
    return m->hasTag(v, tag);
  }
  Mesh* m;
  Tag* tag;
};

struct LayerNumberer : public Crawler
{
  LayerNumberer(Adapt* a_):
    Crawler(a_)
  {
    a = a_;
    m = a->mesh;
    tag = m->createIntTag("ma_layer", 1);
    t.init(m, tag);
  }
  void begin(Layer& first)
  {
    getDimensionBase(a, 0, first);
    for (size_t i = 0; i < first.size(); ++i)
      t.setNumber(first[i], 0);
  }
  Entity* crawl(Entity* v)
  {
    HasTag p(m, tag);
    Entity* ov = getOtherVert(m, v, p);
    if (!ov)
      return 0;
    t.setNumber(ov, t.getNumber(v) + 1);
    return ov;
  }
  void send(Entity* v, int to)
  {
    int n = t.getNumber(v);
    PCU_COMM_PACK(to, n);
  }
  bool recv(Entity* v, int)
  {
    int n;
    PCU_COMM_UNPACK(n);
    if (t.hasNumber(v))
      return false;
    t.setNumber(v, n);
    return true;
  }
  Adapt* a;
  Mesh* m;
  Tag* tag;
  Tagger t;
};

static Tag* numberLayer(Adapt* a)
{
  LayerNumberer op(a);
  crawlLayers(&op);
  return op.tag;
}

struct TopFlagger : public apf::CavityOp
{
  TopFlagger(Adapt* a_, Tag* t_):
    apf::CavityOp(a_->mesh)
  {
    a = a_;
    m = a->mesh;
    t.init(m, t_);
  }
  Outcome setEntity(Entity* v_)
  {
    if ((!getFlag(a, v_, LAYER)) ||
        getFlag(a, v_, LAYER_BASE) ||
        getFlag(a, v_, CHECKED))
      return SKIP;
    if (!requestLocality(&v_, 1))
      return REQUEST;
    v = v_;
    return OK;
  }
  bool isTop()
  {
    int n = t.getNumber(v);
    apf::Up es;
    m->getUp(v, es);
    for (int i = 0; i < es.n; ++i) {
      Entity* ov = apf::getEdgeVertOppositeVert(m, es.e[i], v);
      if (!t.hasNumber(ov))
        continue;
      int on = t.getNumber(ov);
      if (on > n)
        return false;
    }
    return true;
  }
  void apply()
  {
    setFlag(a, v, CHECKED);
    if (isTop())
      setFlag(a, v, LAYER_TOP);
  }
  Adapt* a;
  Mesh* m;
  Entity* v;
  Tagger t;
};

void flagLayerTop(Adapt* a)
{
  Tag* layerNumbers = numberLayer(a);
  TopFlagger op(a, layerNumbers);
  op.applyToDimension(0);
  clearFlagFromDimension(a, CHECKED, 0);
  apf::removeTagFromDimension(a->mesh, layerNumbers, 0);
  a->mesh->destroyTag(layerNumbers);
}

}
<commit_msg>fixed bug in layer top flagger<commit_after>#include "maCrawler.h"
#include "maAdapt.h"
#include "maLayer.h"
#include <PCU.h>
#include <apfCavityOp.h>

namespace ma {

void syncLayer(Crawler* c, Crawler::Layer& layer)
{
  Mesh* m = c->adapter->mesh;
  PCU_Comm_Begin();
  for (size_t i = 0; i < layer.size(); ++i) {
    Entity* e = layer[i];
    if (m->isShared(e)) {
      apf::Copies remotes;
      m->getRemotes(e,remotes);
      APF_ITERATE(apf::Copies,remotes,it) {
        PCU_COMM_PACK(it->first,it->second);
        c->send(e, it->first);
      }
    }
  }
  PCU_Comm_Send();
  while (PCU_Comm_Listen()) {
    int from = PCU_Comm_Sender();
    while ( ! PCU_Comm_Unpacked()) {
      Entity* e;
      PCU_COMM_UNPACK(e);
      if (c->recv(e, from))
        layer.push_back(e);
    }
  }
}

static void crawlLayer(Crawler* c, Crawler::Layer& layer)
{
  Crawler::Layer nextLayer;
  for (size_t i = 0; i < layer.size(); ++i) {
    Entity* e = layer[i];
    Entity* e2 = c->crawl(e);
    if (e2)
      nextLayer.push_back(e2);
  }
  layer.swap(nextLayer);
}

void crawlLayers(Crawler* c)
{
  Crawler::Layer layer;
  c->begin(layer);
  while (PCU_Or( ! layer.empty())) {
    crawlLayer(c, layer);
    syncLayer(c, layer);
  }
  c->end();
}

void getDimensionBase(Adapt* a, int d, Crawler::Layer& base)
{
  Mesh* m = a->mesh;
  Iterator* it = m->begin(d);
  Entity* e;
  while ((e = m->iterate(it)))
    if (getFlag(a, e, LAYER_BASE))
      base.push_back(e);
  m->end(it);
}

Entity* getOtherVert(Mesh* m, Entity* v, Predicate& visited)
{
  Upward faces;
  m->getAdjacent(v, 2, faces);
  APF_ITERATE(Upward, faces, it) {
    if (m->getType(*it) != QUAD)
      continue;
    Entity* vs[4];
    m->getDownward(*it, 0, vs);
    int i = apf::findIn(vs, 4, v);
    int j = (i + 1) % 4;
    int k = (i - 1 + 4) % 4;
    if (!visited(vs[j]))
      return vs[j];
    if (!visited(vs[k]))
      return vs[k];
  }
  return 0;
}

Entity* getOtherEdge(Mesh* m, Entity* e, Predicate& visited)
{
  Upward faces;
  m->getAdjacent(e, 2, faces);
  APF_ITERATE(Upward, faces, it) {
    if (m->getType(*it) != QUAD)
      continue;
    Entity* es[4];
    m->getDownward(*it, 1, es);
    int i = apf::findIn(es, 4, e);
    int j = (i + 2) % 4;
    if (!visited(es[j]))
      return es[j];
  }
  return 0;
}

struct Tagger
{
  void init(Mesh* m_, Tag* t_)
  {
    m = m_;
    tag = t_;
  }
  int getNumber(Entity* v)
  {
    int n;
    m->getIntTag(v, tag, &n);
    return n;
  }
  void setNumber(Entity* v, int n)
  {
    m->setIntTag(v, tag, &n);
  }
  bool hasNumber(Entity* v)
  {
    return m->hasTag(v, tag);
  }
  Mesh* m;
  Tag* tag;
};

struct LayerNumberer : public Crawler
{
  LayerNumberer(Adapt* a_):
    Crawler(a_)
  {
    a = a_;
    m = a->mesh;
    tag = m->createIntTag("ma_layer", 1);
    t.init(m, tag);
  }
  void begin(Layer& first)
  {
    getDimensionBase(a, 0, first);
    for (size_t i = 0; i < first.size(); ++i)
      t.setNumber(first[i], 0);
  }
  Entity* crawl(Entity* v)
  {
    HasTag p(m, tag);
    Entity* ov = getOtherVert(m, v, p);
    if (!ov)
      return 0;
    t.setNumber(ov, t.getNumber(v) + 1);
    return ov;
  }
  void send(Entity* v, int to)
  {
    int n = t.getNumber(v);
    PCU_COMM_PACK(to, n);
  }
  bool recv(Entity* v, int)
  {
    int n;
    PCU_COMM_UNPACK(n);
    if (t.hasNumber(v))
      return false;
    t.setNumber(v, n);
    return true;
  }
  Adapt* a;
  Mesh* m;
  Tag* tag;
  Tagger t;
};

static Tag* numberLayer(Adapt* a)
{
  LayerNumberer op(a);
  crawlLayers(&op);
  return op.tag;
}

struct TopFlagger : public apf::CavityOp
{
  TopFlagger(Adapt* a_, Tag* t_):
    apf::CavityOp(a_->mesh)
  {
    a = a_;
    m = a->mesh;
    t.init(m, t_);
  }
  Outcome setEntity(Entity* v_)
  {
    if ((!t.hasNumber(v_)) ||
        getFlag(a, v_, CHECKED))
      return SKIP;
    if (!requestLocality(&v_, 1))
      return REQUEST;
    v = v_;
    return OK;
  }
  bool isTop()
  {
    int n = t.getNumber(v);
    apf::Up es;
    m->getUp(v, es);
    for (int i = 0; i < es.n; ++i) {
      Entity* ov = apf::getEdgeVertOppositeVert(m, es.e[i], v);
      if (!t.hasNumber(ov))
        continue;
      int on = t.getNumber(ov);
      if (on > n)
        return false;
    }
    return true;
  }
  void apply()
  {
    setFlag(a, v, CHECKED);
    if (isTop())
      setFlag(a, v, LAYER_TOP);
  }
  Adapt* a;
  Mesh* m;
  Entity* v;
  Tagger t;
};

void flagLayerTop(Adapt* a)
{
  Tag* layerNumbers = numberLayer(a);
  TopFlagger op(a, layerNumbers);
  op.applyToDimension(0);
  clearFlagFromDimension(a, CHECKED, 0);
  apf::removeTagFromDimension(a->mesh, layerNumbers, 0);
  a->mesh->destroyTag(layerNumbers);
}

}
<|endoftext|>


<commit_before>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>

TrackingWorker::TrackingWorker(IPositionReceiver *receiver)
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;

	while (!stop) {
		CameraData data = dequeue();

		if (data.valid) {
			ROS_DEBUG("Got valid data");
			receivedFirstPosition = true;
			Vector position = tracker.updatePosition(data.cameraVector, data.camNo, data.quadcopterId);

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data.quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				receiver->updatePositions(positions, ids, updates);
				ROS_DEBUG("Updated position of quadcopter %d", data.quadcopterId);
			} else {
				ROS_DEBUG("Not enough information to get position of quadcopter %d", data.quadcopterId);
			}
		} else if (receivedFirstPosition) {
			ROS_WARN("Position update buffer is empty!");
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	ROS_DEBUG("updatePosition: called");

	enqueue(data);

	ROS_DEBUG("updatePosition: Inserted CameraData for camera %d and quadcopter %d", data.camNo, data.quadcopterId);
}

void TrackingWorker::enqueue(CameraData data)
{
	ROS_DEBUG("enqueue: Inserting CameraData");

	{
		boost::mutex::scoped_lock lock(positionsMutex);
		ROS_DEBUG("enqueue: Got positions lock");
		positions.push(data);

		if (positions.size() > 25) {
			ROS_WARN("Position update buffer is running full (%ld entries). Seems like the position updating can't keep up!", positions.size());
		}
	}

	ROS_DEBUG("enqueue: Released positions lock");
	ROS_DEBUG("enqueue: Notifying about new CameraData");

	positionsEmpty.notify_one();

	ROS_DEBUG("enqueue: Finished insertion process");
}

CameraData TrackingWorker::dequeue()
{
	ROS_DEBUG("dequeue: Getting positions lock");

	{
		boost::mutex::scoped_lock lock(positionsMutex);

		ROS_DEBUG("dequeue: Got positions lock");

		if (!dataAvailable()) {
			positionsEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
		}

		if (dataAvailable()) {
			CameraData data = positions.back();
			positions.pop();

			ROS_DEBUG("dequeue: Released positions lock");
			return data;
		} else {
			CameraData data;
			data.valid = false;

			ROS_DEBUG("dequeue: Released positions lock");
			return data;
		}
	}
}

bool TrackingWorker::dataAvailable()
{
	return positions.size() > 0;
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}<commit_msg>Removed debug output, added tracking time measurement.<commit_after>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include "../matlab/position.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver)
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;

	while (!stop) {
		CameraData data = dequeue();

		if (data.valid) {
			// ROS_DEBUG("Got valid data");
			receivedFirstPosition = true;
			Vector position = tracker.updatePosition(data.cameraVector, data.camNo, data.quadcopterId);

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data.quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				long int startTime = getNanoTime();
				receiver->updatePositions(positions, ids, updates);
				double duration = getNanoTime() - startTime;
				duration /= 1e6;

				ROS_DEBUG("Updating position of quadcopter %d took %.3f ms", data.quadcopterId, duration);
			} else {
				// ROS_DEBUG("Not enough information to get position of quadcopter %d", data.quadcopterId);
			}
		} else if (receivedFirstPosition) {
			ROS_WARN("Position update buffer is empty!");
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	// ROS_DEBUG("updatePosition: called");

	enqueue(data);

	// ROS_DEBUG("updatePosition: Inserted CameraData for camera %d and quadcopter %d", data.camNo, data.quadcopterId);
}

void TrackingWorker::enqueue(CameraData data)
{
	// ROS_DEBUG("enqueue: Inserting CameraData");

	{
		boost::mutex::scoped_lock lock(positionsMutex);
		// ROS_DEBUG("enqueue: Got positions lock");
		positions.push(data);

		if (positions.size() > 25) {
			ROS_WARN("Position update buffer is running full (%ld entries). Seems like the position updating can't keep up!", positions.size());
		}
	}

	// ROS_DEBUG("enqueue: Released positions lock");
	// ROS_DEBUG("enqueue: Notifying about new CameraData");

	positionsEmpty.notify_one();

	// ROS_DEBUG("enqueue: Finished insertion process");
}

CameraData TrackingWorker::dequeue()
{
	// ROS_DEBUG("dequeue: Getting positions lock");

	{
		boost::mutex::scoped_lock lock(positionsMutex);

		// ROS_DEBUG("dequeue: Got positions lock");

		if (!dataAvailable()) {
			positionsEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
		}

		if (dataAvailable()) {
			CameraData data = positions.back();
			positions.pop();

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		} else {
			CameraData data;
			data.valid = false;

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		}
	}
}

bool TrackingWorker::dataAvailable()
{
	return positions.size() > 0;
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}<|endoftext|>


<commit_before>// Copyright 2016 Zheng Xian Qiu

#include "Seeker.h"

namespace Seeker {
  namespace UI {

    // Global Object
    Event* Event::_instance = Event::Instance();

    Event* Event::Instance() {
      if(!_instance) {
        _instance = new Event;
      }
      return _instance;
    }

    Event::Event() {
    }

    Event::~Event() {
    }

    // Subscriber
    void Event::OnEvent(EventType type, Seeker::Event& event) {
      switch(type) {
        case EventType::Mouse:
          // TODO: Implement mouse event with data
          OnMouseDown(static_cast<MouseEvent&>(event));
          break;
        case EventType::Key:
          // TODO: Implement key event with data
          OnKeyDown();
          break;
        default:
          break;
      }
    }

    void Event::OnMouseDown(MouseEvent& event) {
      for(auto it : _widgets) {
        // TODO: Get mouse event data
        if(it->MouseInBound(event.x, event.y)) {
          it->OnClick();
        }

        if(it->BlockEvent()) {
          break;
        }
      }
    }

    void Event::OnKeyDown() {
      // TODO: Implement KeyDown Handler
    }

    bool Event::Exists(Widget* widget) {
      for(auto it : _widgets) {
        if(it == widget) {
          return true;
        }
      }
      return false;
    }

    void Event::Register(Widget* widget) {
      if(Exists(widget)) return;
      _widgets.push_back(widget);
      ReSortSubscriber();
    }

    void Event::UnRegister(Widget* widget) {
      if(!Exists(widget)) return;
      _widgets.erase(std::remove(_widgets.begin(), _widgets.end(), widget), _widgets.end());
    }

    void Event::ReSortSubscriber() {
      std::sort(_widgets.begin(), _widgets.end(), WidgetEventWeightCompare);
    }

    bool Event::WidgetEventWeightCompare(Widget* a, Widget* b) {
      return a->EventWeight() > b->EventWeight();
    }

  }
}
<commit_msg>Subscribe UI Event<commit_after>// Copyright 2016 Zheng Xian Qiu

#include "Seeker.h"

namespace Seeker {
  namespace UI {

    // Global Object
    Event* Event::_instance = Event::Instance();

    Event* Event::Instance() {
      if(!_instance) {
        _instance = new Event;
      }
      return _instance;
    }

    Event::Event() {
      EventManager::On(this);
    }

    Event::~Event() {
      EventManager::Off(this);
    }

    // Subscriber
    void Event::OnEvent(EventType type, Seeker::Event& event) {
      switch(type) {
        case EventType::Mouse:
          // TODO: Implement mouse event with data
          OnMouseDown(static_cast<MouseEvent&>(event));
          break;
        case EventType::Key:
          // TODO: Implement key event with data
          OnKeyDown();
          break;
        default:
          break;
      }
    }

    void Event::OnMouseDown(MouseEvent& event) {
      for(auto it : _widgets) {
        // TODO: Get mouse event data
        if(it->MouseInBound(event.x, event.y)) {
          it->OnClick();
        }

        if(it->BlockEvent()) {
          break;
        }
      }
    }

    void Event::OnKeyDown() {
      // TODO: Implement KeyDown Handler
    }

    bool Event::Exists(Widget* widget) {
      for(auto it : _widgets) {
        if(it == widget) {
          return true;
        }
      }
      return false;
    }

    void Event::Register(Widget* widget) {
      if(Exists(widget)) return;
      _widgets.push_back(widget);
      ReSortSubscriber();
    }

    void Event::UnRegister(Widget* widget) {
      if(!Exists(widget)) return;
      _widgets.erase(std::remove(_widgets.begin(), _widgets.end(), widget), _widgets.end());
    }

    void Event::ReSortSubscriber() {
      std::sort(_widgets.begin(), _widgets.end(), WidgetEventWeightCompare);
    }

    bool Event::WidgetEventWeightCompare(Widget* a, Widget* b) {
      return a->EventWeight() > b->EventWeight();
    }

  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Srijan R Shetty <srijan.shetty+code@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#define PREFIX "leaves/leaf_"
#define DEBUG

#include <iostream>
#include <math.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <queue>
#include <vector>
#include <climits>
#include <algorithm>

using namespace std;

namespace BPlusTree {
    class Node {
        // Static data
        static int leafCount;

        // Type of leaf
        bool leaf;

        // LeafNode properties
        string leafFileName;

        public:

        // Bounds
        static int lowerBound;
        static int upperBound;

        // Keys and their associated children
        vector<double> keys;
        vector<Node *> children;

        // The parent of the Node
        Node *parent;

        // The next leaf
        Node *nextLeaf;

        // Basic initialization
        Node();

        // Check if leaf
        bool isLeaf() { return leaf; }

        // set to internalNode
        void setToInternalNode() { leaf = false; }

        // Return the size of keys
        int size() { return keys.size(); }

        // Initialize the for the tree
        static void initialize(int pageSize);

        // Return the position of a key in keys
        int getKeyPosition(double key);

        // Read all the keys from disk to memory
        void getKeysFromDisk();

        // Insert object into disk
        void insertObject(double key);

        // Insert an internal node into the tree
        void insertNode(double key, Node *leftChild, Node *rightChild);

        // Split the current Leaf Node
        void splitLeaf();

        // Split the current internal Node
        void splitInternal();
    };

    // Initialize static variables
    int Node::lowerBound = 0;
    int Node::upperBound = 0;
    int Node::leafCount = 0;

    Node *bRoot = nullptr;

    Node::Node() {
        // Initially the parent is NULL
        parent = nullptr;
        nextLeaf = nullptr;

        // Initially every node is a leaf
        leaf = true;

        // Exit if the lowerBoundKey is not defined
        if (lowerBound == 0) {
            cout << "LowerKeyBound not defined";
            exit(1);
        }

        // LeafNode properties
        leafFileName = PREFIX + to_string(leafCount++);
    }

    void Node::initialize(int pageSize) {
        int nodeSize = sizeof(new Node());
        int keySize = sizeof(double);
        lowerBound = floor((pageSize - nodeSize) / (2 * (keySize + nodeSize)));

        lowerBound = 5;
        upperBound = 2 * lowerBound;
    }

    int Node::getKeyPosition(double key) {
        // If keys are empty, return
        if (keys.size() == 0) {
            return 0;
        }

        // Find the original position of the key
        int position = -1;
        if (key < keys.front()) {
            position = 0;
        } else {
            for (int i = 1; i < (int)keys.size(); ++i) {
                if (keys[i -1] < key && key <= keys[i]) {
                    position = i;
                }
            }

            if (position == -1) {
                position = keys.size();
            }
        }

        return position;
    }

    void Node::getKeysFromDisk() {
        // Clear the exisitng keys
        keys.clear();

        // Create a binary file
        ifstream leafFile;
        leafFile.open(leafFileName, ios::binary|ios::in);

        // Read the key and enter it into keys
        double key;
        while (!leafFile.eof()) {
            leafFile.read((char *) &key, sizeof(key));

            /* Common Error in reading files */
            if (!leafFile) break;

            keys.push_back(key);
        }

        // sort the keys
        sort(keys.begin(), keys.end());

        // Close the file
        leafFile.close();
    }

    void Node::insertObject(double key) {
        ofstream leafFile;
        leafFile.open(leafFileName, ios::binary|ios::app);
        leafFile.write((char *) &key, sizeof(key));
        leafFile.close();

        // Load keys to avoid stale keys
        getKeysFromDisk();
    }

    void Node::insertNode(double key, Node *leftChild, Node *rightChild) {
        int position = getKeyPosition(key);

        // insert the new key to keys
        keys.insert(keys.begin() + position, key);

        // insert the newChild
        children.insert(children.begin() + position + 1, rightChild);

#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        // Print them out
        cout << "LeftNode : ";
        for (auto key : leftChild->keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "RightNode : ";
        for (auto key : rightChild->keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // If this overflows, we move again upward
        if ((int)keys.size() > upperBound) {
            splitInternal();
        }
    }

    void Node::splitInternal() {
#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Create a surrogate internal node
        Node *surrogateInternalNode = new Node();
        surrogateInternalNode->setToInternalNode();

        // Fix up the keys
        double startPoint = *(keys.begin() + lowerBound);
        for (auto key = keys.begin() + lowerBound + 1; key != keys.end(); ++key) {
            surrogateInternalNode->keys.push_back(*key);
        }
        keys.resize(lowerBound);

#ifdef DEBUG
        // Print them out
        cout << "First InternalNode : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Second InternalNode : ";
        for (auto key : surrogateInternalNode->keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Split At " << startPoint << endl;
#endif

        // Fix up the pointers
        for (auto child = children.begin() + lowerBound + 1; child != children.end(); ++child) {
            surrogateInternalNode->children.push_back(*child);
            (*child)->parent = surrogateInternalNode;
        }
        children.resize(lowerBound + 1);

        if (parent != nullptr) {
            // Assign parents
            surrogateInternalNode->parent = parent;

            // Now we push up the splitting one level
            parent->insertNode(startPoint, this, surrogateInternalNode);
        } else {
            // Create a new parent node
            Node *newParent = new Node();
            newParent->setToInternalNode();

            // Assign parents
            surrogateInternalNode->parent = newParent;
            parent = newParent;

            // Insert the key into the keys
            newParent->keys.push_back(startPoint);

            // Insert the children
            newParent->children.push_back(this);
            newParent->children.push_back(surrogateInternalNode);

            // Reset the root node
            bRoot = newParent;
        }
    }

    void Node::splitLeaf() {
#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";

        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Create a surrogate leaf node
        Node *surrogateLeafNode = new Node();
        for (auto key = keys.begin() + lowerBound; key != keys.end(); ++key) {
            surrogateLeafNode->insertObject(*key);
        }

        // Resize the current leaf node
        keys.resize(lowerBound);

#ifdef DEBUG
        // Print them out
        cout << "First Leaf : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Second Leaf : ";
        for (auto key : surrogateLeafNode->keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Add a pointer to the nextLeaf
        nextLeaf = surrogateLeafNode;

        if (parent != nullptr) {
            // Assign parents
            surrogateLeafNode->parent = parent;

            // Now we push up the splitting one level
            parent->insertNode(surrogateLeafNode->keys.front(), this, surrogateLeafNode);
        } else {
            // Create a new parent node
            Node *newParent = new Node();
            newParent->setToInternalNode();

            // Assign parents
            surrogateLeafNode->parent = newParent;
            parent = newParent;

            // Insert the key into the keys
            newParent->keys.push_back(surrogateLeafNode->keys.front());

            // Insert the children
            newParent->children.push_back(this);
            newParent->children.push_back(surrogateLeafNode);

            // Reset the root node
            bRoot = newParent;
        }
    }

    // Initialize the BPlusTree
    void initialize(int pageSize) {
        // Compute the number of keys in each node
        Node::initialize(pageSize);

        // Intialize the root
        bRoot = new Node();
    }

    // Serialize the tree
    void serialize(Node *root) {
        // Prettify
        cout << endl << endl;

        queue< pair<Node *, char> > previousLevel;
        previousLevel.push(make_pair(root, 'N'));

        Node *iterator;
        char type;
        while (!previousLevel.empty()) {
            queue< pair<Node *, char> > nextLevel;

            while (!previousLevel.empty()) {
                // Get the front and pop
                iterator = previousLevel.front().first;
                type = previousLevel.front().second;
                previousLevel.pop();

                // If it a seperator, print and move ahead
                if (type == '|') {
                    cout << "|| ";
                    continue;
                }

                // Print all the keys
                for (auto key : iterator->keys) {
                    cout << key << " ";
                }

                // Enqueue all the children
                for (auto child : iterator->children) {
                    nextLevel.push(make_pair(child, 'N'));

                    // Insert a marker to indicate end of child
                    nextLevel.push(make_pair(nullptr, '|'));
                }
            }

            // Seperate different levels
            cout << endl << endl;
            previousLevel = nextLevel;
        }
    }

    // Insert a key into the BPlusTree
    void insert(Node *root, double key) {
        // If the root is a leaf, we can directly insert
        if (root->isLeaf()) {
            // Insert object
            root->insertObject(key);

            // Split if required
            if (root->size() > root->upperBound) {
                root->splitLeaf();
            }
        } else {
            // We traverse the tree
            int position = root->getKeyPosition(key);

            // Recurse into the tree
            insert(root->children[position], key);
        }
    }

    // Point search in a BPlusTree
}

using namespace BPlusTree;

int main() {
    // Open the configuration file
    ifstream configFile;
    configFile.open("./bplustree.config");

    // Read in the pageSize from the configuration file
    int pageSize = 0;
    configFile >> pageSize;

    // Initialize the BPlusTree module
    initialize(pageSize);

    for (int i = 0; i < 150; ++i) {
        insert(bRoot, i);
    }

    serialize(bRoot);
    // pointSearch(bRoot, 140);

    // Clean up on exit
    system("rm leaves/* && touch leaves/DUMMY");

    return 0;
}
<commit_msg>Save keys to disk on leaf resize<commit_after>/*
 * Copyright (c) 2015 Srijan R Shetty <srijan.shetty+code@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#define PREFIX "leaves/leaf_"
#define DEBUG

#include <iostream>
#include <math.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <queue>
#include <vector>
#include <climits>
#include <algorithm>

using namespace std;

namespace BPlusTree {
    class Node {
        // Static data
        static int leafCount;

        // Type of leaf
        bool leaf;

        // LeafNode properties
        string leafFileName;

        public:

        // Bounds
        static int lowerBound;
        static int upperBound;

        // Keys and their associated children
        vector<double> keys;
        vector<Node *> children;

        // The parent of the Node
        Node *parent;

        // The next leaf
        Node *nextLeaf;

        // Basic initialization
        Node();

        // Check if leaf
        bool isLeaf() { return leaf; }

        // set to internalNode
        void setToInternalNode() { leaf = false; }

        // Return the size of keys
        int size() { return keys.size(); }

        // Initialize the for the tree
        static void initialize(int pageSize);

        // Return the position of a key in keys
        int getKeyPosition(double key);

        // Read all the keys from disk to memory
        void getKeysFromDisk();

        // Save keys to disk
        void saveKeysToDisk();

        // Insert object into disk
        void insertObject(double key);

        // Insert an internal node into the tree
        void insertNode(double key, Node *leftChild, Node *rightChild);

        // Split the current Leaf Node
        void splitLeaf();

        // Split the current internal Node
        void splitInternal();
    };

    // Initialize static variables
    int Node::lowerBound = 0;
    int Node::upperBound = 0;
    int Node::leafCount = 0;

    Node *bRoot = nullptr;

    Node::Node() {
        // Initially the parent is NULL
        parent = nullptr;
        nextLeaf = nullptr;

        // Initially every node is a leaf
        leaf = true;

        // Exit if the lowerBoundKey is not defined
        if (lowerBound == 0) {
            cout << "LowerKeyBound not defined";
            exit(1);
        }

        // LeafNode properties
        leafFileName = PREFIX + to_string(leafCount++);
    }

    void Node::initialize(int pageSize) {
        int nodeSize = sizeof(new Node());
        int keySize = sizeof(double);
        lowerBound = floor((pageSize - nodeSize) / (2 * (keySize + nodeSize)));

        lowerBound = 5;
        upperBound = 2 * lowerBound;
    }

    int Node::getKeyPosition(double key) {
        // If keys are empty, return
        if (keys.size() == 0) {
            return 0;
        }

        // Find the original position of the key
        if (key <= keys.front()) {
            return 0;
        }

        for (int i = 1; i < (int)keys.size(); ++i) {
            if (keys[i -1] < key && key <= keys[i]) {
                return i;
            }
        }

        return keys.size();
    }

    void Node::saveKeysToDisk() {
        // Create a binary file
        ofstream leafFile;
        leafFile.open(leafFileName, ios::binary|ios::out);

        // Read the key and enter it into keys
        for (auto key : keys) {
            leafFile.write((char *) &key, sizeof(key));
        }

        // Close the file
        leafFile.close();
    }

    void Node::getKeysFromDisk() {
        // Clear the exisitng keys
        keys.clear();

        // Create a binary file
        ifstream leafFile;
        leafFile.open(leafFileName, ios::binary|ios::in);

        // Read the key and enter it into keys
        double key;
        while (!leafFile.eof()) {
            leafFile.read((char *) &key, sizeof(key));

            /* Common Error in reading files */
            if (!leafFile) break;

            keys.push_back(key);
        }

        // sort the keys
        sort(keys.begin(), keys.end());

        // Close the file
        leafFile.close();
    }

    void Node::insertObject(double key) {
        ofstream leafFile;
        leafFile.open(leafFileName, ios::binary|ios::app);
        leafFile.write((char *) &key, sizeof(key));
        leafFile.close();

        // Load keys to avoid stale keys
        getKeysFromDisk();
    }

    void Node::insertNode(double key, Node *leftChild, Node *rightChild) {
        int position = getKeyPosition(key);

        // insert the new key to keys
        keys.insert(keys.begin() + position, key);

        // insert the newChild
        children.insert(children.begin() + position + 1, rightChild);

#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        // Print them out
        cout << "LeftNode : ";
        for (auto key : leftChild->keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "RightNode : ";
        for (auto key : rightChild->keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // If this overflows, we move again upward
        if ((int)keys.size() > upperBound) {
            splitInternal();
        }
    }

    void Node::splitInternal() {
#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Create a surrogate internal node
        Node *surrogateInternalNode = new Node();
        surrogateInternalNode->setToInternalNode();

        // Fix up the keys
        double startPoint = *(keys.begin() + lowerBound);
        for (auto key = keys.begin() + lowerBound + 1; key != keys.end(); ++key) {
            surrogateInternalNode->keys.push_back(*key);
        }
        keys.resize(lowerBound);

#ifdef DEBUG
        // Print them out
        cout << "First InternalNode : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Second InternalNode : ";
        for (auto key : surrogateInternalNode->keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Split At " << startPoint << endl;
#endif

        // Fix up the pointers
        for (auto child = children.begin() + lowerBound + 1; child != children.end(); ++child) {
            surrogateInternalNode->children.push_back(*child);
            (*child)->parent = surrogateInternalNode;
        }
        children.resize(lowerBound + 1);

        if (parent != nullptr) {
            // Assign parents
            surrogateInternalNode->parent = parent;

            // Now we push up the splitting one level
            parent->insertNode(startPoint, this, surrogateInternalNode);
        } else {
            // Create a new parent node
            Node *newParent = new Node();
            newParent->setToInternalNode();

            // Assign parents
            surrogateInternalNode->parent = newParent;
            parent = newParent;

            // Insert the key into the keys
            newParent->keys.push_back(startPoint);

            // Insert the children
            newParent->children.push_back(this);
            newParent->children.push_back(surrogateInternalNode);

            // Reset the root node
            bRoot = newParent;
        }
    }

    void Node::splitLeaf() {
#ifdef DEBUG
        cout << endl;
        cout << "Base Node : ";

        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Create a surrogate leaf node
        Node *surrogateLeafNode = new Node();
        for (auto key = keys.begin() + lowerBound; key != keys.end(); ++key) {
            surrogateLeafNode->insertObject(*key);
        }

        // Resize the current leaf node and save keys to disk
        keys.resize(lowerBound);
        saveKeysToDisk();

#ifdef DEBUG
        // Print them out
        cout << "First Leaf : ";
        for (auto key : keys) {
            cout << key << " ";
        }
        cout << endl;

        cout << "Second Leaf : ";
        for (auto key : surrogateLeafNode->keys) {
            cout << key << " ";
        }
        cout << endl;
#endif

        // Add a pointer to the nextLeaf
        nextLeaf = surrogateLeafNode;

        if (parent != nullptr) {
            // Assign parents
            surrogateLeafNode->parent = parent;

            // Now we push up the splitting one level
            parent->insertNode(surrogateLeafNode->keys.front(), this, surrogateLeafNode);
        } else {
            // Create a new parent node
            Node *newParent = new Node();
            newParent->setToInternalNode();

            // Assign parents
            surrogateLeafNode->parent = newParent;
            parent = newParent;

            // Insert the key into the keys
            newParent->keys.push_back(surrogateLeafNode->keys.front());

            // Insert the children
            newParent->children.push_back(this);
            newParent->children.push_back(surrogateLeafNode);

            // Reset the root node
            bRoot = newParent;
        }
    }

    // Initialize the BPlusTree
    void initialize(int pageSize) {
        // Compute the number of keys in each node
        Node::initialize(pageSize);

        // Intialize the root
        bRoot = new Node();
    }

    // Serialize the tree
    void serialize(Node *root) {
        // Prettify
        cout << endl << endl;

        queue< pair<Node *, char> > previousLevel;
        previousLevel.push(make_pair(root, 'N'));

        Node *iterator;
        char type;
        while (!previousLevel.empty()) {
            queue< pair<Node *, char> > nextLevel;

            while (!previousLevel.empty()) {
                // Get the front and pop
                iterator = previousLevel.front().first;
                type = previousLevel.front().second;
                previousLevel.pop();

                // If it a seperator, print and move ahead
                if (type == '|') {
                    cout << "|| ";
                    continue;
                }

                // Print all the keys
                for (auto key : iterator->keys) {
                    cout << key << " ";
                }

                // Enqueue all the children
                for (auto child : iterator->children) {
                    nextLevel.push(make_pair(child, 'N'));

                    // Insert a marker to indicate end of child
                    nextLevel.push(make_pair(nullptr, '|'));
                }
            }

            // Seperate different levels
            cout << endl << endl;
            previousLevel = nextLevel;
        }
    }

    // Insert a key into the BPlusTree
    void insert(Node *root, double key) {
        // If the root is a leaf, we can directly insert
        if (root->isLeaf()) {
            // Insert object
            root->insertObject(key);

            // Split if required
            if (root->size() > root->upperBound) {
                root->splitLeaf();
            }
        } else {
            // We traverse the tree
            int position = root->getKeyPosition(key);

            // Recurse into the tree
            insert(root->children[position], key);
        }
    }

    // Point search in a BPlusTree
}

using namespace BPlusTree;

int main() {
    // Open the configuration file
    ifstream configFile;
    configFile.open("./bplustree.config");

    // Read in the pageSize from the configuration file
    int pageSize = 0;
    configFile >> pageSize;

    // Initialize the BPlusTree module
    initialize(pageSize);

    for (int i = 0; i < 150; ++i) {
        insert(bRoot, i);
    }

    serialize(bRoot);
    // pointSearch(bRoot, 140);

    // Clean up on exit
    system("rm leaves/* && touch leaves/DUMMY");

    return 0;
}
<|endoftext|>