<commit_before>//инициализация библиотек
#include <windows.h>
#include <conio.h>
#include <iostream>

//устанавливаем пространство имён
using namespace std;

//класс Sokoban, в котором описана вся игра
class Sokoban
{
private:
	//выбранный уровень
	unsigned short int lvl;
	unsigned short int boxNum;
	unsigned short int boxInPlace;

public:
	//конструктор
	Sokoban()
	{
		setLVL(1);
		menu();
	}

	//выбор уровня
	void setLVL(int level)
	{
		lvl = level;
	}

	//получение уровня
	int getLVL()
	{
		return lvl;
	}

	//изменение уровня (тут оно херовое, надо научить его двигаться в обе стороны)
	void changeLVL()
	{
		/*TODO: прописать if для нажатых клавиш влево/вправо*/
		/*Также нужно сделать так, чтобы счётчик уровней не опускался ниже 1 и не поднимался выше количества уровней*/
		unsigned short int newLVL = getLVL() + 1;
		setLVL(newLVL);
	}

	//кол-во коробок на уровне
	void setBox(int boxes)
	{
		boxNum = boxes;
	}

	//меню (тут надо будет ебаться)
	void menu()
	{

	}

	class tile
	{
	private:
		bool box;
		bool playerPos;
		bool wall;
		bool winPlace;

	public:
		//конструктор
		tile()
		{
			/*
			box = false;
			playerPos = false;
			wall = false;
			winPlace = false;
			*/

			//НАДО ПОЛУЧИТЬ НАЗВАНИЕ УРОВНЯ
			//А ДЛЯ ЭТОГО СДЕЛАТЬ ОТДЕЛЬНЫЙ ПРИВАТНЫЙ МЕТОД
			ifstream fin(lvlName);
			lvlGen();
		}

		//геттеры
		bool getBox()
		{
			return box;
		}
		bool getPlayerPos()
		{
			return playerPos;
		}
		bool getWall()
		{
			return wall;
		}
		bool getWinPlace()
		{
			return winPlace;
		}

		//сеттеры
		void setBox(bool boxState)
		{
			box = boxState;
		}
		void setPlayerPos(bool playerPosState)
		{
			playerPos = playerPosState
		}
		void setWall(bool wallState)
		{
			wall = wallState;
		}
		void setWinPlace(bool winPlaceState)
		{
			winPlace = winPlaceState;
		}

		void lvlGen()
		{
			//НАДО ПОЛУЧИТЬ НАЗВАНИЕ УРОВНЯ
			//А ДЛЯ ЭТОГО СДЕЛАТЬ ОТДЕЛЬНЫЙ ПРИВАТНЫЙ МЕТОД
			ifstream fin(lvlName);

			//в начало уровней надо поместить кол-во строк/столбцов
			fin >> rows >> columns;

			for (int i = 0; i < rows; i++)
				for (int j = 0; j < columns + 1; j++)
				{
					//считываем один символ
					tileSpec = getline(fin, 1);

					switch (tilespec)
					{
					case '#':
					{
						array[i, j].setWall(true);
					}
					case '@':
					{
						array[i, j].setBox(true);
					}
					case '+':
					{
						array[i, j].setPlayerPos(true);
					}
					case '$':
					{
						array[i, j].setWinPlace(true);
					}
					}
				}

			//СЮДА ЖЕ ВСУНУТЬ ОТРИСОВКУ УРОВНЯ
		}
	};

	class player
	{
	private:
		int PlayerCoordinateX, PlayerCoordinateY;//Координаты, где стоит игрок
		bool CanMovePlayer(int MoveInX, int MoveInY)/*Метод, который проверяет, может ли игрок двигаться влево или вправо,
								  MoveInX и MoveInY - смещение от координат героя, ожидаемый диапазон значений от -1 до +1*/
		{
			if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getWall != true)//Если там не стена
			{
				if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getBox == true &&
					(title[CoordinateX + 2 * MoveInX][CoordinateY + 2 * MoveInY].getBox != true) or (title[CoordinateX + 2 * MoveInX][CoordinateY + 2 * MoveInY].getWall != true))//Если там не две коробки или коробка+стена
					return true; //можно
				else return false;//иначе нельзя
			}
			else return false; //инача нельзя
		};

	public:
		void MovePlayer(int MoveInX, int MoveInY)/*Метод, который двигает игрка влево или вправо,
								  MoveInX и MoveInY - смещение от координат героя, ожидаемый диапазон значений от -1 до +1*/
		{
			if (player.CanMovePlayer(MoveInX, MoveInY) == true)
			{
				if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getBox() == true)
				{
					tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].setBox(false);//убрать коробку
					tile[PlayerCoordinateX + 2 * MoveInX][PlayerCoordinateY + 2 * MoveInY].setBox(true);//поставить коробку
				}
				tile[PlayerCoordinateX][PlayerCoordinateY].setPlayerPos(false);//Убрать игрока с клетки
				tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].setPlayerPos(true);//Поставить игрока на новую клетку
				PlayerCoordinateX = PlayerCoordinateX + MoveInX;//Записать новые координаты игрока
				PlayerCoordinateY = PlayerCoordinateY + MoveInY;
			}/*Сама коробка двигаться не может, поэтому нет нужны в написании метода её отдельного движения*/
		};
	};
};

void main()
{

}

/*
Легенда:
+ тип public
- тип private
*/

//Итак, что нам нужно
/*
данные:
	-счётчик уровней: lvl
	-количестов ящиков на уровне: boxNum
	-количество установленных на нужное место ящиков: boxInPlace

методы:
	конструктор: Sokoban (тут надо реализовать запуск меню, меню - отдельный подкласс)
	+выбор уровня: setLVL
	+меню: menu
	+получение уровня: getLVL (для последующего счётчика уровней)
	+смена уровня: changeLVL
	+кол-во коробок на уровне: setBox
*/

/*
Итак, появляется новый класс: tile
данные:
	-наличие коробки: box
	-позиция игрока: playerPos
	-наличие стены: wall
	-место для коробки: winPlace
методы:
	+4 геттера
	+4 сеттера
	//это для каждых данных
*/
<commit_msg>Новые комментарии кода<commit_after>//инициализация библиотек
#include <windows.h>
#include <conio.h>
#include <iostream>

//устанавливаем пространство имён
using namespace std;

//класс Sokoban, в котором описана вся игра
class Sokoban
{
private:
	//выбранный уровень
	unsigned short int lvl;
	unsigned short int boxNum;
	unsigned short int boxInPlace;

public:
	//конструктор
	Sokoban()
	{
		setLVL(1);
		menu();
	}

	//выбор уровня
	void setLVL(int level)
	{
		lvl = level;
	}

	//получение уровня
	int getLVL()
	{
		return lvl;
	}

	//изменение уровня (тут оно херовое, надо научить его двигаться в обе стороны)
	void changeLVL()
	{
		/*TODO: прописать if для нажатых клавиш влево/вправо*/
		/*Также нужно сделать так, чтобы счётчик уровней не опускался ниже 1 и не поднимался выше количества уровней*/
		unsigned short int newLVL = getLVL() + 1;
		setLVL(newLVL);
	}

	//кол-во коробок на уровне
	void setBox(int boxes)
	{
		boxNum = boxes;
	}

	//меню (тут надо будет ебаться)
	void menu()
	{

	}

	class tile
	{
	private:
		bool box;
		bool playerPos;
		bool wall;
		bool winPlace;

	public:
		//конструктор
		tile()
		{
			/*
			box = false;
			playerPos = false;
			wall = false;
			winPlace = false;
			*/

			//НАДО ПОЛУЧИТЬ НАЗВАНИЕ УРОВНЯ
			//А ДЛЯ ЭТОГО СДЕЛАТЬ ОТДЕЛЬНЫЙ ПРИВАТНЫЙ МЕТОД
			ifstream fin(lvlName);
			lvlGen();
		}

		//геттеры
		bool getBox()
		{
			return box;
		}
		bool getPlayerPos()
		{
			return playerPos;
		}
		bool getWall()
		{
			return wall;
		}
		bool getWinPlace()
		{
			return winPlace;
		}

		//сеттеры
		void setBox(bool boxState)
		{
			box = boxState;
		}
		void setPlayerPos(bool playerPosState)
		{
			playerPos = playerPosState
		}
		void setWall(bool wallState)
		{
			wall = wallState;
		}
		void setWinPlace(bool winPlaceState)
		{
			winPlace = winPlaceState;
		}

		void lvlGen()
		{
			//НАДО ПОЛУЧИТЬ НАЗВАНИЕ УРОВНЯ
			//А ДЛЯ ЭТОГО СДЕЛАТЬ ОТДЕЛЬНЫЙ ПРИВАТНЫЙ МЕТОД
			ifstream fin(lvlName);

			//в начало уровней надо поместить кол-во строк/столбцов
			fin >> rows >> columns;

			for (int i = 0; i < rows; i++)
				for (int j = 0; j < columns + 1; j++)
				{
					//считываем один символ
					tileSpec = getline(fin, 1);

					switch (tilespec)
					{
					case '#':
					{
						array[i, j].setWall(true);
					}
					case '@':
					{
						array[i, j].setBox(true);
					}
					case '+':
					{
						array[i, j].setPlayerPos(true);
					}
					case '$':
					{
						array[i, j].setWinPlace(true);
					}
					}
				}

			//СЮДА ЖЕ ВСУНУТЬ ОТРИСОВКУ УРОВНЯ
		}
	};

	class player
	{
	private:
		int PlayerCoordinateX, PlayerCoordinateY;//Координаты, где стоит игрок
		bool CanMovePlayer(int MoveInX, int MoveInY)/*Метод, который проверяет, может ли игрок двигаться влево или вправо,
								  MoveInX и MoveInY - смещение от координат героя, ожидаемый диапазон значений от -1 до +1*/
		{
			if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getWall != true)//Если там не стена
			{
				if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getBox == true &&
					(title[CoordinateX + 2 * MoveInX][CoordinateY + 2 * MoveInY].getBox != true) or (title[CoordinateX + 2 * MoveInX][CoordinateY + 2 * MoveInY].getWall != true))//Если там не две коробки или коробка+стена
					return true; //можно
				else return false;//иначе нельзя
			}
			else return false; //инача нельзя
		};

	public:
		void MovePlayer(int MoveInX, int MoveInY)/*Метод, который двигает игрока по плоскости, сдвигает коробки,
								  MoveInX и MoveInY - смещение от координат героя, ожидаемый диапазон значений от -1 до +1*/
		{
			if (player.CanMovePlayer(MoveInX, MoveInY) == true)
			{
				if (tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].getBox() == true)
				{
					tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].setBox(false);//убрать коробку
					tile[PlayerCoordinateX + 2 * MoveInX][PlayerCoordinateY + 2 * MoveInY].setBox(true);//поставить коробку
				}
				tile[PlayerCoordinateX][PlayerCoordinateY].setPlayerPos(false);//Убрать игрока с клетки
				tile[PlayerCoordinateX + MoveInX][PlayerCoordinateY + MoveInY].setPlayerPos(true);//Поставить игрока на новую клетку
				PlayerCoordinateX = PlayerCoordinateX + MoveInX;//Записать новые координаты игрока
				PlayerCoordinateY = PlayerCoordinateY + MoveInY;
			}/*Сама коробка двигаться не может, поэтому нет нужны в написании метода её отдельного движения*/
		};
	};
};

void main()
{

}

/*
Легенда:
+ тип public
- тип private
*/

