<commit_before>// Copyright (c) 2014, ultramailman
// This file is licensed under the MIT License.

#ifndef CHTABLE_H
#define CHTABLE_H
#include <vector>
#include <tuple>
#include <memory>
namespace{
	bool isPrime(unsigned x)
	{
		if((x & 1) != 1) {
			return false;
		}
		char easy [] = {0, 1, 1, 1, 0, 1, 0, 1};
		if(x < sizeof easy) {
			return easy[x] != 0;
		}

		unsigned const half = x / 2;
		for(unsigned i = 3; i < half; i+=2){
			if(x % i == 0)
				return false;
		}
		return true;
	}
	unsigned nextPrime(unsigned const x)
	{
		unsigned n = x;
		if(n / 2 * 2 == n) {
			n++;
		}
		while(!isPrime(n)) {
			n += 2;
		}

		if(n >= x) {
			return n;
		} else {
			return -1;
		}
	}
}

namespace chtable{
	template <class K>
	struct Hash;

}
template <class K, class V, unsigned slots>
struct Bucket{
	unsigned count;
	K keys[slots];
	V vals[slots];
	bool full() const
	{
		return count == slots;
	}
	int Find(K const & key) const
	{
		for(unsigned i = 0; i < count; i++)
		{
			if(keys[i] == key)
			{
				return i;
			}
		}
		return -1;
	}
	void Insert(K key, V val)
	{
		keys[count] = key;
		vals[count] = val;
		count++;
	}
	bool Delete(K const & key)
	{
		for(unsigned i = 0; i < count; i++)
		{
			if(keys[i] == key)
			{
				count--;
				//std::swap(keys[i], keys[count]);
				//std::swap(vals[i], vals[count]);
				keys[i] = std::move(keys[count]);
				vals[i] = std::move(vals[count]);
				return true;
			}
		}
		return false;
	}
};

template <
	class K, class V,
	unsigned slots = 2,
	class Alloc = std::allocator< Bucket<K, V, slots> >
>
class Chtable{
	unsigned count_;
	unsigned tables_;
	unsigned table_buckets_;
	unsigned total_buckets_;
	unsigned total_slots_;

	std::vector< Bucket<K, V, slots>, Alloc > array_;
	chtable::Hash<K> uhash_;

public:
	Chtable( unsigned size , unsigned tables )
	:
		count_(0),

		tables_(tables),
		table_buckets_( nextPrime(size / tables / slots + 1) ),
		total_buckets_( tables_ * table_buckets_ ),
		total_slots_(total_buckets_ * slots),

		array_(total_buckets_),

		uhash_(tables_, table_buckets_)
	{}

	Chtable() : Chtable(13, 2) {}

	unsigned count() const
	{
		return count_;
	}
	unsigned capacity() const
	{
		return total_slots_;
	}
private:
	unsigned index(unsigned table, unsigned hash) const
	{
		return table * table_buckets_ + hash;
	}
public:
	//..................................ITERATOR
	struct Pair{
		K key;
		V val;
		Pair(K k, V v):key(k), val(v){}
	};
	class Iter{
		unsigned bucket_i;
		unsigned slot_i;
		Chtable<K, V, slots, Alloc> const * t;
	public:
		Iter(unsigned bucket, unsigned slot, Chtable<K, V, slots, Alloc> const * table)
		:
			bucket_i(bucket),
			slot_i(slot),
			t(table)
		{}
		bool operator != (Iter const & other)
		{
			return other.bucket_i != bucket_i or other.slot_i != slot_i or other.t != t;
		}
		const Iter & operator++()
		{
			if(t == nullptr)
			{
				return *this;
			}

			slot_i++;
			if(slot_i < t->array_[bucket_i].count)
			{
				return *this;
			}

			slot_i = 0;
			bucket_i++;
			while(bucket_i < t->total_buckets_)
			{
				if(slot_i < t->array_[bucket_i].count)
				{
					return *this;
				}
				bucket_i++;
			}
			slot_i = -1;
			bucket_i = -1;
			t = nullptr;
			return *this;
		}
		Pair operator*()
		{
			auto & bucket = t->array_[bucket_i];
			auto & key = bucket.keys[slot_i];
			auto & val = bucket.vals[slot_i];
			return Pair(key, val);
		}
	};

	Iter begin() const
	{
		Iter iter(0, -1, this);
		++iter;
		return iter;
	}
	Iter end() const
	{
		return Iter(-1, -1, nullptr);
	}
	//.......................... SEARCH ......................................
	std::tuple<V, bool> Get(K const & key) const
	{
		for(unsigned i = 0; i < tables_; i++)
		{
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto const & bucket = array_[bucket_i];
			int slot_i = bucket.Find(key);

			if(slot_i >= 0)
			{
				V ret = bucket.vals[slot_i];
				return std::make_tuple(ret, true);
			}
		}
		return std::make_tuple(V(), false);
	}
	//............................ INSERTION ..................................
private:
	// update val if key is found
	bool update(K const & key, V val)
	{
		for(unsigned i = 0; i < tables_; i++) {
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto & bucket = array_[bucket_i];
			int slot_i = bucket.Find(key);

			if(slot_i >= 0)
			{
				bucket.vals[slot_i] = val;
				return true;
			}
		}
		return false;
	}
	// try to infiltrate a table.
	// true for peaceful infiltration
	// false for eviction
	bool infiltrate(K & key, V & val, unsigned i)
	{
		unsigned hash = uhash_(i, key) % table_buckets_;
		unsigned bucket_i = index(i, hash);

		auto & bucket = array_[bucket_i];
		if(not bucket.full())
		{
			bucket.Insert(key, val);
			count_++;
			return true;
		}

		std::swap(bucket.keys[0], key);
		std::swap(bucket.vals[0], val);

		return false;
	}

	// try to set a new value.
	// true if successful.
	// false if cycle.
	bool trySet(K key, V val)
	{
		K const original = key;
		unsigned tries = tables_ + 1;
		unsigned i = 0;
		while(1)
		{
			if(infiltrate(key, val, i))
			{
				return true;
			}
			if(key == original)
			{
				tries--;
				if(tries == 0)
				{
					return false;
				}
			}
			i++;
			if(i == tables_)
			{
				i = 0;
			}
		}
		return false;

	}
	bool grow(unsigned factor)
	{
		unsigned newSize = nextPrime(capacity() * factor);
		Chtable<K, V, slots, Alloc> bigger( newSize , tables_);
		for(auto slot : *this)
		{
			if(not bigger.trySet(slot.key, slot.val))
			{
				return false;
			}

		}
		std::swap(*this, bigger);
		return true;
	}
public:
	void Set(K key, V val)
	{
		if(update(key, val))
		{
			return;
		}
		while(not trySet(key, val))
		{
			unsigned factor = 2;
			while(not grow( factor ))
			{
				factor++;
			}
		}
	}
	//................................... DELETION .......................
	bool Delete(K const & key)
	{
		for(unsigned i = 0; i < tables_; i++)
		{
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto & bucket = array_[bucket_i];
			if(bucket.Delete(key))
			{
				return true;
			}
		}
		return false;
	}

};

#endif
<commit_msg>added some moves<commit_after>// Copyright (c) 2014, ultramailman
// This file is licensed under the MIT License.

#ifndef CHTABLE_H
#define CHTABLE_H
#include <vector>
#include <tuple>
#include <memory>
namespace{
	bool isPrime(unsigned x)
	{
		if((x & 1) != 1) {
			return false;
		}
		char easy [] = {0, 1, 1, 1, 0, 1, 0, 1};
		if(x < sizeof easy) {
			return easy[x] != 0;
		}

		unsigned const half = x / 2;
		for(unsigned i = 3; i < half; i+=2){
			if(x % i == 0)
				return false;
		}
		return true;
	}
	unsigned nextPrime(unsigned const x)
	{
		unsigned n = x;
		if(n / 2 * 2 == n) {
			n++;
		}
		while(!isPrime(n)) {
			n += 2;
		}

		if(n >= x) {
			return n;
		} else {
			return -1;
		}
	}
}

namespace chtable{
	template <class K>
	struct Hash;

}
template <class K, class V, unsigned slots>
struct Bucket{
	unsigned count;
	K keys[slots];
	V vals[slots];
	bool full() const
	{
		return count == slots;
	}
	int Find(K const & key) const
	{
		for(unsigned i = 0; i < count; i++)
		{
			if(keys[i] == key)
			{
				return i;
			}
		}
		return -1;
	}
	void Insert(K key, V val)
	{
		keys[count] = key;
		vals[count] = val;
		count++;
	}
	bool Delete(K const & key)
	{
		for(unsigned i = 0; i < count; i++)
		{
			if(keys[i] == key)
			{
				count--;
				keys[i] = std::move(keys[count]);
				vals[i] = std::move(vals[count]);
				return true;
			}
		}
		return false;
	}
};

template <
	class K, class V,
	unsigned slots = 2,
	class Alloc = std::allocator< Bucket<K, V, slots> >
>
class Chtable{
	unsigned count_;
	unsigned tables_;
	unsigned table_buckets_;
	unsigned total_buckets_;
	unsigned total_slots_;

	std::vector< Bucket<K, V, slots>, Alloc > array_;
	chtable::Hash<K> uhash_;

public:
	Chtable( unsigned size , unsigned tables )
	:
		count_(0),

		tables_(tables),
		table_buckets_( nextPrime(size / tables / slots + 1) ),
		total_buckets_( tables_ * table_buckets_ ),
		total_slots_(total_buckets_ * slots),

		array_(total_buckets_),

		uhash_(tables_, table_buckets_)
	{}

	Chtable() : Chtable(13, 2) {}

	unsigned count() const
	{
		return count_;
	}
	unsigned capacity() const
	{
		return total_slots_;
	}
private:
	unsigned index(unsigned table, unsigned hash) const
	{
		return table * table_buckets_ + hash;
	}
public:
	//..................................ITERATOR
	struct Pair{
		K key;
		V val;
		Pair(K k, V v):key(std::move(k)), val(std::move(v)){}
	};
	class Iter{
		unsigned bucket_i;
		unsigned slot_i;
		Chtable<K, V, slots, Alloc> const * t;
	public:
		Iter(unsigned bucket, unsigned slot, Chtable<K, V, slots, Alloc> const * table)
		:
			bucket_i(bucket),
			slot_i(slot),
			t(table)
		{}
		bool operator != (Iter const & other)
		{
			return other.bucket_i != bucket_i or other.slot_i != slot_i or other.t != t;
		}
		const Iter & operator++()
		{
			if(t == nullptr)
			{
				return *this;
			}

			slot_i++;
			if(slot_i < t->array_[bucket_i].count)
			{
				return *this;
			}

			slot_i = 0;
			bucket_i++;
			while(bucket_i < t->total_buckets_)
			{
				if(slot_i < t->array_[bucket_i].count)
				{
					return *this;
				}
				bucket_i++;
			}
			slot_i = -1;
			bucket_i = -1;
			t = nullptr;
			return *this;
		}
		Pair operator*()
		{
			auto & bucket = t->array_[bucket_i];
			auto key = bucket.keys[slot_i];
			auto val = bucket.vals[slot_i];
			return Pair(key, val);
		}
	};

