<commit_before>/*
 *
 * Author: Jeffrey Leung
 * Last edited: 2015-12-05
 *
 * This C++ header file contains classes related to creating a LabyrinthMap
 * which creates, updates, and displays a map of a given Labyrinth.
 *
 */

#pragma once

#include <iostream>

#include "room_properties.hpp"
#include "labyrinth.hpp"

// This class is a template for LabyrinthMapCoordinateBorder and
// LabyrinthMapCoordinateRoom to inherit from, so that an array can be
// made where any given element is either a Border or a Room.
class LabyrinthMapCoordinate
{
};

// This class contains necessary information about a given Border coordinate,
// so that a map can be displayed.
// Borders/Walls are true by default to avoid working explicitly with:
//   The outer wall
class LabyrinthMapCoordinateBorder : LabyrinthMapCoordinate
{
  public:

    // This method removes the Wall of a given Wall coordinate.
    // May be used to remove a Wall which has already been removed.
    // An exception is thrown if:
    //   d is kNone (invalid_argument)
    void SetWall( Direction d );

  private:
    bool wall_north_ = true;
    bool wall_east_  = true;
    bool wall_south_ = true;
    bool wall_west_  = true;

    bool exit_       = false;
};

// This class contains necessary information about a given Room coordinate,
// so that a map can be displayed.
class LabyrinthMapCoordinateRoom : LabyrinthMapCoordinate
{
  public:

    // This method sets the current inhabitant of the map's Room.
    // May be used to set the inhabitant to the same inhabitant, or to
    // no inhabitant.
    void SetInhabitant( Inhabitant inh );

    // This method places the treasure in the map's Room.
    // May be used when there is already a treasure in the map's Room.
    void SetTreasure();

    // This method removes the treasure from the Room.
    // May be used when there is no treasure in the map's Room.
    void RemoveTreasure();

  private:
    Inhabitant i_   = Inhabitant::kNone;
    bool treasure_ = false;
};

// This class contains a map of a Labyrinth.
class LabyrinthMap
{
  public:

    // Parameterized constructor
    // An exception is thrown if:
    //   l is null (invalid_argument)
    LabyrinthMap( Labyrinth* l,
                  unsigned int x_size,
                  unsigned int y_size );

    // Destructor
    ~LabyrinthMap();

    // This method displays a map of the current Labyrinth.
    void Display();

  private:

    Labyrinth* l_;

    unsigned int x_size_;
    unsigned int y_size_;

    unsigned int map_x_size_;
    unsigned int map_y_size_;

    LabyrinthMapCoordinate** map_;

    // This method returns true if x and y in the map array designate a Room,
    // and false if they designate a Border.
    bool IsRoom( unsigned int x, unsigned int y ) const;

    // This method updates the map by checking the contents of the Labyrinth.
    void Update();
};
<commit_msg>Making MapCoord inheritance public.<commit_after>/*
 *
 * Author: Jeffrey Leung
 * Last edited: 2015-12-05
 *
 * This C++ header file contains classes related to creating a LabyrinthMap
 * which creates, updates, and displays a map of a given Labyrinth.
 *
 */

#pragma once

#include <iostream>

#include "room_properties.hpp"
#include "labyrinth.hpp"

// This class is a template for LabyrinthMapCoordinateBorder and
// LabyrinthMapCoordinateRoom to inherit from, so that an array can be
// made where any given element is either a Border or a Room.
class LabyrinthMapCoordinate
{
};

// This class contains necessary information about a given Border coordinate,
// so that a map can be displayed.
// Borders/Walls are true by default to avoid working explicitly with:
//   The outer wall
class LabyrinthMapCoordinateBorder : public LabyrinthMapCoordinate
{
  public:

    // This method removes the Wall of a given Wall coordinate.
    // May be used to remove a Wall which has already been removed.
    // An exception is thrown if:
    //   d is kNone (invalid_argument)
    void SetWall( Direction d );

  private:
    bool wall_north_ = true;
    bool wall_east_  = true;
    bool wall_south_ = true;
    bool wall_west_  = true;

    bool exit_       = false;
};

// This class contains necessary information about a given Room coordinate,
// so that a map can be displayed.
class LabyrinthMapCoordinateRoom : public LabyrinthMapCoordinate
{
  public:

    // This method sets the current inhabitant of the map's Room.
    // May be used to set the inhabitant to the same inhabitant, or to
    // no inhabitant.
    void SetInhabitant( Inhabitant inh );

    // This method places the treasure in the map's Room.
    // May be used when there is already a treasure in the map's Room.
    void SetTreasure();

    // This method removes the treasure from the Room.
    // May be used when there is no treasure in the map's Room.
    void RemoveTreasure();

  private:
    Inhabitant i_   = Inhabitant::kNone;
    bool treasure_ = false;
};

// This class contains a map of a Labyrinth.
class LabyrinthMap
{
  public:

    // Parameterized constructor
    // An exception is thrown if:
    //   l is null (invalid_argument)
    LabyrinthMap( Labyrinth* l,
                  unsigned int x_size,
                  unsigned int y_size );

    // Destructor
    ~LabyrinthMap();

    // This method displays a map of the current Labyrinth.
    void Display();

  private:

    Labyrinth* l_;
    unsigned int x_size_;
    unsigned int y_size_;

    unsigned int map_x_size_;
    unsigned int map_y_size_;

    LabyrinthMapCoordinate** map_;

    // This method returns true if x and y in the map array designate a Room,
    // and false if they designate a Border.
    bool IsRoom( unsigned int x, unsigned int y ) const;

    // This method updates the map by checking the contents of the Labyrinth.
    void Update();
};
<|endoftext|>


<commit_before>#include "SDLGameObject.h"
#include "TextureManager.h"
#include "Game.h"

SDLGameObject::SDLGameObject(const LoaderParams* pParams): GameObject(pParams), m_position((float)pParams->getX(), (float)pParams->getY()), m_velocity(0,0), m_acceleration(0,0)
{
	m_width = pParams->getWidth();
	m_height = pParams->getHeight();

	m_textureID = pParams->getTextureID();

	m_currentRow = 1;
	m_currentFrame = 1;
}

void SDLGameObject::draw()
{
	//TextureManager::Instance()->drawFrame(m_textureID, (int)m_position.getX(), (int)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer());
	if (m_velocity.getX() > 0)
	{
		TextureManager::Instance()->drawFrame(m_textureID, (Uint32)m_position.getX(), (Uint32)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer(), SDL_FLIP_HORIZONTAL);
	}
	else
	{
		TextureManager::Instance()->drawFrame(m_textureID, (Uint32)m_position.getX(), (Uint32)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer());
	}
}

void SDLGameObject::update()
{
	m_velocity += m_acceleration;
	m_position += m_velocity;
}

void SDLGameObject::clean()
{
	//blank
}<commit_msg>Added m_numFrames value in SDLGameObject.cpp<commit_after>#include "SDLGameObject.h"
#include "TextureManager.h"
#include "Game.h"

SDLGameObject::SDLGameObject(const LoaderParams* pParams): GameObject(pParams), m_position((float)pParams->getX(), (float)pParams->getY()), m_velocity(0,0), m_acceleration(0,0)
{
	m_width = pParams->getWidth();
	m_height = pParams->getHeight();

	m_textureID = pParams->getTextureID();

	m_currentRow = 1;
	m_currentFrame = 1;
	m_numFrames = pParams->getnFrames();
}

void SDLGameObject::draw()
{
	//TextureManager::Instance()->drawFrame(m_textureID, (int)m_position.getX(), (int)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer());
	if (m_velocity.getX() > 0)
	{
		TextureManager::Instance()->drawFrame(m_textureID, (Uint32)m_position.getX(), (Uint32)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer(), SDL_FLIP_HORIZONTAL);
	}
	else
	{
		TextureManager::Instance()->drawFrame(m_textureID, (Uint32)m_position.getX(), (Uint32)m_position.getY(), m_width, m_height, m_currentRow, m_currentFrame, TheGame::Instance()->getRenderer());
	}
}

void SDLGameObject::update()
{
	m_velocity += m_acceleration;
	m_position += m_velocity;
}

void SDLGameObject::clean()
{
	//blank
}<|endoftext|>


<commit_before>#ifndef SEED11_HPP_E3A87608D1BE11E5A14C96B0531BF5E9
#define SEED11_HPP_E3A87608D1BE11E5A14C96B0531BF5E9

#include <cassert>
#include <climits>
#include <limits>
#include <initializer_list>
#include <memory>
#include <string>
#include <iterator>
#include <vector>
#include <cstddef>
#include <random>
#include <stdexcept>
#include <type_traits>
#include <algorithm>

#include <seed11/seed_device.hpp>

namespace seed11
{
	namespace detail
	{
		template<typename T>
		class acquire_seed_size_seed_seq
		{
			std::size_t* s;

		public:
			typedef T result_type;

			acquire_seed_size_seed_seq(std::size_t* s = nullptr) :
				s(s)
			{

			}

			template<typename InputIterator>
			acquire_seed_size_seed_seq(InputIterator, InputIterator) :
				s(nullptr)
			{

			}

			template<typename V>
			acquire_seed_size_seed_seq(std::initializer_list<V>) :
				s(nullptr)
			{

			}

			template<typename RandomAccessIterator>
			void generate(RandomAccessIterator outb, RandomAccessIterator oute)
			{
				if(s) *s = std::distance(outb, oute);
				std::fill(outb, oute, 0);
			}

			std::size_t size() const
			{
				return 0;
			}

			template<typename OutputIterator>
			void param(OutputIterator)
			{

			}
		};

		template<typename T>
		std::size_t get_seed_size_for()
		{
			std::size_t seed_size;
			acquire_seed_size_seed_seq<unsigned> acq_seed_size(&seed_size);
			T gen(acq_seed_size);
			return seed_size;
		}
	}

	template<typename SequenceContainer>
	class seed_seq_container_adapter
	{
		SequenceContainer seed;

		void ensure_not_empty()
		{
			if(seed.empty())
			{
				seed.push_back(1);
				seed.push_back(2);
			}
		}

	public:
		typedef unsigned result_type;

		seed_seq_container_adapter()
		{
			ensure_not_empty();
		}

		template<typename InputIterator>
		seed_seq_container_adapter(InputIterator b, InputIterator e) :
			seed(b, e)
		{
			ensure_not_empty();
		}

		template<typename V>
		seed_seq_container_adapter(std::initializer_list<V> in) :
			seed(in.begin(), in.end())
		{
			ensure_not_empty();
		}

		seed_seq_container_adapter(const SequenceContainer& s) :
			seed(s)
		{
			ensure_not_empty();
		}

		seed_seq_container_adapter(SequenceContainer&& s) :
			seed(std::move(s))
		{
			ensure_not_empty();
		}

