<commit_before>#include "Players/CECP_Mediator.h"

#include <string>
#include <future>

#include "Game/Board.h"
#include "Game/Clock.h"
#include "Game/Game_Result.h"

#include "Moves/Move.h"

#include "Players/Player.h"

#include "Exceptions/Illegal_Move.h"
#include "Exceptions/Game_Ended.h"

#include "Utility/String.h"

CECP_Mediator::CECP_Mediator(const Player& local_player)
{
    std::string expected = "protover 2";
    if(receive_command() == expected)
    {
        send_command("feature "
                     "usermove=1 "
                     "sigint=0 "
                     "sigterm=0 "
                     "reuse=0 "
                     "myname=\"" + local_player.name() + "\" "
                     "name=1 "
                     "ping=1 "
                     "setboard=1 "
                     "colors=0 "
                     "done=1");
    }
    else
    {
        log("ERROR: Expected \"" + expected + "\"");
        throw std::runtime_error("Error in communicating with CECP program.");
    }
}

void CECP_Mediator::setup_turn(Board& board, Clock& clock)
{
    while(true)
    {
        auto command = receive_cecp_command(board, clock, false);
        if(command == "go")
        {
            set_indent_level(board.whose_turn() == WHITE ? 2 : 3);
            log("telling local AI to move at leisure and accepting move");
            in_force_mode = false;
            board.choose_move_at_leisure();
            return;
        }
        else if (String::starts_with(command, "setboard "))
        {
            auto fen = String::split(command, " ", 1).back();

            try
            {
                // Handle stateless GUIs that send the next board position
                // instead of a move.
                board.submit_move(board.create_move(fen));
                log("Derived move: " + board.game_record().back()->coordinate_move());
            }
            catch(const Illegal_Move&)
            {
                log("Rearranging board to: " + fen);
                board = Board(fen);
            }
        }
        else if(String::starts_with(command, "usermove "))
        {
            auto move = String::split(command).back();
            try
            {
                log("Applying move: " + move);
                auto result = board.submit_move(board.create_move(move));
                if(result.game_has_ended())
                {
                    report_end_of_game(result);
                }

                if( ! in_force_mode)
                {
                    set_indent_level(board.whose_turn() == WHITE ? 2 : 3);
                    log("Local AI now chooses a move");
                    board.choose_move_at_leisure();
                    return;
                }
            }
            catch(const Illegal_Move& e)
            {
                send_command("Illegal move (" + std::string(e.what()) + ") " + move);
            }
        }
        else if(String::starts_with(command, "time ") || String::starts_with(command, "otim "))
        {
            auto time = std::stod(String::split(command, " ")[1])/100; // time specified in centiseconds
            auto ai_color = board.whose_turn();
            auto clock_color = String::starts_with(command, "time ") ? ai_color : opposite(ai_color);
            clock.set_time(clock_color, time);
            log("setting " + color_text(clock_color) + "'s time to " + std::to_string(time) + " seconds.");
        }
    }
}

void CECP_Mediator::listen(Board& board, Clock& clock)
{
    last_listening_command = std::async(std::launch::async, &CECP_Mediator::listener, this, std::ref(board), std::ref(clock));
}

Game_Result CECP_Mediator::handle_move(Board& board, const Move& move)
{
    if(in_force_mode)
    {
        log("Ignoring move: " + move.coordinate_move());
        return {};
    }
    else
    {
        send_command("move " + move.coordinate_move());
        auto result = board.submit_move(move);
        if(result.game_has_ended())
        {
            report_end_of_game(result);
        }
        return result;
    }
}

bool CECP_Mediator::pondering_allowed() const
{
    return thinking_on_opponent_time;
}

std::string CECP_Mediator::receive_cecp_command(Board& board, Clock& clock, bool while_listening)
{
    while(true)
    {
        std::string command;
        if(while_listening)
        {
            command = receive_command();
        }
        else
        {
            command = last_listening_command.valid() ? last_listening_command.get() : receive_command();
        }

        if(String::starts_with(command, "ping "))
        {
            command[1] = 'o'; // change "ping" to "pong"
            send_command(command);
        }
        else if(String::starts_with(command, "result "))
        {
            auto result = String::split(command).at(1);
            auto reason = String::split(String::split(command, "{", 1)[1], "}", 1)[0];
            report_end_of_game(result, reason);
        }
        else if(command == "force")
        {
            board.pick_move_now();
            in_force_mode = true;
        }
        else if(String::starts_with(command, "level "))
        {
            log("got time specs: " + command);
            auto split = String::split(command);

            log("moves to reset clock = " + split[1]);
            auto reset_moves = String::string_to_size_t(split[1]);
            auto time_split = String::split(split[2], ":");
            auto game_time = 0;
            if(time_split.size() == 1)
            {
                log("game time = " + time_split[0] + " minutes");
                game_time = 60*std::stoi(time_split[0]);
            }
            else
            {
                log("game time = " + time_split[0] + " minutes and " + time_split[1] + " seconds");
                game_time = 60*std::stoi(time_split[0]) + std::stoi(time_split[1]);
            }

            log("increment = " + split[3]);
            auto increment = std::stod(split[3]);
            clock = Clock(game_time, reset_moves, increment, WHITE, false);
        }
        else if(String::starts_with(command, "st "))
        {
            log("got time specs: " + command);
            auto split = String::split(command);
            auto time_per_move = std::stoi(split[1]);
            auto reset_moves = 1;
            auto increment = 0;
            auto game_time = time_per_move;
            clock = Clock(game_time, reset_moves, increment, WHITE, false);
        }
        else if(command == "post")
        {
            if(board.thinking_mode() == CECP)
            {
                board.set_thinking_mode(NO_THINKING);
                log("Disabling thinking output for CECP");
            }
            else
            {
                board.set_thinking_mode(CECP);
                log("turning on thinking output for CECP");
            }
        }
        else if(command == "nopost")
        {
            board.set_thinking_mode(NO_THINKING);
            log("turning off thinking output for CECP");
        }
        else if(command == "easy")
        {
            log("Turning off pondering");
            thinking_on_opponent_time = false;
        }
        else if(command == "hard")
        {
            log("Turning on pondering");
            thinking_on_opponent_time = true;
        }
        else if(command == "new")
        {
            log("Setting board to standard start position and resetting clock");
            board = Board{};
            clock = Clock(clock.initial_time(), clock.moves_per_time_period(), clock.increment(WHITE), WHITE, false);
        }
        else if(String::starts_with(command, "name "))
        {
            set_other_player_name(String::split(command, " ", 1).back());
        }
        else
        {
            return command;
        }
    }
}

std::string CECP_Mediator::listener(Board& board, Clock& clock)
{
    while(true)
    {
        auto command = receive_cecp_command(board, clock, true);
        if(command == "?")
        {
            log("Forcing local AI to pick move and accepting it");
            board.pick_move_now();
        }
        else
        {
            return command;
        }
    }
}

void CECP_Mediator::report_end_of_game(const std::string& result, const std::string& reason) const
{
    send_command(result + " {" + reason + "}");
    throw Game_Ended();
}

void CECP_Mediator::report_end_of_game(const Game_Result& result) const
{
    report_end_of_game(result.game_ending_annotation(), result.ending_reason());
}
<commit_msg>Log all accepted commands<commit_after>#include "Players/CECP_Mediator.h"

#include <string>
#include <future>

#include "Game/Board.h"
#include "Game/Clock.h"
#include "Game/Game_Result.h"

#include "Moves/Move.h"

#include "Players/Player.h"

#include "Exceptions/Illegal_Move.h"
#include "Exceptions/Game_Ended.h"

#include "Utility/String.h"

CECP_Mediator::CECP_Mediator(const Player& local_player)
{
    std::string expected = "protover 2";
    if(receive_command() == expected)
    {
        send_command("feature "
                     "usermove=1 "
                     "sigint=0 "
                     "sigterm=0 "
                     "reuse=0 "
                     "myname=\"" + local_player.name() + "\" "
                     "name=1 "
                     "ping=1 "
                     "setboard=1 "
                     "colors=0 "
                     "done=1");
    }
    else
    {
        log("ERROR: Expected \"" + expected + "\"");
        throw std::runtime_error("Error in communicating with CECP program.");
    }
}

void CECP_Mediator::setup_turn(Board& board, Clock& clock)
{
    while(true)
    {
        auto command = receive_cecp_command(board, clock, false);
        if(command == "go")
        {
            set_indent_level(board.whose_turn() == WHITE ? 2 : 3);
            log("telling local AI to move at leisure and accepting move");
            in_force_mode = false;
            board.choose_move_at_leisure();
            return;
        }
        else if (String::starts_with(command, "setboard "))
        {
            auto fen = String::split(command, " ", 1).back();

            try
            {
                // Handle stateless GUIs that send the next board position
                // instead of a move.
                board.submit_move(board.create_move(fen));
                log("Derived move: " + board.game_record().back()->coordinate_move());
            }
            catch(const Illegal_Move&)
            {
                log("Rearranging board to: " + fen);
                board = Board(fen);
            }
        }
        else if(String::starts_with(command, "usermove "))
        {
            auto move = String::split(command).back();
            try
            {
                log("Applying move: " + move);
                auto result = board.submit_move(board.create_move(move));
                if(result.game_has_ended())
                {
                    report_end_of_game(result);
                }

                if( ! in_force_mode)
                {
                    set_indent_level(board.whose_turn() == WHITE ? 2 : 3);
                    log("Local AI now chooses a move");
                    board.choose_move_at_leisure();
                    return;
                }
            }
            catch(const Illegal_Move& e)
            {
                send_command("Illegal move (" + std::string(e.what()) + ") " + move);
            }
        }
        else if(String::starts_with(command, "time ") || String::starts_with(command, "otim "))
        {
            auto time = std::stod(String::split(command, " ")[1])/100; // time specified in centiseconds
            auto ai_color = board.whose_turn();
            auto clock_color = String::starts_with(command, "time ") ? ai_color : opposite(ai_color);
            clock.set_time(clock_color, time);
            log("setting " + color_text(clock_color) + "'s time to " + std::to_string(time) + " seconds.");
        }
    }
}

void CECP_Mediator::listen(Board& board, Clock& clock)
{
    last_listening_command = std::async(std::launch::async, &CECP_Mediator::listener, this, std::ref(board), std::ref(clock));
}

Game_Result CECP_Mediator::handle_move(Board& board, const Move& move)
{
    if(in_force_mode)
    {
        log("Ignoring move: " + move.coordinate_move());
        return {};
    }
    else
    {
        send_command("move " + move.coordinate_move());
        auto result = board.submit_move(move);
        if(result.game_has_ended())
        {
            report_end_of_game(result);
        }
        return result;
    }
}

