<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include "class/SysCommand.h"
#include "class/MakeFile.h"
#include "class/ExistDirFile.h"
#include "class/Validate.h"

//make standard library name space
using namespace std;

// start main of DSCv project
int main()
{
	//make input string variable
	string pointer,
		   dominName,
		   ipAddress,
		   optionv4,
		   zoneDirectory,
		   allowQuery,
		   typeZone,
		   allowUpdate,
		   linuxType,
		   bindInstallStatus,
		   line;

    //make input boolian variable
    //defualt bind dns options
	bool recurasion = false;
	bool dnssec_enable =  true;
	bool dnssec_validation = true;
	bool bindInstall = false;
	bool bindBackupExist = false;
	bool ipVer4Status = false;
	bool dominNameStatus = false;

	char getKeyPress;

	//check linux distro
	ifstream getLinuxType;
	getLinuxType.open("/etc/os-release");
		if(getLinuxType.is_open())
		{
			while( getline(getLinuxType, line) )
			{
				if(line.find("NAME=\"Ubuntu\""))
				{
					linuxType = "Ubuntu";
				}
				else if(line.find("NAME=\"Centos\""))
				{
					linuxType = "Centos";
				}
				else if(line.find("NAME=\"Fedora\""))
				{
					linuxType = "Fedora";
				}
				else if(line.find("Debian GUN/Linux"))
				{
					linuxType = "Debian";
				}
				else
				{
					linuxType = "Unkhowe Os";
				}
			}
		}

	while(true)
	{

		//check bind is install
		ExistDirFile ExistDirObject;
		bindInstall = ExistDirObject.bindIsInstall(linuxType);

		//return bind install status
		SysCommand BindStatus;
		bindInstallStatus = BindStatus.bindInstallStatus(bindInstall);

		//run command
		SysCommand syscommand;

		 system("reset");
		 cout << "Easy Bind Config version 0.1 \n";
		 cout << "-------------------------------------------------------\n";
		 cout << "	+ EBC help to you make easy CONFIG and ZOON file for Bind Dns Server \n";
		 cout << "	+ Author 	: VAHID HEIDARI \n";
		 cout << "	+ Author EMAIL  : vahid-heidari@hotmail.com \n";
		 cout << "	+ License  	: MIT License \n";
		 cout << "-------------------------------------------------------\n";
		 cout << "Your linux is :  " << linuxType << " distro " << endl;
		 cout << "\n";
		 cout << "Bind dns server is : " << bindInstallStatus << endl;
		 cout << "-------------------------------------------------------\n";

		//check BindBackup is exist in /etc/bind
		bindBackupExist = ExistDirObject.chekingBindBackup(linuxType);

		 if(bindInstall)
		 {

		 	//get command by pointer
		 	cout << "For initial bind server please type 'config' \n";
		 	cout << "	+If you need help type 'help' \n";
		 	cout << "EBC > ";
		 	cin  >> pointer;

		 	if(pointer == "config")
		 	{

			 	if(linuxType == "Ubuntu")
				{

				 	if(!bindBackupExist)
				 	{
				 		//make backup from bind file
				 		SysCommand bindBackUpFile;
				 		bindBackUpFile.copyAndMakeBackup(linuxType);
				 	}

				 	cout << "EBC find Bind Dns Server software \n";
				 	cout << "	+Please insert ip server ex = 48.10.15.30\n";
				 	cout << "EBC > ";
				 	cin  >> pointer;

				 	if(pointer == "exit")
				 	{
						syscommand.exitFromEbc();
				 	}
				 	else if(pointer == "back")
				 	{
				 		continue;
				 	}
				 	else if(pointer == "help")
				 	{
				 		//todo
				 	}
				 	else
				 	{
				 		ipAddress = pointer;

				 		//chack ipAddress version 4
				 		Validate validInput;
				 		ipVer4Status = validInput.validateIpV4Address(ipAddress);

					 	if(!ipVer4Status)
					 	{
					 		cout << "Your input ip is not valid ! Please Wait easyBindConfig restart...\n";
					 		usleep(3000000);
					 		continue;
					 	}

				 	   cout << "	+Please insert domin name ex = mydomin.com\n";
   				 	   cout << "EBC > ";
   				 	   cin  >>	pointer;

   				 		if(pointer == "exit")
					 	{
							syscommand.exitFromEbc();
					 	}
					 	else if(pointer == "back")
					 	{
					 		continue;
					 	}
					 	else if(pointer == "help")
				 		{
				 			//todo
				 		}
   					  	else
   					  	{
   					  	    dominName = pointer;

		   				    //check dominName input by user
		   			   	    dominNameStatus = validInput.validateDomineName(dominName);
		   				    if(!dominNameStatus)
		   				    {
		   				 	   	cout << "Your input domine name is not valid ! Please Wait easyBindConfig restart...\n";
		   				 	   	usleep(3000000);
		   				 	   	continue;
		   				    }

		   				 	// making bind9 file in /etc/default/bind9
		   				 	MakeFile makeBind9;
		   				 	makeBind9.ubuntuMakeBind9File();

		   				 	// make and backup zone file in /etc/bind/zones
		   				 	// update zone and master file
		   				 	MakeFile MakeZoneFile;
		   				 	MakeZoneFile.ubuntuUpdateZoneInNamedFile(dominName);
		   				 	MakeZoneFile.ubuntuUpdateMasterInNamedFile(ipAddress);

						    // make zone file and master file
							MakeZoneFile.ubuntuMakeZoneFile(dominName, ipAddress);
						 	MakeZoneFile.ubuntuMakeMasterFile(dominName, ipAddress);

						 	system("reset");

						 	cout << "Please wite ... \n";
						 	cout << "------------------------------------------------ \n";
						 	cout << "BIND IS NOW CONFIG BY easyBindConfig ;-)\n";
						 	cout << "------------------------------------------------ \n";
						 	cout << "Your  ip address : " << ipAddress << endl;
		   				 	cout << "Your domin name  : " << dominName << endl;
		   				 	cout << "Your nameserver  : " << "dns1." << dominName << endl;
		   				 	cout << "Your nameserver  : " << "dns2." << dominName << endl;
						 	cout << "------------------------------------------------ \n";

						 	//restart bind dns server
						 	syscommand.bindServiceRestart(linuxType);

		   				 	usleep(10000000);
   					  	}

				 	}

				}
				else if(linuxType == "Centos")
				{
					//todo
				}
				else if(linuxType == "Fedora")
				{
					//todo
				}
				else if(linuxType == "Debian")
				{
					//todo
				}
		 	}
		 	else if(pointer == "help")
		 	{

		 	}
		 	else if(pointer == "remove")
		 	{
		 		syscommand.bindServiceUnistall(linuxType);
		 	}
		 	else if(pointer == "restor")
		 	{
		 		syscommand.restoreOrginalfile(linuxType);
		 	}
		 	else if(pointer == "start")
		 	{
		 		syscommand.bindServiceStart(linuxType);
		 	}
		 	else if(pointer == "stop")
		 	{
		 		syscommand.bindServiceStop(linuxType);
		 	}
		 	else if(pointer == "enable")
		 	{
		 		syscommand.bindServiceEnable(linuxType);
		 	}
		 	else if(pointer == "disable")
		 	{
		 		syscommand.bindServiceDisable(linuxType);

		 	}
		 	else if(pointer == "reset")
		 	{
		 		syscommand.bindServiceRestart(linuxType);
		 	}
		 	else if(pointer == "exit")
		 	{
		 		syscommand.exitFromEbc();
		 	}

		 }
		 else
		 {
		 	cout << "EBC NOTfind Bind Dns Server software \n";
			cout << "	+For install Bind Dns Server Soft type 'install' \n";
			cout << "EBC > ";
			cin  >>	pointer;
			if(pointer == "install")
			{
				//install bind service on linux by linuxType
				SysCommand BindServiceInstall;
				BindServiceInstall.bindServiceInstall(linuxType);
				BindServiceInstall.bindServiceStart(linuxType);
				BindServiceInstall.bindServiceEnable(linuxType);
			}
			system("clear");
			bindInstall = true;
			continue;
		 }

	} //end of while

}<commit_msg>change linux distro check . fix distro check and change keyword name to ID. add mint ditro<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include "class/SysCommand.h"
#include "class/MakeFile.h"
#include "class/ExistDirFile.h"
#include "class/Validate.h"

//make standard library name space
using namespace std;

