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

//_________________________________________________________________________
// An analysis task to check the PHOS photon data in simulated data
//
//*-- Yves Schutz
//////////////////////////////////////////////////////////////////////////////

#include <TChain.h>
#include <TFile.h>
#include <TNtuple.h>
#include <TVector3.h>

#include "AliTriggerPHOS.h"
#include "AliESD.h"
#include "AliLog.h"

//______________________________________________________________________________
AliTriggerPHOS::AliTriggerPHOS(const char *name) :
  AliAnalysisTask(name,""),
  fChain(0),
  fESD(0),
  fOutputContainer(0),
  fNtTrigger22(0),
  fNtTriggerNN(0)

{
  // Constructor.
  // Input slot #0 works with an Ntuple
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TH1 container
  DefineOutput(0,  TObjArray::Class()) ;
}

//______________________________________________________________________________
AliTriggerPHOS::~AliTriggerPHOS()
{
  // dtor
  fOutputContainer->Clear() ;
  delete fOutputContainer ;
  delete fNtTrigger22 ;
  delete fNtTriggerNN ;
}

//______________________________________________________________________________
void AliTriggerPHOS::ConnectInputData(const Option_t*)
{
  // Initialisation of branch container and histograms

  AliInfo(Form("*** Initialization of %s", GetName())) ;

  // Get input data
  fChain = dynamic_cast<TChain *>(GetInputData(0)) ;
  if (!fChain) {
    AliError(Form("Input 0 for %s not found\n", GetName()));
    return ;
  }

  // One should first check if the branch address was taken by some other task
  char ** address = (char **)GetBranchAddress(0, "ESD");
  if (address) {
    fESD = (AliESD*)(*address);
  } else {
    fESD = new AliESD();
    SetBranchAddress(0, "ESD", &fESD);
  }
}

//________________________________________________________________________

void AliTriggerPHOS::CreateOutputObjects()
{

  // create histograms
  fNtTrigger22 = new TNtuple("PHOStrigger22", "Trigger data 2x2 patch", "a22:a220:enMax:phEnMax:p22:eta22:phi22:etaMax:phiMax:phEtaMax:phPhiMax");
  fNtTriggerNN = new TNtuple("PHOStriggerNN", "Trigger data NxN patch", "aNN:aNN0:enMax:phEnMax:pNN:etaNN:phiNN:etaMax:phiMax:phEtaMax:phPhiMax");

  // create output container

  fOutputContainer = new TObjArray(2) ;
  fOutputContainer->SetName(GetName()) ;

  fOutputContainer->AddAt(fNtTrigger22,             0) ;
  fOutputContainer->AddAt(fNtTriggerNN,             1) ;

}

//______________________________________________________________________________
void AliTriggerPHOS::Exec(Option_t *)
{
  // Processing of one event

  Long64_t entry = fChain->GetReadEntry() ;

  if (!fESD) {
    AliError("fESD is not connected to the input!") ;
    return ;
  }

  if ( !((entry-1)%100) )
    AliInfo(Form("%s ----> Processing event # %lld",  (dynamic_cast<TChain *>(fChain))->GetFile()->GetName(), entry)) ;

  // ************************  PHOS *************************************
  // Get trigger information

  // trigger amplitudes
  const TArrayF * triggerAmplitudes      = fESD->GetPHOSTriggerAmplitudes();
  const Float_t a22    = static_cast<Float_t>(triggerAmplitudes->At(0)) ;
  const Float_t a22O   = static_cast<Float_t>(triggerAmplitudes->At(1)) ;
  const Float_t aNN    = static_cast<Float_t>(triggerAmplitudes->At(2)) ;
  const Float_t aNNO   = static_cast<Float_t>(triggerAmplitudes->At(3)) ;

  // trigger position
  const TArrayF * triggerPosition      = fESD->GetPHOSTriggerPosition();
  const Float_t p22    =  static_cast<Float_t>(triggerPosition->At(0)) ;
  const Float_t phi22  =  static_cast<Float_t>(triggerPosition->At(1)) ;
  const Float_t eta22  =  static_cast<Float_t>(triggerPosition->At(2)) ;
  const Float_t pNN    =  static_cast<Float_t>(triggerPosition->At(3)) ;
  const Float_t phiNN  =  static_cast<Float_t>(triggerPosition->At(4)) ;
  const Float_t etaNN  =  static_cast<Float_t>(triggerPosition->At(5)) ;

  Int_t       firstPhosCluster       = fESD->GetFirstPHOSCluster() ;
  const Int_t numberOfPhosClusters   = fESD->GetNumberOfPHOSClusters() ;

  Float_t enMax       = 0. ;
  Float_t phEnMax     = 0. ;
  Float_t etaMax      = 999. ;
  Float_t phiMax      = 999. ;
  Float_t phEtaMax    = 999. ;
  Float_t phPhiMax    = 999. ;

  Int_t      phosCluster ;

  // loop over the PHOS Cluster

  for(phosCluster = firstPhosCluster ; phosCluster < firstPhosCluster + numberOfPhosClusters ; phosCluster++) {
    AliESDCaloCluster * caloCluster = fESD->GetCaloCluster(phosCluster) ;
    if (caloCluster) {

      Float_t cluEnergy = caloCluster->GetClusterEnergy() ;
      Float_t pos[3] ;
      TVector3 vpos ;

      caloCluster->GetGlobalPosition( pos ) ;

      if ( cluEnergy > enMax) {
	enMax = cluEnergy ;
	vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	etaMax = vpos.Eta() ;
	phiMax = vpos.Phi() ;
      }

      Float_t * pid = caloCluster->GetPid() ;

      if(pid[AliPID::kPhoton] > 0.9) {
	if ( cluEnergy > phEnMax) {
	  phEnMax = cluEnergy ;
	  vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	  phEtaMax = vpos.Eta() ;
	  phPhiMax = vpos.Phi() ;
	}
      }
    }

    fNtTrigger22->Fill(a22, a22O, enMax, phEnMax, p22, eta22, phi22, etaMax, phiMax, phEtaMax, phPhiMax );
    fNtTriggerNN->Fill(aNN, aNNO, enMax, phEnMax, pNN, etaNN, phiNN, etaMax, phiMax, phEtaMax, phPhiMax );
 }

  PostData(0, fOutputContainer);

}

