<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>

#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		BOOST_REQUIRE(o.count("env") > 0);
		BOOST_REQUIRE(o.count("pre") > 0);
		BOOST_REQUIRE(o.count("transaction") > 0);

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
			theState.commit();
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			cout << "fatDB is defined\n";
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stMemoryStressTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

 BOOST_AUTO_TEST_CASE(stSolidityTest)
 {
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 }

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doStateTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--singletest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>add memory tests<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>

#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		BOOST_REQUIRE(o.count("env") > 0);
		BOOST_REQUIRE(o.count("pre") > 0);
		BOOST_REQUIRE(o.count("transaction") > 0);

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
			theState.commit();
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stMemoryStressTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stSolidityTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stMemoryStressTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doStateTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--singletest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "graphicsitemmatrix.h"

GraphicsItemMatrix::GraphicsItemMatrix()
    : Base()
{

}

GraphicsItemMatrix::~GraphicsItemMatrix()
{
}

void GraphicsItemMatrix::allDead()
{
    // Метод для очистки поля от живых клеток

    for (size_t i = 0; i < this->countCol; i++)
        for (size_t j = 0; j < this->countRow; j++)
            m_matrix[i][j]->changeStatus(C_DIED);
}
<commit_msg>Багфикс. Неправильно очищало поле<commit_after>#include "graphicsitemmatrix.h"

GraphicsItemMatrix::GraphicsItemMatrix()
    : Base()
{

}

GraphicsItemMatrix::~GraphicsItemMatrix()
{
}

void GraphicsItemMatrix::allDead()
{
    // Метод для очистки поля от живых клеток

    for (size_t i = 0; i < this->countRow; i++)
        for (size_t j = 0; j < this->countCol; j++)
            this->m_matrix[i][j]->changeStatus(C_DIED);

    qDebug() << "Notice:\t GraphicsItemMatrix: All cells cleared";
}
<|endoftext|>


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

#include "TwitterFeedTourStateMachineFactory.h"

#include <vector>
#include "ITourRepository.h"
#include "TwitterFeedShowTweetState.h"
#include "TourModel.h"
#include "TourStateMachine.h"
#include "TourStateModel.h"
#include "TweetRepository.h"

namespace ExampleApp
{
    namespace Tours
    {
        namespace SdkModel
        {
            namespace TourInstances
            {
                namespace TwitterFeed
                {
                    TwitterFeedTourStateMachineFactory::TwitterFeedTourStateMachineFactory(Camera::IToursCameraTransitionController& toursCameraTransitionController,
                                                                                Camera::IToursCameraController& toursCameraController,
                                                                                WorldPins::SdkModel::IWorldPinsService& worldPinsService,
                                                                                Eegeo::Resources::Interiors::InteriorController& interiorController,
                                                                                InteriorsExplorer::SdkModel::InteriorVisibilityUpdater& interiorVisibilityUpdater,
                                                                                const Eegeo::Resources::Interiors::InteriorSelectionModel& interiorSelectionModel,
                                                                                const std::string& userId,
                                                                                const std::map<std::string, TweetStateData>& tweetStateDataMap,
                                                                                Metrics::IMetricsService& metricsService,
                                                                                ExampleAppMessaging::TMessageBus& messageBus)
                    : m_toursCameraController(toursCameraController)
                    , m_toursCameraTransitionController(toursCameraTransitionController)
                    , m_worldPinsService(worldPinsService)
                    , m_interiorController(interiorController)
                    , m_interiorVisibilityUpdater(interiorVisibilityUpdater)
                    , m_interiorSelectionModel(interiorSelectionModel)
                    , m_userId(userId)
                    , m_tweetStateDataMap(tweetStateDataMap)
                    , m_metricsService(metricsService)
                    , m_messageBus(messageBus)
                    {

                    }

                    TwitterFeedTourStateMachineFactory::~TwitterFeedTourStateMachineFactory()
                    {

                    }

                    States::ITourStateMachine* TwitterFeedTourStateMachineFactory::CreateTourStateMachine(const TourModel& tourModel)
                    {
                        std::vector<States::ITourStateMachineState*> stateMachineStates;
                        std::string tourTwitterBaseUserName = tourModel.TwitterBaseUserName();

                        for (int i = 0; i < tourModel.StateCount(); ++i)
                        {
                            if(!tourModel.States()[i].IsTweet())
                            {
                                Eegeo_ASSERT(false, "Non Tweet TourStateModel in twitter only factory");
                                continue;
                            }

                            const Social::TwitterFeed::TweetModel& tweet = *(tourModel.States()[i].Tweet());
                            std::string nextTourName = tweet.GetUserScreenName();

                            if(tweet.GetUserName() == tourTwitterBaseUserName)
                            {
                                nextTourName = "";
                            }

                            const TweetStateData* tweetStateData = NULL;

                            std::map<std::string, TweetStateData>::const_iterator tweetStateIt = m_tweetStateDataMap.find(tweet.GetUserScreenName());

                            if(tweetStateIt == m_tweetStateDataMap.end())
                            {
                                // use the current tour's state data
                                tweetStateIt = m_tweetStateDataMap.find(m_userId);

                                Eegeo_ASSERT(tweetStateIt != m_tweetStateDataMap.end(), "Couldn't find state data for tour: %s", m_userId.c_str());

                                tweetStateData = &((*tweetStateIt).second);
                            }
                            else
                            {
                                // use the current state's state data
                                tweetStateData = &((*tweetStateIt).second);
                            }

                            const float cameraRotationDeltaRad = Eegeo::Math::Deg2Rad(10.0f);

                            std::string placename = !tweet.GetPlaceName().empty() ? tweet.GetPlaceName() : tweet.GetUserName();

                            Eegeo::Space::LatLong location = tweet.HasCoordinates() ? tweet.GetCoordinates() : Eegeo::Space::LatLong::FromECEF(tweetStateData->m_ecefTarget);

                            bool isInterior = false;
                            WorldPins::SdkModel::WorldPinInteriorData worldPinInteriorData;
                            if( !tweet.HasCoordinates() )
                            {
                                isInterior = tweetStateData->m_isInterior;
                                worldPinInteriorData = tweetStateData->m_interiorData;
                            }
                            else if(tweetStateData->m_useBounds)
                            {
                               if(location.GetLatitude() < tweetStateData->m_minBounds.GetLatitude() ||
                                  location.GetLongitude() < tweetStateData->m_minBounds.GetLongitude() ||
                                  location.GetLatitude() > tweetStateData->m_maxBounds.GetLatitude() ||
                                  location.GetLongitude() > tweetStateData->m_maxBounds.GetLongitude())
                               {
                                   isInterior = tweetStateData->m_isInterior;
                                   worldPinInteriorData = tweetStateData->m_interiorData;
                                   location = Eegeo::Space::LatLong::FromECEF(tweetStateData->m_ecefTarget);
                               }
                            }

                            stateMachineStates.push_back(Eegeo_NEW(TwitterFeedShowTweetState(tourModel.States()[i],
                                                                                m_toursCameraTransitionController,
                                                                                m_worldPinsService,
                                                                                isInterior,
                                                                                worldPinInteriorData,
                                                                                m_interiorController,
                                                                                m_interiorVisibilityUpdater,
                                                                                m_interiorSelectionModel,
                                                                                *tweetStateData,
                                                                                location,
                                                                                placename,
                                                                                tweet.GetFirstAttachedImageUrl(),
                                                                                tweet.GetExpandedMediaUrl(),
                                                                                tweet.HasAttachedVideo(),
                                                                                m_messageBus,
                                                                                i * cameraRotationDeltaRad)));
                        }

                        return Eegeo_NEW(States::TourStateMachine)(stateMachineStates, NULL);
                    }
                }
            }
        }
    }
}<commit_msg>Updated Twitter Tour camera rotation to 15 degrees per card instead of 10 degrees. Pair Francisco<commit_after>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "TwitterFeedTourStateMachineFactory.h"

#include <vector>
#include "ITourRepository.h"
#include "TwitterFeedShowTweetState.h"
#include "TourModel.h"
#include "TourStateMachine.h"
#include "TourStateModel.h"
#include "TweetRepository.h"

namespace ExampleApp
{
    namespace Tours
    {
        namespace SdkModel
        {
            namespace TourInstances
            {
                namespace TwitterFeed
                {
                    TwitterFeedTourStateMachineFactory::TwitterFeedTourStateMachineFactory(Camera::IToursCameraTransitionController& toursCameraTransitionController,
                                                                                Camera::IToursCameraController& toursCameraController,
                                                                                WorldPins::SdkModel::IWorldPinsService& worldPinsService,
                                                                                Eegeo::Resources::Interiors::InteriorController& interiorController,
                                                                                InteriorsExplorer::SdkModel::InteriorVisibilityUpdater& interiorVisibilityUpdater,
                                                                                const Eegeo::Resources::Interiors::InteriorSelectionModel& interiorSelectionModel,
                                                                                const std::string& userId,
                                                                                const std::map<std::string, TweetStateData>& tweetStateDataMap,
                                                                                Metrics::IMetricsService& metricsService,
                                                                                ExampleAppMessaging::TMessageBus& messageBus)
                    : m_toursCameraController(toursCameraController)
                    , m_toursCameraTransitionController(toursCameraTransitionController)
                    , m_worldPinsService(worldPinsService)
                    , m_interiorController(interiorController)
                    , m_interiorVisibilityUpdater(interiorVisibilityUpdater)
                    , m_interiorSelectionModel(interiorSelectionModel)
                    , m_userId(userId)
                    , m_tweetStateDataMap(tweetStateDataMap)
                    , m_metricsService(metricsService)
                    , m_messageBus(messageBus)
                    {

                    }

