<commit_before>/*
    Copyright (c) 2003-2010 KenamicK Entertainment

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#include "Main.h"

//////////////////////////////////////////////////////////////////////
// Name: CSounds()
// Desc:
//////////////////////////////////////////////////////////////////////
CSounds::CSounds()
: _sdl( NULL ),
  current_track( 0 ),
  music_stopped( false )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	memset( sounds, 0, sizeof(int) * NUM_SOUNDS );
	memset( music, 0, sizeof(int) * NUM_MUSIX );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Initialize()
// Desc: Load all ingame sounds
//////////////////////////////////////////////////////////////////////
bool CSounds::Initialize( CSdl *pSdl )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	this->_sdl = pSdl;
	ASSERT( _sdl != NULL );

#define LOAD_SOUND( container, name, buffered ) if ( (sounds[container] = _sdl->LoadSound( name, buffered )) == -1 ) { \
	LOG( "Failed to load " << name << " ! "); \
	return false; }

#define LOAD_MUSIC( container, name ) if ( (music[container] = _sdl->LoadSound( name, false, true )) == -1 ) { \
	LOG( "Failed to load music " << name << " ! "); \
	return false; }

	LOAD_SOUND( SND_CRASHLIGHT1, "sound/crash3.wav", true );
	LOAD_SOUND( SND_CRASHLIGHT2, "sound/crash2.wav", true );
	LOAD_SOUND( SND_CRASHLIGHT3, "sound/crash1.wav", true );
	LOAD_SOUND( SND_EXPLOSION1, "sound/exp.wav", true );
	LOAD_SOUND( SND_SPLAT1, "sound/splat.wav", true );
	LOAD_SOUND( SND_TIRES1, "sound/tires1.wav", true );
	LOAD_SOUND( SND_TIRES2, "sound/tires2.wav", true );
	LOAD_SOUND( SND_WARNING, "sound/warn.wav", true );
	LOAD_SOUND( SND_MENU_NEXTCAR, "sound/snapshot.wav", true );
	LOAD_SOUND( SND_MENU_HONK1, "sound/honk1.wav", true );
//	LOAD_SOUND( SND_MENU_OVERBUTTON, "sound/mmh3.wav", false );
	LOAD_SOUND( SND_MENU_CLICK, "sound/mmh.wav", true );

	LOAD_MUSIC( MUS_MENU, "sound/seek.it" );
	LOAD_MUSIC( MUS_INGAME1, "sound/inertia.it" );
	LOAD_MUSIC( MUS_INGAME2, "sound/desert.it" );
	LOAD_MUSIC( MUS_INGAME3, "sound/vixens.it" );

	music_stopped = false;

#undef LOAD_SOUND
#undef LOAD_MUSIC
#endif
	return true;
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play a sound
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_SOUNDS snd_to_play )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( _sdl )
		_sdl->PlaySound( sounds[snd_to_play] );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play a sound with specified panning (0-255)
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_SOUNDS snd_to_play, int pos )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( _sdl )
		_sdl->PlaySound( sounds[snd_to_play], pos );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play music
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_MUSIC music_to_play, bool looped )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)

	if ( _sdl->GetMusicVolume() <= 0 )
		return;

	current_track = (int)music_to_play;
	_sdl->PlayMusic( music[current_track], looped );

	music_stopped = false;
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: StopMusic()
// Desc: Stop currently playing music
//////////////////////////////////////////////////////////////////////
void CSounds::StopMusic()
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if (music_stopped)
		return;

	if ( music[current_track] )
	{
		_sdl->StopMusic();
	}

	music_stopped = true;
#endif
}

//void CSounds::FadeMusic( int milliseconds )
//{
//#ifdef WITH_FMOD
//	StopMusic();
//#endif
//}

//////////////////////////////////////////////////////////////////////
// Name: CheckMusic()
// Desc: Check if (current) music has finished playing
//////////////////////////////////////////////////////////////////////
void CSounds::CheckMusic()
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( !music_stopped )
	{
		if (!_sdl->IsMusicPlaying())
		{
//			StopMusic();
//			DBG("CheckMusic playing ...");

			current_track++;
			if ( current_track >= NUM_MUSIX )
				current_track = MUS_INGAME1;

			Play( (CONST_MUSIC)current_track, false );
		}
	}
#endif
}

////////////////////////////////////////////////////////////////////////
//// Name: setMusicVolume()
//// Desc:
////////////////////////////////////////////////////////////////////////
//void CSounds::setMusicVolume( int volume )
//{
//#ifdef WITH_FMOD
//	for ( int i = 0; i < NUM_MUSIX; i++ )
//	{
//		if ( music[i] )
//			FMUSIC_SetMasterVolume( music[i], volume );
//	}
//#endif
//}
<commit_msg>Minor syntax changes in CSounds<commit_after>/*
    Copyright (c) 2003-2010 KenamicK Entertainment

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#include "Main.h"

//////////////////////////////////////////////////////////////////////
// Name: CSounds()
// Desc:
//////////////////////////////////////////////////////////////////////
CSounds::CSounds()
: _sdl( NULL ),
  current_track( 0 ),
  music_stopped( false )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	memset( sounds, 0, sizeof(int) * NUM_SOUNDS );
	memset( music, 0, sizeof(int) * NUM_MUSIX );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Initialize()
// Desc: Load all ingame sounds
//////////////////////////////////////////////////////////////////////
bool CSounds::Initialize( CSdl *pSdl )
{
	ASSERT( _sdl != NULL );
	this->_sdl = pSdl;

#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)

#define LOAD_SOUND( container, name, buffered ) if ( (sounds[container] = _sdl->LoadSound( name, buffered )) == -1 ) { \
	LOG( "Failed to load " << name << " ! "); \
	return false; }

#define LOAD_MUSIC( container, name ) if ( (music[container] = _sdl->LoadSound( name, false, true )) == -1 ) { \
	LOG( "Failed to load music " << name << " ! "); \
	return false; }

	LOAD_SOUND( SND_CRASHLIGHT1, "sound/crash3.wav", true );
	LOAD_SOUND( SND_CRASHLIGHT2, "sound/crash2.wav", true );
	LOAD_SOUND( SND_CRASHLIGHT3, "sound/crash1.wav", true );
	LOAD_SOUND( SND_EXPLOSION1, "sound/exp.wav", true );
	LOAD_SOUND( SND_SPLAT1, "sound/splat.wav", true );
	LOAD_SOUND( SND_TIRES1, "sound/tires1.wav", true );
	LOAD_SOUND( SND_TIRES2, "sound/tires2.wav", true );
	LOAD_SOUND( SND_WARNING, "sound/warn.wav", true );
	LOAD_SOUND( SND_MENU_NEXTCAR, "sound/snapshot.wav", true );
	LOAD_SOUND( SND_MENU_HONK1, "sound/honk1.wav", true );
//	LOAD_SOUND( SND_MENU_OVERBUTTON, "sound/mmh3.wav", false );
	LOAD_SOUND( SND_MENU_CLICK, "sound/mmh.wav", true );

	LOAD_MUSIC( MUS_MENU, "sound/seek.it" );
	LOAD_MUSIC( MUS_INGAME1, "sound/inertia.it" );
	LOAD_MUSIC( MUS_INGAME2, "sound/desert.it" );
	LOAD_MUSIC( MUS_INGAME3, "sound/vixens.it" );

	music_stopped = false;

#undef LOAD_SOUND
#undef LOAD_MUSIC
#endif
	return true;
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play a sound
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_SOUNDS snd_to_play )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( _sdl )
		_sdl->PlaySound( sounds[snd_to_play] );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play a sound with specified panning (0-255)
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_SOUNDS snd_to_play, int pos )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( _sdl )
		_sdl->PlaySound( sounds[snd_to_play], pos );
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: Play()
// Desc: Play music
//////////////////////////////////////////////////////////////////////
void CSounds::Play( CONST_MUSIC music_to_play, bool looped )
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( _sdl->GetMusicVolume() <= 0 )
		return;

	current_track = (int)music_to_play;
	_sdl->PlayMusic( music[current_track], looped );

	music_stopped = false;
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: StopMusic()
// Desc: Stop currently playing music
//////////////////////////////////////////////////////////////////////
void CSounds::StopMusic()
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if (music_stopped)
		return;

	if ( music[current_track] )
	{
		_sdl->StopMusic();
	}

	music_stopped = true;
#endif
}

//////////////////////////////////////////////////////////////////////
// Name: CheckMusic()
// Desc: Check if (current) music has finished playing
//////////////////////////////////////////////////////////////////////
void CSounds::CheckMusic()
{
#if defined(WITH_FMOD) || defined(WITH_SDLMIXER)
	if ( !music_stopped )
	{
		if (!_sdl->IsMusicPlaying())
		{
//			StopMusic();
//			DBG("CheckMusic playing ...");

			current_track++;
			if ( current_track >= NUM_MUSIX )
				current_track = MUS_INGAME1;

			Play( (CONST_MUSIC)current_track, false );
		}
	}
#endif
}
<|endoftext|>


<commit_before><commit_msg>Prevent segfault if vertex map isn't set.<commit_after><|endoftext|>


<commit_before>#include "consoleui.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

void ConsoleUI::run()
{
    bool run = true;
    while (run)
    {
       cout << " ================================" << endl;
       cout << " Press 1 to add" << endl;
       cout << " Press 2 to sort" << endl;
       cout << " Press 3 to list" << endl;
       cout << " Press 4 to search"  << endl;
       cout << " Press 5 to remove scientist"     << endl;
       cout << " Press 6 to exit"     << endl;
       cout << " ================================" << endl;

       char input = '0';
       cin >> input;
       cin.clear();
       fflush(stdin);
       int choice = input - '0';

            switch (choice)
            {
            case 1:
                addData();
                break;
            case 2:
                sortData();
                break;
            case 3:
                showData();
                break;
            case 4:
                searchData();
                break;
            case 5:
                removeData();
            case 6:
                run = false;
                break;
            default:
                cout << "Error! Invalid Input" << endl;
            }

    }

}

void ConsoleUI::addData()
{

    string name;
    char gender;
    int birthYear;
    int deathYear;

    cout << "Enter Name: ";
    cin >> ws;
    getline(cin,name);
    cout << "Enter gender (M/F): ";
    cin >> gender;
    cin.clear();
    fflush(stdin);
    if(genderCheck(gender) == false)
    {
        if(check() == false)
        {
            return;
        }
    }
    cout << "Enter birth year: ";
    cin >> birthYear;
    cout << "Enter death year (0 for living person): ";
    cin >> deathYear;
    if(birthChecks(birthYear, deathYear) == false)
    {
        check();    // Checks if you want to try to input again.
    }
    else
    {
        Persons newPerson(name, gender, birthYear, deathYear);
        serve.add(newPerson);
    }

}
bool ConsoleUI::genderCheck(char gender)
{

   if(gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
   {

       return true;
   }
   else
   {
       cout << "Wrong input for gender!" << endl;
       return false;
   }

}

bool ConsoleUI::check()
{
    char continuel;
    cout << "Do you want to try again? (Y for yes and N for No)" ;
    cin  >> continuel;
    if(continuel == 'Y' || continuel == 'y')
    {
        addData();
    }
    else
    {
       return false;
    }
}

bool ConsoleUI::birthChecks(int birthYear, int deathYear)
{

    if(birthYear < 0 )
    {
        cout << "You can not be born before the year zero." << endl;
        return false;

    }
    if(birthYear > 2016)
    {
        cout << "You can not be born after the year 2016" << endl;
        return false;

    }
    if(deathYear < birthYear)
    {
        cout << "You cannot die before you are born!" << endl;
        return false;

    }
    if(deathYear > 2016 && !'0')
    {

        cout << "You are Still alive.";
        return false;
    }
        return true;
    }

void ConsoleUI::showData()
{
    cout << endl;
    printLine();
    for(size_t i = 0; i < serve.list().size();i++)
    {
        cout << serve.list()[i];
    }
     cout << "_____________________________________________________" << endl;

}

void ConsoleUI::searchData()
{
    bool error = false;
    do
    {
        cout << "How would you like to search the data?" << endl;
        cout << " =====================================" << endl;
        cout << " Press 1 to search by name" << endl;
        cout << " Press 2 to search by birth year" << endl;
        cout << " Press 3 to search for gender" << endl;
        cout << " Press 4 to search by birth year range" << endl;
        cout << " Press 5 to cancel" << endl;
        cout << " ======================================"  << endl;

        char input = '0';
        cin >> input;
        int choice = input - '0';

        switch(choice)
        {
            case 1:
            {
                string n = " ";
                cout << "Enter name: ";
                cin >> ws;
                getline(cin, n);
                vector<int> v_n = serve.searchByName(n);
                if (v_n.size() == 0) {
                    cout << "No results found\n";
                }
                else {
                    printLine();
                    for (unsigned int i = 0; i < v_n.size(); i++)
                    {
                        cout << serve.list()[v_n[i]];
                    }
                }
                error = false;
                break;
            }
            case 2:
            {
                int y = 0;
                cout << "Enter year: ";
                cin >> y;
                vector<int> v_y = serve.searchByYear(y);
                if (v_y.size() == 0) {
                    cout << "No results found\n";
                }
                else {
                    printLine();
                    for (unsigned int i = 0; i < v_y.size(); i++)
                    {
                        cout << serve.list()[v_y[i]];
                    }
                }
                error = false;
                break;
            }
            case 3:
            {
                char gender;
                cout << "Enter gender (M/F): ";
                cin >> gender;
                vector<int> v_g = serve.searchByGender(gender);
                if (v_g.size() == 0)
                {
                    cout << "No results found" << endl;
                }
                else
                {
                    printLine();
                    for (unsigned int i = 0; i < v_g.size(); i++)
                    {
                        cout << serve.list()[v_g[i]];
                    }
                }
                break;
            }
            case 4:
            {
                int f = 0, l = 0;
                cout << "Enter first year in range: ";
                cin >> f;
                cout << "Enter last yar in range: ";
                cin >> l;

                vector<int> v_r = serve.searchByRange(f,l);
                if (v_r.size() == 0)
                {
                    cout << "No results found" << endl;
                }
                else
                {
                    printLine();
                    for (unsigned int i = 0; i < v_r.size(); i++)
                    {
                        cout << serve.list()[v_r[i]];
                    }
                }
                break;
            }

            case 5:
                error = false;
                break;
            default:
            {
                cout << "Error! invalid input" << endl;
                error = true;
            }
        }
    } while (error);
}

void ConsoleUI::sortData()
{
    char input = '0';
    int choice = 0;
    int choice2 = 0;
    bool error = false;

    do
    {

        cout << "How would you like to sort the list?" << endl;
        cout << " ================================" << endl;
        cout << " Press 1 for Name" << endl;
        cout << " Press 2 for Birth Year" << endl;
        cout << " Press 3 for Death Year " << endl;
        cout << " Press 4 for Gender" << endl;
        cout << " Press 5 to cancel" << endl;
        cout << " ================================" << endl;

        cin >> input;
        choice = input - '0';
        choice2 = 0;
        input = '1';

            switch (choice)
                 {
                 case 1:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 2:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 3:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 4:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Sort by Males or Females?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for sorting by Females first" << endl;
                        cout << "Press 2 for sorting by Males first" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 5:
                    error = false;
                    break;
                 default:
                     cout << "Error! Invalid input!" << endl;
                     error = true;
                 }
    }
    while (error);

    if (choice != 5) //if you press cancel, you don't want to see the list, do you?
    {
        showData();
    }
}

void ConsoleUI::printLine()
{
    cout.width(16);
    cout << left << "Name";
    cout <<  "\tGender\tBorn\tDied" << endl;
    cout << "_____________________________________________________" << endl;
}
void ConsoleUI::removeData()
{
    string str;
    cout << "Enter the name of the scientist you want to remove: " << endl;

}
<commit_msg>setja a rettan stað<commit_after>#include "consoleui.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

void ConsoleUI::run()
{
    bool run = true;
    while (run)
    {
       cout << " ================================" << endl;
       cout << " Press 1 to add" << endl;
       cout << " Press 2 to sort" << endl;
       cout << " Press 3 to list" << endl;
       cout << " Press 4 to search"  << endl;
       cout << " Press 5 to remove scientist"     << endl;
       cout << " Press 6 to exit"     << endl;
       cout << " ================================" << endl;

       char input = '0';
       cin >> input;
       cin.clear();
       fflush(stdin);
       int choice = input - '0';

            switch (choice)
            {
            case 1:
                addData();
                break;
            case 2:
                sortData();
                break;
            case 3:
                showData();
                break;
            case 4:
                searchData();
                break;
            case 5:
                removeData();
            case 6:
                run = false;
                break;
            default:
                cout << "Error! Invalid Input" << endl;
            }

    }

}

void ConsoleUI::addData()
{

    string name;
    char gender;
    int birthYear;
    int deathYear;

    cout << "Enter Name: ";
    cin >> ws;
    getline(cin,name);
    cout << "Enter gender (M/F): ";
    cin >> gender;
    cin.clear();
    fflush(stdin);
    if(genderCheck(gender) == false)
    {
        if(check() == false)
        {
            return;
        }
    }
    cout << "Enter birth year: ";
    cin >> birthYear;
    cout << "Enter death year (0 for living person): ";
    cin >> deathYear;
    if(birthChecks(birthYear, deathYear) == false)
    {
        check();    // Checks if you want to try to input again.
    }
    else
    {
        Persons newPerson(name, gender, birthYear, deathYear);
        serve.add(newPerson);
    }

}
bool ConsoleUI::genderCheck(char gender)
{

   if(gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
   {

       return true;
   }
   else
   {
       cout << "Wrong input for gender!" << endl;
       return false;
   }

}

bool ConsoleUI::check()
{
    char continuel;
    cout << "Do you want to try again? (Y for yes and N for No)" ;
    cin  >> continuel;
    if(continuel == 'Y' || continuel == 'y')
    {
        addData();
    }
    else
    {
       return false;
    }
}

bool ConsoleUI::birthChecks(int birthYear, int deathYear)
{

    if(birthYear < 0 )
    {
        cout << "You can not be born before the year zero." << endl;
        return false;

    }
    if(birthYear > 2016)
    {
        cout << "You can not be born after the year 2016" << endl;
        return false;

    }
    if(deathYear < birthYear && !'0')
    {
        cout << "You cannot die before you are born!" << endl;
        return false;

    }
    if(deathYear > 2016 )
    {

        cout << "You are Still alive.";
        return false;
    }
        return true;
    }

void ConsoleUI::showData()
{
    cout << endl;
    printLine();
    for(size_t i = 0; i < serve.list().size();i++)
    {
        cout << serve.list()[i];
    }
     cout << "_____________________________________________________" << endl;

}

void ConsoleUI::searchData()
{
    bool error = false;
    do
    {
        cout << "How would you like to search the data?" << endl;
        cout << " =====================================" << endl;
        cout << " Press 1 to search by name" << endl;
        cout << " Press 2 to search by birth year" << endl;
        cout << " Press 3 to search for gender" << endl;
        cout << " Press 4 to search by birth year range" << endl;
        cout << " Press 5 to cancel" << endl;
        cout << " ======================================"  << endl;

        char input = '0';
        cin >> input;
        int choice = input - '0';

        switch(choice)
        {
            case 1:
            {
                string n = " ";
                cout << "Enter name: ";
                cin >> ws;
                getline(cin, n);
                vector<int> v_n = serve.searchByName(n);
                if (v_n.size() == 0) {
                    cout << "No results found\n";
                }
                else {
                    printLine();
                    for (unsigned int i = 0; i < v_n.size(); i++)
                    {
                        cout << serve.list()[v_n[i]];
                    }
                }
                error = false;
                break;
            }
            case 2:
            {
                int y = 0;
                cout << "Enter year: ";
                cin >> y;
                vector<int> v_y = serve.searchByYear(y);
                if (v_y.size() == 0) {
                    cout << "No results found\n";
                }
                else {
                    printLine();
                    for (unsigned int i = 0; i < v_y.size(); i++)
                    {
                        cout << serve.list()[v_y[i]];
                    }
                }
                error = false;
                break;
            }
            case 3:
            {
                char gender;
                cout << "Enter gender (M/F): ";
                cin >> gender;
                vector<int> v_g = serve.searchByGender(gender);
                if (v_g.size() == 0)
                {
                    cout << "No results found" << endl;
                }
                else
                {
                    printLine();
                    for (unsigned int i = 0; i < v_g.size(); i++)
                    {
                        cout << serve.list()[v_g[i]];
                    }
                }
                break;
            }
            case 4:
            {
                int f = 0, l = 0;
                cout << "Enter first year in range: ";
                cin >> f;
                cout << "Enter last yar in range: ";
                cin >> l;

                vector<int> v_r = serve.searchByRange(f,l);
                if (v_r.size() == 0)
                {
                    cout << "No results found" << endl;
                }
                else
                {
                    printLine();
                    for (unsigned int i = 0; i < v_r.size(); i++)
                    {
                        cout << serve.list()[v_r[i]];
                    }
                }
                break;
            }

            case 5:
                error = false;
                break;
            default:
            {
                cout << "Error! invalid input" << endl;
                error = true;
            }
        }
    } while (error);
}

void ConsoleUI::sortData()
{
    char input = '0';
    int choice = 0;
    int choice2 = 0;
    bool error = false;

    do
    {

        cout << "How would you like to sort the list?" << endl;
        cout << " ================================" << endl;
        cout << " Press 1 for Name" << endl;
        cout << " Press 2 for Birth Year" << endl;
        cout << " Press 3 for Death Year " << endl;
        cout << " Press 4 for Gender" << endl;
        cout << " Press 5 to cancel" << endl;
        cout << " ================================" << endl;

        cin >> input;
        choice = input - '0';
        choice2 = 0;
        input = '1';

            switch (choice)
                 {
                 case 1:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 2:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 3:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Regular or Reversed sorting?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for regular sorting" << endl;
                        cout << "Press 2 for reversed sorting" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 4:
                    do
                    {
                        if (input != '1' && input != '2' && input != '3')
                        {
                            cout << "Error! Invalid input" << endl;
                        }
                        cout << "Sort by Males or Females?" << endl;
                        cout << " ================================" << endl;
                        cout << "Press 1 for sorting by Females first" << endl;
                        cout << "Press 2 for sorting by Males first" << endl;
                        cout << "Press 3 to cancel" << endl;
                        cout << " ================================" << endl;

                        cin >> input;
                    }
                    while (input != '1' && input != '2' && input != '3');
                    choice2 = input - '0';

                    if (choice2 == 1 || choice2 == 2)
                    {
                        serve.sorting(choice, choice2);
                        error = false;
                    }
                    else
                    {
                        error = true;
                    }
                    break;
                 case 5:
                    error = false;
                    break;
                 default:
                     cout << "Error! Invalid input!" << endl;
                     error = true;
                 }
    }
    while (error);

    if (choice != 5) //if you press cancel, you don't want to see the list, do you?
    {
        showData();
    }
}

void ConsoleUI::printLine()
{
    cout.width(16);
    cout << left << "Name";
    cout <<  "\tGender\tBorn\tDied" << endl;
    cout << "_____________________________________________________" << endl;
}
void ConsoleUI::removeData()
{
    string str;
    cout << "Enter the name of the scientist you want to remove: " << endl;

}
<|endoftext|>


<commit_before>// RUN: clang-tidy %s -- --serialize-diagnostics %t | FileCheck %s
// CHECK: :[[@LINE+1]]:12: error: expected ';' after struct [clang-diagnostic-error]
struct A {}
<commit_msg>[clang-tidy] Make a test independent of the default check set.<commit_after>// RUN: clang-tidy -checks=-*,llvm-namespace-comment %s -- -serialize-diagnostics %t | FileCheck %s
// CHECK: :[[@LINE+1]]:12: error: expected ';' after struct [clang-diagnostic-error]
struct A {}
<|endoftext|>


<commit_before>/*
 *  ofApp.cpp
 *  PONG
 *
 *  KAZOOSH!  - open platform for interactive installations - 2016
 *  http://kazoosh.com
 *
 *  created by Brian Eschrich - 2016
 */

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    //OSX : bundling data in app
#ifdef __APPLE__
    ofSetDataPathRoot("../Resources/data/");