//______________________________________________________________________________
void AliTriggerPHOS::Terminate(Option_t *)
{
  // Processing when the event loop is ended

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

//_________________________________________________________________________
// An analysis task to check the PHOS photon data in simulated data
//
//*-- Yves Schutz
//////////////////////////////////////////////////////////////////////////////

#include <TChain.h>
#include <TFile.h>
#include <TNtuple.h>
#include <TVector3.h>

#include "AliTriggerPHOS.h"
#include "AliESD.h"
#include "AliLog.h"

//______________________________________________________________________________
AliTriggerPHOS::AliTriggerPHOS(const char *name) :
  AliAnalysisTask(name,""),
  fChain(0),
  fESD(0),
  fOutputContainer(0),
  fNtTrigger22(0),
  fNtTriggerNN(0)

{
  // Constructor.
  // Input slot #0 works with an Ntuple
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TH1 container
  DefineOutput(0,  TObjArray::Class()) ;
}

//______________________________________________________________________________
AliTriggerPHOS::~AliTriggerPHOS()
{
  // dtor
  fOutputContainer->Clear() ;
  delete fOutputContainer ;
  delete fNtTrigger22 ;
  delete fNtTriggerNN ;
}

//______________________________________________________________________________
void AliTriggerPHOS::ConnectInputData(const Option_t*)
{
  // Initialisation of branch container and histograms

  AliInfo(Form("*** Initialization of %s", GetName())) ;

  // Get input data
  fChain = dynamic_cast<TChain *>(GetInputData(0)) ;
  if (!fChain) {
    AliError(Form("Input 0 for %s not found\n", GetName()));
    return ;
  }

  // One should first check if the branch address was taken by some other task
  char ** address = (char **)GetBranchAddress(0, "ESD");
  if (address) {
    fESD = (AliESD*)(*address);
  } else {
    fESD = new AliESD();
    SetBranchAddress(0, "ESD", &fESD);
  }
}

//________________________________________________________________________

void AliTriggerPHOS::CreateOutputObjects()
{

  // create histograms
  fNtTrigger22 = new TNtuple("PHOStrigger22", "Trigger data 2x2 patch", "a22:a220:enMax:phEnMax:eta22:phi22:etaMax:phiMax:phEtaMax:phPhiMax");
  fNtTriggerNN = new TNtuple("PHOStriggerNN", "Trigger data NxN patch", "aNN:aNN0:enMax:phEnMax:etaNN:phiNN:etaMax:phiMax:phEtaMax:phPhiMax");

  // create output container

  fOutputContainer = new TObjArray(2) ;
  fOutputContainer->SetName(GetName()) ;

  fOutputContainer->AddAt(fNtTrigger22,             0) ;
  fOutputContainer->AddAt(fNtTriggerNN,             1) ;

}

//______________________________________________________________________________
void AliTriggerPHOS::Exec(Option_t *)
{
  // Processing of one event

  Long64_t entry = fChain->GetReadEntry() ;

  if (!fESD) {
    AliError("fESD is not connected to the input!") ;
    return ;
  }

  if ( !((entry-1)%100) )
    AliInfo(Form("%s ----> Processing event # %lld",  (dynamic_cast<TChain *>(fChain))->GetFile()->GetName(), entry)) ;

  // ************************  PHOS *************************************
  // Get trigger information

  // trigger amplitudes
  const TArrayF * triggerAmplitudes      = fESD->GetPHOSTriggerAmplitudes();
  const Float_t a22    = static_cast<Float_t>(triggerAmplitudes->At(0)) ;
  const Float_t a22O   = static_cast<Float_t>(triggerAmplitudes->At(1)) ;
  const Float_t aNN    = static_cast<Float_t>(triggerAmplitudes->At(2)) ;
  const Float_t aNNO   = static_cast<Float_t>(triggerAmplitudes->At(3)) ;

  // trigger position
  const TArrayF * triggerPosition      = fESD->GetPHOSTriggerPosition();
  const Float_t x22  =  static_cast<Float_t>(triggerPosition->At(0)) ;
  const Float_t y22  =  static_cast<Float_t>(triggerPosition->At(1)) ;
  const Float_t z22  =  static_cast<Float_t>(triggerPosition->At(2)) ;
  const Float_t xNN  =  static_cast<Float_t>(triggerPosition->At(3)) ;
  const Float_t yNN  =  static_cast<Float_t>(triggerPosition->At(4)) ;
  const Float_t zNN  =  static_cast<Float_t>(triggerPosition->At(5)) ;

  Int_t       firstPhosCluster       = fESD->GetFirstPHOSCluster() ;
  const Int_t numberOfPhosClusters   = fESD->GetNumberOfPHOSClusters() ;

  Float_t enMax       = 0. ;
  Float_t phEnMax     = 0. ;
  Float_t etaMax      = 0.5 ;
  Float_t phiMax      = 0. ;
  Float_t phEtaMax    = 0.5 ;
  Float_t phPhiMax    = 0. ;

  TVector3 vpos22(x22, y22, z22) ;
  TVector3 vposNN(xNN, yNN, zNN) ;
  Float_t eta22 = vpos22.Eta() ;
  Float_t phi22 = vpos22.Phi() * TMath::RadToDeg() + 360. ;
  Float_t etaNN = vposNN.Eta() ;
  Float_t phiNN = vposNN.Phi() * TMath::RadToDeg() + 360. ;

  Int_t      phosCluster ;

  // loop over the PHOS Cluster

  for(phosCluster = firstPhosCluster ; phosCluster < firstPhosCluster + numberOfPhosClusters ; phosCluster++) {
    AliESDCaloCluster * caloCluster = fESD->GetCaloCluster(phosCluster) ;
    if (caloCluster) {

      Float_t cluEnergy = caloCluster->GetClusterEnergy() ;
      Float_t pos[3] ;
      TVector3 vpos ;

      caloCluster->GetGlobalPosition( pos ) ;

      if ( cluEnergy > enMax) {
	enMax = cluEnergy ;
	vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	etaMax = vpos.Eta() ;
	phiMax = vpos.Phi() ;
      }

      Float_t * pid = caloCluster->GetPid() ;

      if(pid[AliPID::kPhoton] > 0.9) {
	if ( cluEnergy > phEnMax) {
	  phEnMax = cluEnergy ;
	  vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	  phEtaMax = vpos.Eta() ;
	  phPhiMax = vpos.Phi() ;
	}
      }
    }

    fNtTrigger22->Fill(a22, a22O, enMax, phEnMax, eta22, phi22, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
    fNtTriggerNN->Fill(aNN, aNNO, enMax, phEnMax, etaNN, phiNN, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
 }

  PostData(0, fOutputContainer);

}

//______________________________________________________________________________
void AliTriggerPHOS::Terminate(Option_t *)
{
  // Processing when the event loop is ended

}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <gazebo_msgs/ApplyJointEffort.h>
#include <urdf/model.h>
#include <urdf_interface/joint.h>
#include <cstdlib>
#include <sys/time.h>
#include <time.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/Twist.h>
#include <atlas_gazebo_msgs/RobotState.h>
#include <lcm/lcm-cpp.hpp>
#include <lcmtypes/drc_lcmtypes.hpp>
#include <atlas_gazebo_msgs/ActuatorCmd.h>

double getTime_now()
{
	struct timeval tv;
	gettimeofday (&tv,NULL);
	return (int64_t) tv.tv_sec*1000000+tv.tv_usec;
}

class ActuatorCmdHandler{
	private:
		ros::Publisher actuator_cmd_pub;
	public:
	ActuatorCmdHandler()
	{
		//ros::init(argc,argv,"actuator_cmd_publisher");
		ros::NodeHandle actuator_cmd_node;
		actuator_cmd_pub = actuator_cmd_node.advertise<atlas_gazebo_msgs::ActuatorCmd>("actuator_cmd",10);
	}
	void actuator_cmd_Callback(const lcm::ReceiveBuffer* rbuf,const std::string &channel,const drc::actuator_cmd_t* msg)//what is rbuf and channel here?
	{
		atlas_gazebo_msgs::ActuatorCmd actuator_cmd_msg;
		actuator_cmd_msg.header.stamp.fromNSec(msg->timestamp/1000);//msg.timestamp is int64_t, how can I convert it to 'Time', why divide by 1000?
		actuator_cmd_msg.robot_name = msg->robot_name;
		//actuator_cmd_msg.joint_name = new string[msg.num_joints];
		//actuator_cmd_msg.joint_effort = new float[msg.num_joints]
		for(std::vector<int>::size_type i=0;i!=msg->joint_name.size();i++){//So varaibles in lcm message are all in vector type
			actuator_cmd_msg.joint_name.push_back(msg->joint_name.at(i));
			actuator_cmd_msg.joint_effort.push_back(msg->joint_effort.at(i));
		}
		if(ros::ok())
		{
			actuator_cmd_pub.publish(actuator_cmd_msg);
			ros::spinOnce();
		}
		//delete[] actuator_cmd_msg.joint_name;
		//delete[] actuator_cmd_msg.joint_effort;
	}
};

int main(int argc,char** argv)
{
	ros::init(argc,argv,"actuator_cmd_publisher");
	lcm::LCM talker;
	if(!talker.good())
		return 1;
	drc::actuator_cmd_t actuator_cmd;
	actuator_cmd.timestamp = 0;
	actuator_cmd.robot_name = "atlas";
	actuator_cmd.num_joints = 2;
	actuator_cmd.joint_name.push_back("hip");
	actuator_cmd.joint_name.push_back("neck");
	actuator_cmd.joint_effort.push_back(0.0);
	actuator_cmd.joint_effort.push_back(1.0);
	lcm::LCM listener;
	ActuatorCmdHandler handler;
	listener.subscribe("ACTUATOR_CMD",&ActuatorCmdHandler::actuator_cmd_Callback,&handler);
	while(true)
	{
	        talker.publish("ACTUATOR_CMD",&actuator_cmd);
		listener.handle();
	}
	return 0;
}
<commit_msg> <commit_after>#include <ros/ros.h>
#include <gazebo_msgs/ApplyJointEffort.h>
#include <urdf/model.h>
#include <urdf_interface/joint.h>
#include <cstdlib>
#include <sys/time.h>
#include <time.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/Twist.h>
#include <atlas_gazebo_msgs/RobotState.h>
#include <lcm/lcm-cpp.hpp>
#include <lcmtypes/drc_lcmtypes.hpp>
#include <atlas_gazebo_msgs/ActuatorCmd.h>

double getTime_now()
{
	struct timeval tv;
	gettimeofday (&tv,NULL);
	return (int64_t) tv.tv_sec*1000000+tv.tv_usec;
}

class ActuatorCmdHandler{
	private:
		ros::Publisher actuator_cmd_pub;
	public:
	ActuatorCmdHandler()
	{
		//ros::init(argc,argv,"actuator_cmd_publisher");
		ros::NodeHandle actuator_cmd_node;
		actuator_cmd_pub = actuator_cmd_node.advertise<atlas_gazebo_msgs::ActuatorCmd>("actuator_cmd",10);
	}
	void actuator_cmd_Callback(const lcm::ReceiveBuffer* rbuf,const std::string &channel,const drc::actuator_cmd_t* msg)//what is rbuf and channel here?
	{
		atlas_gazebo_msgs::ActuatorCmd actuator_cmd_msg;
                long t = msg->timestamp*1000; // from usec to nsec
		actuator_cmd_msg.header.stamp.fromNSec(t);
		actuator_cmd_msg.robot_name = msg->robot_name;
		//actuator_cmd_msg.joint_name = new string[msg.num_joints];
		//actuator_cmd_msg.joint_effort = new float[msg.num_joints]
		for(std::vector<int>::size_type i=0;i!=msg->joint_name.size();i++){//So varaibles in lcm message are all in vector type
			actuator_cmd_msg.joint_name.push_back(msg->joint_name.at(i));
			actuator_cmd_msg.joint_effort.push_back(msg->joint_effort.at(i));
		}
		if(ros::ok())
		{
			actuator_cmd_pub.publish(actuator_cmd_msg);
			ros::spinOnce();
		}
		//delete[] actuator_cmd_msg.joint_name;
		//delete[] actuator_cmd_msg.joint_effort;
	}
};

int main(int argc,char** argv)
{
	ros::init(argc,argv,"actuator_cmd_publisher");
	lcm::LCM talker;
	if(!talker.good())
		return 1;
	drc::actuator_cmd_t actuator_cmd;
	actuator_cmd.timestamp = 0;
	actuator_cmd.robot_name = "atlas";
	actuator_cmd.num_joints = 2;
	actuator_cmd.joint_name.push_back("hip");
	actuator_cmd.joint_name.push_back("neck");
	actuator_cmd.joint_effort.push_back(0.0);
	actuator_cmd.joint_effort.push_back(1.0);
	lcm::LCM listener;
	ActuatorCmdHandler handler;
	listener.subscribe("ACTUATOR_CMDS",&ActuatorCmdHandler::actuator_cmd_Callback,&handler);
	while(true)
	{
	        talker.publish("ACTUATOR_CMDS",&actuator_cmd);
		listener.handle();
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "Tetris/States/GameState.hpp"

#include <iostream>
#include <sstream>
#include <iomanip>

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Text.hpp>

#include "Tetris/App.hpp"
#include "Tetris/Utils.hpp"
#include "Tetris/Game/Tetris.hpp"
#include "Tetris/GameObjects/Tetromino.hpp"
#include "Tetris/GameObjects/GameArea.hpp"
#include "Tetris/GameObjects/GameMenu.hpp"

using namespace tetris::game;

namespace tetris {
namespace states {

struct GameState::Impl {
    tetris::game::Tetris world{};
    tetris::gameobjects::Tetromino tetrominoObject{};
    tetris::gameobjects::Tetromino nextTetrominoObject{};
    tetris::gameobjects::GameArea gameAreaObject{};
    tetris::gameobjects::GameMenu gameMenu{};

    sf::Sprite gridSprite{};
    sf::RectangleShape gameAreaShape{};
    sf::RectangleShape backgroundShape{};
    sf::RectangleShape nextShape{};

    sf::Text highScoreText{};
    sf::Text highScoreValueText{};
    sf::Text scoreText{};
    sf::Text scoreValueText{};
    sf::Text nextText{};
    std::array<sf::Text, 3> infoText{};

    sf::Color defaultFontColor{255, 255, 255};
    sf::Color backgroundShapeColor{254,127,45};
    sf::Color gameAreaShapeColor{253,226,154};
    sf::Color nextShapeColor{252,202,70};
    int defaultFontSize{28};
    int uiCenterPosition{448};
    sf::Vector2f aux{};

    sf::Clock clock{};
    float deltaTime{0.0f};
    bool paused{false};
    bool restart{false};
};

GameState::GameState(App& app)
    : DefaultState(app) {}
GameState::~GameState() = default;

void GameState::create() {
    using namespace tetris::utils;

    impl_ = std::make_unique<Impl>();

    auto& app = getApp();
    auto& assets = app.getAssets();

    auto& defaultFont = assets.getDefaultFont();

    impl_->gridSprite.setTexture(assets.getGrid());

    impl_->gameAreaShape.setSize({
        App::TILE_SIZE * Tetris::WORLD_WIDTH,
        App::TILE_SIZE * Tetris::WORLD_HEIGHT
    });
    impl_->gameAreaShape.setPosition(0, 0);
    impl_->gameAreaShape.setFillColor(impl_->gameAreaShapeColor);

    impl_->backgroundShape.setSize({
        App::WINDOW_WIDTH, App::WINDOW_HEIGHT
    });
    impl_->backgroundShape.setPosition(0, 0);
    impl_->backgroundShape.setFillColor(impl_->backgroundShapeColor);

    impl_->nextShape.setSize({128, 128});
    impl_->nextShape.setPosition(384, App::TILE_SIZE*13);
    impl_->nextShape.setFillColor(impl_->nextShapeColor);

    setupGameMenu();
    setupScores();

    int infoTextSize = static_cast<int>(impl_->infoText.size());
    int infoTextBaseY = 240;
    for (int i = 0; i < infoTextSize; ++i) {
        auto& text = impl_->infoText[i];
        text.setFont(defaultFont);
        text.setCharacterSize(impl_->defaultFontSize);
        text.setFillColor(impl_->defaultFontColor);
        switch (i) {
            case 0:
                text.setString("Press");
                break;
            case 1:
                text.setString("Enter to");
                break;
            case 2:
                text.setString("menu");
                break;
        }
        impl_->aux = tetris::utils::calculateCenterOfRect(
                text.getLocalBounds());
        text.setOrigin(impl_->aux);
        text.setPosition(impl_->uiCenterPosition, infoTextBaseY + 32 * i);
    }

    impl_->nextText.setFont(defaultFont);
    impl_->nextText.setCharacterSize(impl_->defaultFontSize);
    impl_->nextText.setFillColor(impl_->defaultFontColor);
    impl_->nextText.setString("NEXT");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->nextText.getLocalBounds());
    impl_->nextText.setOrigin(impl_->aux);
    impl_->nextText.setPosition(impl_->uiCenterPosition, 400);

    auto& eraseLinesSound = assets.getEraseLinesSound();
    impl_->world.linesErasedCallback = [&] () {
        eraseLinesSound.play();
    };
    auto& fitTetrominoSound = assets.getFitTetrominoSound();
    impl_->world.placedTetrominoCallback = [&] () {
        fitTetrominoSound.play();
    };

    setupBlockRenderers();
    impl_->world.create();
}

void GameState::destroy() {
    impl_->world.destroy();
}

void GameState::restart() {
    destroy();
    create();
}

void GameState::beginTick() {
    impl_->deltaTime = impl_->clock.restart().asSeconds();
}

void GameState::processEvent(const sf::Event& event) {
    DefaultState::processEvent(event);

    if (event.type == sf::Event::KeyPressed) {
        if (event.key.code == sf::Keyboard::Left) {
            impl_->world.setInputMovement(Tetris::InputDirection::LEFT);

            auto& moveSound = getApp().getAssets().getMoveTetrominoSound();
            moveSound.play();
        } else if (event.key.code == sf::Keyboard::Right) {
            impl_->world.setInputMovement(Tetris::InputDirection::RIGHT);

            auto& moveSound = getApp().getAssets().getMoveTetrominoSound();
            moveSound.play();
        }
        if (event.key.code == sf::Keyboard::Z) {
            impl_->world.setInputRotation(Tetris::InputDirection::LEFT);

            auto& rotateSound = getApp().getAssets().getRotateTetrominoSound();
            rotateSound.play();
        } else if (event.key.code == sf::Keyboard::X) {
            impl_->world.setInputRotation(Tetris::InputDirection::RIGHT);

            auto& rotateSound = getApp().getAssets().getRotateTetrominoSound();
            rotateSound.play();
        }
        if (event.key.code == sf::Keyboard::Return) {
            if (impl_->paused) {
                enum { RESUME, RETRY, QUIT };
                int selected = impl_->gameMenu.getSelected();
                switch (selected) {
                    case RETRY:
                        impl_->restart = true;
                        break;
                    case QUIT:
                        getApp().exit();
                        break;
                }
            } else {
                auto& menuOpenSound = getApp().getAssets().getMenuOpenSound();
                menuOpenSound.play();
            }

            impl_->paused = !impl_->paused;
            impl_->gameMenu.setActive(impl_->paused);
        }
        if (impl_->paused) {
            if (event.key.code == sf::Keyboard::Up) {
                impl_->gameMenu.previous();
            } else if (event.key.code == sf::Keyboard::Down) {
                impl_->gameMenu.next();
            }
        }
    }
}

void GameState::update() {
    if (!impl_->paused) {
        impl_->world.setFastFall(sf::Keyboard::isKeyPressed(sf::Keyboard::Down));
        impl_->world.update(impl_->deltaTime);
    }
}

void GameState::render(sf::RenderTarget& renderTarget) {
    renderTarget.draw(impl_->backgroundShape);
    renderTarget.draw(impl_->gameAreaShape);
    renderTarget.draw(impl_->gridSprite);
    renderTarget.draw(impl_->nextShape);
    renderTarget.draw(impl_->highScoreText);
    renderTarget.draw(impl_->highScoreValueText);
    renderTarget.draw(impl_->scoreText);
    renderTarget.draw(impl_->scoreValueText);
    for (auto& info : impl_->infoText) {
        renderTarget.draw(info);
    }
    renderTarget.draw(impl_->nextText);

    renderTarget.draw(impl_->tetrominoObject);
    renderTarget.draw(impl_->nextTetrominoObject);
    renderTarget.draw(impl_->gameAreaObject);
    renderTarget.draw(impl_->gameMenu);
}

void GameState::endTick() {
    if (impl_->restart) {
        restart();
    }
}

void GameState::setupGameMenu() {
    auto& defaultFont = getApp().getAssets().getDefaultFont();

    impl_->gameMenu.setOptions({"RESUME", "RETRY", "QUIT"});
    impl_->gameMenu.setFont(defaultFont);
    impl_->gameMenu.setCharacterSize(impl_->defaultFontSize);
    impl_->gameMenu.setWidth(App::TILE_SIZE*5);
    impl_->gameMenu.setPadding(App::TILE_SIZE / 2.0f, App::TILE_SIZE / 2.0f,
                               App::TILE_SIZE / 2.0f, App::TILE_SIZE / 2.0f);
    impl_->gameMenu.setLineSpacing(impl_->defaultFontSize/2);
    impl_->gameMenu.setBackgroundColor(impl_->backgroundShapeColor);
    impl_->gameMenu.setForegroundColor(impl_->defaultFontColor);
    impl_->gameMenu.setSelectColor(impl_->nextShapeColor);
    impl_->gameMenu.setPosition({5*App::TILE_SIZE, 9*App::TILE_SIZE});
    impl_->gameMenu.create();
    impl_->gameMenu.setActive(false);
}

void GameState::setupScores() {
    auto& assets = getApp().getAssets();
    auto& defaultFont = assets.getDefaultFont();

    impl_->highScoreText.setFont(defaultFont);
    impl_->highScoreText.setCharacterSize(impl_->defaultFontSize);
    impl_->highScoreText.setFillColor(impl_->defaultFontColor);
    impl_->highScoreText.setString("HI-SCORE");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->highScoreText.getLocalBounds());
    impl_->highScoreText.setOrigin(impl_->aux);
    impl_->highScoreText.setPosition(impl_->uiCenterPosition, 49);

    impl_->highScoreValueText.setFont(defaultFont);
    impl_->highScoreValueText.setCharacterSize(impl_->defaultFontSize);
    impl_->highScoreValueText.setFillColor(impl_->defaultFontColor);
    impl_->highScoreValueText.setString("00000000");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->highScoreValueText.getLocalBounds());
    impl_->highScoreValueText.setOrigin(impl_->aux);
    impl_->highScoreValueText.setPosition(impl_->uiCenterPosition, 80);

    impl_->scoreText.setFont(defaultFont);
    impl_->scoreText.setCharacterSize(impl_->defaultFontSize);
    impl_->scoreText.setFillColor(impl_->defaultFontColor);
    impl_->scoreText.setString("SCORE");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->scoreText.getLocalBounds());
    impl_->scoreText.setOrigin(impl_->aux);
    impl_->scoreText.setPosition(impl_->uiCenterPosition, 112);

    impl_->scoreValueText.setFont(defaultFont);
    impl_->scoreValueText.setCharacterSize(impl_->defaultFontSize);
    impl_->scoreValueText.setFillColor(impl_->defaultFontColor);
    impl_->scoreValueText.setString("00000000");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->scoreValueText.getLocalBounds());
    impl_->scoreValueText.setOrigin(impl_->aux);
    impl_->scoreValueText.setPosition(impl_->uiCenterPosition, 144);

    impl_->world.scoreUpdatedCallback = [&] (const int score) {
        std::ostringstream buf;
        buf << std::setfill('0') << std::setw(8);
        buf << score;
        impl_->scoreValueText.setString(buf.str());
    };
    impl_->world.highScoreUpdatedCallback = [&] (const int highScore) {
        std::ostringstream buf;
        buf << std::setfill('0') << std::setw(8);
        buf << highScore;
        impl_->highScoreValueText.setString(buf.str());
    };
}

void GameState::setupBlockRenderers() {
    auto& blockTexture = getApp().getAssets().getBlock();

    impl_->tetrominoObject.create(blockTexture);
    impl_->world.tetrominoUpdatedCallback = [&] (const Tetromino& tetromino) {
        impl_->tetrominoObject.updateTetromino(tetromino);
    };

    impl_->nextTetrominoObject.create(blockTexture);
    impl_->nextTetrominoObject.setPosition(416, 480);
    impl_->world.nextTetrominoCallback = [&] (const Tetromino& tetromino) {
        impl_->nextTetrominoObject.updateTetromino(tetromino);
    };

    impl_->gameAreaObject.create(blockTexture);
    impl_->world.worldUpdatedCallback = [&] (const Tetris::WorldBlockArray& blocks) {
        impl_->gameAreaObject.updateWorld(blocks);
    };
}

} /* namespace states */
} /* namespace tetris */
<commit_msg>Add game over sound<commit_after>#include "Tetris/States/GameState.hpp"