bool CECP_Mediator::pondering_allowed() const
{
    return thinking_on_opponent_time;
}

std::string CECP_Mediator::receive_cecp_command(Board& board, Clock& clock, bool while_listening)
{
    while(true)
    {
        std::string command;
        if(while_listening)
        {
            command = receive_command();
        }
        else
        {
            command = last_listening_command.valid() ? last_listening_command.get() : receive_command();
        }

        if(String::starts_with(command, "ping "))
        {
            command[1] = 'o'; // change "ping" to "pong"
            send_command(command);
        }
        else if(String::starts_with(command, "result "))
        {
            auto result = String::split(command).at(1);
            auto reason = String::split(String::split(command, "{", 1)[1], "}", 1)[0];
            report_end_of_game(result, reason);
        }
        else if(command == "force")
        {
            log("Entering force mode");
            board.pick_move_now();
            in_force_mode = true;
        }
        else if(String::starts_with(command, "level "))
        {
            log("got time specs: " + command);
            auto split = String::split(command);

            log("moves to reset clock = " + split[1]);
            auto reset_moves = String::string_to_size_t(split[1]);
            auto time_split = String::split(split[2], ":");
            auto game_time = 0;
            if(time_split.size() == 1)
            {
                log("game time = " + time_split[0] + " minutes");
                game_time = 60*std::stoi(time_split[0]);
            }
            else
            {
                log("game time = " + time_split[0] + " minutes and " + time_split[1] + " seconds");
                game_time = 60*std::stoi(time_split[0]) + std::stoi(time_split[1]);
            }

            log("increment = " + split[3]);
            auto increment = std::stod(split[3]);
            clock = Clock(game_time, reset_moves, increment, WHITE, false);
        }
        else if(String::starts_with(command, "st "))
        {
            log("got time specs: " + command);
            auto split = String::split(command);
            auto time_per_move = std::stoi(split[1]);
            auto reset_moves = 1;
            auto increment = 0;
            auto game_time = time_per_move;
            clock = Clock(game_time, reset_moves, increment, WHITE, false);
        }
        else if(command == "post")
        {
            if(board.thinking_mode() == CECP)
            {
                board.set_thinking_mode(NO_THINKING);
                log("Disabling thinking output for CECP");
            }
            else
            {
                board.set_thinking_mode(CECP);
                log("turning on thinking output for CECP");
            }
        }
        else if(command == "nopost")
        {
            board.set_thinking_mode(NO_THINKING);
            log("turning off thinking output for CECP");
        }
        else if(command == "easy")
        {
            log("Turning off pondering");
            thinking_on_opponent_time = false;
        }
        else if(command == "hard")
        {
            log("Turning on pondering");
            thinking_on_opponent_time = true;
        }
        else if(command == "new")
        {
            log("Setting board to standard start position and resetting clock");
            board = Board{};
            clock = Clock(clock.initial_time(), clock.moves_per_time_period(), clock.increment(WHITE), WHITE, false);
        }
        else if(String::starts_with(command, "name "))
        {
            log("Getting other player's name");
            set_other_player_name(String::split(command, " ", 1).back());
        }
        else
        {
            return command;
        }
    }
}

std::string CECP_Mediator::listener(Board& board, Clock& clock)
{
    while(true)
    {
        auto command = receive_cecp_command(board, clock, true);
        if(command == "?")
        {
            log("Forcing local AI to pick move and accepting it");
            board.pick_move_now();
        }
        else
        {
            return command;
        }
    }
}

void CECP_Mediator::report_end_of_game(const std::string& result, const std::string& reason) const
{
    send_command(result + " {" + reason + "}");
    throw Game_Ended();
}

void CECP_Mediator::report_end_of_game(const Game_Result& result) const
{
    report_end_of_game(result.game_ending_annotation(), result.ending_reason());
}
<|endoftext|>


<commit_before>#include <efirc.h>

// TODO was das wieder?
IMPLEMENT_APP(Efirc)

using namespace std;

// Empfangene normale Nachrichten werden ausgegeben
void
irc_pmsg(const irc_msg_data *msg_data, void *cp)
{
    string text = msg_data->params_a[1];
    string recipient = msg_data->params_a[0];
    string user = msg_data->nick;

    // CTCP vorerst ignorieren
    if (text[0] != '\001')
    {
        if(recipient == irc->CurrentNick)
        {
            frame->add_message("[" + user + "] " + text);
        }
        else
        {
            frame->add_message("<" + user + "> " + text);
        }
    }
}

// Am Ende der Nachricht des Tages automatisch den in
// der Konfigurationsdatei genannten Kanal betreten
void
irc_endofmotd(const irc_msg_data *msg_data, void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *) cp;
    ircsocket->send_join(config->parsecfgvalue("irc_channel").c_str());
}

// Thema des Raums anzeigen lassen
void
irc_topic(const irc_msg_data *msg_data, void *cp)
{
    string topic = msg_data->params_a[2];
    frame->set_topic(topic);

}

void
irc_requestedtopic(const irc_msg_data *msg_data, void *cp)
{
    string topic = msg_data->params_a[1];
    frame->set_topic(topic);
}

// Benutzerliste einlesen
void
irc_userlist(const irc_msg_data *msg_data, void *cp)
{
    string benutzerliste;
    benutzerliste = msg_data->params_a[3];
    frame->add_user(benutzerliste);

    /*
    frame->add_message("(i) Folgende Benutzer sind zur Zeit im Raum: \n"
                       + benutzerliste);
    */
}

// Benutzerliste aktualisieren / Benutzer hat den Raum
// betreten
void
irc_join(const irc_msg_data *msg_data, void *cp)
{
    string benutzer;
    benutzer = msg_data->nick;
    frame->add_message("(i) " + benutzer + " hat den Raum betreten");

    if (benutzer == irc->CurrentNick)
    {
        irc->CurrentChannel = msg_data->params_a[0];
        frame->SetTitle(wxT(frame->parsecfgvalue("text_title")
                               + " - [ "
                               + irc->CurrentChannel + " ]"));
    }
    else
        // wenn selber, reicht irc_userlist() aus, da
        // neuer Channel und eventuell Operator
        frame->add_user(benutzer);
}

// Benutzerliste aktualisieren / Benutzer hat den Raum
// verlassen
void
irc_leave(const irc_msg_data *msg_data, void *cp)
{
    string benutzer;
    benutzer = msg_data->nick;
    frame->delete_user(benutzer);
    frame->add_message("(i) " + benutzer + " hat den Raum verlassen");
}

// Benutzerliste aktualisieren / Benutzer hat den Raum und
// das Netzwerk verlassen
void
irc_quit(const irc_msg_data *msg_data, void *cp)
{
    string benutzer, nachricht;
    benutzer = msg_data->nick;
    nachricht = msg_data->params_a[0];

    frame->delete_user(benutzer);
    frame->add_message("(i) " + benutzer + " ist gegangen: "
                       + nachricht);
}

// Benutzerliste aktualisieren / Benutzer hat seinen
//  Nickname geaendert
void
irc_changenick(const irc_msg_data *msg_data, void *cp)
{
    string alternick, neuernick;
    alternick = msg_data->nick;
    neuernick = msg_data->params_a[0];
    frame->change_nick(alternick + " -> " + neuernick);

    if (alternick == irc->CurrentNick)
        irc->CurrentNick = neuernick;
}

void
irc_pong(const irc_msg_data *msg_data, void *cp)
{
    irc->send_pong(msg_data->params_a[0]);
}

void
irc_kick(const irc_msg_data *msg_data, void *cp)
{
    string benutzer,sender;
    sender = msg_data->nick;
    benutzer = msg_data->params_a[1];
    if(benutzer == irc->CurrentNick)
    {
        frame->add_message("(i) Sie wurden von "
        + sender + "aus dem Raum geworfen");

        frame->clear_userlist();
        frame->set_topic("");
        frame->SetTitle(wxT(frame->parsecfgvalue("text_title")));
    }
    else
    {
        frame->delete_user(benutzer);
        frame->add_message("(i) " + benutzer + " wurde von "
        + sender + " aus dem Raum geworfen");
    }
}

void
irc_nickinuse(const irc_msg_data *msg_data, void *cp)
{
    frame->add_message("(i) Nickname wird bereits verwendet");

    // Nickname erneuern
    // aktuellen Nickname uebergeben
    config->reset_nickname(irc->CurrentNick);
    // neuen Nicknamen auslesen
    irc->CurrentNick = config->parsecfgvalue("irc_nickname");
    frame->add_message("(i) Sie sind jetzt bekannt als "
                    + config->parsecfgvalue("irc_nickname"));

    irc->send_nick(config->parsecfgvalue("irc_nickname").c_str());
}

void
irc_error(const irc_msg_data *msg_data, void *cp)
{
    string text = msg_data->params_a[2];
    frame->add_message("(!) " + text);
}

// Thread fuer recv_raw-Schleife
void
recv_thread(void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *)cp;
    ircsocket->recv_raw();
}

// Abarbeitung der Befehlsschlange
void
call_thread(void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *)cp;
    ircsocket->call_cmd();
}

void
connect_thread(void *cp)
{
    irc->connect();

    // Wer sagt mir, dass der Nick verfuegbar ist???
    irc->CurrentNick = config->parsecfgvalue("irc_nickname");
    irc->CurrentChannel = config->parsecfgvalue("irc_channel");

    // Ereignisverknpfung
    // TODO wirklich Ereignisse implementieren
    irc->add_link("PRIVMSG", &irc_pmsg);
    irc->add_link("376", &irc_endofmotd);
    irc->add_link("332", &irc_topic);
    irc->add_link("TOPIC", &irc_requestedtopic);
    irc->add_link("353", &irc_userlist);
    irc->add_link("JOIN", &irc_join);
    irc->add_link("PART", &irc_leave);
    irc->add_link("QUIT", &irc_quit);
    irc->add_link("NICK", &irc_changenick);
    irc->add_link("PING", &irc_pong);
    irc->add_link("KICK", &irc_kick);
    irc->add_link("433", &irc_nickinuse);

    //Fehler Antworten
    irc->add_link("401", &irc_error);
    irc->add_link("402", &irc_error);
    irc->add_link("403", &irc_error);
    irc->add_link("404", &irc_error);
    irc->add_link("405", &irc_error);
    irc->add_link("406", &irc_error);
    irc->add_link("407", &irc_error);
    irc->add_link("409", &irc_error);
    irc->add_link("411", &irc_error);
    irc->add_link("412", &irc_error);
    irc->add_link("413", &irc_error);
    irc->add_link("414", &irc_error);
    irc->add_link("421", &irc_error);
    irc->add_link("422", &irc_error);
    irc->add_link("423", &irc_error);
    irc->add_link("424", &irc_error);
    irc->add_link("431", &irc_error);
    irc->add_link("432", &irc_error);
    irc->add_link("433", &irc_error);
    irc->add_link("436", &irc_error);
    irc->add_link("441", &irc_error);
    irc->add_link("442", &irc_error);
    irc->add_link("443", &irc_error);
    irc->add_link("444", &irc_error);
    irc->add_link("445", &irc_error);
    irc->add_link("446", &irc_error);
    irc->add_link("451", &irc_error);
    irc->add_link("461", &irc_error);
    irc->add_link("462", &irc_error);
    irc->add_link("463", &irc_error);
    irc->add_link("464", &irc_error);
    irc->add_link("465", &irc_error);
    irc->add_link("467", &irc_error);
    irc->add_link("471", &irc_error);
    irc->add_link("472", &irc_error);
    irc->add_link("473", &irc_error);
    irc->add_link("474", &irc_error);
    irc->add_link("475", &irc_error);
    irc->add_link("481", &irc_error);
    irc->add_link("482", &irc_error);
    irc->add_link("483", &irc_error);
    irc->add_link("491", &irc_error);
    irc->add_link("501", &irc_error);
    irc->add_link("502", &irc_error);

    _beginthread(recv_thread, 0, irc);
    _beginthread(call_thread, 0, irc);
}