#endif

    ofSeedRandom();
    ofSetFrameRate( 60 );

    //set game state
    changeGameState(END);

    initSettings();

    if (isSerialControl) {
        mouse = new SerialControl(portLeftPaddle, portRightPaddle);
    }
    else {
        mouse = new MouseControl();
    }

    //init controls
    elements.paddleLeft.addControl(*mouse);
    elements.paddleRight.addControl(*mouse);

    //init warper
    initWarper();

    textRenderer = new TextRenderer(&elements);
    playModeController.setup(&elements,textRenderer);

    ofAddListener(gameOverEvent, textRenderer, &TextRenderer::onNewTextElement);

    //init soundPlayer
    soundPlayer.setup();

    //register listeners
    ofAddListener(elements.newScoreEvent, this, &ofApp::onPointsChanged);
    ofAddListener(elements.newGameEvent, &soundPlayer, &SoundPlayer::onGameEvent);
    ofAddListener(elements.newPlayModeEvent, &soundPlayer, &SoundPlayer::onPlaymodeChanged);

    initMessageSwitch = 0;
}

//--------------------------------------------------------------
void ofApp::update(){
    ofSoundUpdate();

    //init message
    if(gamestate == END
       && ofGetElapsedTimeMillis() - lastGamestateChange > 4000){
        restartGame();
        showInitMessage();
    }
    //prepare for start
    else if(gamestate == PLAYERS_PREPARING
            ){
        prepareForStart();
    }
    else if (gamestate == WAIT_FOR_START
             && ofGetElapsedTimeMillis() - lastGamestateChange > 1500) {
        startGame();
    }

    else if (gamestate == RUNNING){
        playModeController.getCurrentRules()->update();
    }

    mouse->update();
    elements.ledControl.update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    //render game view in fbo
    ofBackground(0);
    gameFbo.begin();
    playModeController.getCurrentRenderer()->draw();
    textRenderer->render();

    if (showDebugInfos) {
        drawDebugInformation();
    }
    gameFbo.end();

    //warp fbo on screen
    drawWarpedImage();

}