	Iter begin() const
	{
		Iter iter(0, -1, this);
		++iter;
		return iter;
	}
	Iter end() const
	{
		return Iter(-1, -1, nullptr);
	}
	//.......................... SEARCH ......................................
	std::tuple<V, bool> Get(K const & key) const
	{
		for(unsigned i = 0; i < tables_; i++)
		{
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto const & bucket = array_[bucket_i];
			int slot_i = bucket.Find(key);

			if(slot_i >= 0)
			{
				V ret = bucket.vals[slot_i];
				return std::make_tuple(ret, true);
			}
		}
		return std::make_tuple(V(), false);
	}
	//............................ INSERTION ..................................
private:
	// update val if key is found
	bool update(K const & key, V val)
	{
		for(unsigned i = 0; i < tables_; i++) {
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto & bucket = array_[bucket_i];
			int slot_i = bucket.Find(key);

			if(slot_i >= 0)
			{
				bucket.vals[slot_i] = val;
				return true;
			}
		}
		return false;
	}
	// try to infiltrate a table.
	// that means inserting the key into one of its designated buckets.
	// returns true for peaceful infiltration.
	// returns false for eviction.
	bool infiltrate(K & key, V & val, unsigned i)
	{
		unsigned hash = uhash_(i, key) % table_buckets_;
		unsigned bucket_i = index(i, hash);

		auto & bucket = array_[bucket_i];
		if(not bucket.full())
		{
			bucket.Insert(std::move(key), std::move(val));
			count_++;
			return true;
		}

		std::swap(bucket.keys[0], key);
		std::swap(bucket.vals[0], val);

		return false;
	}

	// try to set a new value.
	// true if successful.
	// false if cycle.
	// pre condition: key is not in the table
	bool trySet(K key, V val)
	{
		K const original = key;
		unsigned tries = tables_ + 1;
		unsigned i = 0;
		while(1)
		{
			if(infiltrate(key, val, i))
			{
				return true;
			}
			if(key == original)
			{
				tries--;
				if(tries == 0)
				{
					return false;
				}
			}
			i++;
			if(i == tables_)
			{
				i = 0;
			}
		}
		return false;

	}
	bool grow(unsigned factor)
	{
		unsigned newSize = nextPrime(capacity() * factor);
		Chtable<K, V, slots, Alloc> bigger( newSize , tables_);
		for(auto slot : *this)
		{
			if(not bigger.trySet(slot.key, slot.val))
			{
				return false;
			}
		}
		std::swap(*this, bigger);
		return true;
	}
public:
	void Set(K key, V val)
	{
		if(update(key, val))
		{
			return;
		}
		while(not trySet(key, val))
		{
			unsigned factor = 2;
			while(not grow( factor ))
			{
				factor++;
			}
		}
	}
	//................................... DELETION .......................
	bool Delete(K const & key)
	{
		for(unsigned i = 0; i < tables_; i++)
		{
			unsigned hash = uhash_(i, key) % table_buckets_;
			unsigned bucket_i = index(i, hash);

			auto & bucket = array_[bucket_i];
			if(bucket.Delete(key))
			{
				return true;
			}
		}
		return false;
	}

};

#endif
<|endoftext|>


<commit_before>// Program.cpp

#include "stdafx.h"
#include "Program.h"
#include "PythonStuff.h"
#include "tinyxml/tinyxml.h"
#include "ProgramCanvas.h"
#include "NCCode.h"
#include "interface/MarkedObject.h"
#include "interface/PropertyString.h"
#include "interface/PropertyChoice.h"
#include "interface/Tool.h"
#include "Profile.h"
#include "Pocket.h"
#include "ZigZag.h"
#include "Adaptive.h"
#include "Op.h"
#include "CNCConfig.h"

bool COperations::CanAdd(HeeksObj* object)
{
	return object->GetType() == ProfileType || object->GetType() == PocketType || object->GetType() == ZigZagType || object->GetType() == AdaptiveType;
}

void COperations::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Operations" );
	root->LinkEndChild( element );
	WriteBaseXML(element);
}

//static
HeeksObj* COperations::ReadFromXMLElement(TiXmlElement* pElem)
{
	COperations* new_object = new COperations;
	new_object->ReadBaseXML(pElem);
	return new_object;
}

static COperations* object_for_tools = NULL;

class SetAllActive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Active");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = true;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setactive");}
};

static SetAllActive set_all_active;

class SetAllInactive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Inactive");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = false;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setinactive");}
};

static SetAllInactive set_all_inactive;

void COperations::GetTools(std::list<Tool*>* t_list, const wxPoint* p)
{
	object_for_tools = this;
	t_list->push_back(&set_all_active);
	t_list->push_back(&set_all_inactive);

	ObjList::GetTools(t_list, p);
}

CProgram::CProgram():m_nc_code(NULL), m_operations(NULL), m_script_edited(false)
{
	CNCConfig config;
	config.Read(_T("ProgramMachine"), &m_machine, _T("nc.iso"));
#ifdef WIN32
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("test.tap"));
#else
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("/tmp/test.tap"));
#endif
	config.Read(_T("ProgramUnits"), &m_units, 1.0);
}

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

void CProgram::CopyFrom(const HeeksObj* object)
{
	operator=(*((CProgram*)object));
}

static void on_set_machine(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_machine = value;
	CNCConfig config;
	config.Write(_T("ProgramMachine"), ((CProgram*)object)->m_machine);
}

static void on_set_output_file(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_output_file = value;
	CNCConfig config;
	config.Write(_T("ProgramOutputFile"), ((CProgram*)object)->m_output_file);
}

static void on_set_units(int value, HeeksObj* object)
{
	((CProgram*)object)->m_units = (value == 0) ? 1.0:25.4;
	CNCConfig config;
	config.Write(_T("ProgramUnits"), ((CProgram*)object)->m_units);

	// also change HeeksCAD's view units automatically
	heeksCAD->SetViewUnits(((CProgram*)object)->m_units, true);
}

void CProgram::GetProperties(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("machine"), m_machine, this, on_set_machine));
	list->push_back(new PropertyString(_("output file"), m_output_file, this, on_set_output_file));
	{
		std::list< wxString > choices;
		choices.push_back ( wxString ( _("mm") ) );
		choices.push_back ( wxString ( _("inch") ) );
		int choice = 0;
		if(m_units > 25.0)choice = 1;
		list->push_back ( new PropertyChoice ( _("units"),  choices, choice, this, on_set_units ) );
	}
	HeeksObj::GetProperties(list);
}

bool CProgram::CanAdd(HeeksObj* object)
{
	return object->GetType() == NCCodeType || object->GetType() == OperationsType;
}

bool CProgram::CanAddTo(HeeksObj* owner)
{
	return owner->GetType() == DocumentType;
}

void CProgram::SetClickMarkPoint(MarkedObject* marked_object, const double* ray_start, const double* ray_direction)
{
	if(marked_object->m_map.size() > 0)
	{
		MarkedObject* sub_marked_object = marked_object->m_map.begin()->second;
		if(sub_marked_object)
		{
			HeeksObj* object = sub_marked_object->m_map.begin()->first;
			if(object && object->GetType() == NCCodeType)
			{
				((CNCCode*)object)->SetClickMarkPoint(sub_marked_object, ray_start, ray_direction);
			}
		}
	}
}

void CProgram::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Program" );
	root->LinkEndChild( element );
	element->SetAttribute("machine", Ttc(m_machine.c_str()));
	element->SetAttribute("output_file", Ttc(m_output_file.c_str()));
	element->SetAttribute("program", Ttc(theApp.m_program_canvas->m_textCtrl->GetValue()));
	element->SetDoubleAttribute("units", m_units);

	WriteBaseXML(element);
}

bool CProgram::Add(HeeksObj* object, HeeksObj* prev_object)
{
	if(object->GetType() == NCCodeType)m_nc_code = (CNCCode*)object;
	if(object->GetType() == OperationsType)m_operations = (COperations*)object;
	return ObjList::Add(object, prev_object);
}

void CProgram::Remove(HeeksObj* object)
{
	 // these shouldn't happen, though
	if(object == m_nc_code)m_nc_code = NULL;
	else if(object == m_operations)m_operations = NULL;

	ObjList::Remove(object);
}

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

	// get the attributes
	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "machine"){new_object->m_machine.assign(Ctt(a->Value()));}
		else if(name == "output_file"){new_object->m_output_file.assign(Ctt(a->Value()));}
		else if(name == "program"){theApp.m_program_canvas->m_textCtrl->SetValue(Ctt(a->Value()));}
		else if(name == "units"){new_object->m_units = a->DoubleValue();}
	}

	new_object->ReadBaseXML(pElem);
	theApp.m_program = new_object;

	return new_object;
}

void CProgram::RewritePythonProgram()
{
	theApp.m_program_canvas->m_textCtrl->Clear();
	CZigZag::number_for_stl_file = 1;
	CAdaptive::number_for_stl_file = 1;

	bool profile_op_exists = false;
	bool pocket_op_exists = false;
	bool zigzag_op_exists = false;
	bool adaptive_op_exists = false;
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		if(object->GetType() == ProfileType)
		{
			if(((CProfile*)object)->m_active)profile_op_exists = true;
		}
		else if(object->GetType() == PocketType)
		{
			if(((CPocket*)object)->m_active)pocket_op_exists = true;
		}
		else if(object->GetType() == ZigZagType)
		{
			if(((CZigZag*)object)->m_active)zigzag_op_exists = true;
		}
		else if(object->GetType() == AdaptiveType)
		{
			if(((CAdaptive*)object)->m_active)adaptive_op_exists = true;
		}
	}

	// add standard stuff at the top
	//hackhack, make it work on unix with FHS
#ifndef WIN32
	theApp.m_program_canvas->AppendText(_T("import sys\n"));
	theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'/usr/lib/heekscnc/')\n"));
