<commit_before>#include "inmost.h"

using namespace INMOST;

//todo: want to separate all faces into those that share edges
//see todo: inside text

int main(int argc, char ** argv)
{
	if (argc < 2)
	{
		std::cout << "Usage: " << argv[0] << " mesh clusters [clusters=10] [max_iterations=10] [mesh_out=grid.vtk]" << std::endl;
		return -1;
	}

	int K = 10;
	if( argc > 2 ) K = atoi(argv[2]);
	int max_iterations = 10;
	if( argc > 3 ) max_iterations = atoi(argv[3]);

	if( K == 0 )
		std::cout << "Problem with number of clusters argument " << argv[2] << std::endl;

	if( max_iterations == 0 )
		std::cout << "Problem with max iterations argument " << argv[3] << std::endl;

	std::string grid_out = "grid.vtk";
	if (argc > 4) grid_out = std::string(argv[4]);

	Mesh m;
	m.Load(argv[1]);

	std::cout << "Start:" << std::endl;
	std::cout << "Cells: " << m.NumberOfCells() << std::endl;
	std::cout << "Faces: " << m.NumberOfFaces() << std::endl;
	std::cout << "Edges: " << m.NumberOfEdges() << std::endl;

	double tt = Timer();
	//There seems to be a problem with the mesh
	/*
	int fixed = 0;
	for (Mesh::iteratorFace f = m.BeginFace(); f != m.EndFace(); ++f)
	{
		if (f->FixNormalOrientation())
			fixed++;
	}
	std::cout << "Time to fix normals: " << Timer() - tt << std::endl;
	std::cout << "Total face normals fixed: " << fixed << std::endl;
	*/
	int total_points = 0

#if defined(USE_OMP)
#pragma omp parallel for reduction(+:total_points)
#endif
	for(int q = 0; q < m.CellLastLocalID(); ++q) if( m.isValidCell(q) )
	{
		Cell n = m.CellByLocalID(q);
		if( n->GetStatus() != Element::Ghost ) total_points++;
	}

	std::vector< double > points_center(total_points*3);
	std::vector< int > points_node(total_points);
	std::vector< int > points_cluster(total_points,-1);
	std::vector< double > cluster_center(K*3);
	std::vector< int > cluster_npoints(K);
#if defined(USE_MPI)
	std::vector< double > cluster_center_tmp(K*3);
	std::vector< int > cluster_npoints_tmp(K);
#endif
	int k = 0;
	for(int q = 0; q < m.CellLastLocalID(); ++q) if( m.isValidCell(q) )
	{
		Cell n = m.CellByLocalID(q);
		if( n->GetStatus() != Element::Ghost ) points_node[k++] = n->LocalID();
	}

#if defined(USE_OMP)
#pragma omp paralell for
#endif
	for(int q = 0; q < total_points; ++q)
	{
		Cell n = m.CellByLocalID(points_node[q]);
		double cnt[3];
		n->Centroid(cnt);
		points_center[q*3+0] = cnt[0];
		points_center[q*3+1] = cnt[1];
		points_center[q*3+2] = cnt[2];
	}

	// choose K distinct values for the centers of the clusters
	{
		std::vector<int> prohibited_indexes;
		int Kpart = (int)ceil((double)K/(double)m.GetProessorsNumber());
		int Kstart = Kpart * m.GetProcessorRank();
		int Kend = Kstart + Kpart;
		if( Kend > K ) Kend = K;
		for(int i = Kstart; i < Kend; i++)
		{
			while(true)
			{
				int index_point = rand() % total_points;

				if(find(prohibited_indexes.begin(), prohibited_indexes.end(),
						index_point) == prohibited_indexes.end())
				{
					prohibited_indexes.push_back(index_point);
					cluster_center[i*3+0] = points_center[index_point*3+0];
					cluster_center[i*3+1] = points_center[index_point*3+1];
					cluster_center[i*3+2] = points_center[index_point*3+2];
					points_cluster[index_point] = i;
					break;
				}
			}
		}
		//guter cluster centers over all processes
#if defined(USE_MPI)
		{
			std::vector<int> recvcounts(m.GetProcessorNumber()), displs(m.GetProcessorNumber());
			displs[0] = 0;
			recvcounts[0] = Kpart*3;
			for(int i = 1; i < (int)m.GetProcessorNumber(); ++i)
			{
				displs[i] = displs[i-1] + recvcounts[i-1];
				recvcounts[i] = Kpart*3;
			}
			recvcounts.back() = K - displs.back();
			MPI_Allgatherv(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,&cluster_center[0],&recvcounts[0],&displs[0],MPI_DOUBLE,MPI_COMM_WORLD);
		}
#endif
	}

	int iter = 1;
	double t = Timer();
	while(true)
	{
		int changed = 0;

		// associates each point to the nearest center
#if defined(USE_OMP)
#pragma omp parallel for reduction(+:changed)
#endif
		for(int i = 0; i < total_points; i++)
		{
			int id_old_cluster = points_cluster[i];
			int id_nearest_center = -1;
			double lmin = 1.0e+100;

			for(int j = 0; j < K; ++j)
			{
				double v[3];
				v[0] = (points_center[i*3+0] - cluster_center[j*3+0]);
				v[1] = (points_center[i*3+1] - cluster_center[j*3+1]);
				v[2] = (points_center[i*3+2] - cluster_center[j*3+2]);

				double l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
				if( l < lmin )
				{
					lmin = l;
					id_nearest_center = j;
				}
			}

			if(id_old_cluster != id_nearest_center)
			{
				points_cluster[i] = id_nearest_center;
				changed++;
			}
		}

#if defined(USE_MPI)
		int tmp = changed;
		MPI_Allreduce(&tmp,&changed,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
#endif

		if(changed == 0 || iter >= max_iterations)
		{
			std::cout << "Break in iteration " << iter << std::endl;
			break;
		}

		for(int i = 0; i < K; i++)
		{
			cluster_center[i*3+0] = 0;
			cluster_center[i*3+1] = 0;
			cluster_center[i*3+2] = 0;
			cluster_npoints[i] = 0;
		}
		// recalculating the center of each cluster
#if defined(USE_OMP)
#pragma omp parallel
#endif
		{
			std::vector< double > local_sum(K*3,0.0);
			std::vector< int > local_npoints(K,0);
			for(int j = 0; j < total_points; ++j)
			{
				local_sum[points_cluster[j]*3+0] += points_center[j*3+0];
				local_sum[points_cluster[j]*3+1] += points_center[j*3+1];
				local_sum[points_cluster[j]*3+2] += points_center[j*3+2];
				local_npoints[points_cluster[j]]++;
			}
#if defined(USE_OMP)
#pragma omp critical
#endif
			{
				for(int i = 0; i < K; ++i)
				{
					cluster_center[i*3+0] += local_sum[i*3+0];
					cluster_center[i*3+1] += local_sum[i*3+1];
					cluster_center[i*3+2] += local_sum[i*3+2];
					cluster_npoints[i] += local_npoints[i];
				}
			}
		}
#if defined(USE_MPI)
		MPI_Allreduce(&cluster_center[0],&cluster_center_tmp[0],K*3,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
		MPI_Allreduce(&cluster_npoints[0],&cluster_npoints_tmp[0],K,MPI_INT,MPI_SUM,MPI_COMM_WORLD);
		cluster_center.swap(cluster_center_tmp);
		cluster_npoints.swap(cluster_npoints_tmp);
#endif
		for(int i = 0; i < K; i++)
		{
			cluster_center[i*3+0] /= (double) cluster_npoints[i];
			cluster_center[i*3+1] /= (double) cluster_npoints[i];
			cluster_center[i*3+2] /= (double) cluster_npoints[i];
		}

		std::cout << "Iteration " << iter << std::endl;
		iter++;
	}
	std::cout << "Clustering in " << Timer() - t << " secs " << std::endl;
	// shows elements of clusters
	TagInteger mat = m.CreateTag("MATERIAL",DATA_INTEGER,CELL,NONE,1);
#if defined(USE_OMP)
#pragma omp parallel for
#endif
	for(int j = 0; j < total_points; ++j)
		mat[m.CellByLocalID(points_node[j])] = points_cluster[j]+1;
	m.ExchangeData(mat,CELL,0);

	m.Save(grid_out);
	return 0;
}
<commit_msg>Fixes for parallel MPI-clustering<commit_after>#include "inmost.h"

using namespace INMOST;

//todo: want to separate all faces into those that share edges
//see todo: inside text

int main(int argc, char ** argv)
{
	if (argc < 2)
	{
		std::cout << "Usage: " << argv[0] << " mesh clusters [clusters=10] [max_iterations=10] [mesh_out=grid.vtk]" << std::endl;
		return -1;
	}

	Mesh::Initialize(&argc,&argv);

	int K = 10;
	if( argc > 2 ) K = atoi(argv[2]);
	int max_iterations = 10;
	if( argc > 3 ) max_iterations = atoi(argv[3]);

	if( K == 0 )
		std::cout << "Problem with number of clusters argument " << argv[2] << std::endl;

	if( max_iterations == 0 )
		std::cout << "Problem with max iterations argument " << argv[3] << std::endl;

	std::string grid_out = "grid.vtk";
	if (argc > 4) grid_out = std::string(argv[4]);

	Mesh m;
	m.SetCommunicator(INMOST_MPI_COMM_WORLD);
	m.Load(argv[1]);

	std::cout << "Start:" << std::endl;
	std::cout << "Cells: " << m.NumberOfCells() << std::endl;
	std::cout << "Faces: " << m.NumberOfFaces() << std::endl;
	std::cout << "Edges: " << m.NumberOfEdges() << std::endl;

	double tt = Timer();
	//There seems to be a problem with the mesh
	/*
	int fixed = 0;
	for (Mesh::iteratorFace f = m.BeginFace(); f != m.EndFace(); ++f)
	{
		if (f->FixNormalOrientation())
			fixed++;
	}
	std::cout << "Time to fix normals: " << Timer() - tt << std::endl;
	std::cout << "Total face normals fixed: " << fixed << std::endl;
	*/
	int total_points = 0, total_global_points = 0;

#if defined(USE_OMP)
#pragma omp parallel for reduction(+:total_points)
#endif
	for(int q = 0; q < m.CellLastLocalID(); ++q) if( m.isValidCell(q) )
	{
		Cell n = m.CellByLocalID(q);
		if( n->GetStatus() != Element::Ghost ) total_points++;
	}

#if defined(USE_MPI)
	MPI_Allreduce(&total_global_points,&total,points,1,MPI_INT,MPI_SUM,MPI_COMM_WORLD)
#else
	total_global_points = total_points;
#endif

	std::vector< double > points_center(total_points*3);
	std::vector< int > points_node(total_points);
	std::vector< int > points_cluster(total_points,-1);
	std::vector< double > cluster_center(K*3);
	std::vector< int > cluster_npoints(K);
#if defined(USE_MPI)
	std::vector< double > cluster_center_tmp(K*3);
	std::vector< int > cluster_npoints_tmp(K);
#endif
	int k = 0;
	for(int q = 0; q < m.CellLastLocalID(); ++q) if( m.isValidCell(q) )
	{
		Cell n = m.CellByLocalID(q);
		if( n->GetStatus() != Element::Ghost ) points_node[k++] = n->LocalID();
	}

#if defined(USE_OMP)
#pragma omp paralell for
#endif
	for(int q = 0; q < total_points; ++q)
	{
		Cell n = m.CellByLocalID(points_node[q]);
		double cnt[3];
		n->Centroid(cnt);
		points_center[q*3+0] = cnt[0];
		points_center[q*3+1] = cnt[1];
		points_center[q*3+2] = cnt[2];
	}

	std::cout << m.GetProcessorRank() << " init clusters" << std::endl;

	// choose K distinct values for the centers of the clusters
	{
		std::vector<int> prohibited_indexes;
		int Kpart = (int)ceil((double)K/(double)m.GetProcessorsNumber());
		int Kstart = Kpart * m.GetProcessorRank();
		int Kend = Kstart + Kpart;
		if( Kend > K ) Kend = K;
		for(int i = Kstart; i < Kend; i++)
		{
			while(true)
			{
				int index_point = rand() % total_points;

				if(find(prohibited_indexes.begin(), prohibited_indexes.end(),
						index_point) == prohibited_indexes.end())
				{
					prohibited_indexes.push_back(index_point);
					cluster_center[i*3+0] = points_center[index_point*3+0];
					cluster_center[i*3+1] = points_center[index_point*3+1];
					cluster_center[i*3+2] = points_center[index_point*3+2];
					points_cluster[index_point] = i;
					break;
				}
			}
		}
		//guter cluster centers over all processes
#if defined(USE_MPI)
		{
			std::vector<int> recvcounts(m.GetProcessorsNumber()), displs(m.GetProcessorsNumber());
			displs[0] = 0;
			recvcounts[0] = Kpart*3;
			for(int i = 1; i < (int)m.GetProcessorsNumber(); ++i)
			{
				displs[i] = displs[i-1] + recvcounts[i-1];
				recvcounts[i] = Kpart*3;
			}
			recvcounts.back() = K*3 - displs.back();
			std::cout << m.GetProcessorRank() << " " << Kstart << " " << Kend << std::endl;
			for(int i = 0; i < (int)m.GetProcessorsNumber(); ++i)
			{
				std::cout << m.GetProcessorRank() << " " << i << " " << displs[i] << " " << recvcounts[i] << std::endl;
			}
			for(int i = Kstart; i < Kend; ++i)
			{
				cluster_center_tmp[i*3+0] = cluster_center[i*3+0];
				cluster_center_tmp[i*3+1] = cluster_center[i*3+1];
				cluster_center_tmp[i*3+2] = cluster_center[i*3+2];
			}
			MPI_Allgatherv(&cluster_center_tmp[Kstart*3],(Kend-Kstart)*3,MPI_DOUBLE,&cluster_center[0],&recvcounts[0],&displs[0],MPI_DOUBLE,MPI_COMM_WORLD);
		}
#endif
	}

	std::cout << m.GetProcessorRank() << " start clustering" << std::endl;

	int iter = 1;
	double t = Timer();
	while(true)
	{
		int changed = 0;

		// associates each point to the nearest center
#if defined(USE_OMP)
#pragma omp parallel for reduction(+:changed)
#endif
		for(int i = 0; i < total_points; i++)
		{
			int id_old_cluster = points_cluster[i];
			int id_nearest_center = -1;
			double lmin = 1.0e+100;

			for(int j = 0; j < K; ++j)
			{
				double v[3];
				v[0] = (points_center[i*3+0] - cluster_center[j*3+0]);
				v[1] = (points_center[i*3+1] - cluster_center[j*3+1]);
				v[2] = (points_center[i*3+2] - cluster_center[j*3+2]);

				double l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
				if( l < lmin )
				{
					lmin = l;
					id_nearest_center = j;
				}
			}

			if(id_old_cluster != id_nearest_center)
			{
				points_cluster[i] = id_nearest_center;
				changed++;
			}
		}

#if defined(USE_MPI)
		int tmp = changed;
		MPI_Allreduce(&tmp,&changed,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
#endif

		if(changed == 0 || iter >= max_iterations)
		{
			std::cout << m.GetProcessorRank() << " break in iteration " << iter << std::endl;
			break;
		}

		for(int i = 0; i < K; i++)
		{
			cluster_center[i*3+0] = 0;
			cluster_center[i*3+1] = 0;
			cluster_center[i*3+2] = 0;
			cluster_npoints[i] = 0;
		}
		// recalculating the center of each cluster
#if defined(USE_OMP)
#pragma omp parallel
#endif
		{
			std::vector< double > local_sum(K*3,0.0);
			std::vector< int > local_npoints(K,0);
			for(int j = 0; j < total_points; ++j)
			{
				local_sum[points_cluster[j]*3+0] += points_center[j*3+0];
				local_sum[points_cluster[j]*3+1] += points_center[j*3+1];
				local_sum[points_cluster[j]*3+2] += points_center[j*3+2];
				local_npoints[points_cluster[j]]++;
			}
#if defined(USE_OMP)
#pragma omp critical
#endif
			{
				for(int i = 0; i < K; ++i)
				{
					cluster_center[i*3+0] += local_sum[i*3+0];
					cluster_center[i*3+1] += local_sum[i*3+1];
					cluster_center[i*3+2] += local_sum[i*3+2];
					cluster_npoints[i] += local_npoints[i];
				}
			}
		}
#if defined(USE_MPI)
		MPI_Allreduce(&cluster_center[0],&cluster_center_tmp[0],K*3,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
		MPI_Allreduce(&cluster_npoints[0],&cluster_npoints_tmp[0],K,MPI_INT,MPI_SUM,MPI_COMM_WORLD);
		cluster_center.swap(cluster_center_tmp);
		cluster_npoints.swap(cluster_npoints_tmp);
#endif
		for(int i = 0; i < K; i++)
		{
			cluster_center[i*3+0] /= (double) cluster_npoints[i];
			cluster_center[i*3+1] /= (double) cluster_npoints[i];
			cluster_center[i*3+2] /= (double) cluster_npoints[i];
		}

		std::cout << "Iteration " << iter << std::endl;
		iter++;
	}
	std::cout << "Clustering in " << Timer() - t << " secs " << std::endl;
	// shows elements of clusters
	TagInteger mat = m.CreateTag("MATERIAL",DATA_INTEGER,CELL,NONE,1);
#if defined(USE_OMP)
#pragma omp parallel for
#endif
	for(int j = 0; j < total_points; ++j)
		mat[m.CellByLocalID(points_node[j])] = points_cluster[j]+1;
	m.ExchangeData(mat,CELL,0);

	m.Save(grid_out);

	Mesh::Finalize();
	return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"

#include "Property.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;
using namespace FTL;

namespace FTLTest
{
	class TestClass
	{
	public:
		// Value
		Property<TestClass, int, false, false, PropertyType::AutoGen> defaultProp;

		Property<TestClass, int, true, true, PropertyType::Manual> prop1{ [this]() { return innerI1; }, [this](int val) { innerI1 = val * val; } };
		Property<TestClass, int, false, true, PropertyType::Manual> prop2{ [this]() { return innerI2; }, [this](int val) { innerI2 = val * val; } };
		Property<TestClass, int, true, false, PropertyType::Manual> prop3{ [this]() { return innerI3; }, [this](int val) { innerI3 = val * val; } };
		Property<TestClass, int, false, false, PropertyType::Manual> prop4{ [this]() { return innerI4; }, [this](int val) { innerI4 = val * val; } };

		int innerI1, innerI2, innerI3, innerI4;

		int *pD, *p1, *p2, *p3, *p4;
		int pID, pI1, pI2, pI3, pI4;

		Property<TestClass, int*, false, false, PropertyType::AutoGen> pDefaultProp{ pD };

		Property<TestClass, int*, true, true, PropertyType::Manual> pProp1{ [this]() { return p1; }, [this](int* val) { p1 = val; } };
		Property<TestClass, int*, false, true, PropertyType::Manual> pProp2{ [this]() { return p2; }, [this](int* val) { p2 = val; } };
		Property<TestClass, int*, true, false, PropertyType::Manual> pProp3{ [this]() { return p3; }, [this](int* val) { p3 = val; } };
		Property<TestClass, int*, false, false, PropertyType::Manual> pProp4{ [this]() { return p4; }, [this](int* val) { p4 = val; } };

		// Pointer
		Property<TestClass, int*, false, false, PropertyType::AutoGen> ptrProp;

		// Smart Pointer
		Property<TestClass, shared_ptr<int>, false, false, PropertyType::AutoGen> smptrProp;

		// Getter only
		int goInnerValue;
		Property <TestClass, int, false, false, PropertyType::GetterOnly> go{ [this]() { return goInnerValue; } };

		// Setter only
		int soInnerValue;
		Property <TestClass, int, false, false, PropertyType::SetterOnly> so{ [this](int value) { soInnerValue = value; } };

		void Test()
		{
			defaultProp = 0;
			prop1 = 1;
			prop2 = 2;
			prop3 = 3;
			prop4 = 4;

			pDefaultProp = &pID;
			pProp1 = &pI1;
			pProp2 = &pI2;
			pProp3 = &pI3;
			pProp4 = &pI4;

			*pDefaultProp = 0;
			*pProp1 = 1;
			*pProp2 = 2;
			*pProp3 = 3;
			*pProp4 = 4;
		}
	};

	TEST_CLASS(PropertyTest)
	{
	public:
		TEST_METHOD(PropertyTest1)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter privateness
			Assert::AreEqual(false, IsGetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsGetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp4, nullptr));

			// Setter privateness
			Assert::AreEqual(false, IsSetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsSetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp4, nullptr));
		}

		TEST_METHOD(PropertyTest2)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter value
			Assert::AreEqual(0, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(1 * 1, static_cast<int>(cls.prop1)); // Compile error
			Assert::AreEqual(2 * 2, static_cast<int>(cls.prop2));
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(4 * 4, static_cast<int>(cls.prop4));

			// Setter value
			Assert::AreEqual(1, static_cast<int>(cls.defaultProp = 1));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1 = 2)); // Compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2 = 3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(cls.prop3 = 4));
			Assert::AreEqual(5, static_cast<int>(cls.prop4 = 5));

			// After set
			Assert::AreEqual(1 * 1, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1)); // Setter private, compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2)); // Setter private
			// Assert::AreEqual(4 * 4, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(5 * 5, static_cast<int>(cls.prop4));
		}

		TEST_METHOD(PropertyTest3)
		{
			FTLTest::TestClass cls;

			int dummyInt = 5555;
			int dummyInt1 = 6666;
			int dummyInt2 = 7777;
			int dummyInt3 = 8888;
			int dummyInt4 = 9999;

			Assert::AreEqual(&dummyInt, static_cast<int*>(cls.pDefaultProp = &dummyInt));
			// Assert::AreEqual(&dummyInt1, static_cast<int*>(cls.pProp1 = &dummyInt1)); // Compile error
			// Assert::AreEqual(&dummyInt2, static_cast<int*>(cls.pProp2 = &dummyInt2)); // Compile error
			Assert::AreEqual(&dummyInt3, static_cast<int*>(cls.pProp3 = &dummyInt3));
			Assert::AreEqual(&dummyInt4, static_cast<int*>(cls.pProp4 = &dummyInt4));
		}

		TEST_METHOD(PropertyTest4)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Pointer dereference(getter)
			Assert::AreEqual(0, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(1, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(2, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(3, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(*cls.pProp4));

			// Pointer deference(setter)
			*cls.pDefaultProp = 10;
			// *cls.pProp1 = 11; // Compile error
			*cls.pProp2 = 12;
			// *cls.pProp3 = 13; // Compile error
			*cls.pProp4 = 14;

			Assert::AreEqual(10, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(11, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(12, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(13, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(14, static_cast<int>(*cls.pProp4));
		}

		TEST_METHOD(PropertyTest5)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter only
			cls.goInnerValue = 3;
			// cls.go = 4; // Compile error
			Assert::AreEqual(3, cls.go.get());

			// Setter only
			cls.so = 6;
			Assert::AreEqual(6, cls.soInnerValue);
			// Assert::AreEqual(6, cls.so.get()); // Compile error
		}

		TEST_METHOD(PropertyTest6)
		{
			FTLTest::TestClass cls;
			cls.Test();

			Assert::AreEqual(false, cls.defaultProp.isPointer);
			Assert::AreEqual(false, cls.prop1.isPointer);
			Assert::AreEqual(false, cls.prop2.isPointer);
			Assert::AreEqual(false, cls.prop3.isPointer);
			Assert::AreEqual(false, cls.prop4.isPointer);

			Assert::AreEqual(true, cls.pDefaultProp.isPointer);
			Assert::AreEqual(true, cls.pProp1.isPointer);
			Assert::AreEqual(true, cls.pProp2.isPointer);
			Assert::AreEqual(true, cls.pProp3.isPointer);
			Assert::AreEqual(true, cls.pProp4.isPointer);
			Assert::AreEqual(true, cls.smptrProp.isPointer);
		}

	private:
		template <class T>
		constexpr bool IsGetterPrivate(const T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsGetterPrivate(const T&, decltype(typename declval<T>().operator T::InterfaceType())* ptr) const
		{
			return false;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T& val, decltype(val = typename T::InterfaceType())* ptr) const
		{
			return false;
		}

		// Sealed due to Visual Studio C++ compiler's bug.  Works well on clang.
		/*
		template <class T, class = void>
		class IsGetterPrivate : public true_type {};

		template <class T>
		class IsGetterPrivate<T, VoidTemplate<decltype(typename declval<T>().operator T::Type())>> : public false_type {};
		*/
	};
}<commit_msg>TMP bug fix<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"

#include "Property.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;
using namespace FTL;

namespace FTLTest
{
	class TestClass
	{
	public:
		// Value
		Property<TestClass, int, false, false, PropertyType::AutoGen> defaultProp;

		Property<TestClass, int, true, true, PropertyType::Manual> prop1{ [this]() { return innerI1; }, [this](int val) { innerI1 = val * val; } };
		Property<TestClass, int, false, true, PropertyType::Manual> prop2{ [this]() { return innerI2; }, [this](int val) { innerI2 = val * val; } };
		Property<TestClass, int, true, false, PropertyType::Manual> prop3{ [this]() { return innerI3; }, [this](int val) { innerI3 = val * val; } };
		Property<TestClass, int, false, false, PropertyType::Manual> prop4{ [this]() { return innerI4; }, [this](int val) { innerI4 = val * val; } };

		int innerI1, innerI2, innerI3, innerI4;

		int *pD, *p1, *p2, *p3, *p4;
		int pID, pI1, pI2, pI3, pI4;

		Property<TestClass, int*, false, false, PropertyType::AutoGen> pDefaultProp{ pD };

		Property<TestClass, int*, true, true, PropertyType::Manual> pProp1{ [this]() { return p1; }, [this](int* val) { p1 = val; } };
		Property<TestClass, int*, false, true, PropertyType::Manual> pProp2{ [this]() { return p2; }, [this](int* val) { p2 = val; } };
		Property<TestClass, int*, true, false, PropertyType::Manual> pProp3{ [this]() { return p3; }, [this](int* val) { p3 = val; } };
		Property<TestClass, int*, false, false, PropertyType::Manual> pProp4{ [this]() { return p4; }, [this](int* val) { p4 = val; } };

		// Pointer
		Property<TestClass, int*, false, false, PropertyType::AutoGen> ptrProp;

		// Smart Pointer
		Property<TestClass, shared_ptr<int>, false, false, PropertyType::AutoGen> smptrProp;

		// Getter only
		int goInnerValue;
		Property <TestClass, int, false, false, PropertyType::GetterOnly> go{ [this]() { return goInnerValue; } };

		// Setter only
		int soInnerValue;
		Property <TestClass, int, false, false, PropertyType::SetterOnly> so{ [this](int value) { soInnerValue = value; } };

		void Test()
		{
			defaultProp = 0;
			prop1 = 1;
			prop2 = 2;
			prop3 = 3;
			prop4 = 4;

			pDefaultProp = &pID;
			pProp1 = &pI1;
			pProp2 = &pI2;
			pProp3 = &pI3;
			pProp4 = &pI4;

			*pDefaultProp = 0;
			*pProp1 = 1;
			*pProp2 = 2;
			*pProp3 = 3;
			*pProp4 = 4;
		}
	};

	TEST_CLASS(PropertyTest)
	{
	public:
		TEST_METHOD(PropertyTest1)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter privateness
			Assert::AreEqual(false, IsGetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsGetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp4, nullptr));

			// Setter privateness
			Assert::AreEqual(false, IsSetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsSetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp4, nullptr));
		}

		TEST_METHOD(PropertyTest2)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter value
			Assert::AreEqual(0, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(1 * 1, static_cast<int>(cls.prop1)); // Compile error
			Assert::AreEqual(2 * 2, static_cast<int>(cls.prop2));
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(4 * 4, static_cast<int>(cls.prop4));

			// Setter value
			Assert::AreEqual(1, static_cast<int>(cls.defaultProp = 1));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1 = 2)); // Compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2 = 3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(cls.prop3 = 4));
			Assert::AreEqual(5, static_cast<int>(cls.prop4 = 5));

			// After set
			Assert::AreEqual(1 * 1, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1)); // Setter private, compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2)); // Setter private
			// Assert::AreEqual(4 * 4, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(5 * 5, static_cast<int>(cls.prop4));
		}

		TEST_METHOD(PropertyTest3)
		{
			FTLTest::TestClass cls;

			int dummyInt = 5555;
			int dummyInt1 = 6666;
			int dummyInt2 = 7777;
			int dummyInt3 = 8888;
			int dummyInt4 = 9999;

			Assert::AreEqual(&dummyInt, static_cast<int*>(cls.pDefaultProp = &dummyInt));
			// Assert::AreEqual(&dummyInt1, static_cast<int*>(cls.pProp1 = &dummyInt1)); // Compile error
			// Assert::AreEqual(&dummyInt2, static_cast<int*>(cls.pProp2 = &dummyInt2)); // Compile error
			Assert::AreEqual(&dummyInt3, static_cast<int*>(cls.pProp3 = &dummyInt3));
			Assert::AreEqual(&dummyInt4, static_cast<int*>(cls.pProp4 = &dummyInt4));
		}

		TEST_METHOD(PropertyTest4)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Pointer dereference(getter)
			Assert::AreEqual(0, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(1, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(2, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(3, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(*cls.pProp4));

			// Pointer deference(setter)
			*cls.pDefaultProp = 10;
			// *cls.pProp1 = 11; // Compile error
			*cls.pProp2 = 12;
			// *cls.pProp3 = 13; // Compile error
			*cls.pProp4 = 14;

			Assert::AreEqual(10, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(11, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(12, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(13, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(14, static_cast<int>(*cls.pProp4));
		}

		TEST_METHOD(PropertyTest5)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter only
			cls.goInnerValue = 3;
			// cls.go = 4; // Compile error
			Assert::AreEqual(3, cls.go.get());

			// Setter only
			cls.so = 6;
			Assert::AreEqual(6, cls.soInnerValue);
			// Assert::AreEqual(6, cls.so.get()); // Compile error
		}

		TEST_METHOD(PropertyTest6)
		{
			FTLTest::TestClass cls;
			cls.Test();

			Assert::AreEqual(false, cls.defaultProp.isPointer);
			Assert::AreEqual(false, cls.prop1.isPointer);
			Assert::AreEqual(false, cls.prop2.isPointer);
			Assert::AreEqual(false, cls.prop3.isPointer);
			Assert::AreEqual(false, cls.prop4.isPointer);

			Assert::AreEqual(true, cls.pDefaultProp.isPointer);
			Assert::AreEqual(true, cls.pProp1.isPointer);
			Assert::AreEqual(true, cls.pProp2.isPointer);
			Assert::AreEqual(true, cls.pProp3.isPointer);
			Assert::AreEqual(true, cls.pProp4.isPointer);
			Assert::AreEqual(true, cls.smptrProp.isPointer);
		}

	private:
		template <class T>
		constexpr bool IsGetterPrivate(const T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsGetterPrivate(const T&, decltype(declval<T>().operator typename T::InterfaceType())* ptr) const
		{
			return false;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T& val, decltype(val = typename T::InterfaceType())* ptr) const
		{
			return false;
		}

		// Sealed due to Visual Studio C++ compiler's bug.  Works well on clang.
		/*
		template <class T, class = void>
		class IsGetterPrivate : public true_type {};

		template <class T>
		class IsGetterPrivate<T, VoidTemplate<decltype(typename declval<T>().operator T::Type())>> : public false_type {};
		*/
	};
}<|endoftext|>


<commit_before>#include "ship_instance.h"
#include "weapon_instance.h"

ShipCarrier::ShipCarrier(int id, std::vector<float> d) : Ship(id, 1000, 400, d, 9.5, 1000, 1, 1) {
	this->add_weapon(new WeaponStandardGun());
	this->add_weapon(new WeaponStandardCannon());
}
ShipScout::ShipScout(int id, std::vector<float> d) : Ship(id, 200, 100, d, .2, 500, .5, .5) {
	this->add_weapon(new WeaponStandardGun());
}
ShipFighter::ShipFighter(int id, std::vector<float> d) : Ship(id, 400, 200, d, .4, 200, .5, .5) {
	this->add_weapon(new WeaponStandardGun());
	this->add_weapon(new WeaponStandardCannon());
}
<commit_msg>changed rotation speeds<commit_after>#include "ship_instance.h"
#include "weapon_instance.h"

ShipCarrier::ShipCarrier(int id, std::vector<float> d) : Ship(id, 1000, 400, d, 9.5, 1000, 1.5, 1.5) {
	this->add_weapon(new WeaponStandardGun());
	this->add_weapon(new WeaponStandardCannon());
}
ShipScout::ShipScout(int id, std::vector<float> d) : Ship(id, 200, 100, d, .2, 500, 1.5,1.5) {
	this->add_weapon(new WeaponStandardGun());
}
ShipFighter::ShipFighter(int id, std::vector<float> d) : Ship(id, 400, 200, d, .4, 200, 1.5, 1.5) {
	this->add_weapon(new WeaponStandardGun());
	this->add_weapon(new WeaponStandardCannon());
}
<|endoftext|>


<commit_before>/*****************************************************************************
// * This source file is part of ArkGameFrame                                *
// * For the latest info, see https://github.com/ArkGame                     *
// *                                                                         *
// * Copyright(c) 2013 - 2017 ArkGame authors.                               *
// *                                                                         *
// * Licensed under the Apache License, Version 2.0 (the "License");         *
// * you may not use this file except in compliance with the License.        *
// * You may obtain a copy of the License at                                 *
// *                                                                         *
// *     http://www.apache.org/licenses/LICENSE-2.0                          *
// *                                                                         *
// * Unless required by applicable law or agreed to in writing, software     *
// * distributed under the License is distributed on an "AS IS" BASIS,       *
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
// * See the License for the specific language governing permissions and     *
// * limitations under the License.                                          *
// *                                                                         *
// *                                                                         *
// * @file      AFPlatform.h                                                *
// * @author    Ark Game Tech                                                *
// * @date      2015-12-15                                                   *
// * @brief     AFPlatform                                                  *
*****************************************************************************/
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <limits>
#include <algorithm>
#include <utility>
#include <functional>
#include <cctype>
#include <iterator>
#include <unordered_map>
#include <stdint.h>
#include <functional>
#include <memory>
#include <signal.h>
#include <chrono>
#include <sstream>
#include <random>
#include <thread>

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
// only windows include
#include <io.h>
#include <time.h>
#ifndef WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <MSWSock.h>
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS

#define SIGHUP  1
#define SIGINT  2
#define SIGQUIT 3
#define SIGUSR1 10
#define SIGPIPE 13
#define SIGCHLD 17
#define SIGSYS  32

#else
// only other unix/linux include
#include <sys/socket.h>
#endif

#define ARK_LITTLE_ENDIAN
#define ARK_BIG_ENDIAN

#if !defined(ARK_ENDIAN)
#  if defined(USE_BIG_ENDIAN)
#    define ARK_ENDIAN ARK_BIG_ENDIAN
#  else
#     define ARK_ENDIAN ARK_LITTLE_ENDIAN
#  endif
#endif // !defined(ARK_ENDIAN)

#define PLATFORM_WIN    0
#define PLATFORM_UNIX   1
#define PLATFORM_APPLE  2

#define UNIX_FLAVOUR_LINUX  1
#define UNIX_FLAVOUR_BSD    2
#define UNIX_FLAVOUR_OTHER  3
#define UNIX_FLAVOUR_OSX    4

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
#  define ARK_PLATFORM PLATFORM_WIN
#elif defined(__APPLE_CC__)
#  define ARK_PLATFORM PLATFORM_APPLE
#else
#  define ARK_PLATFORM PLATFORM_UNIX
#endif

#define COMPILER_MICROSOFT  0
#define COMPILER_GNU        1
#define COMPILER_BORLAND    2
#define COMPILER_INTEL      3
#define COMPILER_CLANG      4

#define GOOGLE_STRIP_LOG    2

#ifdef _MSC_VER
#  define ARK_COMPILER COMPILER_MICROSOFT
#elif defined(__INTEL_COMPILER)
#  define ARK_COMPILER COMPILER_INTEL
#elif defined(__BORLANDC__)
#  define ARK_COMPILER COMPILER_BORLAND
#elif defined(__GNUC__)
#  define ARK_COMPILER COMPILER_GNU
#elif defined( __clang__ )
#  define ARK_COMPILER COMPILER_CLANG
#else
#  pragma error "FATAL ERROR: Unknown compiler."
#endif

#if ARK_PLATFORM == PLATFORM_UNIX || ARK_PLATFORM == PLATFORM_APPLE
#  if defined(HAVE_DARWIN)
#    define ARK_PLATFORM_NAME "MacOSX"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_OSX
#  elif defined(USE_KQUEUE)
#    define ARK_PLATFORM_NAME "FreeBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  elif defined(USE_KQUEUE_DFLY)
#    define ARK_PLATFORM_NAME "DragonFlyBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  else
#    define ARK_PLATFORM_NAME "Linux"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX
#  endif
#elif ARK_PLATFORM == PLATFORM_WIN
#  define ARK_PLATFORM_NAME "Windows"
#else
#  pragma error "FATAL ERROR: Unknown platform."
#endif

#define ARK_RUN_MODE_DEBUG      0
#define ARK_RUN_MODE_RELEASE    1

#ifndef ARK_RUN_MODE
#  if defined(DEBUG) || defined(_DEBUG)
#    define ARK_RUN_MODE ARK_RUN_MODE_DEBUG
#    define ARK_RUN_MODE_NAME "Debug"
#  else
#    define ARK_RUN_MODE ARK_RUN_MODE_RELEASE
#    define ARK_RUN_MODE_NAME "Release"
#  endif // DEBUG
#endif

#ifndef X64
#  if defined(_WIN64) || defined(__x86_64__) || defined(__amd64) || defined(__LP64__)
#    define X64
#  endif
#endif

#ifdef X64
#  define ARK_ARCH_NAME "X64"
#else
#  define ARK_ARCH_NAME "X86"
#endif // X64

#define ARK_LITTLE_ENDIAN

#ifndef ARK_DYNAMIC_PLUGIN
#define ARK_DYNAMIC_PLUGIN
#endif

<commit_msg>remove netmodule log<commit_after>/*****************************************************************************
// * This source file is part of ArkGameFrame                                *
// * For the latest info, see https://github.com/ArkGame                     *
// *                                                                         *
// * Copyright(c) 2013 - 2017 ArkGame authors.                               *
// *                                                                         *
// * Licensed under the Apache License, Version 2.0 (the "License");         *
// * you may not use this file except in compliance with the License.        *
// * You may obtain a copy of the License at                                 *
// *                                                                         *
// *     http://www.apache.org/licenses/LICENSE-2.0                          *
// *                                                                         *
// * Unless required by applicable law or agreed to in writing, software     *
// * distributed under the License is distributed on an "AS IS" BASIS,       *
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
// * See the License for the specific language governing permissions and     *
// * limitations under the License.                                          *
// *                                                                         *
// *                                                                         *
// * @file      AFPlatform.h                                                *
// * @author    Ark Game Tech                                                *
// * @date      2015-12-15                                                   *
// * @brief     AFPlatform                                                  *
*****************************************************************************/
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <limits>
#include <algorithm>
#include <utility>
#include <functional>
#include <cctype>
#include <iterator>
#include <unordered_map>
#include <stdint.h>
#include <functional>
#include <memory>
#include <signal.h>
#include <chrono>
#include <sstream>
#include <random>
#include <thread>

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
// only windows include
#include <io.h>
#include <time.h>
#ifndef WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <MSWSock.h>
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS

#define SIGHUP  1
#define SIGINT  2
#define SIGQUIT 3
#define SIGUSR1 10
#define SIGPIPE 13
#define SIGCHLD 17
#define SIGSYS  32

#else
// only other unix/linux include
#include <sys/socket.h>
#endif

#define ARK_LITTLE_ENDIAN
#define ARK_BIG_ENDIAN

#if !defined(ARK_ENDIAN)
#  if defined(USE_BIG_ENDIAN)
#    define ARK_ENDIAN ARK_BIG_ENDIAN
#  else
#     define ARK_ENDIAN ARK_LITTLE_ENDIAN
#  endif
#endif // !defined(ARK_ENDIAN)

#define PLATFORM_WIN    0
#define PLATFORM_UNIX   1
#define PLATFORM_APPLE  2

#define UNIX_FLAVOUR_LINUX  1
#define UNIX_FLAVOUR_BSD    2
#define UNIX_FLAVOUR_OTHER  3
#define UNIX_FLAVOUR_OSX    4

#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(__WIN64__) || defined(WIN64) || defined(_WIN64)
#  define ARK_PLATFORM PLATFORM_WIN
#elif defined(__APPLE_CC__)
#  define ARK_PLATFORM PLATFORM_APPLE
#else
#  define ARK_PLATFORM PLATFORM_UNIX
#endif

#define COMPILER_MICROSOFT  0
#define COMPILER_GNU        1
#define COMPILER_BORLAND    2
#define COMPILER_INTEL      3
#define COMPILER_CLANG      4

#ifdef _MSC_VER
#  define ARK_COMPILER COMPILER_MICROSOFT
#elif defined(__INTEL_COMPILER)
#  define ARK_COMPILER COMPILER_INTEL
#elif defined(__BORLANDC__)
#  define ARK_COMPILER COMPILER_BORLAND
#elif defined(__GNUC__)
#  define ARK_COMPILER COMPILER_GNU
#elif defined( __clang__ )
#  define ARK_COMPILER COMPILER_CLANG
#else
#  pragma error "FATAL ERROR: Unknown compiler."
#endif

#if ARK_PLATFORM == PLATFORM_UNIX || ARK_PLATFORM == PLATFORM_APPLE
#  if defined(HAVE_DARWIN)
#    define ARK_PLATFORM_NAME "MacOSX"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_OSX
#  elif defined(USE_KQUEUE)
#    define ARK_PLATFORM_NAME "FreeBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  elif defined(USE_KQUEUE_DFLY)
#    define ARK_PLATFORM_NAME "DragonFlyBSD"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#  else
#    define ARK_PLATFORM_NAME "Linux"
#    define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX
#  endif
#elif ARK_PLATFORM == PLATFORM_WIN
#  define ARK_PLATFORM_NAME "Windows"
#else
#  pragma error "FATAL ERROR: Unknown platform."
#endif

#define ARK_RUN_MODE_DEBUG      0
#define ARK_RUN_MODE_RELEASE    1

#ifndef ARK_RUN_MODE
#  if defined(DEBUG) || defined(_DEBUG)
#    define ARK_RUN_MODE ARK_RUN_MODE_DEBUG
#    define ARK_RUN_MODE_NAME "Debug"
#  else
#    define ARK_RUN_MODE ARK_RUN_MODE_RELEASE
#    define ARK_RUN_MODE_NAME "Release"
#  endif // DEBUG
#endif

#ifndef X64
#  if defined(_WIN64) || defined(__x86_64__) || defined(__amd64) || defined(__LP64__)
#    define X64
#  endif
#endif

#ifdef X64
#  define ARK_ARCH_NAME "X64"
#else
#  define ARK_ARCH_NAME "X86"
#endif // X64

#define ARK_LITTLE_ENDIAN

#ifndef ARK_DYNAMIC_PLUGIN
#define ARK_DYNAMIC_PLUGIN
#endif

<|endoftext|>


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

#include "condor_common.h"
#include "condor_config.h"
#include "match_prefix.h"
#include <termios.h>
#include <unistd.h>
#include <grp.h>
#include <signal.h>
#include <algorithm>

// condor_nsenter
//
// This is a replacement for the linux nsenter command to launch a
// shell inside a container.  We need this when running
// condor_ssh_to_job to a job that has been launched inside singularity
// Docker jobs use docker exec to enter the container, but there is no
// equivalent in singularity.  Standard nsenter isn't sufficient, as it
// does not create a pty for the shell, and we need different command
// line arguments to enter a non-setuid singularity container.  This
// is harder because the starter can't tell if singularity is setuid easily.
//
// The architecture for ssh-to-job to a contained job is to land in an sshd
// the starter forks *outside* the container.  This is important because we
// never want to assume anything about the container, even that there is an sshd
// inside it.  After the sshd starts, a script runs which runs condor_docker_enter
// (even for singularity), which connects to a Unix Domain Socket, passes
// stdin/out/err to the starter, which passes those to condor_nsenter, which
// is runs as root.  Rootly privilege is required to enter a setuid namespace
// so this is how we acquire.
//
// condor_nsenter enters the namespace, taking care to try to enter the user
// namespace, which is only set up for non-setuid singularity, and drops
// privileges to the uid and gid passed on the command line.  It sets up
// a pty for the shell to use, so all interactive processses will work.
//
// A final problem is environment variables.  Singularity, especially when
// managing GPUs, sets some nvidia-related environment variables that the
// condor starter doesn't know about.  So, condor_nsenter extracts the environment
// variables from the contained job process, and sets them in the shell
// it spawns.

void
usage( char *cmd )
{
	fprintf(stderr,"Usage: %s [options] condor_* ....\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"-t target_pid:\n");
	fprintf(stderr,"-S user_id:\n");
	fprintf(stderr,"-G group_id:\n");
	fprintf(stderr,"    -help              Display options\n");
}

#if (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 15)
// el6 doesn't have setns.  What are we going to do?
// what can we do?  Just not enter the container
int setns(int , int) {
        return 0;
}
#endif

// Before we exit, we need to reset the pty back to normal
// if we put it in raw mode

bool pty_is_raw = false;
struct termios old_tio;
void reset_pty_and_exit(int signo) {
	if (pty_is_raw)
		tcsetattr(0, TCSAFLUSH, &old_tio);
	exit(signo);
}

int main( int argc, char *argv[] )
{
	std::string condor_prefix;
	pid_t pid = 0;
	uid_t uid = 0;
	gid_t gid = 0;

	// parse command line args
	for( int i=1; i<argc; i++ ) {
		if(is_arg_prefix(argv[i],"-help")) {
			usage(argv[0]);
			exit(1);
		}

		// target pid to enter
		if(is_arg_prefix(argv[i],"-t")) {
			pid = atoi(argv[i + 1]);
			i++;
		}

		// uid to switch to
		if(is_arg_prefix(argv[i],"-S")) {
			uid = atoi(argv[i + 1]);
			i++;
		}

		// gid to switch to
		if(is_arg_prefix(argv[i],"-G")) {
			gid = atoi(argv[i + 1]);
			i++;
		}
	}

	if (pid < 1) {
		fprintf(stderr, "missing -t argument > 1\n");
		exit(1);
	}

	if (uid == 0) {
		fprintf(stderr, "missing -S argument > 1\n");
		exit(1);
	}

	if (gid == 0) {
		fprintf(stderr, "missing -G argument > 1\n");
		exit(1);
	}

	// slurp the enviroment out of our victim
	std::string env;
	std::string envfile;
	formatstr(envfile, "/proc/%d/environ", pid);

	int e = open(envfile.c_str(), O_RDONLY);
	if (e < 0) {
		fprintf(stderr, "Can't open %s %s\n", envfile.c_str(), strerror(errno));
		exit(1);
	}
	char buf[512];
	int bytesRead;
	while ((bytesRead = read(e, &buf, 512)) > 0) {
		env.append(buf, bytesRead);
	}
	close(e);

	// make a vector to hold all the pointers to env entries
	std::vector<const char *> envp;

	// the first one
	envp.push_back(env.c_str());
	auto it = env.begin();
	while (env.end() != (it = std::find(it, env.end(), '\0'))) {
		// skip past null terminator
		it++;
		if (& (*it)  != 0) {
			envp.push_back(& (*it));
		}
	}
	envp.push_back(0);
	envp.push_back(0);

	// grab the fd for the cwd -- need to get this outside
	// but chdir inside the container
	std::string cwdPath;
	formatstr(cwdPath, "/proc/%d/cwd", pid);
	int rootFd = open(cwdPath.c_str(), O_RDONLY);
	if (rootFd < 0) {
		fprintf(stderr, "Can't open %s\n", cwdPath.c_str());
	}

	std::string filename;

	// start changing namespaces.  Note that once we do this, things
	// get funny in this process
	formatstr(filename, "/proc/%d/ns/uts", pid);
	int fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open uts namespace: %d %s\n", errno, strerror(errno));
		exit(1);
	}
	int r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		// This means an unprivileged singularity, most likely
		// need to set user namespace instead.
		formatstr(filename, "/proc/%d/ns/user", pid);
		fd = open(filename.c_str(), O_RDONLY);
		if (fd < 0) {
			fprintf(stderr, "Can't open user namespace: %d %s\n", errno, strerror(errno));
			exit(1);
		}
		r = setns(fd, 0);
		close(fd);
		if (r < 0) {
			fprintf(stderr, "Can't setns to user namespace: %s\n", strerror(errno));
			exit(1);
		}
	}

	// now the pid namespace
	formatstr(filename, "/proc/%d/ns/pid", pid);
	fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open pid namespace: %s\n", strerror(errno));
		exit(1);
	}
	r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		fprintf(stderr, "Can't setns to pid namespace: %s\n", strerror(errno));
		exit(1);
	}

	// finally the mnt namespace
	formatstr(filename, "/proc/%d/ns/mnt", pid);
	fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open mnt namespace: %s\n", strerror(errno));
		exit(1);
	}
	r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		fprintf(stderr, "Can't setns to mnt namespace: %s\n", strerror(errno));
		exit(1);
	}

	setgroups(0, 0);

	// order matters!
	r = setgid(gid);
	if (r < 0) {
		fprintf(stderr, "Can't setgid to %d\n", gid);
		exit(1);
	}
	r = setuid(uid);
	if (r < 0) {
		fprintf(stderr, "Can't setuid to %d\n", uid);
		exit(1);
	}

	// now the pty handling
	int masterPty = -1;
	int workerPty = -1;
	masterPty = open("/dev/ptmx", O_RDWR);
	unlockpt(masterPty);

	if (masterPty < 0) {
		fprintf(stderr, "Can't open master pty %s\n", strerror(errno));
		exit(1);
	} else {
		workerPty = open(ptsname(masterPty), O_RDWR);
		if (workerPty < 0) {
			fprintf(stderr, "Can't open worker pty %s\n", strerror(errno));
			exit(1);
		}
	}
	int childpid = fork();
	if (childpid == 0) {

		// in the child --

		close(0);
		close(1);
		close(2);
		close(masterPty);

		dup2(workerPty, 0);
		dup2(workerPty, 1);
		dup2(workerPty, 2);

		// chdir to existing cwd
		int ret = fchdir(rootFd);
		if (ret < 0) {
			fprintf(stderr, "Can't open %s\n", cwdPath.c_str());
		}
		close(rootFd);

		// make this process group leader so shell job control works
		setsid();

		execle("/bin/sh", "/bin/sh", "-i", 0, envp.data());

		// Only get here if exec fails
		fprintf(stderr, "exec failed %d\n", errno);
		exit(errno);

	} else {

		// the parent
		fd_set readfds, writefds, exceptfds;
		bool keepGoing = true;

		// put the pty in raw mode
		struct termios tio;
		tcgetattr(0, &tio);
		pty_is_raw = true;
		old_tio = tio;
		tio.c_oflag &= ~(OPOST);
		tio.c_cflag |= (CS8);
		tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
		tio.c_cc[VMIN] = 1;
		tio.c_cc[VTIME] = 0;
		tcsetattr(0, TCSAFLUSH, &tio);

		struct sigaction handler;
		struct sigaction oldhandler;
		handler.sa_handler = reset_pty_and_exit;

		sigaction(SIGCHLD, &handler, &oldhandler);

		while (keepGoing) {
			FD_ZERO(&readfds);
			FD_ZERO(&writefds);
			FD_ZERO(&exceptfds);

			FD_SET(0, &readfds);
			FD_SET(masterPty, &readfds);

			select(masterPty + 1, &readfds, &writefds, &exceptfds, 0);

			if (FD_ISSET(masterPty, &readfds)) {
				char buf;
				int r = read(masterPty, &buf, 1);
				if (r > 0) {
					int ret = write(1, &buf, 1);
					if (ret < 0) {
						reset_pty_and_exit(0);
					}
				} else {
					keepGoing = false;
				}
			}

			if (FD_ISSET(0, &readfds)) {
				char buf;
				int r = read(0, &buf, 1);
				if (r > 0) {
					int ret = write(masterPty, &buf, 1);
					if (ret < 0) {
						reset_pty_and_exit(0);
					}
				} else {
					keepGoing = false;
				}
			}
		}
		int status;
		waitpid(childpid, &status, 0);
	}
	return 0;
}