bool
Efirc::OnInit()
{
    frame = new UserInterface(NULL);
    frame->Show();

    config = new ConfigInterface();

    WSADATA wsaData;

    // TODO nach irc (class)
    if (WSAStartup(MAKEWORD(1, 1), &wsaData))
        frame->add_message("(i) Failed to initialise winsock!");

    irc = new IRCInterface(config->parsecfgvalue("irc_port"),
                           config->parsecfgvalue("irc_server"),
                           config->parsecfgvalue("irc_nickname"),
                           config->parsecfgvalue("irc_username"),
                           config->parsecfgvalue("irc_realname"),
                           "pass");

    _beginthread(connect_thread, 0, NULL);

    frame->irc = irc;

    return true;
}

int
Efirc::OnExit()
{
    WSACleanup();

    return 0;
}
<commit_msg><commit_after>#include <efirc.h>

// TODO was das wieder?
IMPLEMENT_APP(Efirc)

using namespace std;

// Empfangene normale Nachrichten werden ausgegeben
void
irc_pmsg(const irc_msg_data *msg_data, void *cp)
{
    string text = msg_data->params_a[1];
    string recipient = msg_data->params_a[0];
    string user = msg_data->nick;

    // CTCP vorerst ignorieren
    if (text[0] != '\001')
    {
        if(recipient == irc->CurrentNick)
        {
            frame->add_message("[" + user + "] " + text);
        }
        else
        {
            frame->add_message("<" + user + "> " + text);
        }
    }
}

// Am Ende der Nachricht des Tages automatisch den in
// der Konfigurationsdatei genannten Kanal betreten
void
irc_endofmotd(const irc_msg_data *msg_data, void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *) cp;
    ircsocket->send_join(config->parsecfgvalue("irc_channel").c_str());
}

// Thema des Raums anzeigen lassen
void
irc_topic(const irc_msg_data *msg_data, void *cp)
{
    string topic = msg_data->params_a[2];
    frame->set_topic(topic);

}

void
irc_requestedtopic(const irc_msg_data *msg_data, void *cp)
{
    string topic = msg_data->params_a[1];
    frame->set_topic(topic);
}

// Benutzerliste einlesen
void
irc_userlist(const irc_msg_data *msg_data, void *cp)
{
    string benutzerliste;
    benutzerliste = msg_data->params_a[3];
    frame->add_user(benutzerliste);

    /*
    frame->add_message("(i) Folgende Benutzer sind zur Zeit im Raum: \n"
                       + benutzerliste);
    */
}

// Benutzerliste aktualisieren / Benutzer hat den Raum
// betreten
void
irc_join(const irc_msg_data *msg_data, void *cp)
{
    string benutzer;
    benutzer = msg_data->nick;
    frame->add_message("(i) " + benutzer + " hat den Raum betreten");

    if (benutzer == irc->CurrentNick)
    {
        irc->CurrentChannel = msg_data->params_a[0];
        frame->SetTitle(wxT(frame->parsecfgvalue("text_title")
                               + " - [ "
                               + irc->CurrentChannel + " ]"));
    }
    else
        // wenn selber, reicht irc_userlist() aus, da
        // neuer Channel und eventuell Operator
        frame->add_user(benutzer);
}

// Benutzerliste aktualisieren / Benutzer hat den Raum
// verlassen
void
irc_leave(const irc_msg_data *msg_data, void *cp)
{
    string benutzer;
    benutzer = msg_data->nick;
    frame->delete_user(benutzer);
    frame->add_message("(i) " + benutzer + " hat den Raum verlassen");
}

// Benutzerliste aktualisieren / Benutzer hat den Raum und
// das Netzwerk verlassen
void
irc_quit(const irc_msg_data *msg_data, void *cp)
{
    string benutzer, nachricht;
    benutzer = msg_data->nick;
    nachricht = msg_data->params_a[0];

    frame->delete_user(benutzer);
    frame->add_message("(i) " + benutzer + " ist gegangen: "
                       + nachricht);
}

// Benutzerliste aktualisieren / Benutzer hat seinen
//  Nickname geaendert
void
irc_changenick(const irc_msg_data *msg_data, void *cp)
{
    string alternick, neuernick;
    alternick = msg_data->nick;
    neuernick = msg_data->params_a[0];
    frame->change_nick(alternick + " -> " + neuernick);

    if (alternick == irc->CurrentNick)
        irc->CurrentNick = neuernick;
}

void
irc_pong(const irc_msg_data *msg_data, void *cp)
{
    irc->send_pong(msg_data->params_a[0]);
}

void
irc_kick(const irc_msg_data *msg_data, void *cp)
{
    string benutzer,sender;
    sender = msg_data->nick;
    benutzer = msg_data->params_a[1];
    if(benutzer == irc->CurrentNick)
    {
        frame->add_message("(i) Sie wurden von "
        + sender + "aus dem Raum geworfen");

        frame->clear_userlist();
        frame->set_topic("");
        frame->SetTitle(wxT(frame->parsecfgvalue("text_title")));
    }
    else
    {
        frame->delete_user(benutzer);
        frame->add_message("(i) " + benutzer + " wurde von "
        + sender + " aus dem Raum geworfen");
    }
}

void
irc_nickinuse(const irc_msg_data *msg_data, void *cp)
{
    frame->add_message("(i) Nickname wird bereits verwendet");

    // Nickname erneuern
    // aktuellen Nickname uebergeben
    config->reset_nickname(irc->CurrentNick);
    // neuen Nicknamen auslesen
    irc->CurrentNick = config->parsecfgvalue("irc_nickname");
    frame->add_message("(i) Sie sind jetzt bekannt als "
                    + config->parsecfgvalue("irc_nickname"));

    irc->send_nick(config->parsecfgvalue("irc_nickname").c_str());
}

void
irc_error(const irc_msg_data *msg_data, void *cp)
{
    string text = msg_data->params_a[2];
    frame->add_message("(!) " + text);
}

// Thread fuer recv_raw-Schleife
void
recv_thread(void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *)cp;
    ircsocket->recv_raw();
}

// Abarbeitung der Befehlsschlange
void
call_thread(void *cp)
{
    IRCSocket *ircsocket = (IRCSocket *)cp;
    ircsocket->call_cmd();
}

void
connect_thread(void *cp)
{
    irc->connect();

    // Wer sagt mir, dass der Nick verfuegbar ist???
    irc->CurrentNick = config->parsecfgvalue("irc_nickname");
    irc->CurrentChannel = config->parsecfgvalue("irc_channel");

    // Ereignisverknpfung
    // TODO wirklich Ereignisse implementieren
    irc->add_link("PRIVMSG", &irc_pmsg);
    irc->add_link("376", &irc_endofmotd);
    irc->add_link("332", &irc_topic);
    irc->add_link("TOPIC", &irc_requestedtopic);
    irc->add_link("353", &irc_userlist);
    irc->add_link("JOIN", &irc_join);
    irc->add_link("PART", &irc_leave);
    irc->add_link("QUIT", &irc_quit);
    irc->add_link("NICK", &irc_changenick);
    irc->add_link("PING", &irc_pong);
    irc->add_link("KICK", &irc_kick);

    //Fehler Antworten
    irc->add_link("401", &irc_error);
    irc->add_link("402", &irc_error);
    irc->add_link("403", &irc_error);
    irc->add_link("404", &irc_error);
    irc->add_link("405", &irc_error);
    irc->add_link("406", &irc_error);
    irc->add_link("407", &irc_error);
    irc->add_link("409", &irc_error);
    irc->add_link("411", &irc_error);
    irc->add_link("412", &irc_error);
    irc->add_link("413", &irc_error);
    irc->add_link("414", &irc_error);
    irc->add_link("421", &irc_error);
    irc->add_link("422", &irc_error);
    irc->add_link("423", &irc_error);
    irc->add_link("424", &irc_error);
    irc->add_link("431", &irc_error);
    irc->add_link("432", &irc_error);
    irc->add_link("433", &irc_nickinuse);
    irc->add_link("436", &irc_error);
    irc->add_link("441", &irc_error);
    irc->add_link("442", &irc_error);
    irc->add_link("443", &irc_error);
    irc->add_link("444", &irc_error);
    irc->add_link("445", &irc_error);
    irc->add_link("446", &irc_error);
    irc->add_link("451", &irc_error);
    irc->add_link("461", &irc_error);
    irc->add_link("462", &irc_error);
    irc->add_link("463", &irc_error);
    irc->add_link("464", &irc_error);
    irc->add_link("465", &irc_error);
    irc->add_link("467", &irc_error);
    irc->add_link("471", &irc_error);
    irc->add_link("472", &irc_error);
    irc->add_link("473", &irc_error);
    irc->add_link("474", &irc_error);
    irc->add_link("475", &irc_error);
    irc->add_link("481", &irc_error);
    irc->add_link("482", &irc_error);
    irc->add_link("483", &irc_error);
    irc->add_link("491", &irc_error);
    irc->add_link("501", &irc_error);
    irc->add_link("502", &irc_error);

    _beginthread(recv_thread, 0, irc);
    _beginthread(call_thread, 0, irc);
}

bool
Efirc::OnInit()
{
    frame = new UserInterface(NULL);
    frame->Show();

    config = new ConfigInterface();

    WSADATA wsaData;

    // TODO nach irc (class)
    if (WSAStartup(MAKEWORD(1, 1), &wsaData))
        frame->add_message("(i) Failed to initialise winsock!");

    irc = new IRCInterface(config->parsecfgvalue("irc_port"),
                           config->parsecfgvalue("irc_server"),
                           config->parsecfgvalue("irc_nickname"),
                           config->parsecfgvalue("irc_username"),
                           config->parsecfgvalue("irc_realname"),
                           "pass");

    _beginthread(connect_thread, 0, NULL);

    frame->irc = irc;

    return true;
}