#endif
	// kurve related things
	if(profile_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import kurve\n"));
		theApp.m_program_canvas->AppendText(_T("import kurve_funcs\n"));
	}

	// area related things
	if(pocket_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import area\n"));
		if(fabs(m_units - 1.0) > 0.00000001)
		{
			theApp.m_program_canvas->AppendText(_T("area.set_units("));
			theApp.m_program_canvas->AppendText(m_units);
			theApp.m_program_canvas->AppendText(_T(")\n"));
		}
		theApp.m_program_canvas->AppendText(_T("import area_funcs\n"));
	}

	// pycam stuff
	if(zigzag_op_exists)
	{
#ifdef WIN32
		theApp.m_program_canvas->AppendText(_T("import sys\n"));
#endif
		theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'PyCam/trunk')\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Geometry import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.SphericalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.CylindricalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.ToroidalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Importers.STLImporter import ImportModel\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.PathGenerators.DropCutter import DropCutter\n"));
		theApp.m_program_canvas->AppendText(_T("from PyCamToHeeks import HeeksCNCExporter\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// actp
	if(adaptive_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import actp_funcs\n"));
		theApp.m_program_canvas->AppendText(_T("import actp\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// machine general stuff
	theApp.m_program_canvas->AppendText(_T("from nc.nc import *\n"));

	// specific machine
	theApp.m_program_canvas->AppendText(_T("import ") + m_machine + _T("\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// output file
	theApp.m_program_canvas->AppendText(_T("output('") + m_output_file + _T("')\n"));

	// begin program
	//theApp.m_program_canvas->AppendText(_T("program_begin(123, 'Test program')\n"));
	theApp.m_program_canvas->AppendText(_T("absolute()\n"));
	if(m_units > 25.0)
	{
		theApp.m_program_canvas->AppendText(_T("imperial()\n"));
	}
	else
	{
		theApp.m_program_canvas->AppendText(_T("metric()\n"));
	}
	theApp.m_program_canvas->AppendText(_T("set_plane(0)\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// write the operations
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		switch(object->GetType())
		{
		case ProfileType:
			if(((CProfile*)object)->m_active)((CProfile*)object)->AppendTextToProgram();
			break;
		case PocketType:
			if(((CPocket*)object)->m_active)((CPocket*)object)->AppendTextToProgram();
			break;
		case ZigZagType:
			if(((CZigZag*)object)->m_active)((CZigZag*)object)->AppendTextToProgram();
			break;
		case AdaptiveType:
			if(((CAdaptive*)object)->m_active)((CAdaptive*)object)->AppendTextToProgram();
			break;
		}
	}
}

ProgramUserType CProgram::GetUserType()
{
	if(m_nc_code->m_user_edited)return ProgramUserTypeNC;
	if(m_script_edited)return ProgramUserTypeScript;
	if(m_operations->GetFirstChild())return ProgramUserTypeTree;
	return ProgramUserTypeUnkown;
}

void CProgram::UpdateFromUserType()
{
#if 0
	switch(GetUserType())
	{
	case ProgramUserTypeUnkown:

	case tree:
   Enable "Operations" icon in tree
     editing the tree, recreates the python script
   Read only "Program" window
     pressing "Post-process" creates the NC code ( and backplots it )
   Read only "Output" window
   Disable all buttons on "Output" window

	}
#endif
}
<commit_msg>always write area.set_units<commit_after>// Program.cpp

#include "stdafx.h"
#include "Program.h"
#include "PythonStuff.h"
#include "tinyxml/tinyxml.h"
#include "ProgramCanvas.h"
#include "NCCode.h"
#include "interface/MarkedObject.h"
#include "interface/PropertyString.h"
#include "interface/PropertyChoice.h"
#include "interface/Tool.h"
#include "Profile.h"
#include "Pocket.h"
#include "ZigZag.h"
#include "Adaptive.h"
#include "Op.h"
#include "CNCConfig.h"

bool COperations::CanAdd(HeeksObj* object)
{
	return object->GetType() == ProfileType || object->GetType() == PocketType || object->GetType() == ZigZagType || object->GetType() == AdaptiveType;
}

void COperations::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Operations" );
	root->LinkEndChild( element );
	WriteBaseXML(element);
}

//static
HeeksObj* COperations::ReadFromXMLElement(TiXmlElement* pElem)
{
	COperations* new_object = new COperations;
	new_object->ReadBaseXML(pElem);
	return new_object;
}

static COperations* object_for_tools = NULL;

class SetAllActive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Active");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = true;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setactive");}
};

static SetAllActive set_all_active;

class SetAllInactive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Inactive");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = false;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setinactive");}
};

static SetAllInactive set_all_inactive;

void COperations::GetTools(std::list<Tool*>* t_list, const wxPoint* p)
{
	object_for_tools = this;
	t_list->push_back(&set_all_active);
	t_list->push_back(&set_all_inactive);

	ObjList::GetTools(t_list, p);
}

CProgram::CProgram():m_nc_code(NULL), m_operations(NULL), m_script_edited(false)
{
	CNCConfig config;
	config.Read(_T("ProgramMachine"), &m_machine, _T("nc.iso"));
#ifdef WIN32
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("test.tap"));
#else
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("/tmp/test.tap"));
#endif
	config.Read(_T("ProgramUnits"), &m_units, 1.0);
}

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

void CProgram::CopyFrom(const HeeksObj* object)
{
	operator=(*((CProgram*)object));
}

static void on_set_machine(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_machine = value;
	CNCConfig config;
	config.Write(_T("ProgramMachine"), ((CProgram*)object)->m_machine);
}

static void on_set_output_file(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_output_file = value;
	CNCConfig config;
	config.Write(_T("ProgramOutputFile"), ((CProgram*)object)->m_output_file);
}

static void on_set_units(int value, HeeksObj* object)
{
	((CProgram*)object)->m_units = (value == 0) ? 1.0:25.4;
	CNCConfig config;
	config.Write(_T("ProgramUnits"), ((CProgram*)object)->m_units);

	// also change HeeksCAD's view units automatically
	heeksCAD->SetViewUnits(((CProgram*)object)->m_units, true);
}

void CProgram::GetProperties(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("machine"), m_machine, this, on_set_machine));
	list->push_back(new PropertyString(_("output file"), m_output_file, this, on_set_output_file));
	{
		std::list< wxString > choices;
		choices.push_back ( wxString ( _("mm") ) );
		choices.push_back ( wxString ( _("inch") ) );
		int choice = 0;
		if(m_units > 25.0)choice = 1;
		list->push_back ( new PropertyChoice ( _("units"),  choices, choice, this, on_set_units ) );
	}
	HeeksObj::GetProperties(list);
}

bool CProgram::CanAdd(HeeksObj* object)
{
	return object->GetType() == NCCodeType || object->GetType() == OperationsType;
}

bool CProgram::CanAddTo(HeeksObj* owner)
{
	return owner->GetType() == DocumentType;
}

void CProgram::SetClickMarkPoint(MarkedObject* marked_object, const double* ray_start, const double* ray_direction)
{
	if(marked_object->m_map.size() > 0)
	{
		MarkedObject* sub_marked_object = marked_object->m_map.begin()->second;
		if(sub_marked_object)
		{
			HeeksObj* object = sub_marked_object->m_map.begin()->first;
			if(object && object->GetType() == NCCodeType)
			{
				((CNCCode*)object)->SetClickMarkPoint(sub_marked_object, ray_start, ray_direction);
			}
		}
	}
}

void CProgram::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Program" );
	root->LinkEndChild( element );
	element->SetAttribute("machine", Ttc(m_machine.c_str()));
	element->SetAttribute("output_file", Ttc(m_output_file.c_str()));
	element->SetAttribute("program", Ttc(theApp.m_program_canvas->m_textCtrl->GetValue()));
	element->SetDoubleAttribute("units", m_units);

	WriteBaseXML(element);
}

bool CProgram::Add(HeeksObj* object, HeeksObj* prev_object)
{
	if(object->GetType() == NCCodeType)m_nc_code = (CNCCode*)object;
	if(object->GetType() == OperationsType)m_operations = (COperations*)object;
	return ObjList::Add(object, prev_object);
}

void CProgram::Remove(HeeksObj* object)
{
	 // these shouldn't happen, though
	if(object == m_nc_code)m_nc_code = NULL;
	else if(object == m_operations)m_operations = NULL;

	ObjList::Remove(object);
}

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

	// get the attributes
	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "machine"){new_object->m_machine.assign(Ctt(a->Value()));}
		else if(name == "output_file"){new_object->m_output_file.assign(Ctt(a->Value()));}
		else if(name == "program"){theApp.m_program_canvas->m_textCtrl->SetValue(Ctt(a->Value()));}
		else if(name == "units"){new_object->m_units = a->DoubleValue();}
	}

	new_object->ReadBaseXML(pElem);
	theApp.m_program = new_object;

	return new_object;
}

void CProgram::RewritePythonProgram()
{
	theApp.m_program_canvas->m_textCtrl->Clear();
	CZigZag::number_for_stl_file = 1;
	CAdaptive::number_for_stl_file = 1;

	bool profile_op_exists = false;
	bool pocket_op_exists = false;
	bool zigzag_op_exists = false;
	bool adaptive_op_exists = false;
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		if(object->GetType() == ProfileType)
		{
			if(((CProfile*)object)->m_active)profile_op_exists = true;
		}
		else if(object->GetType() == PocketType)
		{
			if(((CPocket*)object)->m_active)pocket_op_exists = true;
		}
		else if(object->GetType() == ZigZagType)
		{
			if(((CZigZag*)object)->m_active)zigzag_op_exists = true;
		}
		else if(object->GetType() == AdaptiveType)
		{
			if(((CAdaptive*)object)->m_active)adaptive_op_exists = true;
		}
	}

	// add standard stuff at the top
	//hackhack, make it work on unix with FHS
#ifndef WIN32
	theApp.m_program_canvas->AppendText(_T("import sys\n"));
	theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'/usr/lib/heekscnc/')\n"));