//Итак, что нам нужно
/*
данные:
	-счётчик уровней: lvl
	-количестов ящиков на уровне: boxNum
	-количество установленных на нужное место ящиков: boxInPlace

методы:
	конструктор: Sokoban (тут надо реализовать запуск меню, меню - отдельный подкласс)
	+выбор уровня: setLVL
	+меню: menu
	+получение уровня: getLVL (для последующего счётчика уровней)
	+смена уровня: changeLVL
	+кол-во коробок на уровне: setBox
*/

/*
Итак, появляется новый класс: tile
данные:
	-наличие коробки: box
	-позиция игрока: playerPos
	-наличие стены: wall
	-место для коробки: winPlace
методы:
	+4 геттера
	+4 сеттера
	//это для каждых данных
*/
<|endoftext|>


<commit_before>// Copyright (c) 2017 Baidu Inc. 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.

#include <stdlib.h>
#include <thread>
#include "simulator_interface.h"

using namespace simulator;

DEFINE_string(game, "simple_game", "name of the game");

void run_simulation(std::shared_ptr<SimulatorInterface> g) {
    g->start();
    g->reset_game();
    auto num_actions = g->get_num_actions();

    double reward = 0;
    double r = 0;
    size_t cnt = 0;
    while (cnt < 100) {
        auto game_over_str = g->game_over_string();
        if (game_over_str != "alive") {
            LOG(INFO) << "game over because of " + game_over_str;
            g->reset_game();
            continue;
        }
        g->show_screen();

        StatePacket state;
        // You can choose to store the immediate reward r in the state
        // Or you can just ignore the first argument
        state = g->get_state(r);

        StatePacket actions;
        int a = util::get_rand_ind(num_actions);
        actions.add_buffer_id("action", {a});
        actions.add_buffer_str("pred_sentence", "hello");

        r = g->take_actions(actions, 1);
        reward += r;
        cnt ++;
    }
    g->stop();

    LOG(INFO) << "total reward " << reward;
}

int main(int argc, char** argv) {
    gflags::ParseCommandLineFlags(&argc, &argv, true);

    std::string name = FLAGS_game;

    int client_id = -1;
    const int num_agents = 1;
    const int base_port = 50000;
    for (int i = 0; i < num_agents; ++i) {
        if (fork() == 0) { // child process
            client_id = i;
            break;
        }
        // parent process will continue
    }

    if (client_id < 0) {
        LOG(INFO) << "server process id " << getpid();

        std::vector<std::thread> server_threads;
        for (int i = 0; i < num_agents; ++i) {
            int port = (base_port < 0) ? -1 : base_port + i;
            server_threads.emplace_back(
                [&](int port) {
                    auto g = std::make_shared<SimulatorServer>(name, port);
                    run_simulation(g);
                },
                port
            );
        }
        for (auto& t : server_threads) { t.join(); }
    } else {
        int port = base_port + client_id;
        LOG(INFO) << "client process id " << getpid();
        auto client = std::make_shared<SimulatorClient>(name, port);
        client->start();
    }

    return 0;
}
<commit_msg>multilprocess demo does not support games with more than one type of actions<commit_after>// Copyright (c) 2017 Baidu Inc. 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.

#include <stdlib.h>
#include <thread>
#include "simulator_interface.h"

using namespace simulator;

DEFINE_string(game, "simple_game", "name of the game");

void run_simulation(std::shared_ptr<SimulatorInterface> g) {
    g->start();
    g->reset_game();
    auto num_actions = g->get_num_actions();

    double reward = 0;
    double r = 0;
    size_t cnt = 0;
    while (cnt < 100) {
        auto game_over_str = g->game_over_string();
        if (game_over_str != "alive") {
            LOG(INFO) << "game over because of " + game_over_str;
            g->reset_game();
            continue;
        }
        g->show_screen();

        StatePacket state;
        // You can choose to store the immediate reward r in the state
        // Or you can just ignore the first argument
        state = g->get_state(r);

        StatePacket actions;
        int a = util::get_rand_ind(num_actions);
        actions.add_buffer_id("action", {a});

        r = g->take_actions(actions, 1);
        reward += r;
        cnt ++;
    }
    g->stop();

    LOG(INFO) << "total reward " << reward;
}

int main(int argc, char** argv) {
    gflags::ParseCommandLineFlags(&argc, &argv, true);

    std::string name = FLAGS_game;
    CHECK(name != "xworld" || name != "xworld3d")
            << " This program is for demostration of multiprocesses. It does"
            << " not support games with more than one type of actions.";

    int client_id = -1;
    const int num_agents = 1;
    const int base_port = 50000;
    for (int i = 0; i < num_agents; ++i) {
        if (fork() == 0) { // child process
            client_id = i;
            break;
        }
        // parent process will continue
    }

    if (client_id < 0) {
        LOG(INFO) << "server process id " << getpid();

        std::vector<std::thread> server_threads;
        for (int i = 0; i < num_agents; ++i) {
            int port = (base_port < 0) ? -1 : base_port + i;
            server_threads.emplace_back(
                [&](int port) {
                    auto g = std::make_shared<SimulatorServer>(name, port);
                    run_simulation(g);
                },
                port
            );
        }
        for (auto& t : server_threads) { t.join(); }
    } else {
        int port = base_port + client_id;
        LOG(INFO) << "client process id " << getpid();
        auto client = std::make_shared<SimulatorClient>(name, port);
        client->start();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "actiondb.h"
#include "main.h"
#include "win.h"

#include <iostream>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
//#include <boost/serialization/base_object.hpp>

// I don't know WHY I need this, I'm just glad I found out I did...
BOOST_CLASS_EXPORT(StrokeSet)

BOOST_CLASS_EXPORT(Action)
BOOST_CLASS_EXPORT(Command)
BOOST_CLASS_EXPORT(ModAction)
BOOST_CLASS_EXPORT(Scroll)
BOOST_CLASS_EXPORT(Ignore)
BOOST_CLASS_EXPORT(Button)

class SendKeyPriv : public SendKey {
	friend class boost::serialization::access;
	friend class SendKey;
	guint key;
	guint code;
	template<class Archive> void serialize(Archive & ar, const unsigned int version) {
		ar & boost::serialization::base_object<ModAction>(*this);
		ar & key;
		ar & code;
		if (version < 1) {
			bool xtest;
			ar & xtest;
		}
	}

	SendKeyPriv(guint key_, Gdk::ModifierType mods, guint code_) :
		SendKey(mods), key(key_), code(code_) {}
public:
	SendKeyPriv() {}
	virtual bool run() {
		press();
		XTestFakeKeyEvent(dpy, code, true, 0);
		XTestFakeKeyEvent(dpy, code, false, 0);
		return true;
	}

	virtual const Glib::ustring get_label() const {
		Glib::ustring str = Gtk::AccelGroup::get_label(key, mods);
		if (key == 0) {
			char buf[10];
			snprintf(buf, 9, "0x%x", code);
			str += buf;
		}
		return str;
	}
};

BOOST_CLASS_VERSION(SendKeyPriv, 1)
BOOST_CLASS_EXPORT_GUID(SendKeyPriv, "SendKey")

RSendKey SendKey::create(guint key, Gdk::ModifierType mods, guint code) {
	return RSendKey(new SendKeyPriv(key, mods, code));
}

template<class Archive> void Action::serialize(Archive & ar, const unsigned int version) {
}

template<class Archive> void Command::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<Action>(*this);
	ar & cmd;
}

template<class Archive> void ModAction::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<Action>(*this);
	ar & mods;
}

template<class Archive> void Scroll::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
}

template<class Archive> void Ignore::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
}

template<class Archive> void Button::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
	ar & button;
}

template<class Archive> void StrokeSet::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<std::set<RStroke> >(*this);
}

template<class Archive> void StrokeInfo::serialize(Archive & ar, const unsigned int version) {
	ar & strokes;
	ar & action;
	if (version == 0) return;
	ar & name;
}

using namespace std;

bool Command::run() {
	if (cmd == "")
		return false;
	pid_t pid = fork();
	switch (pid) {
		case 0:
			execlp("/bin/sh", "sh", "-c", cmd.c_str(), NULL);
			exit(1);
		case -1:
			printf("Error: can't execute command %s: fork failed\n", cmd.c_str());
	}
	return true;
}

ButtonInfo Button::get_button_info() const {
	ButtonInfo bi;
	bi.button = button;
	bi.state = mods;
	return bi;
}

const Glib::ustring Button::get_label() const {
	return get_button_info().get_button_text();
}

ActionDB::ActionDB() : current_id(0) {}

template<class Archive> void ActionDB::load(Archive & ar, const unsigned int version) {
	if (version >= 1) {
		std::map<int, StrokeInfo> strokes2;
		ar & strokes2;
		for (std::map<int, StrokeInfo>::iterator i = strokes2.begin(); i != strokes2.end(); ++i)
			add(i->second);
		return;
	} else {
		std::map<std::string, StrokeInfo> strokes2;
		ar & strokes2;
		for (std::map<std::string, StrokeInfo>::iterator i = strokes2.begin(); i != strokes2.end(); ++i) {
			i->second.name = i->first;
			add(i->second);
		}
		return;
	}
}

void ActionDBWatcher::init() {
	std::string filename = config_dir+"actions";
	try {
		ifstream ifs(filename.c_str(), ios::binary);
		boost::archive::text_iarchive ia(ifs);
		ia >> actions.unsafe_ref();
		if (verbosity >= 2)
			cout << "Loaded " << actions.ref().strokes.size() << " actions." << endl;
	} catch (...) {
		cout << "Error: Couldn't read action database." << endl;
	}
	watch(actions);
}

void ActionDBWatcher::timeout() {
	std::string filename = config_dir+"actions";
	try {
		ofstream ofs(filename.c_str());
		boost::archive::text_oarchive oa(ofs);
		const ActionDB &db = actions.ref();
		oa << db;
		if (verbosity >= 2)
			cout << "Saved " << actions.ref().strokes.size() << " actions." << endl;
	} catch (...) {
		cout << "Error: Couldn't save action database." << endl;
		if (!good_state)
			return;
		good_state = false;
		new ErrorDialog("Couldn't save actions.  Your changes will be lost.  \nMake sure that "+config_dir+" is a directory and that you have write access to it.\nYou can change the configuration directory using the -c or --config-dir command line options.");
	}
}

bool ActionDB::remove(int id) {
	return strokes.erase(id);
}

int ActionDB::add(StrokeInfo &si) {
	strokes[current_id] = si;
	return current_id++;
}

int ActionDB::addCmd(RStroke stroke, const string& name, const string& cmd) {
	StrokeInfo si;
	if (stroke)
		si.strokes.insert(stroke);
	si.name = name;
	si.action = Command::create(cmd);
	return add(si);
}

int ActionDB::nested_size() const {
	int size = 0;
	for (const_iterator i = begin(); i != end(); i++)
		size += i->second.strokes.size();
	return size;
}

Ranking *ActionDB::handle(RStroke s) const {
	Ranking *r = new Ranking;
	r->stroke = s;
	r->score = -1;
	r->id = -2;
	bool success = false;
	if (!s)
		return r;
	for (StrokeIterator i = strokes_begin(); i; i++) {
		if (!i.stroke())
			continue;
		double score = Stroke::compare(s, i.stroke());
		if (score < 0.25)
			continue;
		r->r.insert(pair<double, pair<std::string, RStroke> >
				(score, pair<std::string, RStroke>(i.name(), i.stroke())));
		if (score >= r->score) {
			r->score = score;
			if (score >= 0.7) {
				r->id = i.id();
				r->name = i.name();
				r->action = i.action();
				r->best_stroke = i.stroke();
				success = true;
			}
		}
	}
	if (!success && s->trivial()) {
		r->id = -1;
		r->name = "click (default)";
		success = true;
	}
	if (success) {
		if (verbosity >= 1)
			cout << "Excecuting Action " << r->name << "..." << endl;
		if (r->action)
			r->action->run();
	} else {
		if (verbosity >= 1)
			cout << "Couldn't find matching stroke." << endl;
	}
	return r;
}