// start main of DSCv project
int main()
{
	//make input string variable
	string pointer,
		   dominName,
		   ipAddress,
		   optionv4,
		   zoneDirectory,
		   allowQuery,
		   typeZone,
		   allowUpdate,
		   linuxType,
		   linuxName,
		   bindInstallStatus,
		   line;

    //make input boolian variable
    //defualt bind dns options
	bool recurasion = false;
	bool dnssec_enable =  true;
	bool dnssec_validation = true;
	bool bindInstall = false;
	bool bindBackupExist = false;
	bool ipVer4Status = false;
	bool dominNameStatus = false;

	char getKeyPress;

	//check linux distro
	ifstream getLinuxType;
	getLinuxType.open("/etc/os-release");
		if(getLinuxType.is_open())
		{
			while(!getLinuxType.eof())
			{
				getline(getLinuxType, line);
				if(line.find("ID=ubuntu", 0) != string::npos)
				{
					linuxType = "Ubuntu";
					linuxName = "Ubuntu";
				}
				else if(line.find("ID=linuxmint", 0) != string::npos)
				{
					linuxType = "Ubuntu";
					linuxName = "linuxmint";
				}
				else if(line.find("ID=\"centos\"", 0) != string::npos)
				{
					linuxType = "Centos";
					linuxName = "Centos";
				}
				else if(line.find("ID=fedora", 0) != string::npos)
				{
					linuxType = "Fedora";
					linuxName = "Fedora";

				}
				else if(line.find("ID=debian", 0) != string::npos)
				{
					linuxType = "Debian";
					linuxName = "Debian";
				}
			}
		}

	while(true)
	{

		//check bind is install
		ExistDirFile ExistDirObject;
		bindInstall = ExistDirObject.bindIsInstall(linuxType);

		//return bind install status
		SysCommand BindStatus;
		bindInstallStatus = BindStatus.bindInstallStatus(bindInstall);

		//run command
		SysCommand syscommand;

		if(linuxName == "")
		{
			linuxType = "Unkhowe os";
			linuxName = "Unkhowe Os";
		}

		 system("reset");
		 cout << "Easy Bind Config version 0.1 \n";
		 cout << "-------------------------------------------------------\n";
		 cout << "	+ EBC help to you make easy CONFIG and ZOON file for Bind Dns Server \n";
		 cout << "	+ Author 	: VAHID HEIDARI \n";
		 cout << "	+ Author EMAIL  : vahid-heidari@hotmail.com \n";
		 cout << "	+ License  	: MIT License \n";
		 cout << "-------------------------------------------------------\n";
		 cout << "Your linux is :  " << linuxName << " distro " << endl;
		 cout << "\n";
		 cout << "Bind dns server is : " << bindInstallStatus << endl;
		 cout << "-------------------------------------------------------\n";

		 if(linuxType == "Unkhowe Os")
		 {
		 	cout << "-------------------------------------------------------\n";
		 	cout << "EBC Unkhowe Os and not work on linux distro !\n";
		 	cout << "easyBindConfig only work on Ubuntu,Mint,Centos,Fedora,Debian \n";
		 	cout << "-------------------------------------------------------\n";
		 	usleep(3000000);
		 	syscommand.exitFromEbc();
		 }

		//check BindBackup is exist in /etc/bind
		bindBackupExist = ExistDirObject.chekingBindBackup(linuxType);

		 if(bindInstall)
		 {

		 	//get command by pointer
		 	cout << "For initial bind server please type 'config' \n";
		 	cout << "	+If you need help type 'help' \n";
		 	cout << "EBC > ";
		 	cin  >> pointer;

		 	if(pointer == "config")
		 	{

			 	if(linuxType == "Ubuntu")
				{

				 	if(!bindBackupExist)
				 	{
				 		//make backup from bind file
				 		SysCommand bindBackUpFile;
				 		bindBackUpFile.copyAndMakeBackup(linuxType);
				 	}

				 	cout << "EBC find Bind Dns Server software \n";
				 	cout << "	+Please insert ip server ex = 48.10.15.30\n";
				 	cout << "EBC > ";
				 	cin  >> pointer;

				 	if(pointer == "exit")
				 	{
						syscommand.exitFromEbc();
				 	}
				 	else if(pointer == "back")
				 	{
				 		continue;
				 	}
				 	else if(pointer == "help")
				 	{
				 		//todo
				 	}
				 	else
				 	{
				 		ipAddress = pointer;

				 		//chack ipAddress version 4
				 		Validate validInput;
				 		ipVer4Status = validInput.validateIpV4Address(ipAddress);

					 	if(!ipVer4Status)
					 	{
					 		cout << "Your input ip is not valid ! Please Wait easyBindConfig restart...\n";
					 		usleep(3000000);
					 		continue;
					 	}

				 	   cout << "	+Please insert domin name ex = mydomin.com\n";
   				 	   cout << "EBC > ";
   				 	   cin  >>	pointer;

   				 		if(pointer == "exit")
					 	{
							syscommand.exitFromEbc();
					 	}
					 	else if(pointer == "back")
					 	{
					 		continue;
					 	}
					 	else if(pointer == "help")
				 		{
				 			//todo
				 		}
   					  	else
   					  	{
   					  	    dominName = pointer;

		   				    //check dominName input by user
		   			   	    dominNameStatus = validInput.validateDomineName(dominName);
		   				    if(!dominNameStatus)
		   				    {
		   				 	   	cout << "Your input domine name is not valid ! Please Wait easyBindConfig restart...\n";
		   				 	   	usleep(3000000);
		   				 	   	continue;
		   				    }

		   				 	// making bind9 file in /etc/default/bind9
		   				 	MakeFile makeBind9;
		   				 	makeBind9.ubuntuMakeBind9File();

		   				 	// make and backup zone file in /etc/bind/zones
		   				 	// update zone and master file
		   				 	MakeFile MakeZoneFile;
		   				 	MakeZoneFile.ubuntuUpdateZoneInNamedFile(dominName);
		   				 	MakeZoneFile.ubuntuUpdateMasterInNamedFile(ipAddress);

						    // make zone file and master file
							MakeZoneFile.ubuntuMakeZoneFile(dominName, ipAddress);
						 	MakeZoneFile.ubuntuMakeMasterFile(dominName, ipAddress);

						 	system("reset");

						 	cout << "Please wite ... \n";
						 	cout << "------------------------------------------------ \n";
						 	cout << "BIND IS NOW CONFIG BY easyBindConfig ;-)\n";
						 	cout << "------------------------------------------------ \n";
						 	cout << "Your  ip address : " << ipAddress << endl;
		   				 	cout << "Your domin name  : " << dominName << endl;
		   				 	cout << "Your nameserver  : " << "dns1." << dominName << endl;
		   				 	cout << "Your nameserver  : " << "dns2." << dominName << endl;
						 	cout << "------------------------------------------------ \n";

						 	//restart bind dns server
						 	syscommand.bindServiceRestart(linuxType);

		   				 	usleep(10000000);
   					  	}

				 	}

				}
				else if(linuxType == "Centos")
				{
					//todo
				}
				else if(linuxType == "Fedora")
				{
					//todo
				}
				else if(linuxType == "Debian")
				{
					//todo
				}
		 	}
		 	else if(pointer == "help")
		 	{

		 	}
		 	else if(pointer == "remove")
		 	{
		 		syscommand.bindServiceUnistall(linuxType);
		 	}
		 	else if(pointer == "restor")
		 	{
		 		syscommand.restoreOrginalfile(linuxType);
		 	}
		 	else if(pointer == "start")
		 	{
		 		syscommand.bindServiceStart(linuxType);
		 	}
		 	else if(pointer == "stop")
		 	{
		 		syscommand.bindServiceStop(linuxType);
		 	}
		 	else if(pointer == "enable")
		 	{
		 		syscommand.bindServiceEnable(linuxType);
		 	}
		 	else if(pointer == "disable")
		 	{
		 		syscommand.bindServiceDisable(linuxType);

		 	}
		 	else if(pointer == "reset")
		 	{
		 		syscommand.bindServiceRestart(linuxType);
		 	}
		 	else if(pointer == "exit")
		 	{
		 		syscommand.exitFromEbc();
		 	}

		 }
		 else
		 {
		 	cout << "EBC NOTfind Bind Dns Server software \n";
			cout << "	+For install Bind Dns Server Soft type 'install' \n";
			cout << "EBC > ";
			cin  >>	pointer;
			if(pointer == "install")
			{
				//install bind service on linux by linuxType
				SysCommand BindServiceInstall;
				BindServiceInstall.bindServiceInstall(linuxType);
				BindServiceInstall.bindServiceStart(linuxType);
				BindServiceInstall.bindServiceEnable(linuxType);
			}
			system("clear");
			bindInstall = true;
			continue;
		 }

	} //end of while

}<|endoftext|>


<commit_before>9eb95fe6-4b02-11e5-bb0b-28cfe9171a43<commit_msg>The previous fix has been fixed<commit_after>9ec4d3e3-4b02-11e5-aad5-28cfe9171a43<|endoftext|>


<commit_before>bcd323d7-4b02-11e5-938b-28cfe9171a43<commit_msg>This'll fix that<commit_after>bcdffb07-4b02-11e5-a7b5-28cfe9171a43<|endoftext|>


<commit_before>8295f535-4b02-11e5-aee7-28cfe9171a43<commit_msg>fixes, fixes for everyone<commit_after>82a25811-4b02-11e5-aa63-28cfe9171a43<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <memory>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

vector<string> split(const string& str) {
    string buf; // Have a buffer string
    stringstream ss(str); // Insert the string into a stream
    vector<string> tokens; // Create vector to hold our words

    while (ss >> buf)
        tokens.push_back(buf);

    return tokens;
}

using RoomID = int;

struct RoomObject
{
	string description;
};

struct Map
{
	static const int max_width = 100, max_height = 100;
	static const int player_start_x = 50, player_start_y = 50;
    enum Location
    {
        UNKNOWN,
        GRAVEYARD,
        GRAVEYARD_GATES,
        KHATHARRS_MOMS_HOUSE,
    };
	Location map_location[max_width][max_height];
	int x, y;
	Map()
	{
        memset(map_location, UNKNOWN, sizeof(map_location));
		x = 50;
		y = 50;
		map_location[50][50] = GRAVEYARD;
		map_location[50][51] = GRAVEYARD_GATES;
		map_location[50][52] = KHATHARRS_MOMS_HOUSE;
	}
};

struct Entity
{
    Entity(string name, int maxHealth) : name(name), health(maxHealth) {}

    void heal(int points)
    {
        health = min(100, health + points);
        cout << name << " healed to " << health << " health" << endl;
    }

    void damage(int points)
    {
        health = max(0, health - points);
        cout << name << " damaged to " << health << "health" << endl;
    }

    int getHealth() const { return health; }

    // Return false if the entity didn't know the command
    virtual bool act(vector<string> commands) = 0;

    string name;
    Map map;

private:
    int health;
};

struct Shogun : public Entity {
  Shogun() : Entity("Shogibear", 100) {}
};

struct Item
{
    virtual void apply(Entity* entity) = 0;
    virtual string identify() const = 0;
};

struct HealthItem : public Item
{
    HealthItem(int healPower) : healPower(healPower) {}

    void apply(Entity* entity) override
    {
        entity->heal(healPower);
    }

    string identify() const override
    {
        stringstream ss;
        ss << "Health Potion (" << healPower << ")";
        return ss.str();
    }

private:
    int healPower;
};
struct BlessedSword : public Item
{
    BlessedSword(int Weapon) : Weapon(Weapon){}
void apply(Entity* entity) override{entity->damage(Weapon);}string identify() const override{stringstream ss; ss << "Hit (" << Weapon << ")";}
private: int Weapon;};//will add this to entity on my next commit. <.<

/*
struct ReallyFastSword : public Item
struct TheFastcall : public Entity
{
    TheFastcall() : Entity("The Fastcall", 22) {}
    virtual bool act(vector<string> commands) override
    {
    }
};
*/

struct Player : public Entity
{
    Player(string name, int health) : Entity(name, health) {}