/**
 * Setups the warper
 */
void ofApp::initWarper(){
    int x = (ofGetWidth() - elements.getWidth()) * 0.5;       // center on screen.
    int y = (ofGetHeight() - elements.getHeigth()) * 0.5;     // center on screen.
    int w = elements.getWidth();
    int h = elements.getHeigth();

    gameFbo.allocate(elements.getWidth(), elements.getHeigth());

    warper.setSourceRect(ofRectangle(0, 0, w, h));              // this is the source rectangle which is the size of the image and located at ( 0, 0 )
    warper.setTopLeftCornerPosition(ofPoint(x, y));             // this is position of the quad warp corners, centering the image on the screen.
    warper.setTopRightCornerPosition(ofPoint(x + w, y));        // this is position of the quad warp corners, centering the image on the screen.
    warper.setBottomLeftCornerPosition(ofPoint(x, y + h));      // this is position of the quad warp corners, centering the image on the screen.
    warper.setBottomRightCornerPosition(ofPoint(x + w, y + h)); // this is position of the quad warp corners, centering the image on the screen.
    warper.setup();
    warper.load(); // reload last saved changes.

    warper.hide();
}

/**
 * draw warped fbo on screen
 */
void ofApp::drawWarpedImage(){
    //======================== get our quad warp matrix.

    ofMatrix4x4 mat = warper.getMatrix();

    //======================== use the matrix to transform our fbo.

    ofPushMatrix();
    ofMultMatrix(mat);
    gameFbo.draw(0, 0);
    ofPopMatrix();

    //======================== draw quad warp ui.

    ofSetColor(ofColor::magenta);
    warper.drawQuadOutline();

    ofSetColor(ofColor::yellow);
    warper.drawCorners();

    ofSetColor(ofColor::magenta);
    warper.drawHighlightedCorner();

    ofSetColor(ofColor::red);
    warper.drawSelectedCorner();

    ofSetColor(ofColor::white);
}

/**
 * resets all elements
 */
void ofApp::restartGame(){
    playModeController.resetStartModes();
    elements.resetElements();

}

/**
 * notify events to start fireworks ;)
 */
void ofApp::endGame(int winner){

    string text = "Player ";
    text += ofToString(winner);
    text += " wins!";

    TextElement t(text,
                  MEDIUM,
                  true,
                  4000,
                  ofColor(255),
                  true);
    ofNotifyEvent(gameOverEvent, t);

    GameEvent g = P1_WIN;
    if (winner == 2) g = P2_WIN;

    ofNotifyEvent(elements.newGameEvent, g);

    changeGameState(END);
}

