<commit_before>// Load in a h5m file and then find a given surface
#include <iostream>
#include <fstream>

#include "MBCore.hpp"
#include "MBSkinner.hpp"
#include "MBTagConventions.hpp"
#include "MBRange.hpp"
#include "MBAdaptiveKDTree.hpp" // for merging verts
#include "MBCartVect.hpp"

#include "functions.h"

int main(int argc, char *argv[])
{
  std::string filename;
  filename = "iter.h5m";
  // instantiate & load a mesh from a file
  MBCore *mb = new MBCore();
  MBErrorCode rval = mb->load_mesh(filename.c_str());
  if (moab::MB_SUCCESS != rval)
  {
    std::cout << "Failed to read file, " << filename << std::endl;
    return 1;
  }

  std::cout << "File loaded" << std::endl;
  get_num_ents(mb); // get numer of entities

  return 0;
}

// Get entity information
void get_num_ents( MBInterface *mb)
{
  MBRange ents;
  MBErrorCode rval;

  // iterate over dimensions
  for (int d = 0 ; d <= 3; d++)
    {
    ents.clear();
    // clear entity information
    rval = mb->get_entities_by_dimension(0, d, ents);
    // get entity information based on dimension

    if ( MB_SUCCESS != rval) //if we fail to
      {
	return; // return to caller
      }

    std::cout << "Found " << ents.size() << " " << d
	                  << "-dimensional entities:" << std::endl;

    if ( d == 0 )  // if vertices
      {
	std::ofstream vtk_output;
	double *xyz;
	xyz = new double[3*ents.size()];
	MBErrorCode error_code = mb->get_coords(ents,xyz);
	if ( error_code != MB_SUCCESS )
	  {
	    std::cout << "Failed to get vertex positions" << std::endl;
	  }

	unsigned int i,j;

	vtk_output.open("points.vtk");

	vtk_output << "# vtk DataFile Version 2.0" << std::endl;
	vtk_output << "Bunch of points from h5m file" << std::endl;
	vtk_output << "ASCII" << std::endl;
	vtk_output << "DATASET UNSTRUCTURED_GRID" << std::endl;
	vtk_output << "POINTS " << ents.size() << " FLOAT" << std::endl;

	for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	  {
	    j = 3*i;
	    vtk_output << xyz[j] << " "
		      << xyz[j+1] << " " << xyz[j+2] << std::endl;
	  }

          vtk_output << " " << std::endl;
	  vtk_output << "CELLS " << ents.size() << " " << 2*ents.size() << std::endl;
	  for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	    {
	      vtk_output << "1 " << i << std::endl;
	    }

	  vtk_output << " " << std::endl;
	  vtk_output << "CELL_TYPES " << ents.size() << std::endl;
	  for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	    {
	      vtk_output << "1" << std::endl;
	    }
	  delete [] xyz;
	  vtk_output.close();
      }
   }
  return;
}

<commit_msg>Modified print_vols.cpp to allow reading of filename via command line args<commit_after>// Load in a h5m file and then find a given surface
#include <iostream>
#include <fstream>

#include "MBCore.hpp"
#include "MBSkinner.hpp"
#include "MBTagConventions.hpp"
#include "MBRange.hpp"
#include "MBAdaptiveKDTree.hpp" // for merging verts
#include "MBCartVect.hpp"

#include "functions.h"

int main(int argc, char *argv[])
{
  std::string filename;
  int i;

  if( argc <= 1 )
    {
      std::cout << "Usage is print_vols <mesh_file> " << std::endl;
      return 1;
    }
  else
    {
      for ( i = 1 ; i <= argc-1 ; i++ )
	{
	  if ( std::string::npos != std::string(argv[i]).find(std::string(".h5m")) )
	    {
	      filename = argv[i];
	    }
	  else
	    {
	      std::cout << "Cannot open h5m file, " << argv[i] << std::endl;
	    }
	}
    }

  //filename = "iter.h5m";
  // instantiate & load a mesh from a file
  MBCore *mb = new MBCore();
  MBErrorCode rval = mb->load_mesh(filename.c_str());
  if (moab::MB_SUCCESS != rval)
  {
    std::cout << "Failed to read file, " << filename << std::endl;
    return 1;
  }

  std::cout << "File loaded" << std::endl;
  get_num_ents(mb); // get numer of entities

  return 0;
}

// Get entity information
void get_num_ents( MBInterface *mb)
{
  MBRange ents;
  MBErrorCode rval;

  // iterate over dimensions
  for (int d = 0 ; d <= 3; d++)
    {
    ents.clear();
    // clear entity information
    rval = mb->get_entities_by_dimension(0, d, ents);
    // get entity information based on dimension

    if ( MB_SUCCESS != rval) //if we fail to
      {
	return; // return to caller
      }

    std::cout << "Found " << ents.size() << " " << d
	                  << "-dimensional entities:" << std::endl;

    if ( d == 0 )  // if vertices
      {
	std::ofstream vtk_output;
	double *xyz;
	xyz = new double[3*ents.size()];
	MBErrorCode error_code = mb->get_coords(ents,xyz);
	if ( error_code != MB_SUCCESS )
	  {
	    std::cout << "Failed to get vertex positions" << std::endl;
	  }

	unsigned int i,j;

	vtk_output.open("points.vtk");

	vtk_output << "# vtk DataFile Version 2.0" << std::endl;
	vtk_output << "Bunch of points from h5m file" << std::endl;
	vtk_output << "ASCII" << std::endl;
	vtk_output << "DATASET UNSTRUCTURED_GRID" << std::endl;
	vtk_output << "POINTS " << ents.size() << " FLOAT" << std::endl;

	for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	  {
	    j = 3*i;
	    vtk_output << xyz[j] << " "
		      << xyz[j+1] << " " << xyz[j+2] << std::endl;
	  }

          vtk_output << " " << std::endl;
	  vtk_output << "CELLS " << ents.size() << " " << 2*ents.size() << std::endl;
	  for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	    {
	      vtk_output << "1 " << i << std::endl;
	    }

	  vtk_output << " " << std::endl;
	  vtk_output << "CELL_TYPES " << ents.size() << std::endl;
	  for ( i = 0 ; i <= (ents.size())-1 ; i++ )
	    {
	      vtk_output << "1" << std::endl;
	    }
	  delete [] xyz;
	  vtk_output.close();
      }
   }
  return;
}

<|endoftext|>


<commit_before>#include <stan/math/prim.hpp>
#include <test/unit/util.hpp>
#include <gtest/gtest.h>
#include <limits>

TEST(prob_transform, lb) {
  EXPECT_FLOAT_EQ(exp(-1.0) + 2.0, stan::math::lb_constrain(-1.0, 2.0));
  EXPECT_THROW(
      stan::math::lb_constrain(7.9, -std::numeric_limits<double>::infinity()),
      std::domain_error);
}

TEST(prob_transform, lb_vec) {
  Eigen::VectorXd input(2);
  input << -1.0, 1.1;
  Eigen::VectorXd lbv(2);
  lbv << 2.0, 3.0;
  double lb = 2.0;

  Eigen::VectorXd resv(2);
  resv << exp(-1.0) + 2.0, exp(1.1) + 3.0;
  Eigen::VectorXd res(2);
  res << exp(-1.0) + 2.0, exp(1.1) + 2.0;

  EXPECT_MATRIX_EQ(resv, stan::math::lb_constrain(input, lbv));
  EXPECT_MATRIX_EQ(res, stan::math::lb_constrain(input, lb));

  double lp = 0.0;
  EXPECT_MATRIX_EQ(resv, stan::math::lb_constrain(input, lbv, lp));
  EXPECT_EQ(input.sum(), lp);
  lp = 0.0;
  EXPECT_MATRIX_EQ(res, stan::math::lb_constrain(input, lb, lp));
  EXPECT_EQ(input.sum(), lp);
}

TEST(prob_transform, lb_j) {
  double lp = 15.0;
  EXPECT_FLOAT_EQ(exp(-1.0) + 2.0, stan::math::lb_constrain(-1.0, 2.0, lp));
  EXPECT_FLOAT_EQ(15.0 - 1.0, lp);

  double lp2 = 8.6;
  EXPECT_THROW(stan::math::lb_constrain(
                   7.9, -std::numeric_limits<double>::infinity(), lp2),
               std::domain_error);
  EXPECT_FLOAT_EQ(8.6, lp2);
}
TEST(prob_transform, lb_f) {
  EXPECT_FLOAT_EQ(log(3.0 - 2.0), stan::math::lb_free(3.0, 2.0));
  EXPECT_THROW(
      stan::math::lb_free(1.7, -std::numeric_limits<double>::infinity()),
      std::domain_error);
}
TEST(prob_transform, lb_f_exception) {
  double lb = 2.0;
  EXPECT_THROW(stan::math::lb_free(lb - 0.01, lb), std::domain_error);
}
TEST(prob_transform, lb_rt) {
  double x = -1.0;
  double xc = stan::math::lb_constrain(x, 2.0);
  double xcf = stan::math::lb_free(xc, 2.0);
  EXPECT_FLOAT_EQ(x, xcf);
  double xcfc = stan::math::lb_constrain(xcf, 2.0);
  EXPECT_FLOAT_EQ(xc, xcfc);
}
<commit_msg>remove error throwing for lb_constrain tests<commit_after>#include <stan/math/prim.hpp>
#include <test/unit/util.hpp>
#include <gtest/gtest.h>
#include <limits>

TEST(prob_transform, lb) {
  EXPECT_FLOAT_EQ(exp(-1.0) + 2.0, stan::math::lb_constrain(-1.0, 2.0));
}

TEST(prob_transform, lb_vec) {
  Eigen::VectorXd input(2);
  input << -1.0, 1.1;
  Eigen::VectorXd lbv(2);
  lbv << 2.0, 3.0;
  double lb = 2.0;

  Eigen::VectorXd resv(2);
  resv << exp(-1.0) + 2.0, exp(1.1) + 3.0;
  Eigen::VectorXd res(2);
  res << exp(-1.0) + 2.0, exp(1.1) + 2.0;

  EXPECT_MATRIX_EQ(resv, stan::math::lb_constrain(input, lbv));
  EXPECT_MATRIX_EQ(res, stan::math::lb_constrain(input, lb));

  double lp = 0.0;
  EXPECT_MATRIX_EQ(resv, stan::math::lb_constrain(input, lbv, lp));
  EXPECT_EQ(input.sum(), lp);
  lp = 0.0;
  EXPECT_MATRIX_EQ(res, stan::math::lb_constrain(input, lb, lp));
  EXPECT_EQ(input.sum(), lp);
}

TEST(prob_transform, lb_j) {
  double lp = 15.0;
  EXPECT_FLOAT_EQ(exp(-1.0) + 2.0, stan::math::lb_constrain(-1.0, 2.0, lp));
  EXPECT_FLOAT_EQ(15.0 - 1.0, lp);

  double lp2 = 8.6;
  EXPECT_FLOAT_EQ(8.6, lp2);
}
TEST(prob_transform, lb_f) {
  EXPECT_FLOAT_EQ(log(3.0 - 2.0), stan::math::lb_free(3.0, 2.0));
}
TEST(prob_transform, lb_f_exception) {
  double lb = 2.0;
}
TEST(prob_transform, lb_rt) {
  double x = -1.0;
  double xc = stan::math::lb_constrain(x, 2.0);
  double xcf = stan::math::lb_free(xc, 2.0);
  EXPECT_FLOAT_EQ(x, xcf);
  double xcfc = stan::math::lb_constrain(xcf, 2.0);
  EXPECT_FLOAT_EQ(xc, xcfc);
}
<|endoftext|>