#include <iostream>
#include <sstream>
#include <iomanip>

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Text.hpp>

#include "Tetris/App.hpp"
#include "Tetris/Utils.hpp"
#include "Tetris/Game/Tetris.hpp"
#include "Tetris/GameObjects/Tetromino.hpp"
#include "Tetris/GameObjects/GameArea.hpp"
#include "Tetris/GameObjects/GameMenu.hpp"

using namespace tetris::game;

namespace tetris {
namespace states {

struct GameState::Impl {
    tetris::game::Tetris world{};
    tetris::gameobjects::Tetromino tetrominoObject{};
    tetris::gameobjects::Tetromino nextTetrominoObject{};
    tetris::gameobjects::GameArea gameAreaObject{};
    tetris::gameobjects::GameMenu gameMenu{};

    sf::Sprite gridSprite{};
    sf::RectangleShape gameAreaShape{};
    sf::RectangleShape backgroundShape{};
    sf::RectangleShape nextShape{};

    sf::Text highScoreText{};
    sf::Text highScoreValueText{};
    sf::Text scoreText{};
    sf::Text scoreValueText{};
    sf::Text nextText{};
    std::array<sf::Text, 3> infoText{};

    sf::Color defaultFontColor{255, 255, 255};
    sf::Color backgroundShapeColor{254,127,45};
    sf::Color gameAreaShapeColor{253,226,154};
    sf::Color nextShapeColor{252,202,70};
    int defaultFontSize{28};
    int uiCenterPosition{448};
    sf::Vector2f aux{};

    sf::Clock clock{};
    float deltaTime{0.0f};
    bool paused{false};
    bool restart{false};
};

GameState::GameState(App& app)
    : DefaultState(app) {}
GameState::~GameState() = default;

void GameState::create() {
    using namespace tetris::utils;

    impl_ = std::make_unique<Impl>();

    auto& app = getApp();
    auto& assets = app.getAssets();

    auto& defaultFont = assets.getDefaultFont();

    impl_->gridSprite.setTexture(assets.getGrid());

    impl_->gameAreaShape.setSize({
        App::TILE_SIZE * Tetris::WORLD_WIDTH,
        App::TILE_SIZE * Tetris::WORLD_HEIGHT
    });
    impl_->gameAreaShape.setPosition(0, 0);
    impl_->gameAreaShape.setFillColor(impl_->gameAreaShapeColor);

    impl_->backgroundShape.setSize({
        App::WINDOW_WIDTH, App::WINDOW_HEIGHT
    });
    impl_->backgroundShape.setPosition(0, 0);
    impl_->backgroundShape.setFillColor(impl_->backgroundShapeColor);

    impl_->nextShape.setSize({128, 128});
    impl_->nextShape.setPosition(384, App::TILE_SIZE*13);
    impl_->nextShape.setFillColor(impl_->nextShapeColor);

    setupGameMenu();
    setupScores();

    int infoTextSize = static_cast<int>(impl_->infoText.size());
    int infoTextBaseY = 240;
    for (int i = 0; i < infoTextSize; ++i) {
        auto& text = impl_->infoText[i];
        text.setFont(defaultFont);
        text.setCharacterSize(impl_->defaultFontSize);
        text.setFillColor(impl_->defaultFontColor);
        switch (i) {
            case 0:
                text.setString("Press");
                break;
            case 1:
                text.setString("Enter to");
                break;
            case 2:
                text.setString("menu");
                break;
        }
        impl_->aux = tetris::utils::calculateCenterOfRect(
                text.getLocalBounds());
        text.setOrigin(impl_->aux);
        text.setPosition(impl_->uiCenterPosition, infoTextBaseY + 32 * i);
    }

    impl_->nextText.setFont(defaultFont);
    impl_->nextText.setCharacterSize(impl_->defaultFontSize);
    impl_->nextText.setFillColor(impl_->defaultFontColor);
    impl_->nextText.setString("NEXT");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->nextText.getLocalBounds());
    impl_->nextText.setOrigin(impl_->aux);
    impl_->nextText.setPosition(impl_->uiCenterPosition, 400);