int
Efirc::OnExit()
{
    WSACleanup();

    return 0;
}
<|endoftext|>


<commit_before>#include "engine.h"
#include <cstdint>
#include <string>
#include <vector>

// gray all percent
uint_fast32_t Engine::GrayAllPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < pixCount; i++) {
        if (pixDiff > GrayDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / pixCount;
}

// gray mask percent
uint_fast32_t Engine::GrayMaskPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < pixCount; i++) {
        if (bitsetVec[i] == 0 || pixDiff > GrayDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / bitsetCount;
}

// gray regions percent
std::vector<uint_fast32_t> Engine::GrayRegionsPercent(const uint_fast32_t pixCount, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<uint_fast32_t> percentResultVec(regionsLen, 0);
    for (uint_fast32_t i = 0, r = 0; i < pixCount; i++) {
        uint_fast32_t diff = GrayDiff(buf0, buf1, i);
        if (minDiff > diff) continue;
        for (r = 0; r < regionsLen; r++) {
            if (regionsVec[r].bitset[i] == 0 || regionsVec[r].pixDiff > diff) continue;
            percentResultVec[r]++;
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        percentResultVec[r] = percentResultVec[r] * 100 / regionsVec[r].bitsetCount;
    }
    return percentResultVec;
}

// rgb all percent
uint_fast32_t Engine::RgbAllPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < bufLen; i += pixDepth) {
        if (pixDiff > RgbDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / pixCount;
}

// rgb mask percent
uint_fast32_t Engine::RgbMaskPercent(const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0, p = 0; i < bufLen; i += pixDepth, p++) {
        if (bitsetVec[p] == 0 || pixDiff > RgbDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / bitsetCount;
}

// rgb regions percent
std::vector<uint_fast32_t> Engine::RgbRegionsPercent(const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<uint_fast32_t> percentResultVec(regionsLen, 0);
    for (uint_fast32_t i = 0, p = 0, r = 0; i < bufLen; i += pixDepth, p++) {
        uint_fast32_t diff = RgbDiff(buf0, buf1, i);
        if (minDiff > diff) continue;
        for (r = 0; r < regionsLen; r++) {
            if (regionsVec[r].bitset[p] == 0 || regionsVec[r].pixDiff > diff) continue;
            percentResultVec[r]++;
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        percentResultVec[r] = percentResultVec[r] * 100 / regionsVec[r].bitsetCount;
    }
    return percentResultVec;
}

// gray all bounds
Engine::BoundsResult Engine::GrayAllBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            if (pixDiff > GrayDiff(buf0, buf1, i)) continue;
            if (x > maxX) maxX = x;
            if (y > maxY) maxY = y;
            if (x < minX) minX = x;
            if (y < minY) minY = y;
            //minX = MinUint(minX, x);
            //maxX = MaxUint(maxX, x);
            //minY = MinUint(minY, y);
            //maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / pixCount, minX, maxX, minY, maxY};
}

// gray mask bounds
Engine::BoundsResult Engine::GrayMaskBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            if (bitsetVec[i] == 0 || pixDiff > GrayDiff(buf0, buf1, i)) continue;
            if (x > maxX) maxX = x;
            if (y > maxY) maxY = y;
            if (x < minX) minX = x;
            if (y < minY) minY = y;
            //minX = MinUint(minX, x);
            //maxX = MaxUint(maxX, x);
            //minY = MinUint(minY, y);
            //maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / bitsetCount, minX, maxX, minY, maxY};
}

// gray regions bounds
std::vector<Engine::BoundsResult> Engine::GrayRegionsBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<Engine::BoundsResult> boundsResultVec(regionsLen, Engine::BoundsResult {0, width - 1 , 0, height - 1, 0});
    for (uint_fast32_t y = 0, x = 0, i = 0, r = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            uint_fast32_t diff = GrayDiff(buf0, buf1, i);
            if (minDiff > diff) continue;
            for (r = 0; r < regionsLen; r++) {
                if (regionsVec[r].bitset[i] == 0 || regionsVec[r].pixDiff > diff) continue;
                boundsResultVec[r].minX = MinUint(boundsResultVec[r].minX, x);
                boundsResultVec[r].maxX = MaxUint(boundsResultVec[r].maxX, x);
                boundsResultVec[r].minY = MinUint(boundsResultVec[r].minY, y);
                boundsResultVec[r].maxY = MaxUint(boundsResultVec[r].maxY, y);
                boundsResultVec[r].percent++;
            }
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        boundsResultVec[r].percent = boundsResultVec[r].percent * 100 / regionsVec[r].bitsetCount;
    }
    return boundsResultVec;
}

// rgb all bounds
Engine::BoundsResult Engine::RgbAllBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixCount, const uint_fast32_t pixDepth, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth) {
            if (pixDiff > RgbDiff(buf0, buf1, i)) continue;
            minX = MinUint(minX, x);
            maxX = MaxUint(maxX, x);
            minY = MinUint(minY, y);
            maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / pixCount, minX, maxX, minY, maxY};
}

// rgb mask bounds
Engine::BoundsResult Engine::RgbMaskBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDepth, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0, p = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth, p++) {
            if (bitsetVec[p] == 0 || pixDiff > RgbDiff(buf0, buf1, i)) continue;
            minX = MinUint(minX, x);
            maxX = MaxUint(maxX, x);
            minY = MinUint(minY, y);
            maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / bitsetCount, minX, maxX, minY, maxY};
}

// rgb regions bounds
std::vector<Engine::BoundsResult> Engine::RgbRegionsBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDepth, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<Engine::BoundsResult> boundsResultVec(regionsLen, Engine::BoundsResult {0, width - 1 , 0, height - 1, 0});
    for (uint_fast32_t y = 0, x = 0, i = 0, p = 0, r = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth, p++) {
            uint_fast32_t diff = RgbDiff(buf0, buf1, i);
            if (minDiff > diff) continue;
            for (r = 0; r < regionsLen; r++) {
                if (regionsVec[r].bitset[p] == 0 || regionsVec[r].pixDiff > diff) continue;
                boundsResultVec[r].minX = MinUint(boundsResultVec[r].minX, x);
                boundsResultVec[r].maxX = MaxUint(boundsResultVec[r].maxX, x);
                boundsResultVec[r].minY = MinUint(boundsResultVec[r].minY, y);
                boundsResultVec[r].maxY = MaxUint(boundsResultVec[r].maxY, y);
                boundsResultVec[r].percent++;
            }
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        boundsResultVec[r].percent = boundsResultVec[r].percent * 100 / regionsVec[r].bitsetCount;
    }
    return boundsResultVec;
}

// if (x > maxX) maxX = x;
// if (y > maxY) maxY = y;
// if (x < minX) minX = x;
// if (y < minY) minY = y;<commit_msg>test bounds<commit_after>#include "engine.h"
#include <cstdint>
#include <string>
#include <vector>

// gray all percent
uint_fast32_t Engine::GrayAllPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < pixCount; i++) {
        if (pixDiff > GrayDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / pixCount;
}

// gray mask percent
uint_fast32_t Engine::GrayMaskPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < pixCount; i++) {
        if (bitsetVec[i] == 0 || pixDiff > GrayDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / bitsetCount;
}

// gray regions percent
std::vector<uint_fast32_t> Engine::GrayRegionsPercent(const uint_fast32_t pixCount, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<uint_fast32_t> percentResultVec(regionsLen, 0);
    for (uint_fast32_t i = 0, r = 0; i < pixCount; i++) {
        uint_fast32_t diff = GrayDiff(buf0, buf1, i);
        if (minDiff > diff) continue;
        for (r = 0; r < regionsLen; r++) {
            if (regionsVec[r].bitset[i] == 0 || regionsVec[r].pixDiff > diff) continue;
            percentResultVec[r]++;
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        percentResultVec[r] = percentResultVec[r] * 100 / regionsVec[r].bitsetCount;
    }
    return percentResultVec;
}

// rgb all percent
uint_fast32_t Engine::RgbAllPercent(const uint_fast32_t pixCount, const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0; i < bufLen; i += pixDepth) {
        if (pixDiff > RgbDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / pixCount;
}

// rgb mask percent
uint_fast32_t Engine::RgbMaskPercent(const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t diffs = 0;
    for (uint_fast32_t i = 0, p = 0; i < bufLen; i += pixDepth, p++) {
        if (bitsetVec[p] == 0 || pixDiff > RgbDiff(buf0, buf1, i)) continue;
        diffs++;
    }
    return 100 * diffs / bitsetCount;
}

// rgb regions percent
std::vector<uint_fast32_t> Engine::RgbRegionsPercent(const uint_fast32_t pixDepth, const uint_fast32_t bufLen, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<uint_fast32_t> percentResultVec(regionsLen, 0);
    for (uint_fast32_t i = 0, p = 0, r = 0; i < bufLen; i += pixDepth, p++) {
        uint_fast32_t diff = RgbDiff(buf0, buf1, i);
        if (minDiff > diff) continue;
        for (r = 0; r < regionsLen; r++) {
            if (regionsVec[r].bitset[p] == 0 || regionsVec[r].pixDiff > diff) continue;
            percentResultVec[r]++;
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        percentResultVec[r] = percentResultVec[r] * 100 / regionsVec[r].bitsetCount;
    }
    return percentResultVec;
}

// gray all bounds
Engine::BoundsResult Engine::GrayAllBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixCount, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            if (pixDiff > GrayDiff(buf0, buf1, i)) continue;
            if (x < minX) {
                minX = x;
            } else if (x > maxX) {
                maxX = x;
            }
            if (y < minY) {
                minY = y;
            } else if (y > maxY) {
                maxY = y;
            }
            //minX = MinUint(minX, x);
            //maxX = MaxUint(maxX, x);
            //minY = MinUint(minY, y);
            //maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / pixCount, minX, maxX, minY, maxY};
}

// gray mask bounds
Engine::BoundsResult Engine::GrayMaskBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            if (bitsetVec[i] == 0 || pixDiff > GrayDiff(buf0, buf1, i)) continue;
            minX = MinUint(minX, x);
            maxX = MaxUint(maxX, x);
            minY = MinUint(minY, y);
            maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / bitsetCount, minX, maxX, minY, maxY};
}

// gray regions bounds
std::vector<Engine::BoundsResult> Engine::GrayRegionsBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<Engine::BoundsResult> boundsResultVec(regionsLen, Engine::BoundsResult {0, width - 1 , 0, height - 1, 0});
    for (uint_fast32_t y = 0, x = 0, i = 0, r = 0; y < height; y++) {
        for (x = 0; x < width; x++, i++) {
            uint_fast32_t diff = GrayDiff(buf0, buf1, i);
            if (minDiff > diff) continue;
            for (r = 0; r < regionsLen; r++) {
                if (regionsVec[r].bitset[i] == 0 || regionsVec[r].pixDiff > diff) continue;
                boundsResultVec[r].minX = MinUint(boundsResultVec[r].minX, x);
                boundsResultVec[r].maxX = MaxUint(boundsResultVec[r].maxX, x);
                boundsResultVec[r].minY = MinUint(boundsResultVec[r].minY, y);
                boundsResultVec[r].maxY = MaxUint(boundsResultVec[r].maxY, y);
                boundsResultVec[r].percent++;
            }
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        boundsResultVec[r].percent = boundsResultVec[r].percent * 100 / regionsVec[r].bitsetCount;
    }
    return boundsResultVec;
}

// rgb all bounds
Engine::BoundsResult Engine::RgbAllBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixCount, const uint_fast32_t pixDepth, const uint_fast32_t pixDiff, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth) {
            if (pixDiff > RgbDiff(buf0, buf1, i)) continue;
            minX = MinUint(minX, x);
            maxX = MaxUint(maxX, x);
            minY = MinUint(minY, y);
            maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / pixCount, minX, maxX, minY, maxY};
}

