<commit_before>#include "MenuComponent.hpp"
#include "GameEngine/GameEngine.h"
#include "SpriteComponent.hpp"
#include "FileSystem/ImagePreloadingMapper.hpp"
#include "Events/UIChangeEvent.hpp"
#include "Events/UISelectEvent.hpp"
#include "GameEngine/Utilities.hpp"

namespace ASSB
{
	// Constructor
	MenuComponent::MenuComponent(Globals::ObjectID owner, std::string indicatorTag, bool vertical)
		: Component(owner)
		, active_(true)
		, selected_(0)
		, spacing_({ 0, -1, 0 })
		, pos_({ 0, 0, 0 })
		, selectionIndicator_()
		, interactables_()
		, vertical_(vertical)
	{
		selectionIndicator_ = GameEngine::Instance->CreateGameObject();
		SetIndicatorTag(indicatorTag, { 1,1,0 });

		// Connect Events
		Connect(this, &MenuComponent::handleKeyboardEvent);
	}

	void MenuComponent::SetVisible(bool isVisible)
	{
		if (isVisible == false)
		{
			for (size_t i = 0; i < interactables_.size(); ++i)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(interactables_[i].first)
					->Visible = false;
			}
			GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->Visible = false;
		}
		else
		{
			for (size_t i = 0; i < interactables_.size(); ++i)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(interactables_[i].first)
					->Visible = true;
			}
			GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->Visible = true;
		}
	}

	void MenuComponent::SetActive(bool isActive)
	{
		active_ = isActive;
	}

	bool MenuComponent::IsActive()
	{
		return active_;
	}
	// 0-based indexing into the array
	void MenuComponent::SetIndicated(int index)
	{
		if (index < 0)
			index = 0;
		if (index > static_cast<int>(interactables_.size()) - 1)
			index = static_cast<int>(interactables_.size()) - 1;

		selected_ = index;
	}

	// Selects the current index, dispatching the associated event.
	void MenuComponent::Select()
	{
		Globals::EventSystemInstance.Dispatch(new UISelectEvent());
		interactables_[static_cast<size_t>(selected_)].second->Dispatch();
	}

	// Keyboard event callback
	void MenuComponent::handleKeyboardEvent(KeyboardEvent *e)
	{
		if (active_)
		{
			if(e->Down)
			{
				const Key k{ e->Key };
				if (vertical_)
				{
					if (k == Key::S || k == Key::Down || k == Key::Numpad_2)
						IncrementIndicated();
					else if (k == Key::W || k == Key::Up || k == Key::Numpad_8)
						DectementIndicated();
				}
				else // Horizontal
				{
					if (k == Key::D || k == Key::Right || k == Key::Numpad_6)
						IncrementIndicated();
					else if (k == Key::A || k == Key::Left || k == Key::Numpad_4)
						DectementIndicated();
				}

				// Key selected
				if (k == Key::Enter || k == Key::Space || k == Key::Numpad_Enter)
					Select();
			}
		}
	}

	// Updates location of selection indicator to position of the new item
	void MenuComponent::updateSelectionIndicator()
	{
		ComponentHandle<TransformComponent> indicatorLoc = GameEngine::Instance->GetComponent<TransformComponent>(selectionIndicator_);
		ComponentHandle<TransformComponent> interactableLoc = GameEngine::Instance->GetComponent<TransformComponent>(interactables_[static_cast<size_t>(selected_)].first);
		//!TODO: ACTIONS SYSTEM FOR INTERPOLATION
		Utilities::Instance->InterpolatePos(selectionIndicator_, interactableLoc->GetPosition(), 80);
		//indicatorLoc->SetPosition(interactableLoc->GetPosition());
	}

	// Increments the position: Goes Down or Right
	void MenuComponent::IncrementIndicated()
	{
		++selected_;
		if (selected_ >= static_cast<int>(interactables_.size()))
		  selected_ = 0;

		Globals::EventSystemInstance.Dispatch(new UIChangeEvent());
		updateSelectionIndicator();
	}

	// Decrements the positon: Goes Up or Left.
	void MenuComponent::DectementIndicated()
	{
		--selected_;
		if (selected_ < 0)
			selected_ = static_cast<int>(interactables_.size()) - 1;

		Globals::EventSystemInstance.Dispatch(new UIChangeEvent());
		updateSelectionIndicator();
	}

	// Updates the selection location
	void MenuComponent::updateSpacing()
	{
		for (size_t i = 0; i < interactables_.size(); ++i)
		{
			GameEngine::Instance->GetComponent<TransformComponent>(interactables_[i].first)->
				SetPosition(pos_ + spacing_ * static_cast<float>(i));
		}
	}

	// Getters and Setters
	void MenuComponent::SetIndicatorTag(std::string indicatorTag, Graphics::Vector4 scale)
	{
		if (indicatorTag.size() > 0)
		{
			std::string path = FileSystem::ImagePreloadingMapper::Retrieve(indicatorTag);
			if (path.size() > 0)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->
					AddPath(std::wstring(path.begin(), path.end()));
				GameEngine::Instance->GetComponent<TransformComponent>(selectionIndicator_)->
					SetScale(scale.X, scale.Y);
			}
		}
	}
	void MenuComponent::SetVertical(bool isVertical)
	{
		vertical_ = isVertical;
	}
	bool MenuComponent::IsVertical()
	{
		return vertical_;
	}
	void MenuComponent::SetSpacing(Graphics::Vector4 spacingVal)
	{
		spacing_ = spacingVal;
	}
	void MenuComponent::SetPosition(Graphics::Vector4 newPos)
	{
		pos_ = newPos;
	}
	Graphics::Vector4 MenuComponent::GetPosition()
	{
		return pos_;
	}
	int MenuComponent::GetIndicated()
	{
		return selected_;
	}
	Graphics::Vector4 MenuComponent::GetSpacing()
	{
		return spacing_;
	}
}<commit_msg>+ Moved to front<commit_after>#include "MenuComponent.hpp"
#include "GameEngine/GameEngine.h"
#include "SpriteComponent.hpp"
#include "FileSystem/ImagePreloadingMapper.hpp"
#include "Events/UIChangeEvent.hpp"
#include "Events/UISelectEvent.hpp"
#include "GameEngine/Utilities.hpp"

namespace ASSB
{
	// Constructor
	MenuComponent::MenuComponent(Globals::ObjectID owner, std::string indicatorTag, bool vertical)
		: Component(owner)
		, active_(true)
		, selected_(0)
		, spacing_({ 0, -1, 0 })
		, pos_({ 0, 0, 0 })
		, selectionIndicator_()
		, interactables_()
		, vertical_(vertical)
	{
		selectionIndicator_ = GameEngine::Instance->CreateGameObject();
		SetIndicatorTag(indicatorTag, { 1,1,0 });

		// Connect Events
		Connect(this, &MenuComponent::handleKeyboardEvent);
	}

	void MenuComponent::SetVisible(bool isVisible)
	{
		if (isVisible == false)
		{
			for (size_t i = 0; i < interactables_.size(); ++i)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(interactables_[i].first)
					->Visible = false;
			}
			GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->Visible = false;
		}
		else
		{
			for (size_t i = 0; i < interactables_.size(); ++i)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(interactables_[i].first)
					->Visible = true;
			}
			GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->Visible = true;
		}
	}

	void MenuComponent::SetActive(bool isActive)
	{
		active_ = isActive;
	}

	bool MenuComponent::IsActive()
	{
		return active_;
	}
	// 0-based indexing into the array
	void MenuComponent::SetIndicated(int index)
	{
		if (index < 0)
			index = 0;
		if (index > static_cast<int>(interactables_.size()) - 1)
			index = static_cast<int>(interactables_.size()) - 1;

		selected_ = index;
	}

	// Selects the current index, dispatching the associated event.
	void MenuComponent::Select()
	{
		Globals::EventSystemInstance.Dispatch(new UISelectEvent());
		interactables_[static_cast<size_t>(selected_)].second->Dispatch();
	}

	// Keyboard event callback
	void MenuComponent::handleKeyboardEvent(KeyboardEvent *e)
	{
		if (active_)
		{
			if(e->Down)
			{
				const Key k{ e->Key };
				if (vertical_)
				{
					if (k == Key::S || k == Key::Down || k == Key::Numpad_2)
						IncrementIndicated();
					else if (k == Key::W || k == Key::Up || k == Key::Numpad_8)
						DectementIndicated();
				}
				else // Horizontal
				{
					if (k == Key::D || k == Key::Right || k == Key::Numpad_6)
						IncrementIndicated();
					else if (k == Key::A || k == Key::Left || k == Key::Numpad_4)
						DectementIndicated();
				}

				// Key selected
				if (k == Key::Enter || k == Key::Space || k == Key::Numpad_Enter)
					Select();
			}
		}
	}

	// Updates location of selection indicator to position of the new item
	void MenuComponent::updateSelectionIndicator()
	{
		ComponentHandle<TransformComponent> indicatorLoc = GameEngine::Instance->GetComponent<TransformComponent>(selectionIndicator_);
		ComponentHandle<TransformComponent> interactableLoc = GameEngine::Instance->GetComponent<TransformComponent>(interactables_[static_cast<size_t>(selected_)].first);
		//!TODO: ACTIONS SYSTEM FOR INTERPOLATION
		Utilities::Instance->InterpolatePos(selectionIndicator_, interactableLoc->GetPosition() + Graphics::Vector4(0, 0, -0.6f), 80);
		//indicatorLoc->SetPosition(interactableLoc->GetPosition());
	}

	// Increments the position: Goes Down or Right
	void MenuComponent::IncrementIndicated()
	{
		++selected_;
		if (selected_ >= static_cast<int>(interactables_.size()))
		  selected_ = 0;

		Globals::EventSystemInstance.Dispatch(new UIChangeEvent());
		updateSelectionIndicator();
	}

	// Decrements the positon: Goes Up or Left.
	void MenuComponent::DectementIndicated()
	{
		--selected_;
		if (selected_ < 0)
			selected_ = static_cast<int>(interactables_.size()) - 1;

		Globals::EventSystemInstance.Dispatch(new UIChangeEvent());
		updateSelectionIndicator();
	}

	// Updates the selection location
	void MenuComponent::updateSpacing()
	{
		for (size_t i = 0; i < interactables_.size(); ++i)
		{
			GameEngine::Instance->GetComponent<TransformComponent>(interactables_[i].first)->
				SetPosition(pos_ + spacing_ * static_cast<float>(i));
		}
	}

	// Getters and Setters
	void MenuComponent::SetIndicatorTag(std::string indicatorTag, Graphics::Vector4 scale)
	{
		if (indicatorTag.size() > 0)
		{
			std::string path = FileSystem::ImagePreloadingMapper::Retrieve(indicatorTag);
			if (path.size() > 0)
			{
				GameEngine::Instance->GetComponent<SpriteComponent>(selectionIndicator_)->
					AddPath(std::wstring(path.begin(), path.end()));
				GameEngine::Instance->GetComponent<TransformComponent>(selectionIndicator_)->
					SetScale(scale.X, scale.Y);
			}
		}
	}
	void MenuComponent::SetVertical(bool isVertical)
	{
		vertical_ = isVertical;
	}
	bool MenuComponent::IsVertical()
	{
		return vertical_;
	}
	void MenuComponent::SetSpacing(Graphics::Vector4 spacingVal)
	{
		spacing_ = spacingVal;
	}
	void MenuComponent::SetPosition(Graphics::Vector4 newPos)
	{
		pos_ = newPos;
	}
	Graphics::Vector4 MenuComponent::GetPosition()
	{
		return pos_;
	}
	int MenuComponent::GetIndicated()
	{
		return selected_;
	}
	Graphics::Vector4 MenuComponent::GetSpacing()
	{
		return spacing_;
	}
}<|endoftext|>