    auto& eraseLinesSound = assets.getEraseLinesSound();
    impl_->world.linesErasedCallback = [&] () {
        eraseLinesSound.play();
    };
    auto& fitTetrominoSound = assets.getFitTetrominoSound();
    impl_->world.placedTetrominoCallback = [&] () {
        fitTetrominoSound.play();
    };

    auto& gameOverSound = assets.getGameOverSound();
    impl_->world.gameOverCallback = [&] (Tetris& tetris) {
        gameOverSound.play();
    };

    setupBlockRenderers();
    impl_->world.create();
}

void GameState::destroy() {
    impl_->world.destroy();
}

void GameState::restart() {
    destroy();
    create();
}

void GameState::beginTick() {
    impl_->deltaTime = impl_->clock.restart().asSeconds();
}

void GameState::processEvent(const sf::Event& event) {
    DefaultState::processEvent(event);

    if (event.type == sf::Event::KeyPressed) {
        if (event.key.code == sf::Keyboard::Left) {
            impl_->world.setInputMovement(Tetris::InputDirection::LEFT);

            auto& moveSound = getApp().getAssets().getMoveTetrominoSound();
            moveSound.play();
        } else if (event.key.code == sf::Keyboard::Right) {
            impl_->world.setInputMovement(Tetris::InputDirection::RIGHT);

            auto& moveSound = getApp().getAssets().getMoveTetrominoSound();
            moveSound.play();
        }
        if (event.key.code == sf::Keyboard::Z) {
            impl_->world.setInputRotation(Tetris::InputDirection::LEFT);

            auto& rotateSound = getApp().getAssets().getRotateTetrominoSound();
            rotateSound.play();
        } else if (event.key.code == sf::Keyboard::X) {
            impl_->world.setInputRotation(Tetris::InputDirection::RIGHT);

            auto& rotateSound = getApp().getAssets().getRotateTetrominoSound();
            rotateSound.play();
        }
        if (event.key.code == sf::Keyboard::Return) {
            if (impl_->paused) {
                enum { RESUME, RETRY, QUIT };
                int selected = impl_->gameMenu.getSelected();
                switch (selected) {
                    case RETRY:
                        impl_->restart = true;
                        break;
                    case QUIT:
                        getApp().exit();
                        break;
                }
            } else {
                auto& menuOpenSound = getApp().getAssets().getMenuOpenSound();
                menuOpenSound.play();
            }

            impl_->paused = !impl_->paused;
            impl_->gameMenu.setActive(impl_->paused);
        }
        if (impl_->paused) {
            if (event.key.code == sf::Keyboard::Up) {
                impl_->gameMenu.previous();
            } else if (event.key.code == sf::Keyboard::Down) {
                impl_->gameMenu.next();
            }
        }
    }
}

void GameState::update() {
    if (!impl_->paused) {
        impl_->world.setFastFall(sf::Keyboard::isKeyPressed(sf::Keyboard::Down));
        impl_->world.update(impl_->deltaTime);
    }
}

void GameState::render(sf::RenderTarget& renderTarget) {
    renderTarget.draw(impl_->backgroundShape);
    renderTarget.draw(impl_->gameAreaShape);
    renderTarget.draw(impl_->gridSprite);
    renderTarget.draw(impl_->nextShape);
    renderTarget.draw(impl_->highScoreText);
    renderTarget.draw(impl_->highScoreValueText);
    renderTarget.draw(impl_->scoreText);
    renderTarget.draw(impl_->scoreValueText);
    for (auto& info : impl_->infoText) {
        renderTarget.draw(info);
    }
    renderTarget.draw(impl_->nextText);

    renderTarget.draw(impl_->tetrominoObject);
    renderTarget.draw(impl_->nextTetrominoObject);
    renderTarget.draw(impl_->gameAreaObject);
    renderTarget.draw(impl_->gameMenu);
}

void GameState::endTick() {
    if (impl_->restart) {
        restart();
    }
}

void GameState::setupGameMenu() {
    auto& defaultFont = getApp().getAssets().getDefaultFont();

    impl_->gameMenu.setOptions({"RESUME", "RETRY", "QUIT"});
    impl_->gameMenu.setFont(defaultFont);
    impl_->gameMenu.setCharacterSize(impl_->defaultFontSize);
    impl_->gameMenu.setWidth(App::TILE_SIZE*5);
    impl_->gameMenu.setPadding(App::TILE_SIZE / 2.0f, App::TILE_SIZE / 2.0f,
                               App::TILE_SIZE / 2.0f, App::TILE_SIZE / 2.0f);
    impl_->gameMenu.setLineSpacing(impl_->defaultFontSize/2);
    impl_->gameMenu.setBackgroundColor(impl_->backgroundShapeColor);
    impl_->gameMenu.setForegroundColor(impl_->defaultFontColor);
    impl_->gameMenu.setSelectColor(impl_->nextShapeColor);
    impl_->gameMenu.setPosition({5*App::TILE_SIZE, 9*App::TILE_SIZE});
    impl_->gameMenu.create();
    impl_->gameMenu.setActive(false);
}

void GameState::setupScores() {
    auto& assets = getApp().getAssets();
    auto& defaultFont = assets.getDefaultFont();

    impl_->highScoreText.setFont(defaultFont);
    impl_->highScoreText.setCharacterSize(impl_->defaultFontSize);
    impl_->highScoreText.setFillColor(impl_->defaultFontColor);
    impl_->highScoreText.setString("HI-SCORE");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->highScoreText.getLocalBounds());
    impl_->highScoreText.setOrigin(impl_->aux);
    impl_->highScoreText.setPosition(impl_->uiCenterPosition, 49);

    impl_->highScoreValueText.setFont(defaultFont);
    impl_->highScoreValueText.setCharacterSize(impl_->defaultFontSize);
    impl_->highScoreValueText.setFillColor(impl_->defaultFontColor);
    impl_->highScoreValueText.setString("00000000");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->highScoreValueText.getLocalBounds());
    impl_->highScoreValueText.setOrigin(impl_->aux);
    impl_->highScoreValueText.setPosition(impl_->uiCenterPosition, 80);

    impl_->scoreText.setFont(defaultFont);
    impl_->scoreText.setCharacterSize(impl_->defaultFontSize);
    impl_->scoreText.setFillColor(impl_->defaultFontColor);
    impl_->scoreText.setString("SCORE");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->scoreText.getLocalBounds());
    impl_->scoreText.setOrigin(impl_->aux);
    impl_->scoreText.setPosition(impl_->uiCenterPosition, 112);

    impl_->scoreValueText.setFont(defaultFont);
    impl_->scoreValueText.setCharacterSize(impl_->defaultFontSize);
    impl_->scoreValueText.setFillColor(impl_->defaultFontColor);
    impl_->scoreValueText.setString("00000000");
    impl_->aux = tetris::utils::calculateCenterOfRect(
            impl_->scoreValueText.getLocalBounds());
    impl_->scoreValueText.setOrigin(impl_->aux);
    impl_->scoreValueText.setPosition(impl_->uiCenterPosition, 144);

    impl_->world.scoreUpdatedCallback = [&] (const int score) {
        std::ostringstream buf;
        buf << std::setfill('0') << std::setw(8);
        buf << score;
        impl_->scoreValueText.setString(buf.str());
    };
    impl_->world.highScoreUpdatedCallback = [&] (const int highScore) {
        std::ostringstream buf;
        buf << std::setfill('0') << std::setw(8);
        buf << highScore;
        impl_->highScoreValueText.setString(buf.str());
    };
}

void GameState::setupBlockRenderers() {
    auto& blockTexture = getApp().getAssets().getBlock();

    impl_->tetrominoObject.create(blockTexture);
    impl_->world.tetrominoUpdatedCallback = [&] (const Tetromino& tetromino) {
        impl_->tetrominoObject.updateTetromino(tetromino);
    };

    impl_->nextTetrominoObject.create(blockTexture);
    impl_->nextTetrominoObject.setPosition(416, 480);
    impl_->world.nextTetrominoCallback = [&] (const Tetromino& tetromino) {
        impl_->nextTetrominoObject.updateTetromino(tetromino);
    };

    impl_->gameAreaObject.create(blockTexture);
    impl_->world.worldUpdatedCallback = [&] (const Tetris::WorldBlockArray& blocks) {
        impl_->gameAreaObject.updateWorld(blocks);
    };
}

} /* namespace states */
} /* namespace tetris */
<|endoftext|>


<commit_before>//==============================================================================
// Kdpartition
//
// @description: Program for printing out a set of (x,y) points in the order
//    they are visited during an in-order traversal of the kd-tree
// @author: Elisha Lai
// @version: 0.0.1 19/11/2015
//==============================================================================

// Kdpartition program (kdpartition.cpp)

#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

// Stores the string representations of split directions
string splitDirections[] = {"Vertical", "Horizontal"};

// Returns the index of the selected pivot using the median
// of medians algorithm
int choosePivot(vector< pair<pair<int, int>, int> > &points) {
   if (points.size() <= 5) {
      return points[(points.size() / 2)].second;
   } else {
      const int m = ((points.size() / 5) - 1);

      // Creates a vector of medians from vectors of 5 points
      vector< pair< pair<int, int>, int> > medians;
      for (int i = 0; i <= m; i++) {
   	     // Creates a vector of 5 points
         vector< pair<pair<int, int>, int> > pointsGroup;
         for (int j = (5 * i); (j < ((5 * i) + 5)) && (j < points.size()); j++) {
            pointsGroup.push_back(points[j]);
         } // for

         // Stores the median of the vector of 5 points
         medians.push_back(pointsGroup[(pointsGroup.size() / 2)]);
      } // for

      return medians[(medians.size() / 2)].second;
   } // if
} // choosePivot

// Partitions a vector of points by their x-coordinates
int verticalPartition(vector< pair<int, int> > &points, int p) {
   swap(points[0], points[p]);
   int i = 0;
   int j = (points.size() - 1);

   while (true) {
      while ((i < points.size()) && (points[i].first <= points[0].first)) {
         i++;
      } // while

      while ((j >= 1) && (points[j].first > points[0].first)) {
         j--;
      } // while

      if (j < i) {
   	     break;
      } else {
         swap(points[i], points[j]);
      } // if
   } // while

   swap(points[0], points[j]);
   return j;
} // verticalPartition

// Partitions a vector of points by their y-coordinates
int horizontalPartition(vector< pair<int, int> > &points, int p) {
   swap(points[0], points[p]);
   int i = 0;
   int j = (points.size() - 1);

   while (true) {
      while ((i < points.size()) && (points[i].second <= points[0].second)) {
         i++;
      } // while

      while ((j >= 1) && (points[j].second > points[0].second)) {
         j--;
      } // while

      if (j < i) {
   	     break;
      } else {
         swap(points[i], points[j]);
      } // if
   } // while

   swap(points[0], points[j]);
   return j;
} // horizontalPartition