Source<ActionDB> actions;
<commit_msg>only use fixed keycodes anymore if we have to<commit_after>/*
 * Copyright (c) 2008, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "actiondb.h"
#include "main.h"
#include "win.h"

#include <iostream>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
//#include <boost/serialization/base_object.hpp>

// I don't know WHY I need this, I'm just glad I found out I did...
BOOST_CLASS_EXPORT(StrokeSet)

BOOST_CLASS_EXPORT(Action)
BOOST_CLASS_EXPORT(Command)
BOOST_CLASS_EXPORT(ModAction)
BOOST_CLASS_EXPORT(Scroll)
BOOST_CLASS_EXPORT(Ignore)
BOOST_CLASS_EXPORT(Button)

class SendKeyPriv : public SendKey {
	friend class boost::serialization::access;
	friend class SendKey;
	guint key;
	guint code;
	BOOST_SERIALIZATION_SPLIT_MEMBER()
	template<class Archive> void load(Archive & ar, const unsigned int version) {
		ar & boost::serialization::base_object<ModAction>(*this);
		ar & key;
		ar & code;
		if (version < 1) {
			bool xtest;
			ar & xtest;
		}
		compute_code();
	}
	template<class Archive> void save(Archive & ar, const unsigned int version) const {
		ar & boost::serialization::base_object<ModAction>(*this);
		ar & key;
		ar & code;
	}

	SendKeyPriv(guint key_, Gdk::ModifierType mods, guint code_) :
		SendKey(mods), key(key_), code(code_) { compute_code(); }

	void compute_code() {
		if (key)
			code = XKeysymToKeycode(dpy, key);
	}
public:
	SendKeyPriv() {}
	virtual bool run() {
		press();
		XTestFakeKeyEvent(dpy, code, true, 0);
		XTestFakeKeyEvent(dpy, code, false, 0);
		return true;
	}

	virtual const Glib::ustring get_label() const {
		Glib::ustring str = Gtk::AccelGroup::get_label(key, mods);
		if (key == 0) {
			char buf[10];
			snprintf(buf, 9, "0x%x", code);
			str += buf;
		}
		return str;
	}
};

BOOST_CLASS_VERSION(SendKeyPriv, 1)
BOOST_CLASS_EXPORT_GUID(SendKeyPriv, "SendKey")

RSendKey SendKey::create(guint key, Gdk::ModifierType mods, guint code) {
	return RSendKey(new SendKeyPriv(key, mods, code));
}

template<class Archive> void Action::serialize(Archive & ar, const unsigned int version) {
}

template<class Archive> void Command::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<Action>(*this);
	ar & cmd;
}

template<class Archive> void ModAction::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<Action>(*this);
	ar & mods;
}

template<class Archive> void Scroll::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
}

template<class Archive> void Ignore::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
}

template<class Archive> void Button::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<ModAction>(*this);
	ar & button;
}

template<class Archive> void StrokeSet::serialize(Archive & ar, const unsigned int version) {
	ar & boost::serialization::base_object<std::set<RStroke> >(*this);
}

template<class Archive> void StrokeInfo::serialize(Archive & ar, const unsigned int version) {
	ar & strokes;
	ar & action;
	if (version == 0) return;
	ar & name;
}

using namespace std;

bool Command::run() {
	if (cmd == "")
		return false;
	pid_t pid = fork();
	switch (pid) {
		case 0:
			execlp("/bin/sh", "sh", "-c", cmd.c_str(), NULL);
			exit(1);
		case -1:
			printf("Error: can't execute command %s: fork failed\n", cmd.c_str());
	}
	return true;
}

ButtonInfo Button::get_button_info() const {
	ButtonInfo bi;
	bi.button = button;
	bi.state = mods;
	return bi;
}

const Glib::ustring Button::get_label() const {
	return get_button_info().get_button_text();
}

ActionDB::ActionDB() : current_id(0) {}

template<class Archive> void ActionDB::load(Archive & ar, const unsigned int version) {
	if (version >= 1) {
		std::map<int, StrokeInfo> strokes2;
		ar & strokes2;
		for (std::map<int, StrokeInfo>::iterator i = strokes2.begin(); i != strokes2.end(); ++i)
			add(i->second);
		return;
	} else {
		std::map<std::string, StrokeInfo> strokes2;
		ar & strokes2;
		for (std::map<std::string, StrokeInfo>::iterator i = strokes2.begin(); i != strokes2.end(); ++i) {
			i->second.name = i->first;
			add(i->second);
		}
		return;
	}
}

void ActionDBWatcher::init() {
	std::string filename = config_dir+"actions";
	try {
		ifstream ifs(filename.c_str(), ios::binary);
		boost::archive::text_iarchive ia(ifs);
		ia >> actions.unsafe_ref();
		if (verbosity >= 2)
			cout << "Loaded " << actions.ref().strokes.size() << " actions." << endl;
	} catch (...) {
		cout << "Error: Couldn't read action database." << endl;
	}
	watch(actions);
}

void ActionDBWatcher::timeout() {
	std::string filename = config_dir+"actions";
	try {
		ofstream ofs(filename.c_str());
		boost::archive::text_oarchive oa(ofs);
		const ActionDB &db = actions.ref();
		oa << db;
		if (verbosity >= 2)
			cout << "Saved " << actions.ref().strokes.size() << " actions." << endl;
	} catch (...) {
		cout << "Error: Couldn't save action database." << endl;
		if (!good_state)
			return;
		good_state = false;
		new ErrorDialog("Couldn't save actions.  Your changes will be lost.  \nMake sure that "+config_dir+" is a directory and that you have write access to it.\nYou can change the configuration directory using the -c or --config-dir command line options.");
	}
}

bool ActionDB::remove(int id) {
	return strokes.erase(id);
}

int ActionDB::add(StrokeInfo &si) {
	strokes[current_id] = si;
	return current_id++;
}

int ActionDB::addCmd(RStroke stroke, const string& name, const string& cmd) {
	StrokeInfo si;
	if (stroke)
		si.strokes.insert(stroke);
	si.name = name;
	si.action = Command::create(cmd);
	return add(si);
}

int ActionDB::nested_size() const {
	int size = 0;
	for (const_iterator i = begin(); i != end(); i++)
		size += i->second.strokes.size();
	return size;
}

Ranking *ActionDB::handle(RStroke s) const {
	Ranking *r = new Ranking;
	r->stroke = s;
	r->score = -1;
	r->id = -2;
	bool success = false;
	if (!s)
		return r;
	for (StrokeIterator i = strokes_begin(); i; i++) {
		if (!i.stroke())
			continue;
		double score = Stroke::compare(s, i.stroke());
		if (score < 0.25)
			continue;
		r->r.insert(pair<double, pair<std::string, RStroke> >
				(score, pair<std::string, RStroke>(i.name(), i.stroke())));
		if (score >= r->score) {
			r->score = score;
			if (score >= 0.7) {
				r->id = i.id();
				r->name = i.name();
				r->action = i.action();
				r->best_stroke = i.stroke();
				success = true;
			}
		}
	}
	if (!success && s->trivial()) {
		r->id = -1;
		r->name = "click (default)";
		success = true;
	}
	if (success) {
		if (verbosity >= 1)
			cout << "Excecuting Action " << r->name << "..." << endl;
		if (r->action)
			r->action->run();
	} else {
		if (verbosity >= 1)
			cout << "Couldn't find matching stroke." << endl;
	}
	return r;
}

Source<ActionDB> actions;
<|endoftext|>


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

#include "Benchmark.hpp"
#include "BenchmarkRunner.hpp"

using namespace mach5;

class SelectionSortBenchmark : public Benchmark {
public:
	virtual void code();
};

void SelectionSortBenchmark::code() {
	std::cout << "Running..." << std::endl;
	std::vector<int> num = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1};
	int tam = num.size();
	for (int i = 0; i < (tam-1); i++) {
		int min = i;
		for (int j = (i+1); j < tam; j++) {
			if(num[j] < num[min]) {
				min = j;
			}
		}
		if (i != min) {
			int swap = num[i];
			num[i] = num[min];
			num[min] = swap;
		}
	}
}

int main() {
	BenchmarkRunnerPtr runner = BenchmarkRunnerPtr(new BenchmarkRunner());
	runner->addBenchmark(BenchmarkPtr(new SelectionSortBenchmark()));
	runner->runAll();
}<commit_msg>Adds another test<commit_after>#include <iostream>
#include <vector>
#include <algorithm>

#include "Benchmark.hpp"
#include "BenchmarkRunner.hpp"

using namespace mach5;

class SelectionSortBenchmark : public Benchmark {
public:
	virtual void code();
};

void SelectionSortBenchmark::code() {
	std::cout << "Running SelectionSortBenchmark..." << std::endl;
	std::vector<int> num = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1};
	int tam = num.size();
	for (int i = 0; i < (tam-1); i++) {
		int min = i;
		for (int j = (i+1); j < tam; j++) {
			if(num[j] < num[min]) {
				min = j;
			}
		}
		if (i != min) {
			int swap = num[i];
			num[i] = num[min];
			num[min] = swap;
		}
	}
}

class SortBenchmark : public Benchmark {
public:
	virtual void code();
};

void SortBenchmark::code() {
	std::cout << "Running SortBenchmark..." << std::endl;
	std::vector<int> num = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1};
	std::sort(num.begin(), num.end());
}

int main() {
	BenchmarkRunnerPtr runner = BenchmarkRunnerPtr(new BenchmarkRunner());
	runner->addBenchmark(BenchmarkPtr(new SelectionSortBenchmark()));
	runner->addBenchmark(BenchmarkPtr(new SortBenchmark()));
	runner->runAll();
}<|endoftext|>


<commit_before><commit_msg>Made a temporary fix for the code that deals with Previous Section. Added the displaying of the current section to the Go To Section line.<commit_after><|endoftext|>


<commit_before>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <petro/sequence_parameter_set.hpp>

#include <vector>

#include <gtest/gtest.h>

TEST(test_sequence_parameter_set, check_variables)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x42, 0x00, 0x0A, 0xF8, 0x41, 0xA2
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(66U, sps.profile_idc());
    EXPECT_EQ(0U, sps.constraint_set0_flag());
    EXPECT_EQ(0U, sps.constraint_set1_flag());
    EXPECT_EQ(0U, sps.constraint_set2_flag());
    EXPECT_EQ(0U, sps.constraint_set3_flag());
    EXPECT_EQ(10U, sps.level_idc());
    EXPECT_EQ(0U, sps.seq_parameter_set_id());
    EXPECT_EQ(4U, sps.log2_max_frame_num());
    EXPECT_EQ(0U, sps.pic_order_cnt_type());
    EXPECT_EQ(4U, sps.log2_max_pic_order_cnt_lsb());
    EXPECT_EQ(0U, sps.num_ref_frames_in_pic_order_cnt_cycle());
    EXPECT_EQ(0U, sps.gaps_in_frame_num_value_allowed_flag());
    EXPECT_EQ(8U, sps.pic_width_in_mbs());
    EXPECT_EQ(6U, sps.pic_height_in_map_units());
    EXPECT_EQ(1U, sps.frame_mbs_only_flag());
    EXPECT_EQ(0U, sps.direct_8x8_inference_flag());
    EXPECT_EQ(0U, sps.frame_cropping_flag());
    EXPECT_EQ(0U, sps.vui_parameters_present_flag());
    EXPECT_EQ(128U, sps.width());
    EXPECT_EQ(96U, sps.height());
}

TEST(test_sequence_parameter_set, width512_height288)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x15, 0xac, 0xc8, 0x60, 0x20,
            0x09, 0x6c, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00,
            0x40, 0x00, 0x00, 0x07, 0xa3, 0xc5, 0x8b, 0x67,
            0x80
        };
    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(100U, sps.profile_idc());
    EXPECT_EQ(0U, sps.constraint_set0_flag());
    EXPECT_EQ(0U, sps.constraint_set1_flag());
    EXPECT_EQ(0U, sps.constraint_set2_flag());
    EXPECT_EQ(0U, sps.constraint_set3_flag());
    EXPECT_EQ(21U, sps.level_idc());
    EXPECT_EQ(0U, sps.seq_parameter_set_id());
    EXPECT_EQ(1U, sps.chroma_format_idc());
    EXPECT_EQ(0U, sps.gaps_in_frame_num_value_allowed_flag());
    EXPECT_EQ(32U, sps.pic_width_in_mbs());
    EXPECT_EQ(18U, sps.pic_height_in_map_units());
    EXPECT_EQ(1U, sps.frame_mbs_only_flag());
    EXPECT_EQ(1U, sps.direct_8x8_inference_flag());
    EXPECT_EQ(0U, sps.frame_cropping_flag());
    EXPECT_EQ(1U, sps.vui_parameters_present_flag());
    EXPECT_EQ(512U, sps.width());
    EXPECT_EQ(288U, sps.height());
}

TEST(test_sequence_parameter_set, width1280_height800)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x42, 0x00, 0x20, 0xE2, 0x90, 0x0A, 0x00,
            0xCB, 0x60, 0x2D, 0xC0, 0x40, 0x40, 0x69, 0x07,
            0x89, 0x11, 0x50
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(1280U, sps.width());
    EXPECT_EQ(800U, sps.height());

}

TEST(test_sequence_parameter_set, width1920_height1080)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x2A, 0xAD, 0x84, 0x01, 0x0C,
            0x20, 0x08, 0x61, 0x00, 0x43, 0x08, 0x02, 0x18,
            0x40, 0x10, 0xC2, 0x00, 0x84, 0x2B, 0x50, 0x3C,
            0x01, 0x13, 0xF2, 0xC2, 0x00, 0x00, 0x03, 0x00,
            0x02, 0x00, 0x00, 0x03, 0x00, 0x79, 0x08
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(1920U, sps.width());
    EXPECT_EQ(1080U, sps.height());
}

TEST(test_sequence_parameter_set, width3840_height2160)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x33, 0xAC, 0xD1, 0x00, 0x3C,
            0x00, 0x43, 0xEC, 0x05, 0x48, 0x08, 0x08, 0x0A,
            0x00, 0x00, 0x07, 0xD2, 0x00, 0x01, 0xD4, 0xC1,
            0xC8, 0x00, 0x00, 0x0B, 0xEB, 0xC2, 0x00, 0x00,
            0x05, 0xF5, 0xBD, 0xD4, 0x98, 0x60, 0x1F, 0x18,
            0x31, 0x12
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(3840U, sps.width());
    EXPECT_EQ(2160U, sps.height());
}
<commit_msg>Add sps test (#24)<commit_after>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <petro/sequence_parameter_set.hpp>

#include <vector>

#include <gtest/gtest.h>

TEST(test_sequence_parameter_set, check_variables)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x42, 0x00, 0x0A, 0xF8, 0x41, 0xA2
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(66U, sps.profile_idc());
    EXPECT_EQ(0U, sps.constraint_set0_flag());
    EXPECT_EQ(0U, sps.constraint_set1_flag());
    EXPECT_EQ(0U, sps.constraint_set2_flag());
    EXPECT_EQ(0U, sps.constraint_set3_flag());
    EXPECT_EQ(10U, sps.level_idc());
    EXPECT_EQ(0U, sps.seq_parameter_set_id());
    EXPECT_EQ(4U, sps.log2_max_frame_num());
    EXPECT_EQ(0U, sps.pic_order_cnt_type());
    EXPECT_EQ(4U, sps.log2_max_pic_order_cnt_lsb());
    EXPECT_EQ(0U, sps.num_ref_frames_in_pic_order_cnt_cycle());
    EXPECT_EQ(0U, sps.gaps_in_frame_num_value_allowed_flag());
    EXPECT_EQ(8U, sps.pic_width_in_mbs());
    EXPECT_EQ(6U, sps.pic_height_in_map_units());
    EXPECT_EQ(1U, sps.frame_mbs_only_flag());
    EXPECT_EQ(0U, sps.direct_8x8_inference_flag());
    EXPECT_EQ(0U, sps.frame_cropping_flag());
    EXPECT_EQ(0U, sps.vui_parameters_present_flag());
    EXPECT_EQ(128U, sps.width());
    EXPECT_EQ(96U, sps.height());
}

TEST(test_sequence_parameter_set, width512_height288)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x15, 0xac, 0xc8, 0x60, 0x20,
            0x09, 0x6c, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00,
            0x40, 0x00, 0x00, 0x07, 0xa3, 0xc5, 0x8b, 0x67,
            0x80
        };
    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(100U, sps.profile_idc());
    EXPECT_EQ(0U, sps.constraint_set0_flag());
    EXPECT_EQ(0U, sps.constraint_set1_flag());
    EXPECT_EQ(0U, sps.constraint_set2_flag());
    EXPECT_EQ(0U, sps.constraint_set3_flag());
    EXPECT_EQ(21U, sps.level_idc());
    EXPECT_EQ(0U, sps.seq_parameter_set_id());
    EXPECT_EQ(1U, sps.chroma_format_idc());
    EXPECT_EQ(0U, sps.gaps_in_frame_num_value_allowed_flag());
    EXPECT_EQ(32U, sps.pic_width_in_mbs());
    EXPECT_EQ(18U, sps.pic_height_in_map_units());
    EXPECT_EQ(1U, sps.frame_mbs_only_flag());
    EXPECT_EQ(1U, sps.direct_8x8_inference_flag());
    EXPECT_EQ(0U, sps.frame_cropping_flag());
    EXPECT_EQ(1U, sps.vui_parameters_present_flag());
    EXPECT_EQ(512U, sps.width());
    EXPECT_EQ(288U, sps.height());
}

TEST(test_sequence_parameter_set, width1280_height800)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x42, 0x00, 0x20, 0xE2, 0x90, 0x0A, 0x00,
            0xCB, 0x60, 0x2D, 0xC0, 0x40, 0x40, 0x69, 0x07,
            0x89, 0x11, 0x50
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(1280U, sps.width());
    EXPECT_EQ(800U, sps.height());

}

TEST(test_sequence_parameter_set, width1920_height1080)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x2A, 0xAD, 0x84, 0x01, 0x0C,
            0x20, 0x08, 0x61, 0x00, 0x43, 0x08, 0x02, 0x18,
            0x40, 0x10, 0xC2, 0x00, 0x84, 0x2B, 0x50, 0x3C,
            0x01, 0x13, 0xF2, 0xC2, 0x00, 0x00, 0x03, 0x00,
            0x02, 0x00, 0x00, 0x03, 0x00, 0x79, 0x08
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(1920U, sps.width());
    EXPECT_EQ(1080U, sps.height());
}

TEST(test_sequence_parameter_set, width3840_height2160)
{
    std::vector<uint8_t> data =
        {
            0x67, 0x64, 0x00, 0x33, 0xAC, 0xD1, 0x00, 0x3C,
            0x00, 0x43, 0xEC, 0x05, 0x48, 0x08, 0x08, 0x0A,
            0x00, 0x00, 0x07, 0xD2, 0x00, 0x01, 0xD4, 0xC1,
            0xC8, 0x00, 0x00, 0x0B, 0xEB, 0xC2, 0x00, 0x00,
            0x05, 0xF5, 0xBD, 0xD4, 0x98, 0x60, 0x1F, 0x18,
            0x31, 0x12
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(3840U, sps.width());
    EXPECT_EQ(2160U, sps.height());
}

TEST(test_sequence_parameter_set, width560_height320)
{
    /// sps taken from test1.mp4
    std::vector<uint8_t> data =
        {
            0x67, 0x42, 0xC0, 0x1E, 0xD9, 0x00, 0x8C, 0x29, 0xB0,
            0x11, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03,
            0x00, 0x3C, 0x8F, 0x16, 0x2E, 0x48
        };

    petro::sequence_parameter_set sps(data.data(), data.size());
    EXPECT_EQ(560U, sps.width());
    EXPECT_EQ(320U, sps.height());
}
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include "joynr/ParticipantIdStorage.h"

#include <algorithm>
#include <cassert>
#include <exception>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/format.hpp>

#include "joynr/Util.h"

namespace joynr
{

ParticipantIdStorage::ParticipantIdStorage(const std::string& filename)
        : fileMutex(), storageMutex(), storage(), entriesWrittenToDisk(0), fileName(filename)
{
    assert(!fileName.empty());
    loadEntriesFromFile();
}

const std::string& ParticipantIdStorage::STORAGE_FORMAT_STRING()
{
    static const std::string value("joynr.participant.%1%.%2%.v%3%");
    return value;
}

void ParticipantIdStorage::loadEntriesFromFile()
{
    if (!joynr::util::fileExists(fileName)) {
        return;
    }

    JOYNR_LOG_TRACE(logger(), "Attempting to load ParticipantIdStorage from: {}", fileName);

    boost::property_tree::ptree pt;
    WriteLocker lockAccessToStorage(storageMutex);
    try {
        boost::property_tree::ini_parser::read_ini(fileName, pt);
        for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
            StorageItem item{it->first, it->second.data()};
            auto retVal = storage.insert(std::move(item));
            assert(retVal.second);
            std::ignore = retVal;
        }
    } catch (const std::exception& ex) {
        JOYNR_LOG_WARN(logger(),
                       "Cannot read participantId storage file {}. Removing file. Exception: {}",
                       fileName,
                       ex.what());
        std::remove(fileName.c_str());
    }

    // set entriesWrittenToDisk to the size of the storage
    entriesWrittenToDisk = storage.get<participantIdStorageTags::write>().size();
    JOYNR_LOG_TRACE(logger(), "Loaded {} entries.", entriesWrittenToDisk);
}

void ParticipantIdStorage::setProviderParticipantId(const std::string& domain,
                                                    const std::string& interfaceName,
                                                    std::int32_t majorVersion,
                                                    const std::string& participantId)
{
    assert(!domain.empty());
    assert(!interfaceName.empty());
    assert(!participantId.empty());

    bool fileNeedsUpdate = false;
    std::string providerKey = createProviderKey(domain, interfaceName, majorVersion);
    StorageItem item{providerKey, participantId};
    {
        WriteLocker lockAccessToStorage(storageMutex);
        auto retVal = storage.insert(std::move(item));
        fileNeedsUpdate = retVal.second;
    }

    if (fileNeedsUpdate) {
        writeStoreToFile();
    }
}

std::string ParticipantIdStorage::getProviderParticipantId(const std::string& domain,
                                                           const std::string& interfaceName,
                                                           std::int32_t majorVersion)
{
    return getProviderParticipantId(domain, interfaceName, majorVersion, "");
}

std::string ParticipantIdStorage::getProviderParticipantId(const std::string& domain,
                                                           const std::string& interfaceName,
                                                           std::int32_t majorVersion,
                                                           const std::string& defaultValue)
{
    assert(!domain.empty());
    assert(!interfaceName.empty());

    const std::string providerKey = createProviderKey(domain, interfaceName, majorVersion);
    MultiIndexContainer::const_iterator value;

    {
        ReadLocker lockAccessToStorage(storageMutex);
        value = storage.template get<participantIdStorageTags::read>().find(providerKey);
    }

    if (value != storage.cend()) {
        return value->participantId;
    } else {
        return (!defaultValue.empty()) ? defaultValue : util::createUuid();
    }
}

void ParticipantIdStorage::writeStoreToFile()
{
    std::lock_guard<std::mutex> lockAccessToFile(fileMutex);
    WriteLocker lockAccessToStorage(storageMutex);

    auto& writeIndex = storage.get<participantIdStorageTags::write>();
    const size_t entries = writeIndex.size();

    // The storage in memory is supposed to contain at least one entry at this point.
    if (entries == 0) {
        assert(entriesWrittenToDisk == 0);
        return;
    }

    if (entries > entriesWrittenToDisk) {
        JOYNR_LOG_TRACE(
                logger(), "Writing {} new entries to file.", entries - entriesWrittenToDisk);

        // write not present entries to File
        size_t writtenToDisk = 0;
        for (size_t i = entriesWrittenToDisk; i < entries; ++i, ++writtenToDisk) {
            auto entry = writeIndex[i];
            try {
                joynr::util::appendStringToFile(fileName, entry.toIniForm());
            } catch (const std::runtime_error& ex) {
                JOYNR_LOG_ERROR(logger(),
                                "Cannot save ParticipantId to file {}. Next application lifecycle "
                                "might not function correctly. Exception: {}",
                                fileName,
                                ex.what());
                entriesWrittenToDisk += writtenToDisk;
                return;
            }
        }
        assert(entries == entriesWrittenToDisk + writtenToDisk);
        entriesWrittenToDisk = entries;
        JOYNR_LOG_TRACE(logger(), "Storage on file contains now {} entries.", entriesWrittenToDisk);
    } else if (entries < entriesWrittenToDisk) {
        // This actually means that someone modified the file and inserted other entries.
        // Do nothing.
    } else {
        // In this case the number of entries written to disk matches those in the store.
        // Do nothing.
    }
}

std::string ParticipantIdStorage::createProviderKey(const std::string& domain,
                                                    const std::string& interfaceName,
                                                    std::int32_t majorVersion)
{
    std::string key = (boost::format(STORAGE_FORMAT_STRING()) % domain % interfaceName %
                       std::to_string(majorVersion)).str();
    std::replace(key.begin(), key.end(), '/', '.');
    return key;
}

} // namespace joynr
<commit_msg>[C++] ParticipantIdStorage syncs data to disk<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include "joynr/ParticipantIdStorage.h"

#include <algorithm>
#include <cassert>
#include <exception>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/format.hpp>

#include "joynr/Util.h"

namespace joynr
{

ParticipantIdStorage::ParticipantIdStorage(const std::string& filename)
        : fileMutex(), storageMutex(), storage(), entriesWrittenToDisk(0), fileName(filename)
{
    assert(!fileName.empty());
    loadEntriesFromFile();
}

const std::string& ParticipantIdStorage::STORAGE_FORMAT_STRING()
{
    static const std::string value("joynr.participant.%1%.%2%.v%3%");
    return value;
}

void ParticipantIdStorage::loadEntriesFromFile()
{
    if (!joynr::util::fileExists(fileName)) {
        return;
    }

    JOYNR_LOG_TRACE(logger(), "Attempting to load ParticipantIdStorage from: {}", fileName);

    boost::property_tree::ptree pt;
    WriteLocker lockAccessToStorage(storageMutex);
    try {
        boost::property_tree::ini_parser::read_ini(fileName, pt);
        for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
            StorageItem item{it->first, it->second.data()};
            auto retVal = storage.insert(std::move(item));
            assert(retVal.second);
            std::ignore = retVal;
        }
    } catch (const std::exception& ex) {
        JOYNR_LOG_WARN(logger(),
                       "Cannot read participantId storage file {}. Removing file. Exception: {}",
                       fileName,
                       ex.what());
        std::remove(fileName.c_str());
    }

    // set entriesWrittenToDisk to the size of the storage
    entriesWrittenToDisk = storage.get<participantIdStorageTags::write>().size();
    JOYNR_LOG_TRACE(logger(), "Loaded {} entries.", entriesWrittenToDisk);
}

void ParticipantIdStorage::setProviderParticipantId(const std::string& domain,
                                                    const std::string& interfaceName,
                                                    std::int32_t majorVersion,
                                                    const std::string& participantId)
{
    assert(!domain.empty());
    assert(!interfaceName.empty());
    assert(!participantId.empty());

    bool fileNeedsUpdate = false;
    std::string providerKey = createProviderKey(domain, interfaceName, majorVersion);
    StorageItem item{providerKey, participantId};
    {
        WriteLocker lockAccessToStorage(storageMutex);
        auto retVal = storage.insert(std::move(item));
        fileNeedsUpdate = retVal.second;
    }

    if (fileNeedsUpdate) {
        writeStoreToFile();
    }
}

std::string ParticipantIdStorage::getProviderParticipantId(const std::string& domain,
                                                           const std::string& interfaceName,
                                                           std::int32_t majorVersion)
{
    return getProviderParticipantId(domain, interfaceName, majorVersion, "");
}

std::string ParticipantIdStorage::getProviderParticipantId(const std::string& domain,
                                                           const std::string& interfaceName,
                                                           std::int32_t majorVersion,
                                                           const std::string& defaultValue)
{
    assert(!domain.empty());
    assert(!interfaceName.empty());

    const std::string providerKey = createProviderKey(domain, interfaceName, majorVersion);
    MultiIndexContainer::const_iterator value;

    {
        ReadLocker lockAccessToStorage(storageMutex);
        value = storage.template get<participantIdStorageTags::read>().find(providerKey);
    }

    if (value != storage.cend()) {
        return value->participantId;
    } else {
        return (!defaultValue.empty()) ? defaultValue : util::createUuid();
    }
}

void ParticipantIdStorage::writeStoreToFile()
{
    std::lock_guard<std::mutex> lockAccessToFile(fileMutex);
    WriteLocker lockAccessToStorage(storageMutex);

    auto& writeIndex = storage.get<participantIdStorageTags::write>();
    const size_t entries = writeIndex.size();

    // The storage in memory is supposed to contain at least one entry at this point.
    if (entries == 0) {
        assert(entriesWrittenToDisk == 0);
        return;
    }

    if (entries > entriesWrittenToDisk) {
        JOYNR_LOG_TRACE(
                logger(), "Writing {} new entries to file.", entries - entriesWrittenToDisk);

        // write not present entries to File
        size_t writtenToDisk = 0;
        for (size_t i = entriesWrittenToDisk; i < entries; ++i, ++writtenToDisk) {
            auto entry = writeIndex[i];
            try {
                // append to file and fsync it
                joynr::util::appendStringToFile(fileName, entry.toIniForm(), true);
            } catch (const std::runtime_error& ex) {
                JOYNR_LOG_ERROR(logger(),
                                "Cannot save ParticipantId to file {}. Next application lifecycle "
                                "might not function correctly. Exception: {}",
                                fileName,
                                ex.what());
                entriesWrittenToDisk += writtenToDisk;
                return;
            }
        }
        assert(entries == entriesWrittenToDisk + writtenToDisk);
        entriesWrittenToDisk = entries;
        JOYNR_LOG_TRACE(logger(), "Storage on file contains now {} entries.", entriesWrittenToDisk);
    } else if (entries < entriesWrittenToDisk) {
        // This actually means that someone modified the file and inserted other entries.
        // Do nothing.
    } else {
        // In this case the number of entries written to disk matches those in the store.
        // Do nothing.
    }
}

std::string ParticipantIdStorage::createProviderKey(const std::string& domain,
                                                    const std::string& interfaceName,
                                                    std::int32_t majorVersion)
{
    std::string key = (boost::format(STORAGE_FORMAT_STRING()) % domain % interfaceName %
                       std::to_string(majorVersion)).str();
    std::replace(key.begin(), key.end(), '/', '.');
    return key;
}

} // namespace joynr
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 6/15/2019, 3:30:35 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
typedef long long ll;
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
const int MAX_SIZE = 1000010;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return mint(0) - *this; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
mint inv[MAX_SIZE];
mint fact[MAX_SIZE];
mint factinv[MAX_SIZE];
void init()
{
  inv[1] = 1;
  for (int i = 2; i < MAX_SIZE; i++)
  {
    inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
  }
  fact[0] = factinv[0] = 1;
  for (int i = 1; i < MAX_SIZE; i++)
  {
    fact[i] = mint(i) * fact[i - 1];
    factinv[i] = inv[i] * factinv[i - 1];
  }
}
mint choose(int n, int k)
{
  if (n >= 0 && k >= 0 && n - k >= 0)
  {
    return fact[n] * factinv[k] * factinv[n - k];
  }
  return 0;
}
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

int N;
int W[110];

int sum(int *start, int *goal)
{
  int ans = 0;
  for (auto it = start; it != goal; it++)
  {
    ans += *it;
  }
  return ans;
}

using Task_type = int(int *, int *);

#include <future>

int main()
{
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> W[i];
  }
  int ans = 100000000;
  for (auto i = 0; i <= N; i++)
  {
    packaged_task<Task_type> pt0{sum};
    packaged_task<Task_type> pt1{sum};
    future<int> f0{pt0.get_future()};
    future<int> f1{pt0.get_future()};
    thread t0{move(pt0), W, W + i};
    thread t1{move(pt1), W + i, W + N};
    mins(ans, abs(f0.get() - f1.get()));
  }
  cout << ans << endl;
}<commit_msg>tried B2.cpp to 'B'<commit_after>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 6/15/2019, 3:30:35 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
typedef long long ll;
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
const int MAX_SIZE = 1000010;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return mint(0) - *this; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
mint inv[MAX_SIZE];
mint fact[MAX_SIZE];
mint factinv[MAX_SIZE];
void init()
{
  inv[1] = 1;
  for (int i = 2; i < MAX_SIZE; i++)
  {
    inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
  }
  fact[0] = factinv[0] = 1;
  for (int i = 1; i < MAX_SIZE; i++)
  {
    fact[i] = mint(i) * fact[i - 1];
    factinv[i] = inv[i] * factinv[i - 1];
  }
}
mint choose(int n, int k)
{
  if (n >= 0 && k >= 0 && n - k >= 0)
  {
    return fact[n] * factinv[k] * factinv[n - k];
  }
  return 0;
}
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

int N;
int W[110];

int sum(int *start, int *goal)
{
  int ans = 0;
  for (auto it = start; it != goal; it++)
  {
    ans += *it;
  }
  return ans;
}

using Task_type = int(int *, int *);

#include <future>

int main()
{
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> W[i];
  }
  int ans = 100000000;
  for (auto i = 0; i <= N; i++)
  {
    packaged_task<Task_type> pt0{sum};
    packaged_task<Task_type> pt1{sum};
    future<int> f0{pt0.get_future()};
    future<int> f1{pt1.get_future()};
    thread t0{move(pt0), W, W + i};
    thread t1{move(pt1), W + i, W + N};
    mins(ans, abs(f0.get() - f1.get()));
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>#include <silicium/process.hpp>
#include <silicium/build_result.hpp>
#include <silicium/directory_allocator.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
#include <functional>
#include <fstream>
#include <iostream>

namespace Si
{
	struct build_context
	{
		std::function<boost::filesystem::path ()> allocate_temporary_directory;
	};

	build_context make_native_build_context(boost::filesystem::path temporary_directory_root)
	{
		const auto temporary_dirs = std::make_shared<temporary_directory_allocator>(std::move(temporary_directory_root));
		return build_context
		{
			std::bind(&temporary_directory_allocator::allocate, temporary_dirs)
		};
	}

}

namespace
{
	Si::build_result build(Si::build_context const &context)
	{
		const auto source_dir = context.allocate_temporary_directory();
		const auto source_file = (source_dir / "hello.cpp");
		{
			std::ofstream file(source_file.string());
			file << "#include <iostream>\nint main() { std::cout << \"Hello, world!\\n\"; }\n";
			if (!file)
			{
				throw std::runtime_error("Could not write source file");
			}
		}
		const auto build_dir = context.allocate_temporary_directory();
		const auto executable_file = build_dir / "hello";
		{
			const auto compilation_result = Si::run_process("/usr/bin/c++", {source_file.string(), "-o", executable_file.string()}, build_dir, true);
			if (compilation_result.exit_status != 0)
			{
				return Si::build_failure{"Compilation was not successful"};
			}
		}

		const auto testing_result = Si::run_process(executable_file.string(), {}, build_dir, true);
		if (testing_result.exit_status != 0)
		{
			return Si::build_failure{"The built executable returned failure"};
		}

		std::string const expected_output = "Hello, world!\n";
		if (testing_result.stdout != std::vector<char>(begin(expected_output), end(expected_output)))
		{
			return Si::build_failure{"The built executable did not print the expected text to stdout"};
		}

		return Si::build_success{};
	}

	struct result_printer : boost::static_visitor<>
	{
		explicit result_printer(std::ostream &out)
			: m_out(out)
		{
		}

		void operator()(Si::build_success) const
		{
			m_out << "success";
		}

		void operator()(Si::build_failure const &failure) const
		{
			m_out << "failure: " << failure.short_description;
		}

	private:

		std::ostream &m_out;
	};
}

int main()
{
	const auto context = Si::make_native_build_context(boost::filesystem::current_path());
	const Si::build_result result = build(context);
	result_printer printer(std::cerr);
	boost::apply_visitor(printer, result);
	std::cerr << '\n';
}
<commit_msg>remove build_context from example<commit_after>#include <silicium/process.hpp>
#include <silicium/build_result.hpp>
#include <silicium/directory_allocator.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
#include <functional>
#include <fstream>
#include <iostream>

namespace
{
	Si::build_result build(Si::directory_allocator const &allocate_temporary_dir)
	{
		const auto source_dir = allocate_temporary_dir();
		const auto source_file = (source_dir / "hello.cpp");
		{
			std::ofstream file(source_file.string());
			file << "#include <iostream>\nint main() { std::cout << \"Hello, world!\\n\"; }\n";
			if (!file)
			{
				throw std::runtime_error("Could not write source file");
			}
		}
		const auto build_dir = allocate_temporary_dir();
		const auto executable_file = build_dir / "hello";
		{
			const auto compilation_result = Si::run_process("/usr/bin/c++", {source_file.string(), "-o", executable_file.string()}, build_dir, true);
			if (compilation_result.exit_status != 0)
			{
				return Si::build_failure{"Compilation was not successful"};
			}
		}

		const auto testing_result = Si::run_process(executable_file.string(), {}, build_dir, true);
		if (testing_result.exit_status != 0)
		{
			return Si::build_failure{"The built executable returned failure"};
		}

		std::string const expected_output = "Hello, world!\n";
		if (testing_result.stdout != std::vector<char>(begin(expected_output), end(expected_output)))
		{
			return Si::build_failure{"The built executable did not print the expected text to stdout"};
		}

		return Si::build_success{};
	}

	struct result_printer : boost::static_visitor<>
	{
		explicit result_printer(std::ostream &out)
			: m_out(out)
		{
		}

		void operator()(Si::build_success) const
		{
			m_out << "success";
		}

		void operator()(Si::build_failure const &failure) const
		{
			m_out << "failure: " << failure.short_description;
		}

	private:

		std::ostream &m_out;
	};
}

int main()
{
	Si::temporary_directory_allocator temporary_dirs(boost::filesystem::current_path());
	Si::directory_allocator const allocate_temporary_dir = std::bind(&Si::temporary_directory_allocator::allocate, &temporary_dirs);
	const Si::build_result result = build(allocate_temporary_dir);
	result_printer printer(std::cerr);
	boost::apply_visitor(printer, result);
	std::cerr << '\n';
}
<|endoftext|>


<commit_before>#include "Splines.h"
#include "ui_Splines.h"

const float MAX_SPEED = 50.f;

Splines::Splines(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::Splines)
{
    m_ui->setupUi(this);

    m_ltcr = m_ui->ltcr->value() / 100.f;

    connect(m_ui->ltcr, &QSlider::valueChanged, [this](int value)
    {
       m_ltcr = value / 100.f;
    });

    connect(m_ui->applyLTCR, &QPushButton::released, [this]()
    {
       m_points = assignLTC(m_points, m_ltcr);
       m_shape = buildShape(m_points);
    });

    connect(m_ui->newShape, &QPushButton::released, [this]()
    {
       m_points = assignLTC(generatePoints(20, 200), m_ltcr);
       m_shape = buildShape(m_points);
    });

    auto timer = new QTimer(this);
    timer->setSingleShot(false);
    connect(timer, &QTimer::timeout, [this]()
    {
        update();
    });
    timer->start(16);
}

Splines::~Splines()
{
    delete m_ui;
}

void Splines::paintEvent(QPaintEvent*)
{
    auto now = Clock::now();
    if (now - m_last_target_tp > std::chrono::milliseconds(1000))
    {
        m_last_target_tp = now;

        std::random_device rd;
        std::default_random_engine e1(rd());
        std::uniform_real_distribution<float> rnd(0.f, 1.f);

        float x = rnd(e1) * (width() - m_shape.width());
        float y = rnd(e1) * (height() - m_shape.height());

        m_target = QPointF(x, y);
    }

    auto speed = m_ui->speed->value() / 10000.f;
    m_position = (m_position + (m_target - m_position) * speed);

    QPainter painter(this);
    painter.drawImage(m_position, m_shape);

    //make the splines
  //  drawSpline(painter, start, end, c0, c1);
}

std::vector<Splines::Point> Splines::generatePoints(size_t count, float radius)
{
    float angleInc = 2.f * M_PI / count;

    std::random_device rd;
    std::default_random_engine e1(rd());
    std::uniform_real_distribution<float> daRnd(-angleInc / 3.f, angleInc / 3.f);
    std::uniform_real_distribution<float> radiusRnd(radius / 2.f, radius);

    std::vector<Point> points;

    float angle = 0.f;
    for (size_t i = 0; i < count; i++)
    {
        float deltaAngle = daRnd(e1);
        float radius = radiusRnd(e1);

        float x = std::cos(angle + deltaAngle) * radius;
        float y = std::sin(angle + deltaAngle) * radius;

        Point p;
        p.point = QPointF(x, y);
        p.t = 0.f;
        points.push_back(p);

        angle += angleInc;
    }

    return points;
}

std::vector<Splines::Point> Splines::assignLTC(const std::vector<Splines::Point>& _points, float ltcr)
{
    std::random_device rd;
    std::default_random_engine e1(rd());
    std::uniform_real_distribution<float> ltcrRnd(0, 1);

    std::vector<Point> points = _points;

    for (auto& p: points)
    {
        if (ltcrRnd(e1) >= ltcr)
        {
            p.t = 0.f;
        }
        else
        {
            p.t = m_curviness;
        }
    }

    return points;
}

void Splines::getControlPoints(QPointF p0, QPointF p1, QPointF p2, float t, QPointF& c0, QPointF& c1)
{
    auto d01 = std::sqrt(std::pow(p1.x()-p0.x(),2.f)+std::pow(p1.y()-p0.y(),2));
    auto d12=std::sqrt(std::pow(p2.x()-p1.x(),2)+std::pow(p2.y()-p1.y(),2));
    auto fa=t*d01/(d01+d12);   // scaling factor for triangle Ta
    auto fb=t*d12/(d01+d12);   // ditto for Tb, simplifies to fb=t-fa
    auto p0x=p1.x()-fa*(p2.x()-p0.x());    // x2-x0 is the width of triangle T
    auto p0y=p1.y()-fa*(p2.y()-p0.y());    // y2-y0 is the height of T
    auto p1x=p1.x()+fb*(p2.x()-p0.x());
    auto p1y=p1.y()+fb*(p2.y()-p0.y());
    c0 = QPointF(p0x, p0y);
    c1 = QPointF(p1x, p1y);
}

struct fillpixelinfo
{
   int y, xl, xr, dy;
};

#define PUSH(py, pxl, pxr, pdy) \
{ \
    struct fillpixelinfo p;\
    if (((py) + (pdy) >= 0) && ((py) + (pdy) < image.height()))\
    {\
        p.y = (py);\
        p.xl = (pxl);\
        p.xr = (pxr);\
        p.dy = (pdy);\
        stack.push_back(p); \
    }\
}

#define POP(py, pxl, pxr, pdy) \
{\
    struct fillpixelinfo p = stack.back();\
    stack.pop_back();\
    (py) = p.y + p.dy;\
    (pxl) = p.xl;\
    (pxr) = p.xr;\
    (pdy) = p.dy;\
}

QImage Splines::floodFill(const QImage& img, const QPoint &pos, const QRgb &newColor)
{
   QImage image = img.copy();

   int x = pos.x(), y = pos.y();
   const QRgb oldColor = image.pixel(x, y);

   std::vector<fillpixelinfo> stack;

   int l, x1, x2, dy;

   if ((x >= 0) && (x < image.width()) && (y >= 0) && (y < image.height()))
   {
       if (qAlpha(oldColor) == 0xFF)
       {
           return image;
       }
       PUSH(y, x, x, 1);
       PUSH(y + 1, x, x, -1);
       while (!stack.empty())
       {
           POP(y, x1, x2, dy);
           for (x = x1; (x >= 0) && qAlpha(image.pixel(x, y)) != 0xFF; x--)
           {
               image.setPixel(x, y, newColor);
           }
           if (x >= x1)
           {
               goto skip;
           }
           l = x + 1;
           if (l < x1)
           {
               PUSH(y, l, x1 - 1, -dy);
           }
           x = x1 + 1;
           do
           {
               for (; (x < image.width()) && qAlpha(image.pixel(x, y)) != 0xFF; x++)
               {
                   image.setPixel(x, y, newColor);
               }
               PUSH(y, l, x - 1, dy);
               if (x > x2 + 1)
               {
                   PUSH(y, x2 + 1, x - 1, -dy);
               }
skip:
               for (x++; x <= x2 && qAlpha(image.pixel(x, y)) == 0xFF; x++)
               {
                   /* empty */ ;
               }
               l = x;
           } while (x <= x2);
       }
   }
   return image;
}