<commit_msg>Make nsenter work with dash #7666<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2020, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_config.h"
#include "match_prefix.h"
#include <termios.h>
#include <unistd.h>
#include <grp.h>
#include <signal.h>
#include <algorithm>

// condor_nsenter
//
// This is a replacement for the linux nsenter command to launch a
// shell inside a container.  We need this when running
// condor_ssh_to_job to a job that has been launched inside singularity
// Docker jobs use docker exec to enter the container, but there is no
// equivalent in singularity.  Standard nsenter isn't sufficient, as it
// does not create a pty for the shell, and we need different command
// line arguments to enter a non-setuid singularity container.  This
// is harder because the starter can't tell if singularity is setuid easily.
//
// The architecture for ssh-to-job to a contained job is to land in an sshd
// the starter forks *outside* the container.  This is important because we
// never want to assume anything about the container, even that there is an sshd
// inside it.  After the sshd starts, a script runs which runs condor_docker_enter
// (even for singularity), which connects to a Unix Domain Socket, passes
// stdin/out/err to the starter, which passes those to condor_nsenter, which
// is runs as root.  Rootly privilege is required to enter a setuid namespace
// so this is how we acquire.
//
// condor_nsenter enters the namespace, taking care to try to enter the user
// namespace, which is only set up for non-setuid singularity, and drops
// privileges to the uid and gid passed on the command line.  It sets up
// a pty for the shell to use, so all interactive processses will work.
//
// A final problem is environment variables.  Singularity, especially when
// managing GPUs, sets some nvidia-related environment variables that the
// condor starter doesn't know about.  So, condor_nsenter extracts the environment
// variables from the contained job process, and sets them in the shell
// it spawns.