// Returns the point in position k of the sorted vector of points
// according to split direction
pair<int, int> quickSelect(vector< pair<int, int> > &points,
	                         int k, string splitDirection) {
   // Creates a vector of points with their corresponding index
   vector< pair<pair<int, int>, int> > pointsWithIndex;
   for (int i = 0; i < points.size(); i++) {
      pointsWithIndex.push_back(make_pair(points[i],i));
   } // for

   const int p = choosePivot(pointsWithIndex);
   const int i = (splitDirection == "Vertical")?
      verticalPartition(points, p): horizontalPartition(points, p);

   if (i == k) {
      return points[i];
   } else if (i > k) {
      vector< pair<int, int> > leftPoints;
      for (int n = 0; n < i; n++) {
         leftPoints.push_back(points[n]);
      } // for

      return quickSelect(leftPoints, k, splitDirection);
   } else {
   	  vector< pair<int, int> > rightPoints;
   	  for (int n = (i + 1); n < points.size(); n++) {
   	  	 rightPoints.push_back(points[n]);
   	  } // for

   	  return quickSelect(rightPoints, (k - i - 1), splitDirection);
   } // if
} // quickSelect

// Prints out points in the order they are visited during an in-order
// traversal of the kd-tree
void kdPartition(vector< pair<int, int> > &points, int depth) {
   if (points.size() == 0) {
   	  return;
   } else {

      string splitDirection = splitDirections[(depth % 2)];
      pair<int, int> medianPoint = quickSelect(points, points.size() / 2, splitDirection);
      vector< pair<int, int> > leftSubtreePartition;
      vector< pair<int, int> > rightSubtreePartition;

      if (splitDirection == "Vertical") {

   	     // Partitions the points into the left and right subtree
   	     for (int i = 0; i < points.size(); i++) {
   	  	    if (points[i].first == medianPoint.first) {
   	  	 	     if (points[i].second == medianPoint.second) {
   	  	 	        continue;
   	  	 	     } else {
                  leftSubtreePartition.push_back(points[i]);
   	  	 	     } // if
   	  	    } else if (points[i].first < medianPoint.first) {
               leftSubtreePartition.push_back(points[i]);
   	  	    } else {
               rightSubtreePartition.push_back(points[i]);
   	  	    } // if
   	     } // for

      } else {

         // Partitions the points into the left and right subtree
         for (int i = 0; i < points.size(); i++) {
      	    if (points[i].second == medianPoint.second) {
      	 	     if (points[i].first == medianPoint.first) {
      	 	        continue;
      	 	     } else {
      	 	        leftSubtreePartition.push_back(points[i]);
      	 	     } // if
      	    } else if (points[i].second < medianPoint.second) {
      	 	     leftSubtreePartition.push_back(points[i]);
      	    } else {
      	 	     rightSubtreePartition.push_back(points[i]);
      	    } // if
         } // for

      } // if

      kdPartition(leftSubtreePartition, (depth + 1));
      cout << ' ' << medianPoint.first << ' ' << medianPoint.second;
      kdPartition(rightSubtreePartition, (depth + 1));
   } // if
} // kdPartition

int main() {
   int n = 0; // Stores the number of points
   cin >> n;

   // Reads in a vector of points
   vector< pair<int, int> > points;
   for (int i = 0; i < n; ++i) {
      int xCoord = 0;
      int yCoord = 0;
      cin >> xCoord >> yCoord;
      points.push_back(make_pair(xCoord, yCoord));
   } // for

   kdPartition(points, 0);
} // main
<commit_msg>Update kdpartition.cpp<commit_after>//==============================================================================
// Kd-tree Partition
//
// @description: Program for printing out a set of (x,y) points in the order
//    they are visited during an in-order traversal of the kd-tree
// @author: Elisha Lai
// @version: 0.0.1 19/11/2015
//==============================================================================

// Kdpartition program (kdpartition.cpp)

#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

// Stores the string representations of split directions
string splitDirections[] = {"Vertical", "Horizontal"};

// Returns the index of the selected pivot using the median
// of medians algorithm
int choosePivot(vector< pair<pair<int, int>, int> > &points) {
   if (points.size() <= 5) {
      return points[(points.size() / 2)].second;
   } else {
      const int m = ((points.size() / 5) - 1);

      // Creates a vector of medians from vectors of 5 points
      vector< pair< pair<int, int>, int> > medians;
      for (int i = 0; i <= m; i++) {
   	     // Creates a vector of 5 points
         vector< pair<pair<int, int>, int> > pointsGroup;
         for (int j = (5 * i); (j < ((5 * i) + 5)) && (j < points.size()); j++) {
            pointsGroup.push_back(points[j]);
         } // for

         // Stores the median of the vector of 5 points
         medians.push_back(pointsGroup[(pointsGroup.size() / 2)]);
      } // for

      return medians[(medians.size() / 2)].second;
   } // if
} // choosePivot

// Partitions a vector of points by their x-coordinates
int verticalPartition(vector< pair<int, int> > &points, int p) {
   swap(points[0], points[p]);
   int i = 0;
   int j = (points.size() - 1);

   while (true) {
      while ((i < points.size()) && (points[i].first <= points[0].first)) {
         i++;
      } // while

      while ((j >= 1) && (points[j].first > points[0].first)) {
         j--;
      } // while

      if (j < i) {
   	     break;
      } else {
         swap(points[i], points[j]);
      } // if
   } // while

   swap(points[0], points[j]);
   return j;
} // verticalPartition

// Partitions a vector of points by their y-coordinates
int horizontalPartition(vector< pair<int, int> > &points, int p) {
   swap(points[0], points[p]);
   int i = 0;
   int j = (points.size() - 1);

   while (true) {
      while ((i < points.size()) && (points[i].second <= points[0].second)) {
         i++;
      } // while

      while ((j >= 1) && (points[j].second > points[0].second)) {
         j--;
      } // while

      if (j < i) {
   	     break;
      } else {
         swap(points[i], points[j]);
      } // if
   } // while

   swap(points[0], points[j]);
   return j;
} // horizontalPartition

// Returns the point in position k of the sorted vector of points
// according to split direction
pair<int, int> quickSelect(vector< pair<int, int> > &points,
	                         int k, string splitDirection) {
   // Creates a vector of points with their corresponding index
   vector< pair<pair<int, int>, int> > pointsWithIndex;
   for (int i = 0; i < points.size(); i++) {
      pointsWithIndex.push_back(make_pair(points[i],i));
   } // for

   const int p = choosePivot(pointsWithIndex);
   const int i = (splitDirection == "Vertical")?
      verticalPartition(points, p): horizontalPartition(points, p);

   if (i == k) {
      return points[i];
   } else if (i > k) {
      vector< pair<int, int> > leftPoints;
      for (int n = 0; n < i; n++) {
         leftPoints.push_back(points[n]);
      } // for

      return quickSelect(leftPoints, k, splitDirection);
   } else {
   	  vector< pair<int, int> > rightPoints;
   	  for (int n = (i + 1); n < points.size(); n++) {
   	  	 rightPoints.push_back(points[n]);
   	  } // for

   	  return quickSelect(rightPoints, (k - i - 1), splitDirection);
   } // if
} // quickSelect

// Prints out points in the order they are visited during an in-order
// traversal of the kd-tree
void kdPartition(vector< pair<int, int> > &points, int depth) {
   if (points.size() == 0) {
   	  return;
   } else {

      string splitDirection = splitDirections[(depth % 2)];
      pair<int, int> medianPoint = quickSelect(points, points.size() / 2, splitDirection);
      vector< pair<int, int> > leftSubtreePartition;
      vector< pair<int, int> > rightSubtreePartition;

      if (splitDirection == "Vertical") {

   	     // Partitions the points into the left and right subtree
   	     for (int i = 0; i < points.size(); i++) {
   	  	    if (points[i].first == medianPoint.first) {
   	  	 	     if (points[i].second == medianPoint.second) {
   	  	 	        continue;
   	  	 	     } else {
                  leftSubtreePartition.push_back(points[i]);
   	  	 	     } // if
   	  	    } else if (points[i].first < medianPoint.first) {
               leftSubtreePartition.push_back(points[i]);
   	  	    } else {
               rightSubtreePartition.push_back(points[i]);
   	  	    } // if
   	     } // for

      } else {

         // Partitions the points into the left and right subtree
         for (int i = 0; i < points.size(); i++) {
      	    if (points[i].second == medianPoint.second) {
      	 	     if (points[i].first == medianPoint.first) {
      	 	        continue;
      	 	     } else {
      	 	        leftSubtreePartition.push_back(points[i]);
      	 	     } // if
      	    } else if (points[i].second < medianPoint.second) {
      	 	     leftSubtreePartition.push_back(points[i]);
      	    } else {
      	 	     rightSubtreePartition.push_back(points[i]);
      	    } // if
         } // for

      } // if

      kdPartition(leftSubtreePartition, (depth + 1));
      cout << ' ' << medianPoint.first << ' ' << medianPoint.second;
      kdPartition(rightSubtreePartition, (depth + 1));
   } // if
} // kdPartition

int main() {
   int n = 0; // Stores the number of points
   cin >> n;

   // Reads in a vector of points
   vector< pair<int, int> > points;
   for (int i = 0; i < n; ++i) {
      int xCoord = 0;
      int yCoord = 0;
      cin >> xCoord >> yCoord;
      points.push_back(make_pair(xCoord, yCoord));
   } // for

   kdPartition(points, 0);
} // main
<|endoftext|>


<commit_before>#include <cstdio>
#include "Environment.h"

Eigen::Vector2f rightWallNormal = Eigen::Vector2f(-1.0, 0.0);

Environment::Environment(int width, int height) {
    m_width = width;
    m_height = height;
}

void Environment::addObject(RigidBody* body) {
    m_objects.push_back(body);
}
void Environment::step(float timeStep) {
    for(std::vector<RigidBody*>::iterator it = m_objects.begin(); it != m_objects.end(); ++it) {
        (*it)->position += (*it)->velocity * timeStep;
        (*it)->velocity += (*it)->acceleration * timeStep;

        // Handle bounds collisions
        if ((*it)->position[0] < 0) {
            (*it)->velocity[0] *= -1;
        } else if ((*it)->position[1] < 0) {
            (*it)->velocity[1] *= -1;
        } else if ((*it)->position[0] + (*it)->size[0] > m_width) {
            (*it)->velocity[0] *= -1;
        } else if ((*it)->position[1] + (*it)->size[1] > m_height) {
            (*it)->velocity[1] *= -1;
        }

        for(std::vector<RigidBody*>::iterator it2 = m_objects.begin(); it2 != m_objects.end(); ++it2) {
            if (*it2 == *it) continue;
            if (circleVsCircle(*it, *it2)) {
                // Collision occured
            }
        }
    }
}

bool Environment::circleVsCircle(RigidBody* a, RigidBody* b) {
    float r = pow(a->radius + b->radius, 2);
    float distance = pow(a->position[0] - b->position[0], 2) + pow(a->position[1] - b->position[1], 2);
    return distance < r;
}
<commit_msg>Optimization to avoid same collision check in frame<commit_after>#include <cstdio>
#include "Environment.h"

Eigen::Vector2f rightWallNormal = Eigen::Vector2f(-1.0, 0.0);

Environment::Environment(int width, int height) {
    m_width = width;
    m_height = height;
}

void Environment::addObject(RigidBody* body) {
    m_objects.push_back(body);
}
void Environment::step(float timeStep) {
    for(std::vector<RigidBody*>::iterator it = m_objects.begin(); it != m_objects.end(); ++it) {
        (*it)->position += (*it)->velocity * timeStep;
        (*it)->velocity += (*it)->acceleration * timeStep;

        // Handle bounds collisions
        if ((*it)->position[0] < 0) {
            (*it)->velocity[0] *= -1;
        } else if ((*it)->position[1] < 0) {
            (*it)->velocity[1] *= -1;
        } else if ((*it)->position[0] + (*it)->size[0] > m_width) {
            (*it)->velocity[0] *= -1;
        } else if ((*it)->position[1] + (*it)->size[1] > m_height) {
            (*it)->velocity[1] *= -1;
        }

        for(std::vector<RigidBody*>::iterator it2 = it; it2 != m_objects.end(); ++it2) {
            if (*it2 == *it) continue;
            if (circleVsCircle(*it, *it2)) {
                // Collision occured
            }
        }
    }
}