void ofApp::showInitMessage(){

    int t = ofGetElapsedTimeMillis() - lastGamestateChange;

    bool enter = false;
    if (t > 2000 && initMessageSwitch == 1) {
        enter = true;
    }
    if (t > 230 && initMessageSwitch !=1) {
        enter = true;
    }

    if (enter) {
        string message = "";
        int lengthAni = 500;
        bool hasAnimation = false;

        switch (initMessageSwitch) {
            case 0:
                message = "Paddles up!";
                lengthAni = 2000;
                hasAnimation = true;
                break;
            case 1:
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                message +="^             ^\n";
                break;
            case 2:
                message +=".              .\n";
                message +=".              .\n";
                message +="^             ^\n";
                message +=".              .\n";
                break;
            case 3:
                message +=".              .\n";
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 4:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 5:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 6:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            default:
                break;
        }

        initMessageSwitch = (initMessageSwitch+1)%7;

        TextElement t(message,
                      MEDIUM,
                      hasAnimation,
                      lengthAni);
        ofNotifyEvent(gameOverEvent, t);

        changeGameState(PLAYERS_PREPARING);
    }

}

/**
 * checks if paddles are ready to start game
 */
void ofApp::prepareForStart(){

    if(elements.paddleLeft.getPosition() < elements.paddleLeft.height*1.5  &&
       elements.paddleRight.getPosition() < elements.paddleRight.height*1.5){

        TextElement t("GO!",
                      BIG,
                      true,
                      1500);
        ofNotifyEvent(gameOverEvent, t);

        changeGameState(WAIT_FOR_START);
    }
    else{
        showInitMessage();
    }
}

void ofApp::startGame(){

    GameEvent g = START;
    ofNotifyEvent(elements.newGameEvent, g);
    changeGameState(RUNNING);
}

void ofApp::onPointsChanged(PlayerScoreEvent& e){
    if (e.points >= elements.getWinScore()){
        endGame(e.id);
    }
}