<commit_before>/*
 * convey's game of life
*/

#ifndef GOL_HPP
#define GOL_HPP 1

#include <iostream>
#include <fstream>
#include <cstdlib>

#define GOL_WIDTH	32
#define	GOL_HEIGHT	32

using namespace std;

class gameOfLife {
	public:
		gameOfLife();
		void init_file (char*);
		void play();
	private:
		bool life[GOL_WIDTH][GOL_HEIGHT];
		void show();
		void nextgen();
};

void gameOfLife::show()
{
	for (int i = 0; i < GOL_HEIGHT; i++)
	{
		for (int j = 0; j < GOL_WIDTH; j++)
		{
			(life[j][i]) ? cout << " #" : cout << "  ";
		}
		cout << '\n';
	}
}

void gameOfLife::nextgen()
{
	// analyze each pixel
	int neighbors[GOL_WIDTH][GOL_HEIGHT];
	for (int i = 1; i < GOL_WIDTH - 1; i++)
	{
		for (int j = 1; j < GOL_HEIGHT - 1; j++)
		{
			// calculate the number of neighbors of the pixel
			// The Moore neighborhood checks all 8 surrounding cells
			neighbors[i][j] =
				life[i - 1][j - 1] +
				life[i - 1][j] +
				life[i - 1][j + 1] +
				life[i][j - 1] +
				life[i][j + 1] +
				life[i + 1][j - 1] +
				life[i + 1][j] +
				life[i + 1][j + 1];
		}
	}
	// calculate the state of each pixel in the next generation
	for (int i = 0; i < GOL_WIDTH; i++)
		for (int j = 0; j < GOL_HEIGHT; j++)
		{
			// if it has 3 neighbors it comes to life
			if (neighbors[i][j] == 3)
			{
				life[i][j] = true;
			}
			// if it has 2 neighbors it remains the same
			// every other senario it dies
			else if (neighbors[i][j] != 2)
			{
				life[i][j] = false;
			}
		}
}

gameOfLife::gameOfLife()
{
	// loop through every pixel and assign a random value to it
	srand (time(NULL));
	for (int i = 1; i < GOL_WIDTH - 1; i++)
	{
		for (int j = 1; j < GOL_HEIGHT - 1; j++)
		{
			life[i][j] = rand() % 2;
		}
	}
}

void gameOfLife::init_file (char* filename)
{
	// loop through every non-whitespace charecter in a file and initialize the generation zero
	char ch;
	cout << "Initialized with " << filename << ":\n";
	fstream fin(filename, fstream::in);
	for (int j = 0; j < GOL_HEIGHT; j++)
	{
		for (int i = 0; i < GOL_WIDTH; i++)
		{
			fin >> skipws >> ch;
			life[i][j] = (ch == '#');
		}
	}
}

void gameOfLife::play()
{
	for (int gen = 0; true; gen++)
	{
		cout << "Generation: " << gen << '\n';
		show();
		nextgen();
		// intrupt to let the user see the results
		if (cin.get() == 'q') break;
	}
}

#endif
<commit_msg>Added comments.<commit_after>/*
 * convey's game of life
*/

#ifndef GOL_HPP
#define GOL_HPP 1

#include <iostream>
#include <fstream>
#include <cstdlib>

#define GOL_WIDTH	32
#define	GOL_HEIGHT	32

using namespace std;

class gameOfLife {
	public:
		gameOfLife();
		void init_file (char*);
		void play();
	private:
		bool life[GOL_WIDTH][GOL_HEIGHT];
		void show();
		void nextgen();
};

void gameOfLife::show()
{
	for (int i = 0; i < GOL_HEIGHT; i++)
	{
		for (int j = 0; j < GOL_WIDTH; j++)
		{
			(life[j][i]) ? cout << " #" : cout << "  ";
		}
		cout << '\n';
	}
}

void gameOfLife::nextgen()
{
	// count every pixel's neighbors and store them in an array
	short int neighbors[GOL_WIDTH][GOL_HEIGHT];
	for (int i = 1; i < GOL_WIDTH - 1; i++)
	{
		for (int j = 1; j < GOL_HEIGHT - 1; j++)
		{
			// calculate the number of neighbors of the pixel
			// The Moore neighborhood checks all 8 surrounding cells
			neighbors[i][j] =
				life[i - 1][j - 1] +
				life[i - 1][j] +
				life[i - 1][j + 1] +
				life[i][j - 1] +
				life[i][j + 1] +
				life[i + 1][j - 1] +
				life[i + 1][j] +
				life[i + 1][j + 1];
		}
	}
	// calculate the state of each pixel in the next generation
	for (int i = 0; i < GOL_WIDTH; i++)
		for (int j = 0; j < GOL_HEIGHT; j++)
		{
			// if it has 3 neighbors it comes to life
			if (neighbors[i][j] == 3)
			{
				life[i][j] = true;
			}
			// if it has 2 neighbors it remains the same
			// every other senario it dies
			else if (neighbors[i][j] != 2)
			{
				life[i][j] = false;
			}
		}
}

gameOfLife::gameOfLife()
{
	// loop through every pixel and assign a random value to it
	srand (time(NULL));
	for (int i = 1; i < GOL_WIDTH - 1; i++)
	{
		for (int j = 1; j < GOL_HEIGHT - 1; j++)
		{
			life[i][j] = rand() % 2;
		}
	}
}

void gameOfLife::init_file (char* filename)
{
	// loop through every non-whitespace charecter in a file and initialize the generation zero
	char ch;
	cout << "Initialized with " << filename << ":\n";
	fstream fin(filename, fstream::in);
	for (int j = 0; j < GOL_HEIGHT; j++)
	{
		for (int i = 0; i < GOL_WIDTH; i++)
		{
			fin >> skipws >> ch;
			life[i][j] = (ch == '#');
		}
	}
}

void gameOfLife::play()
{
	for (int gen = 0; true; gen++)
	{
		cout << "Generation: " << gen << '\n';
		show();
		nextgen();
		// intrupt to let the user see the results. enter 'q' to end the game.
		if (cin.get() == 'q') break;
	}
}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

using namespace std;

int main()
{
	int s = 0, input = 0;
	vector<int> val;
	vector<int>::iterator ptr;
	cout<<"Please enter as many integers as you like."<<endl;
	do{
		cin>>input;
		val.push_back(input);
		cout<<"Continue? (1 = Yes / 0 = No)"<<endl;
		cin>>input;
	}while(input != 0);
	cout<<"You have entered "<<val.size()<<" items."<<endl;
	cout<<"The elements entered are:"<<endl;
	for(ptr = val.begin(); ptr != val.end(); ptr++)
	{
		s = s + (*ptr);
		cout<<*ptr<<endl;
	}
	cout<<"The sum is "<<s<<"."<<endl;
	return 0;
}<commit_msg>Update<commit_after>#include <iostream>
#include <vector>

using namespace std;

int main()
{
	int s = 0, input = 0;
	vector<int> val;
	vector<int>::iterator ptr;
	cout<<"Please enter as many integers as you like.Enter ESC followed by Return when you're done."<<endl;
	while(cin>>input)
		val.push_back(input);
	cout<<"You have entered "<<val.size()<<" items."<<endl;
	cout<<"The elements entered are:"<<endl;
	for(ptr = val.begin(); ptr != val.end(); ptr++)
	{
		s = s + (*ptr);
		cout<<*ptr<<endl;
	}
	cout<<"The sum is "<<s<<"."<<endl;
	return 0;
}<|endoftext|>


<commit_before>#include <vector>
#include <iostream>

using namespace std;

int main() {
    vector<int> v(10, 0);
    vector<int>::iterator iter = v.begin();
    int counter = 7;
    for (; iter != v.end(); ++iter) {
        if (counter % 5 == 3) {
            iter = v.insert(iter, -1);
        }
        ++counter;
    }

    cout << v.size() << endl;

    for (size_t i = 0; i < v.size(); ++i) {
        cout << v[i] << " ";
    }
    cout << endl;

    return 0;
}
<commit_msg>remove vector_test.cc<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipPackageFolder.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: mtg $ $Date: 2001-03-16 17:11:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_PACKAGE_FOLDER_HXX
#define _ZIP_PACKAGE_FOLDER_HXX

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
#include <com/sun/star/io/XActiveDataSink.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_PACKAGE_ZIPENTRY_HPP_
#include <com/sun/star/packages/ZipEntry.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif

#include <hash_map>

struct eqFunc
{
    sal_Bool operator()( const rtl::OUString &r1,
                         const rtl::OUString &r2) const
    {
        return r1 == r2;
    }
};

struct hashFunc
{
    sal_Int32 operator()(const rtl::OUString &r1) const
    {
        return r1.hashCode();
    }
};
typedef std::hash_map < rtl::OUString,
                        com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel >,
                        hashFunc,
                        eqFunc > TunnelHash;

typedef std::hash_map < rtl::OUString,
                        com::sun::star::uno::Reference < com::sun::star::container::XNameContainer >,
                        hashFunc,
                        eqFunc > NameHash;

/* This include must be after the above struct and typedef declarations.
 * Ugly...but true :)
 */

#ifndef _ZIP_PACKAGE_FOLDER_ENUMERATION_HXX
#include "ZipPackageFolderEnumeration.hxx"
#endif

#ifndef _ZIP_PACKAGE_ENTRY_HXX
#include "ZipPackageEntry.hxx"
#endif

#ifndef _ZIP_PACKAGE_STREAM_HXX
#include "ZipPackageStream.hxx"
#endif

#ifndef _ZIP_PACKAGE_HXX
#include "ZipPackage.hxx"
#endif

#ifndef _ZIP_PACKAGE_BUFFER_HXX
#include "ZipPackageBuffer.hxx"
#endif

#ifndef _ZIP_OUTPUT_STREAM_HXX
#include "ZipOutputStream.hxx"
#endif

#ifndef _ZIP_FILE_HXX
#include "ZipFile.hxx"
#endif

#ifndef _MANIFEST_ENTRY_HXX
#include "ManifestEntry.hxx"
#endif

class ZipPackage;
class ZipPackageFolder : public ZipPackageEntry,
                         public ::cppu::OWeakObject,
                         public ::com::sun::star::container::XNameContainer,
                         public ::com::sun::star::container::XEnumerationAccess
{
private:
    TunnelHash aContents;
public:
    ZipPackage *pPackage;
    com::sun::star::uno::Reference < com::sun::star::lang::XSingleServiceFactory > xPackage;

    ZipPackageFolder ( void );
    virtual ~ZipPackageFolder( void );

    static void copyZipEntry( com::sun::star::packages::ZipEntry &rDest, const com::sun::star::packages::ZipEntry &rSource);
    // Recursive functions
    void  saveContents(rtl::OUString &rPath, std::vector < ManifestEntry * > &rManList, ZipOutputStream & rZipOut)
        throw(::com::sun::star::uno::RuntimeException);
    void  updateReferences( ZipFile * pNewZipFile);
    void  releaseUpwardRef( void );

    // XInterface
    virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& rType )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL acquire(  )
        throw();
    virtual void SAL_CALL release(  )
        throw();

    // XNameContainer
    virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeByName( const ::rtl::OUString& Name )
        throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    // XEnumerationAccess
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration(  )
        throw(::com::sun::star::uno::RuntimeException);

    // XElementAccess
    virtual ::com::sun::star::uno::Type SAL_CALL getElementType(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasElements(  )
        throw(::com::sun::star::uno::RuntimeException);

    // XNameAccess
    virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
        throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
        throw(::com::sun::star::uno::RuntimeException);

    // XNameReplace
    virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    // XUnoTunnel
    static ::com::sun::star::uno::Sequence < sal_Int8 > getUnoTunnelImplementationId( void )
        throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw(::com::sun::star::uno::RuntimeException);
};
#endif
<commit_msg>Moved header files outside of main inc directory<commit_after><|endoftext|>