                    TwitterFeedTourStateMachineFactory::~TwitterFeedTourStateMachineFactory()
                    {

                    }

                    States::ITourStateMachine* TwitterFeedTourStateMachineFactory::CreateTourStateMachine(const TourModel& tourModel)
                    {
                        std::vector<States::ITourStateMachineState*> stateMachineStates;
                        std::string tourTwitterBaseUserName = tourModel.TwitterBaseUserName();

                        for (int i = 0; i < tourModel.StateCount(); ++i)
                        {
                            if(!tourModel.States()[i].IsTweet())
                            {
                                Eegeo_ASSERT(false, "Non Tweet TourStateModel in twitter only factory");
                                continue;
                            }

                            const Social::TwitterFeed::TweetModel& tweet = *(tourModel.States()[i].Tweet());
                            std::string nextTourName = tweet.GetUserScreenName();

                            if(tweet.GetUserName() == tourTwitterBaseUserName)
                            {
                                nextTourName = "";
                            }

                            const TweetStateData* tweetStateData = NULL;

                            std::map<std::string, TweetStateData>::const_iterator tweetStateIt = m_tweetStateDataMap.find(tweet.GetUserScreenName());

                            if(tweetStateIt == m_tweetStateDataMap.end())
                            {
                                // use the current tour's state data
                                tweetStateIt = m_tweetStateDataMap.find(m_userId);

                                Eegeo_ASSERT(tweetStateIt != m_tweetStateDataMap.end(), "Couldn't find state data for tour: %s", m_userId.c_str());

                                tweetStateData = &((*tweetStateIt).second);
                            }
                            else
                            {
                                // use the current state's state data
                                tweetStateData = &((*tweetStateIt).second);
                            }

                            const float cameraRotationDeltaRad = Eegeo::Math::Deg2Rad(15.0f);

                            std::string placename = !tweet.GetPlaceName().empty() ? tweet.GetPlaceName() : tweet.GetUserName();

                            Eegeo::Space::LatLong location = tweet.HasCoordinates() ? tweet.GetCoordinates() : Eegeo::Space::LatLong::FromECEF(tweetStateData->m_ecefTarget);

                            bool isInterior = false;
                            WorldPins::SdkModel::WorldPinInteriorData worldPinInteriorData;
                            if( !tweet.HasCoordinates() )
                            {
                                isInterior = tweetStateData->m_isInterior;
                                worldPinInteriorData = tweetStateData->m_interiorData;
                            }
                            else if(tweetStateData->m_useBounds)
                            {
                               if(location.GetLatitude() < tweetStateData->m_minBounds.GetLatitude() ||
                                  location.GetLongitude() < tweetStateData->m_minBounds.GetLongitude() ||
                                  location.GetLatitude() > tweetStateData->m_maxBounds.GetLatitude() ||
                                  location.GetLongitude() > tweetStateData->m_maxBounds.GetLongitude())
                               {
                                   isInterior = tweetStateData->m_isInterior;
                                   worldPinInteriorData = tweetStateData->m_interiorData;
                                   location = Eegeo::Space::LatLong::FromECEF(tweetStateData->m_ecefTarget);
                               }
                            }

                            stateMachineStates.push_back(Eegeo_NEW(TwitterFeedShowTweetState(tourModel.States()[i],
                                                                                m_toursCameraTransitionController,
                                                                                m_worldPinsService,
                                                                                isInterior,
                                                                                worldPinInteriorData,
                                                                                m_interiorController,
                                                                                m_interiorVisibilityUpdater,
                                                                                m_interiorSelectionModel,
                                                                                *tweetStateData,
                                                                                location,
                                                                                placename,
                                                                                tweet.GetFirstAttachedImageUrl(),
                                                                                tweet.GetExpandedMediaUrl(),
                                                                                tweet.HasAttachedVideo(),
                                                                                m_messageBus,
                                                                                i * cameraRotationDeltaRad)));
                        }

                        return Eegeo_NEW(States::TourStateMachine)(stateMachineStates, NULL);
                    }
                }
            }
        }
    }
}<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef ARCH_RUNTIME_COROUTINES_HPP_
#define ARCH_RUNTIME_COROUTINES_HPP_

#ifndef NDEBUG
#include <string>
#endif

#include "arch/runtime/callable_action.hpp"
#include "arch/runtime/context_switching.hpp"
#include "arch/runtime/runtime_utils.hpp"
#include "utils.hpp"

const size_t MAX_COROUTINE_STACK_SIZE = 8*1024*1024;

// Enable cross-coroutine backtraces in debug mode, or when coro profiling is enabled
#if !defined(NDEBUG) || defined(ENABLE_CORO_PROFILER)
#define CROSS_CORO_BACKTRACES            1
#endif
#define CROSS_CORO_BACKTRACES_MAX_SIZE  64

threadnum_t get_thread_id();
struct coro_globals_t;

struct coro_profiler_mixin_t {
#ifdef ENABLE_CORO_PROFILER
    coro_profiler_mixin_t() : last_resumed_at(0), last_sample_at(0) { }
    ticks_t last_resumed_at;
    ticks_t last_sample_at;
#endif
};

/* A coro_t represents a fiber of execution within a thread. Create one with spawn_*(). Within a
coroutine, call wait() to return control to the scheduler; the coroutine will be resumed when
another fiber calls notify_*() on it.

coro_t objects can switch threads with move_to_thread(), but it is recommended that you use
on_thread_t for more safety. */

class coro_t : private coro_profiler_mixin_t,
               private linux_thread_message_t,
               public intrusive_list_node_t<coro_t>,
               public home_thread_mixin_t {
public:
    friend bool is_coroutine_stack_overflow(void *);

    template<class Callable>
    static coro_t *spawn_now_dangerously(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_now_deprecated();
        return coro;
    }

    template<class Callable>
    static coro_t *spawn_sometime(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_sometime();
        return coro;
    }

    // TODO: spawn_later_ordered is usually what naive people want,
    // but it's such a long and onerous name.  It should have the
    // shortest name.
    template<class Callable>
    static coro_t *spawn_later_ordered(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_later_ordered();
        return coro;
    }

    // Use coro_t::spawn_*(boost::bind(...)) for spawning with parameters.

    /* `spawn()` and `notify()` are aliases for `spawn_later_ordered()` and
    `notify_later_ordered()`. They are deprecated and new code should not use
    them. */
    template<class Callable>
    static coro_t *spawn(const Callable &action) {
        return spawn_later_ordered(action);
    }

    /* Pauses the current coroutine until it is notified */
    static void wait();

    /* Gives another coroutine a chance to run, but schedules this coroutine to
    be run at some point in the future. Might not preserve order; two calls to
    `yield()` by different coroutines may return in a different order than they
    began in. */
    static void yield();
    /* Like `yield()`, but guarantees that the ordering of coroutines calling
    `yield_ordered()` is maintained. */
    static void yield_ordered();

    /* Returns a pointer to the current coroutine, or `NULL` if we are not in a
    coroutine. */
    static coro_t *self();

    /* Transfers control immediately to the coroutine. Returns when the
    coroutine calls `wait()`.

    Note: `notify_now()` may become deprecated eventually. The original purpose
    was to provide better performance than could be achieved with
    `notify_later_ordered()`, but `notify_sometime()` is now filling that role
    instead. */
    void notify_now_deprecated();

    /* Schedules the coroutine to be woken up eventually. Can be safely called
    from any thread. Returns immediately. Does not provide any ordering
    guarantees. If you don't need the ordering guarantees that
    `notify_later_ordered()` provides, use `notify_sometime()` instead. */
    void notify_sometime();

    // TODO: notify_later_ordered is usually what naive people want
    // and should get, but it's such a long and onerous name.  It
    // should have the shortest name.

    /* Pushes the coroutine onto the event queue for the thread it's currently
    on, such that it will be run. This can safely be called from any thread.
    Returns immediately. If you call `notify_later_ordered()` on two coroutines
    that are on the same thread, they will run in the same order you call
    `notify_later_ordered()` in. */
    void notify_later_ordered();

#ifndef NDEBUG
    // A unique identifier for this particular instance of coro_t over
    // the lifetime of the process.
    static int64_t selfname() {
        coro_t *running_coro = self();
        return running_coro ? running_coro->selfname_number : 0;
    }

    const std::string& get_coroutine_type() { return coroutine_type; }
#endif

    static void set_coroutine_stack_size(size_t size);

    artificial_stack_t * get_stack();

    void set_priority(int _priority) {
        linux_thread_message_t::set_priority(_priority);
    }
    int get_priority() const {
        return linux_thread_message_t::get_priority();
    }

    /* Copies the backtrace from the time of spawning the coroutine into
    `buffer_out`, which has to be allocated before calling the function.
    `size` must contain the maximum number of entries to store.
    Returns how many entries have been deposited into `buffer_out`. */
    int copy_spawn_backtrace(void **buffer_out, int size) const;

private:
    /* When called from within a coroutine, schedules the coroutine to be run on
    the given thread and then suspends the coroutine until that other thread
    picks it up again. Do not call this directly; use `on_thread_t` instead. */
    friend class on_thread_t;
    static void move_to_thread(threadnum_t thread);

    // Constructor sets up the stack, get_and_init_coro will load a function to be run
    //  at which point the coroutine can be notified
    coro_t();

    // Generates a spawn-time backtrace and stores it into `spawn_backtrace`.
    void grab_spawn_backtrace();

    // If this function footprint ever changes, you may need to update the parse_coroutine_info function
    template<class Callable>
    static coro_t * get_and_init_coro(const Callable &action) {
        coro_t *coro = get_coro();
#ifndef NDEBUG
        coro->parse_coroutine_type(__PRETTY_FUNCTION__);
#endif
        coro->grab_spawn_backtrace();
        coro->action_wrapper.reset(action);

        // If we were called from a coroutine, the new coroutine inherits our
        // caller's priority.
        if (self() != NULL) {
            coro->set_priority(self()->get_priority());
        } else {
            // Otherwise, just reset to the default.
            coro->set_priority(MESSAGE_SCHEDULER_DEFAULT_PRIORITY);
        }

        return coro;
    }

    static coro_t * get_coro();

    static void return_coro_to_free_list(coro_t *coro);

    static void run() NORETURN;

    friend class coro_profiler_t;
    friend struct coro_globals_t;
    ~coro_t();

    virtual void on_thread_switch();

    artificial_stack_t stack;

    threadnum_t current_thread_;

    // Sanity check variables
    bool notified_;
    bool waiting_;

    callable_action_wrapper_t action_wrapper;

#ifndef NDEBUG
    int64_t selfname_number;
    std::string coroutine_type;
    void parse_coroutine_type(const char *coroutine_function);
#endif

#ifdef CROSS_CORO_BACKTRACES
    int spawn_backtrace_size;
    void *spawn_backtrace[CROSS_CORO_BACKTRACES_MAX_SIZE];
#endif

    DISABLE_COPYING(coro_t);
};