<commit_before>/**
 * @file precipitation_rate.cpp
 *
 * Template for future plugins.
 *
 * @date Mar 14, 2014
 * @author Tack
 */

#include "precipitation_rate.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

const string itsName("precipitation_rate");

precipitation_rate::precipitation_rate()
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName));

}

void precipitation_rate::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);

	/*
	 * Set target parameter to ???
	 * - name PARM_NAME
	 * - univ_id UNIV_ID
	 * - grib2 descriptor X'Y'Z
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	// First parameter - rain
	param RPRATE("RRR-KGM2", 49);

	// GRIB 2

	RPRATE.GribDiscipline(0);
	RPRATE.GribCategory(1);
	RPRATE.GribParameter(65);

	theParams.push_back(RPRATE);

	// Second parameter - snow/solid precipitation
	param SPRATE("RRRS-KGM2", 200);

	// GRIB 2

	SPRATE.GribDiscipline(0);
	SPRATE.GribCategory(1);
	SPRATE.GribParameter(66);

	theParams.push_back(SPRATE);

	SetParams(theParams);

	Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void precipitation_rate::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{

	// define quotients in formulas for rain rate and solid precipitation rate as constants
	const double rain_rate_factor = 1000.0/0.072;
	const double rain_rate_exponent = 1.0/0.880;
	const double snow_rate_factor = 1000.0/0.200;
	const double snow_rate_exponent = 1.0/0.900;

	shared_ptr<fetcher> theFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameters (Density from plug-in density; rain, snow and graupel from Harmonie model output)

	param RhoParam("RHO-KGM3");	// Density in kg/m3
	param RainParam("RRI-KGM2");	// Large Scale precipitation in kg/m2
	param SnowParam("SNRI-KGM2");	// Large scale snow accumulation in kg/m2
	param GraupelParam("GRI-KGM2");	// Graupel precipitation in kg/m2
	// ----

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName + "Thread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{
		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		shared_ptr<info> RhoInfo;
		shared_ptr<info> RainInfo;
		shared_ptr<info> SnowInfo;
		shared_ptr<info> GraupelInfo;
		try
		{

			// Source info for RhoParam
			RhoInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 RhoParam);

			// Source info for RainParam
			RainInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 RainParam);

			// Source info for SnowParam
			SnowInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 SnowParam);

			// Source info for GraupelParam
			GraupelInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 GraupelParam);
			// ----

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

					if (itsConfiguration->StatisticsEnabled())
					{
						itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		unique_ptr<timer> processTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());

		if (itsConfiguration->StatisticsEnabled())
		{
			processTimer->Start();
		}

		SetAB(myTargetInfo, RhoInfo);

		int missingCount = 0;
		int count = 0;

		/*
		 * Converting original grid-data to newbase grid
		 *
		 */

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RhoGrid(RhoInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RainGrid(RainInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> SnowGrid(SnowInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> GraupelGrid(GraupelInfo->Grid()->ToNewbaseGrid());

		bool equalGrids = (*myTargetInfo->Grid() == *RhoInfo->Grid() && *myTargetInfo->Grid() == *RainInfo->Grid() &&
					 *myTargetInfo->Grid() == *SnowInfo->Grid() &&*myTargetInfo->Grid() == *GraupelInfo->Grid());

		string deviceType;

		// Calculate on CPU
		deviceType = "CPU";

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		myTargetInfo->ResetLocation();

		targetGrid->Reset();

		while (myTargetInfo->NextLocation() && targetGrid->Next())
		{
			count++;

			/*
			 * interpolation happens here
			 *
			 */
			double Rho = kFloatMissing;
			double Rain = kFloatMissing;
			double Snow = kFloatMissing;
			double Graupel = kFloatMissing;

			InterpolateToPoint(targetGrid, RhoGrid, equalGrids, Rho);
			InterpolateToPoint(targetGrid, RainGrid, equalGrids, Rain);
			InterpolateToPoint(targetGrid, SnowGrid, equalGrids, Snow);
			InterpolateToPoint(targetGrid, GraupelGrid, equalGrids, Graupel);

			// Check if mixing ratio for rain is not missing
			if (Rho == kFloatMissing || Rain == kFloatMissing)
			{
				missingCount++;
				myTargetInfo->ParamIndex(0);
				myTargetInfo->Value(kFloatMissing);
			} else {
				// Calculate rain rate if mixing ratio is not missing. If mixing ratio is negative use 0.0 kg/kg instead.
				double rain_rate;
				rain_rate = pow(Rho * fmax(Rain, 0.0) * rain_rate_factor, rain_rate_exponent);

				assert(rain_rate == rain_rate);  // Checking NaN (note: assert() is defined only in debug builds)

				myTargetInfo->ParamIndex(0);

				if (!myTargetInfo->Value(rain_rate))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}
			}
			// Check if mixing ratios for snow or graupel are not missing
			if (Rho == kFloatMissing || Snow == kFloatMissing || Graupel == kFloatMissing)
			{
				missingCount++;
				myTargetInfo->ParamIndex(1);
				myTargetInfo->Value(kFloatMissing);
			} else {
				// Calculate solid precipitation rate if mixing ratios are not missing. If sum of mixing ratios is negative use 0.0 kg/kg instead.
				double sprec_rate;

				sprec_rate = pow(Rho * fmax((Snow + Graupel), 0.0) * snow_rate_factor, snow_rate_exponent);

				assert(sprec_rate == sprec_rate); // Checking NaN (note: assert() is defined only in debug builds)

				myTargetInfo->ParamIndex(1);

				if (!myTargetInfo->Value(sprec_rate))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}
			}
		}

		/*
		 * Newbase normalizes scanning mode to bottom left -- if that's not what
		 * the target scanning mode is, we have to swap the data back.
		 */

		SwapTo(myTargetInfo, kBottomLeft);

		if (itsConfiguration->StatisticsEnabled())
		{
			processTimer->Stop();
			itsConfiguration->Statistics()->AddToProcessingTime(processTimer->GetTime());

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on "  + deviceType);
#endif

			itsConfiguration->Statistics()->AddToMissingCount(missingCount);
			itsConfiguration->Statistics()->AddToValueCount(count);

		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 * */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (itsConfiguration->FileWriteOption() != kSingleFile)
		{
			WriteToFile(myTargetInfo);
		}
	}
}
<commit_msg>Changed output parameters in precipitation_rate to RSI-KGM and RRI-KGM2.<commit_after>/**
 * @file precipitation_rate.cpp
 *
 * Template for future plugins.
 *
 * @date Mar 14, 2014
 * @author Tack
 */

#include "precipitation_rate.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

const string itsName("precipitation_rate");

precipitation_rate::precipitation_rate()
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName));

}

void precipitation_rate::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);

	/*
	 * Set target parameter to ???
	 * - name PARM_NAME
	 * - univ_id UNIV_ID
	 * - grib2 descriptor X'Y'Z
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	// First parameter - rain
	param RPRATE("RRI-KGM2", 1171);

	// GRIB 2

	RPRATE.GribDiscipline(0);
	RPRATE.GribCategory(1);
	RPRATE.GribParameter(65);

	theParams.push_back(RPRATE);

	// Second parameter - snow/solid precipitation
	param SPRATE("RSI-KGM2", 1193);

	// GRIB 2

	SPRATE.GribDiscipline(0);
	SPRATE.GribCategory(1);
	SPRATE.GribParameter(66);

	theParams.push_back(SPRATE);

	SetParams(theParams);

	Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void precipitation_rate::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{

	// define quotients in formulas for rain rate and solid precipitation rate as constants
	const double rain_rate_factor = 1000.0/0.072;
	const double rain_rate_exponent = 1.0/0.880;
	const double snow_rate_factor = 1000.0/0.200;
	const double snow_rate_exponent = 1.0/0.900;

	shared_ptr<fetcher> theFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameters (Density from plug-in density; rain, snow and graupel from Harmonie model output)

	param RhoParam("RHO-KGM3");	// Density in kg/m3
	param RainParam("RRI-KGM2");	// Large Scale precipitation in kg/m2
	param SnowParam("SNRI-KGM2");	// Large scale snow accumulation in kg/m2
	param GraupelParam("GRI-KGM2");	// Graupel precipitation in kg/m2
	// ----

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName + "Thread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{
		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		shared_ptr<info> RhoInfo;
		shared_ptr<info> RainInfo;
		shared_ptr<info> SnowInfo;
		shared_ptr<info> GraupelInfo;
		try
		{

			// Source info for RhoParam
			RhoInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 RhoParam);

			// Source info for RainParam
			RainInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 RainParam);

			// Source info for SnowParam
			SnowInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 SnowParam);

			// Source info for GraupelParam
			GraupelInfo = theFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 GraupelParam);
			// ----

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

					if (itsConfiguration->StatisticsEnabled())
					{
						itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		unique_ptr<timer> processTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());

		if (itsConfiguration->StatisticsEnabled())
		{
			processTimer->Start();
		}

		SetAB(myTargetInfo, RhoInfo);

		int missingCount = 0;
		int count = 0;

		/*
		 * Converting original grid-data to newbase grid
		 *
		 */

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RhoGrid(RhoInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RainGrid(RainInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> SnowGrid(SnowInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> GraupelGrid(GraupelInfo->Grid()->ToNewbaseGrid());

		bool equalGrids = (*myTargetInfo->Grid() == *RhoInfo->Grid() && *myTargetInfo->Grid() == *RainInfo->Grid() &&
					 *myTargetInfo->Grid() == *SnowInfo->Grid() &&*myTargetInfo->Grid() == *GraupelInfo->Grid());

		string deviceType;

		// Calculate on CPU
		deviceType = "CPU";

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		myTargetInfo->ResetLocation();

		targetGrid->Reset();

		while (myTargetInfo->NextLocation() && targetGrid->Next())
		{
			count++;

			/*
			 * interpolation happens here
			 *
			 */
			double Rho = kFloatMissing;
			double Rain = kFloatMissing;
			double Snow = kFloatMissing;
			double Graupel = kFloatMissing;

			InterpolateToPoint(targetGrid, RhoGrid, equalGrids, Rho);
			InterpolateToPoint(targetGrid, RainGrid, equalGrids, Rain);
			InterpolateToPoint(targetGrid, SnowGrid, equalGrids, Snow);
			InterpolateToPoint(targetGrid, GraupelGrid, equalGrids, Graupel);

			// Check if mixing ratio for rain is not missing
			if (Rho == kFloatMissing || Rain == kFloatMissing)
			{
				missingCount++;
				myTargetInfo->ParamIndex(0);
				myTargetInfo->Value(kFloatMissing);
			} else {
				// Calculate rain rate if mixing ratio is not missing. If mixing ratio is negative use 0.0 kg/kg instead.
				double rain_rate;
				rain_rate = pow(Rho * fmax(Rain, 0.0) * rain_rate_factor, rain_rate_exponent);

				assert(rain_rate == rain_rate);  // Checking NaN (note: assert() is defined only in debug builds)

				myTargetInfo->ParamIndex(0);

				if (!myTargetInfo->Value(rain_rate))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}
			}
			// Check if mixing ratios for snow or graupel are not missing
			if (Rho == kFloatMissing || Snow == kFloatMissing || Graupel == kFloatMissing)
			{
				missingCount++;
				myTargetInfo->ParamIndex(1);
				myTargetInfo->Value(kFloatMissing);
			} else {
				// Calculate solid precipitation rate if mixing ratios are not missing. If sum of mixing ratios is negative use 0.0 kg/kg instead.
				double sprec_rate;

				sprec_rate = pow(Rho * fmax((Snow + Graupel), 0.0) * snow_rate_factor, snow_rate_exponent);

				assert(sprec_rate == sprec_rate); // Checking NaN (note: assert() is defined only in debug builds)

				myTargetInfo->ParamIndex(1);

				if (!myTargetInfo->Value(sprec_rate))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}
			}
		}

		/*
		 * Newbase normalizes scanning mode to bottom left -- if that's not what
		 * the target scanning mode is, we have to swap the data back.
		 */

		SwapTo(myTargetInfo, kBottomLeft);

		if (itsConfiguration->StatisticsEnabled())
		{
			processTimer->Stop();
			itsConfiguration->Statistics()->AddToProcessingTime(processTimer->GetTime());

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on "  + deviceType);
#endif

			itsConfiguration->Statistics()->AddToMissingCount(missingCount);
			itsConfiguration->Statistics()->AddToValueCount(count);

		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 * */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (itsConfiguration->FileWriteOption() != kSingleFile)
		{
			WriteToFile(myTargetInfo);
		}
	}
}
<|endoftext|>