<commit_before>
#include "stdafx.h"
#include "dbg.h"
#include <chrono>

namespace common {
	namespace dbg {

		// Log Thread
		common::cWQSemaphore g_logThread;
		struct sLogData
		{
			int type; // 0:log, 1:error log, 2:log + error log, 3:others file
			Str256 str;
		};

		StrPath g_logPath = "log.txt";
		StrPath g_errLogPath = "errlog.txt";

// make sLogData from argument list
#define MAKE_LOGDATA(logData, logType, fmt) \
		{\
			logData.type = logType;\
			va_list args;\
			va_start(args, fmt);\
			vsnprintf_s(logData.str.m_str, sizeof(logData.str.m_str) - 1, _TRUNCATE, fmt, args);\
			va_end(args);\
		}

	}
}

using namespace common;
using namespace dbg;

//------------------------------------------------------------------------
// LogThread Task
class cLogTask : public cTask
				, public common::cMemoryPool4<cLogTask>
{
public:
	const char *m_fileName;
	sLogData m_logData;
	cLogTask() : cTask(0, "cLogTask") {}
	cLogTask(const sLogData &logData, const char *fileName = NULL)
		: cTask(0, "cLogTask"), m_logData(logData), m_fileName(fileName) {
	}
	virtual ~cLogTask() {
	}

	virtual eRunResult::Enum Run(const double deltaSeconds) override
	{
		const string timeStr = common::GetCurrentDateTime();

		switch (m_logData.type)
		{
		case 0:
		{
			std::ofstream ofs1(g_logPath.c_str(), std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << timeStr << " : ";
				ofs1 << m_logData.str.c_str();
			}
		}
		break;

		case 1:
		{
			std::ofstream ofs2(g_errLogPath.c_str(), std::ios::app);
			if (ofs2.is_open())
			{
				ofs2 << timeStr << " : ";
				ofs2 << m_logData.str.c_str();
			}
		}
		break;

		case 2:
		{
			std::ofstream ofs1(g_logPath.c_str(), std::ios::app);
			std::ofstream ofs2(g_errLogPath.c_str(), std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << timeStr << " : ";
				ofs1 << m_logData.str.c_str();
			}
			if (ofs2.is_open())
			{
				ofs2 << timeStr << " : ";
				ofs2 << m_logData.str.c_str();
			}
		}
		break;

		case 3:
		{
			std::ofstream ofs1(m_fileName, std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << m_logData.str.c_str();
			}
		}
		break;

		default: assert(!"LogTask Error"); break;
		}
		return eRunResult::END;
	}
};
//-----------------------------------------------------------------------

//------------------------------------------------------------------------
// Set Log File Path
// ex) "./server/"  --> "./server/log.txt"
// ex) "./client/" --> "./client/log.txt"
//------------------------------------------------------------------------
void dbg::SetLogPath(const char *path)
{
	g_logPath = StrPath(path) + g_logPath;
}

//------------------------------------------------------------------------
// Set ErrLog File Path
// ex) "./server/"  --> "./server/errlog.txt"
// ex) "./client/" --> "./client/errlog.txt"
//------------------------------------------------------------------------
void dbg::SetErrLogPath(const char *path)
{
	g_errLogPath = StrPath(path) + g_errLogPath;
}

//------------------------------------------------------------------------
// â Ʈ Ѵ.
//------------------------------------------------------------------------
void dbg::Print( const std::string &str)
{
	OutputDebugStringA(str.c_str());
	OutputDebugStringA("\n");
}

//------------------------------------------------------------------------
// â Ʈ Ѵ. ( )
//------------------------------------------------------------------------
void dbg::Print( const char* fmt, ...)
{
	char textString[ 256] = {'\0'};
	va_list args;
	va_start ( args, fmt );
	vsnprintf_s( textString, sizeof(textString), _TRUNCATE, fmt, args );
	va_end ( args );
	OutputDebugStringA(textString);
	//OutputDebugStringA("\n");
}

void dbg::Log(const char* fmt, ...)
{
	char textString[256];
	ZeroMemory(textString, sizeof(textString));

	va_list args;
	va_start(args, fmt);
	vsnprintf_s(textString, sizeof(textString)-1, _TRUNCATE, fmt, args);
	va_end(args);

	std::ofstream ofs(g_logPath.c_str(), std::ios::app);
	if (ofs.is_open())
		ofs << textString;
}

// log parallel thread
void dbg::Logp(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 0, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data));
}

// log specific file, parallel thread
void dbg::Logp2(const char *fileName, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 3, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data, fileName));
}

// fileName  Ͽ α׸ .
void dbg::Log2(const char *fileName, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 0, fmt);

	FILE *fp = fopen(fileName, "a+");
	if (fp)
	{
		fputs(data.str.c_str(), fp);
		fclose(fp);
	}
}

void dbg::ErrLog(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 1, fmt);

	FILE *fp = fopen(g_errLogPath.c_str(), "a+");
	if (fp)
	{
		fputs(data.str.c_str(), fp);
		fclose(fp);
	}

	// αϿ  ޼ Ѵ.
	Log( "Error : %s", data.str.c_str());
}

// errlog parallel
void dbg::ErrLogp(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 1, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data));

	// αϿ  ޼ Ѵ.
	Logp("Error : %s", data.str.m_str);
}

void dbg::RemoveErrLog()
{
	FILE *fp = fopen(g_errLogPath.c_str(), "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::RemoveLog2(const char *fileName)
{
	FILE *fp = fopen(fileName, "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::RemoveLog()
{
	FILE *fp = fopen(g_logPath.c_str(), "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::TerminateLogThread()
{
	g_logThread.Clear();
}

// log classfy
// none/log/errlog, multithread
//
// level 0 : none
//		 1 : log
//		 2 : log + err log
//		 3 : log + err log + assertion
void dbg::Logc(const int level, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, -1, fmt);

	switch (level)
	{
	case 3:
		//DebugBreak();
		assert(!"dbg::Logc()");
	case 2:
		data.type = 2;
	case 1:
		if (level == 1)
			data.type = 0;
	case 0:
		// cout  ȭ Freeze   ֱ  ܵ
		break;
	default:
		assert(!"dbg::Logc()");
		break;
	}

	//------------------------------------------------------------------------
	// add string to log thread
	if (data.type >= 0)
		g_logThread.PushTask(new cLogTask(data));
}

// log classfy
// print/log/errlog, multithread
//
// level 0 : printf
//		 1 : printf + log
//		 2 : printf + log + err log
//		 3 : printf + log + err log + assertion
void dbg::Logc2(const int level, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, -1, fmt);

	switch (level)
	{
	case 3:
		//DebugBreak();
		assert(!"dbg::Logc2()");
	case 2:
		data.type = 2;
	case 1:
		if (level == 1)
			data.type = 0;
	case 0:
		std::cout << data.str.m_str;
		break;
	default:
		assert(!"dbg::Logc2()");
		break;
	}

	//------------------------------------------------------------------------
	// add string to log thread
	if (data.type >= 0)
		g_logThread.PushTask(new cLogTask(data));
}
<commit_msg>update dbg log buffer size<commit_after>
#include "stdafx.h"
#include "dbg.h"
#include <chrono>

namespace common {
	namespace dbg {

		// Log Thread
		common::cWQSemaphore g_logThread;
		struct sLogData
		{
			int type; // 0:log, 1:error log, 2:log + error log, 3:others file
			Str512 str;
		};

		StrPath g_logPath = "log.txt";
		StrPath g_errLogPath = "errlog.txt";

// make sLogData from argument list
#define MAKE_LOGDATA(logData, logType, fmt) \
		{\
			logData.type = logType;\
			va_list args;\
			va_start(args, fmt);\
			vsnprintf_s(logData.str.m_str, sizeof(logData.str.m_str) - 1, _TRUNCATE, fmt, args);\
			va_end(args);\
		}

	}
}

using namespace common;
using namespace dbg;

//------------------------------------------------------------------------
// LogThread Task
class cLogTask : public cTask
				, public common::cMemoryPool4<cLogTask>
{
public:
	const char *m_fileName;
	sLogData m_logData;
	cLogTask() : cTask(0, "cLogTask") {}
	cLogTask(const sLogData &logData, const char *fileName = NULL)
		: cTask(0, "cLogTask"), m_logData(logData), m_fileName(fileName) {
	}
	virtual ~cLogTask() {
	}

	virtual eRunResult::Enum Run(const double deltaSeconds) override
	{
		const string timeStr = common::GetCurrentDateTime();

		switch (m_logData.type)
		{
		case 0:
		{
			std::ofstream ofs1(g_logPath.c_str(), std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << timeStr << " : ";
				ofs1 << m_logData.str.c_str();
			}
		}
		break;

		case 1:
		{
			std::ofstream ofs2(g_errLogPath.c_str(), std::ios::app);
			if (ofs2.is_open())
			{
				ofs2 << timeStr << " : ";
				ofs2 << m_logData.str.c_str();
			}
		}
		break;

		case 2:
		{
			std::ofstream ofs1(g_logPath.c_str(), std::ios::app);
			std::ofstream ofs2(g_errLogPath.c_str(), std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << timeStr << " : ";
				ofs1 << m_logData.str.c_str();
			}
			if (ofs2.is_open())
			{
				ofs2 << timeStr << " : ";
				ofs2 << m_logData.str.c_str();
			}
		}
		break;

		case 3:
		{
			std::ofstream ofs1(m_fileName, std::ios::app);
			if (ofs1.is_open())
			{
				ofs1 << m_logData.str.c_str();
			}
		}
		break;

		default: assert(!"LogTask Error"); break;
		}
		return eRunResult::END;
	}
};
//-----------------------------------------------------------------------

//------------------------------------------------------------------------
// Set Log File Path
// ex) "./server/"  --> "./server/log.txt"
// ex) "./client/" --> "./client/log.txt"
//------------------------------------------------------------------------
void dbg::SetLogPath(const char *path)
{
	g_logPath = StrPath(path) + g_logPath;
}

//------------------------------------------------------------------------
// Set ErrLog File Path
// ex) "./server/"  --> "./server/errlog.txt"
// ex) "./client/" --> "./client/errlog.txt"
//------------------------------------------------------------------------
void dbg::SetErrLogPath(const char *path)
{
	g_errLogPath = StrPath(path) + g_errLogPath;
}

//------------------------------------------------------------------------
// â Ʈ Ѵ.
//------------------------------------------------------------------------
void dbg::Print( const std::string &str)
{
	OutputDebugStringA(str.c_str());
	OutputDebugStringA("\n");
}

//------------------------------------------------------------------------
// â Ʈ Ѵ. ( )
//------------------------------------------------------------------------
void dbg::Print( const char* fmt, ...)
{
	char textString[ 256] = {'\0'};
	va_list args;
	va_start ( args, fmt );
	vsnprintf_s( textString, sizeof(textString), _TRUNCATE, fmt, args );
	va_end ( args );
	OutputDebugStringA(textString);
	//OutputDebugStringA("\n");
}

void dbg::Log(const char* fmt, ...)
{
	char textString[256];
	ZeroMemory(textString, sizeof(textString));

	va_list args;
	va_start(args, fmt);
	vsnprintf_s(textString, sizeof(textString)-1, _TRUNCATE, fmt, args);
	va_end(args);

	std::ofstream ofs(g_logPath.c_str(), std::ios::app);
	if (ofs.is_open())
		ofs << textString;
}

// log parallel thread
void dbg::Logp(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 0, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data));
}

// log specific file, parallel thread
void dbg::Logp2(const char *fileName, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 3, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data, fileName));
}