void
usage( char *cmd )
{
	fprintf(stderr,"Usage: %s [options] condor_* ....\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"-t target_pid:\n");
	fprintf(stderr,"-S user_id:\n");
	fprintf(stderr,"-G group_id:\n");
	fprintf(stderr,"    -help              Display options\n");
}

#if (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 15)
// el6 doesn't have setns.  What are we going to do?
// what can we do?  Just not enter the container
int setns(int , int) {
        return 0;
}
#endif

// Before we exit, we need to reset the pty back to normal
// if we put it in raw mode

bool pty_is_raw = false;
struct termios old_tio;
void reset_pty_and_exit(int signo) {
	if (pty_is_raw)
		tcsetattr(0, TCSAFLUSH, &old_tio);
	exit(signo);
}

int main( int argc, char *argv[] )
{
	std::string condor_prefix;
	pid_t pid = 0;
	uid_t uid = 0;
	gid_t gid = 0;

	// parse command line args
	for( int i=1; i<argc; i++ ) {
		if(is_arg_prefix(argv[i],"-help")) {
			usage(argv[0]);
			exit(1);
		}

		// target pid to enter
		if(is_arg_prefix(argv[i],"-t")) {
			pid = atoi(argv[i + 1]);
			i++;
		}

		// uid to switch to
		if(is_arg_prefix(argv[i],"-S")) {
			uid = atoi(argv[i + 1]);
			i++;
		}

		// gid to switch to
		if(is_arg_prefix(argv[i],"-G")) {
			gid = atoi(argv[i + 1]);
			i++;
		}
	}

	if (pid < 1) {
		fprintf(stderr, "missing -t argument > 1\n");
		exit(1);
	}

	if (uid == 0) {
		fprintf(stderr, "missing -S argument > 1\n");
		exit(1);
	}

	if (gid == 0) {
		fprintf(stderr, "missing -G argument > 1\n");
		exit(1);
	}

	// slurp the enviroment out of our victim
	std::string env;
	std::string envfile;
	formatstr(envfile, "/proc/%d/environ", pid);

	int e = open(envfile.c_str(), O_RDONLY);
	if (e < 0) {
		fprintf(stderr, "Can't open %s %s\n", envfile.c_str(), strerror(errno));
		exit(1);
	}
	char buf[512];
	int bytesRead;
	while ((bytesRead = read(e, &buf, 512)) > 0) {
		env.append(buf, bytesRead);
	}
	close(e);

	// make a vector to hold all the pointers to env entries
	std::vector<const char *> envp;

	// the first one
	envp.push_back(env.c_str());
	auto it = env.begin();
	while (env.end() != (it = std::find(it, env.end(), '\0'))) {
		// skip past null terminator
		it++;
		if (& (*it)  != 0) {
			envp.push_back(& (*it));
		}
	}
	envp.push_back(0);
	envp.push_back(0);

	// grab the fd for the cwd -- need to get this outside
	// but chdir inside the container
	std::string cwdPath;
	formatstr(cwdPath, "/proc/%d/cwd", pid);
	int rootFd = open(cwdPath.c_str(), O_RDONLY);
	if (rootFd < 0) {
		fprintf(stderr, "Can't open %s\n", cwdPath.c_str());
	}

	std::string filename;

	// start changing namespaces.  Note that once we do this, things
	// get funny in this process
	formatstr(filename, "/proc/%d/ns/uts", pid);
	int fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open uts namespace: %d %s\n", errno, strerror(errno));
		exit(1);
	}
	int r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		// This means an unprivileged singularity, most likely
		// need to set user namespace instead.
		formatstr(filename, "/proc/%d/ns/user", pid);
		fd = open(filename.c_str(), O_RDONLY);
		if (fd < 0) {
			fprintf(stderr, "Can't open user namespace: %d %s\n", errno, strerror(errno));
			exit(1);
		}
		r = setns(fd, 0);
		close(fd);
		if (r < 0) {
			fprintf(stderr, "Can't setns to user namespace: %s\n", strerror(errno));
			exit(1);
		}
	}

	// now the pid namespace
	formatstr(filename, "/proc/%d/ns/pid", pid);
	fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open pid namespace: %s\n", strerror(errno));
		exit(1);
	}
	r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		fprintf(stderr, "Can't setns to pid namespace: %s\n", strerror(errno));
		exit(1);
	}

	// finally the mnt namespace
	formatstr(filename, "/proc/%d/ns/mnt", pid);
	fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open mnt namespace: %s\n", strerror(errno));
		exit(1);
	}
	r = setns(fd, 0);
	close(fd);
	if (r < 0) {
		fprintf(stderr, "Can't setns to mnt namespace: %s\n", strerror(errno));
		exit(1);
	}

	setgroups(0, 0);

	// order matters!
	r = setgid(gid);
	if (r < 0) {
		fprintf(stderr, "Can't setgid to %d\n", gid);
		exit(1);
	}
	r = setuid(uid);
	if (r < 0) {
		fprintf(stderr, "Can't setuid to %d\n", uid);
		exit(1);
	}

	struct winsize win;
	ioctl(0, TIOCGWINSZ, &win);

	// now the pty handling
	int masterPty = -1;
	int workerPty = -1;
	masterPty = open("/dev/ptmx", O_RDWR);
	unlockpt(masterPty);

	if (masterPty < 0) {
		fprintf(stderr, "Can't open master pty %s\n", strerror(errno));
		exit(1);
	} else {
		workerPty = open(ptsname(masterPty), O_RDWR);
		if (workerPty < 0) {
			fprintf(stderr, "Can't open worker pty %s\n", strerror(errno));
			exit(1);
		}
	}
	int childpid = fork();
	if (childpid == 0) {

		// in the child --

		close(0);
		close(1);
		close(2);
		close(masterPty);

		dup2(workerPty, 0);
		dup2(workerPty, 1);
		dup2(workerPty, 2);

		// chdir to existing cwd
		int ret = fchdir(rootFd);
		if (ret < 0) {
			fprintf(stderr, "Can't open %s\n", cwdPath.c_str());
		}
		close(rootFd);

		// make this process group leader so shell job control works
		setsid();

		// Make the pty the controlling terminal
		ioctl(workerPty, TIOCSCTTY, 0);

		// and make it the process group leader
		tcsetpgrp(workerPty, getpid());

		// and set the window size properly
		ioctl(0, TIOCSWINSZ, &win);

		// Finally, launch the shell
		execle("/bin/sh", "/bin/sh", "-l", "-i", nullptr, envp.data());

		// Only get here if exec fails
		fprintf(stderr, "exec failed %d\n", errno);
		exit(errno);

	} else {

		// the parent
		fd_set readfds, writefds, exceptfds;
		bool keepGoing = true;

		// put the pty in raw mode
		struct termios tio;
		tcgetattr(0, &tio);
		pty_is_raw = true;
		old_tio = tio;
		tio.c_oflag &= ~(OPOST);
		tio.c_cflag |= (CS8);
		tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
		tio.c_cc[VMIN] = 1;
		tio.c_cc[VTIME] = 0;
		tcsetattr(0, TCSAFLUSH, &tio);

		struct sigaction handler;
		struct sigaction oldhandler;
		handler.sa_handler = reset_pty_and_exit;
		handler.sa_flags   = 0;

		sigaction(SIGCHLD, &handler, &oldhandler);

		while (keepGoing) {
			FD_ZERO(&readfds);
			FD_ZERO(&writefds);
			FD_ZERO(&exceptfds);

			FD_SET(0, &readfds);
			FD_SET(masterPty, &readfds);

			select(masterPty + 1, &readfds, &writefds, &exceptfds, 0);

			if (FD_ISSET(masterPty, &readfds)) {
				char buf;
				int r = read(masterPty, &buf, 1);
				if (r > 0) {
					int ret = write(1, &buf, 1);
					if (ret < 0) {
						reset_pty_and_exit(0);
					}
				} else {
					keepGoing = false;
				}
			}

			if (FD_ISSET(0, &readfds)) {
				char buf;
				int r = read(0, &buf, 1);
				if (r > 0) {
					int ret = write(masterPty, &buf, 1);
					if (ret < 0) {
						reset_pty_and_exit(0);
					}
				} else {
					keepGoing = false;
				}
			}
		}
		int status;
		waitpid(childpid, &status, 0);
	}
	return 0;
}