QImage Splines::buildShape(const std::vector<Point>& _points)
{
    if (_points.empty())
    {
        return QImage();
    }

    size_t n = _points.size();
    std::vector<Point> points = _points;

    QPointF min, max;
    min.setX(std::numeric_limits<float>::max());
    min.setY(std::numeric_limits<float>::max());
    max.setX(std::numeric_limits<float>::lowest());
    max.setY(std::numeric_limits<float>::lowest());
    for (const auto& p: points)
    {
        max.setX(std::max(max.x(), p.point.x()));
        max.setY(std::max(max.y(), p.point.y()));
        min.setX(std::min(min.x(), p.point.x()));
        min.setY(std::min(min.y(), p.point.y()));
    }

    {
        //re-center the points
        QPointF center = (max + min) / 2.f;
        for (auto& p: points)
        {
            p.point -= center;
        }
    }

    QSizeF imageSize((max - min).x(), (max - min).y());
    imageSize += QSize(200, 200);
    QPointF imageCenter(imageSize.width() / 2.f, imageSize.height() / 2.f);

    QImage image = QImage(imageSize.toSize(), QImage::Format_RGBA8888_Premultiplied);
    image.fill(0);

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing, true);

    QPen pen(Qt::white, 3.f);
    pen.setCapStyle(Qt::RoundCap);
    pen.setJoinStyle(Qt::RoundJoin);
    painter.setPen(pen);

    QPainterPath path;

    //   Append and prepend knots and control points to close the curve

    {
        auto last = points.back();
        points.push_back(*(points.begin() + 0));
        points.push_back(*(points.begin() + 1));
        points.insert(points.begin(), last);
    }

    std::vector<QPointF> cp;
    for(size_t i = 0; i < n; i++)
    {
        QPointF cp0, cp1;
        getControlPoints(points[i].point, points[i + 1].point, points[i + 2].point, points[i].t, cp0, cp1);
        cp.push_back(cp0);
        cp.push_back(cp1);
    }
    cp.push_back(cp.front());
    for(size_t i = 1; i < n + 1; i++)
    {
        //var color=HSVtoRGB(Math.floor(240*(i-2)/(n-2)),0.8,0.8);
        //if(!showDetails){color="#555555"}
        //ctx.strokeStyle=hexToCanvasColor(color,0.75);
        path.moveTo(imageCenter + points[i].point);
        path.cubicTo(imageCenter + cp[i*2 - 1], imageCenter + cp[i*2], imageCenter + points[i + 1].point);
    }

    path.setFillRule(Qt::WindingFill);
    painter.drawPath(path);

    return floodFill(image, imageCenter.toPoint(), qRgb(255, 255, 255));
}