// fileName  Ͽ α׸ .
void dbg::Log2(const char *fileName, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 0, fmt);

	FILE *fp = fopen(fileName, "a+");
	if (fp)
	{
		fputs(data.str.c_str(), fp);
		fclose(fp);
	}
}

void dbg::ErrLog(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 1, fmt);

	FILE *fp = fopen(g_errLogPath.c_str(), "a+");
	if (fp)
	{
		fputs(data.str.c_str(), fp);
		fclose(fp);
	}

	// αϿ  ޼ Ѵ.
	Log( "Error : %s", data.str.c_str());
}

// errlog parallel
void dbg::ErrLogp(const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, 1, fmt);

	// add string to log thread
	g_logThread.PushTask(new cLogTask(data));

	// αϿ  ޼ Ѵ.
	Logp("Error : %s", data.str.m_str);
}

void dbg::RemoveErrLog()
{
	FILE *fp = fopen(g_errLogPath.c_str(), "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::RemoveLog2(const char *fileName)
{
	FILE *fp = fopen(fileName, "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::RemoveLog()
{
	FILE *fp = fopen(g_logPath.c_str(), "w");
	if (fp)
	{
		fputs("", fp);
		fclose(fp);
	}
}

void dbg::TerminateLogThread()
{
	g_logThread.Clear();
}

// log classfy
// none/log/errlog, multithread
//
// level 0 : none
//		 1 : log
//		 2 : log + err log
//		 3 : log + err log + assertion
void dbg::Logc(const int level, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, -1, fmt);

	switch (level)
	{
	case 3:
		//DebugBreak();
		assert(!"dbg::Logc()");
	case 2:
		data.type = 2;
	case 1:
		if (level == 1)
			data.type = 0;
	case 0:
		// cout  ȭ Freeze   ֱ  ܵ
		break;
	default:
		assert(!"dbg::Logc()");
		break;
	}

	//------------------------------------------------------------------------
	// add string to log thread
	if (data.type >= 0)
		g_logThread.PushTask(new cLogTask(data));
}

// log classfy
// print/log/errlog, multithread
//
// level 0 : printf
//		 1 : printf + log
//		 2 : printf + log + err log
//		 3 : printf + log + err log + assertion
void dbg::Logc2(const int level, const char* fmt, ...)
{
	sLogData data;
	MAKE_LOGDATA(data, -1, fmt);

	switch (level)
	{
	case 3:
		//DebugBreak();
		assert(!"dbg::Logc2()");
	case 2:
		data.type = 2;
	case 1:
		if (level == 1)
			data.type = 0;
	case 0:
		std::cout << data.str.m_str;
		break;
	default:
		assert(!"dbg::Logc2()");
		break;
	}

	//------------------------------------------------------------------------
	// add string to log thread
	if (data.type >= 0)
		g_logThread.PushTask(new cLogTask(data));
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include "Vec2i.h"
#include "IMapElement.h"
#include "CDoorway.h"
#include "CActor.h"
#include "CMap.h"
#include "CBullKnight.h"
#include "CFalconKnight.h"
#include "CTurtleKnight.h"
#include "CCuco.h"

#include <iostream>

namespace Knights {
    void CMap::endOfTurn() {
        for (int y = 0; y < 20; ++y) {
            for (int x = 0; x < 20; ++x) {
                if (mActors[y][x] != nullptr) {
                    mActors[y][x]->endOfTurn();
                }
            }
        }

        actors.erase( std::remove_if( actors.begin(), actors.end(),
                                           [](std::shared_ptr<CActor> actor){ return !actor->isAlive();}
        ), actors.end() );
    }

    CMap::CMap(const std::string &mapData) {

        char element;
        std::shared_ptr<CActor> actor = nullptr;
        int id = 0;
        for (int y = 0; y < 20; ++y) {
            for (int x = 0; x < 20; ++x) {

                element = mapData[(y * 20) + x];
                block[y][x] = false;
                map[y][x] = nullptr;
                mElement[ y ][ x ] = element;

                switch (element) {
                    case '0':
                    case '=':
                    case '_':
                    case '-':
                        block[y][x] = false;
                        break;
                    case '1':
                    case '#':
                    case '/':
                    case '\\':
                    case '|':
                        block[y][x] = true;
                        break;
                    case '~':
                        block[y][x] = false;
                        break;

                    case '4':
                        actor = mAvatar = std::make_shared<CBullKnight>(id++);
                        mElement[ y ][ x ] = '.';
                        break;
                    case '9':
                    case '*':
                        map[y][x] = std::make_shared<CDoorway>(element == '9' ? EDoorwayFunction::kExit : EDoorwayFunction::kEntry);
                        break;
                    case '5':
                    case '6':
                        actor = std::make_shared<CCuco>(id++);
                        mElement[ y ][ x ] = '.';
                        break;
                }

                if (actor != nullptr) {
                    actors.push_back(actor);
                    mActors[y][x] = actor;
                    actor->setPosition( { x, y } );
                    actor = nullptr;
                }
            }
        }
    }

    std::shared_ptr<CActor> CMap::attack(std::shared_ptr<CActor> actor, Vec2i position, bool mutual) {

        std::shared_ptr<CActor> otherActor = getActorAt( position );

        if ( otherActor == nullptr ) {
            return nullptr;
        }

        if (actor->getTeam() != otherActor->getTeam()) {
            actor->performAttack(otherActor);

            if (mutual) {
                otherActor->performAttack(actor);
            }

            if (!actor->isAlive() ) {
                auto position = actor->getPosition();
                mActors[position.y][position.x] = nullptr;
            }

            if (!otherActor->isAlive()) {
                auto position = otherActor->getPosition();
                mActors[position.y][position.x] = nullptr;
            }
        }

        return otherActor;
    }

    bool CMap::attackIfNotFriendly(EDirection d, std::shared_ptr<CActor> actor, bool mutual) {

        std::shared_ptr<CActor> other = nullptr;

        auto position = actor->getPosition();

        switch (d) {

            case EDirection::kEast:
                other = attack(actor, Vec2i{position.x + 1, position.y}, mutual);
                break;

            case EDirection::kWest:
                other = attack(actor, Vec2i{position.x - 1, position.y}, mutual);
                break;

            case EDirection::kSouth:
                other = attack(actor, Vec2i{position.x, position.y + 1}, mutual);
                break;

            case EDirection::kNorth:
                other = attack(actor, Vec2i{position.x, position.y - 1}, mutual);
                break;
        }

        return (other != nullptr);
    }

    void CMap::move(EDirection d, std::shared_ptr<CActor> actor) {

        if (actor->canAttack() && attackIfNotFriendly(d, actor, true)) {
            return;
        }

        if (!actor->canMove()) {
            return;
        }

        bool moved = false;

        auto position = actor->getPosition();

        switch (d) {

            case EDirection::kEast:

                if (!isBlockAt(position.x + 1, position.y ) ) {
                    moved = true;
                    moveActor( position, { position.x + 1, position.y }, actor );
                }
                break;

            case EDirection::kWest:
                if (!isBlockAt(position.x - 1, position.y ) ) {
                    moved = true;
                    moveActor( position, { position.x - 1, position.y }, actor );
                }
                break;

            case EDirection::kSouth:
                if (!isBlockAt(position.x, position.y + 1 ) ) {
                    moved = true;
                    moveActor( position, { position.x, position.y + 1 }, actor );
                }
                break;

            case EDirection::kNorth:
                if (!isBlockAt(position.x, position.y - 1) ) {
                    moved = true;
                    moveActor( position, { position.x, position.y - 1}, actor );
                }
                break;

        }

        if (moved) {
            actor->onMove();
        }
    }

    bool CMap::isValid(int x, int y) {
        if ( x < 0 || x > 20 || y < 0 || y > 20 ) {
            return false;
        }
        return true;
    }

    bool CMap::isBlockAt(int x, int y) {

        if ( !isValid( x, y ) ) {
            return true;
        }

        if ( mActors[ y ][ x ] != nullptr ) {
            return true;
        }

        return block[ y ][ x ];
    }

    std::shared_ptr<CActor> CMap::getActorAt( Vec2i position ) {
        return mActors[ position.y ][ position.x ];
    }

    char CMap::getElementAt( int x, int y ) {
        return mElement[ y ][ x ];
    }

    std::vector<std::shared_ptr<CActor>> CMap::getActors() {
        return actors;
    }

    std::shared_ptr<CActor> CMap::getAvatar() {
        return mAvatar;
    }

    void CMap::setActorAt(Vec2i position, std::shared_ptr<CActor> actor) {
        mActors[position.y][position.x] = actor;
    }

    void CMap::moveActor(Vec2i from, Vec2i to, std::shared_ptr<CActor> actor) {
        mActors[from.y][from.x] = nullptr;
        mActors[to.y][to.x] = actor;
        actor->setPosition( to );
    }
}<commit_msg>Add new tile types to maps<commit_after>#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include "Vec2i.h"
#include "IMapElement.h"
#include "CDoorway.h"
#include "CActor.h"
#include "CMap.h"
#include "CBullKnight.h"
#include "CFalconKnight.h"
#include "CTurtleKnight.h"
#include "CCuco.h"

#include <iostream>

namespace Knights {
    void CMap::endOfTurn() {
        for (int y = 0; y < 20; ++y) {
            for (int x = 0; x < 20; ++x) {
                if (mActors[y][x] != nullptr) {
                    mActors[y][x]->endOfTurn();
                }
            }
        }

        actors.erase( std::remove_if( actors.begin(), actors.end(),
                                           [](std::shared_ptr<CActor> actor){ return !actor->isAlive();}
        ), actors.end() );
    }

    CMap::CMap(const std::string &mapData) {

        char element;
        std::shared_ptr<CActor> actor = nullptr;
        int id = 0;
        for (int y = 0; y < 20; ++y) {
            for (int x = 0; x < 20; ++x) {

                element = mapData[(y * 20) + x];
                block[y][x] = false;
                map[y][x] = nullptr;
                mElement[ y ][ x ] = element;

                switch (element) {
                    case '0':
                    case '=':
                    case '_':
                    case '-':
                    case '(':
                    case ')':
                    case '2':
                    case '7':
                        block[y][x] = false;
                        break;
                    case '1':
                    case '#':
                    case '/':
                    case '\\':
                    case '%':
                    case '|':
                    case 'Y':
                    case 'Z':
                    case 'S':
                    case '>':
                    case '<':
                        block[y][x] = true;
                        break;
                    case '~':
                        block[y][x] = false;
                        break;

                    case '4':
                        actor = mAvatar = std::make_shared<CBullKnight>(id++);
                        mElement[ y ][ x ] = '.';
                        break;
                    case '9':
                    case '*':
                        map[y][x] = std::make_shared<CDoorway>(element == '9' ? EDoorwayFunction::kExit : EDoorwayFunction::kEntry);
                        break;
                    case '5':
                    case '6':
                        actor = std::make_shared<CCuco>(id++);
                        mElement[ y ][ x ] = '.';
                        break;
                }

                if (actor != nullptr) {
                    actors.push_back(actor);
                    mActors[y][x] = actor;
                    actor->setPosition( { x, y } );
                    actor = nullptr;
                }
            }
        }
    }

    std::shared_ptr<CActor> CMap::attack(std::shared_ptr<CActor> actor, Vec2i position, bool mutual) {

        std::shared_ptr<CActor> otherActor = getActorAt( position );

        if ( otherActor == nullptr ) {
            return nullptr;
        }

        if (actor->getTeam() != otherActor->getTeam()) {
            actor->performAttack(otherActor);

            if (mutual) {
                otherActor->performAttack(actor);
            }

            if (!actor->isAlive() ) {
                auto position = actor->getPosition();
                mActors[position.y][position.x] = nullptr;
            }

            if (!otherActor->isAlive()) {
                auto position = otherActor->getPosition();
                mActors[position.y][position.x] = nullptr;
            }
        }

        return otherActor;
    }

    bool CMap::attackIfNotFriendly(EDirection d, std::shared_ptr<CActor> actor, bool mutual) {

        std::shared_ptr<CActor> other = nullptr;

        auto position = actor->getPosition();

        switch (d) {

            case EDirection::kEast:
                other = attack(actor, Vec2i{position.x + 1, position.y}, mutual);
                break;

            case EDirection::kWest:
                other = attack(actor, Vec2i{position.x - 1, position.y}, mutual);
                break;

            case EDirection::kSouth:
                other = attack(actor, Vec2i{position.x, position.y + 1}, mutual);
                break;

            case EDirection::kNorth:
                other = attack(actor, Vec2i{position.x, position.y - 1}, mutual);
                break;
        }

        return (other != nullptr);
    }

    void CMap::move(EDirection d, std::shared_ptr<CActor> actor) {

        if (actor->canAttack() && attackIfNotFriendly(d, actor, true)) {
            return;
        }

        if (!actor->canMove()) {
            return;
        }

        bool moved = false;

        auto position = actor->getPosition();

        switch (d) {

            case EDirection::kEast:

                if (!isBlockAt(position.x + 1, position.y ) ) {
                    moved = true;
                    moveActor( position, { position.x + 1, position.y }, actor );
                }
                break;

            case EDirection::kWest:
                if (!isBlockAt(position.x - 1, position.y ) ) {
                    moved = true;
                    moveActor( position, { position.x - 1, position.y }, actor );
                }
                break;

            case EDirection::kSouth:
                if (!isBlockAt(position.x, position.y + 1 ) ) {
                    moved = true;
                    moveActor( position, { position.x, position.y + 1 }, actor );
                }
                break;

            case EDirection::kNorth:
                if (!isBlockAt(position.x, position.y - 1) ) {
                    moved = true;
                    moveActor( position, { position.x, position.y - 1}, actor );
                }
                break;

        }

        if (moved) {
            actor->onMove();
        }
    }

    bool CMap::isValid(int x, int y) {
        if ( x < 0 || x > 20 || y < 0 || y > 20 ) {
            return false;
        }
        return true;
    }

    bool CMap::isBlockAt(int x, int y) {

        if ( !isValid( x, y ) ) {
            return true;
        }

        if ( mActors[ y ][ x ] != nullptr ) {
            return true;
        }

        return block[ y ][ x ];
    }

    std::shared_ptr<CActor> CMap::getActorAt( Vec2i position ) {
        return mActors[ position.y ][ position.x ];
    }

    char CMap::getElementAt( int x, int y ) {
        return mElement[ y ][ x ];
    }

    std::vector<std::shared_ptr<CActor>> CMap::getActors() {
        return actors;
    }

    std::shared_ptr<CActor> CMap::getAvatar() {
        return mAvatar;
    }

    void CMap::setActorAt(Vec2i position, std::shared_ptr<CActor> actor) {
        mActors[position.y][position.x] = actor;
    }

    void CMap::moveActor(Vec2i from, Vec2i to, std::shared_ptr<CActor> actor) {
        mActors[from.y][from.x] = nullptr;
        mActors[to.y][to.x] = actor;
        actor->setPosition( to );
    }
}<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
/*!
 * \file tstMesh.cpp
 * \author Stuart R. Slattery
 * \brief Mesh unit tests.
 */
//---------------------------------------------------------------------------//

#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <cassert>

#include <DTK_Mesh.hpp>
#include <DTK_DataSource.hpp>
#include <DTK_CoreTypes.hpp>
#include <DTK_NodeTraits.hpp>
#include <DTK_ElementTraits.hpp>
#include <DTK_FieldTraits.hpp>

#include <mpi.h>

#include <Teuchos_UnitTestHarness.hpp>
#include <Teuchos_DefaultComm.hpp>
#include <Teuchos_DefaultMpiComm.hpp>
#include <Teuchos_RCP.hpp>
#include <Teuchos_OpaqueWrapper.hpp>
#include <Teuchos_TypeTraits.hpp>

//---------------------------------------------------------------------------//
// MPI Setup
//---------------------------------------------------------------------------//

template<class Ordinal>
Teuchos::RCP<const Teuchos::Comm<Ordinal> > getDefaultComm()
{
#ifdef HAVE_MPI
    return Teuchos::DefaultComm<Ordinal>::getComm();
#else
    return Teuchos::rcp(new Teuchos::SerialComm<Ordinal>() );
#endif
}

//---------------------------------------------------------------------------//
// Node Implementation
//---------------------------------------------------------------------------//

class MyNode
{
  private:

    std::size_t d_handle;
    std::vector<double> d_coords;

  public:

    typedef int    handle_type;
    typedef double coordinate_type;

    MyNode( double x, double y, double z, int handle )
	: d_handle( handle )
    {
	d_coords.push_back(x);
	d_coords.push_back(y);
	d_coords.push_back(z);
    }

    ~MyNode()
    { /* ... */ }

    int handle() const
    { return d_handle; }

    std::vector<double>::const_iterator coordsBegin() const
    { return d_coords.begin(); }

    std::vector<double>::const_iterator coordsEnd() const
    { return d_coords.end(); }
};

//---------------------------------------------------------------------------//
// Element Implementation
//---------------------------------------------------------------------------//

class MyHex
{
  private:

    std::size_t d_handle;
    std::vector<int> d_connectivity;

  public:

    typedef std::size_t handle_type;

    MyHex( int node_0, int node_1, int node_2, int node_3,
	   int node_4, int node_5, int node_6, int node_7,
	   std::size_t handle )
	: d_handle( handle )
    {
	d_connectivity.push_back( node_0 );
	d_connectivity.push_back( node_1 );
	d_connectivity.push_back( node_2 );
	d_connectivity.push_back( node_3 );
	d_connectivity.push_back( node_4 );
	d_connectivity.push_back( node_5 );
	d_connectivity.push_back( node_6 );
	d_connectivity.push_back( node_7 );
    }

    ~MyHex()
    { /* ... */ }

    int handle() const
    { return d_handle; }

    std::vector<int>::const_iterator connectivityBegin() const
    { return d_connectivity.begin(); }

    std::vector<int>::const_iterator connectivityEnd() const
    { return d_connectivity.end(); }
};

//---------------------------------------------------------------------------//
// DTK Traits Specializations
//---------------------------------------------------------------------------//
namespace DataTransferKit
{

//---------------------------------------------------------------------------//
// NodeTraits specialization for the MyNode implementation.
template<>
struct NodeTraits<MyNode>
{
    typedef typename MyNode::handle_type                 handle_type;
    typedef typename MyNode::coordinate_type             coordinate_type;
    typedef typename std::vector<double>::const_iterator
    const_coordinate_iterator;

    static inline std::size_t dim()
    { return 3;}

    static inline handle_type handle( const MyNode& node )
    { return node.handle(); }

    static inline const_coordinate_iterator coordsBegin( const MyNode& node )
    { return node.coordsBegin(); }

    static inline const_coordinate_iterator coordsEnd( const MyNode& node )
    { return node.coordsEnd(); }
};

//---------------------------------------------------------------------------//
// ElementTraits specialization for the MyHex implementation.
template<>
struct ElementTraits<MyHex>
{
    typedef typename MyHex::handle_type              handle_type;
    typedef typename std::vector<int>::const_iterator
    const_connectivity_iterator;

    static inline std::size_t type()
    { return DTK_REGION; }

    static inline std::size_t topology()
    { return DTK_HEXAHEDRON; }

    static inline std::size_t numNodes()
    { return 8; }

    static inline handle_type handle( const MyHex &hex )
    { return hex.handle(); }

    static inline const_connectivity_iterator
    connectivityBegin( const MyHex &hex )
    { return hex.connectivityBegin(); }

    static inline const_connectivity_iterator
    connectivityEnd( const MyHex &hex )
    { return hex.connectivityEnd(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the node field.
template<>
struct FieldTraits< std::vector<MyNode> >
{
    typedef MyNode                                value_type;
    typedef std::vector<MyNode>::iterator         iterator;
    typedef std::vector<MyNode>::const_iterator   const_iterator;

    static inline std::size_t size( const std::vector<MyNode> &node_field )
    { return node_field.size(); }

    static iterator begin( std::vector<MyNode> &node_field )
    { return node_field.begin(); }

    static const_iterator begin( const std::vector<MyNode> &node_field )
    { return node_field.begin(); }

    static inline iterator end( std::vector<MyNode> &node_field )
    { return node_field.end(); }

    static inline const_iterator end( const std::vector<MyNode> &node_field )
    { return node_field.end(); }

    static inline bool empty( const std::vector<MyNode> &node_field )
    { return node_field.empty(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the element field.
template<>
struct FieldTraits< std::vector<MyHex> >
{
    typedef MyHex                                value_type;
    typedef std::vector<MyHex>::iterator         iterator;
    typedef std::vector<MyHex>::const_iterator   const_iterator;

    static inline std::size_t size( const std::vector<MyHex> &quad_field )
    { return quad_field.size(); }

    static inline iterator begin( std::vector<MyHex> &quad_field )
    { return quad_field.begin(); }

    static inline const_iterator begin( const std::vector<MyHex> &quad_field )
    { return quad_field.begin(); }

    static inline iterator end( std::vector<MyHex> &quad_field )
    { return quad_field.end(); }

    static inline const_iterator end( const std::vector<MyHex> &quad_field )
    { return quad_field.end(); }

    static inline bool empty(  const std::vector<MyHex> &quad_field )
    { return quad_field.empty(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the data field.
template<>
struct FieldTraits< std::vector<double> >
{
    typedef MyNode value_type;
    typedef std::vector<double>::iterator iterator;
    typedef std::vector<double>::const_iterator const_iterator;

    static inline std::size_t size( const std::vector<double> &data_field )
    { return data_field.size(); }

    static inline iterator begin( std::vector<double> &data_field )
    { return data_field.begin(); }

    static inline const_iterator begin( const std::vector<double> &data_field )
    { return data_field.begin(); }

    static inline iterator end( std::vector<double> &data_field )
    { return data_field.end(); }

    static inline const_iterator end( const std::vector<double> &data_field )
    { return data_field.end(); }

    static inline bool empty( const std::vector<double> &data_field )
    { return data_field.empty(); }
};

} // end namespace DataTransferKit

//---------------------------------------------------------------------------//
// DataSource Implementation
//---------------------------------------------------------------------------//
class MyDataSource : public DataTransferKit::DataSource< std::vector<MyNode>,
							 std::vector<MyHex>,
							 std::vector<double> >
{
  private:

    std::vector<MyNode> d_nodes;
    std::vector<MyHex> d_elements;
    std::vector<double> d_element_data;
    MPI_Comm d_comm;

    void createMesh()
    {
	// Make some nodes.
	d_nodes.push_back( MyNode(0.0, 0.0, 0.0, 0) );
	d_nodes.push_back( MyNode(1.0, 0.0, 0.0, 1) );
	d_nodes.push_back( MyNode(1.0, 1.0, 0.0, 2) );
	d_nodes.push_back( MyNode(0.0, 1.0, 0.0, 3) );
	d_nodes.push_back( MyNode(0.0, 0.0, 1.0, 4) );
	d_nodes.push_back( MyNode(1.0, 0.0, 1.0, 5) );
	d_nodes.push_back( MyNode(1.0, 1.0, 1.0, 6) );
	d_nodes.push_back( MyNode(0.0, 1.0, 1.0, 7) );

	// Make a quadrilateral.
	d_elements.push_back( MyHex( 0, 1, 2, 3, 4, 5, 6, 7, 12 ) );

	// Add some data for the elements.
	d_element_data.push_back( 1.5 );
	d_element_data.push_back( 3.5 );
	d_element_data.push_back( 5.5 );
	d_element_data.push_back( 7.5 );
    }

  public:

    MyDataSource()
    {
	// Build the mesh.
	createMesh();

	// Get the raw MPI_Comm out of Teuchos.
	Teuchos::RCP< const Teuchos::Comm<int> > comm = getDefaultComm<int>();
	Teuchos::RCP< const Teuchos::MpiComm<int> > mpi_comm =
	    Teuchos::rcp_dynamic_cast< const Teuchos::MpiComm<int> >( comm );
	Teuchos::RCP< const Teuchos::OpaqueWrapper<MPI_Comm> > opaque_comm =
	    mpi_comm->getRawMpiComm();
	d_comm = (*opaque_comm)();
   }

    ~MyDataSource()
    { /* ... */ }

    const MPI_Comm& getSourceComm()
    {
	return d_comm;
    }

    bool isFieldSupported( const std::string &field_name )
    {
	bool return_val = false;
	if ( field_name == "MY_DATA_FIELD" )
	{
	    return_val = true;
	}
	return return_val;
    }

    const std::vector<MyNode>& getSourceMeshNodes()
    {
	return d_nodes;
    }

    const std::vector<MyHex>& getSourceMeshElements()
    {
	return d_elements;
    }

    const std::vector<double> evaluateFieldOnTargetNodes(
	const std::string &field_name,
	const std::vector<MyHex::handle_type> &element_handles,
	const std::vector<MyNode::coordinate_type> &node_coordinates )
    {
	if ( field_name == "MY_DATA_FIELD" )
	{
	    return d_element_data;
	}
	else
	{
	    std::vector<double> empty_vec;
	    return empty_vec;
	}
    }
};

//---------------------------------------------------------------------------//
// Tests
//---------------------------------------------------------------------------//

// DataSource test.
TEUCHOS_UNIT_TEST( Mesh, mesh_test )
{
    using namespace DataTransferKit;

    // Create a DataSource
    Teuchos::RCP< DataSource< std::vector<MyNode>,
			      std::vector<MyHex>,
			      std::vector<double> > > data_source
	= Teuchos::rcp( new MyDataSource() );

    // Create a mesh.
    Teuchos::RCP<Mesh> mesh = createMeshFromDataSource( data_source );

    // Write the mesh to a file.
    mesh->getMoab()->write_mesh( "mesh_test.vtk" );
}

//---------------------------------------------------------------------------//
// end tstMesh.cpp
//---------------------------------------------------------------------------//

<commit_msg>Added a little more complexity to the mesh test.<commit_after>//---------------------------------------------------------------------------//
/*!
 * \file tstMesh.cpp
 * \author Stuart R. Slattery
 * \brief Mesh unit tests.
 */
//---------------------------------------------------------------------------//

#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <cassert>

#include <DTK_Mesh.hpp>
#include <DTK_DataSource.hpp>
#include <DTK_CoreTypes.hpp>
#include <DTK_NodeTraits.hpp>
#include <DTK_ElementTraits.hpp>
#include <DTK_FieldTraits.hpp>

#include <mpi.h>

#include <Teuchos_UnitTestHarness.hpp>
#include <Teuchos_DefaultComm.hpp>
#include <Teuchos_DefaultMpiComm.hpp>
#include <Teuchos_RCP.hpp>
#include <Teuchos_OpaqueWrapper.hpp>
#include <Teuchos_TypeTraits.hpp>

//---------------------------------------------------------------------------//
// MPI Setup
//---------------------------------------------------------------------------//

template<class Ordinal>
Teuchos::RCP<const Teuchos::Comm<Ordinal> > getDefaultComm()
{
#ifdef HAVE_MPI
    return Teuchos::DefaultComm<Ordinal>::getComm();
#else
    return Teuchos::rcp(new Teuchos::SerialComm<Ordinal>() );
#endif
}

//---------------------------------------------------------------------------//
// Node Implementation
//---------------------------------------------------------------------------//

class MyNode
{
  private:

    std::size_t d_handle;
    std::vector<double> d_coords;

  public:

    typedef int    handle_type;
    typedef double coordinate_type;

    MyNode( double x, double y, double z, int handle )
	: d_handle( handle )
    {
	d_coords.push_back(x);
	d_coords.push_back(y);
	d_coords.push_back(z);
    }

    ~MyNode()
    { /* ... */ }

    int handle() const
    { return d_handle; }

    std::vector<double>::const_iterator coordsBegin() const
    { return d_coords.begin(); }

    std::vector<double>::const_iterator coordsEnd() const
    { return d_coords.end(); }
};

//---------------------------------------------------------------------------//
// Element Implementation
//---------------------------------------------------------------------------//

class MyHex
{
  private:

    std::size_t d_handle;
    std::vector<int> d_connectivity;

  public:

    typedef std::size_t handle_type;

    MyHex( int node_0, int node_1, int node_2, int node_3,
	   int node_4, int node_5, int node_6, int node_7,
	   std::size_t handle )
	: d_handle( handle )
    {
	d_connectivity.push_back( node_0 );
	d_connectivity.push_back( node_1 );
	d_connectivity.push_back( node_2 );
	d_connectivity.push_back( node_3 );
	d_connectivity.push_back( node_4 );
	d_connectivity.push_back( node_5 );
	d_connectivity.push_back( node_6 );
	d_connectivity.push_back( node_7 );
    }

    ~MyHex()
    { /* ... */ }

    int handle() const
    { return d_handle; }

    std::vector<int>::const_iterator connectivityBegin() const
    { return d_connectivity.begin(); }

    std::vector<int>::const_iterator connectivityEnd() const
    { return d_connectivity.end(); }
};

//---------------------------------------------------------------------------//
// DTK Traits Specializations
//---------------------------------------------------------------------------//
namespace DataTransferKit
{

//---------------------------------------------------------------------------//
// NodeTraits specialization for the MyNode implementation.
template<>
struct NodeTraits<MyNode>
{
    typedef typename MyNode::handle_type                 handle_type;
    typedef typename MyNode::coordinate_type             coordinate_type;
    typedef typename std::vector<double>::const_iterator
    const_coordinate_iterator;

    static inline std::size_t dim()
    { return 3;}

    static inline handle_type handle( const MyNode& node )
    { return node.handle(); }

    static inline const_coordinate_iterator coordsBegin( const MyNode& node )
    { return node.coordsBegin(); }

    static inline const_coordinate_iterator coordsEnd( const MyNode& node )
    { return node.coordsEnd(); }
};

//---------------------------------------------------------------------------//
// ElementTraits specialization for the MyHex implementation.
template<>
struct ElementTraits<MyHex>
{
    typedef typename MyHex::handle_type              handle_type;
    typedef typename std::vector<int>::const_iterator
    const_connectivity_iterator;

    static inline std::size_t type()
    { return DTK_REGION; }

    static inline std::size_t topology()
    { return DTK_HEXAHEDRON; }

    static inline std::size_t numNodes()
    { return 8; }

    static inline handle_type handle( const MyHex &hex )
    { return hex.handle(); }

    static inline const_connectivity_iterator
    connectivityBegin( const MyHex &hex )
    { return hex.connectivityBegin(); }

    static inline const_connectivity_iterator
    connectivityEnd( const MyHex &hex )
    { return hex.connectivityEnd(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the node field.
template<>
struct FieldTraits< std::vector<MyNode> >
{
    typedef MyNode                                value_type;
    typedef std::vector<MyNode>::iterator         iterator;
    typedef std::vector<MyNode>::const_iterator   const_iterator;

    static inline std::size_t size( const std::vector<MyNode> &node_field )
    { return node_field.size(); }

    static iterator begin( std::vector<MyNode> &node_field )
    { return node_field.begin(); }

    static const_iterator begin( const std::vector<MyNode> &node_field )
    { return node_field.begin(); }

    static inline iterator end( std::vector<MyNode> &node_field )
    { return node_field.end(); }

    static inline const_iterator end( const std::vector<MyNode> &node_field )
    { return node_field.end(); }

    static inline bool empty( const std::vector<MyNode> &node_field )
    { return node_field.empty(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the element field.
template<>
struct FieldTraits< std::vector<MyHex> >
{
    typedef MyHex                                value_type;
    typedef std::vector<MyHex>::iterator         iterator;
    typedef std::vector<MyHex>::const_iterator   const_iterator;

    static inline std::size_t size( const std::vector<MyHex> &quad_field )
    { return quad_field.size(); }

    static inline iterator begin( std::vector<MyHex> &quad_field )
    { return quad_field.begin(); }

    static inline const_iterator begin( const std::vector<MyHex> &quad_field )
    { return quad_field.begin(); }

    static inline iterator end( std::vector<MyHex> &quad_field )
    { return quad_field.end(); }

    static inline const_iterator end( const std::vector<MyHex> &quad_field )
    { return quad_field.end(); }

    static inline bool empty(  const std::vector<MyHex> &quad_field )
    { return quad_field.empty(); }
};

//---------------------------------------------------------------------------//
// FieldTraits specialization for the data field.
template<>
struct FieldTraits< std::vector<double> >
{
    typedef MyNode value_type;
    typedef std::vector<double>::iterator iterator;
    typedef std::vector<double>::const_iterator const_iterator;

    static inline std::size_t size( const std::vector<double> &data_field )
    { return data_field.size(); }

    static inline iterator begin( std::vector<double> &data_field )
    { return data_field.begin(); }

    static inline const_iterator begin( const std::vector<double> &data_field )
    { return data_field.begin(); }

    static inline iterator end( std::vector<double> &data_field )
    { return data_field.end(); }

    static inline const_iterator end( const std::vector<double> &data_field )
    { return data_field.end(); }

    static inline bool empty( const std::vector<double> &data_field )
    { return data_field.empty(); }
};

} // end namespace DataTransferKit

//---------------------------------------------------------------------------//
// DataSource Implementation
//---------------------------------------------------------------------------//
class MyDataSource : public DataTransferKit::DataSource< std::vector<MyNode>,
							 std::vector<MyHex>,
							 std::vector<double> >
{
  private:

    std::vector<MyNode> d_nodes;
    std::vector<MyHex> d_elements;
    std::vector<double> d_element_data;
    MPI_Comm d_comm;

    void createMesh()
    {
	// Make some nodes.
	d_nodes.push_back( MyNode(0.0, 0.0, 0.0, 0) );
	d_nodes.push_back( MyNode(1.0, 0.0, 0.0, 4) );
	d_nodes.push_back( MyNode(1.0, 1.0, 0.0, 9) );
	d_nodes.push_back( MyNode(0.0, 1.0, 0.0, 2) );
	d_nodes.push_back( MyNode(0.0, 0.0, 1.0, 3) );
	d_nodes.push_back( MyNode(1.0, 0.0, 1.0, 8) );
	d_nodes.push_back( MyNode(1.0, 1.0, 1.0, 1) );
	d_nodes.push_back( MyNode(0.0, 1.0, 1.0, 6) );
	d_nodes.push_back( MyNode(0.0, 0.0, 2.0, 12) );
	d_nodes.push_back( MyNode(1.0, 0.0, 2.0, 7) );
	d_nodes.push_back( MyNode(1.0, 1.0, 2.0, 13) );
	d_nodes.push_back( MyNode(0.0, 1.0, 2.0, 5) );

	// Make 2 hexahedrons.
	d_elements.push_back( MyHex( 0, 4, 9, 2, 3, 8, 1, 6, 0 ) );
	d_elements.push_back( MyHex( 3, 8, 1, 6, 12, 7, 13, 5, 1 ) );

	// Add some data for the hexes.
	d_element_data.push_back( 1.5 );
	d_element_data.push_back( 3.5 );
    }

  public:

    MyDataSource()
    {
	// Build the mesh.
	createMesh();

	// Get the raw MPI_Comm out of Teuchos.
	Teuchos::RCP< const Teuchos::Comm<int> > comm = getDefaultComm<int>();
	Teuchos::RCP< const Teuchos::MpiComm<int> > mpi_comm =
	    Teuchos::rcp_dynamic_cast< const Teuchos::MpiComm<int> >( comm );
	Teuchos::RCP< const Teuchos::OpaqueWrapper<MPI_Comm> > opaque_comm =
	    mpi_comm->getRawMpiComm();
	d_comm = (*opaque_comm)();
   }

    ~MyDataSource()
    { /* ... */ }

    const MPI_Comm& getSourceComm()
    {
	return d_comm;
    }

    bool isFieldSupported( const std::string &field_name )
    {
	bool return_val = false;
	if ( field_name == "MY_DATA_FIELD" )
	{
	    return_val = true;
	}
	return return_val;
    }

    const std::vector<MyNode>& getSourceMeshNodes()
    {
	return d_nodes;
    }

    const std::vector<MyHex>& getSourceMeshElements()
    {
	return d_elements;
    }

    const std::vector<double> evaluateFieldOnTargetNodes(
	const std::string &field_name,
	const std::vector<MyHex::handle_type> &element_handles,
	const std::vector<MyNode::coordinate_type> &node_coordinates )
    {
	if ( field_name == "MY_DATA_FIELD" )
	{
	    return d_element_data;
	}
	else
	{
	    std::vector<double> empty_vec;
	    return empty_vec;
	}
    }
};

//---------------------------------------------------------------------------//
// Tests
//---------------------------------------------------------------------------//

// DataSource test.
TEUCHOS_UNIT_TEST( Mesh, mesh_test )
{
    using namespace DataTransferKit;

    // Create a DataSource
    Teuchos::RCP< DataSource< std::vector<MyNode>,
			      std::vector<MyHex>,
			      std::vector<double> > > data_source
	= Teuchos::rcp( new MyDataSource() );

    // Create a mesh.
    Teuchos::RCP<Mesh> mesh = createMeshFromDataSource( data_source );

    // Write the mesh to a file.
    mesh->getMoab()->write_mesh( "mesh_test.vtk" );
}

//---------------------------------------------------------------------------//
// end tstMesh.cpp
//---------------------------------------------------------------------------//

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file stochastic_gradient_descent.hpp
 * \brief Stochastic Gradient Descent (SGD) Implementation for neural networks
 *
 * This implementations supports fully-connected layers, convolutional layers,
 * RBM layers, CRBM layers, transform layers and pooling layers.
 */

#pragma once

#include "cpp_utils/static_if.hpp"

#include "dll/util/checks.hpp"         // For NaN checks
#include "dll/util/timers.hpp"         // For auto_timer
#include "dll/dbn_traits.hpp"

namespace dll {

template <typename DBN>
struct sgd_trainer {
    using dbn_t     = DBN;
    using weight    = typename dbn_t::weight;
    using this_type = sgd_trainer<dbn_t>;

    static constexpr const auto layers     = dbn_t::layers;
    static constexpr const auto batch_size = dbn_t::batch_size;

    bool ae_training = false;

    dbn_t& dbn;

    /*!
     * \brief Indicates if the model is being trained as an auto-encoder (true) or not (false)
     */
    void set_autoencoder(bool ae){
        this->ae_training = ae;;
    }

    template<std::size_t Layer, typename Enable = void>
    struct input_layer_t {
        static constexpr const std::size_t L = Layer;
    };

    template<std::size_t Layer>
    struct input_layer_t<Layer, std::enable_if_t< decay_layer_traits<typename dbn_t::template layer_type<Layer>>::is_transform_layer() >> {
        static constexpr const std::size_t L = input_layer_t<Layer + 1>::L;
    };

    // Some Transform layers need to inherit dimensions from back

    template<typename L1, typename L2, cpp_enable_if(decay_layer_traits<L1>::is_transform_layer())>
    static void inherit_from_back(L1& l1, L2& l2){
        auto& ctx1 = l1.template get_sgd_context<dbn_t>();
        auto& ctx2 = l2.template get_sgd_context<dbn_t>();

        if (ctx1.errors.size() == 0) {
            ctx1.output = ctx2.input;
            ctx1.errors = ctx2.input;
            ctx1.input  = ctx2.input;
        }
    }

    template<typename L1, typename L2, cpp_disable_if(decay_layer_traits<L1>::is_transform_layer())>
    static void inherit_from_back(L1& /*l1*/, L2& /*l2*/){ }

    // Some Transform layers need to inherit dimensions from back

    template<typename L1, typename L2, cpp_enable_if(decay_layer_traits<L2>::is_transform_layer())>
    static void inherit_from_front(L1& l1, L2& l2){
        auto& ctx1 = l1.template get_sgd_context<dbn_t>();
        auto& ctx2 = l2.template get_sgd_context<dbn_t>();

        if (ctx2.errors.size() == 0) {
            ctx2.output = ctx1.output;
            ctx2.errors = ctx1.output;
            ctx2.input  = ctx1.output;
        }
    }

    template<typename L1, typename L2, cpp_disable_if(decay_layer_traits<L2>::is_transform_layer())>
    static void inherit_from_front(L1& /*l1*/, L2& /*l2*/){ }

    explicit sgd_trainer(dbn_t& dbn) : dbn(dbn) {
        // Initialize all the SGD contexts
        dbn.for_each_layer([](auto& layer) {
            layer.template init_sgd_context<dbn_t>();
        });

        // Inherit dimensions from back

        dbn.for_each_layer_rpair([](auto& l1, auto& l2) {
            constexpr bool l1_transform = decay_layer_traits<decltype(l1)>::is_transform_layer();
            constexpr bool l2_transform = decay_layer_traits<decltype(l2)>::is_transform_layer();

            if (l1_transform && (!l2_transform || l2.template get_sgd_context<dbn_t>().errors.size())) {
                this_type::inherit_from_back(l1, l2);
            }
        });

        // Inherit dimensions from front

        dbn.for_each_layer_pair([](auto& l1, auto& l2) {
            constexpr bool l2_transform = decay_layer_traits<decltype(l2)>::is_transform_layer();

            if (l2_transform) {
                this_type::inherit_from_front(l1, l2);
            }
        });
    }

    void init_training(std::size_t) {}

    template <typename D, typename It>
    void copy_inputs(D& dest, It first, It last) {
        std::size_t i = 0;

        while (first != last) {
            dest(i++) = *first++;
        }
    }

    template <typename D, typename It, cpp_enable_if(etl::decay_traits<D>::dimensions() == 2)>
    void copy_labels(D& dest, It first, It last) {
        //TODO How does that work in auto encoder mode ?

        std::size_t i = 0;

        while (first != last) {
            for (std::size_t l = 0; l < etl::dim<1>(dest); ++l) {
                dest(i, l) = (*first)[l];
            }
            ++i;
            ++first;
        }
    }

    template <typename D, typename It, cpp_enable_if(etl::decay_traits<D>::dimensions() == 4)>
    void copy_labels(D& dest, It first, It last) {
        //TODO How does that work in auto encoder mode ?

        std::size_t i = 0;

        while (first != last) {
            dest(i++) = *first++;
        }
    }

    // TODO: There are way too many copies going in this function

    template <typename Inputs, typename Labels, typename InputTransformer>
    std::pair<double, double> train_batch(std::size_t /*epoch*/, const Inputs& inputs, const Labels& labels, InputTransformer input_transformer) {
        dll::auto_timer timer("sgd::train_batch");

        // Ensure that the data batch and the label batch are of the same size
        cpp_assert(etl::dim<0>(inputs) == etl::dim<0>(labels), "Invalid sizes");

        const auto n = etl::dim<0>(inputs);

        decltype(auto) first_layer = dbn.template layer_get<0>();
        decltype(auto) first_ctx = first_layer.template get_sgd_context<dbn_t>();

        decltype(auto) last_layer = dbn.template layer_get<layers - 1>();
        decltype(auto) last_ctx = last_layer.template get_sgd_context<dbn_t>();

        const bool full_batch = etl::dim<0>(inputs) == etl::dim<0>(first_ctx.input);

        //Copy inputs into suitable data structure

        auto tilde_inputs = inputs;
        for(size_t i = 0; i < etl::dim<0>(tilde_inputs); ++i){
            input_transformer(tilde_inputs(i));
        }

        //Feedforward pass

        {
            dll::auto_timer timer("sgd::forward");

            if(cpp_unlikely(!full_batch)){
                first_ctx.input  = 0;
                first_ctx.output = 0;

                for (size_t i = 0; i < etl::dim<0>(inputs); ++i) {
                    first_ctx.input(i) = tilde_inputs(i);
                }
            } else {
                first_ctx.input = tilde_inputs;
            }

            first_layer.batch_activate_hidden(first_ctx.output, first_ctx.input);

            dbn.for_each_layer_pair([](auto& layer_1, auto& layer_2) {
                auto& ctx1 = layer_1.template get_sgd_context<dbn_t>();
                auto& ctx2 = layer_2.template get_sgd_context<dbn_t>();

                ctx2.input = ctx1.output;
                layer_2.batch_activate_hidden(ctx2.output, ctx2.input);
            });
        }

        //Compute the errors of the last layer

        if (cpp_unlikely(!full_batch)) {
            first_ctx.input = 0;
            last_ctx.errors = 0;

            for (size_t i = 0; i < etl::dim<0>(inputs); ++i) {
                last_ctx.errors(i) = labels(i) - last_ctx.output(i);
            }
        } else {
            last_ctx.errors = labels - last_ctx.output;
        }

        // Backpropagate the error

        {
            dll::auto_timer timer("sgd::backward");

            dbn.for_each_layer_rpair([](auto& r1, auto& r2) {
                auto& ctx1 = r1.template get_sgd_context<dbn_t>();
                auto& ctx2 = r2.template get_sgd_context<dbn_t>();

                r2.adapt_errors(ctx2);
                r2.backward_batch(ctx1.errors, ctx2);
            });

            first_layer.adapt_errors(first_ctx);
        }

        // Compute and apply the gradients

        {
            dll::auto_timer timer("sgd::grad");

            dbn.for_each_layer([this, n](auto& layer) {
                // Compute the gradients
                layer.compute_gradients(layer.template get_sgd_context<dbn_t>());

                // Apply the gradients
                this->apply_gradients(layer, n);
            });
        }

        // Compute error and loss

        double error = 0.0;
        double loss = 0.0;

        {
            dll::auto_timer timer("sgd::error");

            auto& out = last_ctx.output;

            if (cpp_unlikely(!full_batch)) {
                error = amean(labels - slice(out, 0, etl::dim<0>(inputs)));

                if (ae_training) {
                    // Reconstruction Cross-Entropy Loss
                    loss = -sum((labels >> log(slice(out, 0, etl::dim<0>(inputs)))) + ((1.0 - labels) >> log(1 - slice(out, 0, etl::dim<0>(inputs))))) / double(n);
                } else {
                    // Cross-Entropy Loss
                    loss = -sum(log(slice(out, 0, etl::dim<0>(inputs))) >> labels) / double(n);
                }
            } else {
                error = amean(labels - out);

                if (ae_training) {
                    // Reconstruction Cross-Entropy Loss
                    loss = -sum((labels >> log(out)) + ((1.0 - labels) >> log(1 - out))) / double(n);
                } else {
                    // Cross-Entropy Loss
                    loss = -sum(log(out) >> labels) / double(n);
                }
            }
        }

        return std::make_pair(error, loss);
    }

    template <typename L, cpp_enable_if(decay_layer_traits<L>::is_neural_layer())>
    void apply_gradients(L& layer, std::size_t n) {
        dll::auto_timer timer("sgd::apply_grad");

        auto& context = layer.template get_sgd_context<dbn_t>();

        //Update the gradients
        this->update_grad(layer.w, context.w_grad, w_decay(dbn_traits<dbn_t>::decay()), 0.0);
        this->update_grad(layer.b, context.b_grad, b_decay(dbn_traits<dbn_t>::decay()), 0.0);

        //Update with momentum and learning rate
        if (dbn_traits<dbn_t>::has_momentum()) {
            auto momentum = dbn.momentum;
            auto eps      = dbn.learning_rate;

            // Note(perf): Some performance could be gained by doing the pair of
            // operations on w in a loop to improve data locality

            context.w_inc = momentum * context.w_inc + (eps / n) * context.w_grad;
            layer.w += context.w_inc;

            context.b_inc = momentum * context.b_inc + (eps / n) * context.b_grad;
            layer.b += context.b_inc;
        } else {
            auto eps = dbn.learning_rate;

            layer.w += (eps / n) * context.w_grad;
            layer.b += (eps / n) * context.b_grad;
        }

        nan_check_deep(layer.w);
        nan_check_deep(layer.b);
    }

    template <typename L, cpp_disable_if(decay_layer_traits<L>::is_neural_layer())>
    void apply_gradients(L&, std::size_t) {
        //Pooling and transform layers have no weights, therefore no
        //gradients
    }

    template <typename V, typename G>
    void update_grad(const V& value, G& grad, decay_type decay, double penalty) {
        if (decay == decay_type::L1) {
            grad = grad - dbn.l1_weight_cost * abs(value) - penalty;
        } else if (decay == decay_type::L2) {
            grad = grad - dbn.l2_weight_cost * value - penalty;
        } else if (decay == decay_type::L1L2) {
            grad = grad - dbn.l1_weight_cost * abs(value) - dbn.l2_weight_cost * value - penalty;
        } else {
            if(penalty != 0.0){
                grad = grad - penalty;
            }
        }
    }

    static std::string name() {
        return "Stochastic Gradient Descent";
    }
};

} //end of dll namespace
<commit_msg>Get rid of inherit of inherit_from_back<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file stochastic_gradient_descent.hpp
 * \brief Stochastic Gradient Descent (SGD) Implementation for neural networks
 *
 * This implementations supports fully-connected layers, convolutional layers,
 * RBM layers, CRBM layers, transform layers and pooling layers.
 */

#pragma once

#include "cpp_utils/static_if.hpp"

#include "dll/util/checks.hpp"         // For NaN checks
#include "dll/util/timers.hpp"         // For auto_timer

namespace dll {

template <typename DBN>
struct sgd_trainer {
    using dbn_t     = DBN;
    using weight    = typename dbn_t::weight;
    using this_type = sgd_trainer<dbn_t>;

    static constexpr const auto layers     = dbn_t::layers;
    static constexpr const auto batch_size = dbn_t::batch_size;

    bool ae_training = false;

    dbn_t& dbn;

    /*!
     * \brief Indicates if the model is being trained as an auto-encoder (true) or not (false)
     */
    void set_autoencoder(bool ae){
        this->ae_training = ae;;
    }

    // Transform layers need to inherit dimensions from back

    template<typename L1, typename L2, cpp_enable_if(decay_layer_traits<L2>::is_transform_layer())>
    static void inherit_from_front(L1& l1, L2& l2){
        auto& ctx1 = l1.template get_sgd_context<dbn_t>();
        auto& ctx2 = l2.template get_sgd_context<dbn_t>();

        if (ctx2.errors.size() == 0) {
            ctx2.output = ctx1.output;
            ctx2.errors = ctx1.output;
            ctx2.input  = ctx1.output;
        }
    }

    template<typename L1, typename L2, cpp_disable_if(decay_layer_traits<L2>::is_transform_layer())>
    static void inherit_from_front(L1& /*l1*/, L2& /*l2*/){ }

    explicit sgd_trainer(dbn_t& dbn) : dbn(dbn) {
        // Initialize all the SGD contexts

        dbn.for_each_layer([](auto& layer) {
            layer.template init_sgd_context<dbn_t>();
        });

        // Inherit dimensions from front to end (for transform layers)

        dbn.for_each_layer_pair([](auto& l1, auto& l2) {
            constexpr bool l2_transform = decay_layer_traits<decltype(l2)>::is_transform_layer();

            if (l2_transform) {
                this_type::inherit_from_front(l1, l2);
            }
        });
    }

    void init_training(std::size_t) {}

    template <typename D, typename It>
    void copy_inputs(D& dest, It first, It last) {
        std::size_t i = 0;

        while (first != last) {
            dest(i++) = *first++;
        }
    }

    template <typename D, typename It, cpp_enable_if(etl::decay_traits<D>::dimensions() == 2)>
    void copy_labels(D& dest, It first, It last) {
        //TODO How does that work in auto encoder mode ?

        std::size_t i = 0;

        while (first != last) {
            for (std::size_t l = 0; l < etl::dim<1>(dest); ++l) {
                dest(i, l) = (*first)[l];
            }
            ++i;
            ++first;
        }
    }

    template <typename D, typename It, cpp_enable_if(etl::decay_traits<D>::dimensions() == 4)>
    void copy_labels(D& dest, It first, It last) {
        //TODO How does that work in auto encoder mode ?

        std::size_t i = 0;

        while (first != last) {
            dest(i++) = *first++;
        }
    }

    // TODO: There are way too many copies going in this function

    template <typename Inputs, typename Labels, typename InputTransformer>
    std::pair<double, double> train_batch(std::size_t /*epoch*/, const Inputs& inputs, const Labels& labels, InputTransformer input_transformer) {
        dll::auto_timer timer("sgd::train_batch");

        // Ensure that the data batch and the label batch are of the same size
        cpp_assert(etl::dim<0>(inputs) == etl::dim<0>(labels), "Invalid sizes");

        const auto n = etl::dim<0>(inputs);

        decltype(auto) first_layer = dbn.template layer_get<0>();
        decltype(auto) first_ctx = first_layer.template get_sgd_context<dbn_t>();

        decltype(auto) last_layer = dbn.template layer_get<layers - 1>();
        decltype(auto) last_ctx = last_layer.template get_sgd_context<dbn_t>();

        const bool full_batch = etl::dim<0>(inputs) == etl::dim<0>(first_ctx.input);

        //Copy inputs into suitable data structure

        auto tilde_inputs = inputs;
        for(size_t i = 0; i < etl::dim<0>(tilde_inputs); ++i){
            input_transformer(tilde_inputs(i));
        }

        //Feedforward pass

        {
            dll::auto_timer timer("sgd::forward");

            if(cpp_unlikely(!full_batch)){
                first_ctx.input  = 0;
                first_ctx.output = 0;

                for (size_t i = 0; i < etl::dim<0>(inputs); ++i) {
                    first_ctx.input(i) = tilde_inputs(i);
                }
            } else {
                first_ctx.input = tilde_inputs;
            }

            first_layer.batch_activate_hidden(first_ctx.output, first_ctx.input);

            dbn.for_each_layer_pair([](auto& layer_1, auto& layer_2) {
                auto& ctx1 = layer_1.template get_sgd_context<dbn_t>();
                auto& ctx2 = layer_2.template get_sgd_context<dbn_t>();

                ctx2.input = ctx1.output;
                layer_2.batch_activate_hidden(ctx2.output, ctx2.input);
            });
        }

        //Compute the errors of the last layer

        if (cpp_unlikely(!full_batch)) {
            first_ctx.input = 0;
            last_ctx.errors = 0;

            for (size_t i = 0; i < etl::dim<0>(inputs); ++i) {
                last_ctx.errors(i) = labels(i) - last_ctx.output(i);
            }
        } else {
            last_ctx.errors = labels - last_ctx.output;
        }

        // Backpropagate the error

        {
            dll::auto_timer timer("sgd::backward");

            dbn.for_each_layer_rpair([](auto& r1, auto& r2) {
                auto& ctx1 = r1.template get_sgd_context<dbn_t>();
                auto& ctx2 = r2.template get_sgd_context<dbn_t>();

                r2.adapt_errors(ctx2);
                r2.backward_batch(ctx1.errors, ctx2);
            });

            first_layer.adapt_errors(first_ctx);
        }

        // Compute and apply the gradients

        {
            dll::auto_timer timer("sgd::grad");

            dbn.for_each_layer([this, n](auto& layer) {
                // Compute the gradients
                layer.compute_gradients(layer.template get_sgd_context<dbn_t>());

                // Apply the gradients
                this->apply_gradients(layer, n);
            });
        }

        // Compute error and loss

        double error = 0.0;
        double loss = 0.0;

        {
            dll::auto_timer timer("sgd::error");

            auto& out = last_ctx.output;

            if (cpp_unlikely(!full_batch)) {
                error = amean(labels - slice(out, 0, etl::dim<0>(inputs)));

                if (ae_training) {
                    // Reconstruction Cross-Entropy Loss
                    loss = -sum((labels >> log(slice(out, 0, etl::dim<0>(inputs)))) + ((1.0 - labels) >> log(1 - slice(out, 0, etl::dim<0>(inputs))))) / double(n);
                } else {
                    // Cross-Entropy Loss
                    loss = -sum(log(slice(out, 0, etl::dim<0>(inputs))) >> labels) / double(n);
                }
            } else {
                error = amean(labels - out);

                if (ae_training) {
                    // Reconstruction Cross-Entropy Loss
                    loss = -sum((labels >> log(out)) + ((1.0 - labels) >> log(1 - out))) / double(n);
                } else {
                    // Cross-Entropy Loss
                    loss = -sum(log(out) >> labels) / double(n);
                }
            }
        }

        return std::make_pair(error, loss);
    }

    template <typename L, cpp_enable_if(decay_layer_traits<L>::is_neural_layer())>
    void apply_gradients(L& layer, std::size_t n) {
        dll::auto_timer timer("sgd::apply_grad");

        auto& context = layer.template get_sgd_context<dbn_t>();

        //Update the gradients
        this->update_grad(layer.w, context.w_grad, w_decay(dbn_traits<dbn_t>::decay()), 0.0);
        this->update_grad(layer.b, context.b_grad, b_decay(dbn_traits<dbn_t>::decay()), 0.0);

        //Update with momentum and learning rate
        if (dbn_traits<dbn_t>::has_momentum()) {
            auto momentum = dbn.momentum;
            auto eps      = dbn.learning_rate;

            // Note(perf): Some performance could be gained by doing the pair of
            // operations on w in a loop to improve data locality

            context.w_inc = momentum * context.w_inc + (eps / n) * context.w_grad;
            layer.w += context.w_inc;

            context.b_inc = momentum * context.b_inc + (eps / n) * context.b_grad;
            layer.b += context.b_inc;
        } else {
            auto eps = dbn.learning_rate;

            layer.w += (eps / n) * context.w_grad;
            layer.b += (eps / n) * context.b_grad;
        }

        nan_check_deep(layer.w);
        nan_check_deep(layer.b);
    }

    template <typename L, cpp_disable_if(decay_layer_traits<L>::is_neural_layer())>
    void apply_gradients(L&, std::size_t) {
        //Pooling and transform layers have no weights, therefore no
        //gradients
    }

    template <typename V, typename G>
    void update_grad(const V& value, G& grad, decay_type decay, double penalty) {
        if (decay == decay_type::L1) {
            grad = grad - dbn.l1_weight_cost * abs(value) - penalty;
        } else if (decay == decay_type::L2) {
            grad = grad - dbn.l2_weight_cost * value - penalty;
        } else if (decay == decay_type::L1L2) {
            grad = grad - dbn.l1_weight_cost * abs(value) - dbn.l2_weight_cost * value - penalty;
        } else {
            if(penalty != 0.0){
                grad = grad - penalty;
            }
        }
    }

    static std::string name() {
        return "Stochastic Gradient Descent";
    }
};

} //end of dll namespace
<|endoftext|>