		template<typename RandomAccessIterator>
		void generate(RandomAccessIterator outb, RandomAccessIterator oute)
		{
			auto in = seed.begin();
			auto inb = seed.begin();
			auto ine = seed.end();
			for(auto& o = outb; o != oute; ++o)
			{
				*o = *in;
				++in;
				if(in == ine)
					in = inb;
			}
		}

		std::size_t size() const
		{
			return seed.size();
		}

		template<typename OutputIterator>
		void param(OutputIterator out)
		{
			std::copy(seed.begin(), seed.end(), out);
		}

		SequenceContainer steal_storage()
		{
			return SequenceContainer(std::move(seed));
		}
	};

	/// create seeded random engine using the generator passed as an argument
	template<typename T, typename U>
	T make_seeded(U&& urng)
	{
		typedef typename std::remove_cv<typename std::remove_reference<U>::type>::type UnqualifiedU;
		// get the size of the seed from the URNG by employing
		// a dummy SeedSequence object.
		const std::size_t seed_size = detail::get_seed_size_for<T>();
		// fill the vector with random data
		std::vector<typename UnqualifiedU::result_type> seed_data;
		seed_data.reserve(seed_size);
		std::generate_n(std::back_inserter(seed_data), seed_size, std::ref(urng));
		// use it to initialize a seed sequence
		seed_seq_container_adapter<decltype(seed_data)> true_seed_seq(std::move(seed_data));
		return T(true_seed_seq);
	}

	namespace detail
	{
		seed_device& thread_local_seed_device();
		std::mt19937_64& thread_local_random();
	}

	/// create seeded random engine
	template<typename T>
	T make_seeded()
	{
		return make_seeded<T>(detail::thread_local_seed_device());
	}

	void reseed();
	void reseed(std::mt19937_64::result_type value);

	template<typename T>
	T randint(T a, T b)
	{
		return std::uniform_int_distribution<T>(a,b)(detail::thread_local_random());
	}

	template<typename RandomAccessIterator>
	void shuffle(RandomAccessIterator first, RandomAccessIterator last)
	{
		std::shuffle(first, last, detail::thread_local_random());
	}

	template<typename RandomAccessIterator, typename URNG>
	RandomAccessIterator choice(RandomAccessIterator first, RandomAccessIterator last, URNG&& urng)
	{
		typedef typename std::iterator_traits<RandomAccessIterator>::difference_type df_t;
		std::uniform_int_distribution<df_t> dist(0, std::max(static_cast<df_t>(0), std::distance(first, last-1)));
		return first + dist(urng);
	}

	template<typename RandomAccessIterator>
	RandomAccessIterator choice(RandomAccessIterator first, RandomAccessIterator last)
	{
		return choice(first, last, detail::thread_local_random());
	}
}

#endif
<commit_msg>fix invalid out of bounds access<commit_after>#ifndef SEED11_HPP_E3A87608D1BE11E5A14C96B0531BF5E9
#define SEED11_HPP_E3A87608D1BE11E5A14C96B0531BF5E9

#include <cassert>
#include <climits>
#include <limits>
#include <initializer_list>
#include <memory>
#include <string>
#include <iterator>
#include <vector>
#include <cstddef>
#include <random>
#include <stdexcept>
#include <type_traits>
#include <algorithm>

#include <seed11/seed_device.hpp>

namespace seed11
{
	namespace detail
	{
		template<typename T>
		class acquire_seed_size_seed_seq
		{
			std::size_t* s;

		public:
			typedef T result_type;

			acquire_seed_size_seed_seq(std::size_t* s = nullptr) :
				s(s)
			{

			}

			template<typename InputIterator>
			acquire_seed_size_seed_seq(InputIterator, InputIterator) :
				s(nullptr)
			{

			}

			template<typename V>
			acquire_seed_size_seed_seq(std::initializer_list<V>) :
				s(nullptr)
			{

			}

			template<typename RandomAccessIterator>
			void generate(RandomAccessIterator outb, RandomAccessIterator oute)
			{
				if(s) *s = std::distance(outb, oute);
				std::fill(outb, oute, 0);
			}

			std::size_t size() const
			{
				return 0;
			}

			template<typename OutputIterator>
			void param(OutputIterator)
			{

			}
		};

		template<typename T>
		std::size_t get_seed_size_for()
		{
			std::size_t seed_size;
			acquire_seed_size_seed_seq<unsigned> acq_seed_size(&seed_size);
			T gen(acq_seed_size);
			return seed_size;
		}
	}

	template<typename SequenceContainer>
	class seed_seq_container_adapter
	{
		SequenceContainer seed;

		void ensure_not_empty()
		{
			if(seed.empty())
			{
				seed.push_back(1);
				seed.push_back(2);
			}
		}

	public:
		typedef unsigned result_type;

		seed_seq_container_adapter()
		{
			ensure_not_empty();
		}

		template<typename InputIterator>
		seed_seq_container_adapter(InputIterator b, InputIterator e) :
			seed(b, e)
		{
			ensure_not_empty();
		}

		template<typename V>
		seed_seq_container_adapter(std::initializer_list<V> in) :
			seed(in.begin(), in.end())
		{
			ensure_not_empty();
		}

		seed_seq_container_adapter(const SequenceContainer& s) :
			seed(s)
		{
			ensure_not_empty();
		}

		seed_seq_container_adapter(SequenceContainer&& s) :
			seed(std::move(s))
		{
			ensure_not_empty();
		}

		template<typename RandomAccessIterator>
		void generate(RandomAccessIterator outb, RandomAccessIterator oute)
		{
			auto in = seed.begin();
			auto inb = seed.begin();
			auto ine = seed.end();
			for(auto& o = outb; o != oute; ++o)
			{
				*o = *in;
				++in;
				if(in == ine)
					in = inb;
			}
		}

		std::size_t size() const
		{
			return seed.size();
		}

		template<typename OutputIterator>
		void param(OutputIterator out)
		{
			std::copy(seed.begin(), seed.end(), out);
		}

		SequenceContainer steal_storage()
		{
			return SequenceContainer(std::move(seed));
		}
	};

	/// create seeded random engine using the generator passed as an argument
	template<typename T, typename U>
	T make_seeded(U&& urng)
	{
		typedef typename std::remove_cv<typename std::remove_reference<U>::type>::type UnqualifiedU;
		// get the size of the seed from the URNG by employing
		// a dummy SeedSequence object.
		const std::size_t seed_size = detail::get_seed_size_for<T>();
		// fill the vector with random data
		std::vector<typename UnqualifiedU::result_type> seed_data;
		seed_data.reserve(seed_size);
		std::generate_n(std::back_inserter(seed_data), seed_size, std::ref(urng));
		// use it to initialize a seed sequence
		seed_seq_container_adapter<decltype(seed_data)> true_seed_seq(std::move(seed_data));
		return T(true_seed_seq);
	}

	namespace detail
	{
		seed_device& thread_local_seed_device();
		std::mt19937_64& thread_local_random();
	}

	/// create seeded random engine
	template<typename T>
	T make_seeded()
	{
		return make_seeded<T>(detail::thread_local_seed_device());
	}

	void reseed();
	void reseed(std::mt19937_64::result_type value);

	template<typename T>
	T randint(T a, T b)
	{
		return std::uniform_int_distribution<T>(a,b)(detail::thread_local_random());
	}

	template<typename RandomAccessIterator>
	void shuffle(RandomAccessIterator first, RandomAccessIterator last)
	{
		std::shuffle(first, last, detail::thread_local_random());
	}

	template<typename RandomAccessIterator, typename URNG>
	RandomAccessIterator choice(RandomAccessIterator first, RandomAccessIterator last, URNG&& urng)
	{
		typedef typename std::iterator_traits<RandomAccessIterator>::difference_type df_t;
		std::uniform_int_distribution<df_t> dist(0, std::max(static_cast<df_t>(0), std::distance(first, last)-1));
		return first + dist(urng);
	}

	template<typename RandomAccessIterator>
	RandomAccessIterator choice(RandomAccessIterator first, RandomAccessIterator last)
	{
		return choice(first, last, detail::thread_local_random());
	}
}

#endif
<|endoftext|>


<commit_before>#include "SFMLUtilities.h"
#include <random>
#include <iostream>

namespace zmc
{
SFMLUtilities::SFMLUtilities()
{
}

sf::Vector2f SFMLUtilities::getCenterPosition(sf::Vector2u parentSize, sf::Sprite &sprite)
{
    sf::Vector2f vector((int)parentSize.x / 2 - (sprite.getTexture()->getSize().x / 2) * sprite.getScale().x , (int)parentSize.y / 2 - (sprite.getTexture()->getSize().y / 2)
                        * sprite.getScale().y);
    return vector;
}

sf::Vector2f SFMLUtilities::getScaledSize(sf::Sprite &sprite, const sf::IntRect &customRect)
{
    sf::Vector2f vector;
    if (customRect.height > 0 || customRect.width > 0)
        vector = sf::Vector2f(customRect.width  * sprite.getScale().x , customRect.height * sprite.getScale().y);
    else
        vector = sf::Vector2f(sprite.getTexture()->getSize().x  * sprite.getScale().x , sprite.getTexture()->getSize().y * sprite.getScale().y);
    return vector;
}

const std::vector<int> SFMLUtilities::getDigits(int n)
{
    std::vector<int> array;
    std::vector<int> array2;
    if (n == 0) {
        array2.push_back(0);
        return array2;
    }
    int number = n;
    while (number > 0) {
        int mod = number % 10;
        array.push_back(mod);
        number -= mod;
        number /= 10;
    }
    for (unsigned int i = array.size() - 1; i < array.size(); i--) {
        array2.push_back(array.at(i));
    }
    return array2;
}

const sf::IntRect SFMLUtilities::getScaledTextureRect(sf::Sprite &sprite)
{
    sf::IntRect intRect;
    intRect.top = (int)sprite.getPosition().y;
    intRect.left = (int)sprite.getPosition().x;
    intRect.height = (int)getScaledSize(sprite).y;
    intRect.width = (int)getScaledSize(sprite).x;
    return intRect;
}

int SFMLUtilities::generateRandomNumber(int start, int end, int seed)
{
    std::random_device rd; // obtain a random number from hardware
    std::mt19937 eng(seed == 0 ? rd() : seed); // seed the generator
    std::uniform_int_distribution<> distr(start, end); // define the range
    return distr(eng);
}

sf::Vector2f SFMLUtilities::getFitToAlignScale(sf::Vector2u textureSize, sf::Vector2u containerSize)
{
    float imageHeight = (float)textureSize.y;
    float imageWidth = (float)textureSize.x;
    float rImage = imageWidth / imageHeight;
    float screenHeight = (float)containerSize.y;
    float screenWidth = (float)containerSize.x;
    float rScreen = screenWidth / screenHeight;
    //    rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)
    sf::Vector2f size(rScreen > rImage ? (imageWidth * screenHeight / imageHeight) : screenWidth,
                      rScreen > rImage ? screenHeight : imageHeight * screenWidth / imageWidth);

    float scalex = (float)size.x / (float)textureSize.x;
    float scaley = (float)size.y / (float)textureSize.y;
    return sf::Vector2f(scalex, scaley);
}

float SFMLUtilities::toSFMLCoordinate(float box2dCoord)
{
    return box2dCoord * 30;
}

float SFMLUtilities::toBox2DCoordinate(float sfmlCoord)
{
    return sfmlCoord / 30;
}

float SFMLUtilities::toDegree(float radian)
{
    const float PI = 3.14159265f;
    return (radian * 180 / PI);
}

float SFMLUtilities::toRadian(float degree)
{
    const float PI = 3.14159265f;
    return (degree * PI / 180);
}

float SFMLUtilities::distanceBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    return std::sqrt(std::pow((firstVector.x - secondVector.x), 2) + std::pow((firstVector.y - secondVector.y), 2));
}

