<commit_before>/*

 Video Core
 Copyright (C) 2014 James G. Hurley

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 USA

 */

#if TARGET_OS_IPHONE
#define VERSION_OK 80000  <= __IPHONE_OS_VERSION_MAX_ALLOWED
#else
#define VERSION_OK 1090 <= MAC_OS_X_VERSION_MAX_ALLOWED
#endif

#include <stdio.h>
#include <videocore/transforms/Apple/H264Encode.h>
#include <videocore/mixers/IVideoMixer.hpp>

#if VERSION_OK
#include <VideoToolbox/VideoToolbox.h>
#endif

namespace videocore { namespace Apple {

#if VERSION_OK
    void vtCallback(void *outputCallbackRefCon,
                    void *sourceFrameRefCon,
                    OSStatus status,
                    VTEncodeInfoFlags infoFlags,
                    CMSampleBufferRef sampleBuffer )
    {
        CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sampleBuffer);
        CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false);
        CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);

        bool isKeyframe = false;
        if(attachments != NULL) {
            CFDictionaryRef attachment;
            CFBooleanRef dependsOnOthers;
            attachment = (CFDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
            dependsOnOthers = (CFBooleanRef)CFDictionaryGetValue(attachment, kCMSampleAttachmentKey_DependsOnOthers);
            isKeyframe = (dependsOnOthers == kCFBooleanFalse);
        }
        if(isKeyframe) {
            // Send the SPS and PPS.
            CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
            size_t spsSize, ppsSize;
            size_t parmCount;
            const uint8_t* sps, *pps;

            CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, &sps, &spsSize, &parmCount, nullptr );
            CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, &pps, &ppsSize, &parmCount, nullptr );

            std::unique_ptr<uint8_t[]> sps_buf (new uint8_t[spsSize + 4]) ;
            std::unique_ptr<uint8_t[]> pps_buf (new uint8_t[ppsSize + 4]) ;

            memcpy(&sps_buf[4], sps, spsSize);
            spsSize+=4 ;
            memcpy(&sps_buf[0], &spsSize, 4);
            memcpy(&pps_buf[4], pps, ppsSize);
            ppsSize += 4;
            memcpy(&pps_buf[0], &ppsSize, 4);

            ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)sps_buf.get(),spsSize, pts.value);
            ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)pps_buf.get(),ppsSize, pts.value);
        }

        char* bufferData;
        size_t size;
        CMBlockBufferGetDataPointer(block, 0, NULL, &size, &bufferData);

        ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)bufferData,size, pts.value);

    }
#endif
    H264Encode::H264Encode( int frame_w, int frame_h, int fps, int bitrate )
    : m_frameW(frame_w), m_frameH(frame_h), m_fps(fps), m_bitrate(bitrate)
    {
        setupCompressionSession();
    }
    H264Encode::~H264Encode()
    {
#if VERSION_OK
        if(m_compressionSession) {
            VTCompressionSessionInvalidate((VTCompressionSessionRef)m_compressionSession);
            CFRelease((VTCompressionSessionRef)m_compressionSession);
        }
#endif
    }
    void
    H264Encode::pushBuffer(const uint8_t *const data, size_t size, videocore::IMetadata &metadata)
    {
#if VERSION_OK
        if(m_compressionSession) {
            VTCompressionSessionRef session = (VTCompressionSessionRef)m_compressionSession;

            CMTime pts = CMTimeMake(metadata.timestampDelta, 1000.); // timestamp is in ms.
            CMTime dur = CMTimeMake(1, m_fps);

            VTCompressionSessionEncodeFrame(session, (CVPixelBufferRef)data, pts, dur, NULL, NULL, NULL);
        }
#endif
    }
    void
    H264Encode::setupCompressionSession()
    {
#if VERSION_OK
        // Parts of this code pulled from https://github.com/galad87/HandBrake-QuickSync-Mac/blob/2c1332958f7095c640cbcbcb45ffc955739d5945/libhb/platform/macosx/encvt_h264.c
        // More info from WWDC 2014 Session 513

        OSStatus err = noErr;
        CFMutableDictionaryRef encoderSpecifications = nullptr;

#if !TARGET_OS_IPHONE
        /** iOS is always hardware-accelerated **/
        CFStringRef key = kVTVideoEncoderSpecification_EncoderID;
        CFStringRef value = CFSTR("com.apple.videotoolbox.videoencoder.h264.gva");

        CFStringRef bkey = CFSTR("EnableHardwareAcceleratedVideoEncoder");
        CFBooleanRef bvalue = kCFBooleanTrue;

        CFStringRef ckey = CFSTR("RequireHardwareAcceleratedVideoEncoder");
        CFBooleanRef cvalue = kCFBooleanTrue;

        encoderSpecifications = CFDictionaryCreateMutable(
                                                                                kCFAllocatorDefault,
                                                                                3,
                                                                                &kCFTypeDictionaryKeyCallBacks,
                                                                                &kCFTypeDictionaryValueCallBacks);

        CFDictionaryAddValue(encoderSpecifications, bkey, bvalue);
        CFDictionaryAddValue(encoderSpecifications, ckey, cvalue);
        CFDictionaryAddValue(encoderSpecifications, key, value);

#endif
        VTCompressionSessionRef session = nullptr;

        err = VTCompressionSessionCreate(
                                         kCFAllocatorDefault,
                                         m_frameW,
                                         m_frameH,
                                         kCMVideoCodecType_H264,
                                         encoderSpecifications,
                                         NULL,
                                         NULL,
                                         &vtCallback,
                                         this,
                                         &session);

        if(err == noErr) {
            m_compressionSession = session;
            const int32_t v = m_fps * 2; // 2-second kfi
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxKeyFrameInterval, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            const int32_t v = m_fps / 2; // limit the number of frames kept in the buffer
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            //err = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxFrameDelayCount, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            const int v = m_fps;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session , kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
        }

        if(err == noErr) {
            const int v = m_bitrate;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel);
        }
        if(err == noErr) {
            VTCompressionSessionPrepareToEncodeFrames(session);
        }
#endif

    }

    void
    H264Encode::compressionSessionOutput(const uint8_t *data, size_t size, uint64_t ts)
    {
#if VERSION_OK
        auto l = m_output.lock();
        if(l) {
            videocore::VideoBufferMetadata md(ts);

            l->pushBuffer(data, size, md);
        }
#endif

    }
}
}<commit_msg>Fix the availability macros<commit_after>/*

 Video Core
 Copyright (C) 2014 James G. Hurley

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 USA

 */
#include <Availability.h>
#include <TargetConditionals.h>

#if TARGET_OS_IPHONE
#if defined(__PHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
#define VERSION_OK 1
#else
#define VERSION_OK 0
#endif
#else
#define VERSION_OK (1090 <= MAC_OS_X_VERSION_MAX_ALLOWED)
#endif

#include <stdio.h>
#include <videocore/transforms/Apple/H264Encode.h>
#include <videocore/mixers/IVideoMixer.hpp>

#if VERSION_OK==1
#include <VideoToolbox/VideoToolbox.h>
#endif

namespace videocore { namespace Apple {

#if VERSION_OK
    void vtCallback(void *outputCallbackRefCon,
                    void *sourceFrameRefCon,
                    OSStatus status,
                    VTEncodeInfoFlags infoFlags,
                    CMSampleBufferRef sampleBuffer )
    {
        CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sampleBuffer);
        CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false);
        CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);

        bool isKeyframe = false;
        if(attachments != NULL) {
            CFDictionaryRef attachment;
            CFBooleanRef dependsOnOthers;
            attachment = (CFDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
            dependsOnOthers = (CFBooleanRef)CFDictionaryGetValue(attachment, kCMSampleAttachmentKey_DependsOnOthers);
            isKeyframe = (dependsOnOthers == kCFBooleanFalse);
        }
        if(isKeyframe) {
            // Send the SPS and PPS.
            CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
            size_t spsSize, ppsSize;
            size_t parmCount;
            const uint8_t* sps, *pps;

            CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, &sps, &spsSize, &parmCount, nullptr );
            CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, &pps, &ppsSize, &parmCount, nullptr );

            std::unique_ptr<uint8_t[]> sps_buf (new uint8_t[spsSize + 4]) ;
            std::unique_ptr<uint8_t[]> pps_buf (new uint8_t[ppsSize + 4]) ;

            memcpy(&sps_buf[4], sps, spsSize);
            spsSize+=4 ;
            memcpy(&sps_buf[0], &spsSize, 4);
            memcpy(&pps_buf[4], pps, ppsSize);
            ppsSize += 4;
            memcpy(&pps_buf[0], &ppsSize, 4);

            ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)sps_buf.get(),spsSize, pts.value);
            ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)pps_buf.get(),ppsSize, pts.value);
        }

        char* bufferData;
        size_t size;
        CMBlockBufferGetDataPointer(block, 0, NULL, &size, &bufferData);

        ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)bufferData,size, pts.value);

    }