<commit_msg>Initial shape<commit_after>#include "Splines.h"
#include "ui_Splines.h"

const float MAX_SPEED = 50.f;

Splines::Splines(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::Splines)
{
    m_ui->setupUi(this);

    m_ltcr = m_ui->ltcr->value() / 100.f;

    //generate first shape
    m_points = assignLTC(generatePoints(20, 200), m_ltcr);
    m_shape = buildShape(m_points);

    connect(m_ui->ltcr, &QSlider::valueChanged, [this](int value)
    {
       m_ltcr = value / 100.f;
    });

    connect(m_ui->applyLTCR, &QPushButton::released, [this]()
    {
       m_points = assignLTC(m_points, m_ltcr);
       m_shape = buildShape(m_points);
    });

    connect(m_ui->newShape, &QPushButton::released, [this]()
    {
       m_points = assignLTC(generatePoints(20, 200), m_ltcr);
       m_shape = buildShape(m_points);
    });

    auto timer = new QTimer(this);
    timer->setSingleShot(false);
    connect(timer, &QTimer::timeout, [this]()
    {
        update();
    });
    timer->start(16);
}

Splines::~Splines()
{
    delete m_ui;
}

void Splines::paintEvent(QPaintEvent*)
{
    auto now = Clock::now();
    if (now - m_last_target_tp > std::chrono::milliseconds(1000))
    {
        m_last_target_tp = now;

        std::random_device rd;
        std::default_random_engine e1(rd());
        std::uniform_real_distribution<float> rnd(0.f, 1.f);

        float x = rnd(e1) * (width() - m_shape.width());
        float y = rnd(e1) * (height() - m_shape.height());

        m_target = QPointF(x, y);
    }

    auto speed = m_ui->speed->value() / 10000.f;
    m_position = (m_position + (m_target - m_position) * speed);

    QPainter painter(this);
    painter.drawImage(m_position, m_shape);

    //make the splines
  //  drawSpline(painter, start, end, c0, c1);
}