    virtual bool act(vector<string> commands) override
    {
        auto& cmd = commands[0];
        if(cmd == "n") { commands = vector<string>{"go","north"}; }
        if(cmd == "s") { commands = vector<string>{"go","south"}; }
        if(cmd == "e") { commands = vector<string>{"go","east"}; }
        if(cmd == "w") { commands = vector<string>{"go","west"}; }

        if (commands.size() >= 1 && commands[0] == "look")
        {
            look();
            return true;
        }
        else if (commands.size() >= 2 && (commands[0] == "examine" || commands[0] == "x"))
        {
        }
        else if (commands.size() >= 2 && commands[0] == "go")
        {
            if (travel(commands[1]) == true)
            {
                look();
            } else {
                cout << "Can't travel " << commands[1] << endl;
            }
            return true;
        }
        else if (commands.size() >= 1 && commands[0] == "items")
        {
            showItems();
            return true;
        }
        else if (commands.size() >= 2 && commands[0] == "use")
        {
            int index = stoi(commands[1]);
            useItem(index);
            return true;
        }

        return false;
    }

    bool travel(string direction)
    {
		if ((map.x <= 0 && direction == "west") || (map.x >= (map.max_width - 1) && direction == "east"))
			return false;
		if ((map.y <= 0 && direction == "south") || (map.y >= (map.max_width - 1) && direction == "north"))
			return false;
        if(direction=="north"&&map.map_location[map.x][map.y+1]==Map::UNKNOWN)return false;if(direction=="south"&&map.map_location[map.x][map.y-1]==Map::UNKNOWN)return false;if(direction=="east"&&map.map_location[map.x+1][map.y]==Map::UNKNOWN)return false
        ;if(direction=="west"&&map.map_location[map.x-1][map.y]==Map::UNKNOWN)return false;if(direction=="north")map.y++;if(direction=="south")map.y--;if(direction=="east")map.x++;if(direction=="west")map.x--;
        return true;/*
        switch (map.map_location[map.x][map.y])
        {
            case Map::GRAVEYARD:
                if (direction == "north")
                {
					map.y++;
                    return true;
                }
                break;
            case Map::GRAVEYARD_GATES:
                if (direction == "south")
                {
					map.y--;
                    return true;
                }
                if (direction == "north")
                {
                    map.y++;
                    return true;
                }
                break;
        }

        cout << "Can't travel " << direction << endl;
        return false;*/
    }

    void look()
    {
        switch (map.map_location[map.x][map.y])
        {
            case Map::GRAVEYARD:
                cout << "A thick layer of fog covers the graveyard soil. Tombstones jut out here and there and an eerie willow tree looms over your head, obstructing the full moon partially. Off in the distance you see the northern gates -- the only entrance into this forsaken place." << endl;
                break;
            case Map::GRAVEYARD_GATES:
                cout << "For many centuries these gates have stood the test of time. The gateway to the afterlife. Inside the graveyard small hills stretch endlessly, littered with thousands of tombstones. You see a willow tree south of the gates. Outisde, north, you see a very large house." << endl;
                break;
            case Map::KHATHARRS_MOMS_HOUSE:
                cout << "The house is gigantic! What could possibly require such volume, such mass, such density? The house appears to not have any doors, but due to the strain from whatever is present inside, cracks have formed. You see a crack you might just fit into east." << endl;
                break;
        }
    }

    void giveItem(shared_ptr<Item> item)
    {
        inventory.push_back(item);
    }

    void showItems()
    {
        if (inventory.size() == 0)
            cout << "You have no items." << endl;
        int i = 1;
        for (auto item : inventory)
        {
            cout << "  " << i++ << ". " << item->identify() << std::endl;
        }
    }

    void useItem(size_t index)
    {
        if (index > inventory.size())
        {
            cout << "Invalid index" << endl;
            return;
        }

        inventory[index-1]->apply(this);
        inventory.erase(inventory.begin() + index - 1);
    }

private:
    vector<shared_ptr<Item>> inventory;
};

struct Room {
	string describe() {
		return ""; //description << list entites, list items, list exits
	}
	string description;
	vector<Entity> entities;
	unordered_map<string, RoomObject> objects;
	unordered_map<string, RoomID> exits;
};

class Adventure
{
public:
    void begin()
    {
        string command;
        cout << "Welcome, brave soul. Pray tell, what is thy name?" << endl;
        cout << "> ";
        getline(cin, command);

        Player player(command, 100);
        player.giveItem(make_shared<HealthItem>(20));

        cout << player.name << "! Your presence defiles these sacred grounds. Beware the soil upon which you step, for it will claim you sooner rather than later." << endl;
        player.look();

        while (player.getHealth() > 0)
        {
            cout << "> ";
            getline(cin, command);
            if (player.act(split(command)) == false)
                cout << "Unknown command" << endl;
        }

        cout << "You died. Game over." << endl;
    }
};

int main()
{
    Adventure adventure;
    adventure.begin();
    return 0;
}
<commit_msg>deferring to popular demand.  Also, visible flag in rooms.<commit_after>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <memory>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

vector<string> split(const string& str) {
    string buf; // Have a buffer string
    stringstream ss(str); // Insert the string into a stream
    vector<string> tokens; // Create vector to hold our words

    while (ss >> buf)
        tokens.push_back(buf);

    return tokens;
}

using RoomID = int;

struct RoomObject
{
	vector<string> names;
	string description;
	bool visible;
};

struct Map
{
	static const int max_width = 100, max_height = 100;
	static const int player_start_x = 50, player_start_y = 50;
    enum Location
    {
        UNKNOWN,
        GRAVEYARD,
        GRAVEYARD_GATES,
        KHATHARRS_MOMS_HOUSE,
    };
	Location map_location[max_width][max_height];
	int x, y;
	Map()
	{
        memset(map_location, UNKNOWN, sizeof(map_location));
		x = 50;
		y = 50;
		map_location[50][50] = GRAVEYARD;
		map_location[50][51] = GRAVEYARD_GATES;
		map_location[50][52] = KHATHARRS_MOMS_HOUSE;
	}
};

struct Entity
{
    Entity(string name, int maxHealth) : name(name), health(maxHealth) {}

    void heal(int points)
    {
        health = min(100, health + points);
        cout << name << " healed to " << health << " health" << endl;
    }

    void damage(int points)
    {
        health = max(0, health - points);
        cout << name << " damaged to " << health << "health" << endl;
    }

    int getHealth() const { return health; }

    // Return false if the entity didn't know the command
    virtual bool act(vector<string> commands) = 0;

    string name;
    Map map;

private:
    int health;
};

struct Shogun : public Entity {
  Shogun() : Entity("Shogibear", 100) {}
};

struct Item
{
    virtual void apply(Entity* entity) = 0;
    virtual string identify() const = 0;
};

struct HealthItem : public Item
{
    HealthItem(int healPower) : healPower(healPower) {}

    void apply(Entity* entity) override
    {
        entity->heal(healPower);
    }

    string identify() const override
    {
        stringstream ss;
        ss << "Health Potion (" << healPower << ")";
        return ss.str();
    }

private:
    int healPower;
};
struct BlessedSword : public Item
{
    BlessedSword(int Weapon) : Weapon(Weapon){}
void apply(Entity* entity) override{entity->damage(Weapon);}string identify() const override{stringstream ss; ss << "Hit (" << Weapon << ")";}
private: int Weapon;};//will add this to entity on my next commit. <.<

/*
struct ReallyFastSword : public Item
struct TheFastcall : public Entity
{
    TheFastcall() : Entity("The Fastcall", 22) {}
    virtual bool act(vector<string> commands) override
    {
    }
};
*/

struct Player : public Entity
{
    Player(string name, int health) : Entity(name, health) {}

    virtual bool act(vector<string> commands) override
    {
        auto& cmd = commands[0];
        if(cmd == "n") { commands = vector<string>{"go","north"}; }
        if(cmd == "s") { commands = vector<string>{"go","south"}; }
        if(cmd == "e") { commands = vector<string>{"go","east"}; }
        if(cmd == "w") { commands = vector<string>{"go","west"}; }

        if (commands.size() >= 1 && commands[0] == "look")
        {
            look();
            return true;
        }
        else if (commands.size() >= 2 && (commands[0] == "examine" || commands[0] == "x"))
        {
        }
        else if (commands.size() >= 2 && commands[0] == "go")
        {
            if (travel(commands[1]) == true)
            {
                look();
            } else {
                cout << "Can't travel " << commands[1] << endl;
            }
            return true;
        }
        else if (commands.size() >= 1 && commands[0] == "items")
        {
            showItems();
            return true;
        }
        else if (commands.size() >= 2 && commands[0] == "use")
        {
            int index = stoi(commands[1]);
            useItem(index);
            return true;
        }

        return false;
    }

    bool travel(string direction)
    {
		if ((map.x <= 0 && direction == "west") || (map.x >= (map.max_width - 1) && direction == "east"))
			return false;
		if ((map.y <= 0 && direction == "south") || (map.y >= (map.max_width - 1) && direction == "north"))
			return false;
        if(direction=="north"&&map.map_location[map.x][map.y+1]==Map::UNKNOWN)return false;if(direction=="south"&&map.map_location[map.x][map.y-1]==Map::UNKNOWN)return false;if(direction=="east"&&map.map_location[map.x+1][map.y]==Map::UNKNOWN)return false
        ;if(direction=="west"&&map.map_location[map.x-1][map.y]==Map::UNKNOWN)return false;if(direction=="north")map.y++;if(direction=="south")map.y--;if(direction=="east")map.x++;if(direction=="west")map.x--;
        return true;/*
        switch (map.map_location[map.x][map.y])
        {
            case Map::GRAVEYARD:
                if (direction == "north")
                {
					map.y++;
                    return true;
                }
                break;
            case Map::GRAVEYARD_GATES:
                if (direction == "south")
                {
					map.y--;
                    return true;
                }
                if (direction == "north")
                {
                    map.y++;
                    return true;
                }
                break;
        }

        cout << "Can't travel " << direction << endl;
        return false;*/
    }