<|endoftext|>


<commit_before>/// This is where the magic happens; program your plug-in's core behavior here.

#include "game_hooks.h"
#include <graphics/graphics.h>
#include <SCBW/api.h>
#include <SCBW/scbwdata.h>
#include <SCBW/ExtendSightLimit.h>
#include "psi_field.h"
#include <cstdio>

namespace hooks {

/// This hook is called every frame; most of your plugin's logic goes here.
bool nextFrame() {
  if (!scbw::isGamePaused()) { //If the game is not paused
    graphics::resetAllGraphics();
    hooks::updatePsiFieldProviders();

    if (*elapsedTimeFrames == 0) {
      scbw::printText("Hello, world!");
    }

    // Loop through all visible units in the game.
    for (CUnit *unit = *firstVisibleUnit; unit; unit = unit->link.next) {
      //Write your code here
    }

    // Loop through all bullets in the game
    //for (BULLET* bullet = *firstBullet; bullet; bullet = bullet->next) {
    //  //Write your code here
    //}
  }
  return true;
}

bool gameOn() {
  return true;
}

bool gameEnd() {
  return true;
}

} //hooks
<commit_msg>GPTP: Cleanup game_hooks.cpp<commit_after>/// This is where the magic happens; program your plug-in's core behavior here.

#include "game_hooks.h"
#include <graphics/graphics.h>
#include <SCBW/api.h>
#include <SCBW/scbwdata.h>
#include <SCBW/ExtendSightLimit.h>
#include "psi_field.h"
#include <cstdio>