float SFMLUtilities::getAngleBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    float rotation = 0;
    float h = zmc::SFMLUtilities::distanceBetweenTwoVectors(firstVector, secondVector);
    if(secondVector.x > firstVector.x) {
        float x = std::abs(firstVector.x - secondVector.x);
        rotation = zmc::SFMLUtilities::toDegree(std::sin(x / h));
    }
    else {
        float y = std::abs(firstVector.y - secondVector.y);
        rotation = zmc::SFMLUtilities::toDegree(std::cos(y / h));
    }
    return rotation;
}
}
<commit_msg>Update getAngleBetweenTwoVectors<commit_after>#include "SFMLUtilities.h"
#include <random>
#include <iostream>

namespace zmc
{
SFMLUtilities::SFMLUtilities()
{
}

sf::Vector2f SFMLUtilities::getCenterPosition(sf::Vector2u parentSize, sf::Sprite &sprite)
{
    sf::Vector2f vector((int)parentSize.x / 2 - (sprite.getTexture()->getSize().x / 2) * sprite.getScale().x , (int)parentSize.y / 2 - (sprite.getTexture()->getSize().y / 2)
                        * sprite.getScale().y);
    return vector;
}

sf::Vector2f SFMLUtilities::getScaledSize(sf::Sprite &sprite, const sf::IntRect &customRect)
{
    sf::Vector2f vector;
    if (customRect.height > 0 || customRect.width > 0)
        vector = sf::Vector2f(customRect.width  * sprite.getScale().x , customRect.height * sprite.getScale().y);
    else
        vector = sf::Vector2f(sprite.getTexture()->getSize().x  * sprite.getScale().x , sprite.getTexture()->getSize().y * sprite.getScale().y);
    return vector;
}

const std::vector<int> SFMLUtilities::getDigits(int n)
{
    std::vector<int> array;
    std::vector<int> array2;
    if (n == 0) {
        array2.push_back(0);
        return array2;
    }
    int number = n;
    while (number > 0) {
        int mod = number % 10;
        array.push_back(mod);
        number -= mod;
        number /= 10;
    }
    for (unsigned int i = array.size() - 1; i < array.size(); i--) {
        array2.push_back(array.at(i));
    }
    return array2;
}

const sf::IntRect SFMLUtilities::getScaledTextureRect(sf::Sprite &sprite)
{
    sf::IntRect intRect;
    intRect.top = (int)sprite.getPosition().y;
    intRect.left = (int)sprite.getPosition().x;
    intRect.height = (int)getScaledSize(sprite).y;
    intRect.width = (int)getScaledSize(sprite).x;
    return intRect;
}

int SFMLUtilities::generateRandomNumber(int start, int end, int seed)
{
    std::random_device rd; // obtain a random number from hardware
    std::mt19937 eng(seed == 0 ? rd() : seed); // seed the generator
    std::uniform_int_distribution<> distr(start, end); // define the range
    return distr(eng);
}

sf::Vector2f SFMLUtilities::getFitToAlignScale(sf::Vector2u textureSize, sf::Vector2u containerSize)
{
    float imageHeight = (float)textureSize.y;
    float imageWidth = (float)textureSize.x;
    float rImage = imageWidth / imageHeight;
    float screenHeight = (float)containerSize.y;
    float screenWidth = (float)containerSize.x;
    float rScreen = screenWidth / screenHeight;
    //    rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)
    sf::Vector2f size(rScreen > rImage ? (imageWidth * screenHeight / imageHeight) : screenWidth,
                      rScreen > rImage ? screenHeight : imageHeight * screenWidth / imageWidth);

    float scalex = (float)size.x / (float)textureSize.x;
    float scaley = (float)size.y / (float)textureSize.y;
    return sf::Vector2f(scalex, scaley);
}

float SFMLUtilities::toSFMLCoordinate(float box2dCoord)
{
    return box2dCoord * 30;
}

float SFMLUtilities::toBox2DCoordinate(float sfmlCoord)
{
    return sfmlCoord / 30;
}

float SFMLUtilities::toDegree(float radian)
{
    const float PI = 3.14159265f;
    return (radian * 180 / PI);
}

float SFMLUtilities::toRadian(float degree)
{
    const float PI = 3.14159265f;
    return (degree * PI / 180);
}

float SFMLUtilities::distanceBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    return std::sqrt(std::pow((firstVector.x - secondVector.x), 2) + std::pow((firstVector.y - secondVector.y), 2));
}

float SFMLUtilities::getAngleBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    float rotation = 0;
    rotation = (float) toDegree(std::atan2(firstVector.x - secondVector.x, firstVector.y - secondVector.y));
    if (rotation < 0) {
        rotation += 360;
    }
    return rotation;
}
}
<|endoftext|>


<commit_before>#include "SFMLUtilities.h"
#include <random>
#include <iostream>

namespace zmc
{
SFMLUtilities::SFMLUtilities()
{
}

sf::Vector2f SFMLUtilities::getCenterPosition(sf::Vector2u parentSize, sf::Sprite &sprite)
{
    sf::Vector2f vector((int)parentSize.x / 2 - (sprite.getTexture()->getSize().x / 2) * sprite.getScale().x , (int)parentSize.y / 2 - (sprite.getTexture()->getSize().y / 2)
                        * sprite.getScale().y);
    return vector;
}

sf::Vector2f SFMLUtilities::getScaledSize(const sf::Sprite &sprite/*, const sf::IntRect &customRect*/)
{
    sf::Vector2f vector;
//    if (customRect.height > 0 || customRect.width > 0)
//        vector = sf::Vector2f(customRect.width  * sprite.getScale().x , customRect.height * sprite.getScale().y);
//    else
    vector = sf::Vector2f(sprite.getTexture()->getSize().x  * sprite.getScale().x , sprite.getTexture()->getSize().y * sprite.getScale().y);
    return vector;
}

const std::vector<int> SFMLUtilities::getDigits(int n)
{
    std::vector<int> array;
    std::vector<int> array2;
    if (n == 0) {
        array2.push_back(0);
        return array2;
    }
    int number = n;
    while (number > 0) {
        int mod = number % 10;
        array.push_back(mod);
        number -= mod;
        number /= 10;
    }
    for (unsigned int i = array.size() - 1; i < array.size(); i--) {
        array2.push_back(array.at(i));
    }
    return array2;
}

const sf::IntRect SFMLUtilities::getScaledTextureRect(const sf::Sprite &sprite)
{
    sf::IntRect intRect;
    intRect.top = (int)sprite.getPosition().y;
    intRect.left = (int)sprite.getPosition().x;
    intRect.height = (int)getScaledSize(sprite).y;
    intRect.width = (int)getScaledSize(sprite).x;
    return intRect;
}

int SFMLUtilities::generateRandomNumber(int start, int end, int seed)
{
    std::random_device rd; // obtain a random number from hardware
    std::mt19937 eng(seed == 0 ? rd() : seed); // seed the generator
    std::uniform_int_distribution<> distr(start, end); // define the range
    return distr(eng);
}

sf::Vector2f SFMLUtilities::getFitToAlignScale(sf::Vector2u textureSize, sf::Vector2u containerSize)
{
    float imageHeight = (float)textureSize.y;
    float imageWidth = (float)textureSize.x;
    float rImage = imageWidth / imageHeight;
    float screenHeight = (float)containerSize.y;
    float screenWidth = (float)containerSize.x;
    float rScreen = screenWidth / screenHeight;
    //    rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)
    sf::Vector2f size(rScreen > rImage ? (imageWidth * screenHeight / imageHeight) : screenWidth,
                      rScreen > rImage ? screenHeight : imageHeight * screenWidth / imageWidth);

    float scalex = (float)size.x / (float)textureSize.x;
    float scaley = (float)size.y / (float)textureSize.y;
    return sf::Vector2f(scalex, scaley);
}

float SFMLUtilities::toSFMLCoordinate(float box2dCoord)
{
    return box2dCoord * 30;
}

float SFMLUtilities::toBox2DCoordinate(float sfmlCoord)
{
    return sfmlCoord / 30;
}

float SFMLUtilities::toDegree(float radian)
{
    const float PI = 3.14159265f;
    return (radian * 180 / PI);
}

float SFMLUtilities::toRadian(float degree)
{
    const float PI = 3.14159265f;
    return (degree * PI / 180);
}

float SFMLUtilities::distanceBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    return std::sqrt(std::pow((firstVector.x - secondVector.x), 2) + std::pow((firstVector.y - secondVector.y), 2));
}

float SFMLUtilities::getAngleBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    float rotation = 0;
    rotation = (float) toDegree(std::atan2(firstVector.x - secondVector.x, firstVector.y - secondVector.y));
    if (rotation < 0) {
        rotation += 360;
    }
    return rotation;
}

bool SFMLUtilities::intersects(const sf::Sprite *firstSprite, const sf::Sprite *secondSprite)
{
    sf::IntRect firstRect((int)firstSprite->getPosition().x, (int)firstSprite->getPosition().y
                          , (int)getScaledSize(*firstSprite).x, (int)getScaledSize(*firstSprite).y);
    sf::IntRect secondRect((int)secondSprite->getPosition().x, (int)secondSprite->getPosition().y
                           , (int)getScaledSize(*secondSprite).x, (int)getScaledSize(*secondSprite).y);
    return firstRect.intersects(secondRect);
}
}
<commit_msg>Update SFMLUtilities.cpp<commit_after>#include "SFMLUtilities.h"
#include <random>
#include <iostream>