bool Environment::circleVsCircle(RigidBody* a, RigidBody* b) {
    float r = pow(a->radius + b->radius, 2);
    float distance = pow(a->position[0] - b->position[0], 2) + pow(a->position[1] - b->position[1], 2);
    return distance < r;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thread>

#include <folly/Baton.h>
#include <folly/experimental/observer/SimpleObservable.h>
#include <folly/portability/GTest.h>

using namespace folly::observer;

TEST(Observer, Observable) {
  SimpleObservable<int> observable(42);
  auto observer = observable.getObserver();

  EXPECT_EQ(42, **observer);

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(24, **observer);
}

TEST(Observer, MakeObserver) {
  SimpleObservable<int> observable(42);

  auto observer = makeObserver([child = observable.getObserver()]() {
    return **child + 1;
  });

  EXPECT_EQ(43, **observer);

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(25, **observer);
}

TEST(Observer, MakeObserverDiamond) {
  SimpleObservable<int> observable(42);

  auto observer1 = makeObserver([child = observable.getObserver()]() {
    return **child + 1;
  });

  auto observer2 = makeObserver([child = observable.getObserver()]() {
    return std::make_shared<int>(**child + 2);
  });

  auto observer = makeObserver(
      [observer1, observer2]() { return (**observer1) * (**observer2); });

  EXPECT_EQ(43 * 44, *observer.getSnapshot());

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(25 * 26, **observer);
}

TEST(Observer, CreateException) {
  struct ExpectedException {};
  EXPECT_THROW(
      auto observer = makeObserver(
          []() -> std::shared_ptr<int> { throw ExpectedException(); }),
      ExpectedException);

  EXPECT_THROW(
      auto observer =
          makeObserver([]() -> std::shared_ptr<int> { return nullptr; }),
      std::logic_error);
}

TEST(Observer, NullValue) {
  SimpleObservable<int> observable(41);
  auto oddObserver = makeObserver([innerObserver = observable.getObserver()]() {
    auto value = **innerObserver;

    if (value % 2 != 0) {
      return value * 2;
    }

    throw std::logic_error("I prefer odd numbers");
  });

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([oddObserver, &baton]() {
    *oddObserver;
    baton.post();
    return folly::Unit();
  });

  baton.reset();
  EXPECT_EQ(82, **oddObserver);

  observable.setValue(2);

  // Waiting observer shouldn't be updated
  EXPECT_FALSE(baton.timed_wait(std::chrono::seconds{1}));
  baton.reset();

  EXPECT_EQ(82, **oddObserver);

  observable.setValue(23);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(46, **oddObserver);
}

TEST(Observer, Cycle) {
  SimpleObservable<int> observable(0);
  auto observer = observable.getObserver();
  folly::Optional<Observer<int>> observerB;

  auto observerA = makeObserver([observer, &observerB]() {
    auto value = **observer;
    if (value == 1) {
      **observerB;
    }
    return value;
  });

  observerB = makeObserver([observerA]() { return **observerA; });

  auto collectObserver = makeObserver([observer, observerA, &observerB]() {
    auto value = **observer;
    auto valueA = **observerA;
    auto valueB = ***observerB;

    if (value == 1) {
      if (valueA == 0) {
        EXPECT_EQ(0, valueB);
      } else {
        EXPECT_EQ(1, valueA);
        EXPECT_EQ(0, valueB);
      }
    } else if (value == 2) {
      EXPECT_EQ(value, valueA);
      EXPECT_TRUE(valueB == 0 || valueB == 2);
    } else {
      EXPECT_EQ(value, valueA);
      EXPECT_EQ(value, valueB);
    }

    return value;
  });

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([collectObserver, &baton]() {
    *collectObserver;
    baton.post();
    return folly::Unit();
  });

  baton.reset();
  EXPECT_EQ(0, **collectObserver);

  for (size_t i = 1; i <= 3; ++i) {
    observable.setValue(i);

    EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));
    baton.reset();

    EXPECT_EQ(i, **collectObserver);
  }
}

TEST(Observer, Stress) {
  SimpleObservable<int> observable(0);

  folly::Synchronized<std::vector<int>> values;

  auto observer = makeObserver([ child = observable.getObserver(), &values ]() {
    auto value = **child * 10;
    values.withWLock(
        [&](std::vector<int>& values) { values.push_back(value); });
    return value;
  });

  EXPECT_EQ(0, **observer);
  values.withRLock([](const std::vector<int>& values) {
    EXPECT_EQ(1, values.size());
    EXPECT_EQ(0, values.back());
  });

  constexpr size_t numIters = 10000;

  for (size_t i = 1; i <= numIters; ++i) {
    observable.setValue(i);
  }

  while (**observer != numIters * 10) {
    std::this_thread::yield();
  }

  values.withRLock([numIters = numIters](const std::vector<int>& values) {
    EXPECT_EQ(numIters * 10, values.back());
    EXPECT_LT(values.size(), numIters / 2);

    EXPECT_EQ(0, values[0]);
    EXPECT_EQ(numIters * 10, values.back());

    for (auto value : values) {
      EXPECT_EQ(0, value % 10);
    }

    for (size_t i = 0; i < values.size() - 1; ++i) {
      EXPECT_LE(values[i], values[i + 1]);
    }
  });
}

TEST(Observer, TLObserver) {
  auto createTLObserver = [](int value) {
    return folly::observer::makeTLObserver([=] { return value; });
  };

  auto k =
      std::make_unique<folly::observer::TLObserver<int>>(createTLObserver(42));
  EXPECT_EQ(42, ***k);
  k = std::make_unique<folly::observer::TLObserver<int>>(createTLObserver(41));
  EXPECT_EQ(41, ***k);
}
<commit_msg>Make Observer stress test pass a stress run<commit_after>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thread>

#include <folly/Baton.h>
#include <folly/experimental/observer/SimpleObservable.h>
#include <folly/portability/GTest.h>

using namespace folly::observer;

TEST(Observer, Observable) {
  SimpleObservable<int> observable(42);
  auto observer = observable.getObserver();

  EXPECT_EQ(42, **observer);

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(24, **observer);
}

TEST(Observer, MakeObserver) {
  SimpleObservable<int> observable(42);

  auto observer = makeObserver([child = observable.getObserver()]() {
    return **child + 1;
  });

  EXPECT_EQ(43, **observer);

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(25, **observer);
}

TEST(Observer, MakeObserverDiamond) {
  SimpleObservable<int> observable(42);

  auto observer1 = makeObserver([child = observable.getObserver()]() {
    return **child + 1;
  });

  auto observer2 = makeObserver([child = observable.getObserver()]() {
    return std::make_shared<int>(**child + 2);
  });

  auto observer = makeObserver(
      [observer1, observer2]() { return (**observer1) * (**observer2); });

  EXPECT_EQ(43 * 44, *observer.getSnapshot());

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([observer, &baton]() {
    *observer;
    baton.post();
    return folly::Unit();
  });
  baton.reset();

  observable.setValue(24);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(25 * 26, **observer);
}

TEST(Observer, CreateException) {
  struct ExpectedException {};
  EXPECT_THROW(
      auto observer = makeObserver(
          []() -> std::shared_ptr<int> { throw ExpectedException(); }),
      ExpectedException);

  EXPECT_THROW(
      auto observer =
          makeObserver([]() -> std::shared_ptr<int> { return nullptr; }),
      std::logic_error);
}

TEST(Observer, NullValue) {
  SimpleObservable<int> observable(41);
  auto oddObserver = makeObserver([innerObserver = observable.getObserver()]() {
    auto value = **innerObserver;

    if (value % 2 != 0) {
      return value * 2;
    }

    throw std::logic_error("I prefer odd numbers");
  });

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([oddObserver, &baton]() {
    *oddObserver;
    baton.post();
    return folly::Unit();
  });

  baton.reset();
  EXPECT_EQ(82, **oddObserver);

  observable.setValue(2);

  // Waiting observer shouldn't be updated
  EXPECT_FALSE(baton.timed_wait(std::chrono::seconds{1}));
  baton.reset();

  EXPECT_EQ(82, **oddObserver);

  observable.setValue(23);

  EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));

  EXPECT_EQ(46, **oddObserver);
}

TEST(Observer, Cycle) {
  SimpleObservable<int> observable(0);
  auto observer = observable.getObserver();
  folly::Optional<Observer<int>> observerB;

  auto observerA = makeObserver([observer, &observerB]() {
    auto value = **observer;
    if (value == 1) {
      **observerB;
    }
    return value;
  });

  observerB = makeObserver([observerA]() { return **observerA; });

  auto collectObserver = makeObserver([observer, observerA, &observerB]() {
    auto value = **observer;
    auto valueA = **observerA;
    auto valueB = ***observerB;

    if (value == 1) {
      if (valueA == 0) {
        EXPECT_EQ(0, valueB);
      } else {
        EXPECT_EQ(1, valueA);
        EXPECT_EQ(0, valueB);
      }
    } else if (value == 2) {
      EXPECT_EQ(value, valueA);
      EXPECT_TRUE(valueB == 0 || valueB == 2);
    } else {
      EXPECT_EQ(value, valueA);
      EXPECT_EQ(value, valueB);
    }

    return value;
  });

  folly::Baton<> baton;
  auto waitingObserver = makeObserver([collectObserver, &baton]() {
    *collectObserver;
    baton.post();
    return folly::Unit();
  });

  baton.reset();
  EXPECT_EQ(0, **collectObserver);

  for (size_t i = 1; i <= 3; ++i) {
    observable.setValue(i);

    EXPECT_TRUE(baton.timed_wait(std::chrono::seconds{1}));
    baton.reset();

    EXPECT_EQ(i, **collectObserver);
  }
}

TEST(Observer, Stress) {
  SimpleObservable<int> observable(0);

  auto values = std::make_shared<folly::Synchronized<std::vector<int>>>();

  auto observer = makeObserver([ child = observable.getObserver(), values ]() {
    auto value = **child * 10;
    values->withWLock(
        [&](std::vector<int>& values) { values.push_back(value); });
    return value;
  });

  EXPECT_EQ(0, **observer);
  values->withRLock([](const std::vector<int>& values) {
    EXPECT_EQ(1, values.size());
    EXPECT_EQ(0, values.back());
  });

  constexpr size_t numIters = 10000;

  for (size_t i = 1; i <= numIters; ++i) {
    observable.setValue(i);
  }

  while (**observer != numIters * 10) {
    std::this_thread::yield();
  }

  values->withRLock([numIters = numIters](const std::vector<int>& values) {
    EXPECT_EQ(numIters * 10, values.back());
    EXPECT_LT(values.size(), numIters / 2);

    EXPECT_EQ(0, values[0]);
    EXPECT_EQ(numIters * 10, values.back());

    for (auto value : values) {
      EXPECT_EQ(0, value % 10);
    }

    for (size_t i = 0; i < values.size() - 1; ++i) {
      EXPECT_LE(values[i], values[i + 1]);
    }
  });
}