namespace hooks {

/// This hook is called every frame; most of your plugin's logic goes here.
bool nextFrame() {
  if (!scbw::isGamePaused()) { //If the game is not paused
    graphics::resetAllGraphics();
    hooks::updatePsiFieldProviders();

    //This block is executed once every game.
    if (*elapsedTimeFrames == 0) {
      //Write your code here
      scbw::printText(PLUGIN_NAME ": Hello, world!");
    }

    //Loop through all visible units in the game.
    for (CUnit *unit = *firstVisibleUnit; unit; unit = unit->link.next) {
      //Write your code here
    }
  }
  return true;
}

bool gameOn() {
  return true;
}

bool gameEnd() {
  return true;
}

} //hooks
<|endoftext|>


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

/* $Id$ */

#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>

#include "AliAnalysisTaskJets.h"
#include "AliAnalysisManager.h"
#include "AliJetFinder.h"
#include "AliJetHistos.h"
#include "AliESDEvent.h"
#include "AliESD.h"
#include "AliAODEvent.h"
#include "AliAODHandler.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"

ClassImp(AliAnalysisTaskJets)

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

AliAnalysisTaskJets::AliAnalysisTaskJets():
    fDebug(0),
    fJetFinder(0x0),
    fTree(0x0),
    fESD(0x0),
    fAOD(0x0),
    fTreeA(0x0),
    fHistos(0x0),
    fListOfHistos(0x0)
{
  // Default constructor
}