    void look()
    {
        switch (map.map_location[map.x][map.y])
        {
            case Map::GRAVEYARD:
                cout << "A thick layer of fog covers the graveyard soil. Tombstones jut out here and there and an eerie willow tree looms over your head, obstructing the full moon partially. Off in the distance you see the northern gates -- the only entrance into this forsaken place." << endl;
                break;
            case Map::GRAVEYARD_GATES:
                cout << "For many centuries these gates have stood the test of time. The gateway to the afterlife. Inside the graveyard small hills stretch endlessly, littered with thousands of tombstones. You see a willow tree south of the gates. Outisde, north, you see a very large house." << endl;
                break;
            case Map::KHATHARRS_MOMS_HOUSE:
                cout << "The house is gigantic! What could possibly require such volume, such mass, such density? The house appears to not have any doors, but due to the strain from whatever is present inside, cracks have formed. You see a crack you might just fit into east." << endl;
                break;
        }
    }

    void giveItem(shared_ptr<Item> item)
    {
        inventory.push_back(item);
    }

    void showItems()
    {
        if (inventory.size() == 0)
            cout << "You have no items." << endl;
        int i = 1;
        for (auto item : inventory)
        {
            cout << "  " << i++ << ". " << item->identify() << std::endl;
        }
    }

    void useItem(size_t index)
    {
        if (index > inventory.size())
        {
            cout << "Invalid index" << endl;
            return;
        }

        inventory[index-1]->apply(this);
        inventory.erase(inventory.begin() + index - 1);
    }

private:
    vector<shared_ptr<Item>> inventory;
};

struct Room {
	string describe() {
		return ""; //description << list entites, list items, list exits
	}
	string description;
	vector<Entity> entities;
	vector<RoomObject> objects;
	unordered_map<string, RoomID> exits;
};

class Adventure
{
public:
    void begin()
    {
        string command;
        cout << "Welcome, brave soul. Pray tell, what is thy name?" << endl;
        cout << "> ";
        getline(cin, command);

        Player player(command, 100);
        player.giveItem(make_shared<HealthItem>(20));

        cout << player.name << "! Your presence defiles these sacred grounds. Beware the soil upon which you step, for it will claim you sooner rather than later." << endl;
        player.look();

        while (player.getHealth() > 0)
        {
            cout << "> ";
            getline(cin, command);
            if (player.act(split(command)) == false)
                cout << "Unknown command" << endl;
        }

        cout << "You died. Game over." << endl;
    }
};

int main()
{
    Adventure adventure;
    adventure.begin();
    return 0;
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <stdio.h>
#include <string.h>

#pragma comment( lib, "psapi.lib" )

#define app_name "Coder-Assist"
#define exe_name "Coder-Assist.exe"
#define toggle_key1 VK_LCONTROL // ctrl
#define toggle_key2 VK_LMENU // alt
#define toggle_key3 'A'
#define wait_nsec 500
#define OPEN_PROCESS  (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)

using namespace std;

//二重起動防止
int check_process_overlap() {
    DWORD ProcessID[ 1024 ];
    DWORD dwSize;
    DWORD dwMax;
    DWORD dwNow;
    HANDLE hProcess;
    int result_buf = 0;

    // プロセス識別子の取得
    EnumProcesses( ProcessID, sizeof(ProcessID), &dwSize );
    dwMax = (dwSize / sizeof(DWORD));
    // プロセス識別子からプロセス名を列挙
    for ( dwNow = 0 ; dwNow < dwMax ; dwNow++ ){
        TCHAR   szFile[ 1024 ] = { 0 };
        HMODULE Module[ 1024 ] = { 0 };

        // プロセスのフルパス名を取得
        if ( (hProcess = OpenProcess(OPEN_PROCESS,FALSE,ProcessID[dwNow])) != NULL ){
            if ( EnumProcessModules(hProcess,Module,sizeof(Module),&dwSize) ){
                GetModuleFileNameEx( hProcess, Module[0], szFile, sizeof(szFile) );
            }
            CloseHandle( hProcess );
        }
        if(strstr(szFile, exe_name) != NULL)
          result_buf++;
    }

    //２つ以上プロセスが起動してたら1を返す
    if(result_buf > 1)
      return 1;

    return 0;
}

int add_aim_key(int check_key,int next_check_key,int enter_key){
  bool checked_key,
       checked_next_key,
       aim_key_pushing;

  aim_key_pushing= false;

  if(!next_check_key){
    if(GetAsyncKeyState(check_key) && 0x80)
      aim_key_pushing = true;
  }else{
    if(((GetAsyncKeyState(next_check_key) && 0x80) == 1) && ((GetAsyncKeyState(check_key) && 0x80) == 1))
      aim_key_pushing = true;
  }

  if(aim_key_pushing){
    //補完記号が シフト + Nキー ならシフトを押す
    if(VK_SHIFT == (check_key | next_check_key))
      keybd_event(VK_SHIFT,0,0,0);

    keybd_event(enter_key,0,0,0);
    keybd_event(enter_key,0,KEYEVENTF_KEYUP,0);

    if(VK_SHIFT == (check_key | next_check_key))
      keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);

    //補完後、一文字分左へ移動
    keybd_event(VK_LEFT,0,0,0);
    keybd_event(VK_LEFT,0,KEYEVENTF_KEYUP,0);

    Sleep(wait_nsec);
  }

  return 0;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
  bool is_run = true;

  if(check_process_overlap() == 1) {
    MessageBeep( MB_OK );
    MessageBox(NULL, "is already started", app_name, MB_OK);
    return -1;
  };

  MessageBox(NULL, "Coder-Assist started", app_name, MB_OK);

  while(true){
    //トグルキーが押されるとon/off切り替え
    if((GetAsyncKeyState(toggle_key1) && 0x80) &&
       (GetAsyncKeyState(toggle_key2) && 0x80) &&
       (GetAsyncKeyState(toggle_key3) && 0x80))
    {
      is_run = !is_run;
      Sleep(1000);
    }

    if(is_run){
        add_aim_key(VK_OEM_4, 0, VK_OEM_6); //[],「」, {}, 【】
        add_aim_key(VK_OEM_COMMA, VK_SHIFT, VK_OEM_PERIOD); //<>
        add_aim_key('8', VK_SHIFT, '9'); //()
        add_aim_key('2', VK_SHIFT, '2'); //""
        add_aim_key('7', VK_SHIFT, '7'); //''
    }
    Sleep(10);
  }
}
<commit_msg>引用符入力時のバグを修正<commit_after>#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <stdio.h>
#include <string.h>

#pragma comment( lib, "psapi.lib" )

#define app_name "Coder-Assist"
#define exe_name "Coder-Assist.exe"
#define toggle_key1 VK_LCONTROL // ctrl
#define toggle_key2 VK_LMENU // alt
#define toggle_key3 'A'
#define wait_nsec 500
#define OPEN_PROCESS  (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)

using namespace std;

//二重起動防止
int check_process_overlap() {
    DWORD ProcessID[ 1024 ];
    DWORD dwSize;
    DWORD dwMax;
    DWORD dwNow;
    HANDLE hProcess;
    int result_buf = 0;

    // プロセス識別子の取得
    EnumProcesses( ProcessID, sizeof(ProcessID), &dwSize );
    dwMax = (dwSize / sizeof(DWORD));
    // プロセス識別子からプロセス名を列挙
    for ( dwNow = 0 ; dwNow < dwMax ; dwNow++ ){
        TCHAR   szFile[ 1024 ] = { 0 };
        HMODULE Module[ 1024 ] = { 0 };

        // プロセスのフルパス名を取得
        if ( (hProcess = OpenProcess(OPEN_PROCESS,FALSE,ProcessID[dwNow])) != NULL ){
            if ( EnumProcessModules(hProcess,Module,sizeof(Module),&dwSize) ){
                GetModuleFileNameEx( hProcess, Module[0], szFile, sizeof(szFile) );
            }
            CloseHandle( hProcess );
        }
        if(strstr(szFile, exe_name) != NULL)
          result_buf++;
    }

    //２つ以上プロセスが起動してたら1を返す
    if(result_buf > 1)
      return 1;

    return 0;
}

int add_aim_key(int check_key,int next_check_key,int enter_key){
  bool checked_key,
       checked_next_key,
       aim_key_pushing;

  aim_key_pushing= false;

  if(!next_check_key){
    if(GetAsyncKeyState(check_key) && 0x80)
      aim_key_pushing = true;
  }else{
    if(((GetAsyncKeyState(next_check_key) && 0x80) == 1) && ((GetAsyncKeyState(check_key) && 0x80) == 1))
        if(((GetAsyncKeyState(next_check_key) && 0x80) == 1) && ((GetAsyncKeyState(check_key) && 0x80) == 1))
          aim_key_pushing = true;
  }

  if(aim_key_pushing){
    //補完記号が シフト + Nキー ならシフトを押す
    if(VK_SHIFT == (check_key | next_check_key))
      keybd_event(VK_SHIFT,0,0,0);

    keybd_event(enter_key,0,0,0);
    keybd_event(enter_key,0,KEYEVENTF_KEYUP,0);

    if(VK_SHIFT == (check_key | next_check_key))
      keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);

    //補完後、一文字分左へ移動
    keybd_event(VK_LEFT,0,0,0);
    keybd_event(VK_LEFT,0,KEYEVENTF_KEYUP,0);

    Sleep(wait_nsec);
  }

  return 0;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
  bool is_run = true;

  if(check_process_overlap() == 1) {
    MessageBeep( MB_OK );
    MessageBox(NULL, "is already started", app_name, MB_OK);
    return -1;
  };

  MessageBox(NULL, "Coder-Assist started", app_name, MB_OK);

  while(true){
    //トグルキーが押されるとon/off切り替え
    if((GetAsyncKeyState(toggle_key1) && 0x80) &&
       (GetAsyncKeyState(toggle_key2) && 0x80) &&
       (GetAsyncKeyState(toggle_key3) && 0x80))
    {
      is_run = !is_run;
      Sleep(1000);
    }

    if(is_run){
        add_aim_key(VK_OEM_4, 0, VK_OEM_6); //[],「」, {}, 【】
        add_aim_key(VK_OEM_COMMA, VK_SHIFT, VK_OEM_PERIOD); //<>
        add_aim_key('8', VK_SHIFT, '9'); //()
        add_aim_key('2', VK_SHIFT, '2'); //""
        add_aim_key('7', VK_SHIFT, '7'); //''
    }
    Sleep(10);
  }
}
<|endoftext|>