TEST(Observer, TLObserver) {
  auto createTLObserver = [](int value) {
    return folly::observer::makeTLObserver([=] { return value; });
  };

  auto k =
      std::make_unique<folly::observer::TLObserver<int>>(createTLObserver(42));
  EXPECT_EQ(42, ***k);
  k = std::make_unique<folly::observer::TLObserver<int>>(createTLObserver(41));
  EXPECT_EQ(41, ***k);
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "MaterialPropertyStorage.h"
#include "Material.h"
#include "MaterialData.h"

std::map<std::string, unsigned int> MaterialPropertyStorage::_prop_ids;

/**
 * Shallow copy the material properties
 * @param prop_ids List of IDs with properties to shallow copy
 * @param data Destination data
 * @param data_from Source data
 */
void shallowCopyData(const std::set<unsigned int> & prop_ids,
                     MaterialProperties & data,
                     MaterialProperties & data_from)
{
  for (std::set<unsigned int>::const_iterator it = prop_ids.begin(); it != prop_ids.end(); ++it)
  {
    unsigned int id = *it;
    PropertyValue * prop = data[id];                  // do the look-up just once (OPT)
    PropertyValue * prop_from = data_from[id];        // do the look-up just once (OPT)
    if (prop != NULL && prop_from != NULL)
      prop->shallowCopy(prop_from);
  }
}

MaterialPropertyStorage::MaterialPropertyStorage() :
    _has_stateful_props(false),
    _has_older_prop(false)
{
  _props_elem       = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
  _props_elem_old   = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
  _props_elem_older = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
}

MaterialPropertyStorage::~MaterialPropertyStorage()
{
  delete _props_elem;
  delete _props_elem_old;
  delete _props_elem_older;
}

void
MaterialPropertyStorage::releaseProperties()
{
  HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >::iterator i;
  for (i = _props_elem->begin(); i != _props_elem->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }

  for (i = _props_elem_old->begin(); i != _props_elem_old->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }

  for (i = _props_elem_older->begin(); i != _props_elem_older->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }
}

void
MaterialPropertyStorage::initStatefulProps(MaterialData & material_data, std::vector<Material *> & mats, unsigned int n_qpoints, const Elem & elem, unsigned int side/* = 0*/)
{
  // NOTE: since materials are storing their computed properties in MaterialData class, we need to
  // juggle the memory between MaterialData and MaterialProperyStorage classes

  unsigned int elem_id = elem.id();

  material_data.size(n_qpoints);

  if (props()[elem_id][side].size() == 0) props()[elem_id][side].resize(material_data.props().size());
  if (propsOld()[elem_id][side].size() == 0) propsOld()[elem_id][side].resize(material_data.propsOld().size());
  if (propsOlder()[elem_id][side].size() == 0) propsOlder()[elem_id][side].resize(material_data.propsOlder().size());

  // init properties (allocate memory. etc)
  for (std::set<unsigned int>::const_iterator it = _stateful_props.begin(); it != _stateful_props.end(); ++it)
  {
    unsigned int prop_id = *it;
    // duplicate the stateful property in property storage (all three states - we will reuse the allocated memory there)
    // also allocating the right amount of memory, so we do not have to resize, etc.
    if (props()[elem_id][side][prop_id] == NULL) props()[elem_id][side][prop_id] = material_data.props()[prop_id]->init(n_qpoints);
    if (propsOld()[elem_id][side][prop_id] == NULL) propsOld()[elem_id][side][prop_id] = material_data.propsOld()[prop_id]->init(n_qpoints);
    if (hasOlderProperties())
      if (propsOlder()[elem_id][side][prop_id] == NULL) propsOlder()[elem_id][side][prop_id] = material_data.propsOld()[prop_id]->init(n_qpoints);
  }
  // copy from storage to material data
  swap(material_data, elem, side);
  // run custom init on properties
  for (std::vector<Material *>::iterator it = mats.begin(); it != mats.end(); ++it)
    (*it)->initStatefulProperties(n_qpoints);
  swapBack(material_data, elem, side);
}

void
MaterialPropertyStorage::shift()
{
  if (_has_older_prop)
  {
    // shift the properties back in time and reuse older for current (save reallocations etc.)
    HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> > * tmp = _props_elem_older;
    _props_elem_older = _props_elem_old;
    _props_elem_old = _props_elem;
    _props_elem = tmp;
  }
  else
  {
    std::swap(_props_elem, _props_elem_old);
  }
}

void
MaterialPropertyStorage::swap(MaterialData & material_data, const Elem & elem, unsigned int side)
{
  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

  unsigned int elem_id = elem.id();
  shallowCopyData(_stateful_props, material_data.props(), props()[elem_id][side]);
  shallowCopyData(_stateful_props, material_data.propsOld(), propsOld()[elem_id][side]);
  if (hasOlderProperties())
    shallowCopyData(_stateful_props, material_data.propsOlder(), propsOlder()[elem_id][side]);
}

void
MaterialPropertyStorage::swapBack(MaterialData & material_data, const Elem & elem, unsigned int side)
{
  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

  unsigned int elem_id = elem.id();
  shallowCopyData(_stateful_props, props()[elem_id][side], material_data.props());
  shallowCopyData(_stateful_props, propsOld()[elem_id][side], material_data.propsOld());
  if (hasOlderProperties())
    shallowCopyData(_stateful_props, propsOlder()[elem_id][side], material_data.propsOlder());
}

bool
MaterialPropertyStorage::hasProperty(const std::string & prop_name) const
{
  std::map<std::string, unsigned int>::const_iterator it = _prop_ids.find(prop_name);
  return (it != _prop_ids.end());
}

unsigned int
MaterialPropertyStorage::addProperty (const std::string & prop_name)
{
  unsigned int prop_id = addPropertyId(prop_name);
  _prop_names[prop_id] = prop_name;
  return prop_id;
}

unsigned int
MaterialPropertyStorage::addPropertyOld (const std::string & prop_name)
{
  unsigned int prop_id = addProperty(prop_name);
  _has_stateful_props = true;
  _stateful_props.insert(prop_id);
  return prop_id;
}

unsigned int
MaterialPropertyStorage::addPropertyOlder (const std::string & prop_name)
{
  unsigned int prop_id = addProperty(prop_name);
  _has_stateful_props = true;
  _has_older_prop = true;
  _stateful_props.insert(prop_id);
  return prop_id;
}

unsigned int
MaterialPropertyStorage::getPropertyId (const std::string & prop_name) const
{
  std::map<std::string, unsigned int>::const_iterator it = _prop_ids.find(prop_name);
  if (it == _prop_ids.end())
    mooseError("No property name mapping for '" + prop_name + "'");

  return it->second;
}

unsigned int
MaterialPropertyStorage::addPropertyId (const std::string & prop_name)
{
  std::map<std::string, unsigned int>::iterator it = _prop_ids.find(prop_name);
  if (it == _prop_ids.end())
  {
    unsigned int id = _prop_ids.size();
    _prop_ids[prop_name] = id;
    return id;
  }
  else
    return it->second;
}
<commit_msg>Fixing uninitialized memory error - closes #1355<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "MaterialPropertyStorage.h"
#include "Material.h"
#include "MaterialData.h"

std::map<std::string, unsigned int> MaterialPropertyStorage::_prop_ids;

/**
 * Shallow copy the material properties
 * @param prop_ids List of IDs with properties to shallow copy
 * @param data Destination data
 * @param data_from Source data
 */
void shallowCopyData(const std::set<unsigned int> & prop_ids,
                     MaterialProperties & data,
                     MaterialProperties & data_from)
{
  for (std::set<unsigned int>::const_iterator it = prop_ids.begin(); it != prop_ids.end(); ++it)
  {
    unsigned int id = *it;
    PropertyValue * prop = data[id];                  // do the look-up just once (OPT)
    PropertyValue * prop_from = data_from[id];        // do the look-up just once (OPT)
    if (prop != NULL && prop_from != NULL)
      prop->shallowCopy(prop_from);
  }
}

MaterialPropertyStorage::MaterialPropertyStorage() :
    _has_stateful_props(false),
    _has_older_prop(false)
{
  _props_elem       = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
  _props_elem_old   = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
  _props_elem_older = new HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >;
}

MaterialPropertyStorage::~MaterialPropertyStorage()
{
  delete _props_elem;
  delete _props_elem_old;
  delete _props_elem_older;
}

void
MaterialPropertyStorage::releaseProperties()
{
  HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> >::iterator i;
  for (i = _props_elem->begin(); i != _props_elem->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }

  for (i = _props_elem_old->begin(); i != _props_elem_old->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }

  for (i = _props_elem_older->begin(); i != _props_elem_older->end(); ++i)
  {
    HashMap<unsigned int, MaterialProperties>::iterator j;
    for (j = i->second.begin(); j != i->second.end(); ++j)
      j->second.destroy();
  }
}

void
MaterialPropertyStorage::initStatefulProps(MaterialData & material_data, std::vector<Material *> & mats, unsigned int n_qpoints, const Elem & elem, unsigned int side/* = 0*/)
{
  // NOTE: since materials are storing their computed properties in MaterialData class, we need to
  // juggle the memory between MaterialData and MaterialProperyStorage classes

  unsigned int elem_id = elem.id();

  material_data.size(n_qpoints);

  if (props()[elem_id][side].size() == 0) props()[elem_id][side].resize(material_data.props().size());
  if (propsOld()[elem_id][side].size() == 0) propsOld()[elem_id][side].resize(material_data.propsOld().size());
  if (propsOlder()[elem_id][side].size() == 0) propsOlder()[elem_id][side].resize(material_data.propsOlder().size());

  // init properties (allocate memory. etc)
  for (std::set<unsigned int>::const_iterator it = _stateful_props.begin(); it != _stateful_props.end(); ++it)
  {
    unsigned int prop_id = *it;
    // duplicate the stateful property in property storage (all three states - we will reuse the allocated memory there)
    // also allocating the right amount of memory, so we do not have to resize, etc.
    if (props()[elem_id][side][prop_id] == NULL) props()[elem_id][side][prop_id] = material_data.props()[prop_id]->init(n_qpoints);
    if (propsOld()[elem_id][side][prop_id] == NULL) propsOld()[elem_id][side][prop_id] = material_data.propsOld()[prop_id]->init(n_qpoints);
    if (hasOlderProperties())
      if (propsOlder()[elem_id][side][prop_id] == NULL) propsOlder()[elem_id][side][prop_id] = material_data.propsOld()[prop_id]->init(n_qpoints);
  }
  // copy from storage to material data
  swap(material_data, elem, side);
  // run custom init on properties
  for (std::vector<Material *>::iterator it = mats.begin(); it != mats.end(); ++it)
    (*it)->initStatefulProperties(n_qpoints);
  swapBack(material_data, elem, side);

  if (hasStatefulProperties())
  {
    shift(); // Old
    swap(material_data, elem, side);
    for (std::vector<Material *>::iterator it = mats.begin(); it != mats.end(); ++it)
      (*it)->initStatefulProperties(n_qpoints);
    swapBack(material_data, elem, side);

    if (_has_older_prop)
    {
      shift(); // Older
      swap(material_data, elem, side);
      for (std::vector<Material *>::iterator it = mats.begin(); it != mats.end(); ++it)
        (*it)->initStatefulProperties(n_qpoints);
      swapBack(material_data, elem, side);
    }
  }
}

void
MaterialPropertyStorage::shift()
{
  if (_has_older_prop)
  {
    // shift the properties back in time and reuse older for current (save reallocations etc.)
    HashMap<unsigned int, HashMap<unsigned int, MaterialProperties> > * tmp = _props_elem_older;
    _props_elem_older = _props_elem_old;
    _props_elem_old = _props_elem;
    _props_elem = tmp;
  }
  else
  {
    std::swap(_props_elem, _props_elem_old);
  }
}

void
MaterialPropertyStorage::swap(MaterialData & material_data, const Elem & elem, unsigned int side)
{
  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

  unsigned int elem_id = elem.id();
  shallowCopyData(_stateful_props, material_data.props(), props()[elem_id][side]);
  shallowCopyData(_stateful_props, material_data.propsOld(), propsOld()[elem_id][side]);
  if (hasOlderProperties())
    shallowCopyData(_stateful_props, material_data.propsOlder(), propsOlder()[elem_id][side]);
}

void
MaterialPropertyStorage::swapBack(MaterialData & material_data, const Elem & elem, unsigned int side)
{
  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

  unsigned int elem_id = elem.id();
  shallowCopyData(_stateful_props, props()[elem_id][side], material_data.props());
  shallowCopyData(_stateful_props, propsOld()[elem_id][side], material_data.propsOld());
  if (hasOlderProperties())
    shallowCopyData(_stateful_props, propsOlder()[elem_id][side], material_data.propsOlder());
}

bool
MaterialPropertyStorage::hasProperty(const std::string & prop_name) const
{
  std::map<std::string, unsigned int>::const_iterator it = _prop_ids.find(prop_name);
  return (it != _prop_ids.end());
}

unsigned int
MaterialPropertyStorage::addProperty (const std::string & prop_name)
{
  unsigned int prop_id = addPropertyId(prop_name);
  _prop_names[prop_id] = prop_name;
  return prop_id;
}

unsigned int
MaterialPropertyStorage::addPropertyOld (const std::string & prop_name)
{
  unsigned int prop_id = addProperty(prop_name);
  _has_stateful_props = true;
  _stateful_props.insert(prop_id);
  return prop_id;
}

unsigned int
MaterialPropertyStorage::addPropertyOlder (const std::string & prop_name)
{
  unsigned int prop_id = addProperty(prop_name);
  _has_stateful_props = true;
  _has_older_prop = true;
  _stateful_props.insert(prop_id);
  return prop_id;
}

unsigned int
MaterialPropertyStorage::getPropertyId (const std::string & prop_name) const
{
  std::map<std::string, unsigned int>::const_iterator it = _prop_ids.find(prop_name);
  if (it == _prop_ids.end())
    mooseError("No property name mapping for '" + prop_name + "'");

  return it->second;
}

unsigned int
MaterialPropertyStorage::addPropertyId (const std::string & prop_name)
{
  std::map<std::string, unsigned int>::iterator it = _prop_ids.find(prop_name);
  if (it == _prop_ids.end())
  {
    unsigned int id = _prop_ids.size();
    _prop_ids[prop_name] = id;
    return id;
  }
  else
    return it->second;
}
<|endoftext|>


<commit_before>// Fill out your copyright notice in the Description page of Project Settings.

#include "UE4_TurnBased.h"
#include "TB_PlayerController.h"
#include "TB_GameMode.h"

ATB_GameMode::ATB_GameMode(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	PlayerControllerClass = ATB_PlayerController::StaticClass();
}

<commit_msg>set TB_GameState as the default gamestate<commit_after>// Fill out your copyright notice in the Description page of Project Settings.

#include "UE4_TurnBased.h"
#include "TB_PlayerController.h"
#include "TB_GameState.h"

#include "TB_GameMode.h"

ATB_GameMode::ATB_GameMode(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	PlayerControllerClass = ATB_PlayerController::StaticClass();
	GameStateClass = ATB_GameState::StaticClass();
}

<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/slaveproc.h>

using vespalib::SlaveProc;

TEST("simple run, ignore output") {
    EXPECT_TRUE(SlaveProc::run("echo foo"));
}

TEST("simple run, ignore output, failure") {
    EXPECT_TRUE(!SlaveProc::run("false"));
}

TEST("simple run, ignore output, timeout") {
    EXPECT_TRUE(!SlaveProc::run("exec sleep 60", 10));
}

TEST("simple run") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("echo -n foo", out));
#ifdef __APPLE__
    EXPECT_EQUAL(out, "-n foo");