AliAnalysisTaskJets::AliAnalysisTaskJets(const char* name):
    AliAnalysisTask(name, "AnalysisTaskJets"),
    fDebug(0),
    fJetFinder(0x0),
    fTree(0x0),
    fESD(0x0),
    fAOD(0x0),
    fTreeA(0x0),
    fHistos(0x0),
    fListOfHistos(0x0)
{
  // Default constructor
    DefineInput (0, TChain::Class());
    DefineOutput(0, TTree::Class());
    DefineOutput(1, TList::Class());
}

void AliAnalysisTaskJets::CreateOutputObjects()
{
// Create the output container
//
//  Default AOD
    if (fDebug > 1) printf("AnalysisTaskJets::CreateOutPutData() \n");
    AliAODHandler* handler = (AliAODHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());

    fAOD   = handler->GetAOD();
    fTreeA = handler->GetTree();
    fJetFinder->ConnectAOD(fAOD);
//
//  Histograms
    OpenFile(1);
    fListOfHistos = new TList();
    fHistos       = new AliJetHistos();
    fHistos->AddHistosToList(fListOfHistos);
}

void AliAnalysisTaskJets::Init()
{
    // Initialization
    if (fDebug > 1) printf("AnalysisTaskJets::Init() \n");

    // Call configuration file
    gROOT->LoadMacro("ConfigJetAnalysis.C");
    fJetFinder = (AliJetFinder*) gInterpreter->ProcessLine("ConfigJetAnalysis()");
    // Initialise Jet Analysis
    fJetFinder->Init();
    // Write header information to local file
    fJetFinder->WriteHeaders();
}