<commit_before>#include <queue>
#include <iostream>
#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "huffman_tree.hpp"

using namespace std;

void DFS(huffman_node *node)
{
    if (node == NULL)
        return;

    if (node->left == NULL)
    {
        printf("%c: %s\n", node->ch, node->bits.c_str());
        return;
    }

    DFS(node->left);
    DFS(node->right);
}

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        printf("Usage: %s input-file output-file\n", argv[0]);
        return 1;
    }
    FILE *fin = fopen(argv[1], "r");
    FILE *fout = fopen(argv[2], "w");
    if (fin == NULL)
    {
        printf("Cannot open '%s' for reading.\n", argv[1]);
        return 1;
    }
    if (fout == NULL)
    {
        printf("Cannot open '%s' for writing.\n", argv[2]);
        return 1;
    }

    huffman_tree tree = huffman_tree::from_input_file(fin);
    rewind(fin);

    fputs(tree.encode(fin).c_str(), fout);

    fclose(fin);
    fclose(fout);

    fin = fopen("out", "r");
    cout << tree.decode(fin);
    fclose(fin);
    return 0;
}
<commit_msg>Added encoding functionality to main<commit_after>#include <queue>
#include <iostream>
#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "huffman_tree.hpp"

using namespace std;

void DFS(huffman_node *node)
{
    if (node == NULL)
        return;

    if (node->left == NULL)
    {
        printf("%c: %s\n", node->ch, node->bits.c_str());
        return;
    }

    DFS(node->left);
    DFS(node->right);
}

FILE *sfopen(const char *path, const char *mode)
{
    FILE *fil = fopen(path, mode);
    if (fil == NULL)
    {
        printf("Cannot open file '%s' with mode '%s'\n", path, mode);
        exit(1);
    }
    return fil;
}

int main(int argc, char **argv)
{
    if (argc != 4)
    {
        printf("Usage: %s input-file output-file tree-file\n", argv[0]);
        return 1;
    }
    FILE *fin = sfopen(argv[1], "r");
    FILE *fout = sfopen(argv[2], "w");
    FILE *ftree = sfopen(argv[3], "w");

    huffman_tree tree = huffman_tree::from_input_file(fin);
    rewind(fin);

    fputs(tree.encode(fin).c_str(), fout);
    fputs(tree.to_string(fin).c_str(), ftree);

    fclose(fin);
    fclose(fout);
    fclose(ftree);

    return 0;
}
<|endoftext|>


<commit_before>#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/market_engine.hpp>
#include <bts/blockchain/market_operations.hpp>
#include <bts/blockchain/pending_chain_state.hpp>

#include <fc/real128.hpp>

#include <algorithm>

namespace bts { namespace blockchain {

   /**
    *  If the amount is negative then it will withdraw/cancel the bid assuming
    *  it is signed by the owner and there is sufficient funds.
    *
    *  If the amount is positive then it will add funds to the bid.
    */
   void bid_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      if( this->bid_index.order_price == price() )
         FC_CAPTURE_AND_THROW( zero_price, (bid_index.order_price) );

      auto owner = this->bid_index.owner;

      auto base_asset_rec = eval_state.pending_state()->get_asset_record( bid_index.order_price.base_asset_id );
      auto quote_asset_rec = eval_state.pending_state()->get_asset_record( bid_index.order_price.quote_asset_id );
      FC_ASSERT( base_asset_rec.valid() );
      FC_ASSERT( quote_asset_rec.valid() );

      FC_ASSERT( base_asset_rec->address_is_whitelisted( owner ) );
      FC_ASSERT( quote_asset_rec->address_is_whitelisted( owner ) );

      const bool authority_is_retracting = quote_asset_rec->flag_is_active( asset_record::retractable_balances )
                                           && eval_state.verify_authority( quote_asset_rec->authority );

      if( !authority_is_retracting && !eval_state.check_signature( owner ) )
         FC_CAPTURE_AND_THROW( missing_signature, (bid_index.owner) );

      asset delta_amount = this->get_amount();

      auto current_bid = eval_state.pending_state()->get_bid_record( this->bid_index );

      if( this->amount == 0 ) FC_CAPTURE_AND_THROW( zero_amount );
      if( this->amount <  0 ) // withdraw
      {
          if( NOT current_bid )
             FC_CAPTURE_AND_THROW( unknown_market_order, (bid_index) );

          if( llabs(this->amount) > current_bid->balance )
             FC_CAPTURE_AND_THROW( insufficient_funds, (amount)(current_bid->balance) );

          // add the delta amount to the eval state that we withdrew from the bid
          eval_state.add_balance( -delta_amount );
      }
      else // this->amount > 0 - deposit
      {
          if( NOT current_bid )  // then initialize to 0
            current_bid = order_record();
          // sub the delta amount from the eval state that we deposited to the bid
          eval_state.sub_balance( delta_amount );
      }

      current_bid->last_update = eval_state.pending_state()->now();
      current_bid->balance     += this->amount;

      eval_state.pending_state()->store_bid_record( this->bid_index, *current_bid );

      //auto check   = eval_state.pending_state()->get_bid_record( this->bid_index );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   /**
    *  If the amount is negative then it will withdraw/cancel the bid assuming
    *  it is signed by the owner and there is sufficient funds.
    *
    *  If the amount is positive then it will add funds to the bid.
    */
   void ask_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      if( this->ask_index.order_price == price() )
         FC_CAPTURE_AND_THROW( zero_price, (ask_index.order_price) );

      auto owner = this->ask_index.owner;

      auto base_asset_rec = eval_state.pending_state()->get_asset_record( ask_index.order_price.base_asset_id );
      auto quote_asset_rec = eval_state.pending_state()->get_asset_record( ask_index.order_price.quote_asset_id );
      FC_ASSERT( base_asset_rec.valid() );
      FC_ASSERT( quote_asset_rec.valid() );

      FC_ASSERT( base_asset_rec->address_is_whitelisted( owner ) );
      FC_ASSERT( quote_asset_rec->address_is_whitelisted( owner ) );

      const bool authority_is_retracting = base_asset_rec->flag_is_active( asset_record::retractable_balances )
                                           && eval_state.verify_authority( base_asset_rec->authority );

      if( !authority_is_retracting && !eval_state.check_signature( owner ) )
         FC_CAPTURE_AND_THROW( missing_signature, (ask_index.owner) );

      asset delta_amount  = this->get_amount();

      auto current_ask   = eval_state.pending_state()->get_ask_record( this->ask_index );

      if( this->amount == 0 ) FC_CAPTURE_AND_THROW( zero_amount );
      if( this->amount <  0 ) // withdraw
      {
          if( NOT current_ask )
             FC_CAPTURE_AND_THROW( unknown_market_order, (ask_index) );

          if( llabs(this->amount) > current_ask->balance )
             FC_CAPTURE_AND_THROW( insufficient_funds, (amount)(current_ask->balance) );

          // add the delta amount to the eval state that we withdrew from the ask
          eval_state.add_balance( -delta_amount );
      }
      else // this->amount > 0 - deposit
      {
          if( NOT current_ask )  // then initialize to 0
            current_ask = order_record();
          // sub the delta amount from the eval state that we deposited to the ask
          eval_state.sub_balance( delta_amount );
      }

      current_ask->last_update = eval_state.pending_state()->now();
      current_ask->balance     += this->amount;
      FC_ASSERT( current_ask->balance >= 0, "", ("current_ask",current_ask)  );

      eval_state.pending_state()->store_ask_record( this->ask_index, *current_ask );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   balance_id_type  buy_chips_operation::balance_id()const
   {
       withdraw_condition condition(withdraw_with_signature( this->owner ), this->amount.asset_id);
       return condition.get_address();
   }