std::vector<Splines::Point> Splines::generatePoints(size_t count, float radius)
{
    float angleInc = 2.f * M_PI / count;

    std::random_device rd;
    std::default_random_engine e1(rd());
    std::uniform_real_distribution<float> daRnd(-angleInc / 3.f, angleInc / 3.f);
    std::uniform_real_distribution<float> radiusRnd(radius / 2.f, radius);

    std::vector<Point> points;

    float angle = 0.f;
    for (size_t i = 0; i < count; i++)
    {
        float deltaAngle = daRnd(e1);
        float radius = radiusRnd(e1);

        float x = std::cos(angle + deltaAngle) * radius;
        float y = std::sin(angle + deltaAngle) * radius;

        Point p;
        p.point = QPointF(x, y);
        p.t = 0.f;
        points.push_back(p);

        angle += angleInc;
    }

    return points;
}

std::vector<Splines::Point> Splines::assignLTC(const std::vector<Splines::Point>& _points, float ltcr)
{
    std::random_device rd;
    std::default_random_engine e1(rd());
    std::uniform_real_distribution<float> ltcrRnd(0, 1);

    std::vector<Point> points = _points;

    for (auto& p: points)
    {
        if (ltcrRnd(e1) >= ltcr)
        {
            p.t = 0.f;
        }
        else
        {
            p.t = m_curviness;
        }
    }

    return points;
}