void ofApp::drawDebugInformation(){
    ofPushMatrix();
    ofPushStyle();
    ofSetColor(255,0,0);

    int ty = 20;

    ofTranslate(50, 50);
    ofDrawBitmapString("Debug Information (d - show/hide)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("=================================", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("General", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle PlayMode (p)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("current Rules: " + playModeController.getCurrentRules()->getName(), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("current Renderer: " + playModeController.getCurrentRenderer()->getName(), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle Fullscreen (f)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("save settings (s)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("load settings (a)", 0, 0);
    ofTranslate(0, ty);
    string isModeration = soundPlayer.isModerationMode ? "true":"false";
    ofDrawBitmapString("ModerationMode: " + isModeration + " (m - toggle)", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Warper", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle Show (w)", 0, 0);
    ofTranslate(0, ty);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Ball", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("Velocity: " + ofToString(abs(elements.ball.velocity.x)), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("MinVelocity: " + ofToString(abs(elements.minBallVelocity),1) + " -+ (i,o)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("MaxVelocity: " + ofToString(abs(elements.maxBallVelocity),1) + " -+ (k,l)", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Paddle", 0, 0);
    //ofTranslate(0, ty);
    //  ofDrawBitmapString("Brightness: " + ofToString(ledControl.brightness) + " -+ (DOWN,UP)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("PixelPerLed: " + ofToString(elements.ledControl.pixelPerLed) + " -+ (LEFT,RIGHT)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("PaddleSize: " + ofToString(elements.paddleLeft.height) + " -+ (-,+)", 0, 0);
    ofTranslate(0, ty);
    string tPaddle = elements.paddleLeft.isDebug ? "true":"false";
    ofDrawBitmapString("DebugPaddle: " + tPaddle + " (# - show/hide)", 0, 0);

    ofPopStyle();
    ofPopMatrix();
}

void ofApp::changeGameState(Gamestate gamestate_){
    gamestate = gamestate_;
    lastGamestateChange = ofGetElapsedTimeMillis();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    if(key == 'f') {
        ofToggleFullscreen();
    }

    if(key == 'd') {
        showDebugInfos = !showDebugInfos;
    }

    if(key == 'w') {
        warper.toggleShow();
    }

    if(key == 'a' ) {
        loadSettings();
    }

    if(key == 's' ) {
        saveSettings();
    }

    if(key == 'p') {
        playModeController.shufflePlaymode();
    }
    if(key == '1') {
        //playModeController.setRenderer("PSY");
        // playModeController.setRules("Topspin");
    }

    if(key == OF_KEY_RIGHT) {
        elements.ledControl.pixelPerLed++;
    }
    if(key == OF_KEY_LEFT) {
        elements.ledControl.pixelPerLed--;
    }
    if(key == '+') {
        elements.paddleLeft.height++;
        elements.paddleRight.height++;
    }
    if(key == '-') {
        elements.paddleLeft.height--;
        elements.paddleRight.height--;
    }

    if(key == '#'){
        elements.paddleLeft.isDebug = !elements.paddleLeft.isDebug;
        elements.paddleRight.isDebug = !elements.paddleRight.isDebug;
    }

    if(key == 'i') {
        elements.minBallVelocity--;
    }
    if(key == 'o') {
        elements.minBallVelocity++;
    }
    if(key == 'k') {
        elements.maxBallVelocity--;
    }
    if(key == 'l') {
        elements.maxBallVelocity++;
    }

    if(key == 'm') {
        soundPlayer.isModerationMode = !soundPlayer.isModerationMode;
    }
}

void ofApp::initSettings(){
    settings.add(soundPlayer.isModerationMode);
    settings.add(elements.minBallVelocity);
    settings.add(elements.maxBallVelocity);
    settings.add(elements.ledControl.pixelPerLed);
    settings.add(elements.paddleLeft.height);
    settings.add(elements.paddleRight.height);
    settings.add(isSerialControl.set("isSerialControl", false));
    settings.add(portLeftPaddle.set("portLeftPaddle", "COM1"));
    settings.add(portRightPaddle.set("portRightPaddle", "COM2"));
    loadSettings();
}

void ofApp::saveSettings(){
    ofXml xml;
    xml.serialize(settings);
    xml.save("settings.xml");
    warper.save();
}

void ofApp::loadSettings(){
    ofXml xml;
    xml.load("settings.xml");
    xml.deserialize(settings);
    warper.load();
}

<commit_msg>no ofsoundupdate cause of pi errors<commit_after>/*
 *  ofApp.cpp
 *  PONG
 *
 *  KAZOOSH!  - open platform for interactive installations - 2016
 *  http://kazoosh.com
 *
 *  created by Brian Eschrich - 2016
 */

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    //OSX : bundling data in app
#ifdef __APPLE__
    ofSetDataPathRoot("../Resources/data/");
#endif

    ofSeedRandom();
    ofSetFrameRate( 60 );

    //set game state
    changeGameState(END);

    initSettings();

    if (isSerialControl) {
        mouse = new SerialControl(portLeftPaddle, portRightPaddle);
    }
    else {
        mouse = new MouseControl();
    }

    //init controls
    elements.paddleLeft.addControl(*mouse);
    elements.paddleRight.addControl(*mouse);

    //init warper
    initWarper();

    textRenderer = new TextRenderer(&elements);
    playModeController.setup(&elements,textRenderer);

    ofAddListener(gameOverEvent, textRenderer, &TextRenderer::onNewTextElement);

    //init soundPlayer
    soundPlayer.setup();

    //register listeners
    ofAddListener(elements.newScoreEvent, this, &ofApp::onPointsChanged);
    ofAddListener(elements.newGameEvent, &soundPlayer, &SoundPlayer::onGameEvent);
    ofAddListener(elements.newPlayModeEvent, &soundPlayer, &SoundPlayer::onPlaymodeChanged);

    initMessageSwitch = 0;
}

//--------------------------------------------------------------
void ofApp::update(){
    //ofSoundUpdate();

    //init message
    if(gamestate == END
       && ofGetElapsedTimeMillis() - lastGamestateChange > 4000){
        restartGame();
        showInitMessage();
    }
    //prepare for start
    else if(gamestate == PLAYERS_PREPARING
            ){
        prepareForStart();
    }
    else if (gamestate == WAIT_FOR_START
             && ofGetElapsedTimeMillis() - lastGamestateChange > 1500) {
        startGame();
    }

    else if (gamestate == RUNNING){
        playModeController.getCurrentRules()->update();
    }

    mouse->update();
    elements.ledControl.update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    //render game view in fbo
    ofBackground(0);
    gameFbo.begin();
    playModeController.getCurrentRenderer()->draw();
    textRenderer->render();

    if (showDebugInfos) {
        drawDebugInformation();
    }
    gameFbo.end();

    //warp fbo on screen
    drawWarpedImage();

}

/**
 * Setups the warper
 */
void ofApp::initWarper(){
    int x = (ofGetWidth() - elements.getWidth()) * 0.5;       // center on screen.
    int y = (ofGetHeight() - elements.getHeigth()) * 0.5;     // center on screen.
    int w = elements.getWidth();
    int h = elements.getHeigth();

    gameFbo.allocate(elements.getWidth(), elements.getHeigth());

    warper.setSourceRect(ofRectangle(0, 0, w, h));              // this is the source rectangle which is the size of the image and located at ( 0, 0 )
    warper.setTopLeftCornerPosition(ofPoint(x, y));             // this is position of the quad warp corners, centering the image on the screen.
    warper.setTopRightCornerPosition(ofPoint(x + w, y));        // this is position of the quad warp corners, centering the image on the screen.
    warper.setBottomLeftCornerPosition(ofPoint(x, y + h));      // this is position of the quad warp corners, centering the image on the screen.
    warper.setBottomRightCornerPosition(ofPoint(x + w, y + h)); // this is position of the quad warp corners, centering the image on the screen.
    warper.setup();
    warper.load(); // reload last saved changes.

    warper.hide();
}

/**
 * draw warped fbo on screen
 */
void ofApp::drawWarpedImage(){
    //======================== get our quad warp matrix.

    ofMatrix4x4 mat = warper.getMatrix();

    //======================== use the matrix to transform our fbo.

    ofPushMatrix();
    ofMultMatrix(mat);
    gameFbo.draw(0, 0);
    ofPopMatrix();

    //======================== draw quad warp ui.

    ofSetColor(ofColor::magenta);
    warper.drawQuadOutline();

    ofSetColor(ofColor::yellow);
    warper.drawCorners();

    ofSetColor(ofColor::magenta);
    warper.drawHighlightedCorner();

    ofSetColor(ofColor::red);
    warper.drawSelectedCorner();

    ofSetColor(ofColor::white);
}

/**
 * resets all elements
 */
void ofApp::restartGame(){
    playModeController.resetStartModes();
    elements.resetElements();

}

/**
 * notify events to start fireworks ;)
 */
void ofApp::endGame(int winner){

    string text = "Player ";
    text += ofToString(winner);
    text += " wins!";

    TextElement t(text,
                  MEDIUM,
                  true,
                  4000,
                  ofColor(255),
                  true);
    ofNotifyEvent(gameOverEvent, t);

    GameEvent g = P1_WIN;
    if (winner == 2) g = P2_WIN;

    ofNotifyEvent(elements.newGameEvent, g);

    changeGameState(END);
}

void ofApp::showInitMessage(){

    int t = ofGetElapsedTimeMillis() - lastGamestateChange;

    bool enter = false;
    if (t > 2000 && initMessageSwitch == 1) {
        enter = true;
    }
    if (t > 230 && initMessageSwitch !=1) {
        enter = true;
    }

    if (enter) {
        string message = "";
        int lengthAni = 500;
        bool hasAnimation = false;

        switch (initMessageSwitch) {
            case 0:
                message = "Paddles up!";
                lengthAni = 2000;
                hasAnimation = true;
                break;
            case 1:
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                message +="^             ^\n";
                break;
            case 2:
                message +=".              .\n";
                message +=".              .\n";
                message +="^             ^\n";
                message +=".              .\n";
                break;
            case 3:
                message +=".              .\n";
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 4:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 5:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            case 6:
                message +="^             ^\n";
                message +=".              .\n";
                message +=".              .\n";
                message +=".              .\n";
                break;
            default:
                break;
        }

        initMessageSwitch = (initMessageSwitch+1)%7;

        TextElement t(message,
                      MEDIUM,
                      hasAnimation,
                      lengthAni);
        ofNotifyEvent(gameOverEvent, t);

        changeGameState(PLAYERS_PREPARING);
    }

}

/**
 * checks if paddles are ready to start game
 */
void ofApp::prepareForStart(){

    if(elements.paddleLeft.getPosition() < elements.paddleLeft.height*1.5  &&
       elements.paddleRight.getPosition() < elements.paddleRight.height*1.5){

        TextElement t("GO!",
                      BIG,
                      true,
                      1500);
        ofNotifyEvent(gameOverEvent, t);

        changeGameState(WAIT_FOR_START);
    }
    else{
        showInitMessage();
    }
}

void ofApp::startGame(){

    GameEvent g = START;
    ofNotifyEvent(elements.newGameEvent, g);
    changeGameState(RUNNING);
}

void ofApp::onPointsChanged(PlayerScoreEvent& e){
    if (e.points >= elements.getWinScore()){
        endGame(e.id);
    }
}

void ofApp::drawDebugInformation(){
    ofPushMatrix();
    ofPushStyle();
    ofSetColor(255,0,0);

    int ty = 20;

    ofTranslate(50, 50);
    ofDrawBitmapString("Debug Information (d - show/hide)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("=================================", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("General", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle PlayMode (p)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("current Rules: " + playModeController.getCurrentRules()->getName(), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("current Renderer: " + playModeController.getCurrentRenderer()->getName(), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle Fullscreen (f)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("save settings (s)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("load settings (a)", 0, 0);
    ofTranslate(0, ty);
    string isModeration = soundPlayer.isModerationMode ? "true":"false";
    ofDrawBitmapString("ModerationMode: " + isModeration + " (m - toggle)", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Warper", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("toggle Show (w)", 0, 0);
    ofTranslate(0, ty);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Ball", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("Velocity: " + ofToString(abs(elements.ball.velocity.x)), 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("MinVelocity: " + ofToString(abs(elements.minBallVelocity),1) + " -+ (i,o)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("MaxVelocity: " + ofToString(abs(elements.maxBallVelocity),1) + " -+ (k,l)", 0, 0);

    ofTranslate(0, ty);
    ofTranslate(0, ty);
    ofDrawBitmapString("Paddle", 0, 0);
    //ofTranslate(0, ty);
    //  ofDrawBitmapString("Brightness: " + ofToString(ledControl.brightness) + " -+ (DOWN,UP)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("PixelPerLed: " + ofToString(elements.ledControl.pixelPerLed) + " -+ (LEFT,RIGHT)", 0, 0);
    ofTranslate(0, ty);
    ofDrawBitmapString("PaddleSize: " + ofToString(elements.paddleLeft.height) + " -+ (-,+)", 0, 0);
    ofTranslate(0, ty);
    string tPaddle = elements.paddleLeft.isDebug ? "true":"false";
    ofDrawBitmapString("DebugPaddle: " + tPaddle + " (# - show/hide)", 0, 0);

    ofPopStyle();
    ofPopMatrix();
}

void ofApp::changeGameState(Gamestate gamestate_){
    gamestate = gamestate_;
    lastGamestateChange = ofGetElapsedTimeMillis();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    if(key == 'f') {
        ofToggleFullscreen();
    }

    if(key == 'd') {
        showDebugInfos = !showDebugInfos;
    }

    if(key == 'w') {
        warper.toggleShow();
    }

    if(key == 'a' ) {
        loadSettings();
    }

    if(key == 's' ) {
        saveSettings();
    }

    if(key == 'p') {
        playModeController.shufflePlaymode();
    }
    if(key == '1') {
        //playModeController.setRenderer("PSY");
        // playModeController.setRules("Topspin");
    }

    if(key == OF_KEY_RIGHT) {
        elements.ledControl.pixelPerLed++;
    }
    if(key == OF_KEY_LEFT) {
        elements.ledControl.pixelPerLed--;
    }
    if(key == '+') {
        elements.paddleLeft.height++;
        elements.paddleRight.height++;
    }
    if(key == '-') {
        elements.paddleLeft.height--;
        elements.paddleRight.height--;
    }

    if(key == '#'){
        elements.paddleLeft.isDebug = !elements.paddleLeft.isDebug;
        elements.paddleRight.isDebug = !elements.paddleRight.isDebug;
    }

    if(key == 'i') {
        elements.minBallVelocity--;
    }
    if(key == 'o') {
        elements.minBallVelocity++;
    }
    if(key == 'k') {
        elements.maxBallVelocity--;
    }
    if(key == 'l') {
        elements.maxBallVelocity++;
    }

    if(key == 'm') {
        soundPlayer.isModerationMode = !soundPlayer.isModerationMode;
    }
}

void ofApp::initSettings(){
    settings.add(soundPlayer.isModerationMode);
    settings.add(elements.minBallVelocity);
    settings.add(elements.maxBallVelocity);
    settings.add(elements.ledControl.pixelPerLed);
    settings.add(elements.paddleLeft.height);
    settings.add(elements.paddleRight.height);
    settings.add(isSerialControl.set("isSerialControl", false));
    settings.add(portLeftPaddle.set("portLeftPaddle", "COM1"));
    settings.add(portRightPaddle.set("portRightPaddle", "COM2"));
    loadSettings();
}

void ofApp::saveSettings(){
    ofXml xml;
    xml.serialize(settings);
    xml.save("settings.xml");
    warper.save();
}

void ofApp::loadSettings(){
    ofXml xml;
    xml.load("settings.xml");
    xml.deserialize(settings);
    warper.load();
}

<|endoftext|>


<commit_before><commit_msg>Bugfix: `AnyValue` constructor: correct value of `type` for `AnyStruct`.<commit_after><|endoftext|>


<commit_before><commit_msg>`AnyValue::get_string`: cleaning up code.<commit_after><|endoftext|>


<commit_before>/*
 * SSL/TLS configuration.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ssl_factory.hxx"
#include "ssl_config.hxx"
#include "ssl_domain.hxx"
#include "util/Error.hxx"

#include <inline/compiler.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <assert.h>

struct ssl_cert_key {
    X509 *cert;
    EVP_PKEY *key;

    ssl_cert_key():cert(nullptr), key(nullptr) {}

    ssl_cert_key(X509 *_cert, EVP_PKEY *_key)
        :cert(_cert), key(_key) {}

    ssl_cert_key(ssl_cert_key &&other)
        :cert(other.cert), key(other.key) {
        other.cert = nullptr;
        other.key = nullptr;
    }

    ~ssl_cert_key() {
        if (cert != nullptr)
            X509_free(cert);
        if (key != nullptr)
            EVP_PKEY_free(key);
    }

    ssl_cert_key &operator=(ssl_cert_key &&other) {
        std::swap(cert, other.cert);
        std::swap(key, other.key);
        return *this;
    }

    bool Load(const ssl_cert_key_config &config, Error &error);
};

struct ssl_factory {
    SSL_CTX *const ssl_ctx;

    std::vector<ssl_cert_key> cert_key;

    const bool server;

    ssl_factory(SSL_CTX *_ssl_ctx, bool _server)
        :ssl_ctx(_ssl_ctx), server(_server) {}

    ~ssl_factory() {
        SSL_CTX_free(ssl_ctx);
    }

    bool EnableSNI(Error &error);

    SSL *Make();

    unsigned Flush(long tm);
};

static int
verify_callback(int ok, gcc_unused X509_STORE_CTX *ctx)
{
    return ok;
}

static BIO *
bio_open_file(const char *path, Error &error)
{
    BIO *bio = BIO_new_file(path, "r");
    if (bio == NULL)
        error.Format(ssl_domain, "Failed to open file %s", path);

    return bio;
}

static EVP_PKEY *
read_key_file(const char *path, Error &error)
{
    BIO *bio = bio_open_file(path, error);
    if (bio == NULL)
        return NULL;

    EVP_PKEY *key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);
    if (key == NULL)
        error.Format(ssl_domain, "Failed to load key file %s", path);

    return key;
}

static X509 *
read_cert_file(const char *path, Error &error)
{
    BIO *bio = bio_open_file(path, error);
    if (bio == NULL)
        return NULL;

    X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
    BIO_free(bio);
    if (cert == NULL)
        error.Format(ssl_domain, "Failed to load certificate file %s", path);

    return cert;
}

/**
 * Are both public keys equal?
 */
gcc_pure
static bool
MatchModulus(EVP_PKEY *key1, EVP_PKEY *key2)
{
    assert(key1 != nullptr);
    assert(key2 != nullptr);

    if (key1->type != key2->type)
        return false;

    switch (key1->type) {
    case EVP_PKEY_RSA:
        return BN_cmp(key1->pkey.rsa->n, key2->pkey.rsa->n) == 0;

    case EVP_PKEY_DSA:
        return BN_cmp(key1->pkey.dsa->pub_key, key2->pkey.dsa->pub_key) == 0;

    default:
        return false;
    }
}

/**
 * Does the certificate belong to the given key?
 */
gcc_pure
static bool
MatchModulus(X509 *cert, EVP_PKEY *key)
{
    assert(cert != nullptr);
    assert(key != nullptr);

    EVP_PKEY *public_key = X509_get_pubkey(cert);
    if (public_key == nullptr)
        return false;

    const bool result = MatchModulus(public_key, key);
    EVP_PKEY_free(public_key);
    return result;
}

bool
ssl_cert_key::Load(const ssl_cert_key_config &config, Error &error)
{
    assert(key == nullptr);
    assert(cert == nullptr);

    key = read_key_file(config.key_file.c_str(), error);
    if (key == nullptr)
        return false;

    cert = read_cert_file(config.cert_file.c_str(), error);
    if (cert == nullptr)
        return false;

    if (!MatchModulus(cert, key)) {
        error.Format(ssl_domain, "Key '%s' does not match certificate '%s'",
                    config.key_file.c_str(), config.cert_file.c_str());
        return false;
    }

    return true;
}

static bool
load_certs_keys(ssl_factory &factory, const ssl_config &config,
                Error &error)
{
    factory.cert_key.reserve(config.cert_key.size());

    for (const auto &c : config.cert_key) {
        ssl_cert_key ck;
        if (!ck.Load(c, error))
            return false;

        factory.cert_key.emplace_back(std::move(ck));
    }

    return true;
}

static bool
apply_server_config(SSL_CTX *ssl_ctx, const ssl_config &config,
                    Error &error)
{
    assert(!config.cert_key.empty());

    ERR_clear_error();

    if (SSL_CTX_use_RSAPrivateKey_file(ssl_ctx,
                                       config.cert_key[0].key_file.c_str(),
                                       SSL_FILETYPE_PEM) != 1) {
        ERR_print_errors_fp(stderr);
        error.Format(ssl_domain, "Failed to load key file %s",
                     config.cert_key[0].key_file.c_str());
        return false;
    }

    if (SSL_CTX_use_certificate_chain_file(ssl_ctx,
                                           config.cert_key[0].cert_file.c_str()) != 1) {
        ERR_print_errors_fp(stderr);
        error.Format(ssl_domain, "Failed to load certificate file %s",
                     config.cert_key[0].cert_file.c_str());
        return false;
    }

    if (!config.ca_cert_file.empty()) {
        if (SSL_CTX_load_verify_locations(ssl_ctx,
                                          config.ca_cert_file.c_str(),
                                          NULL) != 1) {
            error.Format(ssl_domain, "Failed to load CA certificate file %s",
                         config.ca_cert_file.c_str());
            return false;
        }

        /* send all certificates from this file to the client (list of
           acceptable CA certificates) */

        STACK_OF(X509_NAME) *list =
            SSL_load_client_CA_file(config.ca_cert_file.c_str());
        if (list == NULL) {
            error.Format(ssl_domain,
                         "Failed to load CA certificate list from file %s",
                         config.ca_cert_file.c_str());
            return false;
        }

        SSL_CTX_set_client_CA_list(ssl_ctx, list);
    }

    if (config.verify != ssl_verify::NO) {
        /* enable client certificates */
        int mode = SSL_VERIFY_PEER;

        if (config.verify == ssl_verify::YES)
            mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;

        SSL_CTX_set_verify(ssl_ctx, mode, verify_callback);
    }

    return true;
}

static bool
match_cn(X509_NAME *subject, const char *host_name, size_t hn_length)
{
    char common_name[256];
    if (X509_NAME_get_text_by_NID(subject, NID_commonName, common_name,
                                  sizeof(common_name)) < 0)
        return false;

    if (strcmp(host_name, common_name) == 0)
        return true;

    if (common_name[0] == '*' && common_name[1] == '.' &&
        common_name[2] != 0) {
        const size_t cn_length = strlen(common_name);
        if (hn_length >= cn_length &&
            /* match only one segment (no dots) */
            memchr(host_name, '.', hn_length - cn_length + 1) == NULL &&
            memcmp(host_name + hn_length - cn_length + 1,
                   common_name + 1, cn_length - 1) == 0)
            return true;
    }

    return false;
}

static bool
use_cert_key(SSL *ssl, const ssl_cert_key &ck)
{
    return SSL_use_certificate(ssl, ck.cert) == 1 &&
        SSL_use_PrivateKey(ssl, ck.key) == 1;
}

static int
ssl_servername_callback(SSL *ssl, gcc_unused int *al,
                        const ssl_factory &factory)
{
    const char *host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    if (host_name == NULL)
        return SSL_TLSEXT_ERR_OK;

    const size_t length = strlen(host_name);

    /* find the first certificate that matches */

    for (const auto &ck : factory.cert_key) {
        X509_NAME *subject = X509_get_subject_name(ck.cert);
        if (subject != NULL && match_cn(subject, host_name, length)) {
            /* found it - now use it */
            use_cert_key(ssl, ck);
            break;
        }
    }

    return SSL_TLSEXT_ERR_OK;
}

inline bool
ssl_factory::EnableSNI(Error &error)
{
    if (!SSL_CTX_set_tlsext_servername_callback(ssl_ctx,
                                                ssl_servername_callback) ||
        !SSL_CTX_set_tlsext_servername_arg(ssl_ctx, this)) {
        error.Format(ssl_domain,
                     "SSL_CTX_set_tlsext_servername_callback() failed");
        return false;
    }

    return true;
}

inline SSL *
ssl_factory::Make()
{
    SSL *ssl = SSL_new(ssl_ctx);
    if (ssl == nullptr)
        return nullptr;

    if (server)
        SSL_set_accept_state(ssl);
    else
        SSL_set_connect_state(ssl);

    return ssl;
}

inline unsigned
ssl_factory::Flush(long tm)
{
    unsigned before = SSL_CTX_sess_number(ssl_ctx);
    SSL_CTX_flush_sessions(ssl_ctx, tm);
    unsigned after = SSL_CTX_sess_number(ssl_ctx);
    return after < before ? before - after : 0;
}

/**
 * Enable Elliptic curve Diffie-Hellman (ECDH) for perfect forward
 * secrecy.  By default, it OpenSSL disables it.
 */
static bool
enable_ecdh(SSL_CTX *ssl_ctx, Error &error)
{
    /* OpenSSL 1.0.2 will allow this instead:

       SSL_CTX_set_ecdh_auto(ssl_ctx, 1)
    */

    EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    if (ecdh == nullptr) {
        error.Set(ssl_domain, "EC_KEY_new_by_curve_name() failed");
        return nullptr;
    }

    bool success = SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh) == 1;
    EC_KEY_free(ecdh);
    if (!success)
        error.Set(ssl_domain, "SSL_CTX_set_tmp_ecdh() failed");

    return success;
}

struct ssl_factory *
ssl_factory_new(const ssl_config &config,
                bool server,
                Error &error)
{
    assert(!config.cert_key.empty() || !server);

    /* don't be fooled - we want TLS, not SSL - but TLSv1_method()
       will only allow TLSv1.0 and will refuse TLSv1.1 and TLSv1.2;
       only SSLv23_method() supports all (future) TLS protocol
       versions, even if we don't want any SSL at all */
    auto method = server
        ? SSLv23_server_method()
        : SSLv23_client_method();

    SSL_CTX *ssl_ctx = SSL_CTX_new(method);
    if (ssl_ctx == NULL) {
        error.Format(ssl_domain, "SSL_CTX_new() failed");
        return NULL;
    }

    long mode = SSL_MODE_ENABLE_PARTIAL_WRITE
        | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
#ifdef SSL_MODE_RELEASE_BUFFERS
    /* requires libssl 1.0.0 */
    mode |= SSL_MODE_RELEASE_BUFFERS;
#endif
    SSL_CTX_set_mode(ssl_ctx, mode);

    if (server && !enable_ecdh(ssl_ctx, error)) {
        SSL_CTX_free(ssl_ctx);
        return nullptr;
    }

    /* disable protocols that are known to be insecure */
    SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);

    /* disable weak ciphers */
    SSL_CTX_set_cipher_list(ssl_ctx, "DEFAULT:!EXPORT:!LOW");

    ssl_factory *factory = new ssl_factory(ssl_ctx, server);

    if (server) {
        if (!apply_server_config(ssl_ctx, config, error) ||
            !load_certs_keys(*factory, config, error)) {
            delete factory;
            return NULL;
        }
    } else {
        assert(config.cert_key.empty());
        assert(config.ca_cert_file.empty());
        assert(config.verify == ssl_verify::NO);
    }

    if (factory->cert_key.size() > 1 && !factory->EnableSNI(error)) {
        delete factory;
        return NULL;
    }

    return factory;
}

void
ssl_factory_free(struct ssl_factory *factory)
{
    delete factory;
}

SSL *
ssl_factory_make(ssl_factory &factory)
{
    return factory.Make();
}

unsigned
ssl_factory_flush(struct ssl_factory &factory, long tm)
{
    return factory.Flush(tm);
}
<commit_msg>ssl_factory: dump SSL_CTX_new() errors<commit_after>/*
 * SSL/TLS configuration.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ssl_factory.hxx"
#include "ssl_config.hxx"
#include "ssl_domain.hxx"
#include "util/Error.hxx"

#include <inline/compiler.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <assert.h>

struct ssl_cert_key {
    X509 *cert;
    EVP_PKEY *key;

    ssl_cert_key():cert(nullptr), key(nullptr) {}

    ssl_cert_key(X509 *_cert, EVP_PKEY *_key)
        :cert(_cert), key(_key) {}

    ssl_cert_key(ssl_cert_key &&other)
        :cert(other.cert), key(other.key) {
        other.cert = nullptr;
        other.key = nullptr;
    }

    ~ssl_cert_key() {
        if (cert != nullptr)
            X509_free(cert);
        if (key != nullptr)
            EVP_PKEY_free(key);
    }

    ssl_cert_key &operator=(ssl_cert_key &&other) {
        std::swap(cert, other.cert);
        std::swap(key, other.key);
        return *this;
    }

    bool Load(const ssl_cert_key_config &config, Error &error);
};

struct ssl_factory {
    SSL_CTX *const ssl_ctx;

    std::vector<ssl_cert_key> cert_key;

    const bool server;

    ssl_factory(SSL_CTX *_ssl_ctx, bool _server)
        :ssl_ctx(_ssl_ctx), server(_server) {}

    ~ssl_factory() {
        SSL_CTX_free(ssl_ctx);
    }

    bool EnableSNI(Error &error);

    SSL *Make();

    unsigned Flush(long tm);
};

static int
verify_callback(int ok, gcc_unused X509_STORE_CTX *ctx)
{
    return ok;
}

static BIO *
bio_open_file(const char *path, Error &error)
{
    BIO *bio = BIO_new_file(path, "r");
    if (bio == NULL)
        error.Format(ssl_domain, "Failed to open file %s", path);

    return bio;
}

static EVP_PKEY *
read_key_file(const char *path, Error &error)
{
    BIO *bio = bio_open_file(path, error);
    if (bio == NULL)
        return NULL;

    EVP_PKEY *key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);
    if (key == NULL)
        error.Format(ssl_domain, "Failed to load key file %s", path);

    return key;
}

static X509 *
read_cert_file(const char *path, Error &error)
{
    BIO *bio = bio_open_file(path, error);
    if (bio == NULL)
        return NULL;

    X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
    BIO_free(bio);
    if (cert == NULL)
        error.Format(ssl_domain, "Failed to load certificate file %s", path);

    return cert;
}

/**
 * Are both public keys equal?
 */
gcc_pure
static bool
MatchModulus(EVP_PKEY *key1, EVP_PKEY *key2)
{
    assert(key1 != nullptr);
    assert(key2 != nullptr);

    if (key1->type != key2->type)
        return false;

    switch (key1->type) {
    case EVP_PKEY_RSA:
        return BN_cmp(key1->pkey.rsa->n, key2->pkey.rsa->n) == 0;

    case EVP_PKEY_DSA:
        return BN_cmp(key1->pkey.dsa->pub_key, key2->pkey.dsa->pub_key) == 0;

    default:
        return false;
    }
}

/**
 * Does the certificate belong to the given key?
 */
gcc_pure
static bool
MatchModulus(X509 *cert, EVP_PKEY *key)
{
    assert(cert != nullptr);
    assert(key != nullptr);

    EVP_PKEY *public_key = X509_get_pubkey(cert);
    if (public_key == nullptr)
        return false;

    const bool result = MatchModulus(public_key, key);
    EVP_PKEY_free(public_key);
    return result;
}

bool
ssl_cert_key::Load(const ssl_cert_key_config &config, Error &error)
{
    assert(key == nullptr);
    assert(cert == nullptr);

    key = read_key_file(config.key_file.c_str(), error);
    if (key == nullptr)
        return false;

    cert = read_cert_file(config.cert_file.c_str(), error);
    if (cert == nullptr)
        return false;

    if (!MatchModulus(cert, key)) {
        error.Format(ssl_domain, "Key '%s' does not match certificate '%s'",
                    config.key_file.c_str(), config.cert_file.c_str());
        return false;
    }

    return true;
}

static bool
load_certs_keys(ssl_factory &factory, const ssl_config &config,
                Error &error)
{
    factory.cert_key.reserve(config.cert_key.size());

    for (const auto &c : config.cert_key) {
        ssl_cert_key ck;
        if (!ck.Load(c, error))
            return false;

        factory.cert_key.emplace_back(std::move(ck));
    }

    return true;
}

static bool
apply_server_config(SSL_CTX *ssl_ctx, const ssl_config &config,
                    Error &error)
{
    assert(!config.cert_key.empty());

    ERR_clear_error();

    if (SSL_CTX_use_RSAPrivateKey_file(ssl_ctx,
                                       config.cert_key[0].key_file.c_str(),
                                       SSL_FILETYPE_PEM) != 1) {
        ERR_print_errors_fp(stderr);
        error.Format(ssl_domain, "Failed to load key file %s",
                     config.cert_key[0].key_file.c_str());
        return false;
    }

    if (SSL_CTX_use_certificate_chain_file(ssl_ctx,
                                           config.cert_key[0].cert_file.c_str()) != 1) {
        ERR_print_errors_fp(stderr);
        error.Format(ssl_domain, "Failed to load certificate file %s",
                     config.cert_key[0].cert_file.c_str());
        return false;
    }

    if (!config.ca_cert_file.empty()) {
        if (SSL_CTX_load_verify_locations(ssl_ctx,
                                          config.ca_cert_file.c_str(),
                                          NULL) != 1) {
            error.Format(ssl_domain, "Failed to load CA certificate file %s",
                         config.ca_cert_file.c_str());
            return false;
        }

        /* send all certificates from this file to the client (list of
           acceptable CA certificates) */

        STACK_OF(X509_NAME) *list =
            SSL_load_client_CA_file(config.ca_cert_file.c_str());
        if (list == NULL) {
            error.Format(ssl_domain,
                         "Failed to load CA certificate list from file %s",
                         config.ca_cert_file.c_str());
            return false;
        }

        SSL_CTX_set_client_CA_list(ssl_ctx, list);
    }

    if (config.verify != ssl_verify::NO) {
        /* enable client certificates */
        int mode = SSL_VERIFY_PEER;

        if (config.verify == ssl_verify::YES)
            mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;

        SSL_CTX_set_verify(ssl_ctx, mode, verify_callback);
    }

    return true;
}

static bool
match_cn(X509_NAME *subject, const char *host_name, size_t hn_length)
{
    char common_name[256];
    if (X509_NAME_get_text_by_NID(subject, NID_commonName, common_name,
                                  sizeof(common_name)) < 0)
        return false;

    if (strcmp(host_name, common_name) == 0)
        return true;

    if (common_name[0] == '*' && common_name[1] == '.' &&
        common_name[2] != 0) {
        const size_t cn_length = strlen(common_name);
        if (hn_length >= cn_length &&
            /* match only one segment (no dots) */
            memchr(host_name, '.', hn_length - cn_length + 1) == NULL &&
            memcmp(host_name + hn_length - cn_length + 1,
                   common_name + 1, cn_length - 1) == 0)
            return true;
    }

    return false;
}

static bool
use_cert_key(SSL *ssl, const ssl_cert_key &ck)
{
    return SSL_use_certificate(ssl, ck.cert) == 1 &&
        SSL_use_PrivateKey(ssl, ck.key) == 1;
}

static int
ssl_servername_callback(SSL *ssl, gcc_unused int *al,
                        const ssl_factory &factory)
{
    const char *host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    if (host_name == NULL)
        return SSL_TLSEXT_ERR_OK;

    const size_t length = strlen(host_name);

    /* find the first certificate that matches */

    for (const auto &ck : factory.cert_key) {
        X509_NAME *subject = X509_get_subject_name(ck.cert);
        if (subject != NULL && match_cn(subject, host_name, length)) {
            /* found it - now use it */
            use_cert_key(ssl, ck);
            break;
        }
    }

    return SSL_TLSEXT_ERR_OK;
}

inline bool
ssl_factory::EnableSNI(Error &error)
{
    if (!SSL_CTX_set_tlsext_servername_callback(ssl_ctx,
                                                ssl_servername_callback) ||
        !SSL_CTX_set_tlsext_servername_arg(ssl_ctx, this)) {
        error.Format(ssl_domain,
                     "SSL_CTX_set_tlsext_servername_callback() failed");
        return false;
    }

    return true;
}

inline SSL *
ssl_factory::Make()
{
    SSL *ssl = SSL_new(ssl_ctx);
    if (ssl == nullptr)
        return nullptr;

    if (server)
        SSL_set_accept_state(ssl);
    else
        SSL_set_connect_state(ssl);

    return ssl;
}

inline unsigned
ssl_factory::Flush(long tm)
{
    unsigned before = SSL_CTX_sess_number(ssl_ctx);
    SSL_CTX_flush_sessions(ssl_ctx, tm);
    unsigned after = SSL_CTX_sess_number(ssl_ctx);
    return after < before ? before - after : 0;
}

/**
 * Enable Elliptic curve Diffie-Hellman (ECDH) for perfect forward
 * secrecy.  By default, it OpenSSL disables it.
 */
static bool
enable_ecdh(SSL_CTX *ssl_ctx, Error &error)
{
    /* OpenSSL 1.0.2 will allow this instead:

       SSL_CTX_set_ecdh_auto(ssl_ctx, 1)
    */

    EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    if (ecdh == nullptr) {
        error.Set(ssl_domain, "EC_KEY_new_by_curve_name() failed");
        return nullptr;
    }

    bool success = SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh) == 1;
    EC_KEY_free(ecdh);
    if (!success)
        error.Set(ssl_domain, "SSL_CTX_set_tmp_ecdh() failed");

    return success;
}