   void buy_chips_operation::evaluate( transaction_evaluation_state& eval_state ) const
   { try {
       if ( this->amount.amount == 0) {
           FC_CAPTURE_AND_THROW( zero_amount );
       }

       if( this->amount.amount < 0 )
           FC_CAPTURE_AND_THROW( negative_deposit );

       auto  asset_to_buy = eval_state.pending_state()->get_asset_record( this->amount.asset_id );

       FC_ASSERT( asset_to_buy.valid() );
       // TODO: FC_ASSERT( asset_to_buy->is_chip_asset(), "${symbol} is not a chip asset", ("symbol",asset_to_buy->symbol) );

       double price = (asset_to_buy->current_collateral * 1.0) / asset_to_buy->current_supply;
       share_type collateral_to_add = this->amount.amount * price;

       asset cost_shares( collateral_to_add, 0);

       eval_state.sub_balance( cost_shares);

       // deposit amount of chips to the owner. and update the asset record's current collateral

       withdraw_condition condition( withdraw_with_signature( this->owner ), this->amount.asset_id);

       auto chips_balance_id = condition.get_address();
       auto cur_record = eval_state.pending_state()->get_balance_record( chips_balance_id );
       if( !cur_record )
       {
           cur_record = balance_record( condition );
       }
       cur_record->last_update   = eval_state.pending_state()->now();
       cur_record->balance       += this->amount.amount;
       // because this is system created from vitual, so no need to sub_balance
       eval_state.pending_state()->store_balance_record( *cur_record );

       asset_to_buy->current_collateral += collateral_to_add;
       asset_to_buy->current_supply += this->amount.amount;
       // TODO: Dice, do we need to update the asset 0's current supply, no. Because it is just become the collateral of chips.

       eval_state.pending_state()->store_asset_record( *asset_to_buy );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<commit_msg>debug info<commit_after>#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/market_engine.hpp>
#include <bts/blockchain/market_operations.hpp>
#include <bts/blockchain/pending_chain_state.hpp>

#include <fc/real128.hpp>

#include <algorithm>

namespace bts { namespace blockchain {

   /**
    *  If the amount is negative then it will withdraw/cancel the bid assuming
    *  it is signed by the owner and there is sufficient funds.
    *
    *  If the amount is positive then it will add funds to the bid.
    */
   void bid_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      if( this->bid_index.order_price == price() )
         FC_CAPTURE_AND_THROW( zero_price, (bid_index.order_price) );

      auto owner = this->bid_index.owner;

      auto base_asset_rec = eval_state.pending_state()->get_asset_record( bid_index.order_price.base_asset_id );
      auto quote_asset_rec = eval_state.pending_state()->get_asset_record( bid_index.order_price.quote_asset_id );
      FC_ASSERT( base_asset_rec.valid() );
      FC_ASSERT( quote_asset_rec.valid() );

      FC_ASSERT( base_asset_rec->address_is_whitelisted( owner ) );
      FC_ASSERT( quote_asset_rec->address_is_whitelisted( owner ) );

      const bool authority_is_retracting = quote_asset_rec->flag_is_active( asset_record::retractable_balances )
                                           && eval_state.verify_authority( quote_asset_rec->authority );

      if( !authority_is_retracting && !eval_state.check_signature( owner ) )
         FC_CAPTURE_AND_THROW( missing_signature, (bid_index.owner) );

      asset delta_amount = this->get_amount();

      auto current_bid = eval_state.pending_state()->get_bid_record( this->bid_index );

      if( this->amount == 0 ) FC_CAPTURE_AND_THROW( zero_amount );
      if( this->amount <  0 ) // withdraw
      {
          if( NOT current_bid )
             FC_CAPTURE_AND_THROW( unknown_market_order, (bid_index) );

          if( llabs(this->amount) > current_bid->balance )
             FC_CAPTURE_AND_THROW( insufficient_funds, (amount)(current_bid->balance) );

          // add the delta amount to the eval state that we withdrew from the bid
          eval_state.add_balance( -delta_amount );
      }
      else // this->amount > 0 - deposit
      {
          if( NOT current_bid )  // then initialize to 0
            current_bid = order_record();
          // sub the delta amount from the eval state that we deposited to the bid
          eval_state.sub_balance( delta_amount );
      }

      current_bid->last_update = eval_state.pending_state()->now();
      current_bid->balance     += this->amount;

      eval_state.pending_state()->store_bid_record( this->bid_index, *current_bid );

      //auto check   = eval_state.pending_state()->get_bid_record( this->bid_index );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   /**
    *  If the amount is negative then it will withdraw/cancel the bid assuming
    *  it is signed by the owner and there is sufficient funds.
    *
    *  If the amount is positive then it will add funds to the bid.
    */
   void ask_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      if( this->ask_index.order_price == price() )
         FC_CAPTURE_AND_THROW( zero_price, (ask_index.order_price) );

      auto owner = this->ask_index.owner;

      auto base_asset_rec = eval_state.pending_state()->get_asset_record( ask_index.order_price.base_asset_id );
      auto quote_asset_rec = eval_state.pending_state()->get_asset_record( ask_index.order_price.quote_asset_id );
      FC_ASSERT( base_asset_rec.valid() );
      FC_ASSERT( quote_asset_rec.valid() );

      FC_ASSERT( base_asset_rec->address_is_whitelisted( owner ) );
      FC_ASSERT( quote_asset_rec->address_is_whitelisted( owner ) );

      const bool authority_is_retracting = base_asset_rec->flag_is_active( asset_record::retractable_balances )
                                           && eval_state.verify_authority( base_asset_rec->authority );

      if( !authority_is_retracting && !eval_state.check_signature( owner ) )
         FC_CAPTURE_AND_THROW( missing_signature, (ask_index.owner) );

      asset delta_amount  = this->get_amount();

      auto current_ask   = eval_state.pending_state()->get_ask_record( this->ask_index );

      if( this->amount == 0 ) FC_CAPTURE_AND_THROW( zero_amount );
      if( this->amount <  0 ) // withdraw
      {
          if( NOT current_ask )
             FC_CAPTURE_AND_THROW( unknown_market_order, (ask_index) );

          if( llabs(this->amount) > current_ask->balance )
             FC_CAPTURE_AND_THROW( insufficient_funds, (amount)(current_ask->balance) );

          // add the delta amount to the eval state that we withdrew from the ask
          eval_state.add_balance( -delta_amount );
      }
      else // this->amount > 0 - deposit
      {
          if( NOT current_ask )  // then initialize to 0
            current_ask = order_record();
          // sub the delta amount from the eval state that we deposited to the ask
          eval_state.sub_balance( delta_amount );
      }

      current_ask->last_update = eval_state.pending_state()->now();
      current_ask->balance     += this->amount;
      FC_ASSERT( current_ask->balance >= 0, "", ("current_ask",current_ask)  );

      eval_state.pending_state()->store_ask_record( this->ask_index, *current_ask );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   balance_id_type  buy_chips_operation::balance_id()const
   {
       withdraw_condition condition(withdraw_with_signature( this->owner ), this->amount.asset_id);
       return condition.get_address();
   }

   void buy_chips_operation::evaluate( transaction_evaluation_state& eval_state ) const
   { try {
       if ( this->amount.amount == 0) {
           FC_CAPTURE_AND_THROW( zero_amount );
       }

       if( this->amount.amount < 0 )
           FC_CAPTURE_AND_THROW( negative_deposit );

       auto  asset_to_buy = eval_state.pending_state()->get_asset_record( this->amount.asset_id );

       FC_ASSERT( asset_to_buy.valid() );
       // TODO: FC_ASSERT( asset_to_buy->is_chip_asset(), "${symbol} is not a chip asset", ("symbol",asset_to_buy->symbol) );

       double price = (asset_to_buy->current_collateral * 1.0) / asset_to_buy->current_supply;
       share_type collateral_to_add = this->amount.amount * price;

       asset cost_shares( collateral_to_add, 0);

       eval_state.sub_balance( cost_shares);

       // deposit amount of chips to the owner. and update the asset record's current collateral

       withdraw_condition condition( withdraw_with_signature( this->owner ), this->amount.asset_id);

       auto chips_balance_id = condition.get_address();
       auto cur_record = eval_state.pending_state()->get_balance_record( chips_balance_id );
       if( !cur_record )
       {
           cur_record = balance_record( condition );
       }
       cur_record->last_update   = eval_state.pending_state()->now();
       cur_record->balance       += this->amount.amount;
       // because this is system created from vitual, so no need to sub_balance
       eval_state.pending_state()->store_balance_record( *cur_record );

       asset_to_buy->current_collateral += collateral_to_add;
       asset_to_buy->current_supply += this->amount.amount;
       // TODO: Dice, do we need to update the asset 0's current supply, no. Because it is just become the collateral of chips.

       asset_to_buy->last_update = eval_state.pending_state()->now();
       ilog( "Storing asset: ${a}", ("a",*asset_to_buy) );
       eval_state.pending_state()->store_asset_record( *asset_to_buy );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<|endoftext|>


<commit_before>
#include <bts/chain/vesting_balance_object.hpp>

namespace bts { namespace chain {

/*
         void _check_cap()const
         {
            fc::uint128_t coin_seconds_earned_cap = balance.amount.value;
            coin_seconds_earned_cap *= vesting_seconds;
            assert( coin_seconds_earned <= coin_seconds_earned_cap );
            return;
         }
*/

inline bool sum_below_max_shares( const asset& a, const asset& b )
{
   assert( BTS_MAX_SHARE_SUPPLY + BTS_MAX_SHARE_SUPPLY > BTS_MAX_SHARE_SUPPLY );
   return ( a.amount             <= BTS_MAX_SHARE_SUPPLY)
       && (            b.amount  <= BTS_MAX_SHARE_SUPPLY)
       && ((a.amount + b.amount) <= BTS_MAX_SHARE_SUPPLY)
      ;
}

asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx ) const
{
   if( ctx.now <= begin_date )
      return asset( 0, ctx.balance.asset_id );
   if( vesting_seconds == 0 )
      return ctx.balance;

   int64_t elapsed_seconds = (ctx.now - begin_date).to_seconds();

   // if elapsed_seconds <= 0, then ctx.now <= begin_date,
   // and we should have returned above.
   assert( elapsed_seconds > 0 );

   fc::uint128_t total_allowed = begin_balance.value;
   total_allowed *= uint64_t( elapsed_seconds );
   total_allowed /= vesting_seconds;

   if( total_allowed <= total_withdrawn.value )
      return asset( 0, ctx.balance.asset_id );
   total_allowed -= total_withdrawn.value;
   FC_ASSERT( total_allowed <= BTS_MAX_SHARE_SUPPLY );
   return asset( total_allowed.to_uint64(), ctx.balance.asset_id );
}

void linear_vesting_policy::on_deposit( const vesting_policy_context& ctx )
{
   return;
}

bool linear_vesting_policy::is_deposit_allowed( const vesting_policy_context& ctx )const
{
   return (ctx.amount.asset_id == ctx.balance.asset_id)
      && sum_below_max_shares( ctx.amount, ctx.balance );
}

void linear_vesting_policy::on_withdraw( const vesting_policy_context& ctx )
{
   total_withdrawn += ctx.amount.amount;
   return;
}

bool linear_vesting_policy::is_withdraw_allowed( const vesting_policy_context& ctx )const
{
   return ( ctx.amount <= get_allowed_withdraw( ctx ) );
}

fc::uint128_t cdd_vesting_policy::compute_coin_seconds_earned( const vesting_policy_context& ctx )const
{
   assert( ctx.now >= coin_seconds_earned_last_update );
   int64_t delta_seconds = (ctx.now - coin_seconds_earned_last_update).to_seconds();
   assert( delta_seconds >= 0 );

   fc::uint128_t delta_coin_seconds = ctx.balance.amount.value;
   delta_coin_seconds *= delta_seconds;

   fc::uint128_t coin_seconds_earned_cap = ctx.balance.amount.value;
   coin_seconds_earned_cap *= vesting_seconds;

   return std::min(
      coin_seconds_earned + delta_coin_seconds,
      coin_seconds_earned_cap
      );
}

void cdd_vesting_policy::update_coin_seconds_earned( const vesting_policy_context& ctx )
{
   coin_seconds_earned = compute_coin_seconds_earned( ctx );
   coin_seconds_earned_last_update = ctx.now;
   return;
}

asset cdd_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const
{
   fc::uint128_t cs_earned = compute_coin_seconds_earned( ctx );
   fc::uint128_t withdraw_available = cs_earned / vesting_seconds;
   assert( withdraw_available <= ctx.balance.amount.value );
   return asset( withdraw_available.to_uint64(), ctx.balance.asset_id );
}

void cdd_vesting_policy::on_deposit( const vesting_policy_context& ctx )
{
   update_coin_seconds_earned( ctx );
   return;
}

void cdd_vesting_policy::on_withdraw( const vesting_policy_context& ctx )
{
   update_coin_seconds_earned( ctx );
   fc::uint128_t coin_seconds_needed = ctx.amount.amount.value;
   coin_seconds_needed *= vesting_seconds;
   // is_withdraw_allowed should forbid any withdrawal that
   // would trigger this assert
   assert( coin_seconds_needed <= coin_seconds_earned );

   coin_seconds_earned -= coin_seconds_needed;
   return;
}

bool cdd_vesting_policy::is_deposit_allowed( const vesting_policy_context& ctx )const
{
   return (ctx.amount.asset_id == ctx.balance.asset_id)
      && sum_below_max_shares( ctx.amount, ctx.balance );
}

bool cdd_vesting_policy::is_withdraw_allowed( const vesting_policy_context& ctx )const
{
   return ( ctx.amount <= get_allowed_withdraw( ctx ) );
}

#define VESTING_VISITOR( NAME, MAYBE_CONST )                  \
struct NAME ## _visitor                                       \
{                                                             \
   typedef decltype(                                          \
      std::declval<linear_vesting_policy>().NAME(             \
         std::declval<vesting_policy_context>())              \
      ) result_type;                                          \
                                                              \
   NAME ## _visitor(                                          \
      const asset& balance,                                   \
      const time_point_sec& now,                              \
      const asset& amount                                     \
      )                                                       \
   : ctx( balance, now, amount ) {}                           \
                                                              \
   template< typename Policy >                                \
   result_type                                                \
   operator()( MAYBE_CONST Policy& policy ) MAYBE_CONST       \
   {                                                          \
      return policy.NAME( ctx );                              \
   }                                                          \
                                                              \
   vesting_policy_context ctx;                                \
}

VESTING_VISITOR( on_deposit, );
VESTING_VISITOR( on_withdraw, );
VESTING_VISITOR( is_deposit_allowed, const );
VESTING_VISITOR( is_withdraw_allowed, const );

bool vesting_balance_object::is_deposit_allowed(
   const time_point_sec& now,
   const asset& amount
   )const
{
   return policy.visit( is_deposit_allowed_visitor( balance, now, amount ) );
}

bool vesting_balance_object::is_withdraw_allowed(
   const time_point_sec& now,
   const asset& amount
   )const
{
   bool result = policy.visit( is_withdraw_allowed_visitor( balance, now, amount ) );
   // if some policy allows you to withdraw more than your balance,
   //    there's a programming bug in the policy algorithm
   assert( (amount <= balance) || (!result) );
   return result;
}

void vesting_balance_object::deposit(
   const time_point_sec& now,
   const asset& amount)
{
   assert( amount <= balance );
   on_deposit_visitor vtor( balance, now, amount );
   policy.visit( vtor );
   balance += amount;
   return;
}

void vesting_balance_object::withdraw(
   const time_point_sec& now,
   const asset& amount)
{
   assert( amount <= balance );
   on_withdraw_visitor vtor( balance, now, amount );
   policy.visit( vtor );
   balance -= amount;
   return;
}

} } // bts::chain
<commit_msg>vesting_balance:  Fix bug; deposit greater than balance is OK<commit_after>
#include <bts/chain/vesting_balance_object.hpp>

namespace bts { namespace chain {

/*
         void _check_cap()const
         {
            fc::uint128_t coin_seconds_earned_cap = balance.amount.value;
            coin_seconds_earned_cap *= vesting_seconds;
            assert( coin_seconds_earned <= coin_seconds_earned_cap );
            return;
         }
*/

inline bool sum_below_max_shares( const asset& a, const asset& b )
{
   assert( BTS_MAX_SHARE_SUPPLY + BTS_MAX_SHARE_SUPPLY > BTS_MAX_SHARE_SUPPLY );
   return ( a.amount             <= BTS_MAX_SHARE_SUPPLY)
       && (            b.amount  <= BTS_MAX_SHARE_SUPPLY)
       && ((a.amount + b.amount) <= BTS_MAX_SHARE_SUPPLY)
      ;
}

asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx ) const
{
   if( ctx.now <= begin_date )
      return asset( 0, ctx.balance.asset_id );
   if( vesting_seconds == 0 )
      return ctx.balance;

   int64_t elapsed_seconds = (ctx.now - begin_date).to_seconds();

   // if elapsed_seconds <= 0, then ctx.now <= begin_date,
   // and we should have returned above.
   assert( elapsed_seconds > 0 );

   fc::uint128_t total_allowed = begin_balance.value;
   total_allowed *= uint64_t( elapsed_seconds );
   total_allowed /= vesting_seconds;

   if( total_allowed <= total_withdrawn.value )
      return asset( 0, ctx.balance.asset_id );
   total_allowed -= total_withdrawn.value;
   FC_ASSERT( total_allowed <= BTS_MAX_SHARE_SUPPLY );
   return asset( total_allowed.to_uint64(), ctx.balance.asset_id );
}

void linear_vesting_policy::on_deposit( const vesting_policy_context& ctx )
{
   return;
}

bool linear_vesting_policy::is_deposit_allowed( const vesting_policy_context& ctx )const
{
   return (ctx.amount.asset_id == ctx.balance.asset_id)
      && sum_below_max_shares( ctx.amount, ctx.balance );
}

void linear_vesting_policy::on_withdraw( const vesting_policy_context& ctx )
{
   total_withdrawn += ctx.amount.amount;
   return;
}

bool linear_vesting_policy::is_withdraw_allowed( const vesting_policy_context& ctx )const
{
   return ( ctx.amount <= get_allowed_withdraw( ctx ) );
}

fc::uint128_t cdd_vesting_policy::compute_coin_seconds_earned( const vesting_policy_context& ctx )const
{
   assert( ctx.now >= coin_seconds_earned_last_update );
   int64_t delta_seconds = (ctx.now - coin_seconds_earned_last_update).to_seconds();
   assert( delta_seconds >= 0 );

   fc::uint128_t delta_coin_seconds = ctx.balance.amount.value;
   delta_coin_seconds *= delta_seconds;

   fc::uint128_t coin_seconds_earned_cap = ctx.balance.amount.value;
   coin_seconds_earned_cap *= vesting_seconds;

   return std::min(
      coin_seconds_earned + delta_coin_seconds,
      coin_seconds_earned_cap
      );
}

void cdd_vesting_policy::update_coin_seconds_earned( const vesting_policy_context& ctx )
{
   coin_seconds_earned = compute_coin_seconds_earned( ctx );
   coin_seconds_earned_last_update = ctx.now;
   return;
}

asset cdd_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const
{
   fc::uint128_t cs_earned = compute_coin_seconds_earned( ctx );
   fc::uint128_t withdraw_available = cs_earned / vesting_seconds;
   assert( withdraw_available <= ctx.balance.amount.value );
   return asset( withdraw_available.to_uint64(), ctx.balance.asset_id );
}

void cdd_vesting_policy::on_deposit( const vesting_policy_context& ctx )
{
   update_coin_seconds_earned( ctx );
   return;
}

void cdd_vesting_policy::on_withdraw( const vesting_policy_context& ctx )
{
   update_coin_seconds_earned( ctx );
   fc::uint128_t coin_seconds_needed = ctx.amount.amount.value;
   coin_seconds_needed *= vesting_seconds;
   // is_withdraw_allowed should forbid any withdrawal that
   // would trigger this assert
   assert( coin_seconds_needed <= coin_seconds_earned );

   coin_seconds_earned -= coin_seconds_needed;
   return;
}

bool cdd_vesting_policy::is_deposit_allowed( const vesting_policy_context& ctx )const
{
   return (ctx.amount.asset_id == ctx.balance.asset_id)
      && sum_below_max_shares( ctx.amount, ctx.balance );
}

bool cdd_vesting_policy::is_withdraw_allowed( const vesting_policy_context& ctx )const
{
   return ( ctx.amount <= get_allowed_withdraw( ctx ) );
}

#define VESTING_VISITOR( NAME, MAYBE_CONST )                  \
struct NAME ## _visitor                                       \
{                                                             \
   typedef decltype(                                          \
      std::declval<linear_vesting_policy>().NAME(             \
         std::declval<vesting_policy_context>())              \
      ) result_type;                                          \
                                                              \
   NAME ## _visitor(                                          \
      const asset& balance,                                   \
      const time_point_sec& now,                              \
      const asset& amount                                     \
      )                                                       \
   : ctx( balance, now, amount ) {}                           \
                                                              \
   template< typename Policy >                                \
   result_type                                                \
   operator()( MAYBE_CONST Policy& policy ) MAYBE_CONST       \
   {                                                          \
      return policy.NAME( ctx );                              \
   }                                                          \
                                                              \
   vesting_policy_context ctx;                                \
}

VESTING_VISITOR( on_deposit, );
VESTING_VISITOR( on_withdraw, );
VESTING_VISITOR( is_deposit_allowed, const );
VESTING_VISITOR( is_withdraw_allowed, const );

bool vesting_balance_object::is_deposit_allowed(
   const time_point_sec& now,
   const asset& amount
   )const
{
   return policy.visit( is_deposit_allowed_visitor( balance, now, amount ) );
}

bool vesting_balance_object::is_withdraw_allowed(
   const time_point_sec& now,
   const asset& amount
   )const
{
   bool result = policy.visit( is_withdraw_allowed_visitor( balance, now, amount ) );
   // if some policy allows you to withdraw more than your balance,
   //    there's a programming bug in the policy algorithm
   assert( (amount <= balance) || (!result) );
   return result;
}

void vesting_balance_object::deposit(
   const time_point_sec& now,
   const asset& amount)
{
   on_deposit_visitor vtor( balance, now, amount );
   policy.visit( vtor );
   balance += amount;
   return;
}

void vesting_balance_object::withdraw(
   const time_point_sec& now,
   const asset& amount)
{
   assert( amount <= balance );
   on_withdraw_visitor vtor( balance, now, amount );
   policy.visit( vtor );
   balance -= amount;
   return;
}

} } // bts::chain
<|endoftext|>


<commit_before>#ifndef MAYBE_HH
#define MAYBE_HH

#include <cassert>
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>

template<typename T>
struct maybe {
  constexpr maybe() noexcept : is_init(false) {}

  template<typename ...Args>
  maybe(Args &&...args) : is_init(false) {
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

  template<typename U,
           typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>>::value>::type>
  maybe(std::initializer_list<U> init) : is_init(false) {
    new(&memory) T(std::forward<std::initializer_list<U>>(init));
    is_init = true;
  }

  maybe(const maybe &other) noexcept(std::is_nothrow_copy_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(*other);
      is_init = true;
    }
  }

  maybe(maybe &&other) noexcept(std::is_nothrow_move_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(std::move(*other));
      is_init = true;
    }
  }

  maybe &operator=(const maybe &other) {
    if (this != &other && other.is_init) {
      if (is_init) {
        memory = *other;
      } else {
        new (&memory) T(*other);
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  maybe &operator=(maybe &&other) {
    assert(this != &other);
    if (other.is_init) {
      if (is_init) {
        memory = std::move(*other);
      } else {
        new (&memory) T(std::move(*other));
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  ~maybe() {
    if (is_init) {
      memory.~T();
    }
  }

  explicit operator bool() const noexcept {
    return is_init;
  }

  T &operator*() noexcept {
    assert(is_init);
    return memory;
  }

  const T &operator*() const noexcept {
    assert(is_init);
    return memory;
  }

  T *operator->() noexcept {
    assert(is_init);
    return &memory;
  }

  const T *operator->() const noexcept {
    assert(is_init);
    return &memory;
  }

  T *get() noexcept {
    return is_init ? &memory : nullptr;
  }

  const T *get() const noexcept {
    return is_init ? &memory : nullptr;
  }

  T const &get_value_or(T const &v) const noexcept {
    return is_init ? memory : v;
  }

  void clear() {
    if (is_init) {
      memory.~T();
      is_init = false;
    }
  }

  template<typename ...Args>
  void emplace(Args &&...args) {
    clear();
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

private:
  union { T memory; };
  bool is_init;
};

#endif
<commit_msg>maybe.hh: clarify the exception-safety of emplace<commit_after>#ifndef MAYBE_HH
#define MAYBE_HH

#include <cassert>
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>

template<typename T>
struct maybe {
  constexpr maybe() noexcept : is_init(false) {}

  template<typename ...Args>
  maybe(Args &&...args) : is_init(false) {
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

  template<typename U,
           typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>>::value>::type>
  maybe(std::initializer_list<U> init) : is_init(false) {
    new(&memory) T(std::forward<std::initializer_list<U>>(init));
    is_init = true;
  }

  maybe(const maybe &other) noexcept(std::is_nothrow_copy_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(*other);
      is_init = true;
    }
  }

  maybe(maybe &&other) noexcept(std::is_nothrow_move_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(std::move(*other));
      is_init = true;
    }
  }

  maybe &operator=(const maybe &other) {
    if (this != &other && other.is_init) {
      if (is_init) {
        memory = *other;
      } else {
        new (&memory) T(*other);
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  maybe &operator=(maybe &&other) {
    assert(this != &other);
    if (other.is_init) {
      if (is_init) {
        memory = std::move(*other);
      } else {
        new (&memory) T(std::move(*other));
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  ~maybe() {
    if (is_init) {
      memory.~T();
    }
  }

  explicit operator bool() const noexcept {
    return is_init;
  }

  T &operator*() noexcept {
    assert(is_init);
    return memory;
  }

  const T &operator*() const noexcept {
    assert(is_init);
    return memory;
  }

  T *operator->() noexcept {
    assert(is_init);
    return &memory;
  }

  const T *operator->() const noexcept {
    assert(is_init);
    return &memory;
  }

  T *get() noexcept {
    return is_init ? &memory : nullptr;
  }

  const T *get() const noexcept {
    return is_init ? &memory : nullptr;
  }

  T const &get_value_or(T const &v) const noexcept {
    return is_init ? memory : v;
  }

  void clear() {
    if (is_init) {
      memory.~T();
      is_init = false;
    }
  }

  // Destroy contained value and then construct in-place.
  // If the constructor throws, this has the same effect as calling clear.
  template<typename ...Args>
  void emplace(Args &&...args) {
    clear();
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

private:
  union { T memory; };
  bool is_init;
};

#endif
<|endoftext|>


<commit_before>#ifndef SPLITTER_CUT_HPP
#define SPLITTER_CUT_HPP

#include <geos/io/WKTWriter.h>
#include <osmium/handler/progress.hpp>
#include "geometryreader.hpp"

// information about a single extract
class ExtractInfo {

public:
    std::string name;
    geos::algorithm::locate::IndexedPointInAreaLocator *locator;
    Osmium::Output::Base *writer;

    // the initial size of the id-trackers could be 0, because the vectors
    // are flexible, but providing here an estimation of the max. number of nodes
    // and ways gives the tool a "fail first" behaviour in the case of not enough memory
    // (better fail in init phase, not after 5 hours of processing)
    static const unsigned int est_max_node_id =   1600000000;
    static const unsigned int est_max_way_id =     140000000;
    static const unsigned int est_max_relation_id =  3000000;

    ExtractInfo(std::string name) {
        this->name = name;
    }

    bool contains(const shared_ptr<Osmium::OSM::Node const>& node) {
        // BOUNDARY 1
        // EXTERIOR 2
        // INTERIOR 0

        geos::geom::Coordinate c = geos::geom::Coordinate(node->get_lon(), node->get_lat(), DoubleNotANumber);
        return (0 == locator->locate(&c));
    }
};

// information about the cutting algorithm
template <class TExtractInfo>
class CutInfo {

protected:
    ~CutInfo() {
        for(int i=0, l = extracts.size(); i<l; i++) {
            extracts[i]->writer->final();
            delete extracts[i]->writer;
            delete extracts[i]->locator;
            delete extracts[i];
        }
    }

public:
    std::vector<TExtractInfo*> extracts;

    TExtractInfo *addExtract(std::string name, geos::geom::Geometry *poly) {
        fprintf(stderr, "opening writer for %s\n", name.c_str());
        Osmium::OSMFile outfile(name);
        Osmium::Output::Base *writer = outfile.create_output_file();

        const geos::geom::Envelope *env = poly->getEnvelopeInternal();
        const Osmium::OSM::Position min(env->getMinX(), env->getMinY());
        const Osmium::OSM::Position max(env->getMaxX(), env->getMaxY());

        Osmium::OSM::Bounds bounds;
        bounds.extend(min).extend(max);

        Osmium::OSM::Meta meta(bounds);
        writer->init(meta);

        TExtractInfo *ex = new TExtractInfo(name);
        ex->writer = writer;

        ex->locator = new geos::algorithm::locate::IndexedPointInAreaLocator(*poly);
        Osmium::Geometry::geos_geometry_factory()->destroyGeometry(poly);

        extracts.push_back(ex);
        return ex;
    }
};

template <class TCutInfo>
class Cut : public Osmium::Handler::Base {

protected:

    Osmium::Handler::Progress pg;
    TCutInfo *info;

public:

    bool debug;
    Cut(TCutInfo *info) : info(info) {}
};

#endif // SPLITTER_CUT_HPP

<commit_msg>extend bittracker to mapts latest full-experimental dump<commit_after>#ifndef SPLITTER_CUT_HPP
#define SPLITTER_CUT_HPP

#include <geos/io/WKTWriter.h>
#include <osmium/handler/progress.hpp>
#include "geometryreader.hpp"

// information about a single extract
class ExtractInfo {

public:
    std::string name;
    geos::algorithm::locate::IndexedPointInAreaLocator *locator;
    Osmium::Output::Base *writer;

    // the initial size of the id-trackers could be 0, because the vectors
    // are flexible, but providing here an estimation of the max. number of nodes
    // and ways gives the tool a "fail first" behaviour in the case of not enough memory
    // (better fail in init phase, not after 5 hours of processing)
    static const unsigned int est_max_node_id =   2300000000;
    static const unsigned int est_max_way_id =     240000000;
    static const unsigned int est_max_relation_id =  6000000;

    ExtractInfo(std::string name) {
        this->name = name;
    }

    bool contains(const shared_ptr<Osmium::OSM::Node const>& node) {
        // BOUNDARY 1
        // EXTERIOR 2
        // INTERIOR 0

        geos::geom::Coordinate c = geos::geom::Coordinate(node->get_lon(), node->get_lat(), DoubleNotANumber);
        return (0 == locator->locate(&c));
    }
};

// information about the cutting algorithm
template <class TExtractInfo>
class CutInfo {

protected:
    ~CutInfo() {
        for(int i=0, l = extracts.size(); i<l; i++) {
            extracts[i]->writer->final();
            delete extracts[i]->writer;
            delete extracts[i]->locator;
            delete extracts[i];
        }
    }

public:
    std::vector<TExtractInfo*> extracts;

    TExtractInfo *addExtract(std::string name, geos::geom::Geometry *poly) {
        fprintf(stderr, "opening writer for %s\n", name.c_str());
        Osmium::OSMFile outfile(name);
        Osmium::Output::Base *writer = outfile.create_output_file();

        const geos::geom::Envelope *env = poly->getEnvelopeInternal();
        const Osmium::OSM::Position min(env->getMinX(), env->getMinY());
        const Osmium::OSM::Position max(env->getMaxX(), env->getMaxY());

        Osmium::OSM::Bounds bounds;
        bounds.extend(min).extend(max);

        Osmium::OSM::Meta meta(bounds);
        writer->init(meta);

        TExtractInfo *ex = new TExtractInfo(name);
        ex->writer = writer;

        ex->locator = new geos::algorithm::locate::IndexedPointInAreaLocator(*poly);
        Osmium::Geometry::geos_geometry_factory()->destroyGeometry(poly);

        extracts.push_back(ex);
        return ex;
    }
};

template <class TCutInfo>
class Cut : public Osmium::Handler::Base {

protected:

    Osmium::Handler::Progress pg;
    TCutInfo *info;

public:

    bool debug;
    Cut(TCutInfo *info) : info(info) {}
};

#endif // SPLITTER_CUT_HPP

<|endoftext|>