#endif
    H264Encode::H264Encode( int frame_w, int frame_h, int fps, int bitrate )
    : m_frameW(frame_w), m_frameH(frame_h), m_fps(fps), m_bitrate(bitrate)
    {
        setupCompressionSession();
    }
    H264Encode::~H264Encode()
    {
#if VERSION_OK
        if(m_compressionSession) {
            VTCompressionSessionInvalidate((VTCompressionSessionRef)m_compressionSession);
            CFRelease((VTCompressionSessionRef)m_compressionSession);
        }
#endif
    }
    void
    H264Encode::pushBuffer(const uint8_t *const data, size_t size, videocore::IMetadata &metadata)
    {
#if VERSION_OK
        if(m_compressionSession) {
            VTCompressionSessionRef session = (VTCompressionSessionRef)m_compressionSession;

            CMTime pts = CMTimeMake(metadata.timestampDelta, 1000.); // timestamp is in ms.
            CMTime dur = CMTimeMake(1, m_fps);

            VTCompressionSessionEncodeFrame(session, (CVPixelBufferRef)data, pts, dur, NULL, NULL, NULL);
        }
#endif
    }
    void
    H264Encode::setupCompressionSession()
    {
#if VERSION_OK
        // Parts of this code pulled from https://github.com/galad87/HandBrake-QuickSync-Mac/blob/2c1332958f7095c640cbcbcb45ffc955739d5945/libhb/platform/macosx/encvt_h264.c
        // More info from WWDC 2014 Session 513

        OSStatus err = noErr;
        CFMutableDictionaryRef encoderSpecifications = nullptr;

#if !TARGET_OS_IPHONE
        /** iOS is always hardware-accelerated **/
        CFStringRef key = kVTVideoEncoderSpecification_EncoderID;
        CFStringRef value = CFSTR("com.apple.videotoolbox.videoencoder.h264.gva");

        CFStringRef bkey = CFSTR("EnableHardwareAcceleratedVideoEncoder");
        CFBooleanRef bvalue = kCFBooleanTrue;

        CFStringRef ckey = CFSTR("RequireHardwareAcceleratedVideoEncoder");
        CFBooleanRef cvalue = kCFBooleanTrue;

        encoderSpecifications = CFDictionaryCreateMutable(
                                                                                kCFAllocatorDefault,
                                                                                3,
                                                                                &kCFTypeDictionaryKeyCallBacks,
                                                                                &kCFTypeDictionaryValueCallBacks);

        CFDictionaryAddValue(encoderSpecifications, bkey, bvalue);
        CFDictionaryAddValue(encoderSpecifications, ckey, cvalue);
        CFDictionaryAddValue(encoderSpecifications, key, value);

#endif
        VTCompressionSessionRef session = nullptr;

        err = VTCompressionSessionCreate(
                                         kCFAllocatorDefault,
                                         m_frameW,
                                         m_frameH,
                                         kCMVideoCodecType_H264,
                                         encoderSpecifications,
                                         NULL,
                                         NULL,
                                         &vtCallback,
                                         this,
                                         &session);

        if(err == noErr) {
            m_compressionSession = session;
            const int32_t v = m_fps * 2; // 2-second kfi
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxKeyFrameInterval, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            const int32_t v = m_fps / 2; // limit the number of frames kept in the buffer
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            //err = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxFrameDelayCount, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            const int v = m_fps;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session , kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
        }

        if(err == noErr) {
            const int v = m_bitrate;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel);
        }
        if(err == noErr) {
            VTCompressionSessionPrepareToEncodeFrames(session);
        }
#endif

    }

    void
    H264Encode::compressionSessionOutput(const uint8_t *data, size_t size, uint64_t ts)
    {
#if VERSION_OK
        auto l = m_output.lock();
        if(l) {
            videocore::VideoBufferMetadata md(ts);

            l->pushBuffer(data, size, md);
        }
#endif

    }
}
}<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <vector>
#include <boost/algorithm/string/trim.hpp>

using namespace std;
using namespace boost::algorithm;

int main()
{
	string user = getlogin();	//gets the user name and stores it in string user
	char name[100];				//initialize empty string to be used to get the host name
	gethostname(name, 100);		//gets the host's name and stores it in the char array variable name

	bool done = false;
	string command;
	char *token;
	vector<string> sc_cmd;				//sc_cmd stands for semicolon_commands - this holds the commands in string form
	vector<string> copy;			//this will hold the new commands from sc_cmd without any comments for a short while
	vector<string> and_cmd;			//this will hold the string of single commands combined by &&
	vector<string> or_cmd;			//this will hold the string of commands combined by ||
	while(!done)							//loop until user enters exit and the loop is terminated
	{
		cout << user << "@" << name << " $ ";	//output user name, @ symbol, the host name, followed by $
							// output at this point should result in: [user]@[host]$
		getline(cin, command);				//get the entire line of command from user
		if(command == "exit")
		{
			done = true;					//if the command they type in is initially exit
							//then there is no need to continue traversing the program, simply end
		}
		else
		{
			char cmd[command.size()];
			strcpy(cmd, command.c_str());		//make the inputted command into a c string so that we can parse
			token = strtok(cmd, ";");
			while(token != NULL)
			{
				sc_cmd.push_back(string(token));		//parse the string, looking for semicolons to split the commands
				token = strtok(NULL, ";");
			}
			for(int i = 0; i < sc_cmd.size(); ++i)
			{
				strcpy(cmd, (sc_cmd.at(i)).c_str());
				token = strtok(cmd, "#");					//parse the string looking for the start of a comment
				if(token != NULL)		//then only add the beginning part of the command and throw away everything after the #
				{
					if(string(token).find_first_not_of(' ') != std::string::npos) //if the parsed string is only white spaces
					{									//then dont add it list of commands
						copy.push_back(string(token));
					}
				}
			}
			sc_cmd.clear();
			for(int i = 0; i < copy.size(); ++i)
			{
				sc_cmd.push_back(copy.at(i));			//move the new filtered commands into the proper vector
			}
			copy.clear();
			for(int i = 0; i < sc_cmd.size(); ++i)		//keep executing these commands regardless of result from previous command
			{
				trim(sc_cmd.at(i));					//remove all the unnecessary white spaces around the string if in there
				strcpy(cmd, (sc_cmd.at(i)).c_str());
				token = strtok(cmd, "||");
				while(token != NULL)
				{
					or_cmd.push_back(string(token));		//parse the string for || commands and split the code down to && commnds
					token = strtok(NULL, "||");
				}
				int fails = 0;
				for(int i = 0; i < or_cmd.size(); ++i)			//keep doing || commands as long as the last command failed
				{
					trim(or_cmd.at(i));
					if(fails == i)
					{
						strcpy(cmd, (or_cmd.at(i)).c_str());
						token = strtok(cmd, "&&");
						while(token != NULL)			//parse the string command for && and split the code down to single commands
						{
							and_cmd.push_back(string(token));
							token = strtok(NULL, "&&");
						}
						int trues = 0;
						for(int i = 0; i < and_cmd.size(); ++i)		//keep doing && commands as long as the last command succeeded
						{
							if(trues == i)
							{
								strcpy(cmd, (and_cmd.at(i)).c_str());
								token = strtok(cmd, " ");
								while(token != NULL)			//break down the command into strings
								{
									copy.push_back(string(token));
									token = strtok(NULL, " ");
								}
								char* argv[copy.size()+1];		//create an array of char pointers
								for(int j = 0; j < copy.size(); ++j)
								{
									trim(copy.at(j));		//add char pointers into an array of pointers
									argv[j] = const_cast<char*>((copy.at(j)).c_str());	//this will allow us to use execvp
								}
								argv[copy.size()] = 0;
								int pid = fork();
								if(pid == -1)
								{
									perror("There was an error with fork(). ");
								}
								else if(pid == 0)
								{
									if(and_cmd.at(i) != "exit")	//only move along to execvp if the command is not exit
									{
										if(-1 == execvp((copy.at(0)).c_str(), argv))
										{
											perror("There was an error with execvp(). ");
											_exit(1);		//if the command failed, then kill the child process and exit
										}
									}
									else		//if the command is to exit, dont do anything, simply kill the child process and exit
									{
										_exit(1);
									}
								}
								else
								{
									int status;
									wait(&status);
									if(status == -1)
									{
										perror("There was en error with wait(). ");
									}
									else if(status == 0)		//if the last command was executed successfully, increase the counter
									{
										++trues;
									}
									if(and_cmd.at(i) == "exit")		//if the user entered the exit command, end the shell and program
									{
										done = true;
										return 0;
									}
								}
							}
							copy.clear();				//clear out the vector to be used again
						}									//end of and_cmd
						if(trues != and_cmd.size())
						{
							fails++;			//if the amount of commands that were successfully executed is not the same as the
												//number of commands executed, then increase the number of commands failed
						}
					}
					and_cmd.clear();			//clear out the commands in and vector since we are done
				}						//end of or_cmd
				or_cmd.clear();			//clear out the commands in the or vector since we are done
			}			//end of sc_cmd
			sc_cmd.clear();			//clear out the commands in the semicolon vector since we are done
		}
	}				//end of while(!done) loop
	return 0;
}
<commit_msg>fixed comment bug in command line<commit_after>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <vector>
#include <boost/algorithm/string/trim.hpp>

using namespace std;
using namespace boost::algorithm;