struct ssl_factory *
ssl_factory_new(const ssl_config &config,
                bool server,
                Error &error)
{
    assert(!config.cert_key.empty() || !server);

    ERR_clear_error();

    /* don't be fooled - we want TLS, not SSL - but TLSv1_method()
       will only allow TLSv1.0 and will refuse TLSv1.1 and TLSv1.2;
       only SSLv23_method() supports all (future) TLS protocol
       versions, even if we don't want any SSL at all */
    auto method = server
        ? SSLv23_server_method()
        : SSLv23_client_method();

    SSL_CTX *ssl_ctx = SSL_CTX_new(method);
    if (ssl_ctx == NULL) {
        ERR_print_errors_fp(stderr);
        error.Format(ssl_domain, "SSL_CTX_new() failed");
        return NULL;
    }

    long mode = SSL_MODE_ENABLE_PARTIAL_WRITE
        | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
#ifdef SSL_MODE_RELEASE_BUFFERS
    /* requires libssl 1.0.0 */
    mode |= SSL_MODE_RELEASE_BUFFERS;
#endif
    SSL_CTX_set_mode(ssl_ctx, mode);

    if (server && !enable_ecdh(ssl_ctx, error)) {
        SSL_CTX_free(ssl_ctx);
        return nullptr;
    }

    /* disable protocols that are known to be insecure */
    SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);

    /* disable weak ciphers */
    SSL_CTX_set_cipher_list(ssl_ctx, "DEFAULT:!EXPORT:!LOW");

    ssl_factory *factory = new ssl_factory(ssl_ctx, server);

    if (server) {
        if (!apply_server_config(ssl_ctx, config, error) ||
            !load_certs_keys(*factory, config, error)) {
            delete factory;
            return NULL;
        }
    } else {
        assert(config.cert_key.empty());
        assert(config.ca_cert_file.empty());
        assert(config.verify == ssl_verify::NO);
    }

    if (factory->cert_key.size() > 1 && !factory->EnableSNI(error)) {
        delete factory;
        return NULL;
    }

    return factory;
}