#else
    EXPECT_EQUAL(out, "foo");
#endif
}

TEST("simple run, strip single-line trailing newline") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("echo foo", out));
    EXPECT_EQUAL(out, "foo");
}

TEST("simple run, don't strip multi-line output") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("perl -e 'print \"foo\\n\\n\"'", out));
    EXPECT_EQUAL(out, "foo\n\n");
}

TEST("simple run with input") {
    std::string in = "bar";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL(out, "bar");
}

TEST("simple run with input, strip single-line trailing newline") {
    std::string in = "bar\n";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL(out, "bar");
}

TEST("simple run with input, don't strip multi-line output") {
    std::string in = "bar\n\n";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL("bar\n\n", out);
}

TEST_MT("simple run, partial output due to timeout", 2) {
    std::string out;
    std::vector<size_t> timeouts({150, 300, 3000, 6000, 60000});
    const char *my_cmd = "exec perl -e '$| = 1; print \"foo\\\n\"; sleep(600); print \"bar\\\n\"'";
    for (size_t timeout: timeouts) {
        fprintf(stderr, "... verifying partial output with%s input (timeout = %zu)\n",
                (thread_id == 0) ? "out" : "", timeout);
        if (thread_id == 0) {
            out.clear();
            EXPECT_TRUE(!SlaveProc::run(my_cmd, out, timeout));
        } else {
            out.clear();
            std::string in = "ignored\n";
            EXPECT_TRUE(!SlaveProc::run(in, my_cmd, out, timeout));
        }
        if (out == "foo") {
            break;
        }
    }
    EXPECT_EQUAL(out, "foo");
}

TEST("proc failure") {
    SlaveProc proc("false");
    // read with length 0 will wait for output
    EXPECT_TRUE(proc.read(NULL, 0) == 0);
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(proc.failed());
}

TEST("basic read/write") {
    int x;
    int read;
    char buf[64];
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo", 3));
    for (x = 0, read = 0; x < 10 && read < 3; ++x) {
        read += proc.read(buf + read, sizeof(buf) - read);
    }
    EXPECT_TRUE(read == 3 && memcmp(buf, "foo", 3) == 0);
    EXPECT_TRUE(proc.write("bar!", 4));
    for (x = 0, read = 0; x < 10 && read < 4; ++x) {
        read += proc.read(buf + read, sizeof(buf) - read);
    }
    EXPECT_TRUE(read == 4 && memcmp(buf, "bar!", 4) == 0);
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("continuos run, readLine") {
    std::string str;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo\n", 4));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "foo");
    EXPECT_TRUE(proc.write("bar!\n", 5));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "bar!");
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("readLine, eof flushes last line") {
    std::string str;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo\n", 4));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "foo");
    EXPECT_TRUE(proc.write("bar!", 4));
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "bar!");
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("long continuos run, readLine") {
    std::string in;
    std::string out;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    for (uint32_t i = 0; i < 10000; ++i) {
        char num[32];
        sprintf(num, "%d", i);
        in.assign("long continous run, line ");
        in.append(num).append("\n");
        EXPECT_TRUE(proc.write(in.data(), in.length()));
        in.erase(in.size() - 1, 1);
        EXPECT_TRUE(proc.readLine(out));
        EXPECT_EQUAL(in, out);
    }
    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
<commit_msg>Don't use shell builtin echo.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/slaveproc.h>

using vespalib::SlaveProc;

TEST("simple run, ignore output") {
    EXPECT_TRUE(SlaveProc::run("echo foo"));
}

TEST("simple run, ignore output, failure") {
    EXPECT_TRUE(!SlaveProc::run("false"));
}

TEST("simple run, ignore output, timeout") {
    EXPECT_TRUE(!SlaveProc::run("exec sleep 60", 10));
}

TEST("simple run") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("/bin/echo -n foo", out));
    EXPECT_EQUAL(out, "foo");
}

TEST("simple run, strip single-line trailing newline") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("echo foo", out));
    EXPECT_EQUAL(out, "foo");
}

TEST("simple run, don't strip multi-line output") {
    std::string out;
    EXPECT_TRUE(SlaveProc::run("perl -e 'print \"foo\\n\\n\"'", out));
    EXPECT_EQUAL(out, "foo\n\n");
}

TEST("simple run with input") {
    std::string in = "bar";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL(out, "bar");
}

TEST("simple run with input, strip single-line trailing newline") {
    std::string in = "bar\n";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL(out, "bar");
}

TEST("simple run with input, don't strip multi-line output") {
    std::string in = "bar\n\n";
    std::string out;
    EXPECT_TRUE(SlaveProc::run(in, "cat", out));
    EXPECT_EQUAL("bar\n\n", out);
}

TEST_MT("simple run, partial output due to timeout", 2) {
    std::string out;
    std::vector<size_t> timeouts({150, 300, 3000, 6000, 60000});
    const char *my_cmd = "exec perl -e '$| = 1; print \"foo\\\n\"; sleep(600); print \"bar\\\n\"'";
    for (size_t timeout: timeouts) {
        fprintf(stderr, "... verifying partial output with%s input (timeout = %zu)\n",
                (thread_id == 0) ? "out" : "", timeout);
        if (thread_id == 0) {
            out.clear();
            EXPECT_TRUE(!SlaveProc::run(my_cmd, out, timeout));
        } else {
            out.clear();
            std::string in = "ignored\n";
            EXPECT_TRUE(!SlaveProc::run(in, my_cmd, out, timeout));
        }
        if (out == "foo") {
            break;
        }
    }
    EXPECT_EQUAL(out, "foo");
}

TEST("proc failure") {
    SlaveProc proc("false");
    // read with length 0 will wait for output
    EXPECT_TRUE(proc.read(NULL, 0) == 0);
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(proc.failed());
}

TEST("basic read/write") {
    int x;
    int read;
    char buf[64];
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo", 3));
    for (x = 0, read = 0; x < 10 && read < 3; ++x) {
        read += proc.read(buf + read, sizeof(buf) - read);
    }
    EXPECT_TRUE(read == 3 && memcmp(buf, "foo", 3) == 0);
    EXPECT_TRUE(proc.write("bar!", 4));
    for (x = 0, read = 0; x < 10 && read < 4; ++x) {
        read += proc.read(buf + read, sizeof(buf) - read);
    }
    EXPECT_TRUE(read == 4 && memcmp(buf, "bar!", 4) == 0);
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("continuos run, readLine") {
    std::string str;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo\n", 4));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "foo");
    EXPECT_TRUE(proc.write("bar!\n", 5));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "bar!");
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("readLine, eof flushes last line") {
    std::string str;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    EXPECT_TRUE(proc.write("foo\n", 4));
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "foo");
    EXPECT_TRUE(proc.write("bar!", 4));
    EXPECT_TRUE(!proc.eof());  // not eof yet
    EXPECT_TRUE(proc.close()); // close stdin
    EXPECT_TRUE(!proc.eof());  // eof not detected yet
    EXPECT_TRUE(proc.readLine(str));
    EXPECT_EQUAL(str, "bar!");
    EXPECT_TRUE(proc.eof());
    EXPECT_TRUE(!proc.readLine(str));
    EXPECT_EQUAL(str, "");
    EXPECT_TRUE(proc.wait(60000));
    EXPECT_TRUE(!proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST("long continuos run, readLine") {
    std::string in;
    std::string out;
    SlaveProc proc("cat");

    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
    for (uint32_t i = 0; i < 10000; ++i) {
        char num[32];
        sprintf(num, "%d", i);
        in.assign("long continous run, line ");
        in.append(num).append("\n");
        EXPECT_TRUE(proc.write(in.data(), in.length()));
        in.erase(in.size() - 1, 1);
        EXPECT_TRUE(proc.readLine(out));
        EXPECT_EQUAL(in, out);
    }
    EXPECT_TRUE(proc.running());
    EXPECT_TRUE(!proc.failed());
}

TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
<|endoftext|>