int main()
{
	string user = getlogin();	//gets the user name and stores it in string user
	char name[100];				//initialize empty string to be used to get the host name
	gethostname(name, 100);		//gets the host's name and stores it in the char array variable name

	bool done = false;
	string command;
	char *token;
	vector<string> sc_cmd;				//sc_cmd stands for semicolon_commands - this holds the commands in string form
	vector<string> copy;			//this will hold the new commands from sc_cmd without any comments for a short while
	vector<string> and_cmd;			//this will hold the string of single commands combined by &&
	vector<string> or_cmd;			//this will hold the string of commands combined by ||
	while(!done)							//loop until user enters exit and the loop is terminated
	{
		cout << user << "@" << name << " $ ";	//output user name, @ symbol, the host name, followed by $
							// output at this point should result in: [user]@[host]$
		getline(cin, command);				//get the entire line of command from user
		if(command == "exit")
		{
			done = true;					//if the command they type in is initially exit
							//then there is no need to continue traversing the program, simply end
		}
		else
		{
			char* cmd = new char[command.size()];
			//strcpy(cmd, command.c_str());		//make the inputted command into a c string so that we can parse
			//token = strtok(cmd, "#");					//parse the string looking for the start of a comment
			//if(token != NULL)		//then only add the beginning part of the command and throw away everything after the #
			//{
			//	if(string(token).find_first_not_of(' ') != std::string::npos) //if the parsed string is only white spaces
			//	{									//then dont add it list of commands
			//		copy.push_back(string(token));
			//	}
			//}
			unsigned int loc = command.find_first_of("#");
			command = command.substr(0, loc);
			if(command.size() > 0)
			{
				copy.push_back(command);
			}
			if(copy.size() > 0)
			{
				strcpy(cmd, (copy.at(0)).c_str());
				copy.clear();
				token = strtok(cmd, ";");
				while(token != NULL)
				{
					sc_cmd.push_back(string(token));		//parse the string, looking for semicolons to split the commands
					token = strtok(NULL, ";");
				}
				for(unsigned int i = 0; i < sc_cmd.size(); ++i)
				{
					strcpy(cmd, (sc_cmd.at(i)).c_str());
					token = strtok(cmd, "#");					//parse the string looking for the start of a comment
					if(token != NULL)		//then only add the beginning part of the command and throw away everything after the #
					{
						if(string(token).find_first_not_of(' ') != std::string::npos) //if the parsed string is only white spaces
						{									//then dont add it list of commands
							copy.push_back(string(token));
						}
					}
				}
				sc_cmd.clear();
				for(unsigned int i = 0; i < copy.size(); ++i)
				{
					sc_cmd.push_back(copy.at(i));			//move the new filtered commands into the proper vector
				}
				copy.clear();
				for(unsigned int i = 0; i < sc_cmd.size(); ++i)	//keep executing these commands regardless of result from previous command
				{
					trim(sc_cmd.at(i));					//remove all the unnecessary white spaces around the string if in there
					strcpy(cmd, (sc_cmd.at(i)).c_str());
					token = strtok(cmd, "||");
					while(token != NULL)
					{
						or_cmd.push_back(string(token));		//parse the string for || commands and split the code down to && commnds
						token = strtok(NULL, "||");
					}
					unsigned int fails = 0;
					for(unsigned int i = 0; i < or_cmd.size(); ++i)			//keep doing || commands as long as the last command failed
					{
						trim(or_cmd.at(i));
						if(fails == i)
						{
							strcpy(cmd, (or_cmd.at(i)).c_str());
							token = strtok(cmd, "&&");
							while(token != NULL)			//parse the string command for && and split the code down to single commands
							{
								and_cmd.push_back(string(token));
								token = strtok(NULL, "&&");
							}
							unsigned int trues = 0;
							for(unsigned int i = 0; i < and_cmd.size(); ++i)//keep doing && commands as long as the last command succeeded
							{
								if(trues == i)
								{
									strcpy(cmd, (and_cmd.at(i)).c_str());
									token = strtok(cmd, " ");
									while(token != NULL)			//break down the command into strings
									{
										copy.push_back(string(token));
										token = strtok(NULL, " ");
									}
									char **argv = new char*[copy.size()+1];		//create an array of char pointers
									for(unsigned int j = 0; j < copy.size(); ++j)
									{
										trim(copy.at(j));		//add char pointers into an array of pointers
										argv[j] = const_cast<char*>((copy.at(j)).c_str());	//this will allow us to use execvp
									}
									argv[copy.size()] = 0;
									int pid = fork();
									if(pid == -1)
									{
										perror("There was an error with fork(). ");
									}
									else if(pid == 0)
									{
										if(and_cmd.at(i) != "exit")	//only move along to execvp if the command is not exit
										{
											if(-1 == execvp((copy.at(0)).c_str(), argv))
											{
												perror("There was an error with execvp(). ");
												_exit(1);		//if the command failed, then kill the child process and exit
											}
										}
										else		//if the command is to exit, dont do anything, simply kill the child process and exit
										{
											_exit(1);
										}
									}
									else
									{
										int status;
										wait(&status);
										if(status == -1)
										{
											perror("There was en error with wait(). ");
										}
										else if(status == 0)		//if the last command was executed successfully, increase the counter
										{
											++trues;
										}
										if(and_cmd.at(i) == "exit")		//if the user entered the exit command, end the shell and program
										{
											done = true;
											return 0;
										}
									}
								delete []argv;
								}
								copy.clear();				//clear out the vector to be used again
							}									//end of and_cmd
							if(trues != and_cmd.size())
							{
								fails++;			//if the amount of commands that were successfully executed is not the same as the
													//number of commands executed, then increase the number of commands failed
							}
						}
						and_cmd.clear();			//clear out the commands in and vector since we are done
					}						//end of or_cmd
					or_cmd.clear();			//clear out the commands in the or vector since we are done
				}			//end of sc_cmd
			sc_cmd.clear();			//clear out the commands in the semicolon vector since we are done
			}
		delete []cmd;
		}
	}				//end of while(!done) loop
	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2015 FMAW

#include <sstream>
#include <cstdlib>

#include "./constants.h"

#include "./FMAW.h"  // Import our awesome framework!
#include "./memtrack.h"

//------------------------------------------------------------------------------
// Graphic references
//------------------------------------------------------------------------------

#include "./warrior.h"
#include "./knight.h"
#include "./sniper.h"

#include "./gfx_brick.h"
#include "./gfx_gradient.h"

#include "./gfx_black.h"
#include "./gfx_blank.h"

#include "./gfx_Base.h"
#include "./gfx_Bridge.h"
#include "./gfx_Forest.h"
#include "./gfx_Grass.h"
#include "./gfx_Mountain.h"
#include "./gfx_River.h"

//------------------------------------------------------------------------------
// Background tile entries
//------------------------------------------------------------------------------

#define TILE_EMPTY     0  // Tile 0 = empty
#define TILE_BRICK     1  // Tile 1 = brick
#define TILE_GRADIENT  2  // Tile 2 = gradient

//------------------------------------------------------------------------------
// Background...
//------------------------------------------------------------------------------

//----------//------------------------------------------------------------------
//----------// Palette entries
//----------//------------------------------------------------------------------

#define PAL_BRICKS     0  // Brick palette (entry 0->15).
#define PAL_GRADIENT   1  // Gradient palette (entry 16->31).

#define BACKDROP_COLOR RGB8(190, 255, 255)

//------------------------------------------------------------------------------
// Game objects
//------------------------------------------------------------------------------

#include "./main_menu.h"
#include "./grid.h"
#include "./gridmap.h"
#include "./turnManager.h"
#include "./player.h"
#include "./player_ai.h"

Grid grid;
MainMenu menu;
Player *blue;
Player *red;

FMAW::FixedReal g_camera_x;
FMAW::FixedReal g_camera_y;

//------------------------------------------------------------------------------
// Main code section
//------------------------------------------------------------------------------

/**
 * Sets up graphics.
 * Calling this method will require to reinitialize all sprites!
 */
void setupGraphics(void) {
    FMAW::TileAttributes gfx_Base_attributes {
        gfx_BaseTiles,
        gfx_BaseTilesLen,
        gfx_BasePal,
        gfx_BasePalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile base_tile(gfx_Base_attributes);
    FMAW::printf("El fondo Base tiene ID=%d", base_tile.ID);

    FMAW::TileAttributes gfx_Bridge_attributes {
        gfx_BridgeTiles,
        gfx_BridgeTilesLen,
        gfx_BridgePal,
        gfx_BridgePalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Bridge_tile(gfx_Bridge_attributes);
    FMAW::printf("El fondo Bridge tiene ID=%d", Bridge_tile.ID);

    FMAW::TileAttributes gfx_Forest_attributes {
        gfx_ForestTiles,
        gfx_ForestTilesLen,
        gfx_ForestPal,
        gfx_ForestPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Forest_tile(gfx_Forest_attributes);
    FMAW::printf("El fondo Forest tiene ID=%d", Forest_tile.ID);

    FMAW::TileAttributes gfx_Grass_attributes {
        gfx_GrassTiles,
        gfx_GrassTilesLen,
        gfx_GrassPal,
        gfx_GrassPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Grass_tile(gfx_Grass_attributes);
    FMAW::printf("El fondo Grass tiene ID=%d", Grass_tile.ID);

    FMAW::TileAttributes gfx_Mountain_attributes {
        gfx_MountainTiles,
        gfx_MountainTilesLen,
        gfx_MountainPal,
        gfx_MountainPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Mountain_tile(gfx_Mountain_attributes);
    FMAW::printf("El fondo Mountain tiene ID=%d", Mountain_tile.ID);

    FMAW::TileAttributes gfx_River_attributes {
        gfx_RiverTiles,
        gfx_RiverTilesLen,
        gfx_RiverPal,
        gfx_RiverPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile River_tile(gfx_River_attributes);
    FMAW::printf("El fondo River tiene ID=%d", River_tile.ID);

    //------------------------------------------------------------------------//

    // Set backdrop color.
    FMAW::setBackgroundColor(BACKDROP_COLOR);

    FMAW::Background(0).setScreenBaseBlock(2);
    FMAW::Background(1).setScreenBaseBlock(3);
    FMAW::Background(2).setScreenBaseBlock(4);
    FMAW::Background(3).setScreenBaseBlock(5);
}

void update_camera() { }

void update_logic() {
    FMAW::Input::check();
    FMAW::Timer::check();
    update_camera();
}

void update_graphics() {
    FMAW::Camera::setHorizontalOffset(g_camera_x);
    grid.renderCharacters();
}

int main(void) {
    auto finishTurnCallback = []() {
        grid.resetUnitMovements();
        FMAW::printf("Tocaría cambiar de turno!");
        grid.resetPickedUpCell();
        TurnManager::finishTurn();
        menu.adjustCurrentTile();
    };

    blue = new Player();
    TurnManager::addPlayer(blue);
    red = new Player();
    TurnManager::addPlayer(red);

    FMAW::init(update_graphics, update_logic);
    setupGraphics();

    grid.initCursor();

    GridMap::loadDefaultGridMap(&grid);

    auto addSomeUnits = []() {
        Warrior *warriorA = new Warrior(blue->getID());
        Warrior *warriorB = new Warrior(red->getID());
        Sniper *warriorC = new Sniper(blue->getID());
        Sniper *warriorD = new Sniper(red->getID());
        Warrior *warriorE = new Warrior(blue->getID());
        Knight *warriorF = new Knight(blue->getID());
        Knight *warriorG = new Knight(blue->getID());
        /*
        Warrior *warriorI = new Warrior(blue.getID());
        Warrior *warriorJ = new Warrior(blue.getID());
        Warrior *warriorK = new Warrior(blue.getID());
        Warrior *warriorL = new Warrior(blue.getID());
        */

        grid.cellAtIndexPath({0, 0})->setCharacter(warriorA);
        grid.cellAtIndexPath({4, 2})->setCharacter(warriorB);

        grid.cellAtIndexPath({0, 1})->setCharacter(warriorC);
        grid.cellAtIndexPath({0, 2})->setCharacter(warriorD);
        grid.cellAtIndexPath({0, 3})->setCharacter(warriorE);
        grid.cellAtIndexPath({0, 4})->setCharacter(warriorF);
        grid.cellAtIndexPath({0, 5})->setCharacter(warriorG);
        /*
        grid.cellAtIndexPath({1, 1})->setCharacter(warriorI);
        grid.cellAtIndexPath({1, 2})->setCharacter(warriorJ);
        grid.cellAtIndexPath({1, 3})->setCharacter(warriorK);
        grid.cellAtIndexPath({1, 4})->setCharacter(warriorL);
        */

        grid.resetUnitMovements();
    };

    auto releaseB = [finishTurnCallback]() {
        if (menu.isInForeground() || grid.isInteractionEnabled()) return;
        finishTurnCallback();
        FMAW::printf("Has soltado la tecla B");
    };
    FMAW::Input::onButtonBReleased(releaseB);

    auto releaseStart = []() {
        // Disable interaction is saved game is being played.
        if (grid.isPlayingSavedFile()) return;

        if (menu.isInForeground()) {
            menu.makeBackground();
            grid.enqueueCallbacks();
        } else {
            menu.makeForeground();
            grid.dequeueCallbacks();
        }
        // MemTrack::TrackListMemoryUsage();
    };
    FMAW::Input::onButtonStartReleased(releaseStart);

    auto newGameCallback = [addSomeUnits, finishTurnCallback]() {
        TurnManager::reset();
        delete blue;
        delete red;
        blue = new Player();
        TurnManager::addPlayer(blue);
        red = new PlayerAI(&grid, finishTurnCallback);
        red->print();
        TurnManager::addPlayer(red);

        FMAW::printf("Should start a new game!");
        grid.clearGridUnits();
        FMAW::Tile::releaseAllSpriteMemory();
        grid.initCursor();
        addSomeUnits();
        grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
        menu.makeBackground();
        grid.enqueueCallbacks();
    };

    auto loadGameCallback = [addSomeUnits]() {
        menu.makeBackground();
        FMAW::printf("Should load a previous game!");
        auto callback = [&addSomeUnits](bool success) {
            FMAW::printf("Played saved game: %d", success);
            if (success) {
                addSomeUnits();
                grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
            }
            menu.makeForeground();
        };
        grid.playSavedHistory(DEFAULT_SAVEGAME_FILE, callback);
    };

    auto versusCallback = [addSomeUnits]() {
        TurnManager::reset();
        delete blue;
        delete red;
        blue = new Player();
        TurnManager::addPlayer(blue);
        red = new Player();
        red->print();
        TurnManager::addPlayer(red);

        FMAW::printf("Should start a new versus game!");
        grid.clearGridUnits();
        FMAW::Tile::releaseAllSpriteMemory();
        grid.initCursor();
        addSomeUnits();
        grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
        menu.makeBackground();
        grid.enqueueCallbacks();
    };

    menu.newGameCallback = newGameCallback;
    menu.loadGameCallback = loadGameCallback;
    menu.versusCallback = versusCallback;

    addSomeUnits();

    auto gameOverCallback = [](int winner) {
        FMAW::printf("Winner is %d!", winner);
        TurnManager::setWinner(winner);
        menu.adjustCurrentTile();
    };
    grid.gameOverCallback = gameOverCallback;

    menu.init();
    grid.enqueueCallbacks();
    grid.renderBackground();
    if (!grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE)) {
        FMAW::printf("ERROR when trying to write file");
    }

    FMAW::Sound::setBackgroundMusic(MOD_FLATOUTLIES);

    FMAW::start();

    return 0;
}
<commit_msg>Added sound<commit_after>// Copyright 2015 FMAW

#include <sstream>
#include <cstdlib>

#include "./constants.h"

#include "./FMAW.h"  // Import our awesome framework!
#include "./memtrack.h"

//------------------------------------------------------------------------------
// Graphic references
//------------------------------------------------------------------------------

#include "./warrior.h"
#include "./knight.h"
#include "./sniper.h"

#include "./gfx_brick.h"
#include "./gfx_gradient.h"

#include "./gfx_black.h"
#include "./gfx_blank.h"

#include "./gfx_Base.h"
#include "./gfx_Bridge.h"
#include "./gfx_Forest.h"
#include "./gfx_Grass.h"
#include "./gfx_Mountain.h"
#include "./gfx_River.h"

//------------------------------------------------------------------------------
// Background tile entries
//------------------------------------------------------------------------------

#define TILE_EMPTY     0  // Tile 0 = empty
#define TILE_BRICK     1  // Tile 1 = brick
#define TILE_GRADIENT  2  // Tile 2 = gradient

//------------------------------------------------------------------------------
// Background...
//------------------------------------------------------------------------------

//----------//------------------------------------------------------------------
//----------// Palette entries
//----------//------------------------------------------------------------------

#define PAL_BRICKS     0  // Brick palette (entry 0->15).
#define PAL_GRADIENT   1  // Gradient palette (entry 16->31).

#define BACKDROP_COLOR RGB8(190, 255, 255)

//------------------------------------------------------------------------------
// Game objects
//------------------------------------------------------------------------------

#include "./main_menu.h"
#include "./grid.h"
#include "./gridmap.h"
#include "./turnManager.h"
#include "./player.h"
#include "./player_ai.h"

Grid grid;
MainMenu menu;
Player *blue;
Player *red;

FMAW::FixedReal g_camera_x;
FMAW::FixedReal g_camera_y;

//------------------------------------------------------------------------------
// Main code section
//------------------------------------------------------------------------------

/**
 * Sets up graphics.
 * Calling this method will require to reinitialize all sprites!
 */
void setupGraphics(void) {
    FMAW::TileAttributes gfx_Base_attributes {
        gfx_BaseTiles,
        gfx_BaseTilesLen,
        gfx_BasePal,
        gfx_BasePalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile base_tile(gfx_Base_attributes);
    FMAW::printf("El fondo Base tiene ID=%d", base_tile.ID);

    FMAW::TileAttributes gfx_Bridge_attributes {
        gfx_BridgeTiles,
        gfx_BridgeTilesLen,
        gfx_BridgePal,
        gfx_BridgePalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Bridge_tile(gfx_Bridge_attributes);
    FMAW::printf("El fondo Bridge tiene ID=%d", Bridge_tile.ID);

    FMAW::TileAttributes gfx_Forest_attributes {
        gfx_ForestTiles,
        gfx_ForestTilesLen,
        gfx_ForestPal,
        gfx_ForestPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Forest_tile(gfx_Forest_attributes);
    FMAW::printf("El fondo Forest tiene ID=%d", Forest_tile.ID);

    FMAW::TileAttributes gfx_Grass_attributes {
        gfx_GrassTiles,
        gfx_GrassTilesLen,
        gfx_GrassPal,
        gfx_GrassPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Grass_tile(gfx_Grass_attributes);
    FMAW::printf("El fondo Grass tiene ID=%d", Grass_tile.ID);

    FMAW::TileAttributes gfx_Mountain_attributes {
        gfx_MountainTiles,
        gfx_MountainTilesLen,
        gfx_MountainPal,
        gfx_MountainPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile Mountain_tile(gfx_Mountain_attributes);
    FMAW::printf("El fondo Mountain tiene ID=%d", Mountain_tile.ID);

    FMAW::TileAttributes gfx_River_attributes {
        gfx_RiverTiles,
        gfx_RiverTilesLen,
        gfx_RiverPal,
        gfx_RiverPalLen,
        FMAW::TypeBackground,
        FMAW::ScreenMain
    };
    FMAW::Tile River_tile(gfx_River_attributes);
    FMAW::printf("El fondo River tiene ID=%d", River_tile.ID);

    //------------------------------------------------------------------------//

    // Set backdrop color.
    FMAW::setBackgroundColor(BACKDROP_COLOR);

    FMAW::Background(0).setScreenBaseBlock(2);
    FMAW::Background(1).setScreenBaseBlock(3);
    FMAW::Background(2).setScreenBaseBlock(4);
    FMAW::Background(3).setScreenBaseBlock(5);
}

void update_camera() { }

void update_logic() {
    FMAW::Input::check();
    FMAW::Timer::check();
    update_camera();
}

void update_graphics() {
    FMAW::Camera::setHorizontalOffset(g_camera_x);
    grid.renderCharacters();
}

int main(void) {
    auto finishTurnCallback = []() {
        grid.resetUnitMovements();
        FMAW::printf("Tocaría cambiar de turno!");
        grid.resetPickedUpCell();
        TurnManager::finishTurn();
        menu.adjustCurrentTile();
    };

    blue = new Player();
    TurnManager::addPlayer(blue);
    red = new Player();
    TurnManager::addPlayer(red);

    FMAW::init(update_graphics, update_logic);
    setupGraphics();

    grid.initCursor();

    GridMap::loadDefaultGridMap(&grid);

    auto addSomeUnits = []() {
        Warrior *warriorA = new Warrior(blue->getID());
        Warrior *warriorB = new Warrior(red->getID());
        Sniper *warriorC = new Sniper(blue->getID());
        Sniper *warriorD = new Sniper(red->getID());
        Warrior *warriorE = new Warrior(blue->getID());
        Knight *warriorF = new Knight(blue->getID());
        Knight *warriorG = new Knight(blue->getID());
        /*
        Warrior *warriorI = new Warrior(blue.getID());
        Warrior *warriorJ = new Warrior(blue.getID());
        Warrior *warriorK = new Warrior(blue.getID());
        Warrior *warriorL = new Warrior(blue.getID());
        */

        grid.cellAtIndexPath({0, 0})->setCharacter(warriorA);
        grid.cellAtIndexPath({4, 2})->setCharacter(warriorB);

        grid.cellAtIndexPath({0, 1})->setCharacter(warriorC);
        grid.cellAtIndexPath({0, 2})->setCharacter(warriorD);
        grid.cellAtIndexPath({0, 3})->setCharacter(warriorE);
        grid.cellAtIndexPath({0, 4})->setCharacter(warriorF);
        grid.cellAtIndexPath({0, 5})->setCharacter(warriorG);
        /*
        grid.cellAtIndexPath({1, 1})->setCharacter(warriorI);
        grid.cellAtIndexPath({1, 2})->setCharacter(warriorJ);
        grid.cellAtIndexPath({1, 3})->setCharacter(warriorK);
        grid.cellAtIndexPath({1, 4})->setCharacter(warriorL);
        */

        grid.resetUnitMovements();
    };

    auto releaseB = [finishTurnCallback]() {
        if (menu.isInForeground() || grid.isInteractionEnabled()) return;
        finishTurnCallback();
        FMAW::printf("Has soltado la tecla B");
    };
    FMAW::Input::onButtonBReleased(releaseB);

    int ambulanceSoundID = FMAW::Sound::registerFX(FMAW::Sound::effectWithSoundID(
                               SFX_BOOM));

    auto releaseStart = [ambulanceSoundID]() {
        // Disable interaction is saved game is being played.
        if (grid.isPlayingSavedFile()) return;

        if (menu.isInForeground()) {
            menu.makeBackground();
            grid.enqueueCallbacks();
        } else {
            menu.makeForeground();
            grid.dequeueCallbacks();
        }
        // MemTrack::TrackListMemoryUsage();

        FMAW::Sound::playEffect(ambulanceSoundID);
    };

    FMAW::Input::onButtonStartReleased(releaseStart);

    auto newGameCallback = [addSomeUnits, finishTurnCallback]() {
        TurnManager::reset();
        delete blue;
        delete red;
        blue = new Player();
        TurnManager::addPlayer(blue);
        red = new PlayerAI(&grid, finishTurnCallback);
        red->print();
        TurnManager::addPlayer(red);

        FMAW::printf("Should start a new game!");
        grid.clearGridUnits();
        FMAW::Tile::releaseAllSpriteMemory();
        grid.initCursor();
        addSomeUnits();
        grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
        menu.makeBackground();
        grid.enqueueCallbacks();
    };

    auto loadGameCallback = [addSomeUnits]() {
        menu.makeBackground();
        FMAW::printf("Should load a previous game!");
        auto callback = [&addSomeUnits](bool success) {
            FMAW::printf("Played saved game: %d", success);
            if (success) {
                addSomeUnits();
                grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
            }
            menu.makeForeground();
        };
        grid.playSavedHistory(DEFAULT_SAVEGAME_FILE, callback);
    };

    auto versusCallback = [addSomeUnits]() {
        TurnManager::reset();
        delete blue;
        delete red;
        blue = new Player();
        TurnManager::addPlayer(blue);
        red = new Player();
        red->print();
        TurnManager::addPlayer(red);

        FMAW::printf("Should start a new versus game!");
        grid.clearGridUnits();
        FMAW::Tile::releaseAllSpriteMemory();
        grid.initCursor();
        addSomeUnits();
        grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE);
        menu.makeBackground();
        grid.enqueueCallbacks();
    };

    menu.newGameCallback = newGameCallback;
    menu.loadGameCallback = loadGameCallback;
    menu.versusCallback = versusCallback;

    addSomeUnits();

    auto gameOverCallback = [](int winner) {
        FMAW::printf("Winner is %d!", winner);
        TurnManager::setWinner(winner);
        menu.adjustCurrentTile();
    };
    grid.gameOverCallback = gameOverCallback;

    menu.init();
    grid.enqueueCallbacks();
    grid.renderBackground();
    if (!grid.enableSavingHistory(DEFAULT_SAVEGAME_FILE)) {
        FMAW::printf("ERROR when trying to write file");
    }

    FMAW::Sound::setBackgroundMusic(MOD_FLATOUTLIES);

    FMAW::start();

    return 0;
}
<|endoftext|>


<commit_before>/*
VROOM (Vehicle Routing Open-source Optimization Machine)
Copyright (C) 2015, Julien Coupey

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

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <sstream>
#include <unistd.h>
#include "./structures/typedefs.h"
#include "./heuristics/tsp_strategy.h"

void display_usage(){
  std::string usage = "VROOM Copyright (C) 2015, Julien Coupey\n";
  usage += "Usage :\n\tvroom [OPTION]... \"loc=lat,lon&loc=lat,lon[&loc=lat,lon...]\"";
  usage += "\n\tvroom [OPTION]... -i FILE\n";
  usage += "Options:\n";
  usage += "\t-a=ADDRESS\t OSRM server address (\"0.0.0.0\")\n";
  usage += "\t-p=PORT,\t OSRM listening port (5000)\n";
  usage += "\t-g,\t\t get detailed route geometry for the solution\n";
  usage += "\t-o=OUTPUT,\t output file name\n";
  usage += "\t-i=FILE,\t read input from FILE rather than from\n\t\t\t command-line\n";
  usage += "\t-t,\t\t read input file from -i option as TSPLIB format\n";
  usage += "\t-v,\t\t turn on verbose output\n";
  usage += "\nThis program is distributed under the terms of the GNU General Public\n";
  usage += "License, version 3, and comes with ABSOLUTELY NO WARRANTY.\n";
  std::cout << usage << std::endl;
  exit(0);
}

int main(int argc, char **argv){
  // Default options.
  cl_args_t cl_args;
  cl_args.geometry = false;
  cl_args.osrm_address = "0.0.0.0";
  cl_args.osrm_port = "5000";
  cl_args.use_osrm = true;
  cl_args.use_tsplib = false;
  cl_args.verbose = false;

  // Parsing command-line arguments.
  const char* optString = "a:gi:o:p:tvh?";
  int opt = getopt(argc, argv, optString);

  while(opt != -1) {
    switch(opt){
    case 'a':
      cl_args.osrm_address = optarg;
      break;
    case 'g':
      cl_args.geometry = true;
      break;
    case 'h':
      display_usage();
      break;
    case 'i':
      cl_args.input_file = optarg;
      break;
    case 'o':
      cl_args.output_file = optarg;
      break;
    case 'p':
      cl_args.osrm_port = optarg;
      break;
    case 't':
      cl_args.use_tsplib = true;
      cl_args.use_osrm = false;
      break;
    case 'v':
      cl_args.verbose = true;
      break;
    default:
      break;
    }
    opt = getopt(argc, argv, optString);
  }

  if(cl_args.input_file.empty()){
    // Getting input from command-line.
    if(argc == optind){
      // Missing argument!
      display_usage();
    }
    cl_args.input = argv[optind];
  }
  else{
    // Getting input from provided file.
    std::ifstream ifs (cl_args.input_file);
    std::stringstream buffer;
    buffer << ifs.rdbuf();
    cl_args.input = buffer.str();
  }

  try{
    solve_atsp(cl_args);
  }
  catch(const custom_exception& e){
    std::cout << "Error: " << e.get_message() << std::endl;
    exit(1);
  }

  return 0;
}
<commit_msg>Write to cerr when catching an exception. #9<commit_after>/*
VROOM (Vehicle Routing Open-source Optimization Machine)
Copyright (C) 2015, Julien Coupey

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

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <sstream>
#include <unistd.h>
#include "./structures/typedefs.h"
#include "./heuristics/tsp_strategy.h"

void display_usage(){
  std::string usage = "VROOM Copyright (C) 2015, Julien Coupey\n";
  usage += "Usage :\n\tvroom [OPTION]... \"loc=lat,lon&loc=lat,lon[&loc=lat,lon...]\"";
  usage += "\n\tvroom [OPTION]... -i FILE\n";
  usage += "Options:\n";
  usage += "\t-a=ADDRESS\t OSRM server address (\"0.0.0.0\")\n";
  usage += "\t-p=PORT,\t OSRM listening port (5000)\n";
  usage += "\t-g,\t\t get detailed route geometry for the solution\n";
  usage += "\t-o=OUTPUT,\t output file name\n";
  usage += "\t-i=FILE,\t read input from FILE rather than from\n\t\t\t command-line\n";
  usage += "\t-t,\t\t read input file from -i option as TSPLIB format\n";
  usage += "\t-v,\t\t turn on verbose output\n";
  usage += "\nThis program is distributed under the terms of the GNU General Public\n";
  usage += "License, version 3, and comes with ABSOLUTELY NO WARRANTY.\n";
  std::cout << usage << std::endl;
  exit(0);
}

int main(int argc, char **argv){
  // Default options.
  cl_args_t cl_args;
  cl_args.geometry = false;
  cl_args.osrm_address = "0.0.0.0";
  cl_args.osrm_port = "5000";
  cl_args.use_osrm = true;
  cl_args.use_tsplib = false;
  cl_args.verbose = false;

  // Parsing command-line arguments.
  const char* optString = "a:gi:o:p:tvh?";
  int opt = getopt(argc, argv, optString);

  while(opt != -1) {
    switch(opt){
    case 'a':
      cl_args.osrm_address = optarg;
      break;
    case 'g':
      cl_args.geometry = true;
      break;
    case 'h':
      display_usage();
      break;
    case 'i':
      cl_args.input_file = optarg;
      break;
    case 'o':
      cl_args.output_file = optarg;
      break;
    case 'p':
      cl_args.osrm_port = optarg;
      break;
    case 't':
      cl_args.use_tsplib = true;
      cl_args.use_osrm = false;
      break;
    case 'v':
      cl_args.verbose = true;
      break;
    default:
      break;
    }
    opt = getopt(argc, argv, optString);
  }

  if(cl_args.input_file.empty()){
    // Getting input from command-line.
    if(argc == optind){
      // Missing argument!
      display_usage();
    }
    cl_args.input = argv[optind];
  }
  else{
    // Getting input from provided file.
    std::ifstream ifs (cl_args.input_file);
    std::stringstream buffer;
    buffer << ifs.rdbuf();
    cl_args.input = buffer.str();
  }

  try{
    solve_atsp(cl_args);
  }
  catch(const custom_exception& e){
    std::cerr << "Error: " << e.get_message() << std::endl;
    exit(1);
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "neovim.hpp"

int main() {
    NeoVim client;

    client.send("vim_list_runtime_paths");

    sleep(1);
    client.send("vim_del_current_line");
    client.send("vim_list_runtime_paths");

    for(;;) {}

    return 0;
}
<commit_msg>add test func<commit_after>#include "neovim.hpp"

int main() {
    NeoVim client;

    client.send("vim_list_runtime_paths");

    sleep(1);
    client.send("vim_del_current_line");
    client.send("vim_list_runtime_paths");
    client.send("vim_set_current_line", "testhogefuga");

    for(;;) {}

    return 0;
}
<|endoftext|>


<commit_before>#include "ball.hpp"
#include "utils.hpp"
#include "pong.hpp"
#include "debug.hpp"
#include "sdl_audio.h"

#include <iostream>
#include <cmath>

/**
 * @brief Ball::Ball The Ball implementation of the class Ball.
 * @param ballSurface The surface that carries the image of the ball.
 * @param ballRenderer The renderer which will be used to render the ball
 * texture on the screen.
 * @param xCor The actual position in X axis of the ball.
 * @param yCor The actual position in Y axis of the ball.
 * @param width The width size of the ball.
 * @param height The height size of the ball.
 */
Ball::Ball(SDL_Surface* ballSurface, SDL_Renderer** ballRenderer, float xCor,
           float yCor, int width, int height)
{
    if(ballSurface == NULL || ballRenderer == NULL)
        logerr("The ball surface or the ball renderer passed is null.");
    else
    {
        //Arguments initialization
        this->ballRect = new SDL_Rect();

        this->ballSurface   = ballSurface;

        setXVelocity(2.0);
        setYVelocity(0.0);

        this->ballRect->x   = xCor;
        this->ballRect->y   = yCor;
        this->ballRect->w   = width;
        this->ballRect->h   = height;

        this->ballTexture = SDL_CreateTextureFromSurface(*ballRenderer,
                                                         ballSurface);

        if(this->ballTexture == NULL)
        {
            logerr("Failed to create ballTexture!");
            logerr(SDL_GetError());
        }

        this->ballRenderer = *ballRenderer;

        if(this->ballTexture == NULL)
        {
            logerr("Failed to create ballRenderer");
            logerr(SDL_GetError());
        }

        SDL_FreeSurface(ballSurface);

        if(this->ballTexture != NULL)
            log("Ball created perfectly! :)");
    }
}

Ball::~Ball()
{
    SDL_DestroyTexture(this->ballTexture);
    SDL_DestroyRenderer(this->ballRenderer);
    delete this->ballRect;
}

/**
 * @brief Ball::show This function just "blit"(SDL 1.2) the texture on the
 * renderer.
 */
void Ball::show()
{
    SDL_RenderCopy(this->ballRenderer, this->ballTexture, NULL, this->ballRect);
}

void Ball::move(SDL_Rect* player1, SDL_Rect* player2, Pong* pongObject,
                AudioWrapper* audio)
{
    this->ballRect->x += this->getXVelocity();
    this->ballRect->y += this->getYVelocity();

    //Detecting the collision on the Y axis.
    if(this->ballRect->y <= 0)
        this->yVelocity = -yVelocity;
    if(this->ballRect->y+ballRect->h > pongObject->getHeight())
        this->yVelocity = -yVelocity;
    //Detecting the collision with the paddles.
    if(collision(ballRect, player1)) {
        /* Still need to fix the collision detection, it looks like the
         * collision with the player 1 doesn't work at  21.5 of  speed.
         * The bug is not only in the player1, it does so in the player 2
         * as well.
         */
        if(ballRect->x+abs(this->getXVelocity()) < player1->x + player1->w)
            this->yVelocity = -yVelocity;
        else
            this->xVelocity = -xVelocity;
        audio->playEffect();

        log(pongObject->getHits());
        pongObject->addHit();
    }
    if(collision(ballRect, player2)) {
        if((ballRect->x + ballRect->w)-xVelocity > player2->x)
            this->yVelocity = -yVelocity;
        else
            this->xVelocity = -xVelocity;
        audio->playEffect();

        log(pongObject->getHits());
        pongObject->addHit();
    }

    //The fun begins when the speed gets higher :3
    if(pongObject->getHits() == 1) {
        std::cout << "Actual speed: " << getXVelocity() << std::endl;
        if(getXVelocity() < 0.0)
            setXVelocity(getXVelocity() + (-0.5));
        else
            setXVelocity(getXVelocity() + 0.5);

        pongObject->resetHitCount();
        std::cout << "New speed is: x(" << this->getXVelocity() << ") y("
                  << this->getYVelocity() << ")" << std::endl;
    }
}

/**
 * @brief Ball::collision A function to test the collision between two SDL_Rects.
 * @param rect1 The first rect that we wanna to test the collision.
 * @param rect2 The second rect that we wanna to test the collision.
 * @return If a collision occurs or not.
 */
bool Ball::collision(SDL_Rect* rect1, SDL_Rect* rect2)
{
    if(rect1->y >= rect2->y + rect2->h)
        return false;
    if(rect1->x >= rect2->x + rect2->w)
        return false;
    if(rect1->y + rect1->h <= rect2->y)
        return false;
    if(rect1->x + rect1->w <= rect2->x)
        return false;
    return true;
}

/**
  * @brief Ball::getBallRect() Function to return the SDL_Rect* of the ball.
  * @return the
  */
SDL_Rect* Ball::getBallRect()
{
    return this->ballRect;
}

double Ball::getXVelocity()
{
    return this->xVelocity;
}

double Ball::getYVelocity()
{
    return this->yVelocity;
}

/**
 * @brief Ball::setXVelocity Function to set the velocity on the X axis of the
 * ball.
 * @param xVelocity The velocity on X axis.
 */
void Ball::setXVelocity(double xVelocity)
{
    this->xVelocity = xVelocity;
}

/**
 * @brief Ball::setYVelocity Function to set the velocity on the Y axis of the
 * ball.
 * @param yVelocity The velocity on Y axis.
 */
void Ball::setYVelocity(double yVelocity)
{
    this->yVelocity = yVelocity;
}
<commit_msg>Updated ball.cpp<commit_after>#include "ball.hpp"
#include "utils.hpp"
#include "pong.hpp"
#include "debug.hpp"
#include "sdl_audio.h"

#include <iostream>
#include <cmath>

/**
 * @brief Ball::Ball The Ball implementation of the class Ball.
 * @param ballSurface The surface that carries the image of the ball.
 * @param ballRenderer The renderer which will be used to render the ball
 * texture on the screen.
 * @param xCor The actual position in X axis of the ball.
 * @param yCor The actual position in Y axis of the ball.
 * @param width The width size of the ball.
 * @param height The height size of the ball.
 */
Ball::Ball(SDL_Surface* ballSurface, SDL_Renderer** ballRenderer, float xCor,
           float yCor, int width, int height)
{
    if(ballSurface == NULL || ballRenderer == NULL)
        logerr("The ball surface or the ball renderer passed is null.");
    else
    {
        //Arguments initialization
        this->ballRect = new SDL_Rect();

        this->ballSurface   = ballSurface;

        setXVelocity(2.0);
        setYVelocity(0.0);

        this->ballRect->x   = xCor;
        this->ballRect->y   = yCor;
        this->ballRect->w   = width;
        this->ballRect->h   = height;

        this->ballTexture = SDL_CreateTextureFromSurface(*ballRenderer,
                                                         ballSurface);

        if(this->ballTexture == NULL)
        {
            logerr("Failed to create ballTexture!");
            logerr(SDL_GetError());
        }

        this->ballRenderer = *ballRenderer;

        if(this->ballTexture == NULL)
        {
            logerr("Failed to create ballRenderer");
            logerr(SDL_GetError());
        }

        SDL_FreeSurface(ballSurface);

        if(this->ballTexture != NULL)
            log("Ball created perfectly! :)");
    }
}

Ball::~Ball()
{
    SDL_DestroyTexture(this->ballTexture);
    SDL_DestroyRenderer(this->ballRenderer);
    delete this->ballRect;
}

/**
 * @brief Ball::show This function just "blit"(SDL 1.2) the texture on the
 * renderer.
 */
void Ball::show()
{
    SDL_RenderCopy(this->ballRenderer, this->ballTexture, NULL, this->ballRect);
}

void Ball::move(SDL_Rect* player1, SDL_Rect* player2, Pong* pongObject,
                AudioWrapper* audio)
{
    this->ballRect->x += this->getXVelocity();
    this->ballRect->y += this->getYVelocity();

    //Detecting the collision on the Y axis.
    if(this->ballRect->y <= 0)
        this->yVelocity = -yVelocity;
    if(this->ballRect->y+ballRect->h > pongObject->getHeight())
        this->yVelocity = -yVelocity;
    //Detecting the collision with the paddles.
    if(collision(ballRect, player1)) {
        /* Still need to fix the collision detection, it looks like the
         * collision with the player 1 doesn't work at  21.5 of  speed.
         * The bug is not only in the player1, it does so in the player 2
         * as well.
         */
        if(ballRect->x+abs(this->getXVelocity()) < player1->x + player1->w)
            this->yVelocity = -yVelocity;
        else
            this->xVelocity = -xVelocity;
        audio->playEffect();

        log(pongObject->getHits());
        pongObject->addHit();
    }
    if(collision(ballRect, player2)) {
        if((ballRect->x + ballRect->w)-xVelocity > player2->x)
            this->yVelocity = -yVelocity;
        else
            this->xVelocity = -xVelocity;
        audio->playEffect();

        log(pongObject->getHits());
        pongObject->addHit();
    }

    //The fun begins when the speed gets higher :3
    if(pongObject->getHits() == 4) {
        std::cout << "Actual speed: " << getXVelocity() << std::endl;
        if(getXVelocity() < 0.0)
            setXVelocity(getXVelocity() + (-0.5));
        else
            setXVelocity(getXVelocity() + 0.5);

        pongObject->resetHitCount();
        std::cout << "New speed is: x(" << this->getXVelocity() << ") y("
                  << this->getYVelocity() << ")" << std::endl;
    }
}

/**
 * @brief Ball::collision A function to test the collision between two SDL_Rects.
 * @param rect1 The first rect that we wanna to test the collision.
 * @param rect2 The second rect that we wanna to test the collision.
 * @return If a collision occurs or not.
 */
bool Ball::collision(SDL_Rect* rect1, SDL_Rect* rect2)
{
    if(rect1->y >= rect2->y + rect2->h)
        return false;
    if(rect1->x >= rect2->x + rect2->w)
        return false;
    if(rect1->y + rect1->h <= rect2->y)
        return false;
    if(rect1->x + rect1->w <= rect2->x)
        return false;
    return true;
}

/**
  * @brief Ball::getBallRect() Function to return the SDL_Rect* of the ball.
  * @return the
  */
SDL_Rect* Ball::getBallRect()
{
    return this->ballRect;
}

double Ball::getXVelocity()
{
    return this->xVelocity;
}

double Ball::getYVelocity()
{
    return this->yVelocity;
}

/**
 * @brief Ball::setXVelocity Function to set the velocity on the X axis of the
 * ball.
 * @param xVelocity The velocity on X axis.
 */
void Ball::setXVelocity(double xVelocity)
{
    this->xVelocity = xVelocity;
}

/**
 * @brief Ball::setYVelocity Function to set the velocity on the Y axis of the
 * ball.
 * @param yVelocity The velocity on Y axis.
 */
void Ball::setYVelocity(double yVelocity)
{
    this->yVelocity = yVelocity;
}
<|endoftext|>


<commit_before>#include "ardrone/ardrone.h"

// --------------------------------------------------------------------------
// main(Number of arguments, Argument values)
// Description  : This is the entry point of the program.
// Return value : SUCCESS:0  ERROR:-1
// --------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        std::cout << "Failed to initialize." << std::endl;
        return -1;
    }

    // Thresholds
    int minH = 0, maxH = 255;
    int minS = 0, maxS = 255;
    int minV = 0, maxV = 255;

    // XML save data
    std::string filename("thresholds.xml");
    cv::FileStorage fs(filename, cv::FileStorage::READ);

    // If there is a save file then read it
    if (fs.isOpened()) {
        maxH = fs["H_MAX"];
        minH = fs["H_MIN"];
        maxS = fs["S_MAX"];
        minS = fs["S_MIN"];
        maxV = fs["V_MAX"];
        minV = fs["V_MIN"];
        fs.release();
    }

    // Create a window
    cv::namedWindow("binalized");
    cv::createTrackbar("H max", "binalized", &maxH, 255);
    cv::createTrackbar("H min", "binalized", &minH, 255);
    cv::createTrackbar("S max", "binalized", &maxS, 255);
    cv::createTrackbar("S min", "binalized", &minS, 255);
    cv::createTrackbar("V max", "binalized", &maxV, 255);
    cv::createTrackbar("V min", "binalized", &minV, 255);
    cv::resizeWindow("binalized", 0, 0);

    // Kalman filter
    cv::KalmanFilter kalman(4, 2, 0);

    // Sampling time [s]
    const double dt = 1.0;

    // Transition matrix (x, y, vx, vy)
    cv::Mat1f A(4, 4);
    A << 1.0, 0.0,  dt, 0.0,
         0.0, 1.0, 0.0,  dt,
         0.0, 0.0, 1.0, 0.0,
         0.0, 0.0, 0.0, 1.0;
    kalman.transitionMatrix = A;

    // Measurement matrix (x, y)
    cv::Mat1f H(2, 4);
    H << 1, 0, 0, 0,
         0, 1, 0, 0;
    kalman.measurementMatrix = H;

    // Process noise covairance (x, y, vx, vy)
    cv::Mat1f Q(4, 4);
    Q << 1e-5,  0.0,  0.0,  0.0,
          0.0, 1e-5,  0.0,  0.0,
          0.0,  0.0, 1e-5,  0.0,
          0.0,  0.0,  0.0, 1e-5;
    kalman.processNoiseCov = Q;

    // Measurement noise covariance (x, y)
    cv::Mat1f R(2, 2);
    R << 1e-1,  0.0,
          0.0, 1e-1;
    kalman.measurementNoiseCov = R;

	char textBuffer[80];
	float speed = 0.0;

    // Main loop
    while (1) {
        // Key input
        int key = cv::waitKey(33);
        if (key == 0x1b) break;

        // Get an image
        cv::Mat image = ardrone.getImage();

        // HSV image
        cv::Mat hsv;
        cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL);

        // Binalize
        cv::Mat binalized;
        cv::Scalar lower(minH, minS, minV);
        cv::Scalar upper(maxH, maxS, maxV);
        cv::inRange(hsv, lower, upper, binalized);

        // Show result
        cv::imshow("binalized", binalized);

        // De-noising
        cv::Mat kernel = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
        cv::morphologyEx(binalized, binalized, cv::MORPH_CLOSE, kernel);
        //cv::imshow("morphologyEx", binalized);

        // Detect contours
        std::vector<std::vector<cv::Point>> contours;
        cv::findContours(binalized.clone(), contours, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

        // Find largest contour
        int contour_index = -1;
        double max_area = 0.0;
        for (size_t i = 0; i < contours.size(); i++) {
            double area = fabs(cv::contourArea(contours[i]));
            if (area > max_area) {
                contour_index = i;
                max_area = area;
            }
        }

        // Object detected
        if (contour_index >= 0) {
            // Moments
            cv::Moments moments = cv::moments(contours[contour_index], true);
            double marker_y = (int)(moments.m01 / moments.m00);
            double marker_x = (int)(moments.m10 / moments.m00);

            // Measurements
            cv::Mat measurement = (cv::Mat1f(2, 1) << marker_x, marker_y);

            // Correction
            cv::Mat estimated = kalman.correct(measurement);

            // Show result
            cv::Rect rect = cv::boundingRect(contours[contour_index]);
            cv::rectangle(image, rect, cv::Scalar(0, 255, 0));
        }

        // Prediction
        cv::Mat1f prediction = kalman.predict();
        int radius = 1e+3 * kalman.errorCovPre.at<float>(0, 0);

        // Show predicted position
        cv::circle(image, cv::Point(prediction(0, 0), prediction(0, 1)), radius, cv::Scalar(0, 255, 0), 2);

		// Calculate object heading fraction
		float heading = -((image.cols/2)-prediction(0, 0))/(image.cols/2);
		sprintf(textBuffer, "heading = %+3.2f", heading);
		putText(image, textBuffer, cvPoint(30,30), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 255, 0), 1, CV_AA);

		// Control drone
		double vx = 0.0, vy = 0.0, vz = 0.0, vr = 0.0;
        if (key == 0x260000) vx =  1.0;
        if (key == 0x280000) vx = -1.0;
        if (key == 0x250000) vr =  1.0;
        if (key == 0x270000) vr = -1.0;
        if (key == 'q')      vz =  1.0;
        if (key == 'a')      vz = -1.0;
		if ((key >= '0') && (key <= '9'))
		{
			speed = (key-'0')*0.1;
			printf("speed = %3.2f\n", speed);
		}
		if (key == -1)
		{//No key hit - chase the object
			vx=speed;
			vr = -heading*2;
		}
        ardrone.move3D(vx, vy, vz, vr);

		// Take off / Landing
        if (key == ' ') {
            if (ardrone.onGround())
			{
				ardrone.takeoff();
			}
            else
			{
				ardrone.landing();
			}
        }

        // Display the image
        cv::imshow("camera", image);
    }

    // Save thresholds
    fs.open(filename, cv::FileStorage::WRITE);
    if (fs.isOpened()) {
        cv::write(fs, "H_MAX", maxH);
        cv::write(fs, "H_MIN", minH);
        cv::write(fs, "S_MAX", maxS);
        cv::write(fs, "S_MIN", minS);
        cv::write(fs, "V_MAX", maxV);
        cv::write(fs, "V_MIN", minV);
        fs.release();
    }

    // See you
    ardrone.close();

    return 0;
}<commit_msg>Display the speed setting.<commit_after>#include "ardrone/ardrone.h"

// --------------------------------------------------------------------------
// main(Number of arguments, Argument values)
// Description  : This is the entry point of the program.
// Return value : SUCCESS:0  ERROR:-1
// --------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        std::cout << "Failed to initialize." << std::endl;
        return -1;
    }

    // Thresholds
    int minH = 0, maxH = 255;
    int minS = 0, maxS = 255;
    int minV = 0, maxV = 255;

    // XML save data
    std::string filename("thresholds.xml");
    cv::FileStorage fs(filename, cv::FileStorage::READ);

    // If there is a save file then read it
    if (fs.isOpened()) {
        maxH = fs["H_MAX"];
        minH = fs["H_MIN"];
        maxS = fs["S_MAX"];
        minS = fs["S_MIN"];
        maxV = fs["V_MAX"];
        minV = fs["V_MIN"];
        fs.release();
    }

    // Create a window
    cv::namedWindow("binalized");
    cv::createTrackbar("H max", "binalized", &maxH, 255);
    cv::createTrackbar("H min", "binalized", &minH, 255);
    cv::createTrackbar("S max", "binalized", &maxS, 255);
    cv::createTrackbar("S min", "binalized", &minS, 255);
    cv::createTrackbar("V max", "binalized", &maxV, 255);
    cv::createTrackbar("V min", "binalized", &minV, 255);
    cv::resizeWindow("binalized", 0, 0);

    // Kalman filter
    cv::KalmanFilter kalman(4, 2, 0);

    // Sampling time [s]
    const double dt = 1.0;

    // Transition matrix (x, y, vx, vy)
    cv::Mat1f A(4, 4);
    A << 1.0, 0.0,  dt, 0.0,
         0.0, 1.0, 0.0,  dt,
         0.0, 0.0, 1.0, 0.0,
         0.0, 0.0, 0.0, 1.0;
    kalman.transitionMatrix = A;

    // Measurement matrix (x, y)
    cv::Mat1f H(2, 4);
    H << 1, 0, 0, 0,
         0, 1, 0, 0;
    kalman.measurementMatrix = H;

    // Process noise covairance (x, y, vx, vy)
    cv::Mat1f Q(4, 4);
    Q << 1e-5,  0.0,  0.0,  0.0,
          0.0, 1e-5,  0.0,  0.0,
          0.0,  0.0, 1e-5,  0.0,
          0.0,  0.0,  0.0, 1e-5;
    kalman.processNoiseCov = Q;

    // Measurement noise covariance (x, y)
    cv::Mat1f R(2, 2);
    R << 1e-1,  0.0,
          0.0, 1e-1;
    kalman.measurementNoiseCov = R;

	char textBuffer[80];
	float speed = 0.0;

    // Main loop
    while (1) {
        // Key input
        int key = cv::waitKey(33);
        if (key == 0x1b) break;

        // Get an image
        cv::Mat image = ardrone.getImage();

        // HSV image
        cv::Mat hsv;
        cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL);

        // Binalize
        cv::Mat binalized;
        cv::Scalar lower(minH, minS, minV);
        cv::Scalar upper(maxH, maxS, maxV);
        cv::inRange(hsv, lower, upper, binalized);

        // Show result
        cv::imshow("binalized", binalized);

        // De-noising
        cv::Mat kernel = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
        cv::morphologyEx(binalized, binalized, cv::MORPH_CLOSE, kernel);
        //cv::imshow("morphologyEx", binalized);

        // Detect contours
        std::vector<std::vector<cv::Point>> contours;
        cv::findContours(binalized.clone(), contours, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

        // Find largest contour
        int contour_index = -1;
        double max_area = 0.0;
        for (size_t i = 0; i < contours.size(); i++) {
            double area = fabs(cv::contourArea(contours[i]));
            if (area > max_area) {
                contour_index = i;
                max_area = area;
            }
        }

        // Object detected
        if (contour_index >= 0) {
            // Moments
            cv::Moments moments = cv::moments(contours[contour_index], true);
            double marker_y = (int)(moments.m01 / moments.m00);
            double marker_x = (int)(moments.m10 / moments.m00);

            // Measurements
            cv::Mat measurement = (cv::Mat1f(2, 1) << marker_x, marker_y);

            // Correction
            cv::Mat estimated = kalman.correct(measurement);

            // Show result
            cv::Rect rect = cv::boundingRect(contours[contour_index]);
            cv::rectangle(image, rect, cv::Scalar(0, 255, 0));
        }

        // Prediction
        cv::Mat1f prediction = kalman.predict();
        int radius = 1e+3 * kalman.errorCovPre.at<float>(0, 0);

        // Show predicted position
        cv::circle(image, cv::Point(prediction(0, 0), prediction(0, 1)), radius, cv::Scalar(0, 255, 0), 2);

		// Calculate object heading fraction
		float heading = -((image.cols/2)-prediction(0, 0))/(image.cols/2);
		sprintf(textBuffer, "heading = %+3.2f", heading);
		putText(image, textBuffer, cvPoint(30,30), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 255, 0), 1, CV_AA);

		// Control drone
		double vx = 0.0, vy = 0.0, vz = 0.0, vr = 0.0;
        if (key == 0x260000) vx =  1.0;
        if (key == 0x280000) vx = -1.0;
        if (key == 0x250000) vr =  1.0;
        if (key == 0x270000) vr = -1.0;
        if (key == 'q')      vz =  1.0;
        if (key == 'a')      vz = -1.0;
		if ((key >= '0') && (key <= '9'))
		{
			speed = (key-'0')*0.1;
			//printf("speed = %3.2f\n", speed);
		}
		sprintf(textBuffer, "speed = %3.2f", speed);
		putText(image, textBuffer, cvPoint(30,60), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 255, 0), 1, CV_AA);

		if (key == -1)
		{//No key hit - chase the object
			vx=speed;
			vr = -heading*2;
		}
        ardrone.move3D(vx, vy, vz, vr);

		// Take off / Landing
        if (key == ' ') {
            if (ardrone.onGround())
			{
				ardrone.takeoff();
			}
            else
			{
				ardrone.landing();
			}
        }

        // Display the image
        cv::imshow("camera", image);
    }

    // Save thresholds
    fs.open(filename, cv::FileStorage::WRITE);
    if (fs.isOpened()) {
        cv::write(fs, "H_MAX", maxH);
        cv::write(fs, "H_MIN", minH);
        cv::write(fs, "S_MAX", maxS);
        cv::write(fs, "S_MIN", minS);
        cv::write(fs, "V_MAX", maxV);
        cv::write(fs, "V_MIN", minV);
        fs.release();
    }

    // See you
    ardrone.close();

    return 0;
}<|endoftext|>


<commit_before>/**
 * \file
 *
 * \brief Tests for KDB
 *
 * \copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <keysetio.hpp>

#include <gtest/gtest-elektra.h>

class Nested : public ::testing::Test
{
protected:
	static const std::string testRoot;
	static const std::string testBelow;
	static const std::string configFileRoot;
	static const std::string configFileBelow;

	testing::Namespaces namespaces;
	testing::MountpointPtr mpRoot;
	testing::MountpointPtr mpBelow;

	Nested() : namespaces()
	{}

	virtual void SetUp()
	{
		mpRoot.reset(new testing::Mountpoint(testRoot, configFileRoot));
		mpBelow.reset(new testing::Mountpoint(testBelow, configFileBelow));
	}

	virtual void TearDown()
	{
		mpBelow.reset();
		mpRoot.reset();
	}
};

const std::string Nested::testRoot = "/tests/kdb/";
const std::string Nested::testBelow = "/tests/kdb/below/";
const std::string Nested::configFileRoot = "kdbFileRoot.dump";
const std::string Nested::configFileBelow = "kdbFileBelow.dump";

TEST_F(Nested, GetSetNothing)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;
	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 0) << "got keys from freshly mounted backends" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 0) << "should be nothing to set";
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
}

TEST_F(Nested, GetSetRoot)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	std::string name = "system" + testRoot + "key";
	Key k(name, KEY_END);
	EXPECT_EQ(k.getName(), name);
	ks.append(k);

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 1) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 1) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), 0) << "root file not created";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 1) << "did not get key stored before" << ks;
}

TEST_F(Nested, GetSetBelow)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	std::string name = "system" + testRoot + "below/key";
	Key k(name, KEY_END);
	EXPECT_EQ(k.getName(), name);
	ks.append(k);

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 1) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 1) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "root file created?";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), 0) << "below file not created";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 1) << "did not get key stored before" << ks;
}

TEST_F(Nested, RemoveFiles)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append(Key("system" + testRoot + "key", KEY_END));
	ks.append(Key("system" + testRoot + "below/key", KEY_END));

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 2) << "did not keep key at get" << ks;
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 2) << "did not keep key at set" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), 0) << "root file not created";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), 0) << "below file not created";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 2) << "did not get key stored before" << ks;
	ks2.clear();
	ASSERT_EQ(kdb.set(ks2, testRoot), 1); // remove files
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file, file not removed";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file, file not removed";
}

TEST_F(Nested, ErrorBelow)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append(Key("system"+testRoot+"a", KEY_END));
	ks.append(Key("system"+testRoot+"k", KEY_END));
	ks.append(Key("system"+testRoot+"7", KEY_END));
	ks.append(Key("system"+testBelow+"a", KEY_END));
	ks.append(Key("system"+testBelow+"k", KEY_META, "trigger/error", "10", KEY_END));
	ks.append(Key("system"+testBelow+"z", KEY_END));

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 6) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	EXPECT_THROW(kdb.set(ks, testRoot), kdb::KDBException) << "could not trigger error";
	ASSERT_EQ(ks.size(), 6) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
}

<commit_msg>combine in one test case: GetSetRemoveBoth<commit_after>/**
 * \file
 *
 * \brief Tests for KDB
 *
 * \copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <keysetio.hpp>

#include <gtest/gtest-elektra.h>

class Nested : public ::testing::Test
{
protected:
	static const std::string testRoot;
	static const std::string testBelow;
	static const std::string configFileRoot;
	static const std::string configFileBelow;

	testing::Namespaces namespaces;
	testing::MountpointPtr mpRoot;
	testing::MountpointPtr mpBelow;

	Nested() : namespaces()
	{}

	virtual void SetUp()
	{
		mpRoot.reset(new testing::Mountpoint(testRoot, configFileRoot));
		mpBelow.reset(new testing::Mountpoint(testBelow, configFileBelow));
	}

	virtual void TearDown()
	{
		mpBelow.reset();
		mpRoot.reset();
	}
};

const std::string Nested::testRoot = "/tests/kdb/";
const std::string Nested::testBelow = "/tests/kdb/below/";
const std::string Nested::configFileRoot = "kdbFileRoot.dump";
const std::string Nested::configFileBelow = "kdbFileBelow.dump";

TEST_F(Nested, GetSetNothing)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;
	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 0) << "got keys from freshly mounted backends" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 0) << "should be nothing to set";
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
}

TEST_F(Nested, GetSetRoot)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	std::string name = "system" + testRoot + "key";
	Key k(name, KEY_END);
	EXPECT_EQ(k.getName(), name);
	ks.append(k);

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 1) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 1) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), 0) << "root file not created";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 1) << "did not get key stored before" << ks;
}

kdb::KeySet getAll()
{
	using namespace ckdb;
	return
#include <data_allns.c>
}

TEST_F(Nested, GetSetBelow)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	std::string name = "system" + testRoot + "below/key";
	Key k(name, KEY_END);
	EXPECT_EQ(k.getName(), name);
	ks.append(k);
	ks.append(getAll());

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 715) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 715) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "root file created?";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), 0) << "below file not created";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 1) << "did not get key stored before" << ks;
}

TEST_F(Nested, RemoveFiles)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append(Key("system" + testRoot + "key", KEY_END));
	ks.append(Key("system" + testRoot + "below/key", KEY_END));

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 2) << "did not keep key at get" << ks;
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 2) << "did not keep key at set" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), 0) << "root file not created";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), 0) << "below file not created";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 2) << "did not get key stored before" << ks;
	ks2.clear();
	ASSERT_EQ(kdb.set(ks2, testRoot), 1); // remove files
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file, file not removed";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file, file not removed";
}

TEST_F(Nested, GetSetRemoveBoth)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append(Key("system" + testRoot + "key", KEY_END));
	ks.append(Key("system" + testRoot + "key/subkey", KEY_END));
	ks.append(Key("system" + testRoot + "below/key", KEY_END));
	ks.append(Key("system" + testRoot + "below/key/subkey", KEY_END));
	ks.append(getAll());

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 718) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(kdb.set(ks, testRoot), 1);
	ASSERT_EQ(ks.size(), 718) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), 0) << "root file not created";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), 0) << "below file not created";

	Key parent(testRoot, KEY_END);
	kdb.close(parent);
	kdb.open(parent);
	KeySet ks2;
	ASSERT_EQ(kdb.get(ks2, testRoot), 1);
	ASSERT_EQ(ks2.size(), 4) << "did not get key stored before" << ks;

	KeySet ks3;
	ks3.append(getAll());
	ASSERT_EQ(kdb.set(ks3, testRoot), 1); // remove all keys
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file (not removed)";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file (not removed)";
}

TEST_F(Nested, ErrorBelow)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append(Key("system"+testRoot+"a", KEY_END));
	ks.append(Key("system"+testRoot+"k", KEY_END));
	ks.append(Key("system"+testRoot+"7", KEY_END));
	ks.append(Key("system"+testBelow+"a", KEY_END));
	ks.append(Key("system"+testBelow+"k", KEY_META, "trigger/error", "10", KEY_END));
	ks.append(Key("system"+testBelow+"z", KEY_END));

	ASSERT_EQ(kdb.get(ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ(ks.size(), 6) << "did not keep key at get" << ks;
	struct stat buf;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	EXPECT_THROW(kdb.set(ks, testRoot), kdb::KDBException) << "could not trigger error";
	ASSERT_EQ(ks.size(), 6) << "did not keep key at set" << ks;
	ASSERT_EQ(stat(mpRoot->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
	ASSERT_EQ(stat(mpBelow->systemConfigFile.c_str(), &buf), -1) << "found wrong file";
}

<|endoftext|>