// rgb mask bounds
Engine::BoundsResult Engine::RgbMaskBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDepth, const uint_fast32_t pixDiff, const uint_fast32_t bitsetCount, const std::vector<bool> &bitsetVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    uint_fast32_t minX = width - 1, maxX = 0, minY = height - 1, maxY = 0, diffs = 0;
    for (uint_fast32_t y = 0, x = 0, i = 0, p = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth, p++) {
            if (bitsetVec[p] == 0 || pixDiff > RgbDiff(buf0, buf1, i)) continue;
            minX = MinUint(minX, x);
            maxX = MaxUint(maxX, x);
            minY = MinUint(minY, y);
            maxY = MaxUint(maxY, y);
            diffs++;
        }
    }
    return Engine::BoundsResult {100 * diffs / bitsetCount, minX, maxX, minY, maxY};
}

// rgb regions bounds
std::vector<Engine::BoundsResult> Engine::RgbRegionsBounds(const uint_fast32_t width, const uint_fast32_t height, const uint_fast32_t pixDepth, const uint_fast32_t minDiff, const uint_fast32_t regionsLen, const std::vector<Engine::Region> &regionsVec, const uint_fast8_t *buf0, const uint_fast8_t *buf1) {
    std::vector<Engine::BoundsResult> boundsResultVec(regionsLen, Engine::BoundsResult {0, width - 1 , 0, height - 1, 0});
    for (uint_fast32_t y = 0, x = 0, i = 0, p = 0, r = 0; y < height; y++) {
        for (x = 0; x < width; x++, i += pixDepth, p++) {
            uint_fast32_t diff = RgbDiff(buf0, buf1, i);
            if (minDiff > diff) continue;
            for (r = 0; r < regionsLen; r++) {
                if (regionsVec[r].bitset[p] == 0 || regionsVec[r].pixDiff > diff) continue;
                boundsResultVec[r].minX = MinUint(boundsResultVec[r].minX, x);
                boundsResultVec[r].maxX = MaxUint(boundsResultVec[r].maxX, x);
                boundsResultVec[r].minY = MinUint(boundsResultVec[r].minY, y);
                boundsResultVec[r].maxY = MaxUint(boundsResultVec[r].maxY, y);
                boundsResultVec[r].percent++;
            }
        }
    }
    for (uint_fast32_t r = 0; r < regionsLen; r++) {
        boundsResultVec[r].percent = boundsResultVec[r].percent * 100 / regionsVec[r].bitsetCount;
    }
    return boundsResultVec;
}

// if (x > maxX) maxX = x;
// if (y > maxY) maxY = y;
// if (x < minX) minX = x;
// if (y < minY) minY = y;<|endoftext|>


<commit_before>//============================================================================
// Name        : Shader.cpp
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Shader
//============================================================================

#include "Shaders.h"
#include <stdlib.h>
#ifdef ANDROID
    #include <GLES2/gl2.h>
    #include <GLES2/gl2ext.h>
#else
    #include "GL/glew.h"
#endif
#include "../../Core/Buffers/FrameBuffer.h"

namespace p3d {

    Shader::Shader() {
    }
    Shader::Shader(uint32 type) {
        this->type = type;
    }

    Shader::~Shader() {}

    const uint32 &Shader::GetType() const
    {
        return type;
    }
    void Shader::loadShaderFile(const char* filename)
    {
        std::ifstream t(filename);
        std::string str;

        t.seekg(0, std::ios::end);
        str.reserve(t.tellg());
        t.seekg(0, std::ios::beg);

        str.assign((std::istreambuf_iterator<char>(t)),
        std::istreambuf_iterator<char>());

        shaderString = str.c_str();
    }

    void Shader::loadShaderText(const std::string &text)
    {
            shaderString = text;
    }