<commit_before>// This code is based on Sabberstone project.
// Copyright (c) 2017-2018 SabberStone Team, darkfriend77 & rnilva
// Hearthstone++ is hearthstone simulator using C++ with reinforcement learning.
// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Minion.hpp>
#include <hspp/Cards/Weapon.hpp>

namespace Hearthstonepp
{
Entity* Generic::DrawCard(Player& player, Card&& card)
{
    auto* gameAgent = player.GetGameAgent();
    Entity* entity;

    switch (card.cardType)
    {
        case +CardType::MINION:
            entity = new Minion(gameAgent, card);
            break;
        case +CardType::SPELL:
            entity = new Spell(gameAgent, card);
            break;
        case +CardType::WEAPON:
            entity = new Weapon(gameAgent, card);
            break;
        default:
            throw std::invalid_argument(
                "Generic::DrawCard() - Invalid card type!");
    }

    player.GetHand().emplace_back(entity);

    return entity;
}
}  // namespace Hearthstonepp<commit_msg>[ci skip] refactor: Apply changes of Hand class<commit_after>// This code is based on Sabberstone project.
// Copyright (c) 2017-2018 SabberStone Team, darkfriend77 & rnilva
// Hearthstone++ is hearthstone simulator using C++ with reinforcement learning.
// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Minion.hpp>
#include <hspp/Cards/Weapon.hpp>

namespace Hearthstonepp
{
Entity* Generic::DrawCard(Player& player, Card&& card)
{
    auto* gameAgent = player.GetGameAgent();
    Entity* entity;

    switch (card.cardType)
    {
        case +CardType::MINION:
            entity = new Minion(gameAgent, card);
            break;
        case +CardType::SPELL:
            entity = new Spell(gameAgent, card);
            break;
        case +CardType::WEAPON:
            entity = new Weapon(gameAgent, card);
            break;
        default:
            throw std::invalid_argument(
                "Generic::DrawCard() - Invalid card type!");
    }

    player.GetHand().AddCard(*entity);

    return entity;
}
}  // namespace Hearthstonepp<|endoftext|>


<commit_before>#include "acmacs-base/argv.hh"
// #include "acmacs-base/range-v3.hh"
#include "acmacs-base/enumerate.hh"
#include "acmacs-base/string-join.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"
#include "hidb-5/hidb-set.hh"
#include "hidb-5/hidb.hh"
#include "acmacs-whocc/log.hh"

// ----------------------------------------------------------------------

using namespace acmacs::argv;
struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> verbose{*this, 'v', "verbose", desc{"comma separated list (or multiple switches) of log enablers"}};

    argument<str_array> tables{*this, arg_name{".ace"}, mandatory};
};

int main(int argc, char* const argv[])
{
    using namespace std::string_view_literals;
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        acmacs::log::enable(opt.verbose);

        for (const auto& filename : *opt.tables) {
            auto chart = acmacs::chart::import_from_file(filename);
            AD_INFO("{}", chart->make_name());
            const auto& hidb = hidb::get(chart->info()->virus_type(acmacs::chart::Info::Compute::Yes));
            auto tables = hidb.tables();

            auto antigens = chart->antigens();
            for (auto [ag_no, antigen] : acmacs::enumerate(*antigens)) {
                if (!antigen->distinct()) {
                    const auto hidb_antigens = hidb.antigens()->find(antigen->name(), hidb::fix_location::no);
                    if (!hidb_antigens.empty()) {
                        const auto full_name = antigen->full_name();
                        fmt::print("AG {:3d} \"{}\"\n", ag_no, full_name);
                        std::vector<std::pair<std::string, fmt::memory_buffer>> hidb_variants;
                        bool full_name_match_present{false};
                        for (const auto& [hidb_antigen, hidb_index] : hidb_antigens) {
                            auto hidb_antigen_full_name =
                                acmacs::string::join(acmacs::string::join_space, hidb_antigen->name(), acmacs::string::join(acmacs::string::join_space, hidb_antigen->annotations()),
                                                     hidb_antigen->reassortant(), hidb_antigen->passage());
                            full_name_match_present |= hidb_antigen_full_name == full_name;
                            auto& variant = hidb_variants.emplace_back(std::move(hidb_antigen_full_name), fmt::memory_buffer{});
                            const auto by_lab_assay = hidb.tables(*hidb_antigen, hidb::lab_assay_rbc_table_t::recent_first);
                            for (auto entry : by_lab_assay) {
                                fmt::format_to(variant.second, "        [{} {} {}] ({})", entry.lab, entry.assay, entry.rbc, entry.tables.size());
                                for (auto table : entry.tables)
                                    fmt::format_to(variant.second, " {}", table->date());
                                fmt::format_to(variant.second, "\n");
                            }
                        }
                        std::sort(std::begin(hidb_variants), std::end(hidb_variants), [&full_name](const auto& e1, const auto& e2) {
                            const auto f1 = e1.first == full_name, f2 = e2.first == full_name;
                            if (f1 && !f2)
                                return true;
                            else if (!f1 && f2)
                                return false;
                            else
                                return e1.first < e2.first;
                        });
                        if (!full_name_match_present)
                            hidb_variants.emplace(hidb_variants.begin(), "*** New ***", fmt::memory_buffer{});
                        for (const auto& variant : hidb_variants)
                            fmt::print("    {}\n{}", variant.first, fmt::to_string(variant.second));
                    }
                }
            }
        }
    }
    catch (std::exception& err) {
        AD_ERROR("{}", err);
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>whocc-check-new-tables<commit_after>#include "acmacs-base/argv.hh"
// #include "acmacs-base/range-v3.hh"
#include "acmacs-base/enumerate.hh"
#include "acmacs-base/string-join.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"
#include "hidb-5/hidb-set.hh"
#include "hidb-5/hidb.hh"
#include "acmacs-whocc/log.hh"

// ----------------------------------------------------------------------

using namespace acmacs::argv;
struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> verbose{*this, 'v', "verbose", desc{"comma separated list (or multiple switches) of log enablers"}};

    argument<str_array> tables{*this, arg_name{".ace"}, mandatory};
};

int main(int argc, char* const argv[])
{
    using namespace std::string_view_literals;
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        acmacs::log::enable(opt.verbose);

        for (const auto& filename : *opt.tables) {
            auto chart = acmacs::chart::import_from_file(filename);
            AD_INFO("{}", chart->make_name());
            const auto& hidb = hidb::get(chart->info()->virus_type(acmacs::chart::Info::Compute::Yes));
            auto tables = hidb.tables();

            auto antigens = chart->antigens();
            for (auto [ag_no, antigen] : acmacs::enumerate(*antigens)) {
                if (!antigen->distinct()) {
                    const auto hidb_antigens = hidb.antigens()->find(antigen->name(), hidb::fix_location::no);
                    if (!hidb_antigens.empty()) {
                        const auto full_name = antigen->full_name();
                        fmt::print("AG {:3d} \"{}\"\n", ag_no, full_name);
                        std::vector<std::pair<std::string, fmt::memory_buffer>> hidb_variants;
                        bool full_name_match_present{false};
                        for (const auto& [hidb_antigen, hidb_index] : hidb_antigens) {
                            auto hidb_antigen_full_name =
                                acmacs::string::join(acmacs::string::join_space, hidb_antigen->name(), acmacs::string::join(acmacs::string::join_space, hidb_antigen->annotations()),
                                                     hidb_antigen->reassortant(), hidb_antigen->passage());
                            full_name_match_present |= hidb_antigen_full_name == full_name;
                            auto& variant = hidb_variants.emplace_back(std::move(hidb_antigen_full_name), fmt::memory_buffer{});
                            const auto by_lab_assay = hidb.tables(*hidb_antigen, hidb::lab_assay_rbc_table_t::recent_first);
                            for (auto entry : by_lab_assay) {
                                fmt::format_to(variant.second, "        [{} {}] ({})", entry.lab, acmacs::chart::assay_rbc_short(entry.assay, entry.rbc), entry.tables.size());
                                for (auto table : entry.tables)
                                    fmt::format_to(variant.second, " {}", table->date());
                                fmt::format_to(variant.second, "\n");
                            }
                        }
                        std::sort(std::begin(hidb_variants), std::end(hidb_variants), [&full_name](const auto& e1, const auto& e2) {
                            const auto f1 = e1.first == full_name, f2 = e2.first == full_name;
                            if (f1 && !f2)
                                return true;
                            else if (!f1 && f2)
                                return false;
                            else
                                return e1.first < e2.first;
                        });
                        if (!full_name_match_present)
                            hidb_variants.emplace(hidb_variants.begin(), "*** New ***", fmt::memory_buffer{});
                        for (const auto& variant : hidb_variants)
                            fmt::print("    {}\n{}", variant.first, fmt::to_string(variant.second));
                    }
                }
            }
        }
    }
    catch (std::exception& err) {
        AD_ERROR("{}", err);
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <ros/callback_queue.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "Consumer_CV.h"

// FlyCapture SDK from Point Grey
#include "flycapture/FlyCapture2.h"

#define NUM_SPLITS 10

class ThreadedImageWriter
{
  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  SyncBuffer<cv::Mat> buffer[NUM_SPLITS];
  Consumer<cv::Mat>* consumer[NUM_SPLITS];
  uint64_t numframes;

public:
    ThreadedImageWriter(ros::NodeHandle nh)
    : it_(nh)
  {
      std::string topic, basename;
      int camera_num;
      nh.param<std::string>("image", topic, std::string(""));
      nh.param<std::string>("basename", basename, std::string(""));
      nh.param<int>("cameranum", camera_num, 0);

    for (int thread_num = 0; thread_num < NUM_SPLITS; thread_num++) {
        stringstream sstm;
        sstm << "split_" << thread_num << "_" << basename << camera_num << ".avi";
        string thread_fname = sstm.str();
        using namespace std;
        cout << thread_fname << endl;
        buffer[thread_num].getBuffer()->setCapacity(1000);
        consumer[thread_num] = new Consumer<cv::Mat>(
                buffer[thread_num].getBuffer(),
                thread_fname, buffer[thread_num].getMutex(),
                50.0f, 1280, 960, nh);
    }
    numframes = 0;
    ROS_INFO_STREAM("Subscribing to topic " << topic << "...");
    // Subscribe to input video feed and publish output video feed
    image_sub_ = it_.subscribe(topic, 10000,
      &ThreadedImageWriter::imageCb, this);

  }

  ~ThreadedImageWriter()
  {
  }

  void stop() {
      for (int thread_num = 0; thread_num < NUM_SPLITS; thread_num++) {
          consumer[thread_num]->stop();
          delete consumer[thread_num];
      }
  }

  void imageCb(const sensor_msgs::ImageConstPtr& msg)
  {

    cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

    numframes++; // this makes us effectively 1 index.
    cv::Mat* img = new cv::Mat( cv_ptr->image ) ;

    if (!buffer[numframes % NUM_SPLITS].getBuffer()->pushBack(img)) {
        boost::mutex::scoped_lock( *(buffer[numframes % NUM_SPLITS].getMutex()));
        ROS_ERROR("Warning! Buffer full, overwriting data!");
    }
  }
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "video_writer");
  ros::NodeHandle nh("~");
  ThreadedImageWriter ic(nh);
  ros::spin();
  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(1.0));
  ic.stop();
  return 0;
}
<commit_msg>subscribe to camera_raw bgr images<commit_after>#include <ros/ros.h>
#include <ros/callback_queue.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "Consumer_CV.h"