namespace zmc
{
SFMLUtilities::SFMLUtilities()
{
}

sf::Vector2f SFMLUtilities::getCenterPosition(sf::Vector2u parentSize, sf::Sprite &sprite)
{
    sf::Vector2f vector((int)parentSize.x / 2 - (sprite.getTexture()->getSize().x / 2) * sprite.getScale().x , (int)parentSize.y / 2 - (sprite.getTexture()->getSize().y / 2)
                        * sprite.getScale().y);
    return vector;
}

sf::Vector2f SFMLUtilities::getScaledSize(const sf::Sprite &sprite/*, const sf::IntRect &customRect*/)
{
    sf::Vector2f vector;
//    if (customRect.height > 0 || customRect.width > 0)
//        vector = sf::Vector2f(customRect.width  * sprite.getScale().x , customRect.height * sprite.getScale().y);
//    else
    vector = sf::Vector2f(sprite.getTexture()->getSize().x  * sprite.getScale().x , sprite.getTexture()->getSize().y * sprite.getScale().y);
    return vector;
}

const std::vector<int> SFMLUtilities::getDigits(int n)
{
    std::vector<int> array;
    std::vector<int> array2;
    if (n == 0) {
        array2.push_back(0);
        return array2;
    }
    int number = n;
    while (number > 0) {
        int mod = number % 10;
        array.push_back(mod);
        number -= mod;
        number /= 10;
    }
    for (unsigned int i = array.size() - 1; i < array.size(); i--) {
        array2.push_back(array.at(i));
    }
    return array2;
}

const sf::IntRect SFMLUtilities::getScaledTextureRect(const sf::Sprite &sprite)
{
    sf::IntRect intRect;
    intRect.top = (int)sprite.getPosition().y;
    intRect.left = (int)sprite.getPosition().x;
    intRect.height = (int)getScaledSize(sprite).y;
    intRect.width = (int)getScaledSize(sprite).x;
    return intRect;
}

int SFMLUtilities::generateRandomNumber(int start, int end)
{
    auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    std::mt19937 eng(seed);
    std::uniform_int_distribution<> distr(start, end);
    return distr(eng);
}

sf::Vector2f SFMLUtilities::getFitToAlignScale(sf::Vector2u textureSize, sf::Vector2u containerSize)
{
    float imageHeight = (float)textureSize.y;
    float imageWidth = (float)textureSize.x;
    float rImage = imageWidth / imageHeight;
    float screenHeight = (float)containerSize.y;
    float screenWidth = (float)containerSize.x;
    float rScreen = screenWidth / screenHeight;
    //    rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)
    sf::Vector2f size(rScreen > rImage ? (imageWidth * screenHeight / imageHeight) : screenWidth,
                      rScreen > rImage ? screenHeight : imageHeight * screenWidth / imageWidth);

    float scalex = (float)size.x / (float)textureSize.x;
    float scaley = (float)size.y / (float)textureSize.y;
    return sf::Vector2f(scalex, scaley);
}

float SFMLUtilities::toSFMLCoordinate(float box2dCoord)
{
    return box2dCoord * 30;
}

float SFMLUtilities::toBox2DCoordinate(float sfmlCoord)
{
    return sfmlCoord / 30;
}

float SFMLUtilities::toDegree(float radian)
{
    const float PI = 3.14159265f;
    return (radian * 180 / PI);
}

float SFMLUtilities::toRadian(float degree)
{
    const float PI = 3.14159265f;
    return (degree * PI / 180);
}

float SFMLUtilities::distanceBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    return std::sqrt(std::pow((firstVector.x - secondVector.x), 2) + std::pow((firstVector.y - secondVector.y), 2));
}

float SFMLUtilities::getAngleBetweenTwoVectors(sf::Vector2f firstVector, sf::Vector2f secondVector)
{
    float rotation = 0;
    rotation = (float) toDegree(std::atan2(firstVector.x - secondVector.x, firstVector.y - secondVector.y));
    if (rotation < 0) {
        rotation += 360;
    }
    return rotation;
}

bool SFMLUtilities::intersects(const sf::Sprite *firstSprite, const sf::Sprite *secondSprite)
{
    sf::IntRect firstRect((int)firstSprite->getPosition().x, (int)firstSprite->getPosition().y
                          , (int)getScaledSize(*firstSprite).x, (int)getScaledSize(*firstSprite).y);
    sf::IntRect secondRect((int)secondSprite->getPosition().x, (int)secondSprite->getPosition().y
                           , (int)getScaledSize(*secondSprite).x, (int)getScaledSize(*secondSprite).y);
    return firstRect.intersects(secondRect);
}
}
<|endoftext|>


<commit_before>#ifndef V_SMC_PARTICLE_HPP
#define V_SMC_PARTICLE_HPP

#include <algorithm>
#include <limits>
#include <cstddef>
#include <mkl_vml.h>
#include <gsl/gsl_cblas.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <vDist/utilities/buffer.hpp>
#include <vDist/utilities/eblas.hpp>

namespace vSMC {

/// Resample scheme
enum ResampleScheme {MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <class T>
class Particle
{
    public :