    void Shader::compileShader(uint32* ProgramObject)
    {

        std::string shaderType;

        switch (type) {
            case ShaderType::VertexShader:
                shader = glCreateShader(GL_VERTEX_SHADER);
                shaderType = "Vertex Shader";
                break;
            case ShaderType::FragmentShader:
                shader = glCreateShader(GL_FRAGMENT_SHADER);
                shaderType = "Fragment Shader";
                break;
            case ShaderType::GeometryShader:
                //shader = glCreateShader(GL_GEOMETRY_SHADER);
                shaderType = "Geometry Shader";
            break;
        }

        uint32 len = shaderString.length();

        // batatas because is a good example :P
        const char *batatas = shaderString.c_str();

        glShaderSource(shader,1,(const GLchar**) &batatas,(const GLint *)&len);
        glCompileShader(shader);

        GLint result, length = 0;

        glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
        if (result==GL_FALSE)
        {
            std::string log;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
            std::stringstream ss;//create a stringstream
            ss << length;
            echo(ss.str());
            if (length>0)
            {
                log.resize(length);
                glGetShaderInfoLog(shader, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" COMPILATION ERROR: ") + log.c_str()));
            }
        } else {
            std::string log;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
            std::stringstream ss;//create a stringstream
            ss << length;
            echo(ss.str());
            if (length>1)
            {
                log.resize(length);
                glGetShaderInfoLog(shader, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" COMPILED WITH WARNINGS: ") + log.c_str()));
            }
            if (*ProgramObject==0)
                *ProgramObject = (uint32)glCreateProgram();

            // Attach shader
            glAttachShader(*ProgramObject, shader);
            // Link Program
            glLinkProgram(*ProgramObject);
            // Get Linkage error
            glGetProgramiv(*ProgramObject, GL_LINK_STATUS, &result);
            if (result==GL_FALSE)
            {
                glGetProgramiv(*ProgramObject, GL_INFO_LOG_LENGTH, &length);
                log.resize(length);
                std::stringstream ss;//create a stringstream
                ss << length;
                echo(ss.str());
                glGetProgramInfoLog(*ProgramObject, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" LINK ERROR: ") + log.c_str()));
            }
        }
    }
    void Shader::DeleteShader(uint32 ProgramObject)
    {
        if (glIsProgram(ProgramObject)) {
            if (glIsShader(shader)) {
                glDetachShader(ProgramObject, shader);
                glDeleteShader(shader);
    //            std::cout << "Shader Destroyed: " << shader << std::endl;
            }
    //        else std::cout << "Shader Not Found: " << shader << std::endl;
        }
    //    else std::cout << "Shader Program Object Not Found: " << ProgramObject << std::endl;
    }
    void Shader::DeleteProgram(uint32* ProgramObject)
    {
        if (glIsProgram(*ProgramObject)) {
            glDeleteProgram(*ProgramObject);
    //      std::cout << "Shader Program Destroyed: " << *ProgramObject << std::endl;
            *ProgramObject = 0;
        }
    //    else std::cout << "Shader Program Object Not Found: " << *ProgramObject << std::endl;
    }

    // Get positions
    int32 Shader::GetUniformLocation(const uint32 &program, const std::string &name) {
        return glGetUniformLocation(program, name.c_str());
    }
    int32 Shader::GetAttributeLocation(const uint32 &program, const std::string &name) {
        return glGetAttribLocation(program, name.c_str());
    }

    void Shader::SendUniform(const Uniform::Uniform &uniform, const int32 &Handle)
    {
        if (Handle>-1 && uniform.ElementCount>0)
        switch(uniform.Type)
        {
            case Uniform::DataType::Int:
            {
                glUniform1iv(Handle,uniform.ElementCount,(int*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Float:
            {
                glUniform1fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec2:
            {
                glUniform2fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec3:
            {
                glUniform3fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec4:
            {
                glUniform4fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Matrix:
            {
                glUniformMatrix4fv(Handle,uniform.ElementCount,false,(f32*)&uniform.Value[0]);
                break;
            }
        }
    }

    void Shader::SendUniform(const Uniform::Uniform &uniform, void* data, const int32 &Handle, const uint32 &elementCount)
    {
        if (Handle>-1 && elementCount>0)
        {
            switch(uniform.Type)
            {
                case Uniform::DataType::Int:
                {
                    glUniform1iv(Handle,elementCount,(int*)data);
                    break;
                }
                case Uniform::DataType::Float:
                {
                    glUniform1fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec2:
                {
                    glUniform2fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec3:
                {
                    glUniform3fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec4:
                {
                    glUniform4fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Matrix:
                {
                    glUniformMatrix4fv(Handle,elementCount,false,(f32*)data);
                    break;
                }
            }
        }
    }
}
<commit_msg>Fix to last commit<commit_after>//============================================================================
// Name        : Shader.cpp
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Shader
//============================================================================

#include "Shaders.h"
#include <stdlib.h>
#ifdef ANDROID
    #include <GLES2/gl2.h>
    #include <GLES2/gl2ext.h>
#else
    #include "GL/glew.h"
#endif
#include "../../Core/Buffers/FrameBuffer.h"

namespace p3d {

    Shader::Shader() {
    }
    Shader::Shader(uint32 type) {
        this->type = type;
    }

    Shader::~Shader() {}

    const uint32 &Shader::GetType() const
    {
        return type;
    }
    void Shader::loadShaderFile(const char* filename)
    {
        std::ifstream t(filename);
        std::string str;

        t.seekg(0, std::ios::end);
        str.reserve(t.tellg());
        t.seekg(0, std::ios::beg);

        str.assign((std::istreambuf_iterator<char>(t)),
        std::istreambuf_iterator<char>());

        shaderString = str.c_str();
    }

    void Shader::loadShaderText(const std::string &text)
    {
        shaderString = text;
    }

    void Shader::compileShader(uint32* ProgramObject)
    {

        std::string shaderType;

        switch (type) {
            case ShaderType::VertexShader:
                shader = glCreateShader(GL_VERTEX_SHADER);
                shaderType = "Vertex Shader";
                break;
            case ShaderType::FragmentShader:
                shader = glCreateShader(GL_FRAGMENT_SHADER);
                shaderType = "Fragment Shader";
                break;
            case ShaderType::GeometryShader:
                //shader = glCreateShader(GL_GEOMETRY_SHADER);
                shaderType = "Geometry Shader";
            break;
        }

        uint32 len = shaderString.length();

        // batatas because is a good example :P
        const char *batatas = shaderString.c_str();

        glShaderSource(shader,1,(const GLchar**) &batatas,(const GLint *)&len);
        glCompileShader(shader);

        GLint result, length = 0;

        glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
        if (result==GL_FALSE)
        {
            std::string log;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
            if (length>0)
            {
                log.resize(length);
                glGetShaderInfoLog(shader, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" COMPILATION ERROR: ") + log.c_str()));
            }
        } else {
            std::string log;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
            if (length>0)
            {
                log.resize(length);
                glGetShaderInfoLog(shader, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" COMPILED WITH WARNINGS: ") + log.c_str()));
            }
            if (*ProgramObject==0)
                *ProgramObject = (uint32)glCreateProgram();

            // Attach shader
            glAttachShader(*ProgramObject, shader);
            // Link Program
            glLinkProgram(*ProgramObject);
            // Get Linkage error
            glGetProgramiv(*ProgramObject, GL_LINK_STATUS, &result);
            if (result==GL_FALSE)
            {
                glGetProgramiv(*ProgramObject, GL_INFO_LOG_LENGTH, &length);
                log.resize(length);
                glGetProgramInfoLog(*ProgramObject, length, &result, &log[0]);
                echo(std::string(shaderType.c_str() + std::string(" LINK ERROR: ") + log.c_str()));
            }
        }
    }
    void Shader::DeleteShader(uint32 ProgramObject)
    {
        if (glIsProgram(ProgramObject)) {
            if (glIsShader(shader)) {
                glDetachShader(ProgramObject, shader);
                glDeleteShader(shader);
    //            std::cout << "Shader Destroyed: " << shader << std::endl;
            }
    //        else std::cout << "Shader Not Found: " << shader << std::endl;
        }
    //    else std::cout << "Shader Program Object Not Found: " << ProgramObject << std::endl;
    }
    void Shader::DeleteProgram(uint32* ProgramObject)
    {
        if (glIsProgram(*ProgramObject)) {
            glDeleteProgram(*ProgramObject);
    //      std::cout << "Shader Program Destroyed: " << *ProgramObject << std::endl;
            *ProgramObject = 0;
        }
    //    else std::cout << "Shader Program Object Not Found: " << *ProgramObject << std::endl;
    }

    // Get positions
    int32 Shader::GetUniformLocation(const uint32 &program, const std::string &name) {
        return glGetUniformLocation(program, name.c_str());
    }
    int32 Shader::GetAttributeLocation(const uint32 &program, const std::string &name) {
        return glGetAttribLocation(program, name.c_str());
    }

    void Shader::SendUniform(const Uniform::Uniform &uniform, const int32 &Handle)
    {
        if (Handle>-1 && uniform.ElementCount>0)
        switch(uniform.Type)
        {
            case Uniform::DataType::Int:
            {
                glUniform1iv(Handle,uniform.ElementCount,(int*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Float:
            {
                glUniform1fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec2:
            {
                glUniform2fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec3:
            {
                glUniform3fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Vec4:
            {
                glUniform4fv(Handle,uniform.ElementCount,(f32*)&uniform.Value[0]);
                break;
            }
            case Uniform::DataType::Matrix:
            {
                glUniformMatrix4fv(Handle,uniform.ElementCount,false,(f32*)&uniform.Value[0]);
                break;
            }
        }
    }

    void Shader::SendUniform(const Uniform::Uniform &uniform, void* data, const int32 &Handle, const uint32 &elementCount)
    {
        if (Handle>-1 && elementCount>0)
        {
            switch(uniform.Type)
            {
                case Uniform::DataType::Int:
                {
                    glUniform1iv(Handle,elementCount,(int*)data);
                    break;
                }
                case Uniform::DataType::Float:
                {
                    glUniform1fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec2:
                {
                    glUniform2fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec3:
                {
                    glUniform3fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Vec4:
                {
                    glUniform4fv(Handle,elementCount,(f32*)data);
                    break;
                }
                case Uniform::DataType::Matrix:
                {
                    glUniformMatrix4fv(Handle,elementCount,false,(f32*)data);
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#include <babylon/samples/samples_index.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/core/string.h>
#include <babylon/interfaces/irenderable_scene.h>
#include <babylon/samples/animations/_animations_samples_index.h>
#include <babylon/samples/cameras/_cameras_samples_index.h>
#include <babylon/samples/collisionsandintersections/_collisions_and_intersections_samples_index.h>
#include <babylon/samples/extensions/_extensions_samples_index.h>
#include <babylon/samples/lights/_lights_samples_index.h>
#include <babylon/samples/loaders/_loaders_samples_index.h>
#include <babylon/samples/materials/_materials_samples_index.h>
#include <babylon/samples/materialslibrary/_materials_library_samples_index.h>
#include <babylon/samples/meshes/_meshes_samples_index.h>
#include <babylon/samples/optimizations/_optimizations_samples_index.h>
#include <babylon/samples/particles/_particles_samples_index.h>
#include <babylon/samples/proceduraltextureslibrary/_procedural_textures_library_samples_index.h>
#include <babylon/samples/shadows/_shadows_samples_index.h>
#include <babylon/samples/specialfx/_special_fx_samples_index.h>
#include <babylon/samples/textures/_textures_samples_index.h>

#include <nlohmann/json.hpp>
#include <iostream>
#include <fstream>

namespace BABYLON {
namespace Samples {

SamplesIndex::SamplesIndex()
{
  _samplesFailures = {
    {"BlurModeForMirrorsScene", SampleFailureReason::empty3d},
    {"ColoredRibbonScene", SampleFailureReason::outOfBoundAccess},
    {"CircleCurvesFromBeziersScene", SampleFailureReason::empty3d},
    {"EdgesRenderScene", SampleFailureReason::outOfBoundAccess},
    {"HighlightLayerScene", SampleFailureReason::incomplete3d},
    {"InnerMeshPointsScene", SampleFailureReason::outOfBoundAccess},
    {"LinesMeshSpiralScene", SampleFailureReason::empty3d},
    {"LorenzAttractorScene", SampleFailureReason::empty3d},
    {"MorphTargetsScene", SampleFailureReason::broken},
    {"MultiSampleRenderTargetsScene", SampleFailureReason::empty3d},
    {"PBRMaterialCheckerORMScene", SampleFailureReason::broken},
    {"PBRMaterialScene", SampleFailureReason::broken},
    {"PBRMetallicRoughnessGoldMaterialScene", SampleFailureReason::broken},
    {"PBRMetallicRoughnessMaterialScene", SampleFailureReason::outOfBoundAccess},
    {"PBRMetallicRoughnessTextureMaterialScene", SampleFailureReason::broken},
    {"ShaderMaterialWarpSpeedScene", SampleFailureReason::empty3d},
  };

  // Initialize the samples index
  _samplesIndex = {
    // Animations samples
    {_AnimationsSamplesIndex::CategoryName(), _AnimationsSamplesIndex()},
    // Cameras samples
    {_CamerasSamplesIndex::CategoryName(), _CamerasSamplesIndex()},
    // Collisions and Intersections samples
    {_CollisionsAndIntersectionsSamplesIndex::CategoryName(),
     _CollisionsAndIntersectionsSamplesIndex()},
    // Extensions samples
    {_ExtensionsSamplesIndex::CategoryName(), _ExtensionsSamplesIndex()},
    // Lights samples
    {_LightsSamplesIndex::CategoryName(), _LightsSamplesIndex()},
    // Loaders - babylon format
    {_LoadersBabylonSamplesIndex::CategoryName(),
     _LoadersBabylonSamplesIndex()},
#ifdef WITH_LOADERS
    // Loaders - glTF format
    {_LoadersGLTFSamplesIndex::CategoryName(), _LoadersGLTFSamplesIndex()},
#endif
    // Materials samples
    {_MaterialsSamplesIndex::CategoryName(), _MaterialsSamplesIndex()},
    // // Materials Library samples
    {_MaterialsLibrarySamplesIndex::CategoryName(),
     _MaterialsLibrarySamplesIndex()},
    // Meshes samples
    {_MeshesSamplesIndex::CategoryName(), _MeshesSamplesIndex()},
    // Optimizations samples
    {_OptimizationsSamplesIndex::CategoryName(), _OptimizationsSamplesIndex()},
    // Particles samples
    {_ParticlesSamplesIndex::CategoryName(), _ParticlesSamplesIndex()},
    // Procedural Textures Library samples
    {_ProceduralTexturesLibrarySamplesIndex::CategoryName(),
     _ProceduralTexturesLibrarySamplesIndex()},
    // Shadows samples
    {_ShadowsSamplesIndex::CategoryName(), _ShadowsSamplesIndex()},
    // Special FX samples
    {_SpecialFXSamplesIndex::CategoryName(), _SpecialFXSamplesIndex()},
    // Textures samples
    {_TexturesSamplesIndex::CategoryName(), _TexturesSamplesIndex()},
  };
}

SamplesIndex::~SamplesIndex()
{
}

bool SamplesIndex::isSampleEnabled(const std::string& sampleName) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return std::get<0>(item.second.samples().at(sampleName));
    }
  }

  return false;
}

std::optional<BABYLON::Samples::SampleFailureReason> SamplesIndex::doesSampleFail(const std::string& sampleName) const
{
  if (_samplesFailures.find(sampleName) == _samplesFailures.end())
    return std::nullopt;
  else
    return _samplesFailures.at(sampleName);
}

bool SamplesIndex::sampleExists(const std::string& sampleName) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return true;
    }
  }

  return false;
}

nlohmann::json ReadSampleInfoFile()
{
  std::ifstream is("samples_info.json");
  if (! is.good())
    is = std::ifstream("../samples_info.json");
  if (! is.good())
    is = std::ifstream("../../samples_info.json");
  if (is.good())
  {
    nlohmann::json j;
    is >> j;
    return j;
  }
  else
    return nlohmann::json();
}

SampleInfo SamplesIndex::getSampleInfo(const std::string& sampleName) const
{
  static nlohmann::json _samplesInfo = ReadSampleInfoFile();
  static std::map<std::string, SampleInfo> cache;
  if (cache.find(sampleName) != cache.end())
    return cache.at(sampleName);

  SampleInfo result;
  for (const auto & element : _samplesInfo)
  {
    if (element["sample_name"] == sampleName)
    {
      result.Brief = element["brief"];
      result.HeaderFile = element["header_file"];
      result.SourceFile = element["source_file"];
      for (const auto & link : element["links"])
      {
        result.Links.push_back(link);
      }
    }
  }
  cache[sampleName] = result;
  return result;
}

std::vector<std::string> SamplesIndex::getSampleNames() const
{
  // Extract the enabled sample names from the map
  std::vector<std::string> sampleNames;
  for (const auto& samplesCategory : _samplesIndex) {
    for (const auto& element : samplesCategory.second.samples()) {
      // Check if enabled
      if (std::get<0>(element.second)) {
        sampleNames.emplace_back(element.first);
      }
    }
  }

  // Sort the vector with sample names in ascending order
  std::sort(sampleNames.begin(), sampleNames.end());

  return sampleNames;
}

std::vector<std::string> SamplesIndex::getCategoryNames() const
{
  // Extract the category names
  auto categoryNames = stl_util::extract_keys(_samplesIndex);

  // Sort the vector with category names in ascending order
  std::sort(categoryNames.begin(), categoryNames.end());

  return categoryNames;
}

bool SamplesIndex::categoryExists(const std::string& categoryNameToSearch) const
{
  bool _categoryExists = false;

  // Extract the category names
  auto categoryNames = stl_util::extract_keys(_samplesIndex);

  // Search for sample
  for (const auto& categoryName : categoryNames) {
    if (categoryName == categoryNameToSearch) {
      _categoryExists = true;
      break;
    }
  }

  return _categoryExists;
}

std::vector<std::string>
SamplesIndex::getSampleNamesInCategory(const std::string& categoryName) const
{
  // Extract the enabled sample names for the given category from the map
  std::vector<std::string> sampleNames;
  if (stl_util::contains(_samplesIndex, categoryName)) {
    const auto& samplesCategory = _samplesIndex.at(categoryName);
    for (const auto& element : samplesCategory.samples()) {
      // Check if enabled
      if (std::get<0>(element.second)) {
        sampleNames.emplace_back(element.first);
      }
    }
  }

  // Sort the vector with sample names in ascending order
  std::sort(sampleNames.begin(), sampleNames.end());

  return sampleNames;
}

IRenderableScenePtr
SamplesIndex::createRenderableScene(const std::string& sampleName,
                                    ICanvas* iCanvas) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return std::get<1>(item.second.samples().at(sampleName))(iCanvas);
    }
  }

  return nullptr;
}

void SamplesIndex::listSamples()
{
  auto categories = getCategoryNames();
  for (const auto & category : categories)
  {
    std::cout << "********************************************" << "\n";
    std::cout << "Category: " << category << "\n";
    std::cout << "********************************************" << "\n";
    auto samples = getSampleNamesInCategory(category);
    for (const auto & sample : samples)
    {
      std::string ko = (!isSampleEnabled(sample)) ? " (KO)" : "";
      std::cout << sample << ko << "\n";
    }
  }
}

std::string SampleFailureReason_Str(SampleFailureReason s)
{
  switch (s) {
    case SampleFailureReason::blankDisplay:
      return "Blank display";
      break;
    case SampleFailureReason::outOfBoundAccess :
      return "Out of bounds access";
      break;
    case SampleFailureReason::processHung:
      return "Process hung";
      break;
    case SampleFailureReason::invalidComparator:
      return "Invalid comparator";
      break;
    case SampleFailureReason::vectorIteratorInvalid:
      return "vector iterators in range are from different containers";
      break;
    case SampleFailureReason::empty3d:
      return "3D rendering is empty";
      break;
    case SampleFailureReason::readAccessViolation:
      return "Read Access Violation";
      break;
    case SampleFailureReason::incomplete3d:
      return "Incomplete 3d (black textures and co)";
      break;
    case SampleFailureReason::broken:
      return "Broken (bad rendering and/or bad behavior)";
      break;
    default:
      throw "Unhandled enum!";
  }
}

} // end of namespace Samples
} // end of namespace BABYLON
<commit_msg>the samples index file is now using lower case<commit_after>#include <babylon/samples/samples_index.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/core/string.h>
#include <babylon/interfaces/irenderable_scene.h>
#include <babylon/samples/animations/_animations_samples_index.h>
#include <babylon/samples/cameras/_cameras_samples_index.h>
#include <babylon/samples/collisionsandintersections/_collisions_and_intersections_samples_index.h>
#include <babylon/samples/extensions/_extensions_samples_index.h>
#include <babylon/samples/lights/_lights_samples_index.h>
#include <babylon/samples/loaders/_loaders_samples_index.h>
#include <babylon/samples/materials/_materials_samples_index.h>
#include <babylon/samples/materialslibrary/_materials_library_samples_index.h>
#include <babylon/samples/meshes/_meshes_samples_index.h>
#include <babylon/samples/optimizations/_optimizations_samples_index.h>
#include <babylon/samples/particles/_particles_samples_index.h>
#include <babylon/samples/proceduraltextureslibrary/_procedural_textures_library_samples_index.h>
#include <babylon/samples/shadows/_shadows_samples_index.h>
#include <babylon/samples/specialfx/_special_fx_samples_index.h>
#include <babylon/samples/textures/_textures_samples_index.h>

#include <nlohmann/json.hpp>
#include <iostream>
#include <fstream>

namespace BABYLON {
namespace Samples {

SamplesIndex::SamplesIndex()
{
  _samplesFailures = {
    {"BlurModeForMirrorsScene", SampleFailureReason::empty3d},
    {"ColoredRibbonScene", SampleFailureReason::outOfBoundAccess},
    {"CircleCurvesFromBeziersScene", SampleFailureReason::empty3d},
    {"EdgesRenderScene", SampleFailureReason::outOfBoundAccess},
    {"HighlightLayerScene", SampleFailureReason::incomplete3d},
    {"InnerMeshPointsScene", SampleFailureReason::outOfBoundAccess},
    {"LinesMeshSpiralScene", SampleFailureReason::empty3d},
    {"LorenzAttractorScene", SampleFailureReason::empty3d},
    {"MorphTargetsScene", SampleFailureReason::broken},
    {"MultiSampleRenderTargetsScene", SampleFailureReason::empty3d},
    {"PBRMaterialCheckerORMScene", SampleFailureReason::broken},
    {"PBRMaterialScene", SampleFailureReason::broken},
    {"PBRMetallicRoughnessGoldMaterialScene", SampleFailureReason::broken},
    {"PBRMetallicRoughnessMaterialScene", SampleFailureReason::outOfBoundAccess},
    {"PBRMetallicRoughnessTextureMaterialScene", SampleFailureReason::broken},
    {"ShaderMaterialWarpSpeedScene", SampleFailureReason::empty3d},
  };

  // Initialize the samples index
  _samplesIndex = {
    // Animations samples
    {_AnimationsSamplesIndex::CategoryName(), _AnimationsSamplesIndex()},
    // Cameras samples
    {_CamerasSamplesIndex::CategoryName(), _CamerasSamplesIndex()},
    // Collisions and Intersections samples
    {_CollisionsAndIntersectionsSamplesIndex::CategoryName(),
     _CollisionsAndIntersectionsSamplesIndex()},
    // Extensions samples
    {_ExtensionsSamplesIndex::CategoryName(), _ExtensionsSamplesIndex()},
    // Lights samples
    {_LightsSamplesIndex::CategoryName(), _LightsSamplesIndex()},
    // Loaders - babylon format
    {_LoadersBabylonSamplesIndex::CategoryName(),
     _LoadersBabylonSamplesIndex()},
#ifdef WITH_LOADERS
    // Loaders - glTF format
    {_LoadersGLTFSamplesIndex::CategoryName(), _LoadersGLTFSamplesIndex()},
#endif
    // Materials samples
    {_MaterialsSamplesIndex::CategoryName(), _MaterialsSamplesIndex()},
    // // Materials Library samples
    {_MaterialsLibrarySamplesIndex::CategoryName(),
     _MaterialsLibrarySamplesIndex()},
    // Meshes samples
    {_MeshesSamplesIndex::CategoryName(), _MeshesSamplesIndex()},
    // Optimizations samples
    {_OptimizationsSamplesIndex::CategoryName(), _OptimizationsSamplesIndex()},
    // Particles samples
    {_ParticlesSamplesIndex::CategoryName(), _ParticlesSamplesIndex()},
    // Procedural Textures Library samples
    {_ProceduralTexturesLibrarySamplesIndex::CategoryName(),
     _ProceduralTexturesLibrarySamplesIndex()},
    // Shadows samples
    {_ShadowsSamplesIndex::CategoryName(), _ShadowsSamplesIndex()},
    // Special FX samples
    {_SpecialFXSamplesIndex::CategoryName(), _SpecialFXSamplesIndex()},
    // Textures samples
    {_TexturesSamplesIndex::CategoryName(), _TexturesSamplesIndex()},
  };
}

SamplesIndex::~SamplesIndex()
{
}

bool SamplesIndex::isSampleEnabled(const std::string& sampleName) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return std::get<0>(item.second.samples().at(sampleName));
    }
  }

  return false;
}

std::optional<BABYLON::Samples::SampleFailureReason> SamplesIndex::doesSampleFail(const std::string& sampleName) const
{
  if (_samplesFailures.find(sampleName) == _samplesFailures.end())
    return std::nullopt;
  else
    return _samplesFailures.at(sampleName);
}

bool SamplesIndex::sampleExists(const std::string& sampleName) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return true;
    }
  }

  return false;
}

nlohmann::json ReadSampleInfoFile()
{
  std::ifstream is("samples_info.json");
  if (! is.good())
    is = std::ifstream("../samples_info.json");
  if (! is.good())
    is = std::ifstream("../../samples_info.json");
  if (is.good())
  {
    nlohmann::json j;
    is >> j;
    return j;
  }
  else
    return nlohmann::json();
}

SampleInfo SamplesIndex::getSampleInfo(const std::string& sampleNameMixedCase) const
{
  static nlohmann::json _samplesInfo = ReadSampleInfoFile();
  static std::map<std::string, SampleInfo> cache;

  std::string sampleNameLowerCase;
  for (auto c : sampleNameMixedCase)
    sampleNameLowerCase += static_cast<char>(std::tolower(c));

  if (cache.find(sampleNameLowerCase) != cache.end())
    return cache.at(sampleNameLowerCase);

  SampleInfo result;
  for (const auto & element : _samplesInfo)
  {
    if (element["sample_name"] == sampleNameLowerCase)
    {
      result.Brief = element["brief"];
      result.HeaderFile = element["header_file"];
      result.SourceFile = element["source_file"];
      for (const auto & link : element["links"])
      {
        result.Links.push_back(link);
      }
    }
  }
  cache[sampleNameLowerCase] = result;
  return result;
}

std::vector<std::string> SamplesIndex::getSampleNames() const
{
  // Extract the enabled sample names from the map
  std::vector<std::string> sampleNames;
  for (const auto& samplesCategory : _samplesIndex) {
    for (const auto& element : samplesCategory.second.samples()) {
      // Check if enabled
      if (std::get<0>(element.second)) {
        sampleNames.emplace_back(element.first);
      }
    }
  }

  // Sort the vector with sample names in ascending order
  std::sort(sampleNames.begin(), sampleNames.end());

  return sampleNames;
}

std::vector<std::string> SamplesIndex::getCategoryNames() const
{
  // Extract the category names
  auto categoryNames = stl_util::extract_keys(_samplesIndex);

  // Sort the vector with category names in ascending order
  std::sort(categoryNames.begin(), categoryNames.end());

  return categoryNames;
}

bool SamplesIndex::categoryExists(const std::string& categoryNameToSearch) const
{
  bool _categoryExists = false;

  // Extract the category names
  auto categoryNames = stl_util::extract_keys(_samplesIndex);

  // Search for sample
  for (const auto& categoryName : categoryNames) {
    if (categoryName == categoryNameToSearch) {
      _categoryExists = true;
      break;
    }
  }

  return _categoryExists;
}

std::vector<std::string>
SamplesIndex::getSampleNamesInCategory(const std::string& categoryName) const
{
  // Extract the enabled sample names for the given category from the map
  std::vector<std::string> sampleNames;
  if (stl_util::contains(_samplesIndex, categoryName)) {
    const auto& samplesCategory = _samplesIndex.at(categoryName);
    for (const auto& element : samplesCategory.samples()) {
      // Check if enabled
      if (std::get<0>(element.second)) {
        sampleNames.emplace_back(element.first);
      }
    }
  }

  // Sort the vector with sample names in ascending order
  std::sort(sampleNames.begin(), sampleNames.end());

  return sampleNames;
}

IRenderableScenePtr
SamplesIndex::createRenderableScene(const std::string& sampleName,
                                    ICanvas* iCanvas) const
{
  for (const auto& item : _samplesIndex) {
    if (stl_util::contains(item.second.samples(), sampleName)) {
      return std::get<1>(item.second.samples().at(sampleName))(iCanvas);
    }
  }

  return nullptr;
}

void SamplesIndex::listSamples()
{
  auto categories = getCategoryNames();
  for (const auto & category : categories)
  {
    std::cout << "********************************************" << "\n";
    std::cout << "Category: " << category << "\n";
    std::cout << "********************************************" << "\n";
    auto samples = getSampleNamesInCategory(category);
    for (const auto & sample : samples)
    {
      std::string ko = (!isSampleEnabled(sample)) ? " (KO)" : "";
      std::cout << sample << ko << "\n";
    }
  }
}

std::string SampleFailureReason_Str(SampleFailureReason s)
{
  switch (s) {
    case SampleFailureReason::blankDisplay:
      return "Blank display";
      break;
    case SampleFailureReason::outOfBoundAccess :
      return "Out of bounds access";
      break;
    case SampleFailureReason::processHung:
      return "Process hung";
      break;
    case SampleFailureReason::invalidComparator:
      return "Invalid comparator";
      break;
    case SampleFailureReason::vectorIteratorInvalid:
      return "vector iterators in range are from different containers";
      break;
    case SampleFailureReason::empty3d:
      return "3D rendering is empty";
      break;
    case SampleFailureReason::readAccessViolation:
      return "Read Access Violation";
      break;
    case SampleFailureReason::incomplete3d:
      return "Incomplete 3d (black textures and co)";
      break;
    case SampleFailureReason::broken:
      return "Broken (bad rendering and/or bad behavior)";
      break;
    default:
      throw "Unhandled enum!";
  }
}

} // end of namespace Samples
} // end of namespace BABYLON
<|endoftext|>


<commit_before>/**
 * @file neighborreduce.hxx
 * @author Muhammad Osama (mosama@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2021-11-05
 *
 * @copyright Copyright (c) 2021
 *
 */

#pragma once

#include <gunrock/cuda/context.hxx>
#include <gunrock/error.hxx>
#include <gunrock/util/type_limits.hxx>

#include <gunrock/framework/operators/configs.hxx>

#include <moderngpu/kernel_segreduce.hxx>

namespace gunrock {
namespace operators {
namespace neighborreduce {

/**
 * @brief Neighbor reduce is an operator that performs reduction on the segments
 * of neighbors (or data associated with the neighbors), where each segment is
 * defined by the source vertex. Another simple way to understand this operator
 * is to perform advance and then reduction on the resultant traversal.
 *
 * @par Overview
 * Neighbor reduce operator, built on top of segmented reduction. This is
 * a very limited approach to neighbor reduce, and only gives you the edge per
 * advance. It's only implemented on the entire graph (frontiers not yet
 * supported).
 *
 * @tparam input_t advance input type (advance_io_type_t::graph supported)
 * @tparam graph_t graph type.
 * @tparam enactor_t enactor type.
 * @tparam output_t output type.
 * @tparam operator_t user-defined lambda function.
 * @tparam arithmetic_t binary function, arithmetic operator such as sum, max,
 * min, etc.
 * @param G graph to perform advance-reduce on.
 * @param E enactor structure (not used as of right now).
 * @param output output buffer.
 * @param op user-defined lambda function.
 * @param arithmetic_op arithmetic operator (binary).
 * @param init_value initial value for the reduction.
 * @param context cuda context (@see cuda::multi_context_t).
 */
template <advance_io_type_t input_t = advance_io_type_t::graph,
          typename graph_t,
          typename enactor_t,
          typename output_t,
          typename operator_t,
          typename arithmetic_t>
void execute(graph_t& G,
             enactor_t* E,
             output_t* output,
             operator_t op,
             arithmetic_t arithmetic_op,
             output_t init_value,
             cuda::multi_context_t& context) {
  if (context.size() == 1) {
    auto context0 = context.get_context(0);

    using find_csr_t = typename graph_t::graph_csr_view_t;
    if (!(G.template contains_representation<find_csr_t>())) {
      error::throw_if_exception(cudaErrorUnknown,
                                "CSR sparse-matrix representation "
                                "required for neighborreduce operator.");
    }

    // TODO: Throw an exception if input_t is not advance_io_type_t::graph.
    mgpu::transform_segreduce(op, G.get_number_of_edges(), G.get_row_offsets(),
                              G.get_number_of_vertices(), output, arithmetic_op,
                              init_value, *(context0->mgpu()));
  }
}

}  // namespace neighborreduce
}  // namespace operators
}  // namespace gunrock<commit_msg>Another implementation of neighborreduce. Uses lbs_segreduce instead of transform_segreduce. Can be used to optimize the vertex lookup and also support neighborreduce on frontiers instead of just on graphs.<commit_after>/**
 * @file neighborreduce.hxx
 * @author Muhammad Osama (mosama@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2021-11-05
 *
 * @copyright Copyright (c) 2021
 *
 */

#pragma once

#include <gunrock/cuda/context.hxx>
#include <gunrock/error.hxx>
#include <gunrock/util/type_limits.hxx>

#include <gunrock/framework/operators/configs.hxx>

#include <moderngpu/kernel_segreduce.hxx>

// #define LBS_SEGREDUCE 1

namespace gunrock {
namespace operators {
namespace neighborreduce {

/**
 * @brief Neighbor reduce is an operator that performs reduction on the segments
 * of neighbors (or data associated with the neighbors), where each segment is
 * defined by the source vertex. Another simple way to understand this operator
 * is to perform advance and then reduction on the resultant traversal.
 *
 * @par Overview
 * Neighbor reduce operator, built on top of segmented reduction. This is
 * a very limited approach to neighbor reduce, and only gives you the edge per
 * advance. It's only implemented on the entire graph (frontiers not yet
 * supported).
 *
 * @tparam input_t advance input type (advance_io_type_t::graph supported)
 * @tparam graph_t graph type.
 * @tparam enactor_t enactor type.
 * @tparam output_t output type.
 * @tparam operator_t user-defined lambda function.
 * @tparam arithmetic_t binary function, arithmetic operator such as sum, max,
 * min, etc.
 * @param G graph to perform advance-reduce on.
 * @param E enactor structure (not used as of right now).
 * @param output output buffer.
 * @param op user-defined lambda function.
 * @param arithmetic_op arithmetic operator (binary).
 * @param init_value initial value for the reduction.
 * @param context cuda context (@see cuda::multi_context_t).
 */
template <advance_io_type_t input_t = advance_io_type_t::graph,
          typename graph_t,
          typename enactor_t,
          typename output_t,
          typename operator_t,
          typename arithmetic_t>
void execute(graph_t& G,
             enactor_t* E,
             output_t* output,
             operator_t op,
             arithmetic_t arithmetic_op,
             output_t init_value,
             cuda::multi_context_t& context) {
  if (context.size() == 1) {
    auto context0 = context.get_context(0);

    using type_t = typename graph_t::vertex_type;
    using find_csr_t = typename graph_t::graph_csr_view_t;
    if (!(G.template contains_representation<find_csr_t>())) {
      error::throw_if_exception(cudaErrorUnknown,
                                "CSR sparse-matrix representation "
                                "required for neighborreduce operator.");
    }

#ifndef LBS_SEGREDUCE
    // TODO: Throw an exception if input_t is not advance_io_type_t::graph.
    mgpu::transform_segreduce(op, G.get_number_of_edges(), G.get_row_offsets(),
                              G.get_number_of_vertices(), output, arithmetic_op,
                              init_value, *(context0->mgpu()));

#else

    auto f = [=] __device__(std::size_t index, std::size_t seg,
                            std::size_t rank) {
      auto v = type_t(seg);
      auto start_edge = G.get_starting_edge(v);
      auto e = start_edge + rank;
      return op(e);
    };

    // TODO: Throw an exception if input_t is not advance_io_type_t::graph.
    mgpu::lbs_segreduce(f, G.get_number_of_edges(), G.get_row_offsets(),
                        G.get_number_of_vertices(), output, arithmetic_op,
                        init_value, *(context0->mgpu()));
#endif
  }
}

}  // namespace neighborreduce
}  // namespace operators
}  // namespace gunrock<|endoftext|>