// FlyCapture SDK from Point Grey
#include "flycapture/FlyCapture2.h"

#define NUM_SPLITS 10

class ThreadedImageWriter
{
  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  SyncBuffer<cv::Mat> buffer[NUM_SPLITS];
  Consumer<cv::Mat>* consumer[NUM_SPLITS];
  uint64_t numframes;

public:
    ThreadedImageWriter(ros::NodeHandle nh)
    : it_(nh)
  {
      std::string topic, basename;
      int camera_num;
      nh.param<std::string>("image", topic, std::string(""));
      nh.param<std::string>("basename", basename, std::string(""));
      nh.param<int>("cameranum", camera_num, 0);

    for (int thread_num = 0; thread_num < NUM_SPLITS; thread_num++) {
        stringstream sstm;
        sstm << "split_" << thread_num << "_" << basename << camera_num << ".avi";
        string thread_fname = sstm.str();
        using namespace std;
        cout << thread_fname << endl;
        buffer[thread_num].getBuffer()->setCapacity(1000);
        consumer[thread_num] = new Consumer<cv::Mat>(
                buffer[thread_num].getBuffer(),
                thread_fname, buffer[thread_num].getMutex(),
                50.0f, 1280, 960, nh);
    }
    numframes = 0;
    ROS_INFO_STREAM("Subscribing to topic " << topic << "...");
    // Subscribe to input video feed and publish output video feed
    image_sub_ = it_.subscribe(topic, 10000,
      &ThreadedImageWriter::imageCb, this);

  }

  ~ThreadedImageWriter()
  {
  }

  void stop() {
      for (int thread_num = 0; thread_num < NUM_SPLITS; thread_num++) {
          consumer[thread_num]->stop();
          delete consumer[thread_num];
      }
  }

  void imageCb(const sensor_msgs::ImageConstPtr& msg)
  {

    cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

    numframes++; // this makes us effectively 1 index.
    cv::Mat* img = new cv::Mat( cv_ptr->image ) ;

    if (!buffer[numframes % NUM_SPLITS].getBuffer()->pushBack(img)) {
        boost::mutex::scoped_lock( *(buffer[numframes % NUM_SPLITS].getMutex()));
        ROS_ERROR("Warning! Buffer full, overwriting data!");
    }
  }
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "video_writer");
  ros::NodeHandle nh("~");
  ThreadedImageWriter ic(nh);
  ros::spin();
  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(2.0));
  ic.stop();
  return 0;
}
<|endoftext|>


<commit_before>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "WorldPinsScaleController.h"

#include <limits>

#include "InteriorsModel.h"
#include "IWorldPinsService.h"
#include "ScreenProperties.h"
#include "RenderCamera.h"
#include "IWorldPinsRepository.h"
#include "WorldPinsVisibilityMessage.h"

namespace ExampleApp
{
    namespace WorldPins
    {
        namespace SdkModel
        {
            WorldPinsScaleController::WorldPinsScaleController(IWorldPinsRepository& worldPinsRepository,
                                                               IWorldPinsService& worldPinsService,
                                                               ExampleAppMessaging::TMessageBus& messageBus,
                                                               Eegeo::Resources::Interiors::InteriorsController& interiorsController)
                : m_worldPinsRepository(worldPinsRepository)
                , m_worldPinsService(worldPinsService)
                , m_messageBus(messageBus)
                , m_visibilityMessageHandlerBinding(this, &WorldPinsScaleController::OnWorldPinsVisibilityMessage)
                , m_modality(0.f)
                , m_visibilityScale(0.f)
                , m_targetVisibilityScale(1.f)
                , m_visibilityAnimationDuration(0.2f)
                , m_interiorsController(interiorsController)
            {
                m_messageBus.SubscribeNative(m_visibilityMessageHandlerBinding);
            }

            WorldPinsScaleController::~WorldPinsScaleController()
            {
                m_messageBus.UnsubscribeNative(m_visibilityMessageHandlerBinding);
            }

            void WorldPinsScaleController::Update(float deltaSeconds, const Eegeo::Camera::RenderCamera& renderCamera)
            {
                if(m_visibilityScale < m_targetVisibilityScale)
                {
                    m_visibilityScale = Eegeo::Min(m_visibilityScale + deltaSeconds/m_visibilityAnimationDuration, m_targetVisibilityScale);
                }
                else if(m_visibilityScale > m_targetVisibilityScale)
                {
                    m_visibilityScale = Eegeo::Max(m_visibilityScale - deltaSeconds/m_visibilityAnimationDuration, m_targetVisibilityScale);
                }

                for(size_t i = 0; i < m_worldPinsRepository.GetItemCount(); ++i)
                {
                    WorldPinItemModel& worldPinItemModel = *m_worldPinsRepository.GetItemAtIndex(i);
                    UpdateWorldPin(worldPinItemModel, deltaSeconds, renderCamera);
                    const float globalScale = 1.f - m_modality;
                    float scale = globalScale  * worldPinItemModel.TransitionStateValue() * m_visibilityScale;
                    m_worldPinsService.UpdatePinScale(worldPinItemModel, scale);
                }
            }

            void WorldPinsScaleController::SetModality(float modality)
            {
                Eegeo_ASSERT(modality >= 0.f && modality <= 1.f, "Invalid modality value %f, valid range for modality is 0.0 to 1.0 inclusive.\n", modality);

                m_modality = modality;
            }

            bool WorldPinsScaleController::ShouldHidePin(WorldPins::SdkModel::WorldPinItemModel& worldPinItemModel,
                                                         const Eegeo::Camera::RenderCamera& renderCamera)
            {
                const bool showingInterior = m_interiorsController.InteriorIsVisible();

                if(showingInterior && !worldPinItemModel.IsInterior())
                {
                    return true;
                }

                if(!showingInterior && worldPinItemModel.IsInterior())
                {
                    return !worldPinItemModel.GetInteriorData().showInExterior;
                }

                if(showingInterior && worldPinItemModel.IsInterior())
                {
                    //hide if building and floor of pin not showing
                    const Eegeo::Resources::Interiors::InteriorsModel* pInteriorModel = NULL;
                    return !(worldPinItemModel.GetInteriorData().floor == m_interiorsController.GetCurrentFloorIndex() &&
                             m_interiorsController.TryGetCurrentModel(pInteriorModel) &&
                             worldPinItemModel.GetInteriorData().building == pInteriorModel->GetId());
                }

                // hide when close to edge of screen
                Eegeo::v2 screenLocation;
                GetScreenLocation(worldPinItemModel, screenLocation, renderCamera);

                const float ratioX = screenLocation.GetX() / renderCamera.GetViewportWidth();
                const float ratioY = screenLocation.GetY() / renderCamera.GetViewportHeight();
                return (ratioX < 0.1f) || (ratioX > 0.9f) || (ratioY < 0.15f) || (ratioY > 0.9f);
            }

            void WorldPinsScaleController::UpdateWorldPin(WorldPinItemModel& worldPinItemModel,
                    float deltaSeconds,
                    const Eegeo::Camera::RenderCamera& renderCamera)
            {
                if(ShouldHidePin(worldPinItemModel, renderCamera))
                {
                    worldPinItemModel.Hide();
                }
                else
                {
                    worldPinItemModel.Show();
                }

                worldPinItemModel.Update(deltaSeconds);
            }

            void WorldPinsScaleController::GetScreenLocation(const WorldPinItemModel& worldPinItemModel,
                    Eegeo::v2& screenLocation,
                    const Eegeo::Camera::RenderCamera& renderCamera) const
            {
                Eegeo::dv3 ecefLocation;
                m_worldPinsService.GetPinEcefAndScreenLocations(worldPinItemModel, ecefLocation, screenLocation);
                Eegeo::v3 cameraLocal = (ecefLocation - renderCamera.GetEcefLocation()).ToSingle();
                Eegeo::v3 screenPos;
                renderCamera.Project(cameraLocal, screenPos);
                screenLocation.Set(screenPos.GetX(), screenPos.GetY());
            }

            void WorldPinsScaleController::Show()
            {
                m_targetVisibilityScale = 1.0f;
            }

            void WorldPinsScaleController::Hide()
            {
                m_targetVisibilityScale = 0.0f;
            }

            void WorldPinsScaleController::OnWorldPinsVisibilityMessage(const WorldPinsVisibilityMessage &worldPinsVisibilityMessage)
            {
                if(worldPinsVisibilityMessage.ShouldSetVisible())
                {
                    Show();
                }
                else
                {
                    Hide();
                }
            }
        }
    }
}
<commit_msg>Fixed interior pins not hiding when going offscreen<commit_after>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "WorldPinsScaleController.h"

#include <limits>

#include "InteriorsModel.h"
#include "IWorldPinsService.h"
#include "ScreenProperties.h"
#include "RenderCamera.h"
#include "IWorldPinsRepository.h"
#include "WorldPinsVisibilityMessage.h"

namespace ExampleApp
{
    namespace WorldPins
    {
        namespace SdkModel
        {
            WorldPinsScaleController::WorldPinsScaleController(IWorldPinsRepository& worldPinsRepository,
                                                               IWorldPinsService& worldPinsService,
                                                               ExampleAppMessaging::TMessageBus& messageBus,
                                                               Eegeo::Resources::Interiors::InteriorsController& interiorsController)
                : m_worldPinsRepository(worldPinsRepository)
                , m_worldPinsService(worldPinsService)
                , m_messageBus(messageBus)
                , m_visibilityMessageHandlerBinding(this, &WorldPinsScaleController::OnWorldPinsVisibilityMessage)
                , m_modality(0.f)
                , m_visibilityScale(0.f)
                , m_targetVisibilityScale(1.f)
                , m_visibilityAnimationDuration(0.2f)
                , m_interiorsController(interiorsController)
            {
                m_messageBus.SubscribeNative(m_visibilityMessageHandlerBinding);
            }