/* Returns true if the given address is in the protection page of the current coroutine. */
bool is_coroutine_stack_overflow(void *addr);
bool coroutines_have_been_initialized();

class home_coro_mixin_t {
private:
    coro_t *home_coro;
public:
    home_coro_mixin_t();
    void assert_coro();
};

#endif // ARCH_RUNTIME_COROUTINES_HPP_
<commit_msg>Undid a change to the interface of coro_t::spawn_now_dangerously which wasn't really save.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef ARCH_RUNTIME_COROUTINES_HPP_
#define ARCH_RUNTIME_COROUTINES_HPP_

#ifndef NDEBUG
#include <string>
#endif

#include "arch/runtime/callable_action.hpp"
#include "arch/runtime/context_switching.hpp"
#include "arch/runtime/runtime_utils.hpp"
#include "utils.hpp"

const size_t MAX_COROUTINE_STACK_SIZE = 8*1024*1024;

// Enable cross-coroutine backtraces in debug mode, or when coro profiling is enabled
#if !defined(NDEBUG) || defined(ENABLE_CORO_PROFILER)
#define CROSS_CORO_BACKTRACES            1
#endif
#define CROSS_CORO_BACKTRACES_MAX_SIZE  64

threadnum_t get_thread_id();
struct coro_globals_t;

struct coro_profiler_mixin_t {
#ifdef ENABLE_CORO_PROFILER
    coro_profiler_mixin_t() : last_resumed_at(0), last_sample_at(0) { }
    ticks_t last_resumed_at;
    ticks_t last_sample_at;
#endif
};

/* A coro_t represents a fiber of execution within a thread. Create one with spawn_*(). Within a
coroutine, call wait() to return control to the scheduler; the coroutine will be resumed when
another fiber calls notify_*() on it.

coro_t objects can switch threads with move_to_thread(), but it is recommended that you use
on_thread_t for more safety. */

class coro_t : private coro_profiler_mixin_t,
               private linux_thread_message_t,
               public intrusive_list_node_t<coro_t>,
               public home_thread_mixin_t {
public:
    friend bool is_coroutine_stack_overflow(void *);

    template<class Callable>
    static void spawn_now_dangerously(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_now_deprecated();
    }

    template<class Callable>
    static coro_t *spawn_sometime(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_sometime();
        return coro;
    }

    // TODO: spawn_later_ordered is usually what naive people want,
    // but it's such a long and onerous name.  It should have the
    // shortest name.
    template<class Callable>
    static coro_t *spawn_later_ordered(const Callable &action) {
        coro_t *coro = get_and_init_coro(action);
        coro->notify_later_ordered();
        return coro;
    }

    // Use coro_t::spawn_*(boost::bind(...)) for spawning with parameters.

    /* `spawn()` and `notify()` are aliases for `spawn_later_ordered()` and
    `notify_later_ordered()`. They are deprecated and new code should not use
    them. */
    template<class Callable>
    static coro_t *spawn(const Callable &action) {
        return spawn_later_ordered(action);
    }

    /* Pauses the current coroutine until it is notified */
    static void wait();

    /* Gives another coroutine a chance to run, but schedules this coroutine to
    be run at some point in the future. Might not preserve order; two calls to
    `yield()` by different coroutines may return in a different order than they
    began in. */
    static void yield();
    /* Like `yield()`, but guarantees that the ordering of coroutines calling
    `yield_ordered()` is maintained. */
    static void yield_ordered();

    /* Returns a pointer to the current coroutine, or `NULL` if we are not in a
    coroutine. */
    static coro_t *self();

    /* Transfers control immediately to the coroutine. Returns when the
    coroutine calls `wait()`.

    Note: `notify_now()` may become deprecated eventually. The original purpose
    was to provide better performance than could be achieved with
    `notify_later_ordered()`, but `notify_sometime()` is now filling that role
    instead. */
    void notify_now_deprecated();

    /* Schedules the coroutine to be woken up eventually. Can be safely called
    from any thread. Returns immediately. Does not provide any ordering
    guarantees. If you don't need the ordering guarantees that
    `notify_later_ordered()` provides, use `notify_sometime()` instead. */
    void notify_sometime();

    // TODO: notify_later_ordered is usually what naive people want
    // and should get, but it's such a long and onerous name.  It
    // should have the shortest name.

    /* Pushes the coroutine onto the event queue for the thread it's currently
    on, such that it will be run. This can safely be called from any thread.
    Returns immediately. If you call `notify_later_ordered()` on two coroutines
    that are on the same thread, they will run in the same order you call
    `notify_later_ordered()` in. */
    void notify_later_ordered();

#ifndef NDEBUG
    // A unique identifier for this particular instance of coro_t over
    // the lifetime of the process.
    static int64_t selfname() {
        coro_t *running_coro = self();
        return running_coro ? running_coro->selfname_number : 0;
    }

    const std::string& get_coroutine_type() { return coroutine_type; }
#endif

    static void set_coroutine_stack_size(size_t size);

    artificial_stack_t * get_stack();

    void set_priority(int _priority) {
        linux_thread_message_t::set_priority(_priority);
    }
    int get_priority() const {
        return linux_thread_message_t::get_priority();
    }

    /* Copies the backtrace from the time of spawning the coroutine into
    `buffer_out`, which has to be allocated before calling the function.
    `size` must contain the maximum number of entries to store.
    Returns how many entries have been deposited into `buffer_out`. */
    int copy_spawn_backtrace(void **buffer_out, int size) const;

private:
    /* When called from within a coroutine, schedules the coroutine to be run on
    the given thread and then suspends the coroutine until that other thread
    picks it up again. Do not call this directly; use `on_thread_t` instead. */
    friend class on_thread_t;
    static void move_to_thread(threadnum_t thread);

    // Constructor sets up the stack, get_and_init_coro will load a function to be run
    //  at which point the coroutine can be notified
    coro_t();

    // Generates a spawn-time backtrace and stores it into `spawn_backtrace`.
    void grab_spawn_backtrace();

    // If this function footprint ever changes, you may need to update the parse_coroutine_info function
    template<class Callable>
    static coro_t * get_and_init_coro(const Callable &action) {
        coro_t *coro = get_coro();
#ifndef NDEBUG
        coro->parse_coroutine_type(__PRETTY_FUNCTION__);
#endif
        coro->grab_spawn_backtrace();
        coro->action_wrapper.reset(action);

        // If we were called from a coroutine, the new coroutine inherits our
        // caller's priority.
        if (self() != NULL) {
            coro->set_priority(self()->get_priority());
        } else {
            // Otherwise, just reset to the default.
            coro->set_priority(MESSAGE_SCHEDULER_DEFAULT_PRIORITY);
        }

        return coro;
    }

    static coro_t * get_coro();

    static void return_coro_to_free_list(coro_t *coro);

    static void run() NORETURN;

    friend class coro_profiler_t;
    friend struct coro_globals_t;
    ~coro_t();

    virtual void on_thread_switch();

    artificial_stack_t stack;

    threadnum_t current_thread_;

    // Sanity check variables
    bool notified_;
    bool waiting_;

    callable_action_wrapper_t action_wrapper;

#ifndef NDEBUG
    int64_t selfname_number;
    std::string coroutine_type;
    void parse_coroutine_type(const char *coroutine_function);
#endif

#ifdef CROSS_CORO_BACKTRACES
    int spawn_backtrace_size;
    void *spawn_backtrace[CROSS_CORO_BACKTRACES_MAX_SIZE];
#endif

    DISABLE_COPYING(coro_t);
};