#endif
	// kurve related things
	if(profile_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import kurve\n"));
		theApp.m_program_canvas->AppendText(_T("import kurve_funcs\n"));
	}

	// area related things
	if(pocket_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import area\n"));
		theApp.m_program_canvas->AppendText(_T("area.set_units("));
		theApp.m_program_canvas->AppendText(m_units);
		theApp.m_program_canvas->AppendText(_T(")\n"));
		theApp.m_program_canvas->AppendText(_T("import area_funcs\n"));
	}

	// pycam stuff
	if(zigzag_op_exists)
	{
#ifdef WIN32
		theApp.m_program_canvas->AppendText(_T("import sys\n"));
#endif
		theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'PyCam/trunk')\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Geometry import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.SphericalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.CylindricalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.ToroidalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Importers.STLImporter import ImportModel\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.PathGenerators.DropCutter import DropCutter\n"));
		theApp.m_program_canvas->AppendText(_T("from PyCamToHeeks import HeeksCNCExporter\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// actp
	if(adaptive_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import actp_funcs\n"));
		theApp.m_program_canvas->AppendText(_T("import actp\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// machine general stuff
	theApp.m_program_canvas->AppendText(_T("from nc.nc import *\n"));

	// specific machine
	theApp.m_program_canvas->AppendText(_T("import ") + m_machine + _T("\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// output file
	theApp.m_program_canvas->AppendText(_T("output('") + m_output_file + _T("')\n"));

	// begin program
	//theApp.m_program_canvas->AppendText(_T("program_begin(123, 'Test program')\n"));
	theApp.m_program_canvas->AppendText(_T("absolute()\n"));
	if(m_units > 25.0)
	{
		theApp.m_program_canvas->AppendText(_T("imperial()\n"));
	}
	else
	{
		theApp.m_program_canvas->AppendText(_T("metric()\n"));
	}
	theApp.m_program_canvas->AppendText(_T("set_plane(0)\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// write the operations
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		switch(object->GetType())
		{
		case ProfileType:
			if(((CProfile*)object)->m_active)((CProfile*)object)->AppendTextToProgram();
			break;
		case PocketType:
			if(((CPocket*)object)->m_active)((CPocket*)object)->AppendTextToProgram();
			break;
		case ZigZagType:
			if(((CZigZag*)object)->m_active)((CZigZag*)object)->AppendTextToProgram();
			break;
		case AdaptiveType:
			if(((CAdaptive*)object)->m_active)((CAdaptive*)object)->AppendTextToProgram();
			break;
		}
	}
}

ProgramUserType CProgram::GetUserType()
{
	if(m_nc_code->m_user_edited)return ProgramUserTypeNC;
	if(m_script_edited)return ProgramUserTypeScript;
	if(m_operations->GetFirstChild())return ProgramUserTypeTree;
	return ProgramUserTypeUnkown;
}

void CProgram::UpdateFromUserType()
{
#if 0
	switch(GetUserType())
	{
	case ProgramUserTypeUnkown:

	case tree:
   Enable "Operations" icon in tree
     editing the tree, recreates the python script
   Read only "Program" window
     pressing "Post-process" creates the NC code ( and backplots it )
   Read only "Output" window
   Disable all buttons on "Output" window

	}
#endif
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Library
  Module:    Property.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include <stdlib.h>
#include "Property.hh"

// Description:
// Construct object with object color, ambient color, diffuse color,
// specular color, and edge color white; ambient coefficient=0; diffuse
// coefficient=0; specular coefficient=0; specular power=1; Gouraud shading;
// and surface representation.
vlProperty::vlProperty()
{
  this->Color[0] = 1;
  this->Color[1] = 1;
  this->Color[2] = 1;

  this->AmbientColor[0] = 1;
  this->AmbientColor[1] = 1;
  this->AmbientColor[2] = 1;

  this->DiffuseColor[0] = 1;
  this->DiffuseColor[1] = 1;
  this->DiffuseColor[2] = 1;

  this->SpecularColor[0] = 1;
  this->SpecularColor[1] = 1;
  this->SpecularColor[2] = 1;

  this->EdgeColor[0] = 1;
  this->EdgeColor[1] = 1;
  this->EdgeColor[2] = 1;

  this->Ambient = 0.0;
  this->Diffuse = 1.0;
  this->Specular = 0.0;
  this->SpecularPower = 1.0;
  this->Transparency = 1.0;
  this->Interpolation = VL_GOURAUD;
  this->Representation = VL_SURFACE;
  this->EdgeVisibility = 0;
  this->Backface = 0;
  this->Subdivide = 0;

  this->Texture  = NULL;
}

// Description:
// Set shading method to flat.
void vlProperty::SetFlat (void)
{
  this->Interpolation= VL_FLAT;
}

// Description:
// Set shading method to Gouraud.
void vlProperty::SetGouraud (void)
{
  this->Interpolation = VL_GOURAUD;
}

// Description:
// Set shading method to Phong.
void vlProperty::SetPhong (void)
{
  this->Interpolation = VL_PHONG;
}

// Description:
// Represent geometry with points.
void vlProperty::SetPoints (void)
{
  this->Interpolation = VL_POINTS;
}

// Description:
// Represent geometry as wireframe.
void vlProperty::SetWireframe (void)
{
  this->Representation = VL_WIREFRAME;
}

// Description:
// Represent geometry as surface.
void vlProperty::SetSurface (void)
{
  this->Representation = VL_SURFACE;
}

// Description:
// Set the color of the object. Has side effects in that it sets the
// ambient diffuse and specular colors as well.
void vlProperty::SetColor(float R,float G,float B)
{
  /* store the coordinates */
  this->Color[0] = R;
  this->AmbientColor[0] = R;
  this->DiffuseColor[0] = R;
  this->SpecularColor[0] = R;

  this->Color[1] = G;
  this->AmbientColor[1] = G;
  this->DiffuseColor[1] = G;
  this->SpecularColor[1] = G;

  this->Color[2] = B;
  this->AmbientColor[2] = B;
  this->DiffuseColor[2] = B;
  this->SpecularColor[2] = B;
}

void vlProperty::PrintSelf(ostream& os, vlIndent indent)
{
  vlObject::PrintSelf(os,indent);

  os << indent << "Ambient: " << this->Ambient << "\n";
  os << indent << "Ambient Color: (" << this->AmbientColor[0] << ", "
    << this->AmbientColor[1] << ", " << this->AmbientColor[2] << ")\n";
  os << indent << "Backface: " << (this->Backface ? "On\n" : "Off\n");
  os << indent << "Color: (" << this->Color[0] << ", "
    << this->Color[1] << ", " << this->Color[2] << ")\n";
  os << indent << "Diffuse: " << this->Diffuse << "\n";
  os << indent << "Diffuse Color: (" << this->DiffuseColor[0] << ", "
    << this->DiffuseColor[1] << ", " << this->DiffuseColor[2] << ")\n";
  os << indent << "Edge Color: (" << this->EdgeColor[0] << ", "
    << this->EdgeColor[1] << ", " << this->EdgeColor[2] << ")\n";
  os << indent << "Edge Visibility: "
    << (this->EdgeVisibility ? "On\n" : "Off\n");
  os << indent << "Interpolation: ";
  switch (this->Interpolation)
    {
    case 0: os << "VL_FLAT\n"; break;
    case 1: os << "VL_GOURAUD\n"; break;
    case 2: os << "VL_PHONG\n"; break;
    default: os << "unknown\n";
    }
  os << indent << "Representation: ";
  switch (this->Representation)
    {
    case 0: os << "VL_POINTS\n"; break;
    case 1: os << "VL_WIREFRAME\n"; break;
    case 2: os << "VL_SURFACE\n"; break;
    default: os << "unknown\n";
    }
  os << indent << "Specular: " << this->Specular << "\n";
  os << indent << "Specular Color: (" << this->SpecularColor[0] << ", "
     << this->SpecularColor[1] << ", " << this->SpecularColor[2] << ")\n";
  os << indent << "Specular Power: " << this->SpecularPower << "\n";
  os << indent << "Subdivide: " << (this->Subdivide ? "On\n" : "Off\n");
  os << indent << "Transparency: " << this->Transparency << "\n";
  if ( this->Texture )
    {
    os << indent << "Texture: (" << (void *)this->Texture << ")\n";
    }
  else
    {
    os << indent << "Texture: (none)\n";
    }
}
<commit_msg>added texture<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    Property.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include <stdlib.h>
#include "Property.hh"

// Description:
// Construct object with object color, ambient color, diffuse color,
// specular color, and edge color white; ambient coefficient=0; diffuse
// coefficient=0; specular coefficient=0; specular power=1; Gouraud shading;
// and surface representation.
vlProperty::vlProperty()
{
  this->Color[0] = 1;
  this->Color[1] = 1;
  this->Color[2] = 1;

  this->AmbientColor[0] = 1;
  this->AmbientColor[1] = 1;
  this->AmbientColor[2] = 1;

  this->DiffuseColor[0] = 1;
  this->DiffuseColor[1] = 1;
  this->DiffuseColor[2] = 1;

  this->SpecularColor[0] = 1;
  this->SpecularColor[1] = 1;
  this->SpecularColor[2] = 1;

  this->EdgeColor[0] = 1;
  this->EdgeColor[1] = 1;
  this->EdgeColor[2] = 1;

  this->Ambient = 0.0;
  this->Diffuse = 1.0;
  this->Specular = 0.0;
  this->SpecularPower = 1.0;
  this->Transparency = 1.0;
  this->Interpolation = VL_GOURAUD;
  this->Representation = VL_SURFACE;
  this->EdgeVisibility = 0;
  this->Backface = 0;
}

// Description:
// Set shading method to flat.
void vlProperty::SetFlat (void)
{
  this->Interpolation= VL_FLAT;
}

// Description:
// Set shading method to Gouraud.
void vlProperty::SetGouraud (void)
{
  this->Interpolation = VL_GOURAUD;
}

// Description:
// Set shading method to Phong.
void vlProperty::SetPhong (void)
{
  this->Interpolation = VL_PHONG;
}

// Description:
// Represent geometry with points.
void vlProperty::SetPoints (void)
{
  this->Interpolation = VL_POINTS;
}

// Description:
// Represent geometry as wireframe.
void vlProperty::SetWireframe (void)
{
  this->Representation = VL_WIREFRAME;
}

// Description:
// Represent geometry as surface.
void vlProperty::SetSurface (void)
{
  this->Representation = VL_SURFACE;
}

// Description:
// Set the color of the object. Has side effects in that it sets the
// ambient diffuse and specular colors as well.
void vlProperty::SetColor(float R,float G,float B)
{
  /* store the coordinates */
  this->Color[0] = R;
  this->AmbientColor[0] = R;
  this->DiffuseColor[0] = R;
  this->SpecularColor[0] = R;

  this->Color[1] = G;
  this->AmbientColor[1] = G;
  this->DiffuseColor[1] = G;
  this->SpecularColor[1] = G;

  this->Color[2] = B;
  this->AmbientColor[2] = B;
  this->DiffuseColor[2] = B;
  this->SpecularColor[2] = B;
}

void vlProperty::PrintSelf(ostream& os, vlIndent indent)
{
  vlObject::PrintSelf(os,indent);

  os << indent << "Ambient: " << this->Ambient << "\n";
  os << indent << "Ambient Color: (" << this->AmbientColor[0] << ", "
    << this->AmbientColor[1] << ", " << this->AmbientColor[2] << ")\n";
  os << indent << "Backface: " << (this->Backface ? "On\n" : "Off\n");
  os << indent << "Color: (" << this->Color[0] << ", "
    << this->Color[1] << ", " << this->Color[2] << ")\n";
  os << indent << "Diffuse: " << this->Diffuse << "\n";
  os << indent << "Diffuse Color: (" << this->DiffuseColor[0] << ", "
    << this->DiffuseColor[1] << ", " << this->DiffuseColor[2] << ")\n";
  os << indent << "Edge Color: (" << this->EdgeColor[0] << ", "
    << this->EdgeColor[1] << ", " << this->EdgeColor[2] << ")\n";
  os << indent << "Edge Visibility: "
    << (this->EdgeVisibility ? "On\n" : "Off\n");
  os << indent << "Interpolation: ";
  switch (this->Interpolation)
    {
    case 0: os << "VL_FLAT\n"; break;
    case 1: os << "VL_GOURAUD\n"; break;
    case 2: os << "VL_PHONG\n"; break;
    default: os << "unknown\n";
    }
  os << indent << "Representation: ";
  switch (this->Representation)
    {
    case 0: os << "VL_POINTS\n"; break;
    case 1: os << "VL_WIREFRAME\n"; break;
    case 2: os << "VL_SURFACE\n"; break;
    default: os << "unknown\n";
    }
  os << indent << "Specular: " << this->Specular << "\n";
  os << indent << "Specular Color: (" << this->SpecularColor[0] << ", "
     << this->SpecularColor[1] << ", " << this->SpecularColor[2] << ")\n";
  os << indent << "Specular Power: " << this->SpecularPower << "\n";
  os << indent << "Transparency: " << this->Transparency << "\n";
}
<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include"ork/ork.hpp"

namespace ork {

/*
The C++ standard does not offer a smart pointer with value sematics.
For one, C++ does not offer a standard way to copy an object to prevent slicing.

Nonetheless, pimpl is so common that we implement a unique ownership, copyable pointer.
The pointer therefore has value semantics, and if such a thing is ever standardized it may be called value_ptr.
We implement a simple wrapper around unique_ptr that delegates copying and deleting to a templated functor.

No default templates are offered.
If pimpl is being used the functor interfaces cannot be defined in a header.

The functor must implement both copy and delete interfaces
std::unique_ptr<T, D> D(const T&);
void D(T*);
Note that the copy interface must handle null objects by returning empty pointer

No casting interface is offered, although if the copier supports it...
No auto_ptr conversion is offered, because who uses auto_ptr?
No relational operators are offered, because these are a source of more bugs than functionality.
*/

template<class T, class D>
class value_ptr {
public:
	using element_type = T;
	using pointer = T*;//This is a little simplistic
	using copier_type = D;
	using deleter_type = D;
private:
	std::unique_ptr<T, D>_ptr;
public:
	constexpr value_ptr() noexcept : _ptr() {}
	constexpr value_ptr(nullptr_t) noexcept : _ptr(nullptr) {}
	explicit value_ptr(pointer p) noexcept : _ptr(p) {}
	value_ptr(pointer p, typename std::conditional<std::is_reference<D>::value, D, const D&> del) noexcept : _ptr(p, del) {}
	value_ptr(pointer p, typename std::remove_reference<D>::type&& del) noexcept : _ptr(p, std::move(del)) {}

	value_ptr(value_ptr&& x) noexcept : _ptr(std::move(x._ptr)) {}
	template<class D2>
	value_ptr(value_ptr<T, D2>&& x) noexcept : _ptr(std::move(x._ptr)) {}

	//Allow conversion from unique_ptr
	value_ptr(std::unique_ptr<T, D>&& x) noexcept : _ptr(std::move(x)) {}
	template<class D2>
	value_ptr(std::unique_ptr<T, D2>&& x) noexcept : _ptr(std::move(x)) {}

	//The big payoff
	value_ptr(const value_ptr&x) : _ptr(x.get_deleter()(*x._ptr)) {}
	template<class D2>
	value_ptr(const value_ptr<T, D2>& x) : _ptr(x.get_deleter()(*x._ptr)) {}

	//The big payoff + conversion
	value_ptr(const std::unique_ptr<T, D>& x) : _ptr(x.get_deleter()(*x._ptr)) {}
	template<class D2>
	value_ptr(const std::unique_ptr<T, D2>& x) : _ptr(x.get_deleter()(*x._ptr)) {}

	//Destructor is implicitly defined
public:
	value_ptr& operator=(nullptr_t) noexcept {
		_ptr = nullptr;
		return *this;
	}

	value_ptr& operator=(value_ptr&& x) noexcept {
		_ptr = std::move(x._ptr);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(value_ptr<T, D2>&& x) noexcept {
		_ptr = std::move(x._ptr);
		return *this;
	}

	//Allow conversion from unique_ptr
	value_ptr& operator=(std::unique_ptr<T, D>&& x) noexcept {
		_ptr = std::move(x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(std::unique_ptr<T, D2>&& x) noexcept {
		_ptr = std::move(x);
		return *this;
	}

	//The big payoff
	value_ptr& operator=(const value_ptr& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(const value_ptr<T, D2>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}

	//The big payoff + conversion
	value_ptr& operator=(const std::unique_ptr<T, D>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(const std::unique_ptr<T, D2>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
public:
	typename std::add_lvalue_reference<element_type>::type operator*() const {
		return _ptr.operator*();
	}
	pointer operator->() const noexcept {
		return _ptr.operator->();
	}
	pointer get() const noexcept {
		return _ptr.get();
	}
	deleter_type& get_deleter() noexcept {
		return _ptr.get_deleter();
	}
	const deleter_type& get_deleter() const noexcept {
		return _ptr.get_deleter();
	}
	explicit operator bool() const noexcept {
		return _ptr.operator bool();
	}
	pointer release() noexcept {
		return _ptr.release();
	}
	//The reset interface is different than std, but I prefer overloads to default params
	void reset() noexcept {
		_ptr.reset();
	}
	void reset(pointer p) noexcept {
		_ptr.reset(p);
	}
	void swap(value_ptr& x) noexcept {
		_ptr.swap(x._ptr);
	}
};

}//namespace ork

namespace std {

template <class T, class D>
void swap(ork::value_ptr<T, D>& x, ork::value_ptr<T, D>& y) noexcept {
	x.swap(y);
}

}//namespace std
<commit_msg>Added two deleter templates<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include"ork/ork.hpp"

namespace ork {

/*
The C++ standard does not offer a smart pointer with value sematics.
For one, C++ does not offer a standard way to copy an object to prevent slicing.

Nonetheless, pimpl is so common that we implement a unique ownership, copyable pointer.
The pointer therefore has value semantics, and if such a thing is ever standardized it may be called value_ptr.
We implement a simple wrapper around unique_ptr that delegates copying and deleting to a templated functor.

No default templates are offered.
If pimpl is being used the functor interfaces cannot be defined in a header.

The functor must implement both copy and delete interfaces
std::unique_ptr<T, D> D(const T&);
void D(T*);
Note that the copy interface must handle null objects by returning empty pointer

No casting interface is offered, although if the copier supports it...
No auto_ptr conversion is offered, because who uses auto_ptr?
No relational operators are offered, because these are a source of more bugs than functionality.
*/

template<typename T>
struct default_deleter {
	void operator()(const T*t) {
		delete t;
	}
	T operator()(const T&t) {
		return T(t);
	}
};

//This allows smart interfaces over singleton implementations
template<typename T>
struct singleton_deleter {
	void operator()(const T*t) {
		//Do Nothing
	}
	T operator()(const T&t) {
		return t;
	}
};

template<class T, class D>
class value_ptr {
public:
	using element_type = T;
	using pointer = T*;//This is a little simplistic
	using copier_type = D;
	using deleter_type = D;
private:
	std::unique_ptr<T, D>_ptr;
public:
	constexpr value_ptr() noexcept : _ptr() {}
	constexpr value_ptr(nullptr_t) noexcept : _ptr(nullptr) {}
	explicit value_ptr(pointer p) noexcept : _ptr(p) {}
	value_ptr(pointer p, typename std::conditional<std::is_reference<D>::value, D, const D&> del) noexcept : _ptr(p, del) {}
	value_ptr(pointer p, typename std::remove_reference<D>::type&& del) noexcept : _ptr(p, std::move(del)) {}

	value_ptr(value_ptr&& x) noexcept : _ptr(std::move(x._ptr)) {}
	template<class D2>
	value_ptr(value_ptr<T, D2>&& x) noexcept : _ptr(std::move(x._ptr)) {}

	//Allow conversion from unique_ptr
	value_ptr(std::unique_ptr<T, D>&& x) noexcept : _ptr(std::move(x)) {}
	template<class D2>
	value_ptr(std::unique_ptr<T, D2>&& x) noexcept : _ptr(std::move(x)) {}

	//The big payoff
	value_ptr(const value_ptr&x) : _ptr(x.get_deleter()(*x._ptr)) {}
	template<class D2>
	value_ptr(const value_ptr<T, D2>& x) : _ptr(x.get_deleter()(*x._ptr)) {}

	//The big payoff + conversion
	value_ptr(const std::unique_ptr<T, D>& x) : _ptr(x.get_deleter()(*x._ptr)) {}
	template<class D2>
	value_ptr(const std::unique_ptr<T, D2>& x) : _ptr(x.get_deleter()(*x._ptr)) {}

	//Destructor is implicitly defined
public:
	value_ptr& operator=(nullptr_t) noexcept {
		_ptr = nullptr;
		return *this;
	}

	value_ptr& operator=(value_ptr&& x) noexcept {
		_ptr = std::move(x._ptr);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(value_ptr<T, D2>&& x) noexcept {
		_ptr = std::move(x._ptr);
		return *this;
	}

	//Allow conversion from unique_ptr
	value_ptr& operator=(std::unique_ptr<T, D>&& x) noexcept {
		_ptr = std::move(x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(std::unique_ptr<T, D2>&& x) noexcept {
		_ptr = std::move(x);
		return *this;
	}

	//The big payoff
	value_ptr& operator=(const value_ptr& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(const value_ptr<T, D2>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}

	//The big payoff + conversion
	value_ptr& operator=(const std::unique_ptr<T, D>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
	template<class D2>
	value_ptr& operator=(const std::unique_ptr<T, D2>& x) {
		_ptr = x.get_deleter()(*x);
		return *this;
	}
public:
	typename std::add_lvalue_reference<element_type>::type operator*() const {
		return _ptr.operator*();
	}
	pointer operator->() const noexcept {
		return _ptr.operator->();
	}
	pointer get() const noexcept {
		return _ptr.get();
	}
	deleter_type& get_deleter() noexcept {
		return _ptr.get_deleter();
	}
	const deleter_type& get_deleter() const noexcept {
		return _ptr.get_deleter();
	}
	explicit operator bool() const noexcept {
		return _ptr.operator bool();
	}
	pointer release() noexcept {
		return _ptr.release();
	}
	//The reset interface is different than std, but I prefer overloads to default params
	void reset() noexcept {
		_ptr.reset();
	}
	void reset(pointer p) noexcept {
		_ptr.reset(p);
	}
	void swap(value_ptr& x) noexcept {
		_ptr.swap(x._ptr);
	}
};

}//namespace ork

namespace std {

template <class T, class D>
void swap(ork::value_ptr<T, D>& x, ork::value_ptr<T, D>& y) noexcept {
	x.swap(y);
}

}//namespace std
<|endoftext|>


<commit_before>// LAF OS Library
// Copyright (C) 2018  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/memory.h"
#include "os/system.h"

namespace os {

class NoneSystem : public System {
public:
  void dispose() override { delete this; }
  void activateApp() override { }
  void finishLaunching() override { }
  Capabilities capabilities() const override { return (Capabilities)0; }
  void useWintabAPI(bool enable) override { }
  Logger* logger() override { return nullptr; }
  Menus* menus() override { return nullptr; }
  NativeDialogs* nativeDialogs() override { return nullptr; }
  EventQueue* eventQueue() override { return nullptr; }
  bool gpuAcceleration() const override { return false; }
  void setGpuAcceleration(bool state) override { }
  gfx::Size defaultNewDisplaySize() override { return gfx::Size(0, 0); }
  Display* defaultDisplay() override { return nullptr; }
  Display* createDisplay(int width, int height, int scale) override { return nullptr; }
  Surface* createSurface(int width, int height) override { return nullptr; }
  Surface* createRgbaSurface(int width, int height) override { return nullptr; }
  Surface* loadSurface(const char* filename) override { return nullptr; }
  Surface* loadRgbaSurface(const char* filename) override { return nullptr; }
  Font* loadSpriteSheetFont(const char* filename, int scale) override { return nullptr; }
  Font* loadTrueTypeFont(const char* filename, int height) override { return nullptr; }
  bool isKeyPressed(KeyScancode scancode) override { return false; }
  KeyModifiers keyModifiers() override { return kKeyNoneModifier; }
  int getUnicodeFromScancode(KeyScancode scancode) override { return 0; }
  void setTranslateDeadKeys(bool state) override { }
};

System* create_system_impl() {
  return new NoneSystem;
}

void error_message(const char* msg)
{
  fputs(msg, stderr);
  // TODO
}

} // namespace os

extern int app_main(int argc, char* argv[]);

#if _WIN32
int wmain(int argc, wchar_t* wargv[], wchar_t* envp[]) {
  char** argv;
  if (wargv && argc > 0) {
    argv = new char*[argc];
    for (int i=0; i<argc; ++i)
      argv[i] = base_strdup(base::to_utf8(std::wstring(wargv[i])).c_str());
  }
  else {
    argv = new char*[1];
    argv[0] = base_strdup("");
    argc = 1;
  }
#else
int main(int argc, char* argv[]) {
#endif
  return app_main(argc, argv);
}
<commit_msg>Fix compilation of os::NoneSystem<commit_after>// LAF OS Library
// Copyright (C) 2018  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/memory.h"
#include "gfx/size.h"
#include "os/system.h"

namespace os {

class NoneSystem : public System {
public:
  void dispose() override { delete this; }
  void activateApp() override { }
  void finishLaunching() override { }
  Capabilities capabilities() const override { return (Capabilities)0; }
  void useWintabAPI(bool enable) override { }
  Logger* logger() override { return nullptr; }
  Menus* menus() override { return nullptr; }
  NativeDialogs* nativeDialogs() override { return nullptr; }
  EventQueue* eventQueue() override { return nullptr; }
  bool gpuAcceleration() const override { return false; }
  void setGpuAcceleration(bool state) override { }
  gfx::Size defaultNewDisplaySize() override { return gfx::Size(0, 0); }
  Display* defaultDisplay() override { return nullptr; }
  Display* createDisplay(int width, int height, int scale) override { return nullptr; }
  Surface* createSurface(int width, int height) override { return nullptr; }
  Surface* createRgbaSurface(int width, int height) override { return nullptr; }
  Surface* loadSurface(const char* filename) override { return nullptr; }
  Surface* loadRgbaSurface(const char* filename) override { return nullptr; }
  Font* loadSpriteSheetFont(const char* filename, int scale) override { return nullptr; }
  Font* loadTrueTypeFont(const char* filename, int height) override { return nullptr; }
  bool isKeyPressed(KeyScancode scancode) override { return false; }
  KeyModifiers keyModifiers() override { return kKeyNoneModifier; }
  int getUnicodeFromScancode(KeyScancode scancode) override { return 0; }
  void setTranslateDeadKeys(bool state) override { }
};

System* create_system_impl() {
  return new NoneSystem;
}

void error_message(const char* msg)
{
  fputs(msg, stderr);
  // TODO
}

} // namespace os

extern int app_main(int argc, char* argv[]);

#if _WIN32
int wmain(int argc, wchar_t* wargv[], wchar_t* envp[]) {
  char** argv;
  if (wargv && argc > 0) {
    argv = new char*[argc];
    for (int i=0; i<argc; ++i)
      argv[i] = base_strdup(base::to_utf8(std::wstring(wargv[i])).c_str());
  }
  else {
    argv = new char*[1];
    argv[0] = base_strdup("");
    argc = 1;
  }
#else
int main(int argc, char* argv[]) {
#endif
  return app_main(argc, argv);
}
<|endoftext|>


<commit_before>//- Standard Library -
#include <map>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

//- Beach Judge -
#include <BeachJudge/Base.h>
#include <BeachJudge/Session.h>

using namespace std;

#define BEACHJUDGE_SESSION_EXPIREMS 30 * 60 * 1000 //- TODO: Externalize to Config -

namespace beachjudge
{
	bool SessionExpireComp(Session *sessA, Session *sessB)
	{
		return sessA->GetExpireTimeMS() > sessB->GetExpireTimeMS();
	}

	map<unsigned long, Session *> g_sessionMap;
	map<unsigned short, Session *> g_sessionIDMap;
	vector<Session *> g_sessionVec;

	Session *Session::Create(unsigned long address, unsigned short port, Team *team)
	{
		Session *session = Lookup(address);
		if(!session)
		{
			session = new Session();
			session->m_address = address;
			string addrStr;
			for(unsigned char a = 0; a < 4; a++)
			{
				char buff[4];
				memset(buff, 0, 4);
				sprintf(buff, "%d", (unsigned short)(address & 0xFF));
				addrStr.append(buff);
				address >>= 8;
				if(a < 3)
					addrStr.push_back('.');
			}
			session->m_addressString = addrStr;

			g_sessionMap[address] = session;

			do
			{
				session->m_id = (unsigned short)rand();
			}
			while(g_sessionIDMap.count(session->m_id));
			g_sessionIDMap[session->m_id] = session;
			g_sessionVec.push_back(session);
		}

		session->m_port = port;
		session->m_team = team;
		session->ResetTimeout();
		return session;
	}
	Session *Session::Lookup(unsigned long address)
	{
		if(g_sessionMap.count(address))
			return g_sessionMap[address];
		return 0;
	}
	void Session::Cleanup(bool deleteAll)
	{
		unsigned long currTimeMS = getRunTimeMS();
		while(g_sessionVec.size())
		{
			Session *session = g_sessionVec.back();
			if(deleteAll || session->GetExpireTimeMS() <= currTimeMS)
				delete session;
		}
	}

	void Session::ListCurrent()
	{
		if(g_sessionMap.size())
		{
			cout << "Current Sessions:" << endl;
			unsigned long currTimeMS = getRunTimeMS();
			for(map<unsigned long, Session *>::iterator it = g_sessionMap.begin(); it != g_sessionMap.end(); it++)
			{
				Session *session = it->second;
				cout << "+ " << session->m_id << '\t' << session->m_addressString << ":" << session->m_port << '\t' << session->m_team->GetName() << '\t' << (session->m_expireTimeMS - currTimeMS) << endl;
			}
		}
		else
			cout << "No Current Sessions" << endl;
	}

	Session::Session()
	{
		m_id = 0;
		m_team = 0;
		m_expireTimeMS = 0;
		m_variables["loggedIn"] = 1;
	}
	Session::~Session()
	{
		g_sessionMap.erase(this->m_address);
		g_sessionIDMap.erase(this->m_id);
		g_sessionVec.erase(find(g_sessionVec.begin(), g_sessionVec.end(), this));
	}
	unsigned long Session::GetExpireTimeMS() const
	{
		return m_expireTimeMS;
	}
	unsigned short Session::GetID() const
	{
		return m_id;
	}
	Team *Session::GetTeam() const
	{
		return m_team;
	}
	unsigned short Session::GetVariable(std::string name)
	{
		if(m_variables.count(name))
			return m_variables[name];
		return 0;
	}
	void Session::ResetTimeout()
	{
		m_expireTimeMS = getRunTimeMS() + BEACHJUDGE_SESSION_EXPIREMS;
		sort(g_sessionVec.begin(), g_sessionVec.end(), SessionExpireComp);
	}
}
<commit_msg>Fixed Session cleanup<commit_after>//- Standard Library -
#include <map>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

//- Beach Judge -
#include <BeachJudge/Base.h>
#include <BeachJudge/Session.h>

using namespace std;

#define BEACHJUDGE_SESSION_EXPIREMS 30 * 60 * 1000 //- TODO: Externalize to Config -

namespace beachjudge
{
	bool SessionExpireComp(Session *sessA, Session *sessB)
	{
		return sessA->GetExpireTimeMS() > sessB->GetExpireTimeMS();
	}

	map<unsigned long, Session *> g_sessionMap;
	map<unsigned short, Session *> g_sessionIDMap;
	vector<Session *> g_sessionVec;

	Session *Session::Create(unsigned long address, unsigned short port, Team *team)
	{
		Session *session = Lookup(address);
		if(!session)
		{
			session = new Session();
			session->m_address = address;
			string addrStr;
			g_sessionMap[address] = session;
			for(unsigned char a = 0; a < 4; a++)
			{
				char buff[4];
				memset(buff, 0, 4);
				sprintf(buff, "%d", (unsigned short)(address & 0xFF));
				addrStr.append(buff);
				address >>= 8;
				if(a < 3)
					addrStr.push_back('.');
			}
			session->m_addressString = addrStr;

			do
			{
				session->m_id = (unsigned short)rand();
			}
			while(g_sessionIDMap.count(session->m_id));
			g_sessionIDMap[session->m_id] = session;
			g_sessionVec.push_back(session);
		}

		session->m_port = port;
		session->m_team = team;
		session->ResetTimeout();
		return session;
	}
	Session *Session::Lookup(unsigned long address)
	{
		if(g_sessionMap.count(address))
			return g_sessionMap[address];
		return 0;
	}
	void Session::Cleanup(bool deleteAll)
	{
		unsigned long currTimeMS = getRunTimeMS();
		while(g_sessionVec.size())
		{
			Session *session = g_sessionVec.back();
			if(deleteAll || session->GetExpireTimeMS() <= currTimeMS)
				delete session;
			else
				break;
		}
	}

	void Session::ListCurrent()
	{
		if(g_sessionMap.size())
		{
			cout << "Current Sessions:" << endl;
			unsigned long currTimeMS = getRunTimeMS();
			for(map<unsigned long, Session *>::iterator it = g_sessionMap.begin(); it != g_sessionMap.end(); it++)
			{
				Session *session = it->second;
				cout << "+ " << session->m_id << '\t' << session->m_addressString << ":" << session->m_port << '\t' << session->m_team->GetName() << '\t' << (session->m_expireTimeMS - currTimeMS) << endl;
			}
		}
		else
			cout << "No Current Sessions" << endl;
	}

	Session::Session()
	{
		m_id = 0;
		m_team = 0;
		m_expireTimeMS = 0;
		m_variables["loggedIn"] = 1;
	}
	Session::~Session()
	{
		g_sessionMap.erase(this->m_address);
		g_sessionIDMap.erase(this->m_id);
		g_sessionVec.erase(find(g_sessionVec.begin(), g_sessionVec.end(), this));
	}
	unsigned long Session::GetExpireTimeMS() const
	{
		return m_expireTimeMS;
	}
	unsigned short Session::GetID() const
	{
		return m_id;
	}
	Team *Session::GetTeam() const
	{
		return m_team;
	}
	unsigned short Session::GetVariable(std::string name)
	{
		if(m_variables.count(name))
			return m_variables[name];
		return 0;
	}
	void Session::ResetTimeout()
	{
		m_expireTimeMS = getRunTimeMS() + BEACHJUDGE_SESSION_EXPIREMS;
		sort(g_sessionVec.begin(), g_sessionVec.end(), SessionExpireComp);
	}
}
<|endoftext|>


<commit_before>#include "Testing.h"

#ifdef DEBUG
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <cmath>
#include <thread>
#include <iomanip>

#include "Game/Board.h"
#include "Game/Clock.h"
#include "Moves/Complete_Move.h"
#include "Players/Genetic_AI.h"
#include "Players/Game_Tree_Node_Result.h"

#include "Utility.h"

#include "Exceptions/Illegal_Move_Exception.h"

// Declaration to silence warnings
bool files_are_identical(const std::string& file_name1, const std::string& file_name2);

bool files_are_identical(const std::string& file_name1, const std::string& file_name2)
{
    std::ifstream file1(file_name1);
    std::ifstream file2(file_name2);
    int line_count = 0;

    while(true)
    {
        std::string line1, line2;
        std::getline(file1, line1);
        std::getline(file2, line2);
        ++line_count;

        if(line1 != line2)
        {
            std::cerr << "Mismatch at line " << line_count << ":\n";
            std::cerr << line1 << " != " << line2 << "\n";
            return false;
        }

        if( ! file1 && ! file2)
        {
            break;
        }
    }

    return true;
}

void run_tests()
{
    bool tests_passed = true;

    // Basic chess rules check
    Board starting_board;
    auto starting_move_count = starting_board.legal_moves().size();
    auto correct_move_count = 20;
    if(starting_move_count != correct_move_count)
    {
        std::cerr << "Wrong number of legal moves at beginning of game. Got " << starting_move_count
                  << ", should be " << correct_move_count << std::endl;
        std::cerr << "Legal moves found:" << std::endl;
        auto move_count = 0;
        for(const auto& move : starting_board.legal_moves())
        {
            std::cerr << ++move_count << ". " << move.game_record_item(starting_board) << std::endl;
        }

        tests_passed = false;
    }

    // Castling with attacking piece
    for(auto castle_side : std::string("KQ"))
    {
        for(int rook_left_space = 0; rook_left_space < 8; ++rook_left_space)
        {
            auto rook_left  = (rook_left_space > 0 ? std::to_string(rook_left_space) : std::string());
            auto rook_right = (rook_left_space < 7 ? std::to_string(7 - rook_left_space) : std::string());
            Board board("1k6/" + rook_left + "r" + rook_right + "/8/8/8/8/8/R3K2R w KQ - 0 1");

            char final_file = (castle_side == 'K' ? 'g' : 'c');

            try
            {
                board.get_complete_move('e', 1, final_file, 1);
            }
            catch(const Illegal_Move_Exception&)
            {
                if(castle_side == 'K')
                {
                    if(rook_left_space >= 4 && rook_left_space <= 6)
                    {
                        continue;
                    }
                }
                else
                {
                    if(rook_left_space >= 2 && rook_left_space <= 4)
                    {
                        continue;
                    }
                }

                board.ascii_draw(WHITE);
                std::cout << std::string(1, castle_side) + "-castle should be legal here." << std::endl;
                tests_passed = false;
            }

            if(castle_side == 'K')
            {
                if(rook_left_space < 4 || rook_left_space > 6)
                {
                    continue;
                }
            }
            else
            {
                if(rook_left_space < 2 || rook_left_space > 4)
                {
                    continue;
                }
            }

            board.ascii_draw(WHITE);
            std::cout << std::string(1, castle_side) + "-castle should be illegal here." << std::endl;
            tests_passed = false;
        }
    }

    // Test Genetic_AI file loading
    auto pool_file_name = "test_gene_pool.txt";
    auto write_file_name = "test_genome_write.txt";
    auto rewrite_file_name = "test_genome_rewrite.txt";
    remove(pool_file_name);
    remove(write_file_name);
    remove(rewrite_file_name);

    std::vector<Genetic_AI> test_pool(100);
    for(auto& ai : test_pool)
    {
        for(int i = 0; i < 1000; ++i)
        {
            ai.mutate();
        }
        ai.print_genome(pool_file_name);
    }

    auto index = Random::random_integer(0, test_pool.size() - 1);
    test_pool[index].print_genome(write_file_name);
    auto read_ai = Genetic_AI(pool_file_name, index);
    read_ai.print_genome(rewrite_file_name);

    if( ! files_are_identical(write_file_name, rewrite_file_name))
    {
        std::cerr << "Genome loaded from gene pool file not preserved." << std::endl;
        tests_passed = false;
    }
    else
    {
        remove(pool_file_name);
        remove(write_file_name);
        remove(rewrite_file_name);
    }

    // String utilities
    std::string original = "   a    #     b";
    std::string expected = "a";
    std::string result = String::strip_comments(original, '#');
    if(expected != result)
    {
        std::cerr << "\"" << original << "\" --> \"" << result << "\"" << std::endl;
        std::cerr << "Expected result: \"" << expected << "\"" << std::endl;
        tests_passed = false;
    }

    original = "   a    {    b    }    c   {   d  }   ";
    expected = "a c";
    result = String::strip_block_comment(original, '{', '}');
    if(expected != result)
    {
        std::cerr << "\"" << original << "\" --> \"" << result << "\"" << std::endl;
        std::cerr << "Expected result: \"" << expected << "\"" << std::endl;
        tests_passed = false;
    }

    std::string search_string = "abcdefg";
    std::string target = "abc";
    if( ! String::starts_with(search_string, target))
    {
        std::cerr << "\"" << target << "\" not found at beginning of " << search_string << std::endl;
        tests_passed = false;
    }

    std::string wrong_target = "abd";
    if(String::starts_with(search_string, wrong_target))
    {
        std::cerr << "\"" << wrong_target << "\" erroneously found at beginning of " << search_string << std::endl;
        tests_passed = false;
    }

    // Log-Norm distribution check
    const double mean_moves = 26.0;
    const double width = .5;
    const size_t moves_so_far = 22;
    auto moves_left = Math::average_moves_left(mean_moves, width, moves_so_far);
    auto expected_moves_left = 15.2629;
    if(std::abs(moves_left - expected_moves_left) > 1e-4)
    {
        std::cout << "Log-Norm failed: Expected: " << expected_moves_left
                  << " --- Got: " << moves_left << std::endl;
        tests_passed = false;
    }

    // Clock time reset test
    auto time = 30;
    double expected_time_after_reset;
    auto moves_to_reset = 40;
    auto clock = Clock(time, moves_to_reset);
    clock.start();
    for(int i = 0; i < 2*moves_to_reset; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
        expected_time_after_reset = clock.time_left(BLACK) + time;
        clock.punch();
    }
    clock.stop();
    if(std::abs(clock.time_left(BLACK) - expected_time_after_reset) > 1e-3)
    {
        std::cerr << "Clock incorrect: time left for black is " << clock.time_left(BLACK) << " sec. Should be " << expected_time_after_reset << "sec." << std::endl;
        tests_passed = false;
    }

    // Clock time increment test
    auto increment = 5;
    auto clock2 = Clock(time, 0, increment);
    clock2.start();
    double expected_time = time;
    for(int i = 0; i < 2*moves_to_reset; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
        clock2.punch();
        if(i % 2 == 1) // only on black moves
        {
            expected_time += increment - 0.005;
        }
    }
    clock2.stop();
    if(std::abs(clock2.time_left(BLACK) - expected_time) > 0.01)
    {
        std::cerr << "Clock incorrect: time left for black is " << clock2.time_left(BLACK) << " sec. Should be " << expected_time << "sec." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result r1 = {Complete_Move(),
                                10,
                                WHITE,
                                2,
                                {}};
    Game_Tree_Node_Result r2 = {Complete_Move(),
                                10,
                                BLACK,
                                2,
                                {}};

    if(better_than(r2, r1, WHITE))
    {
        std::cerr << "1. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    if(better_than(r1, r2, BLACK))
    {
        std::cerr << "2. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         -Math::infinity,
                                         WHITE,
                                         0,
                                         {}};

    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::infinity,
                                        WHITE,
                                        0,
                                        {}};
    if(better_than(alpha_start, beta_start, WHITE))
    {
        std::cerr << "3. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    if( ! better_than(alpha_start, beta_start, BLACK))
    {
        std::cerr << "4. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result white_win4 = {Complete_Move(),
                                        Math::win_score,
                                        WHITE,
                                        4,
                                        {}};
    Game_Tree_Node_Result white_win6 = {Complete_Move(),
                                        Math::win_score,
                                        WHITE,
                                        6,
                                        {}};
    if(better_than(white_win6, white_win4, WHITE))
    {
        std::cerr << "Later win preferred over earlier win." << std::endl;
        tests_passed = false;
    }

    if(better_than(white_win4, white_win6, BLACK))
    {
        std::cerr << "Earlier loss preferred over later win." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result black_loss6 = {Complete_Move(),
                                         -Math::win_score,
                                         BLACK,
                                         6,
                                         {}};
    if( ! (white_win6 == black_loss6))
    {
        std::cerr << "White win in 6 not equal to black loss in 6." << std::endl;
        tests_passed = false;
    }

    // Move ambiguity check
    Board board;
    bool ambiguous_move_caught = false;
    try
    {
        for(auto move : {"Nc3", "a1",
                         "Nf3", "b1",
                         "Ne4", "c1",
                         "Ng5"})
        {
            board.submit_move(board.get_complete_move(move));
        }
    }
    catch(const Illegal_Move_Exception&)
    {
        ambiguous_move_caught = true;
    }

    if( ! ambiguous_move_caught)
    {
        std::cerr << "Last move should have been an error:" << std::endl;
        board.print_game_record(nullptr, nullptr,
                                "", Game_Result(NONE, "", false), 0, 0, 0, Clock());

        tests_passed = false;
    }

    Board().ascii_draw(WHITE);

    int int_width = 10;
    int real_width = 15;
    int norm_width = 15;
    std::cout << std::setw(int_width) << "Integers"
              << std::setw(real_width) << "Reals"
              << std::setw(norm_width) << "Normals" << '\n';
    std::cout << std::setw(int_width) << "+/-1000"
              << std::setw(real_width) << "[0-2]"
              << std::setw(norm_width) << "sig = 3" << '\n';
    for(int i = 0; i < 10; ++i)
    {
        std::cout << std::setw(int_width) << Random::random_integer(-1000, 1000)
                  << std::setw(real_width) << Random::random_real(0, 2)
                  << std::setw(norm_width) << Random::random_normal(3) << '\n';
    }

    // FEN input/output
    for(std::string test : {"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
                            "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
                            "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2",
                            "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"})
    {
        if(Board(test).fen_status() != test)
        {
            std::cerr << test << " -->\n" << Board(test).fen_status() << "\n\n";
            tests_passed = false;
        }
    }

    if(tests_passed)
    {
        std::cout << "All tests passed." << std::endl;
    }
    else
    {
        std::cout << "Tests failed." << std::endl;
    }
}
#else
void run_tests() {}
#endif
<commit_msg>Fix signed/unsigned comparison<commit_after>#include "Testing.h"

#ifdef DEBUG
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <cmath>
#include <thread>
#include <iomanip>

#include "Game/Board.h"
#include "Game/Clock.h"
#include "Moves/Complete_Move.h"
#include "Players/Genetic_AI.h"
#include "Players/Game_Tree_Node_Result.h"

#include "Utility.h"

#include "Exceptions/Illegal_Move_Exception.h"

// Declaration to silence warnings
bool files_are_identical(const std::string& file_name1, const std::string& file_name2);

bool files_are_identical(const std::string& file_name1, const std::string& file_name2)
{
    std::ifstream file1(file_name1);
    std::ifstream file2(file_name2);
    int line_count = 0;

    while(true)
    {
        std::string line1, line2;
        std::getline(file1, line1);
        std::getline(file2, line2);
        ++line_count;

        if(line1 != line2)
        {
            std::cerr << "Mismatch at line " << line_count << ":\n";
            std::cerr << line1 << " != " << line2 << "\n";
            return false;
        }

        if( ! file1 && ! file2)
        {
            break;
        }
    }

    return true;
}

void run_tests()
{
    bool tests_passed = true;

    // Basic chess rules check
    Board starting_board;
    auto starting_move_count = starting_board.legal_moves().size();
    size_t correct_move_count = 20;
    if(starting_move_count != correct_move_count)
    {
        std::cerr << "Wrong number of legal moves at beginning of game. Got " << starting_move_count
                  << ", should be " << correct_move_count << std::endl;
        std::cerr << "Legal moves found:" << std::endl;
        auto move_count = 0;
        for(const auto& move : starting_board.legal_moves())
        {
            std::cerr << ++move_count << ". " << move.game_record_item(starting_board) << std::endl;
        }

        tests_passed = false;
    }

    // Castling with attacking piece
    for(auto castle_side : std::string("KQ"))
    {
        for(int rook_left_space = 0; rook_left_space < 8; ++rook_left_space)
        {
            auto rook_left  = (rook_left_space > 0 ? std::to_string(rook_left_space) : std::string());
            auto rook_right = (rook_left_space < 7 ? std::to_string(7 - rook_left_space) : std::string());
            Board board("1k6/" + rook_left + "r" + rook_right + "/8/8/8/8/8/R3K2R w KQ - 0 1");

            char final_file = (castle_side == 'K' ? 'g' : 'c');

            try
            {
                board.get_complete_move('e', 1, final_file, 1);
            }
            catch(const Illegal_Move_Exception&)
            {
                if(castle_side == 'K')
                {
                    if(rook_left_space >= 4 && rook_left_space <= 6)
                    {
                        continue;
                    }
                }
                else
                {
                    if(rook_left_space >= 2 && rook_left_space <= 4)
                    {
                        continue;
                    }
                }

                board.ascii_draw(WHITE);
                std::cout << std::string(1, castle_side) + "-castle should be legal here." << std::endl;
                tests_passed = false;
            }

            if(castle_side == 'K')
            {
                if(rook_left_space < 4 || rook_left_space > 6)
                {
                    continue;
                }
            }
            else
            {
                if(rook_left_space < 2 || rook_left_space > 4)
                {
                    continue;
                }
            }

            board.ascii_draw(WHITE);
            std::cout << std::string(1, castle_side) + "-castle should be illegal here." << std::endl;
            tests_passed = false;
        }
    }

    // Test Genetic_AI file loading
    auto pool_file_name = "test_gene_pool.txt";
    auto write_file_name = "test_genome_write.txt";
    auto rewrite_file_name = "test_genome_rewrite.txt";
    remove(pool_file_name);
    remove(write_file_name);
    remove(rewrite_file_name);

    std::vector<Genetic_AI> test_pool(100);
    for(auto& ai : test_pool)
    {
        for(int i = 0; i < 1000; ++i)
        {
            ai.mutate();
        }
        ai.print_genome(pool_file_name);
    }

    auto index = Random::random_integer(0, test_pool.size() - 1);
    test_pool[index].print_genome(write_file_name);
    auto read_ai = Genetic_AI(pool_file_name, index);
    read_ai.print_genome(rewrite_file_name);

    if( ! files_are_identical(write_file_name, rewrite_file_name))
    {
        std::cerr << "Genome loaded from gene pool file not preserved." << std::endl;
        tests_passed = false;
    }
    else
    {
        remove(pool_file_name);
        remove(write_file_name);
        remove(rewrite_file_name);
    }

    // String utilities
    std::string original = "   a    #     b";
    std::string expected = "a";
    std::string result = String::strip_comments(original, '#');
    if(expected != result)
    {
        std::cerr << "\"" << original << "\" --> \"" << result << "\"" << std::endl;
        std::cerr << "Expected result: \"" << expected << "\"" << std::endl;
        tests_passed = false;
    }

    original = "   a    {    b    }    c   {   d  }   ";
    expected = "a c";
    result = String::strip_block_comment(original, '{', '}');
    if(expected != result)
    {
        std::cerr << "\"" << original << "\" --> \"" << result << "\"" << std::endl;
        std::cerr << "Expected result: \"" << expected << "\"" << std::endl;
        tests_passed = false;
    }

    std::string search_string = "abcdefg";
    std::string target = "abc";
    if( ! String::starts_with(search_string, target))
    {
        std::cerr << "\"" << target << "\" not found at beginning of " << search_string << std::endl;
        tests_passed = false;
    }

    std::string wrong_target = "abd";
    if(String::starts_with(search_string, wrong_target))
    {
        std::cerr << "\"" << wrong_target << "\" erroneously found at beginning of " << search_string << std::endl;
        tests_passed = false;
    }

    // Log-Norm distribution check
    const double mean_moves = 26.0;
    const double width = .5;
    const size_t moves_so_far = 22;
    auto moves_left = Math::average_moves_left(mean_moves, width, moves_so_far);
    auto expected_moves_left = 15.2629;
    if(std::abs(moves_left - expected_moves_left) > 1e-4)
    {
        std::cout << "Log-Norm failed: Expected: " << expected_moves_left
                  << " --- Got: " << moves_left << std::endl;
        tests_passed = false;
    }

    // Clock time reset test
    auto time = 30;
    double expected_time_after_reset;
    auto moves_to_reset = 40;
    auto clock = Clock(time, moves_to_reset);
    clock.start();
    for(int i = 0; i < 2*moves_to_reset; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
        expected_time_after_reset = clock.time_left(BLACK) + time;
        clock.punch();
    }
    clock.stop();
    if(std::abs(clock.time_left(BLACK) - expected_time_after_reset) > 1e-3)
    {
        std::cerr << "Clock incorrect: time left for black is " << clock.time_left(BLACK) << " sec. Should be " << expected_time_after_reset << "sec." << std::endl;
        tests_passed = false;
    }

    // Clock time increment test
    auto increment = 5;
    auto clock2 = Clock(time, 0, increment);
    clock2.start();
    double expected_time = time;
    for(int i = 0; i < 2*moves_to_reset; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
        clock2.punch();
        if(i % 2 == 1) // only on black moves
        {
            expected_time += increment - 0.005;
        }
    }
    clock2.stop();
    if(std::abs(clock2.time_left(BLACK) - expected_time) > 0.01)
    {
        std::cerr << "Clock incorrect: time left for black is " << clock2.time_left(BLACK) << " sec. Should be " << expected_time << "sec." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result r1 = {Complete_Move(),
                                10,
                                WHITE,
                                2,
                                {}};
    Game_Tree_Node_Result r2 = {Complete_Move(),
                                10,
                                BLACK,
                                2,
                                {}};

    if(better_than(r2, r1, WHITE))
    {
        std::cerr << "1. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    if(better_than(r1, r2, BLACK))
    {
        std::cerr << "2. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         -Math::infinity,
                                         WHITE,
                                         0,
                                         {}};

    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::infinity,
                                        WHITE,
                                        0,
                                        {}};
    if(better_than(alpha_start, beta_start, WHITE))
    {
        std::cerr << "3. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    if( ! better_than(alpha_start, beta_start, BLACK))
    {
        std::cerr << "4. Error in comparing Game Tree Node Results." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result white_win4 = {Complete_Move(),
                                        Math::win_score,
                                        WHITE,
                                        4,
                                        {}};
    Game_Tree_Node_Result white_win6 = {Complete_Move(),
                                        Math::win_score,
                                        WHITE,
                                        6,
                                        {}};
    if(better_than(white_win6, white_win4, WHITE))
    {
        std::cerr << "Later win preferred over earlier win." << std::endl;
        tests_passed = false;
    }

    if(better_than(white_win4, white_win6, BLACK))
    {
        std::cerr << "Earlier loss preferred over later win." << std::endl;
        tests_passed = false;
    }

    Game_Tree_Node_Result black_loss6 = {Complete_Move(),
                                         -Math::win_score,
                                         BLACK,
                                         6,
                                         {}};
    if( ! (white_win6 == black_loss6))
    {
        std::cerr << "White win in 6 not equal to black loss in 6." << std::endl;
        tests_passed = false;
    }

    // Move ambiguity check
    Board board;
    bool ambiguous_move_caught = false;
    try
    {
        for(auto move : {"Nc3", "a1",
                         "Nf3", "b1",
                         "Ne4", "c1",
                         "Ng5"})
        {
            board.submit_move(board.get_complete_move(move));
        }
    }
    catch(const Illegal_Move_Exception&)
    {
        ambiguous_move_caught = true;
    }

    if( ! ambiguous_move_caught)
    {
        std::cerr << "Last move should have been an error:" << std::endl;
        board.print_game_record(nullptr, nullptr,
                                "", Game_Result(NONE, "", false), 0, 0, 0, Clock());

        tests_passed = false;
    }

    Board().ascii_draw(WHITE);

    int int_width = 10;
    int real_width = 15;
    int norm_width = 15;
    std::cout << std::setw(int_width) << "Integers"
              << std::setw(real_width) << "Reals"
              << std::setw(norm_width) << "Normals" << '\n';
    std::cout << std::setw(int_width) << "+/-1000"
              << std::setw(real_width) << "[0-2]"
              << std::setw(norm_width) << "sig = 3" << '\n';
    for(int i = 0; i < 10; ++i)
    {
        std::cout << std::setw(int_width) << Random::random_integer(-1000, 1000)
                  << std::setw(real_width) << Random::random_real(0, 2)
                  << std::setw(norm_width) << Random::random_normal(3) << '\n';
    }

    // FEN input/output
    for(std::string test : {"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
                            "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
                            "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2",
                            "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"})
    {
        if(Board(test).fen_status() != test)
        {
            std::cerr << test << " -->\n" << Board(test).fen_status() << "\n\n";
            tests_passed = false;
        }
    }

    if(tests_passed)
    {
        std::cout << "All tests passed." << std::endl;
    }
    else
    {
        std::cout << "Tests failed." << std::endl;
    }
}
#else
void run_tests() {}
#endif
<|endoftext|>