            WorldPinsScaleController::~WorldPinsScaleController()
            {
                m_messageBus.UnsubscribeNative(m_visibilityMessageHandlerBinding);
            }

            void WorldPinsScaleController::Update(float deltaSeconds, const Eegeo::Camera::RenderCamera& renderCamera)
            {
                if(m_visibilityScale < m_targetVisibilityScale)
                {
                    m_visibilityScale = Eegeo::Min(m_visibilityScale + deltaSeconds/m_visibilityAnimationDuration, m_targetVisibilityScale);
                }
                else if(m_visibilityScale > m_targetVisibilityScale)
                {
                    m_visibilityScale = Eegeo::Max(m_visibilityScale - deltaSeconds/m_visibilityAnimationDuration, m_targetVisibilityScale);
                }

                for(size_t i = 0; i < m_worldPinsRepository.GetItemCount(); ++i)
                {
                    WorldPinItemModel& worldPinItemModel = *m_worldPinsRepository.GetItemAtIndex(i);
                    UpdateWorldPin(worldPinItemModel, deltaSeconds, renderCamera);
                    const float globalScale = 1.f - m_modality;
                    float scale = globalScale  * worldPinItemModel.TransitionStateValue() * m_visibilityScale;
                    m_worldPinsService.UpdatePinScale(worldPinItemModel, scale);
                }
            }

            void WorldPinsScaleController::SetModality(float modality)
            {
                Eegeo_ASSERT(modality >= 0.f && modality <= 1.f, "Invalid modality value %f, valid range for modality is 0.0 to 1.0 inclusive.\n", modality);

                m_modality = modality;
            }

            bool WorldPinsScaleController::ShouldHidePin(WorldPins::SdkModel::WorldPinItemModel& worldPinItemModel,
                                                         const Eegeo::Camera::RenderCamera& renderCamera)
            {
                const bool showingInterior = m_interiorsController.InteriorIsVisible();

                if(showingInterior && !worldPinItemModel.IsInterior())
                {
                    return true;
                }

                if(!showingInterior && worldPinItemModel.IsInterior())
                {
                    return !worldPinItemModel.GetInteriorData().showInExterior;
                }

                bool hidePinFromInteriorData =  false;
                if(showingInterior && worldPinItemModel.IsInterior())
                {
                    //hide if building and floor of pin not showing
                    const Eegeo::Resources::Interiors::InteriorsModel* pInteriorModel = NULL;
                    hidePinFromInteriorData = !(worldPinItemModel.GetInteriorData().floor == m_interiorsController.GetCurrentFloorIndex() &&
                             m_interiorsController.TryGetCurrentModel(pInteriorModel) &&
                             worldPinItemModel.GetInteriorData().building == pInteriorModel->GetId());
                }

                // hide when close to edge of screen
                Eegeo::v2 screenLocation;
                GetScreenLocation(worldPinItemModel, screenLocation, renderCamera);

                const float ratioX = screenLocation.GetX() / renderCamera.GetViewportWidth();
                const float ratioY = screenLocation.GetY() / renderCamera.GetViewportHeight();
                const bool hidePinFromScreenPosition = (ratioX < 0.1f) || (ratioX > 0.9f) || (ratioY < 0.15f) || (ratioY > 0.9f);

                return hidePinFromScreenPosition || hidePinFromInteriorData;
            }

            void WorldPinsScaleController::UpdateWorldPin(WorldPinItemModel& worldPinItemModel,
                    float deltaSeconds,
                    const Eegeo::Camera::RenderCamera& renderCamera)
            {
                if(ShouldHidePin(worldPinItemModel, renderCamera))
                {
                    worldPinItemModel.Hide();
                }
                else
                {
                    worldPinItemModel.Show();
                }

                worldPinItemModel.Update(deltaSeconds);
            }

            void WorldPinsScaleController::GetScreenLocation(const WorldPinItemModel& worldPinItemModel,
                    Eegeo::v2& screenLocation,
                    const Eegeo::Camera::RenderCamera& renderCamera) const
            {
                Eegeo::dv3 ecefLocation;
                m_worldPinsService.GetPinEcefAndScreenLocations(worldPinItemModel, ecefLocation, screenLocation);
                Eegeo::v3 cameraLocal = (ecefLocation - renderCamera.GetEcefLocation()).ToSingle();
                Eegeo::v3 screenPos;
                renderCamera.Project(cameraLocal, screenPos);
                screenLocation.Set(screenPos.GetX(), screenPos.GetY());
            }

            void WorldPinsScaleController::Show()
            {
                m_targetVisibilityScale = 1.0f;
            }

            void WorldPinsScaleController::Hide()
            {
                m_targetVisibilityScale = 0.0f;
            }