void
ssl_factory_free(struct ssl_factory *factory)
{
    delete factory;
}

SSL *
ssl_factory_make(ssl_factory &factory)
{
    return factory.Make();
}

unsigned
ssl_factory_flush(struct ssl_factory &factory, long tm)
{
    return factory.Flush(tm);
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2016 Intel Corporation                                         //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "OSPRayFixture.h"

using namespace ospcommon;
using namespace ospray;

const static int DEFAULT_WIDTH = 1024;
const static int DEFAULT_HEIGHT = 1024;
const static size_t DEFAULT_BENCH_FRAMES = 100;
const static size_t DEFAULT_WARMUP_FRAMES = 10;

const static vec3f DEFAULT_BG_COLOR = {1.f, 1.f, 1.f};

namespace bench {
// helper function to write the rendered image as PPM file
void writePPM(const std::string &fileName, const int sizeX, const int sizeY,
              const uint32_t *pixel)
{
  FILE *file = fopen(fileName.c_str(), "wb");
  fprintf(file, "P6\n%i %i\n255\n", sizeX, sizeY);
  unsigned char *out = (unsigned char *)alloca(3*sizeX);
  for (int y = 0; y < sizeY; y++) {
    const unsigned char *in = (const unsigned char *)&pixel[(sizeY-1-y)*sizeX];
    for (int x = 0; x < sizeX; x++) {
      out[3*x + 0] = in[4*x + 0];
      out[3*x + 1] = in[4*x + 1];
      out[3*x + 2] = in[4*x + 2];
    }
    fwrite(out, 3*sizeX, sizeof(char), file);
  }
  fprintf(file, "\n");
  fclose(file);
}
}

OSPRayFixture::OSPRayFixture(cpp::Renderer r, cpp::Camera c, cpp::Model m)
  : renderer(r), camera(c), model(m), width(DEFAULT_WIDTH), height(DEFAULT_HEIGHT),
  defaultBenchFrames(DEFAULT_BENCH_FRAMES), defaultWarmupFrames(DEFAULT_WARMUP_FRAMES)
{
  setFrameBufferDims(width, height);
  renderer.set("world", model);
  renderer.set("model", model);
  renderer.set("camera", camera);
  renderer.set("spp", 1);
  renderer.commit();
}
pico_bench::Statistics<OSPRayFixture::Millis>
OSPRayFixture::benchmark(const size_t warmUpFrames, const size_t benchFrames) {
  const size_t warmup = warmUpFrames == 0 ? defaultWarmupFrames : warmUpFrames;
  const size_t bench = benchFrames == 0 ? defaultBenchFrames : benchFrames;
  for (size_t i = 0; i < warmup; ++i) {
    renderer.renderFrame(fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  }
  fb.clear(OSP_FB_ACCUM | OSP_FB_COLOR);

  auto benchmarker = pico_bench::Benchmarker<Millis>(bench);
  auto stats = benchmarker([&]() {
      renderer.renderFrame(fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  });
  stats.time_suffix = " ms";
  return stats;
}
void OSPRayFixture::saveImage(const std::string &fname) {
  auto *lfb = (uint32_t*)fb.map(OSP_FB_COLOR);
  bench::writePPM(fname + ".ppm", width, height, lfb);
  fb.unmap(lfb);
}
void OSPRayFixture::setFrameBufferDims(const int w, const int h) {
  width = w > 0 ? w : width;
  height = h > 0 ? h : height;

  fb = cpp::FrameBuffer(osp::vec2i{width, height}, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM);
  fb.clear(OSP_FB_ACCUM | OSP_FB_COLOR);

  camera.set("aspect", static_cast<float>(width) / height);
  camera.commit();
}

<commit_msg>fixing benchmark app overwriting spp<commit_after>// ======================================================================== //
// Copyright 2016 Intel Corporation                                         //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "OSPRayFixture.h"

using namespace ospcommon;
using namespace ospray;

const static int DEFAULT_WIDTH = 1024;
const static int DEFAULT_HEIGHT = 1024;
const static size_t DEFAULT_BENCH_FRAMES = 100;
const static size_t DEFAULT_WARMUP_FRAMES = 10;

const static vec3f DEFAULT_BG_COLOR = {1.f, 1.f, 1.f};

namespace bench {
// helper function to write the rendered image as PPM file
void writePPM(const std::string &fileName, const int sizeX, const int sizeY,
              const uint32_t *pixel)
{
  FILE *file = fopen(fileName.c_str(), "wb");
  fprintf(file, "P6\n%i %i\n255\n", sizeX, sizeY);
  unsigned char *out = (unsigned char *)alloca(3*sizeX);
  for (int y = 0; y < sizeY; y++) {
    const unsigned char *in = (const unsigned char *)&pixel[(sizeY-1-y)*sizeX];
    for (int x = 0; x < sizeX; x++) {
      out[3*x + 0] = in[4*x + 0];
      out[3*x + 1] = in[4*x + 1];
      out[3*x + 2] = in[4*x + 2];
    }
    fwrite(out, 3*sizeX, sizeof(char), file);
  }
  fprintf(file, "\n");
  fclose(file);
}
}

OSPRayFixture::OSPRayFixture(cpp::Renderer r, cpp::Camera c, cpp::Model m)
  : renderer(r), camera(c), model(m), width(DEFAULT_WIDTH), height(DEFAULT_HEIGHT),
  defaultBenchFrames(DEFAULT_BENCH_FRAMES), defaultWarmupFrames(DEFAULT_WARMUP_FRAMES)
{
  setFrameBufferDims(width, height);
  renderer.set("world", model);
  renderer.set("model", model);
  renderer.set("camera", camera);
  renderer.commit();
}
pico_bench::Statistics<OSPRayFixture::Millis>
OSPRayFixture::benchmark(const size_t warmUpFrames, const size_t benchFrames) {
  const size_t warmup = warmUpFrames == 0 ? defaultWarmupFrames : warmUpFrames;
  const size_t bench = benchFrames == 0 ? defaultBenchFrames : benchFrames;
  for (size_t i = 0; i < warmup; ++i) {
    renderer.renderFrame(fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  }
  fb.clear(OSP_FB_ACCUM | OSP_FB_COLOR);

  auto benchmarker = pico_bench::Benchmarker<Millis>(bench);
  auto stats = benchmarker([&]() {
      renderer.renderFrame(fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  });
  stats.time_suffix = " ms";
  return stats;
}
void OSPRayFixture::saveImage(const std::string &fname) {
  auto *lfb = (uint32_t*)fb.map(OSP_FB_COLOR);
  bench::writePPM(fname + ".ppm", width, height, lfb);
  fb.unmap(lfb);
}
void OSPRayFixture::setFrameBufferDims(const int w, const int h) {
  width = w > 0 ? w : width;
  height = h > 0 ? h : height;

  fb = cpp::FrameBuffer(osp::vec2i{width, height}, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM);
  fb.clear(OSP_FB_ACCUM | OSP_FB_COLOR);

  camera.set("aspect", static_cast<float>(width) / height);
  camera.commit();
}

<|endoftext|>