    /// \brief Particle does not have a default constructor
    ///
    /// \param N The number of particles
    /// \param copy A pointer to the function that can copy particle from one
    /// position to another position
    Particle (std::size_t N, void (*copy)(std::size_t, std::size_t, T &)) :
        pnum(N), pval(N), weight(N), log_weight(N),
        copy_particle(copy) {}

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return pnum;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the reference.
    T &value ()
    {
        return pval;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values, type (const T &)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the reference.
    const T &value () const
    {
        return pval;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights, type (const double *)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the pointer.
    const double *getWeightPtr () const
    {
        return weight.get();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights, type (const double *)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the pointer.
    const double *getLogWeightPtr () const
    {
        return log_weight.get();
    }

    /// \brief Set the log weights of the particle sets
    ///
    /// \param [in] new_weight New log weights
    void setLogWeight (const double *new_weight)
    {
        cblas_dcopy(pnum, new_weight, 1, log_weight, 1);
        set_weight();
    }

    /// \brief Add to the log weights of the particle sets
    ///
    /// \param [in] inc_weight Incremental log weights
    void addLogWeight (const double *inc_weight)
    {
        vdAdd(pnum, log_weight, inc_weight, log_weight);
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ESS () const
    {
        return 1 / cblas_ddot(pnum, weight, 1, weight, 1);
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    /// \param [in] rng A gsl rng object pointer
    void resample (ResampleScheme scheme, const gsl_rng *rng)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial(rng);
                break;
            case RESIDUAL :
                resample_residual(rng);
                break;
            case STRATIFIED :
                resample_stratified(rng);
                break;
            case SYSTEMATIC :
                resample_systematic(rng);
                break;
            default :
                resample_residual(rng);
        }
    }

    private :

    std::size_t pnum;
    T pval;
    vDist::internal::Buffer<double> weight;
    vDist::internal::Buffer<double> log_weight;
    void (*copy_particle) (std::size_t, std::size_t, T &);

    void set_weight ()
    {
        double max_weight = -std::numeric_limits<double>::infinity();

        for (std::size_t i = 0; i != pnum; ++i)
            max_weight = std::max(max_weight, log_weight[i]);
        for (std::size_t i = 0; i != pnum; ++i)
            log_weight[i] -= max_weight;
        vdExp(pnum, log_weight, weight);
        double sum = cblas_dasum(pnum, weight, 1);
        cblas_dscal(pnum, 1 / sum, weight, 1);
    }

    void resample_multinomial (const gsl_rng *rng)
    {
        vDist::internal::Buffer<unsigned> rep(pnum);

        gsl_ran_multinomial(rng, pnum, pnum, weight, rep);
        resample_do(rep);
    }

    void resample_residual (const gsl_rng *rng)
    {
        vDist::internal::Buffer<unsigned> rep(pnum);
        vDist::internal::Buffer<double> uweight(pnum);
        vDist::internal::Buffer<double> prob(pnum);

        vDist::dyatx(pnum, pnum, weight, 1, uweight, 1);
        vdModf(pnum, uweight, uweight, prob);
        std::size_t size = pnum;
        size -= cblas_dasum(pnum, uweight, 1);
        gsl_ran_multinomial(rng, pnum, size, prob, rep);
        for (std::size_t i = 0; i != pnum; ++i)
            rep[i] += uweight[i];
        resample_do(rep);
    }

    void resample_stratified (const gsl_rng *rng) {}
    void resample_systematic (const gsl_rng *rng) {}

    void resample_do (const unsigned *rep)
    {
        std::size_t from = 0;
        std::size_t time = 0;

        for (std::size_t to = 0; to != pnum; ++to)
        {
            if (!rep[to]) {
                // rep[to] has zero child, copy from elsewhere
                if (rep[from] - time <= 1) {
                    // only 1 child left on rep[from]
                    time = 0;
                    ++from;
                    while (rep[from] < 2)
                        // rep[from] shall has at least 2 child, 1 for itself
                        ++from;
                }
                copy_particle(from, to, pval);
                ++time;
            }
        }
        vDist::dfill(pnum, 1.0 / pnum, weight, 1);
        vDist::dfill(pnum, 0, log_weight, 1);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_PARTICLE_HPP
<commit_msg>minore performance tuneing<commit_after>#ifndef V_SMC_PARTICLE_HPP
#define V_SMC_PARTICLE_HPP

#include <algorithm>
#include <limits>
#include <cstddef>
#include <mkl_vml.h>
#include <gsl/gsl_cblas.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <vDist/utilities/buffer.hpp>
#include <vDist/utilities/eblas.hpp>

namespace vSMC {

/// Resample scheme
enum ResampleScheme {MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <class T>
class Particle
{
    public :

    /// \brief Particle does not have a default constructor
    ///
    /// \param N The number of particles
    /// \param copy A pointer to the function that can copy particle from one
    /// position to another position
    Particle (std::size_t N, void (*copy)(std::size_t, std::size_t, T &)) :
        pnum(N), pval(N), weight(N), log_weight(N), rep(N),
        copy_particle(copy) {}

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return pnum;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the reference.
    T &value ()
    {
        return pval;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values, type (const T &)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the reference.
    const T &value () const
    {
        return pval;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights, type (const double *)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the pointer.
    const double *getWeightPtr () const
    {
        return weight.get();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights, type (const double *)
    /// \note Any operations that change the state of the particle (e.g.,
    /// setting log weights or resampling) set can invalidate the pointer.
    const double *getLogWeightPtr () const
    {
        return log_weight.get();
    }

    /// \brief Set the log weights of the particle sets
    ///
    /// \param [in] new_weight New log weights
    void setLogWeight (const double *new_weight)
    {
        cblas_dcopy(pnum, new_weight, 1, log_weight, 1);
        set_weight();
    }

    /// \brief Add to the log weights of the particle sets
    ///
    /// \param [in] inc_weight Incremental log weights
    void addLogWeight (const double *inc_weight)
    {
        vdAdd(pnum, log_weight, inc_weight, log_weight);
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ESS () const
    {
        return 1 / cblas_ddot(pnum, weight, 1, weight, 1);
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    /// \param [in] rng A gsl rng object pointer
    void resample (ResampleScheme scheme, const gsl_rng *rng)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial(rng);
                break;
            case RESIDUAL :
                resample_residual(rng);
                break;
            case STRATIFIED :
                resample_stratified(rng);
                break;
            case SYSTEMATIC :
                resample_systematic(rng);
                break;
            default :
                resample_residual(rng);
        }
    }

    private :

    std::size_t pnum;
    T pval;
    vDist::internal::Buffer<double> weight;
    vDist::internal::Buffer<double> log_weight;
    vDist::internal::Buffer<unsigned> rep;
    void (*copy_particle) (std::size_t, std::size_t, T &);

    void set_weight ()
    {
        double max_weight = -std::numeric_limits<double>::infinity();

        for (std::size_t i = 0; i != pnum; ++i)
            max_weight = std::max(max_weight, log_weight[i]);
        for (std::size_t i = 0; i != pnum; ++i)
            log_weight[i] -= max_weight;
        vdExp(pnum, log_weight, weight);
        double sum = cblas_dasum(pnum, weight, 1);
        cblas_dscal(pnum, 1 / sum, weight, 1);
    }

    void resample_multinomial (const gsl_rng *rng)
    {
        gsl_ran_multinomial(rng, pnum, pnum, weight, rep);
        resample_do();
    }

    void resample_residual (const gsl_rng *rng)
    {
        /// \internal Reuse weight and log_weight.
        /// weight: act as the fractional part of N * weight.
        /// log_weight: act as the integral part of N * weight.
        /// They all will be reset to equal weights after resampling.
        /// So it is safe to modify them here.
        vDist::dyatx(pnum, pnum, weight, 1, log_weight, 1);
        vdModf(pnum, log_weight, log_weight, weight);
        std::size_t size = pnum;
        size -= cblas_dasum(pnum, log_weight, 1);
        gsl_ran_multinomial(rng, pnum, size, weight, rep);
        for (std::size_t i = 0; i != pnum; ++i)
            rep[i] += log_weight[i];
        resample_do();
    }

    void resample_stratified (const gsl_rng *rng) {}
    void resample_systematic (const gsl_rng *rng) {}

    void resample_do ()
    {
        std::size_t from = 0;
        std::size_t time = 0;

        for (std::size_t to = 0; to != pnum; ++to)
        {
            if (!rep[to]) {
                // rep[to] has zero child, copy from elsewhere
                if (rep[from] - time <= 1) {
                    // only 1 child left on rep[from]
                    time = 0;
                    ++from;
                    while (rep[from] < 2)
                        // rep[from] shall has at least 2 child, 1 for itself
                        ++from;
                }
                copy_particle(from, to, pval);
                ++time;
            }
        }
        vDist::dfill(pnum, 1.0 / pnum, weight, 1);
        vDist::dfill(pnum, 0, log_weight, 1);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_PARTICLE_HPP
<|endoftext|>


<commit_before>#ifndef MINIASCAPE_STEPPER
#define MINIASCAPE_STEPPER
#include "core/World.hpp"
#include "core/Rule.hpp"
#include "util/zip_iterator.hpp"

namespace miniascape
{

template<typename T_traits>
class SynchronousStepper
{
  public:
    using traits_type = T_traits;
    using time_type   = typename traits_type::time_type;
    using state_type  = typename traits_type::state_type;
    using cell_type   = typename traits_type::cell_type;
    using rule_type   = RuleBase<traits_type>;
    using world_type  = World<traits_type>;

    SynchronousStepper() = default;
   ~SynchronousStepper() = default;
    time_type step(world_type& world, const rule_type& rule) const;
};

template<typename T_traits>
typename SynchronousStepper<T_traits>::time_type
SynchronousStepper<T_traits>::step(world_type& world, const rule_type& rule) const
{
    std::vector<state_type> temp(world.size());

    for(auto cell = make_zip(world.cbegin(), temp.begin());
            cell != make_zip(world.cend(),   temp.end()); ++cell)
        *get<1>(cell) = rule.step(**get<0>(cell));

    for(auto cell = make_zip(world.begin(), temp.begin());
            cell != make_zip(world.end(),   temp.end()); ++cell)
        (*get<0>(cell))->state = *get<1>(cell);

    return rule.delta_t();
}

}

#endif /* MINIASCAPE_STEPPER */
<commit_msg>add asynchronous stepper<commit_after>#ifndef MINIASCAPE_STEPPER
#define MINIASCAPE_STEPPER
#include "core/World.hpp"
#include "core/Rule.hpp"
#include "core/RandomNumberGenerator.hpp"
#include "util/zip_iterator.hpp"

namespace miniascape
{

template<typename T_traits>
class SynchronousStepper
{
  public:
    using traits_type = T_traits;
    using time_type   = typename traits_type::time_type;
    using state_type  = typename traits_type::state_type;
    using cell_type   = typename traits_type::cell_type;
    using rule_type   = RuleBase<traits_type>;
    using world_type  = World<traits_type>;

    SynchronousStepper() = default;
   ~SynchronousStepper() = default;
    time_type step(world_type& world, const rule_type& rule) const;
};

template<typename T_traits>
typename SynchronousStepper<T_traits>::time_type
SynchronousStepper<T_traits>::step(world_type& world, const rule_type& rule) const
{
    std::vector<state_type> temp(world.size());

    for(auto cell = make_zip(world.cbegin(), temp.begin());
            cell != make_zip(world.cend(),   temp.end()); ++cell)
        *get<1>(cell) = rule.step(**get<0>(cell));

    for(auto cell = make_zip(world.begin(), temp.begin());
            cell != make_zip(world.end(),   temp.end()); ++cell)
        (*get<0>(cell))->state = *get<1>(cell);

    return rule.delta_t();
}

template<typename T_traits>
class AsynchronousStepper
{
  public:
    using traits_type = T_traits;
    using time_type   = typename traits_type::time_type;
    using state_type  = typename traits_type::state_type;
    using cell_type   = typename traits_type::cell_type;
    using rule_type   = RuleBase<traits_type>;
    using world_type  = World<traits_type>;

    AsynchronousStepper() = default;
   ~AsynchronousStepper() = default;
    time_type step(world_type& world, const rule_type& rule) const;

    const std::shared_ptr<RandomNumberGenerator> rng_;
};

template<typename T_traits>
typename AsynchronousStepper<T_traits>::time_type
AsynchronousStepper<T_traits>::step(world_type& world, const rule_type& rule) const
{
    std::size_t size = world.size();
    std::size_t cell_idx = rng_->uniform_int<std::size_t>(0, size);
    world.at(cell_idx)->state = rule.step(*(world.at(cell_idx)));

    return rule.delta_t();
}

}

#endif /* MINIASCAPE_STEPPER */
<|endoftext|>


<commit_before>/*++

Module Name:

    FASTA.cpp

Abstract:

    FASTA reader

Authors:

    Bill Bolosky, August, 2011

Environment:

    User mode service.

Revision History:

    Adapted from Matei Zaharia's Scala implementation.

--*/

#include "stdafx.h"
#include "Compat.h"
#include "FASTA.h"
#include "Error.h"
#include "exit.h"
#include "Util.h"

using namespace std;

    bool
IsContigALT(
	const char		*contigName,
	GenomeDistance	 contigSize,
	const char* const*opt_in_alt_names,
	int				 opt_in_alt_names_count,
	const char* const*opt_out_alt_names,
	int				 opt_out_alt_names_count,
	GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT)
{

	for (int i = 0; i < opt_out_alt_names_count; i++) {
		if (!_stricmp(opt_out_alt_names[i], contigName)) {
			return false;
		}
	} // opt out

	if (contigSize <= maxSizeForAutomaticALT) {
		return true;
	}

	for (int i = 0; i < opt_in_alt_names_count; i++) {
		if (!_stricmp(opt_in_alt_names[i], contigName)) {
			return true;
		} // match
	} // opt in

    if (autoALT && ((strlen(contigName) > 4 && !_stricmp(contigName + strlen(contigName) - 4, "_alt")) ||
                    (strlen(contigName) > 3 && (contigName[0] == 'H' || contigName[0] == 'h') && (contigName[1] == 'L' || contigName[1] == 'l') && (contigName[2] == 'A' || contigName[2] == 'a') && contigName[3] == '-')))  {
        return true;
    }

    return false;
} // MarkALTContigIfAppropriate

//
// There are several ways of specifying ALT contigs.  There is an opt-in list of ALTs, an opt-out list of regular chromosomes (these must be mutually
// exclusive), and a size cutoff below which is contig is an ALT.  The opt-in and opt-out lists supersede the size cutoff.
//

struct ContigLine {
    char* bases;
    ContigLine* next;

    ContigLine() {
        bases = NULL;
        next = NULL;
    }
};

struct RawContigData {
    ContigLine* lines;
    ContigLine* lastLine;
    GenomeDistance totalSize;
    char* name;
    RawContigData* next;
    int contigNumber;   // Where this contig is in the original FASTA file

    RawContigData() {
        lines = NULL;
        lastLine = NULL;
        totalSize = 0;
        name = NULL;
        next = NULL;
        contigNumber = -1;
    }

    void addLine(const char* bases) {
        ContigLine*line = new ContigLine();
        size_t size = strlen(bases) + 1;
        line->bases = new char[size];
        strncpy(line->bases, bases, size);
        if (lines == NULL) {
            lines = lastLine = line;
        } else {
            lastLine->next = line;
            lastLine = line;
        }
    } // addLine

    ~RawContigData() {
        delete[] name;

        while (lines != NULL) {
            ContigLine* toDelete = lines;
            lines = lines->next;
            delete[] toDelete->bases;
            delete toDelete;
        }
    }
}; // RawContigData

   void
AddRawContigToList(
    RawContigData*   currentContig,
    RawContigData**  altContigs,
    RawContigData**  regularContigs,
    const char* const* opt_in_alt_names,
    int				 opt_in_alt_names_count,
    const char* const* opt_out_alt_names,
    int				 opt_out_alt_names_count,
    GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT)
{
    if (IsContigALT(currentContig->name, currentContig->totalSize, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names,
        opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT)) {
        currentContig->next = *altContigs;
        *altContigs = currentContig;
    }  else {
        currentContig->next = *regularContigs;
        *regularContigs = currentContig;
    }
}

   void
AddContigToGenome(
    RawContigData   *contig,
    Genome          *genome,
    char            *paddingBuffer)
{
    genome->addData(paddingBuffer);
    genome->startContig(contig->name, contig->contigNumber);

    for (ContigLine* line = contig->lines; NULL != line; line = line->next) {
        genome->addData(line->bases);
    }
} // AddContigToGenome

   void
ReverseContigList(RawContigData** head)
{
    if (*head == NULL) {
        return;
    }

    RawContigData* cur = *head;
    RawContigData* prev = NULL;

    for (;;) {
        RawContigData* next = cur->next;
        cur->next = prev;

        if (next == NULL) {
            *head = cur;
            return;
        }

        prev = cur;
        cur = next;
    } // for ever
} // ReverseContigList

    const Genome *
ReadFASTAGenome(
	const char		*fileName,
	const char		*pieceNameTerminatorCharacters,
	bool			 spaceIsAPieceNameTerminator,
	unsigned		 chromosomePaddingSize,
	const char* const*opt_in_alt_names,
	int				 opt_in_alt_names_count,
	const char* const*opt_out_alt_names,
	int				 opt_out_alt_names_count,
	GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT,
    char            **alt_liftover_contig_names,
	unsigned		*alt_liftover_contig_flags,
	char			**alt_liftover_proj_contig_names,
	unsigned		*alt_liftover_proj_contig_offsets,
	char			**alt_liftover_proj_cigar,
	int				 alt_liftover_count)
{
    //
    // We need to know a bound on the size of the genome before we create the Genome object.
    // A bound is the number of bytes in the FASTA file, because we store at most one base per
    // byte. We count the bytes as we read them rather than getting the file size so that
    // we can deal with inputs that are redirected to pipes.
    //
    _int64 fileSize = 0;
    bool isValidGenomeCharacter[256];

    for (int i = 0; i < 256; i++) {
        isValidGenomeCharacter[i] = false;
    }

    isValidGenomeCharacter['A'] = isValidGenomeCharacter['T'] = isValidGenomeCharacter['C'] = isValidGenomeCharacter['G'] = isValidGenomeCharacter['N'] = true;
    isValidGenomeCharacter['a'] = isValidGenomeCharacter['t'] = isValidGenomeCharacter['c'] = isValidGenomeCharacter['g'] = isValidGenomeCharacter['n'] = true;

    FILE *fastaFile = fopen(fileName, "r");
    if (fastaFile == NULL) {
        WriteErrorMessage("Unable to open FASTA file '%s' (even though we already got its size)\n",fileName);
        return NULL;
    }

    int lineBufferSize = 0;
    char *lineBuffer;

    //
    // Read in the raw data and split it up by chromosome.  We're going to rearrange it to put the ALT chromosomes at the end so that it's
    // quick to test whether a GenomeLocation is ALT or not.
    //
    unsigned nContigs = 0;

    RawContigData* regularContigs = NULL;
    RawContigData* altContigs = NULL;
    RawContigData* currentContig = NULL;

    bool warningIssued = false;
    bool inAContig = false;

    int nextContigNumber = 0;

    while (NULL != reallocatingFgets(&lineBuffer, &lineBufferSize, fastaFile)) {
        fileSize += strlen(lineBuffer);
        if (lineBuffer[0] == '>') {
            nContigs++;

            if (inAContig) {
                AddRawContigToList(currentContig, &altContigs, &regularContigs, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names, opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT);
			}

            currentContig = new RawContigData();

            inAContig = true;

            //
            // Now supply the contig name.
            //
            if (NULL != pieceNameTerminatorCharacters) {
                for (int i = 0; i < strlen(pieceNameTerminatorCharacters); i++) {
                    char *terminator = strchr(lineBuffer+1, pieceNameTerminatorCharacters[i]);
                    if (NULL != terminator) {
                        *terminator = '\0';
                    }
                }
            }

            if (spaceIsAPieceNameTerminator) {
                char *terminator = strchr(lineBuffer, ' ');
                if (NULL != terminator) {
                    *terminator = '\0';
                }
                terminator = strchr(lineBuffer, '\t');
                if (NULL != terminator) {
                    *terminator = '\0';
                }
            }

            char *terminator = strchr(lineBuffer, '\n');
            if (NULL != terminator) {
                *terminator = '\0';
            }

            terminator = strchr(lineBuffer, '\r');
            if (NULL != terminator) {
                *terminator = '\0';
            }

            size_t nameLength = strlen(lineBuffer + 1) + 1;

            currentContig->name = new char[nameLength];
            strncpy(currentContig->name, lineBuffer + 1, nameLength);
            currentContig->contigNumber = nextContigNumber;
            nextContigNumber++;

        } else {
            if (!inAContig) {
                WriteErrorMessage("\nFASTA file doesn't begin with a contig name (i.e., the first line doesn't start with '>').\n");
                soft_exit(1);
            }

            //
            // Convert it to upper case and truncate the newline before adding it to the genome.
            //

            char *newline = strchr(lineBuffer, '\n');
            if (NULL != newline) {
                *newline = 0;
            }

            size_t lineLen = strlen(lineBuffer);

			for (unsigned i = 0; i < lineLen; i++) {
              lineBuffer[i] = toupper(lineBuffer[i]);
            }

			currentContig->totalSize += lineLen;

			for (unsigned i = 0; i < lineLen; i++) {
                if (!isValidGenomeCharacter[(unsigned char)lineBuffer[i]]) {
                    if (!warningIssued) {
                        WriteErrorMessage("\nFASTA file contained a character that's not a valid base (or N): '%c', full line '%s'; \nconverting to 'N'.  This may happen again, but there will be no more warnings.\n", lineBuffer[i], lineBuffer);
                        warningIssued = true;
                    }
                    lineBuffer[i] = 'N';
                }
            }

            currentContig->addLine(lineBuffer);
        }
    }

	if (!inAContig) {
		WriteErrorMessage("The FASTA file was empty.");
		return NULL;
	}

    AddRawContigToList(currentContig, &altContigs, &regularContigs, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names, opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT);

    //
    // AddRawContigToList reversed them.  Reverse them again so that they're in the same order as the FASTA, except that all ALTs follow all non-ALTs.
    // That's necessary to have the test for ALT be a simple comparison.  We fix that at sort time so they come out in the original order.
    //
    ReverseContigList(&altContigs);
    ReverseContigList(&regularContigs);

    Genome* genome = new Genome(fileSize + ((_int64)nContigs + 1) * (size_t)chromosomePaddingSize, fileSize + ((_int64)nContigs + 1) * (size_t)chromosomePaddingSize, chromosomePaddingSize, nContigs + 1);

    char* paddingBuffer = new char[(GenomeDistance)chromosomePaddingSize + 1];
    for (unsigned i = 0; i < chromosomePaddingSize; i++) {
        paddingBuffer[i] = 'n';
    }
    paddingBuffer[chromosomePaddingSize] = '\0';

    while (regularContigs != NULL) {
        AddContigToGenome(regularContigs, genome, paddingBuffer);
        RawContigData* toDelete = regularContigs;
        regularContigs = regularContigs->next;
        delete toDelete;
    }

    while (altContigs != NULL) {
        AddContigToGenome(altContigs, genome, paddingBuffer);
        genome->markContigALT(altContigs->name);
        if (alt_liftover_count > 0) {
            genome->markContigLiftover(altContigs->name, alt_liftover_contig_names, alt_liftover_contig_flags, alt_liftover_proj_contig_names, alt_liftover_proj_contig_offsets, alt_liftover_proj_cigar, alt_liftover_count);
        }
        RawContigData* toDelete = altContigs;
        altContigs = altContigs->next;
        delete toDelete;
    }

    //
    // And finally add padding at the end of the genome.
    //
    genome->addData(paddingBuffer);
    genome->fillInContigLengths();
    genome->sortContigsByName();
    genome->setUpContigNumbersByOriginalOrder();

    fclose(fastaFile);
    delete [] paddingBuffer;
    delete [] lineBuffer;
    return genome;
}
<commit_msg>Fix error message<commit_after>/*++

Module Name:

    FASTA.cpp

Abstract:

    FASTA reader

Authors:

    Bill Bolosky, August, 2011

Environment:

    User mode service.

Revision History:

    Adapted from Matei Zaharia's Scala implementation.

--*/

#include "stdafx.h"
#include "Compat.h"
#include "FASTA.h"
#include "Error.h"
#include "exit.h"
#include "Util.h"

using namespace std;

    bool
IsContigALT(
	const char		*contigName,
	GenomeDistance	 contigSize,
	const char* const*opt_in_alt_names,
	int				 opt_in_alt_names_count,
	const char* const*opt_out_alt_names,
	int				 opt_out_alt_names_count,
	GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT)
{

	for (int i = 0; i < opt_out_alt_names_count; i++) {
		if (!_stricmp(opt_out_alt_names[i], contigName)) {
			return false;
		}
	} // opt out

	if (contigSize <= maxSizeForAutomaticALT) {
		return true;
	}

	for (int i = 0; i < opt_in_alt_names_count; i++) {
		if (!_stricmp(opt_in_alt_names[i], contigName)) {
			return true;
		} // match
	} // opt in

    if (autoALT && ((strlen(contigName) > 4 && !_stricmp(contigName + strlen(contigName) - 4, "_alt")) ||
                    (strlen(contigName) > 3 && (contigName[0] == 'H' || contigName[0] == 'h') && (contigName[1] == 'L' || contigName[1] == 'l') && (contigName[2] == 'A' || contigName[2] == 'a') && contigName[3] == '-')))  {
        return true;
    }

    return false;
} // MarkALTContigIfAppropriate

//
// There are several ways of specifying ALT contigs.  There is an opt-in list of ALTs, an opt-out list of regular chromosomes (these must be mutually
// exclusive), and a size cutoff below which is contig is an ALT.  The opt-in and opt-out lists supersede the size cutoff.
//

struct ContigLine {
    char* bases;
    ContigLine* next;

    ContigLine() {
        bases = NULL;
        next = NULL;
    }
};

struct RawContigData {
    ContigLine* lines;
    ContigLine* lastLine;
    GenomeDistance totalSize;
    char* name;
    RawContigData* next;
    int contigNumber;   // Where this contig is in the original FASTA file

    RawContigData() {
        lines = NULL;
        lastLine = NULL;
        totalSize = 0;
        name = NULL;
        next = NULL;
        contigNumber = -1;
    }

    void addLine(const char* bases) {
        ContigLine*line = new ContigLine();
        size_t size = strlen(bases) + 1;
        line->bases = new char[size];
        strncpy(line->bases, bases, size);
        if (lines == NULL) {
            lines = lastLine = line;
        } else {
            lastLine->next = line;
            lastLine = line;
        }
    } // addLine

    ~RawContigData() {
        delete[] name;

        while (lines != NULL) {
            ContigLine* toDelete = lines;
            lines = lines->next;
            delete[] toDelete->bases;
            delete toDelete;
        }
    }
}; // RawContigData

   void
AddRawContigToList(
    RawContigData*   currentContig,
    RawContigData**  altContigs,
    RawContigData**  regularContigs,
    const char* const* opt_in_alt_names,
    int				 opt_in_alt_names_count,
    const char* const* opt_out_alt_names,
    int				 opt_out_alt_names_count,
    GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT)
{
    if (IsContigALT(currentContig->name, currentContig->totalSize, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names,
        opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT)) {
        currentContig->next = *altContigs;
        *altContigs = currentContig;
    }  else {
        currentContig->next = *regularContigs;
        *regularContigs = currentContig;
    }
}

   void
AddContigToGenome(
    RawContigData   *contig,
    Genome          *genome,
    char            *paddingBuffer)
{
    genome->addData(paddingBuffer);
    genome->startContig(contig->name, contig->contigNumber);

    for (ContigLine* line = contig->lines; NULL != line; line = line->next) {
        genome->addData(line->bases);
    }
} // AddContigToGenome

   void
ReverseContigList(RawContigData** head)
{
    if (*head == NULL) {
        return;
    }

    RawContigData* cur = *head;
    RawContigData* prev = NULL;

    for (;;) {
        RawContigData* next = cur->next;
        cur->next = prev;

        if (next == NULL) {
            *head = cur;
            return;
        }

        prev = cur;
        cur = next;
    } // for ever
} // ReverseContigList

    const Genome *
ReadFASTAGenome(
	const char		*fileName,
	const char		*pieceNameTerminatorCharacters,
	bool			 spaceIsAPieceNameTerminator,
	unsigned		 chromosomePaddingSize,
	const char* const*opt_in_alt_names,
	int				 opt_in_alt_names_count,
	const char* const*opt_out_alt_names,
	int				 opt_out_alt_names_count,
	GenomeDistance	 maxSizeForAutomaticALT,
    bool             autoALT,
    char            **alt_liftover_contig_names,
	unsigned		*alt_liftover_contig_flags,
	char			**alt_liftover_proj_contig_names,
	unsigned		*alt_liftover_proj_contig_offsets,
	char			**alt_liftover_proj_cigar,
	int				 alt_liftover_count)
{
    //
    // We need to know a bound on the size of the genome before we create the Genome object.
    // A bound is the number of bytes in the FASTA file, because we store at most one base per
    // byte. We count the bytes as we read them rather than getting the file size so that
    // we can deal with inputs that are redirected to pipes.
    //
    _int64 fileSize = 0;
    bool isValidGenomeCharacter[256];

    for (int i = 0; i < 256; i++) {
        isValidGenomeCharacter[i] = false;
    }

    isValidGenomeCharacter['A'] = isValidGenomeCharacter['T'] = isValidGenomeCharacter['C'] = isValidGenomeCharacter['G'] = isValidGenomeCharacter['N'] = true;
    isValidGenomeCharacter['a'] = isValidGenomeCharacter['t'] = isValidGenomeCharacter['c'] = isValidGenomeCharacter['g'] = isValidGenomeCharacter['n'] = true;

    FILE *fastaFile = fopen(fileName, "r");
    if (fastaFile == NULL) {
        WriteErrorMessage("Unable to open FASTA file '%s' (does it exist and do you have permission to open it?)\n",fileName);
        return NULL;
    }

    int lineBufferSize = 0;
    char *lineBuffer;

    //
    // Read in the raw data and split it up by chromosome.  We're going to rearrange it to put the ALT chromosomes at the end so that it's
    // quick to test whether a GenomeLocation is ALT or not.
    //
    unsigned nContigs = 0;

    RawContigData* regularContigs = NULL;
    RawContigData* altContigs = NULL;
    RawContigData* currentContig = NULL;

    bool warningIssued = false;
    bool inAContig = false;

    int nextContigNumber = 0;

    while (NULL != reallocatingFgets(&lineBuffer, &lineBufferSize, fastaFile)) {
        fileSize += strlen(lineBuffer);
        if (lineBuffer[0] == '>') {
            nContigs++;

            if (inAContig) {
                AddRawContigToList(currentContig, &altContigs, &regularContigs, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names, opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT);
			}

            currentContig = new RawContigData();

            inAContig = true;

            //
            // Now supply the contig name.
            //
            if (NULL != pieceNameTerminatorCharacters) {
                for (int i = 0; i < strlen(pieceNameTerminatorCharacters); i++) {
                    char *terminator = strchr(lineBuffer+1, pieceNameTerminatorCharacters[i]);
                    if (NULL != terminator) {
                        *terminator = '\0';
                    }
                }
            }

            if (spaceIsAPieceNameTerminator) {
                char *terminator = strchr(lineBuffer, ' ');
                if (NULL != terminator) {
                    *terminator = '\0';
                }
                terminator = strchr(lineBuffer, '\t');
                if (NULL != terminator) {
                    *terminator = '\0';
                }
            }

            char *terminator = strchr(lineBuffer, '\n');
            if (NULL != terminator) {
                *terminator = '\0';
            }

            terminator = strchr(lineBuffer, '\r');
            if (NULL != terminator) {
                *terminator = '\0';
            }

            size_t nameLength = strlen(lineBuffer + 1) + 1;

            currentContig->name = new char[nameLength];
            strncpy(currentContig->name, lineBuffer + 1, nameLength);
            currentContig->contigNumber = nextContigNumber;
            nextContigNumber++;

        } else {
            if (!inAContig) {
                WriteErrorMessage("\nFASTA file doesn't begin with a contig name (i.e., the first line doesn't start with '>').\n");
                soft_exit(1);
            }

            //
            // Convert it to upper case and truncate the newline before adding it to the genome.
            //

            char *newline = strchr(lineBuffer, '\n');
            if (NULL != newline) {
                *newline = 0;
            }

            size_t lineLen = strlen(lineBuffer);

			for (unsigned i = 0; i < lineLen; i++) {
              lineBuffer[i] = toupper(lineBuffer[i]);
            }

			currentContig->totalSize += lineLen;

			for (unsigned i = 0; i < lineLen; i++) {
                if (!isValidGenomeCharacter[(unsigned char)lineBuffer[i]]) {
                    if (!warningIssued) {
                        WriteErrorMessage("\nFASTA file contained a character that's not a valid base (or N): '%c', full line '%s'; \nconverting to 'N'.  This may happen again, but there will be no more warnings.\n", lineBuffer[i], lineBuffer);
                        warningIssued = true;
                    }
                    lineBuffer[i] = 'N';
                }
            }

            currentContig->addLine(lineBuffer);
        }
    }

	if (!inAContig) {
		WriteErrorMessage("The FASTA file was empty.");
		return NULL;
	}

    AddRawContigToList(currentContig, &altContigs, &regularContigs, opt_in_alt_names, opt_in_alt_names_count, opt_out_alt_names, opt_out_alt_names_count, maxSizeForAutomaticALT, autoALT);

    //
    // AddRawContigToList reversed them.  Reverse them again so that they're in the same order as the FASTA, except that all ALTs follow all non-ALTs.
    // That's necessary to have the test for ALT be a simple comparison.  We fix that at sort time so they come out in the original order.
    //
    ReverseContigList(&altContigs);
    ReverseContigList(&regularContigs);

    Genome* genome = new Genome(fileSize + ((_int64)nContigs + 1) * (size_t)chromosomePaddingSize, fileSize + ((_int64)nContigs + 1) * (size_t)chromosomePaddingSize, chromosomePaddingSize, nContigs + 1);

    char* paddingBuffer = new char[(GenomeDistance)chromosomePaddingSize + 1];
    for (unsigned i = 0; i < chromosomePaddingSize; i++) {
        paddingBuffer[i] = 'n';
    }
    paddingBuffer[chromosomePaddingSize] = '\0';

    while (regularContigs != NULL) {
        AddContigToGenome(regularContigs, genome, paddingBuffer);
        RawContigData* toDelete = regularContigs;
        regularContigs = regularContigs->next;
        delete toDelete;
    }

    while (altContigs != NULL) {
        AddContigToGenome(altContigs, genome, paddingBuffer);
        genome->markContigALT(altContigs->name);
        if (alt_liftover_count > 0) {
            genome->markContigLiftover(altContigs->name, alt_liftover_contig_names, alt_liftover_contig_flags, alt_liftover_proj_contig_names, alt_liftover_proj_contig_offsets, alt_liftover_proj_cigar, alt_liftover_count);
        }
        RawContigData* toDelete = altContigs;
        altContigs = altContigs->next;
        delete toDelete;
    }

    //
    // And finally add padding at the end of the genome.
    //
    genome->addData(paddingBuffer);
    genome->fillInContigLengths();
    genome->sortContigsByName();
    genome->setUpContigNumbersByOriginalOrder();

    fclose(fastaFile);
    delete [] paddingBuffer;
    delete [] lineBuffer;
    return genome;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/**
 * @file        test/service/monitor/entriesmanager.cpp
 * @author      Aleksander Zdyb <a.zdyb@samsung.com>
 * @version     1.0
 * @brief       Tests of EntriesManager
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <ctime>

#include <service/monitor/EntriesManager.h>
#include <common/types/MonitorEntry.h>

#include "../../helpers.h"

using namespace Cynara;

namespace {

typedef std::vector<MonitorEntry> MonitorEntries;

} /* namespace anonymous */

TEST(EntriesManager, oneClient) {
    EntriesManager entriesManager;
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(-1, filledClient);
}

TEST(EntriesManager, oneClientNotFilled) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(-1, filledClient);
}

TEST(EntriesManager, oneClientFilled) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(666, filledClient);
}

TEST(EntriesManager, oneClientModified) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 5);

    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    ASSERT_EQ(-1, entriesManager.getFilledClientId());

    entriesManager.modifyClient(666, 3);
    ASSERT_EQ(666, entriesManager.getFilledClientId());
}

TEST(EntriesManager, oneClientRemoved) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);

    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    ASSERT_EQ(666, entriesManager.getFilledClientId());

    entriesManager.removeClient(666);
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
}

TEST(EntriesManager, fetchForOne) {
    EntriesManager entriesManager;
    MonitorEntries expectedEntries;

    expectedEntries.push_back({{"c1", "u1", "p1"}, 0, {0, 0}});
    expectedEntries.push_back({{"c2", "u2", "p2"}, 0, {0, 0}});
    expectedEntries.push_back({{"c3", "u3", "p3"}, 0, {0, 0}});

    entriesManager.addClient(666, 3);

    entriesManager.addEntry(expectedEntries.at(0));
    entriesManager.addEntry(expectedEntries.at(1));
    entriesManager.addEntry(expectedEntries.at(2));

    auto actualEntries = entriesManager.fetchEntriesForClient(666);
    ASSERT_EQ(expectedEntries, actualEntries);
}

TEST(EntriesManager, fetchForMore) {
    EntriesManager entriesManager;
    MonitorEntries expectedEntries;

    expectedEntries.push_back({{"c1", "u1", "p1"}, 0, {0, 0}});
    expectedEntries.push_back({{"c2", "u2", "p2"}, 0, {0, 0}});
    expectedEntries.push_back({{"c3", "u3", "p3"}, 0, {0, 0}});
    expectedEntries.push_back({{"c4", "u4", "p4"}, 0, {0, 0}});

    entriesManager.addClient(666, 3);
    entriesManager.addClient(777, 4);

    entriesManager.addEntry(expectedEntries.at(0));
    entriesManager.addEntry(expectedEntries.at(1));
    entriesManager.addEntry(expectedEntries.at(2));

    // 666 should be filled as they are waiting for only 3 entries
    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_FALSE(entriesManager.isClientFilled(777));

    // 666 should get their 3 entries, then be unregistered
    auto actualEntries666 = entriesManager.fetchEntriesForClient(666);
    ASSERT_EQ(actualEntries666, Helpers::sliced<MonitorEntries>(expectedEntries.begin(), 3));
    ASSERT_FALSE(entriesManager.isClientFilled(666));

    // Add one more entry and assert 777 is filled
    entriesManager.addEntry(expectedEntries.at(3));
    ASSERT_TRUE(entriesManager.isClientFilled(777));
    auto actualEntries777 = entriesManager.fetchEntriesForClient(777);
    ASSERT_EQ(actualEntries777, expectedEntries);
    ASSERT_FALSE(entriesManager.isClientFilled(777));
}

TEST(EntriesManager, user1) {
    EntriesManager entriesManager;
    ASSERT_FALSE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
}

TEST(EntriesManager, user2) {
    EntriesManager entriesManager;
    ASSERT_FALSE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
    ASSERT_TRUE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.isClientFilled(666));
}

TEST(EntriesManager, user3) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    ASSERT_FALSE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_EQ(666, entriesManager.getFilledClientId());
    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry2));
}

TEST(EntriesManager, user4) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));
    ASSERT_TRUE(entriesManager.addClient(777, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_TRUE(entriesManager.isClientFilled(777));

    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_TRUE(entriesManager.isClientFilled(777));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry1, entry2));
}

TEST(EntriesManager, user5) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 1));

    ASSERT_TRUE(entriesManager.addEntry(entry1));

    ASSERT_TRUE(entriesManager.addClient(777, 2))
                        ;
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));

    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry2, entry3));
}