            void WorldPinsScaleController::OnWorldPinsVisibilityMessage(const WorldPinsVisibilityMessage &worldPinsVisibilityMessage)
            {
                if(worldPinsVisibilityMessage.ShouldSetVisible())
                {
                    Show();
                }
                else
                {
                    Hide();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* Generated from orogen/lib/orogen/templates/typekit/Plugin.cpp */

// First load all RTT interfaces so that we get all "extern template"
// declarations in the TypekitImpl files
#include "Plugin.hpp"

#include <iostream>
#include <boost/cstdint.hpp>
#include <boost/lexical_cast.hpp>

#include <rtt/types/TypeInfoRepository.hpp>
#include "type_info/Registration.hpp"
#include "Types.hpp"
#include <rtt/types/SequenceConstructor.hpp>
#include <rtt/types/TemplateConstructor.hpp>

using namespace RTT;
using namespace RTT::types;

orogen_typekits::<%= typekit.name %>TypekitPlugin::<%= typekit.name %>TypekitPlugin()
{}

orogen_typekits::<%= typekit.name %>TypekitPlugin::~<%= typekit.name %>TypekitPlugin()
{}

#define TYPEKIT_PACKAGE_NAME_aux0(target) #target
#define TYPEKIT_PACKAGE_NAME_aux(target) "<%= typekit.name %>-typekit-" TYPEKIT_PACKAGE_NAME_aux0(target)
#define TYPEKIT_PACKAGE_NAME TYPEKIT_PACKAGE_NAME_aux(OROCOS_TARGET)
bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadTypes()
{
    RTT::types::TypeInfoRepository::shared_ptr ti_repository = RTT::types::TypeInfoRepository::Instance();

    RTT::types::TypeInfo* ti = 0;
    <% registered_types.each do |type| %>
    ti = <%= type.method_name(true) %>_TypeInfo();
    ti_repository->addType( ti );
    <% end %>
    <% array_types.each do |type| %>
    ti = <%= type.deference.method_name(true) %>_ArrayTypeInfo();
    ti_repository->addType( ti );
    <% end %>

    return true;
}

bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadOperators()
{
	return true;
}
bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadConstructors()
{
    RTT::types::TypeInfoRepository::shared_ptr ti_repository = RTT::types::TypeInfoRepository::Instance();

    // Add sequence constructors for sequence types:
    <% registered_types.each do |type| if type.info_type == "RTT::types::SequenceTypeInfo" %>
    ti_repository->type( "<%= type.full_name %>" )->addConstructor( newConstructor(sequence_ctor< <%= type.deference.cxx_name %> >()));
    ti_repository->type( "<%= type.full_name %>" )->addConstructor( newConstructor(sequence_ctor2< <%= type.deference.cxx_name %> >()));
    ti_repository->type( "<%= type.full_name %>" )->addConstructor( new SequenceBuilder< <%= type.deference.cxx_name %> >());
    <% end end %>

	return true;
}
std::string orogen_typekits::<%= typekit.name %>TypekitPlugin::getName()
{ return "/orogen/<%= typekit.name %>"; }

ORO_TYPEKIT_PLUGIN(orogen_typekits::<%= typekit.name %>TypekitPlugin);

<commit_msg>typekit: no longer generate sequence constructors<commit_after>/* Generated from orogen/lib/orogen/templates/typekit/Plugin.cpp */

// First load all RTT interfaces so that we get all "extern template"
// declarations in the TypekitImpl files
#include "Plugin.hpp"

#include <iostream>
#include <boost/cstdint.hpp>
#include <boost/lexical_cast.hpp>

#include <rtt/types/TypeInfoRepository.hpp>
#include "type_info/Registration.hpp"
#include "Types.hpp"
#include <rtt/types/SequenceConstructor.hpp>
#include <rtt/types/TemplateConstructor.hpp>

using namespace RTT;
using namespace RTT::types;

orogen_typekits::<%= typekit.name %>TypekitPlugin::<%= typekit.name %>TypekitPlugin()
{}

orogen_typekits::<%= typekit.name %>TypekitPlugin::~<%= typekit.name %>TypekitPlugin()
{}

#define TYPEKIT_PACKAGE_NAME_aux0(target) #target
#define TYPEKIT_PACKAGE_NAME_aux(target) "<%= typekit.name %>-typekit-" TYPEKIT_PACKAGE_NAME_aux0(target)
#define TYPEKIT_PACKAGE_NAME TYPEKIT_PACKAGE_NAME_aux(OROCOS_TARGET)
bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadTypes()
{
    RTT::types::TypeInfoRepository::shared_ptr ti_repository = RTT::types::TypeInfoRepository::Instance();

    RTT::types::TypeInfo* ti = 0;
    <% registered_types.each do |type| %>
    ti = <%= type.method_name(true) %>_TypeInfo();
    ti_repository->addType( ti );
    <% end %>
    <% array_types.each do |type| %>
    ti = <%= type.deference.method_name(true) %>_ArrayTypeInfo();
    ti_repository->addType( ti );
    <% end %>

    return true;
}

bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadOperators()
{
	return true;
}
bool orogen_typekits::<%= typekit.name %>TypekitPlugin::loadConstructors()
{
	return true;
}
std::string orogen_typekits::<%= typekit.name %>TypekitPlugin::getName()
{ return "/orogen/<%= typekit.name %>"; }

ORO_TYPEKIT_PLUGIN(orogen_typekits::<%= typekit.name %>TypekitPlugin);

<|endoftext|>


<commit_before>#include "compiler/build_tables/parse_item_set_builder.h"
#include <algorithm>
#include <cassert>
#include <set>
#include <unordered_map>
#include <vector>
#include <utility>
#include "compiler/syntax_grammar.h"
#include "compiler/lexical_grammar.h"
#include "compiler/rule.h"

namespace tree_sitter {
namespace build_tables {

using std::find;
using std::get;
using std::move;
using std::pair;
using std::set;
using std::unordered_map;
using std::vector;
using rules::Symbol;

struct FollowSetInfo {
  LookaheadSet lookaheads;
  bool propagates_lookaheads;
};

struct NonTerminalQueueEntry {
  Symbol::Index non_terminal;
  LookaheadSet lookaheads;
  bool propagates_lookaheads;
};

bool ParseItemSetBuilder::ParseItemSetComponent::operator==(
  const ParseItemSetBuilder::ParseItemSetComponent &other) const {
  return item == other.item &&
    lookaheads == other.lookaheads &&
    propagates_lookaheads == other.propagates_lookaheads;
}

template <typename T>
inline void find_or_push(vector<T> &vector, const T &item) {
  if (find(vector.begin(), vector.end(), item) == vector.end()) {
    vector.push_back(item);
  }
}

ParseItemSetBuilder::ParseItemSetBuilder(
  const SyntaxGrammar &grammar,
  const LexicalGrammar &lexical_grammar
) : grammar{grammar} {

  // Populate the FIRST and LAST set of each terminal, which just contains the terminal itself.
  for (size_t i = 0, n = lexical_grammar.variables.size(); i < n; i++) {
    Symbol symbol = Symbol::terminal(i);
    first_sets.insert({symbol, LookaheadSet({symbol})});
    last_sets.insert({symbol, LookaheadSet({symbol})});
  }
  for (size_t i = 0, n = grammar.external_tokens.size(); i < n; i++) {
    Symbol symbol = Symbol::external(i);
    first_sets.insert({symbol, LookaheadSet({symbol})});
    last_sets.insert({symbol, LookaheadSet({symbol})});
  }

  // Populate the FIRST and LAST set of each non-terminal by recursively expanding non-terminals.
  vector<Symbol> symbols_to_process;
  set<Symbol::Index> processed_non_terminals;
  for (size_t i = 0, n = grammar.variables.size(); i < n; i++) {
    Symbol symbol = Symbol::non_terminal(i);
    LookaheadSet &first_set = first_sets[symbol];
    LookaheadSet &last_set = last_sets[symbol];

    processed_non_terminals.clear();
    symbols_to_process.assign({symbol});
    while (!symbols_to_process.empty()) {
      Symbol current_symbol = symbols_to_process.back();
      symbols_to_process.pop_back();

      if (!current_symbol.is_non_terminal()) {
        first_set.insert(current_symbol);
      } else if (processed_non_terminals.insert(current_symbol.index).second) {
        for (const Production &production : grammar.variables[current_symbol.index].productions) {
          if (!production.empty()) {
            symbols_to_process.push_back(production[0].symbol);
          }
        }
      }
    }

    processed_non_terminals.clear();
    symbols_to_process.assign({symbol});
    while (!symbols_to_process.empty()) {
      Symbol current_symbol = symbols_to_process.back();
      symbols_to_process.pop_back();

      if (!current_symbol.is_non_terminal()) {
        last_set.insert(current_symbol);
      } else if (processed_non_terminals.insert(current_symbol.index).second) {
        for (const Production &production : grammar.variables[current_symbol.index].productions) {
          if (!production.empty()) {
            symbols_to_process.push_back(production.back().symbol);
          }
        }
      }
    }
  }

  // Populate a cache of which ParseItems will be created when a given non-terminal is expanded.
  vector<NonTerminalQueueEntry> non_terminal_queue;
  for (Symbol::Index i = 0, n = grammar.variables.size(); i < n; i++) {

    // Compute the follow set of each *other* non-terminal that the current non-terminal can
    // start with.
    unordered_map<Symbol::Index, FollowSetInfo> follow_set_info_by_non_terminal;
    non_terminal_queue.assign({{i, LookaheadSet(), true}});
    while (!non_terminal_queue.empty()) {
      NonTerminalQueueEntry queue_entry = non_terminal_queue.back();
      non_terminal_queue.pop_back();

      bool queue_entry_is_new;
      auto &follow_set_info = follow_set_info_by_non_terminal[queue_entry.non_terminal];
      if (queue_entry.propagates_lookaheads) {
        queue_entry_is_new = !follow_set_info.propagates_lookaheads;
        follow_set_info.propagates_lookaheads = true;
      } else {
        queue_entry_is_new = follow_set_info.lookaheads.insert_all(queue_entry.lookaheads);
      }

      if (queue_entry_is_new) {
        for (const Production &production : grammar.variables[queue_entry.non_terminal].productions) {
          if (production.empty()) continue;
          Symbol next_symbol = production.at(0).symbol;
          if (!next_symbol.is_non_terminal() || next_symbol.is_built_in()) continue;

          LookaheadSet next_lookaheads;
          bool propagates_lookaheads;
          if (production.size() == 1) {
            next_lookaheads = queue_entry.lookaheads;
            propagates_lookaheads = queue_entry.propagates_lookaheads;
          } else {
            Symbol symbol_after_next = production.at(1).symbol;
            next_lookaheads = first_sets.find(symbol_after_next)->second;
            propagates_lookaheads = false;
          }

          non_terminal_queue.push_back({
            next_symbol.index,
            next_lookaheads,
            propagates_lookaheads
          });
        }
      }
    }

    // Use these follow sets to populate the cache of ParseItems for non-terminal `i`.
    for (auto &pair : follow_set_info_by_non_terminal) {
      Symbol non_terminal = Symbol::non_terminal(pair.first);

      for (const Production &production : grammar.variables[non_terminal.index].productions) {
        ParseItem item(non_terminal, production, 0);

        if (grammar.variables_to_inline.count(item.next_symbol())) {
          for (const Production &inlined_production : inline_production(item)) {
            find_or_push(transitive_closure_component_cache[i], {
              ParseItem(non_terminal, inlined_production, 0),
              pair.second.lookaheads,
              pair.second.propagates_lookaheads
            });
          }
        } else if (!grammar.variables_to_inline.count(non_terminal)) {
          find_or_push(transitive_closure_component_cache[i], {
            item,
            pair.second.lookaheads,
            pair.second.propagates_lookaheads
          });
        }
      }
    }
  }
}

const vector<Production> &ParseItemSetBuilder::inline_production(const ParseItem &item) {
  vector<Production> &result = inlined_productions_by_original_production[item];
  if (!result.empty()) return result;

  auto &inlined_step = item.production->at(item.step_index);
  vector<const Production *> productions_to_insert;
  for (auto &production : grammar.variables[inlined_step.symbol.index].productions) {
    productions_to_insert.push_back(&production);
  }

  for (auto iter = productions_to_insert.begin(); iter != productions_to_insert.end();) {
    const Production *production = *iter;

    if (!production->empty() && grammar.variables_to_inline.count(production->steps.front().symbol)) {
      iter = productions_to_insert.erase(iter);
      for (auto &production : inline_production(ParseItem(inlined_step.symbol, *production, 0))) {
        iter = productions_to_insert.insert(iter, &production);
      }
    } else {
      ++iter;
    }
  }

  for (const Production *production_to_insert : productions_to_insert) {
    auto begin = item.production->steps.begin();
    auto end = item.production->steps.end();
    auto step = begin + item.step_index;

    Production production{{begin, step}, item.production->dynamic_precedence};
    for (auto &step : *production_to_insert) {
      production.steps.push_back(step);
      if (!inlined_step.name_replacement.empty()) {
        production.steps.back().name_replacement = inlined_step.name_replacement;
      }
    }
    production.back().precedence = inlined_step.precedence;
    production.back().associativity = inlined_step.associativity;
    production.steps.insert(
      production.steps.end(),
      step + 1,
      end
    );

    if (find(result.begin(), result.end(), production) == result.end()) {
      result.push_back(move(production));
    }
  }

  return result;
}

void ParseItemSetBuilder::apply_transitive_closure(ParseItemSet *item_set) {
  for (auto iter = item_set->entries.begin(), end = item_set->entries.end(); iter != end;) {
    const ParseItem &item = iter->first;
    const LookaheadSet &lookaheads = iter->second;

    // Items whose `step_index` is 0 are not part of the item set's "kernel"; they have been
    // added in previous iterations of this loop, and they don't need to be further processed.
    if (item.lhs() == rules::START() || item.step_index > 0) {

      // Kernel items whose next symbol is a non-terminal are expanded using the pre-computed
      // parse item cache.
      const Symbol &next_symbol = item.next_symbol();
      if (next_symbol.is_non_terminal() && !next_symbol.is_built_in()) {

        LookaheadSet next_lookaheads;
        size_t next_step = item.step_index + 1;
        if (next_step == item.production->size()) {
          next_lookaheads = lookaheads;
        } else {
          Symbol symbol_after_next = item.production->at(next_step).symbol;
          next_lookaheads = first_sets.find(symbol_after_next)->second;
        }

        for (const auto &component : transitive_closure_component_cache[next_symbol.index]) {
          LookaheadSet &current_lookaheads = item_set->entries[component.item];
          current_lookaheads.insert_all(component.lookaheads);
          if (component.propagates_lookaheads) {
            current_lookaheads.insert_all(next_lookaheads);
          }
        }

        if (grammar.variables_to_inline.count(next_symbol)) {
          for (const Production &inlined_production : inline_production(item)) {
            item_set->entries.insert({
              ParseItem(item.lhs(), inlined_production, item.step_index),
              lookaheads
            });
          }

          iter = item_set->entries.erase(iter);
          continue;
        }
      }
    }

    if (grammar.variables_to_inline.count(item.lhs())) {
      iter = item_set->entries.erase(iter);
      continue;
    }

    ++iter;
  }
}

LookaheadSet ParseItemSetBuilder::get_first_set(const rules::Symbol &symbol) const {
  return first_sets.find(symbol)->second;
}

LookaheadSet ParseItemSetBuilder::get_last_set(const rules::Symbol &symbol) const {
  return last_sets.find(symbol)->second;
}

}  // namespace build_tables
}  // namespace tree_sitter
<commit_msg>Fix name collision that gcc didn't tolerate<commit_after>#include "compiler/build_tables/parse_item_set_builder.h"
#include <algorithm>
#include <cassert>
#include <set>
#include <unordered_map>
#include <vector>
#include <utility>
#include "compiler/syntax_grammar.h"
#include "compiler/lexical_grammar.h"
#include "compiler/rule.h"

namespace tree_sitter {
namespace build_tables {

using std::find;
using std::get;
using std::move;
using std::pair;
using std::set;
using std::unordered_map;
using std::vector;
using rules::Symbol;

struct FollowSetInfo {
  LookaheadSet lookaheads;
  bool propagates_lookaheads;
};

struct NonTerminalQueueEntry {
  Symbol::Index non_terminal;
  LookaheadSet lookaheads;
  bool propagates_lookaheads;
};

bool ParseItemSetBuilder::ParseItemSetComponent::operator==(
  const ParseItemSetBuilder::ParseItemSetComponent &other) const {
  return item == other.item &&
    lookaheads == other.lookaheads &&
    propagates_lookaheads == other.propagates_lookaheads;
}

template <typename T>
inline void find_or_push(vector<T> &vector, const T &item) {
  if (find(vector.begin(), vector.end(), item) == vector.end()) {
    vector.push_back(item);
  }
}

ParseItemSetBuilder::ParseItemSetBuilder(
  const SyntaxGrammar &grammar,
  const LexicalGrammar &lexical_grammar
) : grammar{grammar} {

  // Populate the FIRST and LAST set of each terminal, which just contains the terminal itself.
  for (size_t i = 0, n = lexical_grammar.variables.size(); i < n; i++) {
    Symbol symbol = Symbol::terminal(i);
    first_sets.insert({symbol, LookaheadSet({symbol})});
    last_sets.insert({symbol, LookaheadSet({symbol})});
  }
  for (size_t i = 0, n = grammar.external_tokens.size(); i < n; i++) {
    Symbol symbol = Symbol::external(i);
    first_sets.insert({symbol, LookaheadSet({symbol})});
    last_sets.insert({symbol, LookaheadSet({symbol})});
  }

  // Populate the FIRST and LAST set of each non-terminal by recursively expanding non-terminals.
  vector<Symbol> symbols_to_process;
  set<Symbol::Index> processed_non_terminals;
  for (size_t i = 0, n = grammar.variables.size(); i < n; i++) {
    Symbol symbol = Symbol::non_terminal(i);
    LookaheadSet &first_set = first_sets[symbol];
    LookaheadSet &last_set = last_sets[symbol];

    processed_non_terminals.clear();
    symbols_to_process.assign({symbol});
    while (!symbols_to_process.empty()) {
      Symbol current_symbol = symbols_to_process.back();
      symbols_to_process.pop_back();

      if (!current_symbol.is_non_terminal()) {
        first_set.insert(current_symbol);
      } else if (processed_non_terminals.insert(current_symbol.index).second) {
        for (const Production &production : grammar.variables[current_symbol.index].productions) {
          if (!production.empty()) {
            symbols_to_process.push_back(production[0].symbol);
          }
        }
      }
    }

    processed_non_terminals.clear();
    symbols_to_process.assign({symbol});
    while (!symbols_to_process.empty()) {
      Symbol current_symbol = symbols_to_process.back();
      symbols_to_process.pop_back();

      if (!current_symbol.is_non_terminal()) {
        last_set.insert(current_symbol);
      } else if (processed_non_terminals.insert(current_symbol.index).second) {
        for (const Production &production : grammar.variables[current_symbol.index].productions) {
          if (!production.empty()) {
            symbols_to_process.push_back(production.back().symbol);
          }
        }
      }
    }
  }

  // Populate a cache of which ParseItems will be created when a given non-terminal is expanded.
  vector<NonTerminalQueueEntry> non_terminal_queue;
  for (Symbol::Index i = 0, n = grammar.variables.size(); i < n; i++) {

    // Compute the follow set of each *other* non-terminal that the current non-terminal can
    // start with.
    unordered_map<Symbol::Index, FollowSetInfo> follow_set_info_by_non_terminal;
    non_terminal_queue.assign({{i, LookaheadSet(), true}});
    while (!non_terminal_queue.empty()) {
      NonTerminalQueueEntry queue_entry = non_terminal_queue.back();
      non_terminal_queue.pop_back();

      bool queue_entry_is_new;
      auto &follow_set_info = follow_set_info_by_non_terminal[queue_entry.non_terminal];
      if (queue_entry.propagates_lookaheads) {
        queue_entry_is_new = !follow_set_info.propagates_lookaheads;
        follow_set_info.propagates_lookaheads = true;
      } else {
        queue_entry_is_new = follow_set_info.lookaheads.insert_all(queue_entry.lookaheads);
      }

      if (queue_entry_is_new) {
        for (const Production &production : grammar.variables[queue_entry.non_terminal].productions) {
          if (production.empty()) continue;
          Symbol next_symbol = production.at(0).symbol;
          if (!next_symbol.is_non_terminal() || next_symbol.is_built_in()) continue;

          LookaheadSet next_lookaheads;
          bool propagates_lookaheads;
          if (production.size() == 1) {
            next_lookaheads = queue_entry.lookaheads;
            propagates_lookaheads = queue_entry.propagates_lookaheads;
          } else {
            Symbol symbol_after_next = production.at(1).symbol;
            next_lookaheads = first_sets.find(symbol_after_next)->second;
            propagates_lookaheads = false;
          }

          non_terminal_queue.push_back({
            next_symbol.index,
            next_lookaheads,
            propagates_lookaheads
          });
        }
      }
    }

    // Use these follow sets to populate the cache of ParseItems for non-terminal `i`.
    for (auto &pair : follow_set_info_by_non_terminal) {
      Symbol non_terminal = Symbol::non_terminal(pair.first);

      for (const Production &production : grammar.variables[non_terminal.index].productions) {
        ParseItem item(non_terminal, production, 0);

        if (grammar.variables_to_inline.count(item.next_symbol())) {
          for (const Production &inlined_production : inline_production(item)) {
            find_or_push(transitive_closure_component_cache[i], {
              ParseItem(non_terminal, inlined_production, 0),
              pair.second.lookaheads,
              pair.second.propagates_lookaheads
            });
          }
        } else if (!grammar.variables_to_inline.count(non_terminal)) {
          find_or_push(transitive_closure_component_cache[i], {
            item,
            pair.second.lookaheads,
            pair.second.propagates_lookaheads
          });
        }
      }
    }
  }
}

const vector<Production> &ParseItemSetBuilder::inline_production(const ParseItem &item) {
  vector<Production> &result = inlined_productions_by_original_production[item];
  if (!result.empty()) return result;

  auto &inlined_step = item.production->at(item.step_index);
  vector<const Production *> productions_to_insert;
  for (auto &production : grammar.variables[inlined_step.symbol.index].productions) {
    productions_to_insert.push_back(&production);
  }

  for (auto iter = productions_to_insert.begin(); iter != productions_to_insert.end();) {
    const Production *production = *iter;

    if (!production->empty() && grammar.variables_to_inline.count(production->steps.front().symbol)) {
      iter = productions_to_insert.erase(iter);
      for (auto &inlined_production : inline_production(ParseItem(inlined_step.symbol, *production, 0))) {
        iter = productions_to_insert.insert(iter, &inlined_production);
      }
    } else {
      ++iter;
    }
  }

  for (const Production *production_to_insert : productions_to_insert) {
    auto begin = item.production->steps.begin();
    auto end = item.production->steps.end();
    auto step = begin + item.step_index;

    Production production{{begin, step}, item.production->dynamic_precedence};
    for (auto &step : *production_to_insert) {
      production.steps.push_back(step);
      if (!inlined_step.name_replacement.empty()) {
        production.steps.back().name_replacement = inlined_step.name_replacement;
      }
    }
    production.back().precedence = inlined_step.precedence;
    production.back().associativity = inlined_step.associativity;
    production.steps.insert(
      production.steps.end(),
      step + 1,
      end
    );

    if (find(result.begin(), result.end(), production) == result.end()) {
      result.push_back(move(production));
    }
  }

  return result;
}

void ParseItemSetBuilder::apply_transitive_closure(ParseItemSet *item_set) {
  for (auto iter = item_set->entries.begin(), end = item_set->entries.end(); iter != end;) {
    const ParseItem &item = iter->first;
    const LookaheadSet &lookaheads = iter->second;

    // Items whose `step_index` is 0 are not part of the item set's "kernel"; they have been
    // added in previous iterations of this loop, and they don't need to be further processed.
    if (item.lhs() == rules::START() || item.step_index > 0) {

      // Kernel items whose next symbol is a non-terminal are expanded using the pre-computed
      // parse item cache.
      const Symbol &next_symbol = item.next_symbol();
      if (next_symbol.is_non_terminal() && !next_symbol.is_built_in()) {

        LookaheadSet next_lookaheads;
        size_t next_step = item.step_index + 1;
        if (next_step == item.production->size()) {
          next_lookaheads = lookaheads;
        } else {
          Symbol symbol_after_next = item.production->at(next_step).symbol;
          next_lookaheads = first_sets.find(symbol_after_next)->second;
        }

        for (const auto &component : transitive_closure_component_cache[next_symbol.index]) {
          LookaheadSet &current_lookaheads = item_set->entries[component.item];
          current_lookaheads.insert_all(component.lookaheads);
          if (component.propagates_lookaheads) {
            current_lookaheads.insert_all(next_lookaheads);
          }
        }

        if (grammar.variables_to_inline.count(next_symbol)) {
          for (const Production &inlined_production : inline_production(item)) {
            item_set->entries.insert({
              ParseItem(item.lhs(), inlined_production, item.step_index),
              lookaheads
            });
          }

          iter = item_set->entries.erase(iter);
          continue;
        }
      }
    }

    if (grammar.variables_to_inline.count(item.lhs())) {
      iter = item_set->entries.erase(iter);
      continue;
    }

    ++iter;
  }
}

LookaheadSet ParseItemSetBuilder::get_first_set(const rules::Symbol &symbol) const {
  return first_sets.find(symbol)->second;
}

LookaheadSet ParseItemSetBuilder::get_last_set(const rules::Symbol &symbol) const {
  return last_sets.find(symbol)->second;
}

}  // namespace build_tables
}  // namespace tree_sitter
<|endoftext|>


<commit_before>/*
** Author(s):
**   - Thomas Fontenay <tfontenay@aldebaran.com>
**
** Copyright (c) 2014 Aldebaran Robotics. All rights reserved.
**
*/

#include <algorithm>

#include <gtest/gtest.h>

#include <qi/log.hpp>
#include <qi/application.hpp>
#include <qi/session.hpp>

#include "src/messaging/transportsocketcache.hpp"
#include "src/messaging/tcptransportsocket.hpp"
#include "src/messaging/transportserver.hpp"

qiLogCategory("TestTransportSocketCache");

namespace {

void newConnection(qi::TransportSocketPtr socket)
{
  socket->startReading();
}

class TestTransportSocketCache : public ::testing::Test
{
protected:
  TestTransportSocketCache()
  {
    cache_.init();
    server_.newConnection.connect(&newConnection, _1);
  }
  ~TestTransportSocketCache()
  {
    cache_.close();
    server_.close();
  }

  qi::TransportSocketCache cache_;
  qi::TransportServer server_;
};

}

TEST_F(TestTransportSocketCache, DisconnectReconnect)
{
  qi::Promise<void> prom;

  server_.listen("tcp://0.0.0.0:0").wait();
  server_.listen("tcp://0.0.0.0:0").wait();

  std::vector<qi::Url> endpoints = server_.endpoints();
  //endpoints.push_back(server_.endpoints()[0]);
  qi::ServiceInfo servInfo;
  servInfo.setMachineId("tle;l");
  servInfo.setEndpoints(endpoints);
  qi::Future<qi::TransportSocketPtr> sockfut = cache_.socket(servInfo, endpoints[0].protocol());
  qi::TransportSocketPtr sock = sockfut.value();
  ASSERT_TRUE(sock->isConnected());
  sock->disconnect();
  ASSERT_FALSE(sock->isConnected());
  sockfut = cache_.socket(servInfo, endpoints[0].protocol());
  sock = sockfut.value();
  ASSERT_TRUE(sock->isConnected());
}

TEST_F(TestTransportSocketCache, FirstUrlWillFail)
{
  server_.listen("tcp://127.0.0.1:5555").wait();
  qi::UrlVector endpoints;
  endpoints.push_back("tcp://127.0.0.1:4444");
  endpoints.push_back(server_.endpoints()[0]);

  qi::ServiceInfo servInfo;
  servInfo.setMachineId(qi::os::getMachineId());
  servInfo.setEndpoints(endpoints);
  qi::Future<qi::TransportSocketPtr> sockFut = cache_.socket(servInfo, endpoints[0].protocol());
  qi::TransportSocketPtr sock = sockFut.value();

  ASSERT_TRUE(sock->isConnected());
}

TEST_F(TestTransportSocketCache, DifferentMachineIdLocalConnection)
{
  qi::TransportSocketPtr socket = boost::make_shared<qi::TcpTransportSocket>();
  const std::string& fakeMachineId = "there is relatively low chances this \
      could end being the same machineID than the actual one of this \
      machine. Then again, one can't be too sure, and we should probably \
      randomly generate it in order to guarantee this test will be consistent.\
      Butwe can probably take this chance.";

  ASSERT_NE(fakeMachineId, qi::os::getMachineId());

  server_.listen("tcp://127.0.0.1:0").wait();
  qi::Url endpoint = server_.endpoints()[0];
  socket->connect(endpoint);
  cache_.insert(fakeMachineId, endpoint, socket);

  // Forge a service info, change the machine ID
  // TransportSocketCache only uses the machineID and the endpoints
  qi::ServiceInfo serviceInfo;
  // This will make the cache think the target and ourselves are not
  // on the same machine
  serviceInfo.setMachineId(fakeMachineId);
  serviceInfo.setEndpoints(server_.endpoints());

  qi::Future<qi::TransportSocketPtr> tentativeSocketFuture = cache_.socket(serviceInfo, "");

  ASSERT_FALSE(tentativeSocketFuture.hasError());
  ASSERT_EQ(tentativeSocketFuture.value(), socket);
  socket->disconnect();
}

static bool publicIp(const qi::Url& url)
{
  const std::string& host = url.host();
  bool ispublic= host.find("127.") == std::string::npos && host.find("localhost") == std::string::npos;
  return ispublic;
}

TEST_F(TestTransportSocketCache, SameMachinePublicIp)
{
  qi::TransportSocketPtr client = boost::make_shared<qi::TcpTransportSocket>();

  server_.listen("tcp://0.0.0.0:0").wait();
  qi::UrlVector endpoints = server_.endpoints();
  // Find public IP
  qi::UrlVector::iterator urlIt = std::find_if(endpoints.begin(), endpoints.end(), &publicIp);
  ASSERT_NE(urlIt, endpoints.end());
  qi::Url url = *urlIt;
  qi::UrlVector v;

  v.push_back(url);
  client->connect(url);
  cache_.insert(qi::os::getMachineId(), url, client);

  qi::ServiceInfo info;
  info.setMachineId(qi::os::getMachineId());
  info.setEndpoints(v);
  qi::Future<qi::TransportSocketPtr> tentativeSocketFuture = cache_.socket(info, "");

  tentativeSocketFuture.wait();
  ASSERT_FALSE(tentativeSocketFuture.hasError());
  ASSERT_EQ(tentativeSocketFuture.value(), client);
  client->disconnect();
}

TEST(TestCall, IPV6Accepted)
{
  // todo: enable whenever qi::Url properly supports ipv6
  return;
  std::string initialEnvValue = qi::os::getenv("QIMESSAGING_ENABLE_IPV6");
  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", "1");

  qi::Url ipv6Url("tcp://[::1]:0");
  ASSERT_TRUE(ipv6Url.isValid());

  qi::TransportServer server;
  qi::Future<void> fut = server.listen(ipv6Url);

  ASSERT_FALSE(fut.hasError());

  qi::TransportSocketPtr socket = qi::makeTransportSocket("tcp");
  fut = socket->connect(ipv6Url);

  ASSERT_FALSE(fut.hasError());

  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", initialEnvValue.c_str());
}

TEST(TestCall, IPV6Rejected)
{
  // todo: enable whenever qi::Url properly supports ipv6
  return;

  std::string initialEnvValue = qi::os::getenv("QIMESSAGING_ENABLE_IPV6");
  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", "");

  qi::Url ipv6Url("tcp://[::1]:4444");
  ASSERT_TRUE(ipv6Url.isValid());

  qi::TransportSocketPtr socket = qi::makeTransportSocket("tcp");
  qi::Future<void> fut = socket->connect(ipv6Url);

  ASSERT_TRUE(fut.hasError());

  qi::TransportServer server;
  fut = server.listen(ipv6Url);

  ASSERT_TRUE(fut.hasError());

  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", initialEnvValue.c_str());
}
<commit_msg>Transport Socket Cache: fix text in test<commit_after>/*
** Author(s):
**   - Thomas Fontenay <tfontenay@aldebaran.com>
**
** Copyright (c) 2014 Aldebaran Robotics. All rights reserved.
**
*/

#include <algorithm>

#include <gtest/gtest.h>

#include <qi/log.hpp>
#include <qi/application.hpp>
#include <qi/session.hpp>

#include "src/messaging/transportsocketcache.hpp"
#include "src/messaging/tcptransportsocket.hpp"
#include "src/messaging/transportserver.hpp"

qiLogCategory("TestTransportSocketCache");

namespace {

void newConnection(qi::TransportSocketPtr socket)
{
  socket->startReading();
}

class TestTransportSocketCache : public ::testing::Test
{
protected:
  TestTransportSocketCache()
  {
    cache_.init();
    server_.newConnection.connect(&newConnection, _1);
  }
  ~TestTransportSocketCache()
  {
    cache_.close();
    server_.close();
  }

  qi::TransportSocketCache cache_;
  qi::TransportServer server_;
};

}

TEST_F(TestTransportSocketCache, DisconnectReconnect)
{
  qi::Promise<void> prom;

  server_.listen("tcp://0.0.0.0:0").wait();
  server_.listen("tcp://0.0.0.0:0").wait();

  std::vector<qi::Url> endpoints = server_.endpoints();
  //endpoints.push_back(server_.endpoints()[0]);
  qi::ServiceInfo servInfo;
  servInfo.setMachineId("tle;l");
  servInfo.setEndpoints(endpoints);
  qi::Future<qi::TransportSocketPtr> sockfut = cache_.socket(servInfo, endpoints[0].protocol());
  qi::TransportSocketPtr sock = sockfut.value();
  ASSERT_TRUE(sock->isConnected());
  sock->disconnect();
  ASSERT_FALSE(sock->isConnected());
  sockfut = cache_.socket(servInfo, endpoints[0].protocol());
  sock = sockfut.value();
  ASSERT_TRUE(sock->isConnected());
}

TEST_F(TestTransportSocketCache, FirstUrlWillFail)
{
  server_.listen("tcp://127.0.0.1:5555").wait();
  qi::UrlVector endpoints;
  endpoints.push_back("tcp://127.0.0.1:4444");
  endpoints.push_back(server_.endpoints()[0]);

  qi::ServiceInfo servInfo;
  servInfo.setMachineId(qi::os::getMachineId());
  servInfo.setEndpoints(endpoints);
  qi::Future<qi::TransportSocketPtr> sockFut = cache_.socket(servInfo, endpoints[0].protocol());
  qi::TransportSocketPtr sock = sockFut.value();

  ASSERT_TRUE(sock->isConnected());
}

TEST_F(TestTransportSocketCache, DifferentMachineIdLocalConnection)
{
  qi::TransportSocketPtr socket = boost::make_shared<qi::TcpTransportSocket>();
  const std::string& fakeMachineId = "there is relatively low chances this \
      could end being the same machineID than the actual one of this \
      machine. Then again, one can't be too sure, and we should probably \
      randomly generate it in order to guarantee this test will be consistent.\
      But we can probably take this chance.";

  ASSERT_NE(fakeMachineId, qi::os::getMachineId());

  server_.listen("tcp://127.0.0.1:0").wait();
  qi::Url endpoint = server_.endpoints()[0];
  socket->connect(endpoint);
  cache_.insert(fakeMachineId, endpoint, socket);

  // Forge a service info, change the machine ID
  // TransportSocketCache only uses the machineID and the endpoints
  qi::ServiceInfo serviceInfo;
  // This will make the cache think the target and ourselves are not
  // on the same machine
  serviceInfo.setMachineId(fakeMachineId);
  serviceInfo.setEndpoints(server_.endpoints());

  qi::Future<qi::TransportSocketPtr> tentativeSocketFuture = cache_.socket(serviceInfo, "");

  ASSERT_FALSE(tentativeSocketFuture.hasError());
  ASSERT_EQ(tentativeSocketFuture.value(), socket);
  socket->disconnect();
}

static bool publicIp(const qi::Url& url)
{
  const std::string& host = url.host();
  bool ispublic= host.find("127.") == std::string::npos && host.find("localhost") == std::string::npos;
  return ispublic;
}

TEST_F(TestTransportSocketCache, SameMachinePublicIp)
{
  qi::TransportSocketPtr client = boost::make_shared<qi::TcpTransportSocket>();

  server_.listen("tcp://0.0.0.0:0").wait();
  qi::UrlVector endpoints = server_.endpoints();
  // Find public IP
  qi::UrlVector::iterator urlIt = std::find_if(endpoints.begin(), endpoints.end(), &publicIp);
  ASSERT_NE(urlIt, endpoints.end());
  qi::Url url = *urlIt;
  qi::UrlVector v;

  v.push_back(url);
  client->connect(url);
  cache_.insert(qi::os::getMachineId(), url, client);

  qi::ServiceInfo info;
  info.setMachineId(qi::os::getMachineId());
  info.setEndpoints(v);
  qi::Future<qi::TransportSocketPtr> tentativeSocketFuture = cache_.socket(info, "");

  tentativeSocketFuture.wait();
  ASSERT_FALSE(tentativeSocketFuture.hasError());
  ASSERT_EQ(tentativeSocketFuture.value(), client);
  client->disconnect();
}

TEST(TestCall, IPV6Accepted)
{
  // todo: enable whenever qi::Url properly supports ipv6
  return;
  std::string initialEnvValue = qi::os::getenv("QIMESSAGING_ENABLE_IPV6");
  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", "1");

  qi::Url ipv6Url("tcp://[::1]:0");
  ASSERT_TRUE(ipv6Url.isValid());

  qi::TransportServer server;
  qi::Future<void> fut = server.listen(ipv6Url);

  ASSERT_FALSE(fut.hasError());

  qi::TransportSocketPtr socket = qi::makeTransportSocket("tcp");
  fut = socket->connect(ipv6Url);

  ASSERT_FALSE(fut.hasError());

  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", initialEnvValue.c_str());
}

TEST(TestCall, IPV6Rejected)
{
  // todo: enable whenever qi::Url properly supports ipv6
  return;

  std::string initialEnvValue = qi::os::getenv("QIMESSAGING_ENABLE_IPV6");
  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", "");

  qi::Url ipv6Url("tcp://[::1]:4444");
  ASSERT_TRUE(ipv6Url.isValid());

  qi::TransportSocketPtr socket = qi::makeTransportSocket("tcp");
  qi::Future<void> fut = socket->connect(ipv6Url);

  ASSERT_TRUE(fut.hasError());

  qi::TransportServer server;
  fut = server.listen(ipv6Url);

  ASSERT_TRUE(fut.hasError());

  qi::os::setenv("QIMESSAGING_ENABLE_IPV6", initialEnvValue.c_str());
}
<|endoftext|>


<commit_before>#include "limit_quote.h"

void Limit_quote::debug() const
{
	Quote::debug();
    std::cout << "max_qty= " << this->max_qty << " "
              << "discount= " << this->discount<< " ";
}
<commit_msg>Update limit_quote.cpp<commit_after>#include <iostream>
#include <cstddef>
#include "Limit_quote.h"

double Limit_quote::net_price(size_t n) const
{
    if(n<=max_qty)
        return n*price*(1-discount);
    else
        return max_qty*price*(1-discount)+(n-max_qty)*price;
}

void Limit_quote::debug() const
{
    Quote::debug();
    cout<<"max_qty= "<<max_qty<<" "
        <<"discount= "<<discount<<" ";
}
<|endoftext|>