void Splines::getControlPoints(QPointF p0, QPointF p1, QPointF p2, float t, QPointF& c0, QPointF& c1)
{
    auto d01 = std::sqrt(std::pow(p1.x()-p0.x(),2.f)+std::pow(p1.y()-p0.y(),2));
    auto d12=std::sqrt(std::pow(p2.x()-p1.x(),2)+std::pow(p2.y()-p1.y(),2));
    auto fa=t*d01/(d01+d12);   // scaling factor for triangle Ta
    auto fb=t*d12/(d01+d12);   // ditto for Tb, simplifies to fb=t-fa
    auto p0x=p1.x()-fa*(p2.x()-p0.x());    // x2-x0 is the width of triangle T
    auto p0y=p1.y()-fa*(p2.y()-p0.y());    // y2-y0 is the height of T
    auto p1x=p1.x()+fb*(p2.x()-p0.x());
    auto p1y=p1.y()+fb*(p2.y()-p0.y());
    c0 = QPointF(p0x, p0y);
    c1 = QPointF(p1x, p1y);
}

struct fillpixelinfo
{
   int y, xl, xr, dy;
};

#define PUSH(py, pxl, pxr, pdy) \
{ \
    struct fillpixelinfo p;\
    if (((py) + (pdy) >= 0) && ((py) + (pdy) < image.height()))\
    {\
        p.y = (py);\
        p.xl = (pxl);\
        p.xr = (pxr);\
        p.dy = (pdy);\
        stack.push_back(p); \
    }\
}

#define POP(py, pxl, pxr, pdy) \
{\
    struct fillpixelinfo p = stack.back();\
    stack.pop_back();\
    (py) = p.y + p.dy;\
    (pxl) = p.xl;\
    (pxr) = p.xr;\
    (pdy) = p.dy;\
}

QImage Splines::floodFill(const QImage& img, const QPoint &pos, const QRgb &newColor)
{
   QImage image = img.copy();

   int x = pos.x(), y = pos.y();
   const QRgb oldColor = image.pixel(x, y);

   std::vector<fillpixelinfo> stack;

   int l, x1, x2, dy;

   if ((x >= 0) && (x < image.width()) && (y >= 0) && (y < image.height()))
   {
       if (qAlpha(oldColor) == 0xFF)
       {
           return image;
       }
       PUSH(y, x, x, 1);
       PUSH(y + 1, x, x, -1);
       while (!stack.empty())
       {
           POP(y, x1, x2, dy);
           for (x = x1; (x >= 0) && qAlpha(image.pixel(x, y)) != 0xFF; x--)
           {
               image.setPixel(x, y, newColor);
           }
           if (x >= x1)
           {
               goto skip;
           }
           l = x + 1;
           if (l < x1)
           {
               PUSH(y, l, x1 - 1, -dy);
           }
           x = x1 + 1;
           do
           {
               for (; (x < image.width()) && qAlpha(image.pixel(x, y)) != 0xFF; x++)
               {
                   image.setPixel(x, y, newColor);
               }
               PUSH(y, l, x - 1, dy);
               if (x > x2 + 1)
               {
                   PUSH(y, x2 + 1, x - 1, -dy);
               }
skip:
               for (x++; x <= x2 && qAlpha(image.pixel(x, y)) == 0xFF; x++)
               {
                   /* empty */ ;
               }
               l = x;
           } while (x <= x2);
       }
   }
   return image;
}

QImage Splines::buildShape(const std::vector<Point>& _points)
{
    if (_points.empty())
    {
        return QImage();
    }

    size_t n = _points.size();
    std::vector<Point> points = _points;

    QPointF min, max;
    min.setX(std::numeric_limits<float>::max());
    min.setY(std::numeric_limits<float>::max());
    max.setX(std::numeric_limits<float>::lowest());
    max.setY(std::numeric_limits<float>::lowest());
    for (const auto& p: points)
    {
        max.setX(std::max(max.x(), p.point.x()));
        max.setY(std::max(max.y(), p.point.y()));
        min.setX(std::min(min.x(), p.point.x()));
        min.setY(std::min(min.y(), p.point.y()));
    }

    {
        //re-center the points
        QPointF center = (max + min) / 2.f;
        for (auto& p: points)
        {
            p.point -= center;
        }
    }

    QSizeF imageSize((max - min).x(), (max - min).y());
    imageSize += QSize(200, 200);
    QPointF imageCenter(imageSize.width() / 2.f, imageSize.height() / 2.f);

    QImage image = QImage(imageSize.toSize(), QImage::Format_RGBA8888_Premultiplied);
    image.fill(0);

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing, true);

    QPen pen(Qt::white, 3.f);
    pen.setCapStyle(Qt::RoundCap);
    pen.setJoinStyle(Qt::RoundJoin);
    painter.setPen(pen);

    QPainterPath path;

    //   Append and prepend knots and control points to close the curve

    {
        auto last = points.back();
        points.push_back(*(points.begin() + 0));
        points.push_back(*(points.begin() + 1));
        points.insert(points.begin(), last);
    }

    std::vector<QPointF> cp;
    for(size_t i = 0; i < n; i++)
    {
        QPointF cp0, cp1;
        getControlPoints(points[i].point, points[i + 1].point, points[i + 2].point, points[i].t, cp0, cp1);
        cp.push_back(cp0);
        cp.push_back(cp1);
    }
    cp.push_back(cp.front());
    for(size_t i = 1; i < n + 1; i++)
    {
        //var color=HSVtoRGB(Math.floor(240*(i-2)/(n-2)),0.8,0.8);
        //if(!showDetails){color="#555555"}
        //ctx.strokeStyle=hexToCanvasColor(color,0.75);
        path.moveTo(imageCenter + points[i].point);
        path.cubicTo(imageCenter + cp[i*2 - 1], imageCenter + cp[i*2], imageCenter + points[i + 1].point);
    }

    path.setFillRule(Qt::WindingFill);
    painter.drawPath(path);

    return floodFill(image, imageCenter.toPoint(), qRgb(255, 255, 255));
}