TEST(EntriesManager, user6) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));

    ASSERT_TRUE(entriesManager.addClient(777, 2))
                        ;
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry2, entry3));
}

TEST(EntriesManager, user7) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));

    ASSERT_TRUE(entriesManager.modifyClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry3));
    ASSERT_TRUE(entriesManager.addEntry(entry4));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry3, entry4));
}

TEST(EntriesManager, user8) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));
    ASSERT_TRUE(entriesManager.addClient(777, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_TRUE(entriesManager.modifyClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry3));
    ASSERT_TRUE(entriesManager.addEntry(entry4));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry3, entry4));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry1, entry2));
}

TEST(EntriesManager, user9) {
    using ::testing::ElementsAre;
    using ::testing::IsEmpty;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_FALSE(entriesManager.addEntry(entry3));
    ASSERT_FALSE(entriesManager.addEntry(entry4));

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), IsEmpty());
}
<commit_msg>Add flush tests for EntriesManager<commit_after>/*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/**
 * @file        test/service/monitor/entriesmanager.cpp
 * @author      Aleksander Zdyb <a.zdyb@samsung.com>
 * @version     1.0
 * @brief       Tests of EntriesManager
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <ctime>

#include <service/monitor/EntriesManager.h>
#include <common/types/MonitorEntry.h>

#include "../../helpers.h"

using namespace Cynara;

namespace {

typedef std::vector<MonitorEntry> MonitorEntries;

} /* namespace anonymous */