/* Returns true if the given address is in the protection page of the current coroutine. */
bool is_coroutine_stack_overflow(void *addr);
bool coroutines_have_been_initialized();

class home_coro_mixin_t {
private:
    coro_t *home_coro;
public:
    home_coro_mixin_t();
    void assert_coro();
};

#endif // ARCH_RUNTIME_COROUTINES_HPP_
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Actions/Draw.hpp>
#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Cards.hpp>
#include <hspp/Games/Game.hpp>
#include <hspp/Games/GameManager.hpp>

#include <effolkronium/random.hpp>

#include <algorithm>

using Random = effolkronium::random_static;

namespace Hearthstonepp
{
Game::Game(GameConfig& gameConfig) : m_gameConfig(gameConfig)
{
    // Add hero and hero power
    GetPlayer1().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player1Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player1Class));
    GetPlayer2().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player2Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player2Class));

    // Set opponent player
    GetPlayer1().SetOpponent(&GetPlayer2());
    GetPlayer2().SetOpponent(&GetPlayer1());
}

Player& Game::GetPlayer1()
{
    return m_players[0];
}

Player& Game::GetPlayer2()
{
    return m_players[1];
}

Player& Game::GetCurrentPlayer()
{
    return *m_currentPlayer;
}

Player& Game::GetOpponentPlayer()
{
    return m_currentPlayer->GetOpponent();
}

