<commit_before>#include <iostream>
#include <memory>
#include <fstream>

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

#include "Moves/Move.h"

#include "Players/Genetic_AI.h"
#include "Players/Human_Player.h"
#include "Players/Random_AI.h"
#include "Players/Outside_Player.h"

#include "Genes/Gene_Pool.h"

#include "Exceptions/Illegal_Move_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"
#include "Testing.h"

void print_help();
void replay_game(const std::string& file_name, int game_number);
int find_last_id(const std::string& filename);

int main(int argc, char *argv[])
{
    try
    {
        run_tests();

        if(argc > 1)
        {
            if(std::string(argv[1]) == "-genepool")
            {
                std::string gene_pool_config_file_name;
                if(argc > 2)
                {
                    gene_pool_config_file_name = argv[2];
                }

                gene_pool(gene_pool_config_file_name);
            }
            else if(std::string(argv[1]) == "-replay")
            {
                if(argc > 2)
                {
                    std::string file_name = argv[2];
                    int game_number = -1;
                    if(argc > 3)
                    {
                        game_number = std::stoi(argv[3]);
                    }
                    replay_game(file_name, game_number);
                }
                else
                {
                    std::cout << "Provide a file containing a game to replay." << std::endl;
                    return 1;
                }
            }
            else
            {
                // Use pointers since each player could be Human, Genetic, Random, etc.
                std::unique_ptr<Player> white;
                std::unique_ptr<Player> black;
                std::unique_ptr<Player> latest;

                int game_time = 0;
                int moves_per_reset = 0;
                int increment_time = 0;

                for(int i = 1; i < argc; ++i)
                {
                    std::string opt = argv[i];
                    if(opt == "-human")
                    {
                        latest.reset(new Human_Player());
                    }
                    else if(opt == "-random")
                    {
                        latest.reset(new Random_AI());
                    }
                    else if(opt == "-genetic")
                    {
                        Genetic_AI *genetic_ptr = nullptr;
                        std::string filename;
                        int id = -1;
                        if(i + 1 < argc)
                        {
                            filename = argv[i+1];
                            if(filename.front() == '-')
                            {
                                filename.clear();
                            }
                        }

                        if(i + 2 < argc)
                        {
                            try
                            {
                                id = std::stoi(argv[i+2]);
                            }
                            catch(const std::exception&)
                            {
                            }
                        }

                        if(filename.empty())
                        {
                            genetic_ptr = new Genetic_AI;
                            for(int j = 0; j < 100; ++j)
                            {
                                genetic_ptr->mutate();
                            }
                            genetic_ptr->print_genome("single_game_player.txt");
                        }
                        else
                        {
                            if(id < 0)
                            {
                                genetic_ptr = new Genetic_AI(filename, find_last_id(filename));
                                i += 1;
                            }
                            else
                            {
                                genetic_ptr = new Genetic_AI(filename, id);
                                i += 2;
                            }
                        }

                        latest.reset(genetic_ptr);
                    }
                    else if(opt == "-time")
                    {
                        game_time = std::stoi(argv[++i]);
                    }
                    else if(opt == "-reset_moves")
                    {
                        moves_per_reset = std::stoi(argv[++i]);
                    }
                    else if(opt == "-increment_time")
                    {
                        increment_time = std::stoi(argv[++i]);
                    }
                    else
                    {
                        throw std::runtime_error("Invalid option: " + opt);
                    }

                    if(latest)
                    {
                        if( ! white)
                        {
                            white = std::move(latest);
                        }
                        else if( ! black)
                        {
                            black = std::move(latest);
                        }
                        else
                        {
                            throw std::runtime_error("More than two players specified.");
                        }
                    }
                }

                std::string game_file_name = "game.pgn";

                if(black)
                {
                    play_game(*white, *black, game_time, moves_per_reset, increment_time, game_file_name);
                }
                else
                {
                    auto outside = connect_to_outside(*white);
                    game_time = outside->get_game_time();
                    moves_per_reset = outside->get_reset_moves();
                    increment_time = outside->get_increment();

                    if(outside->get_ai_color() == WHITE)
                    {
                        play_game(*white, *outside, game_time, moves_per_reset, increment_time, game_file_name);
                    }
                    else
                    {
                        play_game(*outside, *white, game_time, moves_per_reset, increment_time, game_file_name);
                    }
                }
            }
        }
        else
        {
            print_help();
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << "\n\nERROR: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

void print_help()
{
    std::cout << "\n\nGenetic Chess" << std::endl
              << "=============" << std::endl << std::endl
              << "Options:" << std::endl
              << "\t-genepool [file name]" << std::endl
              << "\t\tStart a run of a gene pool with parameters set in the given\n\t\tfile name." << std::endl << std::endl
              << "\t-replay [filename]" << std::endl
              << "\t\tStep through a PGN game file, drawing the board after each\n\t\tmove with an option to begin playing at any time." << std::endl << std::endl
              << "The following options start a game with various players. If two players are\nspecified, the first plays white and the second black. If only one player is\nspecified, the program will wait for a CECP command from outside to start\nplaying." << std::endl << std::endl
              << "\t-human" << std::endl
              << "\t\tSpecify a human player for a game." << std::endl << std::endl
              << "\t-genetic [filename [number]]" << std::endl
              << "\t\tSpecify a genetic AI player for a game. Optional file name and\n\t\tID number to load an AI from a file." << std::endl << std::endl
              << "\t-random" << std::endl
              << "\t\tSpecify a player that makes random moves for a game." << std::endl << std::endl
              << "\t-time [number]" << std::endl
              << "\t\tSpecify the time each player has to play the game or to make\n\t\ta set number of moves (see -reset_moves option)." << std::endl << std::endl
              << "\t-reset_moves [number]" << std::endl
              << "\t\tSpecify the number of moves a player must make within the time\n\t\tlimit. The clock resets to the initial time every time this\n\t\tnumber of moves is made." << std::endl << std::endl
              << "\t-increment_time [number]" << std::endl
              << "\t\tSpecify seconds to add to time after each move." << std::endl << std::endl;
}

int find_last_id(const std::string& filename)
{
    std::ifstream ifs(filename);
    std::string line;
    std::string id_line;
    while(std::getline(ifs, line))
    {
        if(String::starts_with(line, "ID:"))
        {
            id_line = line;
        }
    }

    if(id_line.empty())
    {
        throw std::runtime_error("No Genetic AIs found in " + filename);
    }
    else
    {
        return std::stoi(String::split(id_line)[1]);
    }
}

void replay_game(const std::string& file_name, int game_number)
{
    std::ifstream ifs(file_name);
    std::vector<std::string> game_headers;
    std::string line;
    if(game_number >= 0)
    {
        // fast forward to indicated game
        while(std::getline(ifs, line))
        {
            line = String::trim_outer_whitespace(line);
            if(String::starts_with(line, '['))
            {
                game_headers.push_back(line);
            }
            else
            {
                game_headers.clear();
            }

            if(String::starts_with(line, "[Round"))
            {
                auto number = std::stoi(String::split(line, "\"")[1]);
                if(number == game_number)
                {
                    break;
                }
            }
        }

        if( ! ifs)
        {
            std::cout << "No game with ID number " << game_number << " found." << std::endl;
        }

        for(const auto& header : game_headers)
        {
            std::cout << header << std::endl;
        }
    }

    Board board;
    bool game_started = false;
    while( ! board.game_has_ended() && std::getline(ifs, line))
    {
        line = String::trim_outer_whitespace(line);
        line = String::strip_block_comment(line, '{', '}');
        line = String::strip_comments(line, ';');
        if(line.empty())
        {
            if(game_started)
            {
                break;
            }
            else
            {
                continue;
            }
        }
        if(line[0] == '[')
        {
            std::cout << line << std::endl;
            continue;
        }

        for(const auto& s : String::split(line))
        {
            try
            {
                board.submit_move(board.get_complete_move(s));
            }
            catch(const Illegal_Move_Exception&)
            {
                std::cout << "Ignoring: " << s << std::endl;
                continue;
            }
            catch(const Game_Ending_Exception& e)
            {
                std::cout << e.what() << std::endl;
            }
            board.ascii_draw(WHITE);
            game_started = true;
            std::cout << "Last move: ";
            std::cout << (board.get_game_record().size() + 1)/2 << ". ";
            std::cout << (board.whose_turn() == WHITE ? "... " : "");
            std::cout << board.get_game_record().back() << std::endl;
            if(board.game_has_ended())
            {
                break;
            }

            std::cout << "Enter \"y\" to play game from here: " << std::endl;
            char response = std::cin.get();
            if(std::tolower(response) == 'y')
            {
                play_game_with_board(Human_Player(),
                                     Human_Player(),
                                     0,
                                     0,
                                     0,
                                     file_name + "_continued.pgn",
                                     board);
                 break;
            }
        }
    }
}
<commit_msg>Require at least 3 wins when picking last AI<commit_after>#include <iostream>
#include <memory>
#include <fstream>

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

#include "Moves/Move.h"

#include "Players/Genetic_AI.h"
#include "Players/Human_Player.h"
#include "Players/Random_AI.h"
#include "Players/Outside_Player.h"

#include "Genes/Gene_Pool.h"

#include "Exceptions/Illegal_Move_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"
#include "Testing.h"

void print_help();
void replay_game(const std::string& file_name, int game_number);
int find_last_id(const std::string& filename);

int main(int argc, char *argv[])
{
    try
    {
        run_tests();

        if(argc > 1)
        {
            if(std::string(argv[1]) == "-genepool")
            {
                std::string gene_pool_config_file_name;
                if(argc > 2)
                {
                    gene_pool_config_file_name = argv[2];
                }

                gene_pool(gene_pool_config_file_name);
            }
            else if(std::string(argv[1]) == "-replay")
            {
                if(argc > 2)
                {
                    std::string file_name = argv[2];
                    int game_number = -1;
                    if(argc > 3)
                    {
                        game_number = std::stoi(argv[3]);
                    }
                    replay_game(file_name, game_number);
                }
                else
                {
                    std::cout << "Provide a file containing a game to replay." << std::endl;
                    return 1;
                }
            }
            else
            {
                // Use pointers since each player could be Human, Genetic, Random, etc.
                std::unique_ptr<Player> white;
                std::unique_ptr<Player> black;
                std::unique_ptr<Player> latest;

                int game_time = 0;
                int moves_per_reset = 0;
                int increment_time = 0;

                for(int i = 1; i < argc; ++i)
                {
                    std::string opt = argv[i];
                    if(opt == "-human")
                    {
                        latest.reset(new Human_Player());
                    }
                    else if(opt == "-random")
                    {
                        latest.reset(new Random_AI());
                    }
                    else if(opt == "-genetic")
                    {
                        Genetic_AI *genetic_ptr = nullptr;
                        std::string filename;
                        int id = -1;
                        if(i + 1 < argc)
                        {
                            filename = argv[i+1];
                            if(filename.front() == '-')
                            {
                                filename.clear();
                            }
                        }

                        if(i + 2 < argc)
                        {
                            try
                            {
                                id = std::stoi(argv[i+2]);
                            }
                            catch(const std::exception&)
                            {
                            }
                        }

                        if(filename.empty())
                        {
                            genetic_ptr = new Genetic_AI;
                            for(int j = 0; j < 100; ++j)
                            {
                                genetic_ptr->mutate();
                            }
                            genetic_ptr->print_genome("single_game_player.txt");
                        }
                        else
                        {
                            if(id < 0)
                            {
                                genetic_ptr = new Genetic_AI(filename, find_last_id(filename));
                                i += 1;
                            }
                            else
                            {
                                genetic_ptr = new Genetic_AI(filename, id);
                                i += 2;
                            }
                        }

                        latest.reset(genetic_ptr);
                    }
                    else if(opt == "-time")
                    {
                        game_time = std::stoi(argv[++i]);
                    }
                    else if(opt == "-reset_moves")
                    {
                        moves_per_reset = std::stoi(argv[++i]);
                    }
                    else if(opt == "-increment_time")
                    {
                        increment_time = std::stoi(argv[++i]);
                    }
                    else
                    {
                        throw std::runtime_error("Invalid option: " + opt);
                    }

                    if(latest)
                    {
                        if( ! white)
                        {
                            white = std::move(latest);
                        }
                        else if( ! black)
                        {
                            black = std::move(latest);
                        }
                        else
                        {
                            throw std::runtime_error("More than two players specified.");
                        }
                    }
                }

                std::string game_file_name = "game.pgn";

                if(black)
                {
                    play_game(*white, *black, game_time, moves_per_reset, increment_time, game_file_name);
                }
                else
                {
                    auto outside = connect_to_outside(*white);
                    game_time = outside->get_game_time();
                    moves_per_reset = outside->get_reset_moves();
                    increment_time = outside->get_increment();

                    if(outside->get_ai_color() == WHITE)
                    {
                        play_game(*white, *outside, game_time, moves_per_reset, increment_time, game_file_name);
                    }
                    else
                    {
                        play_game(*outside, *white, game_time, moves_per_reset, increment_time, game_file_name);
                    }
                }
            }
        }
        else
        {
            print_help();
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << "\n\nERROR: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

void print_help()
{
    std::cout << "\n\nGenetic Chess" << std::endl
              << "=============" << std::endl << std::endl
              << "Options:" << std::endl
              << "\t-genepool [file name]" << std::endl
              << "\t\tStart a run of a gene pool with parameters set in the given\n\t\tfile name." << std::endl << std::endl
              << "\t-replay [filename]" << std::endl
              << "\t\tStep through a PGN game file, drawing the board after each\n\t\tmove with an option to begin playing at any time." << std::endl << std::endl
              << "The following options start a game with various players. If two players are\nspecified, the first plays white and the second black. If only one player is\nspecified, the program will wait for a CECP command from outside to start\nplaying." << std::endl << std::endl
              << "\t-human" << std::endl
              << "\t\tSpecify a human player for a game." << std::endl << std::endl
              << "\t-genetic [filename [number]]" << std::endl
              << "\t\tSpecify a genetic AI player for a game. Optional file name and\n\t\tID number to load an AI from a file." << std::endl << std::endl
              << "\t-random" << std::endl
              << "\t\tSpecify a player that makes random moves for a game." << std::endl << std::endl
              << "\t-time [number]" << std::endl
              << "\t\tSpecify the time each player has to play the game or to make\n\t\ta set number of moves (see -reset_moves option)." << std::endl << std::endl
              << "\t-reset_moves [number]" << std::endl
              << "\t\tSpecify the number of moves a player must make within the time\n\t\tlimit. The clock resets to the initial time every time this\n\t\tnumber of moves is made." << std::endl << std::endl
              << "\t-increment_time [number]" << std::endl
              << "\t\tSpecify seconds to add to time after each move." << std::endl << std::endl;
}

int find_last_id(const std::string& players_file_name)
{
    std::ifstream player_input(players_file_name);
    std::string line;
    std::vector<int> all_players;
    while(std::getline(player_input, line))
    {
        if(String::starts_with(line, "ID:"))
        {
            all_players.push_back(std::stoi(String::split(line).back()));
        }
    }

    // Filter out players with zero wins
    auto games_file = players_file_name + "_games.txt";
    std::ifstream games_input(games_file);
    std::map<int, int> games_won;
    std::map<Color, int> player_colors;
    while(std::getline(games_input, line))
    {
        if(String::starts_with(line, "[White"))
        {
            player_colors[WHITE] = std::stoi(String::split(String::split(line, "\"")[1])[2]);
        }
        else if(String::starts_with(line, "[Black"))
        {
            player_colors[BLACK] = std::stoi(String::split(String::split(line, "\"")[1])[2]);
        }
        else if(String::starts_with(line, "[Result"))
        {
            auto result_string = String::split(line, "\"")[1];
            if(result_string == "1-0")
            {
                ++games_won[player_colors[WHITE]];
            }
            else if(result_string == "0-1")
            {
                ++games_won[player_colors[BLACK]];
            }
            player_colors.clear();
        }
    }

    int best_id = -1;
    for(auto id_won : games_won)
    {
        if(id_won.second >= 3) // require at least 3 wins
        {
            best_id = id_won.first;
        }
    }

    if(best_id == -1)
    {
        return all_players.back();
    }
    else
    {
        return best_id;
    }
}

void replay_game(const std::string& file_name, int game_number)
{
    std::ifstream ifs(file_name);
    std::vector<std::string> game_headers;
    std::string line;
    if(game_number >= 0)
    {
        // fast forward to indicated game
        while(std::getline(ifs, line))
        {
            line = String::trim_outer_whitespace(line);
            if(String::starts_with(line, '['))
            {
                game_headers.push_back(line);
            }
            else
            {
                game_headers.clear();
            }

            if(String::starts_with(line, "[Round"))
            {
                auto number = std::stoi(String::split(line, "\"")[1]);
                if(number == game_number)
                {
                    break;
                }
            }
        }

        if( ! ifs)
        {
            std::cout << "No game with ID number " << game_number << " found." << std::endl;
        }

        for(const auto& header : game_headers)
        {
            std::cout << header << std::endl;
        }
    }

    Board board;
    bool game_started = false;
    while( ! board.game_has_ended() && std::getline(ifs, line))
    {
        line = String::trim_outer_whitespace(line);
        line = String::strip_block_comment(line, '{', '}');
        line = String::strip_comments(line, ';');
        if(line.empty())
        {
            if(game_started)
            {
                break;
            }
            else
            {
                continue;
            }
        }
        if(line[0] == '[')
        {
            std::cout << line << std::endl;
            continue;
        }

        for(const auto& s : String::split(line))
        {
            try
            {
                board.submit_move(board.get_complete_move(s));
            }
            catch(const Illegal_Move_Exception&)
            {
                std::cout << "Ignoring: " << s << std::endl;
                continue;
            }
            catch(const Game_Ending_Exception& e)
            {
                std::cout << e.what() << std::endl;
            }
            board.ascii_draw(WHITE);
            game_started = true;
            std::cout << "Last move: ";
            std::cout << (board.get_game_record().size() + 1)/2 << ". ";
            std::cout << (board.whose_turn() == WHITE ? "... " : "");
            std::cout << board.get_game_record().back() << std::endl;
            if(board.game_has_ended())
            {
                break;
            }

            std::cout << "Enter \"y\" to play game from here: " << std::endl;
            char response = std::cin.get();
            if(std::tolower(response) == 'y')
            {
                play_game_with_board(Human_Player(),
                                     Human_Player(),
                                     0,
                                     0,
                                     0,
                                     file_name + "_continued.pgn",
                                     board);
                 break;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 *   @author Andre Moreira Magalhaes <andre.magalhaes@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <KAboutData>
#include <KCmdLineArgs>
#include <KApplication>
#include <KDebug>

#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/AccountManager>
#include <TelepathyQt/ConnectionFactory>
#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/ChannelFactory>
#include <TelepathyQt/ClientRegistrar>
#include <TelepathyQt/ContactFactory>
#include <TelepathyQt/Debug>
#include <TelepathyQt/Types>

#include "sasl-handler.h"
#include "tls-handler.h"

#include <KTp/telepathy-handler-application.h>

// FIXME: Move this to tp-qt4 itself
#include "types.h"

int main(int argc, char *argv[])
{
    KAboutData aboutData("ktp-auth-handler",
                         "ktp-auth-handler",
                         ki18n("Telepathy Authentication Handler"),
                         "0.3");
    aboutData.addAuthor(ki18n("David Edmundson"), ki18n("Developer"), "kde@davidedmundson.co.uk");
    aboutData.addAuthor(ki18n("Daniele E. Domenichelli"), ki18n("Developer"), "daniele.domenichelli@gmail.com");
    aboutData.setProductName("telepathy/auth-handler");

    KCmdLineArgs::init(argc, argv, &aboutData);
    KTp::TelepathyHandlerApplication app;

    // FIXME: Move this to tp-qt4 itself
    registerTypes();

    Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(
            QDBusConnection::sessionBus(), Tp::Account::FeatureCore);
    Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(
            QDBusConnection::sessionBus(), Tp::Connection::FeatureCore);
    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(
            QDBusConnection::sessionBus());
    channelFactory->addCommonFeatures(Tp::Channel::FeatureCore);
    Tp::ClientRegistrarPtr clientRegistrar = Tp::ClientRegistrar::create(
            accountFactory, connectionFactory, channelFactory);

    int handlers = 2;

    Tp::ChannelClassSpecList saslFilter;
    QVariantMap saslOtherProperties;
    saslOtherProperties.insert(
            TP_QT_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION + QLatin1String(".AuthenticationMethod"),
            TP_QT_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION);
    saslFilter.append(Tp::ChannelClassSpec(TP_QT_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
                Tp::HandleTypeNone, false, saslOtherProperties));
    Tp::SharedPtr<SaslHandler> saslHandler = Tp::SharedPtr<SaslHandler>(new SaslHandler(saslFilter));
    if (!clientRegistrar->registerClient(
                Tp::AbstractClientPtr(saslHandler), QLatin1String("KTp.SASLHandler"))) {
        handlers -= 1;
    }

    Tp::ChannelClassSpecList tlsFilter;
    tlsFilter.append(Tp::ChannelClassSpec(TP_QT_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
                Tp::HandleTypeNone, false));
    Tp::SharedPtr<TlsHandler> tlsHandler = Tp::SharedPtr<TlsHandler>(new TlsHandler(tlsFilter));
    if (!clientRegistrar->registerClient(
                Tp::AbstractClientPtr(tlsHandler), QLatin1String("KTp.TLSHandler"))) {
        handlers -= 1;
    }

    if (!handlers) {
        kDebug() << "No handlers registered. Exiting";
        return 1;
    }
    return app.exec();
}
<commit_msg>Use the default translation catalog, since it has the same name as the application.<commit_after>/*
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 *   @author Andre Moreira Magalhaes <andre.magalhaes@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <KAboutData>
#include <KCmdLineArgs>
#include <KApplication>
#include <KDebug>

#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/AccountManager>
#include <TelepathyQt/ConnectionFactory>
#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/ChannelFactory>
#include <TelepathyQt/ClientRegistrar>
#include <TelepathyQt/ContactFactory>
#include <TelepathyQt/Debug>
#include <TelepathyQt/Types>

#include "sasl-handler.h"
#include "tls-handler.h"

#include <KTp/telepathy-handler-application.h>

// FIXME: Move this to tp-qt4 itself
#include "types.h"

int main(int argc, char *argv[])
{
    KAboutData aboutData("ktp-auth-handler", 0,
                         ki18n("Telepathy Authentication Handler"),
                         "0.3");
    aboutData.addAuthor(ki18n("David Edmundson"), ki18n("Developer"), "kde@davidedmundson.co.uk");
    aboutData.addAuthor(ki18n("Daniele E. Domenichelli"), ki18n("Developer"), "daniele.domenichelli@gmail.com");
    aboutData.setProductName("telepathy/auth-handler");

    KCmdLineArgs::init(argc, argv, &aboutData);
    KTp::TelepathyHandlerApplication app;

    // FIXME: Move this to tp-qt4 itself
    registerTypes();

    Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(
            QDBusConnection::sessionBus(), Tp::Account::FeatureCore);
    Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(
            QDBusConnection::sessionBus(), Tp::Connection::FeatureCore);
    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(
            QDBusConnection::sessionBus());
    channelFactory->addCommonFeatures(Tp::Channel::FeatureCore);
    Tp::ClientRegistrarPtr clientRegistrar = Tp::ClientRegistrar::create(
            accountFactory, connectionFactory, channelFactory);

    int handlers = 2;

    Tp::ChannelClassSpecList saslFilter;
    QVariantMap saslOtherProperties;
    saslOtherProperties.insert(
            TP_QT_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION + QLatin1String(".AuthenticationMethod"),
            TP_QT_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION);
    saslFilter.append(Tp::ChannelClassSpec(TP_QT_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
                Tp::HandleTypeNone, false, saslOtherProperties));
    Tp::SharedPtr<SaslHandler> saslHandler = Tp::SharedPtr<SaslHandler>(new SaslHandler(saslFilter));
    if (!clientRegistrar->registerClient(
                Tp::AbstractClientPtr(saslHandler), QLatin1String("KTp.SASLHandler"))) {
        handlers -= 1;
    }

    Tp::ChannelClassSpecList tlsFilter;
    tlsFilter.append(Tp::ChannelClassSpec(TP_QT_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
                Tp::HandleTypeNone, false));
    Tp::SharedPtr<TlsHandler> tlsHandler = Tp::SharedPtr<TlsHandler>(new TlsHandler(tlsFilter));
    if (!clientRegistrar->registerClient(
                Tp::AbstractClientPtr(tlsHandler), QLatin1String("KTp.TLSHandler"))) {
        handlers -= 1;
    }

    if (!handlers) {
        kDebug() << "No handlers registered. Exiting";
        return 1;
    }
    return app.exec();
}
<|endoftext|>


<commit_before>86c65266-4b02-11e5-8318-28cfe9171a43<commit_msg>I'm done<commit_after>86d36a99-4b02-11e5-8a22-28cfe9171a43<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <sstream>
#include <iomanip>
#include "DbfTable.h"
#include "Version.h"

using namespace std;

typedef enum Mode {
    kVersion,
    kSummary,
    kCsv
} Mode;

void print_usage() {
    cerr << "usage: dbf2csv [-h|-s|-a|-c|-r] filename" << endl;
    cerr << "-h = print this message" << endl;
    cerr << "-v = print the program version" << endl;
    cerr << "-s = print summary information" << endl;
    cerr << "-c = create a CSV file" << endl;
}

int main(int argc, char *argv[]) {
    Mode mode;
    bool skip_deleted = true;

    int opt;
    while ((opt = getopt(argc, argv, "usd:tq:r:")) != -1) {
        switch (opt) {
            case 'v':
                mode = kVersion;
                break;
            case 's':
                mode = kSummary;
                break;
            case 'c':
                mode = kCsv;
                break;
            case 'k':
                skip_deleted = (optarg[0] == 'Y' || optarg[0] == 'y');
                break;
            case 'h':
                print_usage();
                return 0;
            default:
                cerr << "Unrecognized option: '" << optopt << "'" << endl;
                print_usage();
                return 1;
        }
    }

    if (mode == kVersion) {
        cout << "dbf2csv version: " << Version << endl;
        return 0;
    }

    string dbf_filename = argv[optind];
    DbfTablePtr dbf_table = DbfTablePtr(new DbfTable(dbf_filename, skip_deleted));

    if (!dbf_table->good()) {
        cerr << "Unable to open file: " << dbf_filename << endl;
        return 1;
    }

    if (mode == kSummary) {
        cout << "Database: " << dbf_filename << endl;

        const DbfHeaderPtr header = dbf_table->header();
        cout << "Type: (" << hex << header->version() << ") " << header->version_description() << endl;
        cout << "Memo File: " << (dbf_table->has_memo_file() ? "true" : "false") << endl;
        cout << "Records: " << header->record_count() << endl;
        cout << "Last updated at: " << header->updated_at() << endl;
        cout << endl;

        cout << "Fields:" << endl;
        cout << "Name             Type       Length     Decimal" << endl;
        cout << "------------------------------------------------------------------------------" << endl;

        std::vector<DbfColumnPtr> columns = dbf_table->columns();
        for (auto it = std::begin(columns); it != std::end(columns); ++it) {
            DbfColumnPtr column(*it);
            cout << left << setw(17) << column->name();
            cout << left << setw(11) << column->type();
            cout << left << setw(11) << column->length();
            cout << left << column->decimal();
            cout << endl;
        }
    }
    else if (mode == kCsv) {
        dbf_table->to_csv(cout);
    }

    return 0;
}

<commit_msg>Fixes command line option parsing<commit_after>#include <iostream>
#include <vector>
#include <sstream>
#include <iomanip>
#include "DbfTable.h"
#include "Version.h"

using namespace std;

typedef enum Mode {
    kVersion,
    kSummary,
    kCsv
} Mode;

void print_usage() {
    cerr << "usage: dbf2csv [-h|-v|-s|-c|] filename" << endl;
    cerr << "-h = print this message" << endl;
    cerr << "-v = print the program version" << endl;
    cerr << "-s = print summary information" << endl;
    cerr << "-c = create a CSV file" << endl;
    cerr << "-k = skip deleted records (default: true)" << endl;
}

int main(int argc, char *argv[]) {
    Mode mode;
    bool skip_deleted = true;

    int opt;
    while ((opt = getopt(argc, argv, "hvsck:")) != -1) {
        switch (opt) {
            case 'v':
                mode = kVersion;
                break;
            case 's':
                mode = kSummary;
                break;
            case 'c':
                mode = kCsv;
                break;
            case 'k':
                skip_deleted = (optarg[0] == 'Y' || optarg[0] == 'y');
                break;
            case 'h':
                print_usage();
                return 0;
            default:
                cerr << "Unrecognized option: '" << optopt << "'" << endl;
                print_usage();
                return 1;
        }
    }

    if (mode == kVersion) {
        cout << "dbf2csv version: " << Version << endl;
        return 0;
    }

    string dbf_filename = argv[optind];
    DbfTablePtr dbf_table = DbfTablePtr(new DbfTable(dbf_filename, skip_deleted));

    if (!dbf_table->good()) {
        cerr << "Unable to open file: " << dbf_filename << endl;
        return 1;
    }

    if (mode == kSummary) {
        cout << "Database: " << dbf_filename << endl;

        const DbfHeaderPtr header = dbf_table->header();
        cout << "Type: (" << hex << header->version() << ") " << header->version_description() << endl;
        cout << "Memo File: " << (dbf_table->has_memo_file() ? "true" : "false") << endl;
        cout << "Records: " << header->record_count() << endl;
        cout << "Last updated at: " << header->updated_at() << endl;
        cout << endl;

        cout << "Fields:" << endl;
        cout << "Name             Type       Length     Decimal" << endl;
        cout << "------------------------------------------------------------------------------" << endl;

        std::vector<DbfColumnPtr> columns = dbf_table->columns();
        for (auto it = std::begin(columns); it != std::end(columns); ++it) {
            DbfColumnPtr column(*it);
            cout << left << setw(17) << column->name();
            cout << left << setw(11) << column->type();
            cout << left << setw(11) << column->length();
            cout << left << column->decimal();
            cout << endl;
        }
    }
    else if (mode == kCsv) {
        dbf_table->to_csv(cout);
    }

    return 0;
}

<|endoftext|>


<commit_before><commit_msg>Translated German class description (thanks to Markus Mohrhard).<commit_after><|endoftext|>


<commit_before>#include <utility>
#include <iterator>
#include <limits>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/**
 * Parser data
 */
enum class Puzzle::Expr::NodeType {
	EQUAL = 0,          // should occur exactly once - at root
	PLUS,
	MINUS,
	MULTIPLY,
	DIVIDE,
	// FACTORIAL,
	// BINOMIAL,   etc.
	LEAF = 0x1000,      // dummy type
	WORD,               // "fixed-value"/number leaf
	NUMBER              // "variable-value"/word leaf
};

struct Puzzle::Expr::ExprType {
	char op;
	Puzzle::Expr::NodeType type;
	int priority;
};

const Puzzle::Expr::ExprType Puzzle::Expr::ParseTable[] = {
	{'=', Puzzle::Expr::NodeType::EQUAL, 0},
	{'+', Puzzle::Expr::NodeType::PLUS, 1},
	{'-', Puzzle::Expr::NodeType::MINUS, 1},
	{'*', Puzzle::Expr::NodeType::MULTIPLY, 2},
	{'/', Puzzle::Expr::NodeType::DIVIDE, 2}
};

//------------------------------
// IMPLEMENTATION OF EXPRESSIONS
//------------------------------

Puzzle::Expr::Expr(const char* expr, int len, const std::map<char, int> &transmap, int rad)
{
	type = NodeType::LEAF;
	int split;
	int priority = std::numeric_limits<int>::max();

	// TODO: process parantheses
	// LOW: skip whitespace (well, maybe)
	for (int i=0; i<len; ++i)
		for (int op=0; op < (sizeof(ParseTable)/sizeof(ExprType)); ++op)			// LOW: what about a std::map?
			if (expr[i] == ParseTable[op].op && priority >= ParseTable[op].priority) {
				type = ParseTable[op].type;
				split = i;
				priority = ParseTable[op].priority;
			}

	// split expression and process parts recursively
	if (type != NodeType::LEAF) {
		left = new Expr(expr, split, transmap, rad);
		right = new Expr(expr+split+1, len-split-1, transmap, rad);
	}
	else {
		// word or number?
		int i;
		for (i=0; i<len; ++i)
			if (expr[i] >= '0' && expr[i] <= '9')
				break;
		if (i == len) {	 // word
			type = NodeType::WORD;
			word = new int[len+1];
			for (i=0; i<len; ++i)
				word[i] = transmap.find(expr[(len-1)-i])->second;
			word[len] = -1;
			radix = rad;
		}
		else {			 // number
			type = NodeType::NUMBER;
			const char *end;
			end = expr+len;
			value = strtol(expr, const_cast<char **>(&end), rad);
			// LOW: catch errors?
		}
	}
}

Puzzle::Expr::~Expr()
{
	switch (type) {
	case NodeType::WORD:      // leaf
		delete word;
		break;
	case NodeType::NUMBER:
		break;
	case NodeType::EQUAL:
	case NodeType::PLUS:
	case NodeType::MINUS:
	case NodeType::MULTIPLY:
	case NodeType::DIVIDE:    // inner node
		delete left;
		delete right;
		break;
	}
}

fraction<int> Puzzle::Expr::Eval(const int *NumMap) const
{
	int res=0, val=1;

	switch (type) {
		case NodeType::EQUAL:
			return (fraction<int>)(left->Eval(NumMap) == right->Eval(NumMap));
		case NodeType::PLUS:
			return left->Eval(NumMap) + right->Eval(NumMap);
		case NodeType::MINUS:
			return left->Eval(NumMap) - right->Eval(NumMap);
		case NodeType::MULTIPLY:
			return left->Eval(NumMap) * right->Eval(NumMap);
		case NodeType::DIVIDE:
			return left->Eval(NumMap) / right->Eval(NumMap);
		case NodeType::WORD:
			for (int i=0; word[i]>=0; ++i) {
				res += NumMap[word[i]]*val;
				val *= radix;
			}
			return fraction<int>(res);
		case NodeType::NUMBER:
			return fraction<int>(value);
	}
}

//------------------------------
//  IMPLEMENTATION OF PUZZLES
//------------------------------

Puzzle::Puzz::Puzz(const char *puzzle, int rad) : radix(rad), lettermap(rad), leading(rad)
{
	// fill Map
	std::map<char, int> Map;
	for (int i=0; puzzle[i]; ++i)
		if (puzzle[i]>='A' && puzzle[i]<='Z')				// what about nondecimal digits?
			Map.insert(std::pair<char, int>(puzzle[i], -1));

	// assign numbers to letters
	num = 0;
	for (std::map<char, int>::iterator it = Map.begin(); it != Map.end(); ++it, ++num) {
		lettermap[num] = it->first;
		it->second = num;
	}

	// make syntax tree
	root = new Expr(puzzle, (int)strlen(puzzle), Map, rad);

	// leading digits aren't allowed to be zero
	if (puzzle[0] >= 'A' && puzzle[0] <= 'Z')
		leading[Map[puzzle[0]]] = true;
	for (int i=1; puzzle[i]; ++i)
		if (puzzle[i-1] < 'A' && puzzle[i] >= 'A' && puzzle[i] <= 'Z')
			leading[Map[puzzle[i]]] = true;
}

Puzzle::Puzz::~Puzz()
{
	delete root;
}

bool Puzzle::Puzz::Eval(const int *NumMap) const
{
	for (int i=0; i<radix; ++i)
		if (!NumMap[i] && leading[i])
			return false;
	return (bool)(root->Eval(NumMap));
}

//------------------------------
// PERMUTATION GENERATOR IMPLEMENTATION
//------------------------------
Puzzle::MapGen::MapGen(int DomSize, int CodSize) : n(CodSize), m(DomSize)
{
	if (CodSize < DomSize)
		throw std::domain_error("There are no injektive maps if the codomain is smaller than the domain.");
	map = new int[DomSize];

	// M0
	for (int i=0; i<DomSize; ++i)
		map[i] = i;
}

Puzzle::MapGen::~MapGen()
{
	delete map;
}

//---------------------------  ALGORITHM DESCRIPTION  -------------------------
// (The following algorithm is inspired by Donald E. Knuth: The Art of Computer Programming, Vol. 4, Fasc. 2, Algorithm L; but slightly modified)
// Algorithm M: Visit all injective maps f from {1, ..., m} to {1, ..., n}, given m<n.
// Idea: Run through all m-subsets of {1, ..., n} and visit all permutations of these subsets for each one.
//   Running through all m-subsets is done by a "combination-enumeration" algorithm which outputs all combinations in a canonical order.
//   Running through all permutations of these subsets is done by Alg. L.
// M0. start with map (a_1, ..., a_m) = (1, ..., m).
// M1. visit map (a_1, ..., a_m)
// M2. [Find j] j <- m-1; while (a_j >= a_{j+1}) --j;
//     if (j=0) goto M4;
// M3. [Next a_j] l <- n; while (a_j >= a_l) --l; a_j <-> a_l;
// M4. [Reverse a_{j+1}, ..., a_m] k<-j+1; l<-m; while (k<l) {a_k <-> a_l, k++, l--} if (j>0) goto M1.
// M5. [Next combination] j <- m; while (a_j == j+(n-m)) --j;
//     if (j=0) finished;
//     else {++a_j; while (j<m) a_{++j} <- a_{j-1}+1; goto M1}
bool Puzzle::MapGen::NextMap()
{
	int j, l, k, Temp;

	// M2
	j = m-2;		// "j <- m-1"
	while (j>=0 && (map[j] >= map[j+1])) --j;
	if (j >= 0) {
		// M3
		l = m-1;	// "l <- m"
		while (map[j] >= map[l]) --l;
		Temp = map[j]; map[j] = map[l]; map[l] = Temp;
	}

	// M4
	k = j+1;		// "k <- j+1"
	l = m-1;		// "l <- m"
	while (k<l) {
		Temp = map[k]; map[k] = map[l]; map[l] = Temp;
		++k; --l;
	}

	if (j < 0) {
		// M5
		j = m-1;	// "j <- m"
		int diff = n-m;
		while (j>=0 && (map[j] == j+diff)) --j;
		if (j<0) return false;
		else {
			l = map[j];
			while (j<m) map[j++] = ++l;
		}
	}

	return true;
}

//------------------------------
//        PUZZLE SOLVER
//------------------------------
Puzzle::PuzzleSolver::PuzzleSolver(const Puzz &puzz)
	: puzz(puzz) {}

int Puzzle::PuzzleSolver::print_solutions(std::ostream &out, bool terminal)
{
	int numSolutions = 0;

	try {
		MapGen Gen(puzz.DomainSize(), puzz.radix);

		if (terminal)
			out << "\e[1m";
		for (int i=0; i<puzz.DomainSize(); ++i)
			out << puzz[i] << ' ';
		if (terminal)
			out << "\e[0m";
		out << std::endl;

		do
			if (puzz.Eval(*Gen)) {
				++numSolutions;
				for (int i=0; i<puzz.DomainSize(); ++i)
					out << Gen[i] << ' ';
				out << std::endl;
			}
		while (Gen.NextMap());
	}
	catch (const std::domain_error &err) {
		out << "This alphametic has too many letters.\n\n";
	}

	return numSolutions;
}
<commit_msg>Bug: didn't use the right delete[]<commit_after>#include <utility>
#include <iterator>
#include <limits>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/**
 * Parser data
 */
enum class Puzzle::Expr::NodeType {
	EQUAL = 0,          // should occur exactly once - at root
	PLUS,
	MINUS,
	MULTIPLY,
	DIVIDE,
	// FACTORIAL,
	// BINOMIAL,   etc.
	LEAF = 0x1000,      // dummy type
	WORD,               // "fixed-value"/number leaf
	NUMBER              // "variable-value"/word leaf
};

struct Puzzle::Expr::ExprType {
	char op;
	Puzzle::Expr::NodeType type;
	int priority;
};

const Puzzle::Expr::ExprType Puzzle::Expr::ParseTable[] = {
	{'=', Puzzle::Expr::NodeType::EQUAL, 0},
	{'+', Puzzle::Expr::NodeType::PLUS, 1},
	{'-', Puzzle::Expr::NodeType::MINUS, 1},
	{'*', Puzzle::Expr::NodeType::MULTIPLY, 2},
	{'/', Puzzle::Expr::NodeType::DIVIDE, 2}
};

//------------------------------
// IMPLEMENTATION OF EXPRESSIONS
//------------------------------

Puzzle::Expr::Expr(const char* expr, int len, const std::map<char, int> &transmap, int rad)
{
	type = NodeType::LEAF;
	int split;
	int priority = std::numeric_limits<int>::max();

	// TODO: process parantheses
	// LOW: skip whitespace (well, maybe)
	for (int i=0; i<len; ++i)
		for (int op=0; op < (sizeof(ParseTable)/sizeof(ExprType)); ++op)			// LOW: what about a std::map?
			if (expr[i] == ParseTable[op].op && priority >= ParseTable[op].priority) {
				type = ParseTable[op].type;
				split = i;
				priority = ParseTable[op].priority;
			}

	// split expression and process parts recursively
	if (type != NodeType::LEAF) {
		left = new Expr(expr, split, transmap, rad);
		right = new Expr(expr+split+1, len-split-1, transmap, rad);
	}
	else {
		// word or number?
		int i;
		for (i=0; i<len; ++i)
			if (expr[i] >= '0' && expr[i] <= '9')
				break;
		if (i == len) {	 // word
			type = NodeType::WORD;
			word = new int[len+1];
			for (i=0; i<len; ++i)
				word[i] = transmap.find(expr[(len-1)-i])->second;
			word[len] = -1;
			radix = rad;
		}
		else {			 // number
			type = NodeType::NUMBER;
			const char *end;
			end = expr+len;
			value = strtol(expr, const_cast<char **>(&end), rad);
			// LOW: catch errors?
		}
	}
}

Puzzle::Expr::~Expr()
{
	switch (type) {
	case NodeType::WORD:      // leaf
		delete word;
		break;
	case NodeType::NUMBER:
		break;
	case NodeType::EQUAL:
	case NodeType::PLUS:
	case NodeType::MINUS:
	case NodeType::MULTIPLY:
	case NodeType::DIVIDE:    // inner node
		delete left;
		delete right;
		break;
	}
}

fraction<int> Puzzle::Expr::Eval(const int *NumMap) const
{
	int res=0, val=1;

	switch (type) {
		case NodeType::EQUAL:
			return (fraction<int>)(left->Eval(NumMap) == right->Eval(NumMap));
		case NodeType::PLUS:
			return left->Eval(NumMap) + right->Eval(NumMap);
		case NodeType::MINUS:
			return left->Eval(NumMap) - right->Eval(NumMap);
		case NodeType::MULTIPLY:
			return left->Eval(NumMap) * right->Eval(NumMap);
		case NodeType::DIVIDE:
			return left->Eval(NumMap) / right->Eval(NumMap);
		case NodeType::WORD:
			for (int i=0; word[i]>=0; ++i) {
				res += NumMap[word[i]]*val;
				val *= radix;
			}
			return fraction<int>(res);
		case NodeType::NUMBER:
			return fraction<int>(value);
	}
}

//------------------------------
//  IMPLEMENTATION OF PUZZLES
//------------------------------

Puzzle::Puzz::Puzz(const char *puzzle, int rad) : radix(rad), lettermap(rad), leading(rad)
{
	// fill Map
	std::map<char, int> Map;
	for (int i=0; puzzle[i]; ++i)
		if (puzzle[i]>='A' && puzzle[i]<='Z')				// what about nondecimal digits?
			Map.insert(std::pair<char, int>(puzzle[i], -1));

	// assign numbers to letters
	num = 0;
	for (std::map<char, int>::iterator it = Map.begin(); it != Map.end(); ++it, ++num) {
		lettermap[num] = it->first;
		it->second = num;
	}

	// make syntax tree
	root = new Expr(puzzle, (int)strlen(puzzle), Map, rad);

	// leading digits aren't allowed to be zero
	if (puzzle[0] >= 'A' && puzzle[0] <= 'Z')
		leading[Map[puzzle[0]]] = true;
	for (int i=1; puzzle[i]; ++i)
		if (puzzle[i-1] < 'A' && puzzle[i] >= 'A' && puzzle[i] <= 'Z')
			leading[Map[puzzle[i]]] = true;
}

Puzzle::Puzz::~Puzz()
{
	delete root;
}

bool Puzzle::Puzz::Eval(const int *NumMap) const
{
	for (int i=0; i<radix; ++i)
		if (!NumMap[i] && leading[i])
			return false;
	return (bool)(root->Eval(NumMap));
}

//------------------------------
// PERMUTATION GENERATOR IMPLEMENTATION
//------------------------------
Puzzle::MapGen::MapGen(int DomSize, int CodSize) : n(CodSize), m(DomSize)
{
	if (CodSize < DomSize)
		throw std::domain_error("There are no injektive maps if the codomain is smaller than the domain.");
	map = new int[DomSize];

	// M0
	for (int i=0; i<DomSize; ++i)
		map[i] = i;
}

Puzzle::MapGen::~MapGen()
{
	delete[] map;
}

//---------------------------  ALGORITHM DESCRIPTION  -------------------------
// (The following algorithm is inspired by Donald E. Knuth: The Art of Computer Programming, Vol. 4, Fasc. 2, Algorithm L; but slightly modified)
// Algorithm M: Visit all injective maps f from {1, ..., m} to {1, ..., n}, given m<n.
// Idea: Run through all m-subsets of {1, ..., n} and visit all permutations of these subsets for each one.
//   Running through all m-subsets is done by a "combination-enumeration" algorithm which outputs all combinations in a canonical order.
//   Running through all permutations of these subsets is done by Alg. L.
// M0. start with map (a_1, ..., a_m) = (1, ..., m).
// M1. visit map (a_1, ..., a_m)
// M2. [Find j] j <- m-1; while (a_j >= a_{j+1}) --j;
//     if (j=0) goto M4;
// M3. [Next a_j] l <- n; while (a_j >= a_l) --l; a_j <-> a_l;
// M4. [Reverse a_{j+1}, ..., a_m] k<-j+1; l<-m; while (k<l) {a_k <-> a_l, k++, l--} if (j>0) goto M1.
// M5. [Next combination] j <- m; while (a_j == j+(n-m)) --j;
//     if (j=0) finished;
//     else {++a_j; while (j<m) a_{++j} <- a_{j-1}+1; goto M1}
bool Puzzle::MapGen::NextMap()
{
	int j, l, k, Temp;

	// M2
	j = m-2;		// "j <- m-1"
	while (j>=0 && (map[j] >= map[j+1])) --j;
	if (j >= 0) {
		// M3
		l = m-1;	// "l <- m"
		while (map[j] >= map[l]) --l;
		Temp = map[j]; map[j] = map[l]; map[l] = Temp;
	}

	// M4
	k = j+1;		// "k <- j+1"
	l = m-1;		// "l <- m"
	while (k<l) {
		Temp = map[k]; map[k] = map[l]; map[l] = Temp;
		++k; --l;
	}

	if (j < 0) {
		// M5
		j = m-1;	// "j <- m"
		int diff = n-m;
		while (j>=0 && (map[j] == j+diff)) --j;
		if (j<0) return false;
		else {
			l = map[j];
			while (j<m) map[j++] = ++l;
		}
	}

	return true;
}

//------------------------------
//        PUZZLE SOLVER
//------------------------------
Puzzle::PuzzleSolver::PuzzleSolver(const Puzz &puzz)
	: puzz(puzz) {}

int Puzzle::PuzzleSolver::print_solutions(std::ostream &out, bool terminal)
{
	int numSolutions = 0;

	try {
		MapGen Gen(puzz.DomainSize(), puzz.radix);

		if (terminal)
			out << "\e[1m";
		for (int i=0; i<puzz.DomainSize(); ++i)
			out << puzz[i] << ' ';
		if (terminal)
			out << "\e[0m";
		out << std::endl;

		do
			if (puzz.Eval(*Gen)) {
				++numSolutions;
				for (int i=0; i<puzz.DomainSize(); ++i)
					out << Gen[i] << ' ';
				out << std::endl;
			}
		while (Gen.NextMap());
	}
	catch (const std::domain_error &err) {
		out << "This alphametic has too many letters.\n\n";
	}

	return numSolutions;
}
<|endoftext|>


<commit_before>#include "commandline.h"
#include "consts.h"
#include "preferences.h"

CommandLine::CommandLine()
{
    m_terminated = false;
}

void CommandLine::processKey(Key value)
{
    if(value==ALL_OFF)
    {
        m_keyStack.clear();
        m_errorText.clear();
        m_text.clear();
        m_addresses.clear();
        m_keyStack.push(K1);
        m_keyStack.push(THRU);
        m_keyStack.push(K5);
        m_keyStack.push(K1);
        m_keyStack.push(K2);
        m_keyStack.push(AT);
        m_keyStack.push(K0);
        m_keyStack.push(ENTER);
        processStack();
        return;

    }
    if(value==CLEAR && !m_keyStack.isEmpty())
    {
        if(m_terminated)
        {
            // Clearing a terminated command line
            m_keyStack.clear();
            m_errorText.clear();
            m_text.clear();
            m_addresses.clear();
            m_terminated = false;
        }
        else
        {
            // Backspace
            m_keyStack.pop();
            m_errorText.clear();
        }
    }
    else
    {
        if(m_terminated)
        {
            m_keyStack.clear();
            m_errorText.clear();
            m_text.clear();
            m_addresses.clear();
            m_terminated = false;
        }
        m_keyStack.push(value);
    }
    processStack();
}

void CommandLine::processStack()
{
    enum {
        stChannel,
        stThruStart,
        stThruEnd,
        stLevels,
        stReady,
        stError,
    };

    m_text.clear();
    int state = stChannel;
    int numberEntry = 0;
    int startRange = 0;
    int i=0;
    QSet<int> selection;
    const int maxLevel = Preferences::getInstance()->GetMaxLevel();

    for(int pos=0; pos<m_keyStack.count(); pos++)
    {
        Key key = m_keyStack.at(pos);
        int numeric = (int) key;
        switch(key)
        {
        case K0:
        case K1:
        case K2:
        case K3:
        case K4:
        case K5:
        case K6:
        case K7:
        case K8:
        case K9:
            numberEntry *= 10;
            numberEntry += numeric;

            m_text.append(QString::number(numeric));

            if(state==stChannel || state==stThruStart || state==stThruEnd)
            {
                if(numberEntry>MAX_DMX_ADDRESS)
                {
                    // Not a valid entry, would be >512
                    state = stError;
                    m_errorText = "Error - number out of range";
                    return;
                }

            }

            if(state==stLevels)
            {
                if(numberEntry>maxLevel)
                {
                    // Not a valid entry, would be >max
                    state = stError;
                    m_errorText = "Error - number out of range";
                    return;
                }
            }
            break;

        case THRU:
                m_text.append(" THRU ");
                if(numberEntry==0 || state!=stChannel || startRange!=0)
                {
                    m_errorText = "Error - syntax error";
                    return;
                }
                startRange=numberEntry;
                numberEntry = 0;
            break;

        case AT:
            m_text.append(" @ ");
            if(startRange!=0 && numberEntry==0)
            {
                m_errorText = "Error - syntax error";
                return;
            }
            if(startRange!=0 && numberEntry!=0)
            {
                for(int i=startRange; i<numberEntry; i++)
                    selection << i;
            }
            if(numberEntry!=0) selection << numberEntry;

            if(selection.isEmpty() && !m_previousKeyStack.isEmpty())
            {
                m_keyStack = m_previousKeyStack;
                m_keyStack.push(AT);
                processStack();
                return;
            }

            state = stLevels;
            numberEntry = 0;
            startRange = 0;
            // Copy the entries up to the at to the last addresses
            i=0;
            m_previousKeyStack.clear();
            while(m_keyStack[i]!=AT)
            {
                m_previousKeyStack << m_keyStack[i];
                i++;
            }
            break;

        case AND:
            m_text.append(" AND ");
            if(numberEntry==0 || state != stChannel)
            {
                m_errorText = "Error - syntax error";
                return;
            }
            selection << numberEntry;
            numberEntry = 0;
            break;

        case ENTER:

            m_terminated = true;
            m_text.append("*");

            if(state!=stLevels)
                return;

            // m_level is always in absolute (0-255)
            if(Preferences::getInstance()->GetDisplayFormat()==Preferences::PERCENT)
                m_level = PTOHT[numberEntry];
            else
                m_level = numberEntry;

            m_addresses = selection;
            return;

        case FULL:
            if(selection.isEmpty() && !m_previousKeyStack.isEmpty())
            {
                m_keyStack = m_previousKeyStack;
                m_keyStack.push(AT);
                m_keyStack.push(FULL);
                processStack();
                return;
            }

            if(state!=stLevels)
                m_text.append(" @ ");
            m_text.append("FULL*");
            if(startRange!=0 && numberEntry==0)
            {
                m_errorText = "Error : Syntax Error";
                return;
            }
            if(state==stLevels && numberEntry!=0)
            {
                m_errorText = "Error : Syntax Error";
                return;
            }
            m_level = MAX_SACN_LEVEL;
            m_addresses = selection;
            m_terminated = true;
            return;

        case CLEAR:
        default:
            break;
        }
    }
}

QString CommandLine::text()
{
    return m_text;
}

/************************ CommandLineWidget ******************************/

CommandLineWidget::CommandLineWidget(QWidget *parent) : QTextEdit(parent)
{
    this->setReadOnly(true);
    setStyleSheet("color: rgb(127, 255, 23);background: black;font: 75 12pt \"Courier\";");
    clear();
}

void CommandLineWidget::displayText()
{
    this->setText(m_commandLine.text());
    this->append(QString("%1").arg(m_commandLine.errorText()));
    if(!m_commandLine.addresses().isEmpty())
    {
        emit setLevels(m_commandLine.addresses(), m_commandLine.level());
    }
}

void CommandLineWidget::key1()
{
    m_commandLine.processKey(CommandLine::K1);
    displayText();
}

void CommandLineWidget::key2()
{
    m_commandLine.processKey(CommandLine::K2);
    displayText();
}

void CommandLineWidget::key3()
{
    m_commandLine.processKey(CommandLine::K3);
    displayText();
}

void CommandLineWidget::key4()
{
    m_commandLine.processKey(CommandLine::K4);
    displayText();
}

void CommandLineWidget::key5()
{
    m_commandLine.processKey(CommandLine::K5);
    displayText();
}

void CommandLineWidget::key6()
{
    m_commandLine.processKey(CommandLine::K6);
    displayText();
}

void CommandLineWidget::key7()
{
    m_commandLine.processKey(CommandLine::K7);
    displayText();
}

void CommandLineWidget::key8()
{
    m_commandLine.processKey(CommandLine::K8);
    displayText();
}

void CommandLineWidget::key9()
{
    m_commandLine.processKey(CommandLine::K9);
    displayText();
}

void CommandLineWidget::key0()
{
    m_commandLine.processKey(CommandLine::K0);
    displayText();
}

void CommandLineWidget::keyThru()
{
    m_commandLine.processKey(CommandLine::THRU);
    displayText();
}

void CommandLineWidget::keyAt()
{
    m_commandLine.processKey(CommandLine::AT);
    displayText();
}

void CommandLineWidget::keyFull()
{
    m_commandLine.processKey(CommandLine::FULL);
    displayText();
}

void CommandLineWidget::keyClear()
{
    m_commandLine.processKey(CommandLine::CLEAR);
    displayText();
}

void CommandLineWidget::keyAnd()
{
    m_commandLine.processKey(CommandLine::AND);
    displayText();
}

void CommandLineWidget::keyEnter()
{
    m_commandLine.processKey(CommandLine::ENTER);
    displayText();
}

void CommandLineWidget::keyAllOff()
{
    m_commandLine.processKey(CommandLine::ALL_OFF);
    displayText();
}

void CommandLineWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_0:
        m_commandLine.processKey(CommandLine::K0);
        break;
    case Qt::Key_1:
        m_commandLine.processKey(CommandLine::K1);
        break;
    case Qt::Key_2:
        m_commandLine.processKey(CommandLine::K2);
        break;
    case Qt::Key_3:
        m_commandLine.processKey(CommandLine::K3);
        break;
    case Qt::Key_4:
        m_commandLine.processKey(CommandLine::K4);
        break;
    case Qt::Key_5:
        m_commandLine.processKey(CommandLine::K5);
        break;
    case Qt::Key_6:
        m_commandLine.processKey(CommandLine::K6);
        break;
    case Qt::Key_7:
        m_commandLine.processKey(CommandLine::K7);
        break;
    case Qt::Key_8:
        m_commandLine.processKey(CommandLine::K8);
        break;
    case Qt::Key_9:
        m_commandLine.processKey(CommandLine::K9);
        break;
    case Qt::Key_T:
        m_commandLine.processKey(CommandLine::THRU);
        break;
    case Qt::Key_Delete:
    case Qt::Key_Backspace:
        m_commandLine.processKey(CommandLine::CLEAR);
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        m_commandLine.processKey(CommandLine::ENTER);
        break;
    case Qt::Key_Plus:
        m_commandLine.processKey(CommandLine::AND);
        break;
    case Qt::Key_A:
    case Qt::Key_At:
        m_commandLine.processKey(CommandLine::AT);
        break;
    case Qt::Key_O:
        m_commandLine.processKey(CommandLine::ALL_OFF);
        break;
    case Qt::Key_F:
        m_commandLine.processKey(CommandLine::FULL);
        break;

    }

    displayText();
}

EditableLCDNumber::EditableLCDNumber(QWidget *parent) : QLCDNumber(parent)
{

}

void EditableLCDNumber::keyPressEvent(QKeyEvent *event)
{
    int buf = 0;

    switch(event->key())
    {
    case Qt::Key_Backspace:
        if(intValue()/10 > 0)
        {
            buf = intValue() / 10;
            display(buf);
            emit valueChanged(buf);
        }
        else
            display(QString(" "));
        break;
    case Qt::Key_PageDown:
        if(intValue()-1>0)
        {
            buf = intValue()-1;
            display(buf);
            emit valueChanged(buf);
        }
        else
        {
            display(MAX_DMX_ADDRESS);
            emit valueChanged(MAX_DMX_ADDRESS);
        }
        break;
    case Qt::Key_PageUp:
        if(intValue()<MAX_DMX_ADDRESS)
        {
            buf = intValue()+1;
            display(buf);
            emit valueChanged(buf);
        }
        else
        {
            display(1);
            emit valueChanged(1);
        }
        break;
    case Qt::Key_0:
    case Qt::Key_1:
    case Qt::Key_2:
    case Qt::Key_3:
    case Qt::Key_4:
    case Qt::Key_5:
    case Qt::Key_6:
    case Qt::Key_7:
    case Qt::Key_8:
    case Qt::Key_9:
        buf = value()*10 + (event->key()-Qt::Key_0);
        if(buf<=MAX_DMX_ADDRESS)
        {
            display(buf);
            emit valueChanged(buf);
        }
        break;
    case Qt::Key_Space:
        emit toggleOff();
        break;
    default:
        break;
    }
}
<commit_msg>Fix commandline: x [Full]<commit_after>#include "commandline.h"
#include "consts.h"
#include "preferences.h"

CommandLine::CommandLine()
{
    m_terminated = false;
}

void CommandLine::processKey(Key value)
{
    if(value==ALL_OFF)
    {
        m_keyStack.clear();
        m_errorText.clear();
        m_text.clear();
        m_addresses.clear();
        m_keyStack.push(K1);
        m_keyStack.push(THRU);
        m_keyStack.push(K5);
        m_keyStack.push(K1);
        m_keyStack.push(K2);
        m_keyStack.push(AT);
        m_keyStack.push(K0);
        m_keyStack.push(ENTER);
        processStack();
        return;

    }
    if(value==CLEAR && !m_keyStack.isEmpty())
    {
        if(m_terminated)
        {
            // Clearing a terminated command line
            m_keyStack.clear();
            m_errorText.clear();
            m_text.clear();
            m_addresses.clear();
            m_terminated = false;
        }
        else
        {
            // Backspace
            m_keyStack.pop();
            m_errorText.clear();
        }
    }
    else
    {
        if(m_terminated)
        {
            m_keyStack.clear();
            m_errorText.clear();
            m_text.clear();
            m_addresses.clear();
            m_terminated = false;
        }
        m_keyStack.push(value);
    }
    processStack();
}

void CommandLine::processStack()
{
    enum {
        stChannel,
        stThruStart,
        stThruEnd,
        stLevels,
        stReady,
        stError,
    };

    m_text.clear();
    int state = stChannel;
    int numberEntry = 0;
    int startRange = 0;
    int i=0;
    QSet<int> selection;
    const int maxLevel = Preferences::getInstance()->GetMaxLevel();

    for(int pos=0; pos<m_keyStack.count(); pos++)
    {
        Key key = m_keyStack.at(pos);
        int numeric = (int) key;
        switch(key)
        {
        case K0:
        case K1:
        case K2:
        case K3:
        case K4:
        case K5:
        case K6:
        case K7:
        case K8:
        case K9:
            numberEntry *= 10;
            numberEntry += numeric;

            m_text.append(QString::number(numeric));

            if(state==stChannel || state==stThruStart || state==stThruEnd)
            {
                if(numberEntry>MAX_DMX_ADDRESS)
                {
                    // Not a valid entry, would be >512
                    state = stError;
                    m_errorText = "Error - number out of range";
                    return;
                }

            }

            if(state==stLevels)
            {
                if(numberEntry>maxLevel)
                {
                    // Not a valid entry, would be >max
                    state = stError;
                    m_errorText = "Error - number out of range";
                    return;
                }
            }
            break;

        case THRU:
                m_text.append(" THRU ");
                if(numberEntry==0 || state!=stChannel || startRange!=0)
                {
                    m_errorText = "Error - syntax error";
                    return;
                }
                startRange=numberEntry;
                numberEntry = 0;
            break;

        case AT:
            m_text.append(" @ ");
            if(startRange!=0 && numberEntry==0)
            {
                m_errorText = "Error - syntax error";
                return;
            }
            if(startRange!=0 && numberEntry!=0)
            {
                for(int i=startRange; i<numberEntry; i++)
                    selection << i;
            }
            if(numberEntry!=0) selection << numberEntry;

            if(selection.isEmpty() && !m_previousKeyStack.isEmpty())
            {
                m_keyStack = m_previousKeyStack;
                m_keyStack.push(AT);
                processStack();
                return;
            }

            state = stLevels;
            numberEntry = 0;
            startRange = 0;
            // Copy the entries up to the at to the last addresses
            i=0;
            m_previousKeyStack.clear();
            while(m_keyStack[i]!=AT)
            {
                m_previousKeyStack << m_keyStack[i];
                i++;
            }
            break;

        case AND:
            m_text.append(" AND ");
            if(numberEntry==0 || state != stChannel)
            {
                m_errorText = "Error - syntax error";
                return;
            }
            selection << numberEntry;
            numberEntry = 0;
            break;

        case ENTER:

            m_terminated = true;
            m_text.append("*");

            if(state!=stLevels)
                return;

            // m_level is always in absolute (0-255)
            if(Preferences::getInstance()->GetDisplayFormat()==Preferences::PERCENT)
                m_level = PTOHT[numberEntry];
            else
                m_level = numberEntry;

            m_addresses = selection;
            return;

        case FULL:
            // Anything selected?
            if(
                selection.isEmpty()
                && m_keyStack.size()
                && !m_keyStack.contains(AT)
                )
            {
                m_keyStack.pop();
                processKey(AT);
                processKey(FULL);
                return;
            }
            else if (selection.isEmpty())
            {
                // ...Nope nothing
                // Lets try the previous selection
                if (!m_previousKeyStack.isEmpty())
                {
                    m_keyStack = m_previousKeyStack;
                    processKey(AT);
                    processKey(FULL);
                }
                else
                {
                    m_errorText = "Error - No selection";
                }
                return;
            }

            m_text.append("FULL*");
            if(startRange!=0 && numberEntry==0)
            {
                m_errorText = "Error - Syntax Error";
                return;
            }
            if(state==stLevels && numberEntry!=0)
            {
                m_errorText = "Error - Syntax Error";
                return;
            }
            m_level = MAX_SACN_LEVEL;
            m_addresses = selection;
            m_terminated = true;
            return;

        case CLEAR:
        default:
            break;
        }
    }
}

QString CommandLine::text()
{
    return m_text;
}

/************************ CommandLineWidget ******************************/

CommandLineWidget::CommandLineWidget(QWidget *parent) : QTextEdit(parent)
{
    this->setReadOnly(true);
    setStyleSheet("color: rgb(127, 255, 23);background: black;font: 75 12pt \"Courier\";");
    clear();
}

void CommandLineWidget::displayText()
{
    this->setText(m_commandLine.text());
    this->append(QString("%1").arg(m_commandLine.errorText()));
    if(!m_commandLine.addresses().isEmpty())
    {
        emit setLevels(m_commandLine.addresses(), m_commandLine.level());
    }
}

void CommandLineWidget::key1()
{
    m_commandLine.processKey(CommandLine::K1);
    displayText();
}

void CommandLineWidget::key2()
{
    m_commandLine.processKey(CommandLine::K2);
    displayText();
}

void CommandLineWidget::key3()
{
    m_commandLine.processKey(CommandLine::K3);
    displayText();
}

void CommandLineWidget::key4()
{
    m_commandLine.processKey(CommandLine::K4);
    displayText();
}

void CommandLineWidget::key5()
{
    m_commandLine.processKey(CommandLine::K5);
    displayText();
}

void CommandLineWidget::key6()
{
    m_commandLine.processKey(CommandLine::K6);
    displayText();
}

void CommandLineWidget::key7()
{
    m_commandLine.processKey(CommandLine::K7);
    displayText();
}

void CommandLineWidget::key8()
{
    m_commandLine.processKey(CommandLine::K8);
    displayText();
}

void CommandLineWidget::key9()
{
    m_commandLine.processKey(CommandLine::K9);
    displayText();
}

void CommandLineWidget::key0()
{
    m_commandLine.processKey(CommandLine::K0);
    displayText();
}

void CommandLineWidget::keyThru()
{
    m_commandLine.processKey(CommandLine::THRU);
    displayText();
}

void CommandLineWidget::keyAt()
{
    m_commandLine.processKey(CommandLine::AT);
    displayText();
}

void CommandLineWidget::keyFull()
{
    m_commandLine.processKey(CommandLine::FULL);
    displayText();
}

void CommandLineWidget::keyClear()
{
    m_commandLine.processKey(CommandLine::CLEAR);
    displayText();
}

void CommandLineWidget::keyAnd()
{
    m_commandLine.processKey(CommandLine::AND);
    displayText();
}

void CommandLineWidget::keyEnter()
{
    m_commandLine.processKey(CommandLine::ENTER);
    displayText();
}

void CommandLineWidget::keyAllOff()
{
    m_commandLine.processKey(CommandLine::ALL_OFF);
    displayText();
}

void CommandLineWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_0:
        m_commandLine.processKey(CommandLine::K0);
        break;
    case Qt::Key_1:
        m_commandLine.processKey(CommandLine::K1);
        break;
    case Qt::Key_2:
        m_commandLine.processKey(CommandLine::K2);
        break;
    case Qt::Key_3:
        m_commandLine.processKey(CommandLine::K3);
        break;
    case Qt::Key_4:
        m_commandLine.processKey(CommandLine::K4);
        break;
    case Qt::Key_5:
        m_commandLine.processKey(CommandLine::K5);
        break;
    case Qt::Key_6:
        m_commandLine.processKey(CommandLine::K6);
        break;
    case Qt::Key_7:
        m_commandLine.processKey(CommandLine::K7);
        break;
    case Qt::Key_8:
        m_commandLine.processKey(CommandLine::K8);
        break;
    case Qt::Key_9:
        m_commandLine.processKey(CommandLine::K9);
        break;
    case Qt::Key_T:
        m_commandLine.processKey(CommandLine::THRU);
        break;
    case Qt::Key_Delete:
    case Qt::Key_Backspace:
        m_commandLine.processKey(CommandLine::CLEAR);
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        m_commandLine.processKey(CommandLine::ENTER);
        break;
    case Qt::Key_Plus:
        m_commandLine.processKey(CommandLine::AND);
        break;
    case Qt::Key_A:
    case Qt::Key_At:
        m_commandLine.processKey(CommandLine::AT);
        break;
    case Qt::Key_O:
        m_commandLine.processKey(CommandLine::ALL_OFF);
        break;
    case Qt::Key_F:
        m_commandLine.processKey(CommandLine::FULL);
        break;

    }

    displayText();
}

EditableLCDNumber::EditableLCDNumber(QWidget *parent) : QLCDNumber(parent)
{

}

void EditableLCDNumber::keyPressEvent(QKeyEvent *event)
{
    int buf = 0;

    switch(event->key())
    {
    case Qt::Key_Backspace:
        if(intValue()/10 > 0)
        {
            buf = intValue() / 10;
            display(buf);
            emit valueChanged(buf);
        }
        else
            display(QString(" "));
        break;
    case Qt::Key_PageDown:
        if(intValue()-1>0)
        {
            buf = intValue()-1;
            display(buf);
            emit valueChanged(buf);
        }
        else
        {
            display(MAX_DMX_ADDRESS);
            emit valueChanged(MAX_DMX_ADDRESS);
        }
        break;
    case Qt::Key_PageUp:
        if(intValue()<MAX_DMX_ADDRESS)
        {
            buf = intValue()+1;
            display(buf);
            emit valueChanged(buf);
        }
        else
        {
            display(1);
            emit valueChanged(1);
        }
        break;
    case Qt::Key_0:
    case Qt::Key_1:
    case Qt::Key_2:
    case Qt::Key_3:
    case Qt::Key_4:
    case Qt::Key_5:
    case Qt::Key_6:
    case Qt::Key_7:
    case Qt::Key_8:
    case Qt::Key_9:
        buf = value()*10 + (event->key()-Qt::Key_0);
        if(buf<=MAX_DMX_ADDRESS)
        {
            display(buf);
            emit valueChanged(buf);
        }
        break;
    case Qt::Key_Space:
        emit toggleOff();
        break;
    default:
        break;
    }
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  CC
//
//  Created by Tian Jin on 14-3-24.
//  Copyright (c) 2014年 Tian Jin. All rights reserved.
//

#include <iostream>
#include <list>
#include "edge.h"
#include "nfa_node.h"
#include "def.h"

using namespace std;

void traverse_nfa(edge<nfa_node>* start);

typedef nfa<nfa_node, edge<nfa_node>> t_nfa;

void connect_nfa(t_nfa previous, t_nfa next)
{
    previous._end->push_started(next._start);
}

t_nfa get_a(string input)
{
    nfa_node* a_node = new nfa_node(false, "");
    edge<nfa_node>* a_edge = new edge<nfa_node>(0, a_node, input);
    a_node->push_terminated(a_edge);

    t_nfa a = t_nfa(a_edge, a_node);
    return a;
}

t_nfa get_Epsilon()
{
    nfa_node* e_node = new nfa_node(false, "");
    edge<nfa_node>* e_edge = new edge<nfa_node>(0, e_node, CC_EPSILON);
    e_node->push_terminated(e_edge);

    t_nfa e = t_nfa(e_edge, e_node);
    return e;
}

t_nfa get_M_or_N(t_nfa N, t_nfa M)
{
    t_nfa start_nfa = get_Epsilon();
    connect_nfa(start_nfa, N);
    connect_nfa(start_nfa, M);

    nfa_node* e_node = new nfa_node(false, "");
    edge<nfa_node>* e_edge_N = new edge<nfa_node>(0, e_node, CC_EPSILON);
    edge<nfa_node>* e_edge_M = new edge<nfa_node>(0, e_node, CC_EPSILON);

    e_node->push_terminated(e_edge_N);
    e_node->push_terminated(e_edge_M);

    N._end->push_started(e_edge_N);
    M._end->push_started(e_edge_M);

    t_nfa mn = t_nfa(start_nfa._start, e_node);
    return mn;
}

t_nfa get_M_and_N(t_nfa N, t_nfa M)
{
    connect_nfa(N, M);

    t_nfa mn = t_nfa(N._start, M._end);
    return mn;
}

t_nfa get_M_star(t_nfa M)
{
    t_nfa start_nfa = get_Epsilon();
    connect_nfa(start_nfa, M);

    edge<nfa_node>* e_edge = new edge<nfa_node>(0, e_node, CC_EPSILON);
    M._end->push_started(e_edge);
    start_nfa._end->push_terminated(e_edge);

    t_nfa ms = t_nfa(start_nfa._start, start_nfa._end);
}

t_nfa get_M_plus(t_nfa M)
{
    t_nfa M_star = get_M_star(M);
    connect_nfa(M, M_star);

    t_nfa mp = t_nfa(M._start, M_star._end);
    return mp;
}

t_nfa get_M_question(t_nfa M)
{
    t_nfa e = get_Epsilon();
    t_nfa mq = get_M_or_N(M, e);

    return mq;
}

t_nfa get_or_list(list<string> sym_list)
{
    //to_do
}

t_nfa get_and_list(list<string> sym_list)
{
    //to_do
}

int main(int argc, const char * argv[])
{
    t_nfa nfa_a = get_a("a");
    t_nfa nfa_e = get_a("e");

    t_nfa mn = get_M_or_N(nfa_a, nfa_e);

    traverse_nfa(mn._start);

    return 0;
}

<commit_msg>minor bug fix<commit_after>//
//  main.cpp
//  CC
//
//  Created by Tian Jin on 14-3-24.
//  Copyright (c) 2014年 Tian Jin. All rights reserved.
//

#include <iostream>
#include <list>
#include "edge.h"
#include "nfa_node.h"
#include "def.h"

using namespace std;

void traverse_nfa(edge<nfa_node>* start);

typedef nfa<nfa_node, edge<nfa_node>> t_nfa;

typedef void (*handlr)(int);

void connect_nfa(t_nfa previous, t_nfa next)
{
    previous._end->push_started(next._start);
}

t_nfa get_a(string input, bool accept = false, handlr accept_handlr = nullptr)
{
    nfa_node* a_node = new nfa_node(false, "");
    edge<nfa_node>* a_edge = new edge<nfa_node>(0, a_node, input);
    a_node->push_terminated(a_edge);

    t_nfa a = t_nfa(a_edge, a_node);
    return a;
}

t_nfa get_Epsilon()
{
    nfa_node* e_node = new nfa_node(false, "");
    edge<nfa_node>* e_edge = new edge<nfa_node>(0, e_node, CC_EPSILON);
    e_node->push_terminated(e_edge);

    t_nfa e = t_nfa(e_edge, e_node);
    return e;
}

t_nfa get_M_or_N(t_nfa N, t_nfa M)
{
    t_nfa start_nfa = get_Epsilon();
    connect_nfa(start_nfa, N);
    connect_nfa(start_nfa, M);

    nfa_node* e_node = new nfa_node(false, "");
    edge<nfa_node>* e_edge_N = new edge<nfa_node>(0, e_node, CC_EPSILON);
    edge<nfa_node>* e_edge_M = new edge<nfa_node>(0, e_node, CC_EPSILON);

    e_node->push_terminated(e_edge_N);
    e_node->push_terminated(e_edge_M);

    N._end->push_started(e_edge_N);
    M._end->push_started(e_edge_M);

    t_nfa mn = t_nfa(start_nfa._start, e_node);
    return mn;
}

t_nfa get_M_and_N(t_nfa N, t_nfa M)
{
    connect_nfa(N, M);

    t_nfa mn = t_nfa(N._start, M._end);
    return mn;
}

t_nfa get_M_star(t_nfa M)
{
    t_nfa start_nfa = get_Epsilon();
    connect_nfa(start_nfa, M);

    edge<nfa_node>* e_edge = new edge<nfa_node>(M._end, start_nfa._end, CC_EPSILON);
    M._end->push_started(e_edge);
    start_nfa._end->push_terminated(e_edge);

    t_nfa ms = t_nfa(start_nfa._start, start_nfa._end);
    return ms;
}

t_nfa get_M_plus(t_nfa M)
{
    t_nfa M_star = get_M_star(M);
    connect_nfa(M, M_star);

    t_nfa mp = t_nfa(M._start, M_star._end);
    return mp;
}

t_nfa get_M_question(t_nfa M)
{
    t_nfa e = get_Epsilon();
    t_nfa mq = get_M_or_N(M, e);

    return mq;
}

t_nfa get_or_list(list<string> sym_list)
{
    //to_do
    return get_Epsilon();
}

t_nfa get_and_list(list<string> sym_list)
{
    //to_do
    return get_Epsilon();
}

int main(int argc, const char * argv[])
{
    t_nfa nfa_a = get_a("a");
    t_nfa nfa_e = get_a("e");

    t_nfa mn = get_M_or_N(nfa_a, nfa_e);

    traverse_nfa(mn._start);

    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2018, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "pyinterp.h"
#include "post.h"
#include "xact.h"

namespace ledger {

using namespace boost::python;

namespace {

  bool py_has_tag_1s(post_t& post, const string& tag) {
    return post.has_tag(tag);
  }
  bool py_has_tag_1m(post_t& post, const mask_t& tag_mask) {
    return post.has_tag(tag_mask);
  }
  bool py_has_tag_2m(post_t& post, const mask_t& tag_mask,
                     const boost::optional<mask_t>& value_mask) {
    return post.has_tag(tag_mask, value_mask);
  }

  boost::optional<value_t> py_get_tag_1s(post_t& post, const string& tag) {
    return post.get_tag(tag);
  }
  boost::optional<value_t> py_get_tag_1m(post_t& post, const mask_t& tag_mask) {
    return post.get_tag(tag_mask);
  }
  boost::optional<value_t> py_get_tag_2m(post_t& post, const mask_t& tag_mask,
                                         const boost::optional<mask_t>& value_mask) {
    return post.get_tag(tag_mask, value_mask);
  }

  post_t::xdata_t& py_xdata(post_t& post) {
    return post.xdata();
  }

  account_t * py_reported_account(post_t& post) {
    return post.reported_account();
  }

} // unnamed namespace

void export_post()
{
  scope().attr("POST_EXT_RECEIVED")    = POST_EXT_RECEIVED;
  scope().attr("POST_EXT_HANDLED")     = POST_EXT_HANDLED;
  scope().attr("POST_EXT_DISPLAYED")   = POST_EXT_DISPLAYED;
  scope().attr("POST_EXT_DIRECT_AMT")  = POST_EXT_DIRECT_AMT;
  scope().attr("POST_EXT_SORT_CALC")   = POST_EXT_SORT_CALC;
  scope().attr("POST_EXT_COMPOUND")    = POST_EXT_COMPOUND;
  scope().attr("POST_EXT_VISITED")     = POST_EXT_VISITED;
  scope().attr("POST_EXT_MATCHES")     = POST_EXT_MATCHES;
  scope().attr("POST_EXT_CONSIDERED")  = POST_EXT_CONSIDERED;

  class_< post_t::xdata_t > ("PostingXData")
#if 1
    .add_property("flags",
                  &supports_flags<uint_least16_t>::flags,
                  &supports_flags<uint_least16_t>::set_flags)
    .def("has_flags", &supports_flags<uint_least16_t>::has_flags)
    .def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
    .def("add_flags", &supports_flags<uint_least16_t>::add_flags)
    .def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
#endif

    .add_property("visited_value",
                  make_getter(&post_t::xdata_t::visited_value),
                  make_setter(&post_t::xdata_t::visited_value))
    .add_property("compound_value",
                  make_getter(&post_t::xdata_t::compound_value),
                  make_setter(&post_t::xdata_t::compound_value))
    .add_property("total",
                  make_getter(&post_t::xdata_t::total),
                  make_setter(&post_t::xdata_t::total))
    .add_property("count",
                  make_getter(&post_t::xdata_t::count),
                  make_setter(&post_t::xdata_t::count))
    .add_property("date",
                  make_getter(&post_t::xdata_t::date),
                  make_setter(&post_t::xdata_t::date))
    .add_property("datetime",
                  make_getter(&post_t::xdata_t::datetime),
                  make_setter(&post_t::xdata_t::datetime))
    .add_property("account",
                  make_getter(&post_t::xdata_t::account,
                              return_internal_reference<>()),
                  make_setter(&post_t::xdata_t::account,
                              with_custodian_and_ward<1, 2>()))
    .add_property("sort_values",
                  make_getter(&post_t::xdata_t::sort_values),
                  make_setter(&post_t::xdata_t::sort_values))
    ;

  scope().attr("POST_VIRTUAL")         = POST_VIRTUAL;
  scope().attr("POST_MUST_BALANCE")    = POST_MUST_BALANCE;
  scope().attr("POST_CALCULATED")      = POST_CALCULATED;
  scope().attr("POST_COST_CALCULATED") = POST_COST_CALCULATED;

  class_< post_t, bases<item_t> > ("Posting")
    //.def(init<account_t *>())

    .def("id", &post_t::id)
    .def("seq", &post_t::seq)

    .add_property("xact",
                  make_getter(&post_t::xact,
                              return_internal_reference<>()),
                  make_setter(&post_t::xact,
                              with_custodian_and_ward<1, 2>()))
    .add_property("account",
                  make_getter(&post_t::account,
                              return_internal_reference<>()),
                  make_setter(&post_t::account,
                              with_custodian_and_ward<1, 2>()))
    .add_property("amount",
                  make_getter(&post_t::amount),
                  make_setter(&post_t::amount))
    .add_property("cost",
                  make_getter(&post_t::cost,
                              return_value_policy<return_by_value>()),
                  make_setter(&post_t::cost,
                              return_value_policy<return_by_value>()))
    .add_property("assigned_amount",
                  make_getter(&post_t::assigned_amount,
                              return_value_policy<return_by_value>()),
                  make_setter(&post_t::assigned_amount,
                              return_value_policy<return_by_value>()))

    .def("has_tag", py_has_tag_1s)
    .def("has_tag", py_has_tag_1m)
    .def("has_tag", py_has_tag_2m)
    .def("get_tag", py_get_tag_1s)
    .def("get_tag", py_get_tag_1m)
    .def("get_tag", py_get_tag_2m)

    .add_property("date", &post_t::date)
    .add_property("aux_date", &post_t::aux_date)

    .def("must_balance", &post_t::must_balance)

    .def("lookup", &post_t::lookup)

    .def("valid", &post_t::valid)

    .def("has_xdata", &post_t::has_xdata)
    .def("clear_xdata", &post_t::clear_xdata)
    .def("xdata", py_xdata, return_internal_reference<>())

    //.def("add_to_value", &post_t::add_to_value)
    .def("set_reported_account", &post_t::set_reported_account)

    .def("reported_account", py_reported_account,
         return_internal_reference<>())
    ;
}

} // namespace ledger
<commit_msg>Expose post_t::given_cost over python<commit_after>/*
 * Copyright (c) 2003-2018, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "pyinterp.h"
#include "post.h"
#include "xact.h"

namespace ledger {

using namespace boost::python;

namespace {

  bool py_has_tag_1s(post_t& post, const string& tag) {
    return post.has_tag(tag);
  }
  bool py_has_tag_1m(post_t& post, const mask_t& tag_mask) {
    return post.has_tag(tag_mask);
  }
  bool py_has_tag_2m(post_t& post, const mask_t& tag_mask,
                     const boost::optional<mask_t>& value_mask) {
    return post.has_tag(tag_mask, value_mask);
  }

  boost::optional<value_t> py_get_tag_1s(post_t& post, const string& tag) {
    return post.get_tag(tag);
  }
  boost::optional<value_t> py_get_tag_1m(post_t& post, const mask_t& tag_mask) {
    return post.get_tag(tag_mask);
  }
  boost::optional<value_t> py_get_tag_2m(post_t& post, const mask_t& tag_mask,
                                         const boost::optional<mask_t>& value_mask) {
    return post.get_tag(tag_mask, value_mask);
  }

  post_t::xdata_t& py_xdata(post_t& post) {
    return post.xdata();
  }

  account_t * py_reported_account(post_t& post) {
    return post.reported_account();
  }

} // unnamed namespace

void export_post()
{
  scope().attr("POST_EXT_RECEIVED")    = POST_EXT_RECEIVED;
  scope().attr("POST_EXT_HANDLED")     = POST_EXT_HANDLED;
  scope().attr("POST_EXT_DISPLAYED")   = POST_EXT_DISPLAYED;
  scope().attr("POST_EXT_DIRECT_AMT")  = POST_EXT_DIRECT_AMT;
  scope().attr("POST_EXT_SORT_CALC")   = POST_EXT_SORT_CALC;
  scope().attr("POST_EXT_COMPOUND")    = POST_EXT_COMPOUND;
  scope().attr("POST_EXT_VISITED")     = POST_EXT_VISITED;
  scope().attr("POST_EXT_MATCHES")     = POST_EXT_MATCHES;
  scope().attr("POST_EXT_CONSIDERED")  = POST_EXT_CONSIDERED;

  class_< post_t::xdata_t > ("PostingXData")
#if 1
    .add_property("flags",
                  &supports_flags<uint_least16_t>::flags,
                  &supports_flags<uint_least16_t>::set_flags)
    .def("has_flags", &supports_flags<uint_least16_t>::has_flags)
    .def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
    .def("add_flags", &supports_flags<uint_least16_t>::add_flags)
    .def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
#endif

    .add_property("visited_value",
                  make_getter(&post_t::xdata_t::visited_value),
                  make_setter(&post_t::xdata_t::visited_value))
    .add_property("compound_value",
                  make_getter(&post_t::xdata_t::compound_value),
                  make_setter(&post_t::xdata_t::compound_value))
    .add_property("total",
                  make_getter(&post_t::xdata_t::total),
                  make_setter(&post_t::xdata_t::total))
    .add_property("count",
                  make_getter(&post_t::xdata_t::count),
                  make_setter(&post_t::xdata_t::count))
    .add_property("date",
                  make_getter(&post_t::xdata_t::date),
                  make_setter(&post_t::xdata_t::date))
    .add_property("datetime",
                  make_getter(&post_t::xdata_t::datetime),
                  make_setter(&post_t::xdata_t::datetime))
    .add_property("account",
                  make_getter(&post_t::xdata_t::account,
                              return_internal_reference<>()),
                  make_setter(&post_t::xdata_t::account,
                              with_custodian_and_ward<1, 2>()))
    .add_property("sort_values",
                  make_getter(&post_t::xdata_t::sort_values),
                  make_setter(&post_t::xdata_t::sort_values))
    ;

  scope().attr("POST_VIRTUAL")         = POST_VIRTUAL;
  scope().attr("POST_MUST_BALANCE")    = POST_MUST_BALANCE;
  scope().attr("POST_CALCULATED")      = POST_CALCULATED;
  scope().attr("POST_COST_CALCULATED") = POST_COST_CALCULATED;

  class_< post_t, bases<item_t> > ("Posting")
    //.def(init<account_t *>())

    .def("id", &post_t::id)
    .def("seq", &post_t::seq)

    .add_property("xact",
                  make_getter(&post_t::xact,
                              return_internal_reference<>()),
                  make_setter(&post_t::xact,
                              with_custodian_and_ward<1, 2>()))
    .add_property("account",
                  make_getter(&post_t::account,
                              return_internal_reference<>()),
                  make_setter(&post_t::account,
                              with_custodian_and_ward<1, 2>()))
    .add_property("amount",
                  make_getter(&post_t::amount),
                  make_setter(&post_t::amount))
    .add_property("cost",
                  make_getter(&post_t::cost,
                              return_value_policy<return_by_value>()),
                  make_setter(&post_t::cost,
                              return_value_policy<return_by_value>()))
    .add_property("given_cost",
                  make_getter(&post_t::given_cost,
                              return_value_policy<return_by_value>()),
                  make_setter(&post_t::given_cost,
                              return_value_policy<return_by_value>()))
    .add_property("assigned_amount",
                  make_getter(&post_t::assigned_amount,
                              return_value_policy<return_by_value>()),
                  make_setter(&post_t::assigned_amount,
                              return_value_policy<return_by_value>()))

    .def("has_tag", py_has_tag_1s)
    .def("has_tag", py_has_tag_1m)
    .def("has_tag", py_has_tag_2m)
    .def("get_tag", py_get_tag_1s)
    .def("get_tag", py_get_tag_1m)
    .def("get_tag", py_get_tag_2m)

    .add_property("date", &post_t::date)
    .add_property("aux_date", &post_t::aux_date)

    .def("must_balance", &post_t::must_balance)

    .def("lookup", &post_t::lookup)

    .def("valid", &post_t::valid)

    .def("has_xdata", &post_t::has_xdata)
    .def("clear_xdata", &post_t::clear_xdata)
    .def("xdata", py_xdata, return_internal_reference<>())

    //.def("add_to_value", &post_t::add_to_value)
    .def("set_reported_account", &post_t::set_reported_account)

    .def("reported_account", py_reported_account,
         return_internal_reference<>())
    ;
}

} // namespace ledger
<|endoftext|>