TEST(EntriesManager, oneClient) {
    EntriesManager entriesManager;
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(-1, filledClient);
}

TEST(EntriesManager, oneClientNotFilled) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(-1, filledClient);
}

TEST(EntriesManager, oneClientFilled) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    auto filledClient = entriesManager.getFilledClientId();
    ASSERT_EQ(666, filledClient);
}

TEST(EntriesManager, oneClientModified) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 5);

    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    ASSERT_EQ(-1, entriesManager.getFilledClientId());

    entriesManager.modifyClient(666, 3);
    ASSERT_EQ(666, entriesManager.getFilledClientId());
}

TEST(EntriesManager, oneClientRemoved) {
    EntriesManager entriesManager;
    entriesManager.addClient(666, 3);

    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}});
    ASSERT_EQ(666, entriesManager.getFilledClientId());

    entriesManager.removeClient(666);
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
}

TEST(EntriesManager, fetchForOne) {
    EntriesManager entriesManager;
    MonitorEntries expectedEntries;

    expectedEntries.push_back({{"c1", "u1", "p1"}, 0, {0, 0}});
    expectedEntries.push_back({{"c2", "u2", "p2"}, 0, {0, 0}});
    expectedEntries.push_back({{"c3", "u3", "p3"}, 0, {0, 0}});

    entriesManager.addClient(666, 3);

    entriesManager.addEntry(expectedEntries.at(0));
    entriesManager.addEntry(expectedEntries.at(1));
    entriesManager.addEntry(expectedEntries.at(2));

    auto actualEntries = entriesManager.fetchEntriesForClient(666);
    ASSERT_EQ(expectedEntries, actualEntries);
}