void Game::BeginFirst()
{
    // Set next step
    nextStep = Step::BEGIN_SHUFFLE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginShuffle()
{
    // Shuffle cards in deck
    if (m_gameConfig.doShuffle)
    {
        GetPlayer1().GetDeck().Shuffle();
        GetPlayer2().GetDeck().Shuffle();
    }

    // Set next step
    nextStep = Step::BEGIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginDraw()
{
    for (auto& p : m_players)
    {
        // Draw 3 cards
        Generic::Draw(p);
        Generic::Draw(p);
        Generic::Draw(p);

        if (&p != m_firstPlayer)
        {
            // Draw 4th card for second player
            Generic::Draw(p);

            // Give "The Coin" card to second player
            Card coin = Cards::GetInstance().FindCardByID("GAME_005");
            p.GetHand().AddCard(*Entity::GetFromCard(p, std::move(coin)));
        }
    }

    // Set next step
    nextStep =
        m_gameConfig.skipMulligan ? Step::MAIN_BEGIN : Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginMulligan()
{
    // Do nothing
}

void Game::MainBegin()
{
    // Set next step
    nextStep = Step::MAIN_READY;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainReady()
{
    // Reset the number of attacked
    for (auto& p : m_players)
    {
        // Hero
        p.GetHero()->numAttacked = 0;
        // Field
        for (auto& m : p.GetField().GetAllMinions())
        {
            m->numAttacked = 0;
        }
    }

    // Reset exhaust for current player
    auto& curPlayer = GetCurrentPlayer();
    // Hero
    curPlayer.GetHero()->SetGameTag(GameTag::EXHAUSTED, 0);
    // Weapon
    if (curPlayer.GetHero()->weapon != nullptr)
    {
        curPlayer.GetHero()->weapon->SetGameTag(GameTag::EXHAUSTED, 0);
    }
    // Hero power
    curPlayer.GetHero()->heroPower->SetGameTag(GameTag::EXHAUSTED, 0);
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        m->SetGameTag(GameTag::EXHAUSTED, 0);
    }

    // Set next step
    nextStep = Step::MAIN_START_TRIGGERS;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStartTriggers()
{
    // Set next step
    nextStep = Step::MAIN_RESOURCE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainResource()
{
    auto& curPlayer = GetCurrentPlayer();

    // Add mana crystal to current player
    Generic::ChangeManaCrystal(curPlayer, 1, false);

    // Reset current mana
    curPlayer.currentMana = curPlayer.maximumMana;

    // Set next step
    nextStep = Step::MAIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainDraw()
{
    // Draw a card for current player
    Generic::Draw(GetCurrentPlayer());

    // Set next step
    nextStep = Step::MAIN_START;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStart()
{
    // Set next step
    nextStep = Step::MAIN_ACTION;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainEnd()
{
    // Set next step
    nextStep = Step::MAIN_CLEANUP;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainCleanUp()
{
    auto& curPlayer = GetCurrentPlayer();

    // Unfreeze all characters they control that are Frozen, don't have
    // summoning sickness (or do have Charge) and have not attacked that turn
    // Hero
    if (curPlayer.GetHero()->GetGameTag(GameTag::FROZEN) == 1 &&
        curPlayer.GetHero()->numAttacked == 0)
    {
        curPlayer.GetHero()->SetGameTag(GameTag::FROZEN, 0);
    }
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        if (m->GetGameTag(GameTag::FROZEN) == 1 && m->numAttacked == 0 &&
            m->GetGameTag(GameTag::EXHAUSTED) == 0)
        {
            m->SetGameTag(GameTag::FROZEN, 0);
        }
    }

    // Set next step
    nextStep = Step::MAIN_NEXT;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainNext()
{
    // Set player for next turn
    m_currentPlayer = &m_currentPlayer->GetOpponent();

    // Count next turn
    m_turn++;
}

void Game::FinalWrapUp()
{
    // Do nothing
}

void Game::FinalGameOver()
{
    // Do nothing
}

void Game::StartGame()
{
    // Reverse card order in deck
    if (!m_gameConfig.doShuffle)
    {
        std::reverse(m_gameConfig.player1Deck.begin(),
                     m_gameConfig.player1Deck.end());
        std::reverse(m_gameConfig.player2Deck.begin(),
                     m_gameConfig.player2Deck.end());
    }

    // Set up decks
    for (auto& card : m_gameConfig.player1Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer1(), std::move(card));
        GetPlayer1().GetDeck().AddCard(*entity);
    }
    for (auto& card : m_gameConfig.player2Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer2(), std::move(card));
        GetPlayer2().GetDeck().AddCard(*entity);
    }

    // Determine first player
    switch (m_gameConfig.startPlayer)
    {
        case PlayerType::RANDOM:
        {
            auto val = Random::get(0, 1);
            m_firstPlayer = &m_players[val];
            break;
        }
        case PlayerType::PLAYER1:
            m_firstPlayer = &m_players[0];
            break;
        case PlayerType::PLAYER2:
            m_firstPlayer = &m_players[1];
            break;
    }
    m_currentPlayer = m_firstPlayer;

    // Set first turn
    m_turn = 1;

    // Set next step
    nextStep = Step::BEGIN_FIRST;
    GameManager::ProcessNextStep(*this, nextStep);
}
}  // namespace Hearthstonepp<commit_msg>[ci skip] feat(game-state): Add code to set next step<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Actions/Draw.hpp>
#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Cards.hpp>
#include <hspp/Games/Game.hpp>
#include <hspp/Games/GameManager.hpp>

#include <effolkronium/random.hpp>

#include <algorithm>

using Random = effolkronium::random_static;

namespace Hearthstonepp
{
Game::Game(GameConfig& gameConfig) : m_gameConfig(gameConfig)
{
    // Add hero and hero power
    GetPlayer1().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player1Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player1Class));
    GetPlayer2().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player2Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player2Class));

    // Set opponent player
    GetPlayer1().SetOpponent(&GetPlayer2());
    GetPlayer2().SetOpponent(&GetPlayer1());
}

Player& Game::GetPlayer1()
{
    return m_players[0];
}

Player& Game::GetPlayer2()
{
    return m_players[1];
}

Player& Game::GetCurrentPlayer()
{
    return *m_currentPlayer;
}

Player& Game::GetOpponentPlayer()
{
    return m_currentPlayer->GetOpponent();
}

void Game::BeginFirst()
{
    // Set next step
    nextStep = Step::BEGIN_SHUFFLE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginShuffle()
{
    // Shuffle cards in deck
    if (m_gameConfig.doShuffle)
    {
        GetPlayer1().GetDeck().Shuffle();
        GetPlayer2().GetDeck().Shuffle();
    }

    // Set next step
    nextStep = Step::BEGIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginDraw()
{
    for (auto& p : m_players)
    {
        // Draw 3 cards
        Generic::Draw(p);
        Generic::Draw(p);
        Generic::Draw(p);

        if (&p != m_firstPlayer)
        {
            // Draw 4th card for second player
            Generic::Draw(p);

            // Give "The Coin" card to second player
            Card coin = Cards::GetInstance().FindCardByID("GAME_005");
            p.GetHand().AddCard(*Entity::GetFromCard(p, std::move(coin)));
        }
    }

    // Set next step
    nextStep =
        m_gameConfig.skipMulligan ? Step::MAIN_BEGIN : Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginMulligan()
{
    // Do nothing
}

void Game::MainBegin()
{
    // Set next step
    nextStep = Step::MAIN_READY;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainReady()
{
    // Reset the number of attacked
    for (auto& p : m_players)
    {
        // Hero
        p.GetHero()->numAttacked = 0;
        // Field
        for (auto& m : p.GetField().GetAllMinions())
        {
            m->numAttacked = 0;
        }
    }

    // Reset exhaust for current player
    auto& curPlayer = GetCurrentPlayer();
    // Hero
    curPlayer.GetHero()->SetGameTag(GameTag::EXHAUSTED, 0);
    // Weapon
    if (curPlayer.GetHero()->weapon != nullptr)
    {
        curPlayer.GetHero()->weapon->SetGameTag(GameTag::EXHAUSTED, 0);
    }
    // Hero power
    curPlayer.GetHero()->heroPower->SetGameTag(GameTag::EXHAUSTED, 0);
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        m->SetGameTag(GameTag::EXHAUSTED, 0);
    }

    // Set next step
    nextStep = Step::MAIN_START_TRIGGERS;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStartTriggers()
{
    // Set next step
    nextStep = Step::MAIN_RESOURCE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainResource()
{
    auto& curPlayer = GetCurrentPlayer();

    // Add mana crystal to current player
    Generic::ChangeManaCrystal(curPlayer, 1, false);

    // Reset current mana
    curPlayer.currentMana = curPlayer.maximumMana;

    // Set next step
    nextStep = Step::MAIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainDraw()
{
    // Draw a card for current player
    Generic::Draw(GetCurrentPlayer());

    // Set next step
    nextStep = Step::MAIN_START;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStart()
{
    // Set next step
    nextStep = Step::MAIN_ACTION;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainEnd()
{
    // Set next step
    nextStep = Step::MAIN_CLEANUP;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainCleanUp()
{
    auto& curPlayer = GetCurrentPlayer();

    // Unfreeze all characters they control that are Frozen, don't have
    // summoning sickness (or do have Charge) and have not attacked that turn
    // Hero
    if (curPlayer.GetHero()->GetGameTag(GameTag::FROZEN) == 1 &&
        curPlayer.GetHero()->numAttacked == 0)
    {
        curPlayer.GetHero()->SetGameTag(GameTag::FROZEN, 0);
    }
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        if (m->GetGameTag(GameTag::FROZEN) == 1 && m->numAttacked == 0 &&
            m->GetGameTag(GameTag::EXHAUSTED) == 0)
        {
            m->SetGameTag(GameTag::FROZEN, 0);
        }
    }

    // Set next step
    nextStep = Step::MAIN_NEXT;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainNext()
{
    // Set player for next turn
    m_currentPlayer = &m_currentPlayer->GetOpponent();

    // Count next turn
    m_turn++;

    // Set next step
    nextStep = Step::MAIN_READY;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::FinalWrapUp()
{
    // Do nothing
}

void Game::FinalGameOver()
{
    // Do nothing
}

void Game::StartGame()
{
    // Reverse card order in deck
    if (!m_gameConfig.doShuffle)
    {
        std::reverse(m_gameConfig.player1Deck.begin(),
                     m_gameConfig.player1Deck.end());
        std::reverse(m_gameConfig.player2Deck.begin(),
                     m_gameConfig.player2Deck.end());
    }

    // Set up decks
    for (auto& card : m_gameConfig.player1Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer1(), std::move(card));
        GetPlayer1().GetDeck().AddCard(*entity);
    }
    for (auto& card : m_gameConfig.player2Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer2(), std::move(card));
        GetPlayer2().GetDeck().AddCard(*entity);
    }

    // Determine first player
    switch (m_gameConfig.startPlayer)
    {
        case PlayerType::RANDOM:
        {
            auto val = Random::get(0, 1);
            m_firstPlayer = &m_players[val];
            break;
        }
        case PlayerType::PLAYER1:
            m_firstPlayer = &m_players[0];
            break;
        case PlayerType::PLAYER2:
            m_firstPlayer = &m_players[1];
            break;
    }
    m_currentPlayer = m_firstPlayer;

    // Set first turn
    m_turn = 1;

    // Set next step
    nextStep = Step::BEGIN_FIRST;
    GameManager::ProcessNextStep(*this, nextStep);
}
}  // namespace Hearthstonepp<|endoftext|>


<commit_before>#include "string_manip.hpp"

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <ctgmath>

using namespace std;

/*
 Ensures that space characters sandwich all the target characters in the string 'in'

 in - string in which to ensure targets surrounded by whitespace
 targets - characters to surround with whitespace

 Void return
 */
void ensure_whitespace(string& in, string targets){

    //Add whitespace buffer around all target characters
    for (int i = 0 ; i < in.length() ; i++){
        if (targets.find(in[i]) != string::npos){ //Found in string
            in = in.substr(0, i) + " " + in[i] + " " + in.substr(i+1);
            i++;
        }
    }

    //Remove excess white space - no consecutive spaces
    for (int i = 0; i+1 < in.length() ; i++){
        if (in[i] == ' ' && in[i+1] == ' '){
            in = in.substr(0, i) + in.substr(i+1);
            i--;
        }
    }

}

/*
 Ensures that space characters sandwich the target string in the string 'in'

 in - string in which to ensure targets surrounded by whitespace
 target - string to surround with whitespace - must appear in full to be surrounded

 Void return
 */

void ensure_whitespace_full(string& in, string target){

    //Add whitespace buffer around all target characters
    for (int i = 0 ; i+target.length() < in.length() ; i++){
        if (in.substr(i, target.length()) == target ){
            in = in.substr(0, i) + " " + in.substr(i, target.length()) + " " + in.substr(i+target.length());
            i += 1 + target.length();
        }
    }

    //Remove excess white space - no consecutive spaces
    for (int i = 0; i+1 < in.length() ; i++){
        if (in[i] == ' ' && in[i+1] == ' '){
            in = in.substr(0, i) + in.substr(i+1);
            i--;
        }
    }

}

void remove_end_whitespace(std::string& io){

    while (io.length() > 0){
        if (io[0] == ' ' || io[0] == '\t'){
            io = io.substr(1);
        }else break;
    }

    while (io.length() > 0){
        if (io[io.length() - 1] == ' ' || io[io.length()] == '\t'){
            io = io.substr(0, io.length()-1);
        }else break;
    }

}

/*
 Parses a string into a vector of strings. String broken at each instance of 'delin'. 'delin' is excluded from the output.

 input - string to parse
 delin - deliniating characters

 Returns a vector of parsed strings
 */
vector<string> parse(string input, string delin){

    vector<string> output;

    int len_counter = 0; //Number of elements in the deliated seciton
    for (int i = 0; i < input.length() ; i++){

        if ((delin.find(input[i]) != string::npos)){ //Deliniator found

            //Add block to output if section exists (not two deliniators in a row)
            if (len_counter > 0){
                output.push_back(input.substr(i-len_counter , len_counter));
            }

            //Reset length counter
            len_counter = 0;

        }else if(i+1 == input.length()){ //Handle end conditions
            len_counter++;

            if (input.substr(i-len_counter+1 , len_counter).length() > 0){
                output.push_back(input.substr(i-len_counter+1 , len_counter));
            }

        }else{

            //Increment length counter
            len_counter++;

        }
    }

	return output;
}

/*
 Determines if the string represents a number (decimal or integer). Accepts scientific notation and negatives.

 s - string to analyze

 Returns true if 's' is a number
 */
bool isnum(string s){

    bool allow_e = true;
    bool allow_punct = true;

    for (int i = 0 ; i < s.length() ; i++){
        if (s[i] == '0' || s[i] == '1' ||s[i] == '2' ||s[i] == '3' ||s[i] == '4' ||s[i] == '5' ||s[i] == '6' ||s[i] == '7' || s[i] == '8' ||s[i] == '9' ){
            //Do nothing, all is well
        }else if(i == 0 && s[i] == '-'){
            if (i+1 >= s.length() || !(s[i+1] == '0' || s[i+1] == '1' || s[i+1] == '2' || s[i+1] == '3' || s[i+1] == '4' || s[i+1] == '5' || s[i+1] == '6' || s[i+1] == '7' || s[i+1] == '8' || s[i+1] == '9') ){
                return false;
            }
            i++;
        }else if(allow_e && s[i] == 'e'){

            //Ensure e is not first char
            if (i == 0) return false;

            //Check that e is followed by a number
            if (i+1 >= s.length() || !(s[i+1] == '0' || s[i+1] == '1' || s[i+1] == '2' || s[i+1] == '3' || s[i+1] == '4' || s[i+1] == '5' || s[i+1] == '6' || s[i+1] == '7' || s[i+1] == '8' || s[i+1] == '9' || s[i+1] == '-') ){
                return false;
            }

            //If e is followed by '-', ensure number follows
            if (s[i+1] == '-'){
                if (i+2 >= s.length() || !(s[i+2] == '0' || s[i+2] == '1' || s[i+2] == '2' || s[i+2] == '3' || s[i+2] == '4' || s[i+2] == '5' || s[i+2] == '6' || s[i+2] == '7' || s[i+2] == '8' || s[i+2] == '9') ){
                    return false;
                }
                i++;
            }
            i++;
            allow_e = false;
        }else if(allow_punct && s[i] == '.'){
            allow_punct = false;
        }else{
            return false;
        }

    }

    return true;
}

/*
 Removes any characters following an instance of the 'commentor' string. Must be complete 'commentor' to trigger. Modifies input string 's'.

 s - string whose comments are to be removed
 commentor - string indicating comment follows

 Void return
 */
void remove_comments(string& s, string commentor){

	for (int i = 0 ; i < s.length() ; i++){
		if (s.substr(i, commentor.length()) == commentor){
			s = s.substr(0, i);
		}
	}

}

/*
 Removes any character included in 'targets' from the end of 's'. The target char must be the last character in order to be removed. Modifies 's'

 s - string to modify
 targets - characters to target

 Void return
 */
void remove_from_end(string& s, string targets){

	for (int i = (int)s.length() - 1 ; i >= 0 ; i--){
		if ( targets.find(s.substr(i, 1)) != string::npos){
			s.pop_back();
		}else{
			i = -1;
		}
	}

}

/*
 Concatonates a vector of strings into single string

 t - vector of strings to concatonate
 idx - index at which to start concatonating (inclusive & through end)
 joint - string to add between each vector element concatonated

 Returns concatonated strings
 */
string cat_tokens(vector<string> t, int idx, string joint){

	if (t.size() <= idx){
		return "";
	}

    if (idx < 0) idx = 0;

	string out = t[idx];
	for (int i = idx+1 ; i < t.size() ; i++){
		out = out + joint + t[i];
	}

	return out;
}

/*
 Converts the input string's lowercase letters to uppercase letters.

 s - string to convert to upper case

 Returns the capitolized string
 */
string to_uppercase(std::string s){
	for (int i = 0; i < s.length() ; i++){
		s[i] = toupper(s[i]);
	}
	return s;
}

/*
 Converts the input string's uppercase letters to lowercase letters.

 s - string to convert

 Rerturns the lowercase string
 */
string to_lowercase(std::string s){
	for (int i = 0; i < s.length() ; i++){
		s[i] = tolower(s[i]);
	}
	return s;
}

/*
 Returns a string representing the input boolean value.

 x - bool representing value to output
 uppercase - if true, will print TRUE/FALSE instead of True/False
 */
string bool_to_str(bool x, bool uppercase){
	if (x){
		if (uppercase){
			return "TRUE";
		}else{
			return "True";
		}
	}else{
		if (uppercase){
			return "FALSE";
		}else{
			return "False";
		}
	}
}

string format_newline(string input, string prefix){

    string out = "";

    vector<string> parts = parse(input, "\n");
    for (unsigned long i = 0 ; i < parts.size() ; i++){
        if (out != "") out = out + '\n';
        out = out + prefix + parts[i];
    }

    return out;
}

string hp_string(double input, int precision, bool scientific){

    int len = (int)precision+100;
	char buff[len];
//    for (int i = 0 ; i < len ; i++){
//        buff[i] = '0';
//    }
    string precision_str = "%." + to_string((int)precision);
    precision_str = (scientific) ? precision_str + "e" : precision_str + "f";
	sprintf(buff, precision_str.c_str(), input);
	string out(buff);
//    string out = "";
//    for (int i = 0 ; i < len ; i++){
//        out = out + buff[i];
//    }

    return out;
}

double strtod(std::string input, bool* success){

    //[-][###][.][###][E][-][###]

    if (success != NULL) *success = true;

    return stod(input);

//    double x = 0;
//    bool neg = false;
//    int start = 0;
//
//    //Remove excess whitespace
//    for (int i = 0 ; i < input.length() ; i++){
//        if (input[i] == ' ' || input[i] == '\t'){
//            input = input.substr(0, i) + input.substr(i+1);
//            i--;
//        }
//    }
//
//    //Look for negatives
//    if (input[0] == '-'){
//        neg = true;
//        start = 1;
//    }
//
//    //Read 1st number (before sceintific notation component)
//
//    //Determine length of number
//    bool decimal_used = false;
//    int pt_idx = -1;
//    int end = -1;
//
//    for (int i = start ; i < input.length() ; i++){
//        if (input [i] == '.'){
//            if (decimal_used){
//                return -1;
//                if (success != NULL) *success = false;
//            }
//            decimal_used = true;
//            pt_idx = i;
//        }else if((i+1 == input.length() && end == -1) || input[i+1] == 'e' || input[i+1] == 'E'){
//            end = i;
//        }else if(!isnum(input.substr(i, 1))){
//            //pass
//        }
//    }
//    if (!decimal_used){
//        pt_idx = end+1;
//    }
//
//    //Calculate value of first number
//    if (start != pt_idx){
//        int place = 0;
//        for (int i = start ; i < pt_idx ; i++ ){
//            x = x*10 + ( ((int)input[i])-48 );
//            place++;
//        }
//        //        double decimal = 0; //Alternate evaluation meathod - faster and potentially less accurate in some situation
//        //        for (int i = end ; i > pt_idx ; i--){
//        //            decimal += ( ((int)input[i])-48 );
//        //            decimal /= 10;
//        //        }
//        place = -1;
//        for (int i = pt_idx+1 ; i <= end ; i++){
//            x += pow(10, place) * ( ((int)input[i])-48 );
//            place--;
//        }
//    }
//
//    //Negate negatives
//    if (neg){
//        x = -1 * x;
//    }
//
//    //Evalute power of 10
//    if (end != input.length()-1){
//        if (end + 2 > input.length()){
//            if (success != NULL) *success = false;
//            return -1;
//        }
//        bool subsuccess;
//        double power = strtod(input.substr(end+2), &subsuccess);
//        if (!subsuccess){
//            if (success != NULL) *success = false;
//            return -1;
//        }
//        x *= pow(10, power);
//    }
//
//    return x;
}

void select_notation(double num, int precision, int threshold, bool force_sci, bool force_fix){

    cout.precision(precision);

    if (force_sci || num > threshold){
        cout << std::scientific;
    }else if(force_fix || num >= 1){
        cout << std::fixed;
    }else{
        if (num < 1/threshold){
            cout << std::scientific;
        }else{
            cout << std::fixed;
        }
        //Show as much as possible is 'precision' digits, with as few characters
        //If #_1 > prec, sci & ignore #_2
        //If #_1 < prec && NONZERO: fixed
        //   If #_2 > prec-length(#_1), show #_2
        //   If #_2 < prec-length(#_1), ignore #_2
        //IF #_1 == 0:
        //   If #_2 < prec, sci
        //   If #_2 > prec, fixed

    }

}

char select_notation(double num, int threshold){

    if (num > threshold){
        return 's';
    }else if(num >= 1){
        return 'f';
    }else{
        double a = 1.0/threshold;
        if (num < a){
            return 's';
        }else{
            return 'f';
        }
    }

}

<commit_msg>Fixed notation selection function<commit_after>#include "string_manip.hpp"

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <ctgmath>

using namespace std;

/*
 Ensures that space characters sandwich all the target characters in the string 'in'

 in - string in which to ensure targets surrounded by whitespace
 targets - characters to surround with whitespace

 Void return
 */
void ensure_whitespace(string& in, string targets){

    //Add whitespace buffer around all target characters
    for (int i = 0 ; i < in.length() ; i++){
        if (targets.find(in[i]) != string::npos){ //Found in string
            in = in.substr(0, i) + " " + in[i] + " " + in.substr(i+1);
            i++;
        }
    }

    //Remove excess white space - no consecutive spaces
    for (int i = 0; i+1 < in.length() ; i++){
        if (in[i] == ' ' && in[i+1] == ' '){
            in = in.substr(0, i) + in.substr(i+1);
            i--;
        }
    }

}

/*
 Ensures that space characters sandwich the target string in the string 'in'

 in - string in which to ensure targets surrounded by whitespace
 target - string to surround with whitespace - must appear in full to be surrounded

 Void return
 */

void ensure_whitespace_full(string& in, string target){

    //Add whitespace buffer around all target characters
    for (int i = 0 ; i+target.length() < in.length() ; i++){
        if (in.substr(i, target.length()) == target ){
            in = in.substr(0, i) + " " + in.substr(i, target.length()) + " " + in.substr(i+target.length());
            i += 1 + target.length();
        }
    }

    //Remove excess white space - no consecutive spaces
    for (int i = 0; i+1 < in.length() ; i++){
        if (in[i] == ' ' && in[i+1] == ' '){
            in = in.substr(0, i) + in.substr(i+1);
            i--;
        }
    }

}

void remove_end_whitespace(std::string& io){

    while (io.length() > 0){
        if (io[0] == ' ' || io[0] == '\t'){
            io = io.substr(1);
        }else break;
    }

    while (io.length() > 0){
        if (io[io.length() - 1] == ' ' || io[io.length()] == '\t'){
            io = io.substr(0, io.length()-1);
        }else break;
    }

}

/*
 Parses a string into a vector of strings. String broken at each instance of 'delin'. 'delin' is excluded from the output.

 input - string to parse
 delin - deliniating characters

 Returns a vector of parsed strings
 */
vector<string> parse(string input, string delin){

    vector<string> output;

    int len_counter = 0; //Number of elements in the deliated seciton
    for (int i = 0; i < input.length() ; i++){

        if ((delin.find(input[i]) != string::npos)){ //Deliniator found

            //Add block to output if section exists (not two deliniators in a row)
            if (len_counter > 0){
                output.push_back(input.substr(i-len_counter , len_counter));
            }

            //Reset length counter
            len_counter = 0;

        }else if(i+1 == input.length()){ //Handle end conditions
            len_counter++;

            if (input.substr(i-len_counter+1 , len_counter).length() > 0){
                output.push_back(input.substr(i-len_counter+1 , len_counter));
            }

        }else{

            //Increment length counter
            len_counter++;

        }
    }

	return output;
}

/*
 Determines if the string represents a number (decimal or integer). Accepts scientific notation and negatives.

 s - string to analyze

 Returns true if 's' is a number
 */
bool isnum(string s){

    bool allow_e = true;
    bool allow_punct = true;

    for (int i = 0 ; i < s.length() ; i++){
        if (s[i] == '0' || s[i] == '1' ||s[i] == '2' ||s[i] == '3' ||s[i] == '4' ||s[i] == '5' ||s[i] == '6' ||s[i] == '7' || s[i] == '8' ||s[i] == '9' ){
            //Do nothing, all is well
        }else if(i == 0 && s[i] == '-'){
            if (i+1 >= s.length() || !(s[i+1] == '0' || s[i+1] == '1' || s[i+1] == '2' || s[i+1] == '3' || s[i+1] == '4' || s[i+1] == '5' || s[i+1] == '6' || s[i+1] == '7' || s[i+1] == '8' || s[i+1] == '9') ){
                return false;
            }
            i++;
        }else if(allow_e && s[i] == 'e'){

            //Ensure e is not first char
            if (i == 0) return false;

            //Check that e is followed by a number
            if (i+1 >= s.length() || !(s[i+1] == '0' || s[i+1] == '1' || s[i+1] == '2' || s[i+1] == '3' || s[i+1] == '4' || s[i+1] == '5' || s[i+1] == '6' || s[i+1] == '7' || s[i+1] == '8' || s[i+1] == '9' || s[i+1] == '-') ){
                return false;
            }

            //If e is followed by '-', ensure number follows
            if (s[i+1] == '-'){
                if (i+2 >= s.length() || !(s[i+2] == '0' || s[i+2] == '1' || s[i+2] == '2' || s[i+2] == '3' || s[i+2] == '4' || s[i+2] == '5' || s[i+2] == '6' || s[i+2] == '7' || s[i+2] == '8' || s[i+2] == '9') ){
                    return false;
                }
                i++;
            }
            i++;
            allow_e = false;
        }else if(allow_punct && s[i] == '.'){
            allow_punct = false;
        }else{
            return false;
        }

    }

    return true;
}

/*
 Removes any characters following an instance of the 'commentor' string. Must be complete 'commentor' to trigger. Modifies input string 's'.

 s - string whose comments are to be removed
 commentor - string indicating comment follows

 Void return
 */
void remove_comments(string& s, string commentor){

	for (int i = 0 ; i < s.length() ; i++){
		if (s.substr(i, commentor.length()) == commentor){
			s = s.substr(0, i);
		}
	}

}

/*
 Removes any character included in 'targets' from the end of 's'. The target char must be the last character in order to be removed. Modifies 's'

 s - string to modify
 targets - characters to target

 Void return
 */
void remove_from_end(string& s, string targets){

	for (int i = (int)s.length() - 1 ; i >= 0 ; i--){
		if ( targets.find(s.substr(i, 1)) != string::npos){
			s.pop_back();
		}else{
			i = -1;
		}
	}

}

/*
 Concatonates a vector of strings into single string

 t - vector of strings to concatonate
 idx - index at which to start concatonating (inclusive & through end)
 joint - string to add between each vector element concatonated

 Returns concatonated strings
 */
string cat_tokens(vector<string> t, int idx, string joint){

	if (t.size() <= idx){
		return "";
	}

    if (idx < 0) idx = 0;

	string out = t[idx];
	for (int i = idx+1 ; i < t.size() ; i++){
		out = out + joint + t[i];
	}

	return out;
}

/*
 Converts the input string's lowercase letters to uppercase letters.

 s - string to convert to upper case

 Returns the capitolized string
 */
string to_uppercase(std::string s){
	for (int i = 0; i < s.length() ; i++){
		s[i] = toupper(s[i]);
	}
	return s;
}

/*
 Converts the input string's uppercase letters to lowercase letters.

 s - string to convert

 Rerturns the lowercase string
 */
string to_lowercase(std::string s){
	for (int i = 0; i < s.length() ; i++){
		s[i] = tolower(s[i]);
	}
	return s;
}

/*
 Returns a string representing the input boolean value.

 x - bool representing value to output
 uppercase - if true, will print TRUE/FALSE instead of True/False
 */
string bool_to_str(bool x, bool uppercase){
	if (x){
		if (uppercase){
			return "TRUE";
		}else{
			return "True";
		}
	}else{
		if (uppercase){
			return "FALSE";
		}else{
			return "False";
		}
	}
}

string format_newline(string input, string prefix){

    string out = "";

    vector<string> parts = parse(input, "\n");
    for (unsigned long i = 0 ; i < parts.size() ; i++){
        if (out != "") out = out + '\n';
        out = out + prefix + parts[i];
    }

    return out;
}

string hp_string(double input, int precision, bool scientific){

    int len = (int)precision+100;
	char buff[len];
//    for (int i = 0 ; i < len ; i++){
//        buff[i] = '0';
//    }
    string precision_str = "%." + to_string((int)precision);
    precision_str = (scientific) ? precision_str + "e" : precision_str + "f";
	sprintf(buff, precision_str.c_str(), input);
	string out(buff);
//    string out = "";
//    for (int i = 0 ; i < len ; i++){
//        out = out + buff[i];
//    }

    return out;
}

double strtod(std::string input, bool* success){

    //[-][###][.][###][E][-][###]

    if (success != NULL) *success = true;

    return stod(input);

//    double x = 0;
//    bool neg = false;
//    int start = 0;
//
//    //Remove excess whitespace
//    for (int i = 0 ; i < input.length() ; i++){
//        if (input[i] == ' ' || input[i] == '\t'){
//            input = input.substr(0, i) + input.substr(i+1);
//            i--;
//        }
//    }
//
//    //Look for negatives
//    if (input[0] == '-'){
//        neg = true;
//        start = 1;
//    }
//
//    //Read 1st number (before sceintific notation component)
//
//    //Determine length of number
//    bool decimal_used = false;
//    int pt_idx = -1;
//    int end = -1;
//
//    for (int i = start ; i < input.length() ; i++){
//        if (input [i] == '.'){
//            if (decimal_used){
//                return -1;
//                if (success != NULL) *success = false;
//            }
//            decimal_used = true;
//            pt_idx = i;
//        }else if((i+1 == input.length() && end == -1) || input[i+1] == 'e' || input[i+1] == 'E'){
//            end = i;
//        }else if(!isnum(input.substr(i, 1))){
//            //pass
//        }
//    }
//    if (!decimal_used){
//        pt_idx = end+1;
//    }
//
//    //Calculate value of first number
//    if (start != pt_idx){
//        int place = 0;
//        for (int i = start ; i < pt_idx ; i++ ){
//            x = x*10 + ( ((int)input[i])-48 );
//            place++;
//        }
//        //        double decimal = 0; //Alternate evaluation meathod - faster and potentially less accurate in some situation
//        //        for (int i = end ; i > pt_idx ; i--){
//        //            decimal += ( ((int)input[i])-48 );
//        //            decimal /= 10;
//        //        }
//        place = -1;
//        for (int i = pt_idx+1 ; i <= end ; i++){
//            x += pow(10, place) * ( ((int)input[i])-48 );
//            place--;
//        }
//    }
//
//    //Negate negatives
//    if (neg){
//        x = -1 * x;
//    }
//
//    //Evalute power of 10
//    if (end != input.length()-1){
//        if (end + 2 > input.length()){
//            if (success != NULL) *success = false;
//            return -1;
//        }
//        bool subsuccess;
//        double power = strtod(input.substr(end+2), &subsuccess);
//        if (!subsuccess){
//            if (success != NULL) *success = false;
//            return -1;
//        }
//        x *= pow(10, power);
//    }
//
//    return x;
}

void select_notation(double num, int precision, int threshold, bool force_sci, bool force_fix){

    cout.precision(precision);

    if (force_sci || num > threshold){
        cout << std::scientific;
    }else if(force_fix || num >= 1){
        cout << std::fixed;
    }else{
        if (num < 1/threshold){
            cout << std::scientific;
        }else{
            cout << std::fixed;
        }
        //Show as much as possible is 'precision' digits, with as few characters
        //If #_1 > prec, sci & ignore #_2
        //If #_1 < prec && NONZERO: fixed
        //   If #_2 > prec-length(#_1), show #_2
        //   If #_2 < prec-length(#_1), ignore #_2
        //IF #_1 == 0:
        //   If #_2 < prec, sci
        //   If #_2 > prec, fixed

    }

}

char select_notation(double num, int threshold){

    num = abs(num);

    if (num > threshold){
        return 's';
    }else if(num >= 1){
        return 'f';
    }else{
        double a = 1.0/threshold;
        if (num < a){
            return 's';
        }else{
            return 'f';
        }
    }

}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

namespace choreograph
{

  //! Remove all elements from \a vec that match \a compare
  template<class ELEMENT_TYPE, class COMPARATOR>
  void vector_erase_if( std::vector<ELEMENT_TYPE> *vec, COMPARATOR compare )
  {
    vec->erase( std::remove_if( vec->begin()
                               , vec->end()
                               , compare )
               , vec->end() );
  }

  //! Remove all elements from \a container that match \a compare
  //! This is closer to an earlier strategy I had than vector_erase_if,
  //! but that was plagued by obscure error messages. Will see if this works
  //! a bit better / more flexibly
  template<class CONTAINER_TYPE, class COMPARATOR>
  void erase_if( CONTAINER_TYPE *container, COMPARATOR compare )
  {
    container->erase( std::remove_if( container->begin(),
                                     container->end(),
                                     compare ),
                     container->end() );
  }

  //! Remove all copies of \a element from \a vec
  template<class ELEMENT_TYPE>
  void vector_remove( std::vector<ELEMENT_TYPE> *vec, const ELEMENT_TYPE &element )
  {
    vec->erase( std::remove_if( vec->begin()
                               , vec->end()
                               , [=](const ELEMENT_TYPE &e){ return e == element; } )
               , vec->end() );
  }

/*
 Holds a collection of Motions.
 Maybe variadic templates to specify an animation with different channel types,
 or one composed of n existing channels...
 */
class Timeline
{
public:

  //! Create a Sequence that is connected out to \a output.
  template<typename T>
  Motion<T>& move( T *output )
  { // remove any existing motions that affect the same variable (because that doesn't make sense within a single timeline)
    erase_if( &_motions, [=] (std::shared_ptr<MotionBase> m) { return m->_target == output; } );

    auto c = std::make_shared<Motion<T>>();
    c->sequence = std::make_shared<Sequence<T>>();
    c->output = output;
    c->_target = output;
    c->sequence->_initial_value = *output;
    _motions.push_back( c );
    return *c;
  }

  //! Create a Motion that plays \a sequence into \a output.
  template<typename T>
  Motion<T>& move( T *output, std::shared_ptr<Sequence<T>> sequence )
  { // remove any existing motions that affect the same variable (because that doesn't make sense within a single timeline)
    erase_if( &_motions, [=] (const std::shared_ptr<MotionBase> &m) { return m->_target == output; } );

    auto c = std::make_shared<Motion<T>>();
    c->sequence = sequence;
    c->output = output;
    c->_target = output;
    c->sequence->_initial_value = *output;
    _motions.push_back( c );
    return *c;
  }

  // Advance all current connections.
  void step( float dt )
  {
    for( auto &c : _motions )
    {
      c->step( dt );
    }

    if( _auto_clear )
    {
      erase_if( &_motions, [=] (const std::shared_ptr<MotionBase> &c ) { return !c->_continuous && c->time() >= c->getDuration(); } );
//      _motions.erase( std::remove_if( _motions.begin(), _motions.end(), [=] (const std::shared_ptr<MotionBase> &c ) { return !c->_continuous && c->time >= c->getDuration(); } ), _motions.end() );
    }
  }

  void remove( const std::shared_ptr<MotionBase> &motion )
  {
    _motions.erase( std::remove_if( _motions.begin(), _motions.end(), [=] (const std::shared_ptr<MotionBase> &c ) { return c == motion; } ), _motions.end() );
  }

private:
  bool                                      _auto_clear = true;
  std::vector<std::shared_ptr<MotionBase>>  _motions;
};

} // namespace choreograph
<commit_msg>Use erase_if to remove things from containers.<commit_after>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

namespace choreograph
{

  //! Remove all elements from \a vec that match \a compare
  template<class ELEMENT_TYPE, class COMPARATOR>
  void vector_erase_if( std::vector<ELEMENT_TYPE> *vec, COMPARATOR compare )
  {
    vec->erase( std::remove_if( vec->begin()
                               , vec->end()
                               , compare )
               , vec->end() );
  }

  //! Remove all elements from \a container that match \a compare
  //! This is closer to an earlier strategy I had than vector_erase_if,
  //! but that was plagued by obscure error messages. Will see if this works
  //! a bit better / more flexibly
  template<class CONTAINER_TYPE, class COMPARATOR>
  void erase_if( CONTAINER_TYPE *container, COMPARATOR compare )
  {
    container->erase( std::remove_if( container->begin(),
                                     container->end(),
                                     compare ),
                     container->end() );
  }

  //! Remove all copies of \a element from \a vec
  template<class ELEMENT_TYPE>
  void vector_remove( std::vector<ELEMENT_TYPE> *vec, const ELEMENT_TYPE &element )
  {
    vec->erase( std::remove_if( vec->begin()
                               , vec->end()
                               , [=](const ELEMENT_TYPE &e){ return e == element; } )
               , vec->end() );
  }

/*
 Holds a collection of Motions.
 Maybe variadic templates to specify an animation with different channel types,
 or one composed of n existing channels...
 */
class Timeline
{
public:

  //! Create a Sequence that is connected out to \a output.
  template<typename T>
  Motion<T>& move( T *output )
  { // remove any existing motions that affect the same variable (because that doesn't make sense within a single timeline)
    erase_if( &_motions, [=] (std::shared_ptr<MotionBase> m) { return m->_target == output; } );

    auto c = std::make_shared<Motion<T>>();
    c->sequence = std::make_shared<Sequence<T>>();
    c->output = output;
    c->_target = output;
    c->sequence->_initial_value = *output;
    _motions.push_back( c );
    return *c;
  }

  //! Create a Motion that plays \a sequence into \a output.
  template<typename T>
  Motion<T>& move( T *output, std::shared_ptr<Sequence<T>> sequence )
  { // remove any existing motions that affect the same variable (because that doesn't make sense within a single timeline)
    erase_if( &_motions, [=] (const std::shared_ptr<MotionBase> &m) { return m->_target == output; } );

    auto c = std::make_shared<Motion<T>>();
    c->sequence = sequence;
    c->output = output;
    c->_target = output;
    c->sequence->_initial_value = *output;
    _motions.push_back( c );
    return *c;
  }

  // Advance all current connections.
  void step( float dt )
  {
    for( auto &c : _motions )
    {
      c->step( dt );
    }

    if( _auto_clear )
    {
      erase_if( &_motions, [=] (const std::shared_ptr<MotionBase> &c ) { return !c->_continuous && c->time() >= c->getDuration(); } );
    }
  }

  void remove( const std::shared_ptr<MotionBase> &motion )
  {
    erase_if( &_motions, [motion] (const std::shared_ptr<MotionBase> &c ) { return c == motion; } );
  }

private:
  bool                                      _auto_clear = true;
  std::vector<std::shared_ptr<MotionBase>>  _motions;
};

} // namespace choreograph
<|endoftext|>