void AliAnalysisTaskJets::ConnectInputData(Option_t */*option*/)
{
// Connect the input data
    if (fDebug > 1) printf("AnalysisTaskJets::ConnectInputData() \n");
    AliESDInputHandler* esdH = (AliESDInputHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler());
    AliESDEvent* fESD = esdH->GetEvent();
    fTree = esdH->GetTree();

    AliMCEventHandler*    mcTruth = (AliMCEventHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());

    fJetFinder->GetReader()->SetInputEvent(fESD, fAOD, mcTruth);
}

void AliAnalysisTaskJets::Exec(Option_t */*option*/)
{
// Execute analysis for current event
//
    AliMCEventHandler*    mctruth = (AliMCEventHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());
    if (mctruth) {
	AliStack* stack = mctruth->MCEvent()->Stack();
	//printf("AliAnalysisTaskJets: Number of tracks on stack %5d\n", stack->GetNtrack());
    }

    Long64_t ientry = fTree->GetReadEntry();
    if (fDebug > 1) printf("Analysing event # %5d\n", (Int_t) ientry);
    fJetFinder->ProcessEvent(ientry);

    // Fill control histos
    fHistos->FillHistos(fAOD->GetJets());

    // Post the data
    PostData(0, fTreeA);
    PostData(1, fListOfHistos);
}

void AliAnalysisTaskJets::Terminate(Option_t */*option*/)
{
// Terminate analysis
//
    if (fDebug > 1) printf("AnalysisJets: Terminate() \n");
//    if (fJetFinder) fJetFinder->FinishRun();
}

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

/* $Id$ */

#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>

#include "AliAnalysisTaskJets.h"
#include "AliAnalysisManager.h"
#include "AliJetFinder.h"
#include "AliJetHistos.h"
#include "AliESDEvent.h"
#include "AliESD.h"
#include "AliAODEvent.h"
#include "AliAODHandler.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"

ClassImp(AliAnalysisTaskJets)

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

AliAnalysisTaskJets::AliAnalysisTaskJets():
    fDebug(0),
    fJetFinder(0x0),
    fTree(0x0),
    fESD(0x0),
    fAOD(0x0),
    fTreeA(0x0),
    fHistos(0x0),
    fListOfHistos(0x0)
{
  // Default constructor
}