TEST(EntriesManager, fetchForMore) {
    EntriesManager entriesManager;
    MonitorEntries expectedEntries;

    expectedEntries.push_back({{"c1", "u1", "p1"}, 0, {0, 0}});
    expectedEntries.push_back({{"c2", "u2", "p2"}, 0, {0, 0}});
    expectedEntries.push_back({{"c3", "u3", "p3"}, 0, {0, 0}});
    expectedEntries.push_back({{"c4", "u4", "p4"}, 0, {0, 0}});

    entriesManager.addClient(666, 3);
    entriesManager.addClient(777, 4);

    entriesManager.addEntry(expectedEntries.at(0));
    entriesManager.addEntry(expectedEntries.at(1));
    entriesManager.addEntry(expectedEntries.at(2));

    // 666 should be filled as they are waiting for only 3 entries
    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_FALSE(entriesManager.isClientFilled(777));

    // 666 should get their 3 entries, then be unregistered
    auto actualEntries666 = entriesManager.fetchEntriesForClient(666);
    ASSERT_EQ(actualEntries666, Helpers::sliced<MonitorEntries>(expectedEntries.begin(), 3));
    ASSERT_FALSE(entriesManager.isClientFilled(666));

    // Add one more entry and assert 777 is filled
    entriesManager.addEntry(expectedEntries.at(3));
    ASSERT_TRUE(entriesManager.isClientFilled(777));
    auto actualEntries777 = entriesManager.fetchEntriesForClient(777);
    ASSERT_EQ(actualEntries777, expectedEntries);
    ASSERT_FALSE(entriesManager.isClientFilled(777));
}

TEST(EntriesManager, user1) {
    EntriesManager entriesManager;
    ASSERT_FALSE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
}

TEST(EntriesManager, user2) {
    EntriesManager entriesManager;
    ASSERT_FALSE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
    ASSERT_TRUE(entriesManager.addEntry({{"c", "u", "p"}, 0, {0, 0}}));
    ASSERT_TRUE(entriesManager.isClientFilled(666));
}

TEST(EntriesManager, user3) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    ASSERT_FALSE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addClient(666, 1));
    ASSERT_FALSE(entriesManager.isClientFilled(666));
    ASSERT_EQ(-1, entriesManager.getFilledClientId());
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_EQ(666, entriesManager.getFilledClientId());
    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry2));
}

TEST(EntriesManager, user4) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));
    ASSERT_TRUE(entriesManager.addClient(777, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_TRUE(entriesManager.isClientFilled(666));
    ASSERT_TRUE(entriesManager.isClientFilled(777));

    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_TRUE(entriesManager.isClientFilled(777));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry1, entry2));
}

TEST(EntriesManager, user5) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 1));

    ASSERT_TRUE(entriesManager.addEntry(entry1));

    ASSERT_TRUE(entriesManager.addClient(777, 2))
                        ;
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));

    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry2, entry3));
}

TEST(EntriesManager, user6) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));

    ASSERT_TRUE(entriesManager.addClient(777, 2))
                        ;
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry2, entry3));
}

TEST(EntriesManager, user7) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));

    ASSERT_TRUE(entriesManager.modifyClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry3));
    ASSERT_TRUE(entriesManager.addEntry(entry4));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry3, entry4));
}

TEST(EntriesManager, user8) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));
    ASSERT_TRUE(entriesManager.addClient(777, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_TRUE(entriesManager.modifyClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry3));
    ASSERT_TRUE(entriesManager.addEntry(entry4));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry3, entry4));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(777), ElementsAre(entry1, entry2));
}

TEST(EntriesManager, user9) {
    using ::testing::ElementsAre;
    using ::testing::IsEmpty;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2));
    ASSERT_TRUE(entriesManager.removeClient(666));

    ASSERT_FALSE(entriesManager.addEntry(entry3));
    ASSERT_FALSE(entriesManager.addEntry(entry4));

    ASSERT_TRUE(entriesManager.addClient(666, 2));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), IsEmpty());
}

TEST(EntriesManager, userFlush) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 4));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));

    ASSERT_THAT(entriesManager.fetchEntriesForClient(666, true), ElementsAre(entry1, entry2, entry3));
}

TEST(EntriesManager, userFlushNone) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    ASSERT_TRUE(entriesManager.addClient(666, 4));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(666, true), ElementsAre());
}

TEST(EntriesManager, userFetchFlush) {
    using ::testing::ElementsAre;

    EntriesManager entriesManager;
    MonitorEntry entry1{{"c1", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry2{{"c2", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry3{{"c3", "u", "p"}, 0, {0, 0}};
    MonitorEntry entry4{{"c4", "u", "p"}, 0, {0, 0}};

    ASSERT_TRUE(entriesManager.addClient(666, 3));

    ASSERT_TRUE(entriesManager.addEntry(entry1));
    ASSERT_TRUE(entriesManager.addEntry(entry2));
    ASSERT_TRUE(entriesManager.addEntry(entry3));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(666), ElementsAre(entry1, entry2, entry3));

    ASSERT_TRUE(entriesManager.addEntry(entry4));
    ASSERT_TRUE(entriesManager.modifyClient(666, 3));
    ASSERT_THAT(entriesManager.fetchEntriesForClient(666, true), ElementsAre(entry4));
}
<|endoftext|>