<|endoftext|>


<commit_before>/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_RColor
#define ROOT7_RColor

#include <ROOT/RAttrBase.hxx>

#include <array>

namespace ROOT {
namespace Experimental {

// TODO: see also imagemagick's C++ interface for RColor operations!
// https://www.imagemagick.org/api/magick++-classes.php

/** \class RColor
\ingroup GpadROOT7
\brief The color class
\author Axel Naumann <axel@cern.ch>
\date 2017-09-26
\warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
*/

class RColor : public RAttrBase {

   R__ATTR_CLASS(RColor, "color_", AddString("rgb", "").AddString("a", "").AddString("name", ""));

   using RGB_t = std::array<int, 3>;

private:

   static std::string toHex(int v);

   /** Set RGB values as floats, each from 0..1. Real color values will be stored in hex format */
   RColor &SetRGBFloat(float r, float g, float b)
   {
      return SetRGB(int(r*255),int(g*255),int(b*255));
   }

   bool GetRGBFloat(float &r, float &g, float &b) const;

   int GetColorComponent(int indx) const;

public:

   /** Construct color with provided r,g,b values */
   RColor(int r, int g, int b) : RColor() { SetRGB(r, g, b); }

   /** Construct color with provided r,g,b and alpha values */
   RColor(int r, int g, int b, float alpha) : RColor()
   {
      SetRGB(r, g, b);
      SetAlpha(alpha);
   }

   /** Construct color with provided RGB_t value */
   RColor(const RGB_t &rgb) : RColor() { SetRGB(rgb[0], rgb[1], rgb[2]); }

   /** Set r/g/b/ components of color as hex code, default for the color */
   RColor &SetRGB(int r, int g, int b)
   {
      return SetHex(toHex(r) + toHex(g) + toHex(b));
   }

   /** Set color as hex string like 00FF00 */
   RColor &SetHex(const std::string &_hex)
   {
      SetValue("rgb", _hex);
      return *this;
   }

   /** Return color as hex string like 00FF00 */
   std::string GetHex() const { return GetValue<std::string>("rgb"); }

   bool GetRGB(int &r, int &g, int &b) const;

   /** Returns red color component 0..255 */
   int GetRed() const { return GetColorComponent(0); }

   /** Returns green color component 0..255 */
   int GetGreen() const { return GetColorComponent(1); }

   /** Returns blue color component 0..255 */
   int GetBlue() const { return GetColorComponent(2); }

   /** Clear RGB color value (if any) */
   void ClearRGB()
   {
      ClearValue("rgb");
   }

   /** Set color as plain SVG name like "white" or "lightblue". Clears RGB component before */
   RColor &SetName(const std::string &_name)
   {
      ClearRGB();
      SetValue("name", _name);
      return *this;
   }

   /** Returns color as plain SVG name like "white" or "lightblue" */
   std::string GetName() const { return GetValue<std::string>("name"); }

   /** Clear color plain SVG name (if any) */
   void ClearName()
   {
      ClearValue("name");
   }

   /** Returns color alpha (opacity) as float from 0. to 1. */
   float GetAlpha() const
   {
      auto hex = GetAlphaHex();
      if (hex.empty())
         return 1.;
      return std::strtol(hex.c_str(), nullptr, 16) / 255.;
   }

   /** Returns color alpha (opacity) as hex string like FF. Default is empty */
   std::string GetAlphaHex() const { return GetValue<std::string>("a"); }

   /** Returns true if color alpha (opacity) was specified */
   bool HasAlpha() const { return HasValue("a"); }

   /** Set color alpha (opacity) value - from 0 to 1 */
   RColor &SetAlpha(float _alpha)
   {
      return SetAlphaHex(toHex((int) (_alpha*255)));
   }

   /** Set color alpha (opacity) value as hex string */
   RColor &SetAlphaHex(const std::string &_alfa)
   {
      SetValue("a", _alfa);
      return *this;
   }

   /** Return the Hue, Light, Saturation (HLS) definition of this RColor */
   bool GetHLS(float &hue, float &light, float &satur) const;

   /** Set the Red Green and Blue (RGB) values from the Hue, Light, Saturation (HLS). */
   RColor &SetHLS(float hue, float light, float satur);

   /** Returns color value as it will be used in SVG drawing
    * It either include hex format #66FF66 or just plain SVG name */
   std::string AsSVG() const
   {
      auto hex = GetHex();
      if (!hex.empty()) {
         std::string res = "#";
         res.append(hex);
         res.append(GetAlphaHex());
         return res;
      }

      // check that alpha is not specified
      return GetName();
   }

   static constexpr RGB_t kRed{{255, 0, 0}};
   static constexpr RGB_t kGreen{{0, 255, 0}};
   static constexpr RGB_t kBlue{{0, 0, 255}};
   static constexpr RGB_t kWhite{{255, 255, 255}};
   static constexpr RGB_t kBlack{{0, 0, 0}};
   static constexpr double kTransparent{0.};
   static constexpr double kOpaque{1.};

   friend bool operator==(const RColor &lhs, const RColor &rhs)
   {
      return (lhs.GetHex() == rhs.GetHex()) && (lhs.GetName() == rhs.GetName()) &&
             (lhs.GetAlphaHex() == rhs.GetAlphaHex());
   }
};

} // namespace Experimental
} // namespace ROOT

#endif
<commit_msg>[rcolor] add auto property for the RColor<commit_after>/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_RColor
#define ROOT7_RColor

#include <ROOT/RAttrBase.hxx>

#include <array>

namespace ROOT {
namespace Experimental {

// TODO: see also imagemagick's C++ interface for RColor operations!
// https://www.imagemagick.org/api/magick++-classes.php

/** \class RColor
\ingroup GpadROOT7
\brief The color class
\author Axel Naumann <axel@cern.ch>
\author Sergey Linev <S.Linev@gsi.de>
\date 2017-09-26
\warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
*/

class RColor : public RAttrBase {

   R__ATTR_CLASS(RColor, "color_", AddString("rgb", "").AddString("a", "").AddString("name", "").AddBool("auto", false));

   using RGB_t = std::array<int, 3>;

private:

   static std::string toHex(int v);

   /** Set RGB values as floats, each from 0..1. Real color values will be stored in hex format */
   RColor &SetRGBFloat(float r, float g, float b)
   {
      return SetRGB(int(r*255),int(g*255),int(b*255));
   }

   bool GetRGBFloat(float &r, float &g, float &b) const;

   int GetColorComponent(int indx) const;

public:

   /** Construct color with provided r,g,b values */
   RColor(int r, int g, int b) : RColor() { SetRGB(r, g, b); }

   /** Construct color with provided r,g,b and alpha values */
   RColor(int r, int g, int b, float alpha) : RColor()
   {
      SetRGB(r, g, b);
      SetAlpha(alpha);
   }

   /** Construct color with provided RGB_t value */
   RColor(const RGB_t &rgb) : RColor() { SetRGB(rgb[0], rgb[1], rgb[2]); }

   /** Set r/g/b/ components of color as hex code, default for the color */
   RColor &SetRGB(int r, int g, int b) { return SetHex(toHex(r) + toHex(g) + toHex(b)); }

   /** Set color as hex string like 00FF00 */
   RColor &SetHex(const std::string &_hex)
   {
      SetValue("rgb", _hex);
      return *this;
   }

   /** Return color as hex string like 00FF00 */
   std::string GetHex() const { return GetValue<std::string>("rgb"); }

   bool GetRGB(int &r, int &g, int &b) const;

   /** Returns red color component 0..255 */
   int GetRed() const { return GetColorComponent(0); }

   /** Returns green color component 0..255 */
   int GetGreen() const { return GetColorComponent(1); }

   /** Returns blue color component 0..255 */
   int GetBlue() const { return GetColorComponent(2); }

   /** Clear RGB color value (if any) */
   void ClearRGB()
   {
      ClearValue("rgb");
   }

   /** Set color as plain SVG name like "white" or "lightblue". Clears RGB component before */
   RColor &SetName(const std::string &_name)
   {
      ClearRGB();
      SetValue("name", _name);
      return *this;
   }

   /** Returns color as plain SVG name like "white" or "lightblue" */
   std::string GetName() const { return GetValue<std::string>("name"); }

   /** Clear color plain SVG name (if any) */
   void ClearName() { ClearValue("name"); }

   /** Returns color alpha (opacity) as float from 0. to 1. */
   float GetAlpha() const
   {
      auto hex = GetAlphaHex();
      if (hex.empty())
         return 1.;
      return std::strtol(hex.c_str(), nullptr, 16) / 255.;
   }

   /** Returns color alpha (opacity) as hex string like FF. Default is empty */
   std::string GetAlphaHex() const { return GetValue<std::string>("a"); }

   /** Returns true if color alpha (opacity) was specified */
   bool HasAlpha() const { return HasValue("a"); }

   /** Set color alpha (opacity) value - from 0 to 1 */
   RColor &SetAlpha(float _alpha) { return SetAlphaHex(toHex((int)(_alpha * 255))); }

   /** Set color alpha (opacity) value as hex string */
   RColor &SetAlphaHex(const std::string &_alfa)
   {
      SetValue("a", _alfa);
      return *this;
   }

   /** Clear alpha value of the color */
   void ClearAlpha() { ClearValue("a"); }

   /** Returns true if color should get auto value when primitive drawing is performed */
   bool IsAuto() const { return GetValue<bool>("auto"); }

   /** Set automatic mode for RColor, will be assigned before primitive painted on the canvas */
   RColor &SetAuto(bool on = true)
   {
      SetValue("auto", on);
      return *this;
   }

   /** Clear auto flag of the RColor */
   void ClearAuto() { ClearValue("auto"); }

   /** Return the Hue, Light, Saturation (HLS) definition of this RColor */
   bool GetHLS(float &hue, float &light, float &satur) const;

   /** Set the Red Green and Blue (RGB) values from the Hue, Light, Saturation (HLS). */
   RColor &SetHLS(float hue, float light, float satur);

   /** Returns color value as it will be used in SVG drawing
    * It either include hex format #66FF66 or just plain SVG name */
   std::string AsSVG() const
   {
      auto hex = GetHex();
      if (!hex.empty())
         return std::string("#") + hex + GetAlphaHex();

      // check that alpha is not specified
      return GetName();
   }

   void Clear()
   {
      ClearRGB();
      ClearName();
      ClearAlpha();
      ClearAuto();
   }

   static constexpr RGB_t kRed{{255, 0, 0}};
   static constexpr RGB_t kGreen{{0, 255, 0}};
   static constexpr RGB_t kBlue{{0, 0, 255}};
   static constexpr RGB_t kWhite{{255, 255, 255}};
   static constexpr RGB_t kBlack{{0, 0, 0}};
   static constexpr double kTransparent{0.};
   static constexpr double kOpaque{1.};

   friend bool operator==(const RColor &lhs, const RColor &rhs)
   {
      return (lhs.GetHex() == rhs.GetHex()) && (lhs.GetName() == rhs.GetName()) &&
             (lhs.GetAlphaHex() == rhs.GetAlphaHex()) && (lhs.IsAuto() == rhs.IsAuto());
   }
};

} // namespace Experimental
} // namespace ROOT

#endif
<|endoftext|>