AliAnalysisTaskJets::AliAnalysisTaskJets(const char* name):
    AliAnalysisTask(name, "AnalysisTaskJets"),
    fDebug(0),
    fJetFinder(0x0),
    fTree(0x0),
    fESD(0x0),
    fAOD(0x0),
    fTreeA(0x0),
    fHistos(0x0),
    fListOfHistos(0x0)
{
  // Default constructor
    DefineInput (0, TChain::Class());
    DefineOutput(0, TTree::Class());
    DefineOutput(1, TList::Class());
}

void AliAnalysisTaskJets::CreateOutputObjects()
{
// Create the output container
//
//  Default AOD
    if (fDebug > 1) printf("AnalysisTaskJets::CreateOutPutData() \n");
    AliAODHandler* handler = (AliAODHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());

    fAOD   = handler->GetAOD();
    fTreeA = handler->GetTree();
    fJetFinder->ConnectAOD(fAOD);
//
//  Histograms
    OpenFile(1);
    fListOfHistos = new TList();
    fHistos       = new AliJetHistos();
    fHistos->AddHistosToList(fListOfHistos);
}

void AliAnalysisTaskJets::Init()
{
    // Initialization
    if (fDebug > 1) printf("AnalysisTaskJets::Init() \n");

    // Call configuration file
    gROOT->LoadMacro("ConfigJetAnalysis.C");
    fJetFinder = (AliJetFinder*) gInterpreter->ProcessLine("ConfigJetAnalysis()");
    // Initialise Jet Analysis
    fJetFinder->Init();
    // Write header information to local file
    fJetFinder->WriteHeaders();
}

void AliAnalysisTaskJets::ConnectInputData(Option_t */*option*/)
{
// Connect the input data
    if (fDebug > 1) printf("AnalysisTaskJets::ConnectInputData() \n");
    AliESDInputHandler* esdH = (AliESDInputHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler());
    fESD = esdH->GetEvent();
    fTree = esdH->GetTree();

    AliMCEventHandler*    mcTruth = (AliMCEventHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());

    fJetFinder->GetReader()->SetInputEvent(fESD, fAOD, mcTruth);
}

void AliAnalysisTaskJets::Exec(Option_t */*option*/)
{
// Execute analysis for current event
//
    AliMCEventHandler*    mctruth = (AliMCEventHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());
    if (mctruth) {
	AliStack* stack = mctruth->MCEvent()->Stack();
	//printf("AliAnalysisTaskJets: Number of tracks on stack %5d\n", stack->GetNtrack());
    }

    Long64_t ientry = fTree->GetReadEntry();
    if (fDebug > 1) printf("Analysing event # %5d\n", (Int_t) ientry);
    fJetFinder->ProcessEvent(ientry);

    // Fill control histos
    fHistos->FillHistos(fAOD->GetJets());

    // Post the data
    PostData(0, fTreeA);
    PostData(1, fListOfHistos);
}

void AliAnalysisTaskJets::Terminate(Option_t */*option*/)
{
// Terminate analysis
//
    if (fDebug > 1) printf("AnalysisJets: Terminate() \n");
//    if (fJetFinder) fJetFinder->FinishRun();
}

<|endoftext|>


<commit_before>/*
    Copyright (C) 2012  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "filters.h"

#include <QtGui/QTextDocument> //needed for Qt::escape

EscapeFilter::EscapeFilter(QObject *parent)
    : AbstractMessageFilter(parent)
{
}

void EscapeFilter::filterMessage(Message& message)
{
    QString escapedMessage = Qt::escape(message.mainMessagePart());

    escapedMessage.replace(QLatin1String("\n "), QLatin1String("
 ")); //keep leading whitespaces
    escapedMessage.replace(QLatin1Char('\n'), QLatin1String("
"));
    escapedMessage.replace(QLatin1Char('\t'), QLatin1String("    ")); // replace tabs by 4 spaces
    escapedMessage.replace(QLatin1String("  "), QLatin1String("  ")); // keep multiple whitespaces
    escapedMessage.replace(QLatin1Char('\\'), QLatin1String("\\\\")); //replace a single backslash with two backslashes.

    message.setMainMessagePart(escapedMessage);
}<commit_msg>Move replacement not needed by appendScript to escapeFilter<commit_after>/*
    Copyright (C) 2012  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "filters.h"

#include <QtGui/QTextDocument> //needed for Qt::escape

EscapeFilter::EscapeFilter(QObject *parent)
    : AbstractMessageFilter(parent)
{
}

void EscapeFilter::filterMessage(Message& message)
{
    QString escapedMessage = Qt::escape(message.mainMessagePart());

    escapedMessage.replace(QLatin1String("\n "), QLatin1String("
 ")); //keep leading whitespaces
    escapedMessage.replace(QLatin1Char('\n'), QLatin1String("
"));
    escapedMessage.replace(QLatin1Char('\r'), QLatin1String("
"));
    escapedMessage.replace(QLatin1Char('\t'), QLatin1String("    ")); // replace tabs by 4 spaces
    escapedMessage.replace(QLatin1String("  "), QLatin1String("  ")); // keep multiple whitespaces
    escapedMessage.replace(QLatin1Char('\\'), QLatin1String("\\\\")); //replace a single backslash with two backslashes.

    message.setMainMessagePart(escapedMessage);
}<|endoftext|>


<commit_before>// AntAppSkeleton.cpp

#include "AntAppSkeleton.h"

AntAppSkeleton::AntAppSkeleton()
: m_bar(NULL)
{
}

AntAppSkeleton::~AntAppSkeleton()
{
    ///@todo Delete this before glfw
    //delete m_bar;
}

void AntAppSkeleton::_InitializeBar()
{
    // Create a tweak bar
    m_bar = TwNewBar("TweakBar");
    TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.

    TwAddVarRW(m_bar, "rotation x", TW_TYPE_FLOAT, &g_rotation.x,
               " label='Rot x' min=0 max=360 step=1.0 keyIncr=a keyDecr=A help='Rotation x' ");
    TwAddVarRW(m_bar, "rotation y", TW_TYPE_FLOAT, &g_rotation.y,
               " label='Rot y' min=0 max=360 step=1.0 keyIncr=s keyDecr=S help='Rotation y' ");
    TwAddVarRW(m_bar, "rotation z", TW_TYPE_FLOAT, &g_rotation.z,
               " label='Rot z' min=0 max=360 step=1.0 keyIncr=d keyDecr=D help='Rotation z' ");
}

bool AntAppSkeleton::initGL(int argc, char **argv)
{
    TwInit(TW_OPENGL, NULL);
    _InitializeBar();
    return TriAppSkeleton::initGL(argc, argv);
}

void AntAppSkeleton::display() const
{
    TriAppSkeleton::display();
    TwDraw(); ///@todo Should this go first? Will it write to a depth buffer?
}

void AntAppSkeleton::mouseDown(int button, int state, int x, int y)
{
    TwEventMouseButtonGLFW(button, state);
}

void AntAppSkeleton::mouseMove(int x, int y)
{
    TwEventMousePosGLFW(x, y);
}

void AntAppSkeleton::mouseWheel(int x, int y)
{
    TwEventMouseWheelGLFW(x);
}

void AntAppSkeleton::keyboard(int key, int x, int y)
{
    TwEventKeyGLFW(key, 0);
}

void AntAppSkeleton::charkey(unsigned int key)
{
    TwEventCharGLFW(key, 0);
}<commit_msg>Plugged in callback fallthroughs, key action still broken in Ant.<commit_after>// AntAppSkeleton.cpp

#include "AntAppSkeleton.h"

AntAppSkeleton::AntAppSkeleton()
: m_bar(NULL)
{
}

AntAppSkeleton::~AntAppSkeleton()
{
    ///@todo Delete this before glfw
    //delete m_bar;
}

void AntAppSkeleton::_InitializeBar()
{
    // Create a tweak bar
    m_bar = TwNewBar("TweakBar");
    TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.

    TwAddVarRW(m_bar, "rotation x", TW_TYPE_FLOAT, &g_rotation.x,
               " label='Rot x' min=0 max=360 step=1.0 keyIncr=a keyDecr=A help='Rotation x' ");
    TwAddVarRW(m_bar, "rotation y", TW_TYPE_FLOAT, &g_rotation.y,
               " label='Rot y' min=0 max=360 step=1.0 keyIncr=s keyDecr=S help='Rotation y' ");
    TwAddVarRW(m_bar, "rotation z", TW_TYPE_FLOAT, &g_rotation.z,
               " label='Rot z' min=0 max=360 step=1.0 keyIncr=d keyDecr=D help='Rotation z' ");
}

bool AntAppSkeleton::initGL(int argc, char **argv)
{
    TwInit(TW_OPENGL, NULL);
    _InitializeBar();
    return TriAppSkeleton::initGL(argc, argv);
}

void AntAppSkeleton::display() const
{
    TriAppSkeleton::display();
    TwDraw(); ///@todo Should this go first? Will it write to a depth buffer?
}

void AntAppSkeleton::mouseDown(int button, int state, int x, int y)
{
    int ant = TwEventMouseButtonGLFW(button, state);
    if (ant != 0)
        return;
    TriAppSkeleton::mouseDown(button, state, x, y);
}

void AntAppSkeleton::mouseMove(int x, int y)
{
    TwEventMousePosGLFW(x, y);
    TriAppSkeleton::mouseMove(x, y);
}

void AntAppSkeleton::mouseWheel(int x, int y)
{
    TwEventMouseWheelGLFW(x);
    //TriAppSkeleton::mouseWheel(x, y);
}

void AntAppSkeleton::keyboard(int key, int x, int y)
{
    int ant = TwEventKeyGLFW(key, 0);
    if (ant != 0)
        return;
    TriAppSkeleton::keyboard(key, x, y);
}

void AntAppSkeleton::charkey(unsigned int key)
{
    int ant = TwEventCharGLFW(key, 0);
    if (ant != 0)
        return;
    TriAppSkeleton::keyboard(key, 0, 0);
}
<|endoftext|>