<commit_before>#include <algorithm>
#include <fstream>
#include <iostream>
#include <regex>
#include <SDL.h>
#include <SDL_image.h>
//#include <unistd.h>
//#include <rpc.h>

#include "DirectoryScanner.hh"

const auto company = u8"即死ゲーム開発会社";
const auto product = "image viewer ++";
const int defaultWidth = 800;
const int defaultHeight = 600;

void newImage(SDL_Window *window, SDL_Surface *screen, const std::string &path, float scale, SDL_Rect &offset, bool resizeWindow = false)
{
    SDL_FillRect(screen, nullptr, 0);

    auto image = IMG_Load(path.c_str());

    SDL_Rect imageSize;

    SDL_GetClipRect(image, &imageSize);

    if (resizeWindow) {
        if (imageSize.w > imageSize.h) {
            auto width = defaultWidth;
            auto height = static_cast<int>(static_cast<float>(imageSize.h) / static_cast<float>(imageSize.w) * defaultWidth);
            SDL_SetWindowSize(window, width, height);
        } else {
            auto width = static_cast<int>(static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h) * defaultHeight);
            auto height = defaultHeight;
            SDL_SetWindowSize(window, width, height);
        }

        screen = SDL_GetWindowSurface(window);
    }

    SDL_Rect windowSize;

    SDL_GetClipRect(screen, &windowSize);

    float num1;
    float num2;

    if (imageSize.w > imageSize.h) {
        num1 = static_cast<float>(windowSize.w);
        num2 = static_cast<float>(windowSize.w) * static_cast<float>(imageSize.h) / static_cast<float>(imageSize.w);

        if (num2 > static_cast<float>(windowSize.h)) {
            num1 = static_cast<float>(windowSize.h) * static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h);
            num2 = static_cast<float>(windowSize.h);
        }
    } else {
        num1 = static_cast<float>(windowSize.h) * static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h);
        num2 = static_cast<float>(windowSize.h);

        if (num1 > static_cast<float>(windowSize.w)) {
            num1 = static_cast<float>(windowSize.w);
            num2 = static_cast<float>(windowSize.w) * static_cast<float>(imageSize.h) / static_cast<float>(imageSize.w);
        }
    }

    float width1 = num1 * scale;
    float height1 = num2 * scale;
    float x1 = static_cast<float>(windowSize.w) / 2.0f - width1 / 2.0f;
    float y1 = static_cast<float>(windowSize.h) / 2.0f - height1 / 2.0f;

    if (scale > 1.0) {
        if (width1 >= windowSize.w && offset.x - width1 / 2.0f + windowSize.w / 2.0f > 0.0f) {
            offset.x = static_cast<int>(width1 / 2.0f - windowSize.w / 2.0f);
        }

        if (height1 >= windowSize.h && offset.y - height1 / 2.0f + windowSize.h / 2.0f > 0.0f) {
            offset.y = static_cast<int>(height1 / 2.0f - windowSize.h / 2.0f);
        }

        if (width1 >= windowSize.w && offset.x + width1 / 2.0f - windowSize.w / 2.0f < 0.0f) {
            offset.x = static_cast<int>(windowSize.w / 2.0f - width1 / 2.0f);
        }

        if (height1 >= windowSize.h && offset.y + height1 / 2.0 - windowSize.h / 2.0f < 0.0f) {
            offset.y = static_cast<int>(windowSize.h / 2.0f - height1 / 2.0f);
        }

        x1 = static_cast<float>(windowSize.w) / 2.0f - width1 / 2.0f + offset.x;
        y1 = static_cast<float>(windowSize.h) / 2.0f - height1 / 2.0f + offset.y;
    }

    SDL_Rect imagePosition;

    imagePosition.x = static_cast<int>(x1);
    imagePosition.y = static_cast<int>(y1);
    imagePosition.w = static_cast<int>(width1);
    imagePosition.h = static_cast<int>(height1);

    SDL_SetWindowTitle(window, path.c_str());

    SDL_BlitScaled(image, nullptr, screen, &imagePosition);

    SDL_FreeSurface(image);

    SDL_UpdateWindowSurface(window);

    SDL_FlushEvent(SDL_KEYDOWN);
    SDL_FlushEvent(SDL_MOUSEWHEEL);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "usage: " << argv[0] << " <image>" << std::endl;

        return EXIT_FAILURE;
    }

    std::string argument(argv[1]);

    if (argument.find('\\') != std::string::npos) {
        std::replace(argument.begin(), argument.end(), '\\', '/');
    }

    auto lastSeparator = argument.rfind('/');
    std::string directory;

    if (lastSeparator != std::string::npos) {
        directory = argument.substr(0, lastSeparator);
    } else {
        directory = ".";
    }

    std::cout << directory << std::endl;

    SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
    IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);

    SDL_Rect windowSize = { 0 };
    windowSize.w = defaultWidth;
    windowSize.h = defaultHeight;

    SDL_Window *window = SDL_CreateWindow(product, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, defaultWidth,
        defaultHeight,
        SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL);
    SDL_Surface *screen = SDL_GetWindowSurface(window);

    auto path = SDL_GetPrefPath(company, product);

    auto pathFull = path + std::string("config.ini");

    std::cout << path << std::endl;

    SDL_RWops *file = SDL_RWFromFile(pathFull.c_str(), "w");

    SDL_RWwrite(file, "Hello, world!", 1, 13);
    SDL_RWclose(file);

    SDL_free(path);

    DirectoryScanner scanner(directory, 0);

    auto list = scanner.enumerate();
    auto current = std::find(list.cbegin(), list.cend(), argument);

    bool alive = true;
    bool zooming = false;
    bool resizing = false;
    bool moving = false;
    std::tuple<int, int> origin;
    float scale = 1.0f;
    SDL_Rect offset = { 0 };

    newImage(window, screen, *current, scale, offset, true);

    while (alive) {
        SDL_Event event;

        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_KEYDOWN:
                    switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
                            alive = false;
                            break;

                        case SDLK_LEFT:
                            if (current == list.cbegin()) {
                                current = list.cend();
                            }

                            --current;

                            scale = 1.0f;
                            offset = { 0 };
                            newImage(window, screen, *current, scale, offset);
                            break;

                        case SDLK_RIGHT:
                            ++current;

                            if (current == list.cend()) {
                                current = list.cbegin();
                            }

                            scale = 1.0f;
                            offset = { 0 };
                            newImage(window, screen, *current, scale, offset);
                            break;

                        case SDLK_TAB:
                            zooming = !zooming;

                            break;

                        case SDLK_LSHIFT:
                            resizing = true;
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDLK_LCTRL:
                            moving = true;
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDLK_SPACE:
                            if ((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) {
                                newImage(window, screen, *current, scale, offset, true);
                            } else {
                                auto image = IMG_Load(current->c_str());

                                SDL_Rect imageSize;
                                SDL_Rect realWindowSize;
                                SDL_GetClipRect(image, &imageSize);
                                SDL_GetClipRect(screen, &realWindowSize);

                                SDL_FreeSurface(image);

                                scale = static_cast<float>(realWindowSize.w) / (static_cast<float>(realWindowSize.h) * static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h));
                                offset.x = 0;
                                offset.y = static_cast<int>(static_cast<float>(imageSize.h) / 2.0f * scale);
                                newImage(window, screen, *current, scale, offset);
                            }

                            break;

                        default:
                            break;
                    }
                    break;

                case SDL_KEYUP:
                    if (event.key.keysym.sym == SDLK_LSHIFT) {
                        resizing = false;
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                    } else if (event.key.keysym.sym == SDLK_LCTRL) {
                        moving = false;
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                    }

                    break;

                case SDL_MOUSEWHEEL:
                    if (!zooming) {
                        if (event.wheel.y > 0) {
                            if (current == list.cbegin()) {
                                current = list.cend();
                            }

                            --current;
                        } else {
                            ++current;

                            if (current == list.cend()) {
                                current = list.cbegin();
                            }
                        }

                        scale = 1.0f;
                        offset = { 0 };
                        newImage(window, screen, *current, scale, offset);
                    } else {
                        if (event.wheel.y > 0) {
                            scale *= 1.4128f;
                        } else {
                            scale *= 0.7078143f;
                        }

                        newImage(window, screen, *current, scale, offset);
                    }

                    break;

                case SDL_MOUSEBUTTONDOWN:
                    switch (event.button.button) {
                        case SDL_BUTTON_LEFT:
                            if (event.button.clicks == 1) {
                                moving = true;
                                SDL_SetRelativeMouseMode(SDL_TRUE);
                            } else if (event.button.clicks == 2) {
                                if ((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) {
                                    SDL_MaximizeWindow(window);
                                    SDL_Rect maximizedSize;
                                    SDL_Surface *maximizedScreen = SDL_GetWindowSurface(window);
                                    SDL_GetClipRect(maximizedScreen, &maximizedSize);
                                    SDL_WarpMouseInWindow(window, maximizedSize.w / 2, maximizedSize.h / 2);
                                } else {
                                    SDL_RestoreWindow(window);
                                    SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                                }
                            }

                            break;

                        case SDL_BUTTON_RIGHT:
                            resizing = true;
                            origin = std::make_tuple(0, 0);
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDL_BUTTON_MIDDLE:
                            alive = false;

                            break;

                        default:
                            break;
                    }

                    break;

                case SDL_MOUSEBUTTONUP:
                    if (moving || resizing) {
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                        SDL_FlushEvent(SDL_MOUSEBUTTONDOWN);
                    }

                    switch (event.button.button) {
                        case SDL_BUTTON_LEFT:
                            moving = false;
                            origin = std::make_tuple(-1, -1);

                            break;

                        case SDL_BUTTON_RIGHT:
                            resizing = false;

                            break;

                        default:
                            break;
                    }

                    break;

                case SDL_MOUSEMOTION:
                    if (((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) && resizing) {
                        windowSize.w = std::max(0, windowSize.w + event.motion.xrel);
                        windowSize.h = std::max(0, windowSize.h + event.motion.yrel);
                        SDL_SetWindowSize(window, windowSize.w, windowSize.h);
                        origin = std::make_tuple(event.motion.x, event.motion.y);
                    } else if (moving) {
                        if (zooming) {
                            offset.x += event.motion.xrel;
                            offset.y += event.motion.yrel;
                            newImage(window, screen, *current, scale, offset);
                        } else if (((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0)) {
                            windowSize.x += event.motion.xrel;
                            windowSize.y += event.motion.yrel;
                            SDL_SetWindowPosition(window, windowSize.x, windowSize.y);
                        }
                    }

                    break;

                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_SIZE_CHANGED:
                            screen = SDL_GetWindowSurface(window);
                            newImage(window, screen, *current, scale, offset);
                            break;

                        default:
                            break;
                    }

                    break;

                default:
                    break;
            }
        }
    }

    SDL_SetRelativeMouseMode(SDL_FALSE);
    SDL_ShowCursor(1);

    IMG_Quit();

    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}
<commit_msg>Start to clean up newImage()<commit_after>#include <algorithm>
#include <fstream>
#include <iostream>
#include <regex>
#include <SDL.h>
#include <SDL_image.h>
//#include <unistd.h>
//#include <rpc.h>

#include "DirectoryScanner.hh"

const auto company = u8"即死ゲーム開発会社";
const auto product = "image viewer ++";
const int defaultWidth = 800;
const int defaultHeight = 600;

void newImage(SDL_Window *window, SDL_Surface *screen, const std::string &path, float scale, SDL_Rect &offset, bool resizeWindow = false)
{
    SDL_FillRect(screen, nullptr, 0);

    auto image = IMG_Load(path.c_str());

    SDL_Rect imageSize;

    SDL_GetClipRect(image, &imageSize);

    if (resizeWindow) {
        if (imageSize.w > imageSize.h) {
            auto width = defaultWidth;
            auto height = static_cast<int>(static_cast<float>(imageSize.h) / static_cast<float>(imageSize.w) * defaultWidth);
            SDL_SetWindowSize(window, width, height);
        } else {
            auto width = static_cast<int>(static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h) * defaultHeight);
            auto height = defaultHeight;
            SDL_SetWindowSize(window, width, height);
        }

        screen = SDL_GetWindowSurface(window);
    }

    SDL_Rect windowSize;

    SDL_GetClipRect(screen, &windowSize);

    int windowWidth;
    int windowHeight;

    SDL_GetWindowSize(window, &windowWidth, &windowHeight);

    float imageWidthCorrected;
    float imageHeightCorrected;
    float imageWidthUnscaled = imageSize.w;
    float imageHeightUnscaled = imageSize.h;

    if (imageWidthUnscaled> imageHeightUnscaled) {
        imageWidthCorrected = static_cast<float>(windowWidth);
        imageHeightCorrected = static_cast<float>(windowWidth) * imageHeightUnscaled / imageWidthUnscaled;

        if (imageHeightCorrected > static_cast<float>(windowHeight)) {
            imageWidthCorrected = static_cast<float>(windowHeight) * imageWidthUnscaled / imageHeightUnscaled;
            imageHeightCorrected = static_cast<float>(windowHeight);
        }
    } else {
        imageWidthCorrected = static_cast<float>(windowHeight) * imageWidthUnscaled / imageHeightUnscaled;
        imageHeightCorrected = static_cast<float>(windowHeight);

        if (imageWidthCorrected > static_cast<float>(windowWidth)) {
            imageWidthCorrected = static_cast<float>(windowWidth);
            imageHeightCorrected = static_cast<float>(windowWidth) * imageHeightUnscaled / imageWidthUnscaled;
        }
    }

    float imageWidth = imageWidthCorrected * scale;
    float imageHeight = imageHeightCorrected * scale;
    float halfImageWidth = imageWidth / 2.0f;
    float halfImageHeight = imageHeight / 2.0f;
    float halfWindowWidth = windowWidth / 2.0f;
    float halfWindowHeight = windowHeight / 2.0f;
    float imageAbscissa = halfWindowWidth - halfImageWidth;
    float imageOrdinate = halfWindowHeight - halfImageHeight;

    if (scale > 1.0) {
        if (imageWidth >= windowWidth && offset.x - halfImageWidth + halfWindowWidth > 0.0f) {
            offset.x = static_cast<int>(halfImageWidth - halfWindowWidth);
        }

        if (imageHeight >= windowHeight && offset.y - halfImageHeight + halfWindowHeight > 0.0f) {
            offset.y = static_cast<int>(halfImageHeight - halfWindowHeight);
        }

        if (imageWidth >= windowWidth && offset.x + halfImageWidth - halfWindowWidth < 0.0f) {
            offset.x = static_cast<int>(halfWindowWidth - halfImageWidth);
        }

        if (imageHeight >= windowHeight && offset.y + imageHeight / 2.0 - halfWindowHeight < 0.0f) {
            offset.y = static_cast<int>(halfWindowHeight - halfImageHeight);
        }

        imageAbscissa = halfWindowWidth - halfImageWidth + offset.x;
        imageOrdinate = halfWindowHeight - halfImageHeight + offset.y;
    }

    SDL_Rect imagePosition;

    imagePosition.x = static_cast<int>(imageAbscissa);
    imagePosition.y = static_cast<int>(imageOrdinate);
    imagePosition.w = static_cast<int>(imageWidth);
    imagePosition.h = static_cast<int>(imageHeight);

    SDL_SetWindowTitle(window, path.c_str());

    SDL_BlitScaled(image, nullptr, screen, &imagePosition);

    SDL_FreeSurface(image);

    SDL_UpdateWindowSurface(window);

    SDL_FlushEvent(SDL_KEYDOWN);
    SDL_FlushEvent(SDL_MOUSEWHEEL);
    SDL_FlushEvent(SDL_MOUSEMOTION);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "usage: " << argv[0] << " <image>" << std::endl;

        return EXIT_FAILURE;
    }

    std::string argument(argv[1]);

    if (argument.find('\\') != std::string::npos) {
        std::replace(argument.begin(), argument.end(), '\\', '/');
    }

    auto lastSeparator = argument.rfind('/');
    std::string directory;

    if (lastSeparator != std::string::npos) {
        directory = argument.substr(0, lastSeparator);
    } else {
        directory = ".";
    }

    std::cout << directory << std::endl;

    SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
    IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);

    SDL_Rect windowSize = { 0 };
    windowSize.w = defaultWidth;
    windowSize.h = defaultHeight;

    SDL_Window *window = SDL_CreateWindow(product, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, defaultWidth,
        defaultHeight,
        SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL);
    SDL_Surface *screen = SDL_GetWindowSurface(window);

    auto path = SDL_GetPrefPath(company, product);

    auto pathFull = path + std::string("config.ini");

    std::cout << path << std::endl;

    SDL_RWops *file = SDL_RWFromFile(pathFull.c_str(), "w");

    SDL_RWwrite(file, "Hello, world!", 1, 13);
    SDL_RWclose(file);

    SDL_free(path);

    DirectoryScanner scanner(directory, 0);

    auto list = scanner.enumerate();
    auto current = std::find(list.cbegin(), list.cend(), argument);

    bool alive = true;
    bool zooming = false;
    bool resizing = false;
    bool moving = false;
    std::tuple<int, int> origin;
    float scale = 1.0f;
    SDL_Rect offset = { 0 };

    newImage(window, screen, *current, scale, offset, true);

    while (alive) {
        SDL_Event event;

        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_KEYDOWN:
                    switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
                            alive = false;
                            break;

                        case SDLK_LEFT:
                            if (current == list.cbegin()) {
                                current = list.cend();
                            }

                            --current;

                            scale = 1.0f;
                            offset = { 0 };
                            newImage(window, screen, *current, scale, offset);
                            break;

                        case SDLK_RIGHT:
                            ++current;

                            if (current == list.cend()) {
                                current = list.cbegin();
                            }

                            scale = 1.0f;
                            offset = { 0 };
                            newImage(window, screen, *current, scale, offset);
                            break;

                        case SDLK_TAB:
                            zooming = !zooming;

                            break;

                        case SDLK_LSHIFT:
                            resizing = true;
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDLK_LCTRL:
                            moving = true;
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDLK_SPACE:
                            if ((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) {
                                newImage(window, screen, *current, scale, offset, true);
                            } else {
                                auto image = IMG_Load(current->c_str());

                                SDL_Rect imageSize;
                                SDL_Rect realWindowSize;
                                SDL_GetClipRect(image, &imageSize);
                                SDL_GetClipRect(screen, &realWindowSize);

                                SDL_FreeSurface(image);

                                scale = static_cast<float>(realWindowSize.w) / (static_cast<float>(realWindowSize.h) * static_cast<float>(imageSize.w) / static_cast<float>(imageSize.h));
                                offset.x = 0;
                                offset.y = static_cast<int>(static_cast<float>(imageSize.h) / 2.0f * scale);
                                newImage(window, screen, *current, scale, offset);
                            }

                            break;

                        default:
                            break;
                    }
                    break;

                case SDL_KEYUP:
                    if (event.key.keysym.sym == SDLK_LSHIFT) {
                        resizing = false;
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                    } else if (event.key.keysym.sym == SDLK_LCTRL) {
                        moving = false;
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                    }

                    break;

                case SDL_MOUSEWHEEL:
                    if (!zooming) {
                        if (event.wheel.y > 0) {
                            if (current == list.cbegin()) {
                                current = list.cend();
                            }

                            --current;
                        } else {
                            ++current;

                            if (current == list.cend()) {
                                current = list.cbegin();
                            }
                        }

                        scale = 1.0f;
                        offset = { 0 };
                        newImage(window, screen, *current, scale, offset);
                    } else {
                        if (event.wheel.y > 0) {
                            scale *= 1.4128f;
                        } else {
                            scale *= 0.7078143f;
                        }

                        newImage(window, screen, *current, scale, offset);
                    }

                    break;

                case SDL_MOUSEBUTTONDOWN:
                    switch (event.button.button) {
                        case SDL_BUTTON_LEFT:
                            if (event.button.clicks == 1) {
                                moving = true;
                                SDL_SetRelativeMouseMode(SDL_TRUE);
                            } else if (event.button.clicks == 2) {
                                if ((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) {
                                    SDL_MaximizeWindow(window);
                                    SDL_Rect maximizedSize;
                                    SDL_Surface *maximizedScreen = SDL_GetWindowSurface(window);
                                    SDL_GetClipRect(maximizedScreen, &maximizedSize);
                                    SDL_WarpMouseInWindow(window, maximizedSize.w / 2, maximizedSize.h / 2);
                                } else {
                                    SDL_RestoreWindow(window);
                                    SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                                }
                            }

                            break;

                        case SDL_BUTTON_RIGHT:
                            resizing = true;
                            origin = std::make_tuple(0, 0);
                            SDL_SetRelativeMouseMode(SDL_TRUE);

                            break;

                        case SDL_BUTTON_MIDDLE:
                            alive = false;

                            break;

                        default:
                            break;
                    }

                    break;

                case SDL_MOUSEBUTTONUP:
                    if (moving || resizing) {
                        SDL_SetRelativeMouseMode(SDL_FALSE);
                        SDL_WarpMouseInWindow(window, windowSize.w / 2, windowSize.h / 2);
                        SDL_FlushEvent(SDL_MOUSEBUTTONDOWN);
                    }

                    switch (event.button.button) {
                        case SDL_BUTTON_LEFT:
                            moving = false;
                            origin = std::make_tuple(-1, -1);

                            break;

                        case SDL_BUTTON_RIGHT:
                            resizing = false;

                            break;

                        default:
                            break;
                    }

                    break;

                case SDL_MOUSEMOTION:
                    if (((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0) && resizing) {
                        windowSize.w = std::max(0, windowSize.w + event.motion.xrel);
                        windowSize.h = std::max(0, windowSize.h + event.motion.yrel);
                        SDL_SetWindowSize(window, windowSize.w, windowSize.h);
                        origin = std::make_tuple(event.motion.x, event.motion.y);
                    } else if (moving) {
                        if (zooming) {
                            offset.x += event.motion.xrel;
                            offset.y += event.motion.yrel;
                            newImage(window, screen, *current, scale, offset);
                        } else if (((SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) == 0)) {
                            windowSize.x += event.motion.xrel;
                            windowSize.y += event.motion.yrel;
                            SDL_SetWindowPosition(window, windowSize.x, windowSize.y);
                        }
                    }

                    break;

                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_SIZE_CHANGED:
                            screen = SDL_GetWindowSurface(window);
                            newImage(window, screen, *current, scale, offset);
                            break;

                        default:
                            break;
                    }

                    break;

                default:
                    break;
            }
        }
    }

    SDL_SetRelativeMouseMode(SDL_FALSE);
    SDL_ShowCursor(1);

    IMG_Quit();

    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>56ca575e-ad59-11e7-9a12-ac87a332f658<commit_msg>more bug fix<commit_after>57401861-ad59-11e7-a8e9-ac87a332f658<|endoftext|>


<commit_before>#include "api.hpp"
#include "system.hpp"
#include "threadpool.hpp"
#include "command.hpp"

#include "string.h"
#include <string>
#include <iostream>
#include <cstdlib>

using namespace std;

char *command;
void PrintUsage() {
    cerr << "Usage:" << endl;
    cerr << "\t" << command << " [-v] [-q] [-n nthreads] [--] <command> <arguments...>" << endl;
    cerr << endl;
    cerr << "\t\t-v\t\trun verbose" << endl;
    cerr << "\t\t-q\t\trun quiet" << endl;
    cerr << "\t\t-n nthreads\tuse nthreads threads" << endl;
    cerr << "\t\t--\t\tend option parsing" << endl;
    cerr << endl;
    cerr << "\tPlaceholders:" << endl;
    cerr << "\t\tYou can use {} or {i} with i a non-negative integer to refer to placeholders." << endl;
    cerr << "\t\texamples:" << endl;
    cerr << "\t\t\t- ls {}" << endl;
    cerr << "\t\t\t- cat {1} {0}" << endl;
    cerr << "\t\tYou can use bash-style replacements:" << endl;
    cerr << "\t\t\t- mv {} {0/%txt/md}" << endl;
    cerr << endl;
    cerr << "\tExample usage:" << endl;
    cerr << "\t\tThe current directory contains story1, story1.part2, story2 and story2.part2." << endl;
    cerr << "\t\tRunning the following command will result in the files *.part2 being appended" << endl;
    cerr << "\t\tto the other files and being removed:" << endl;
    cerr << "\t\t\t" << command << " 'cat {} >> {} && rm {0}' '*.part2' 'story{1,2}'" << endl;
    cerr << "\t\tThe current directory contains story1.part1, story1.part2, story2.part1 and" << endl;
    cerr << "\t\tstory2.part2. To create files story1 and story2 containing the entire stories:" << endl;
    cerr << "\t\t\t" << command << " 'cat {} {0/%1/2} > {0/%.part1/}' \\*.part1" << endl;
}

bool matchesNoArg(const char *str, const char *pattern) {
    return !strcmp(str, pattern);
}

bool matchesWithArg(const char *str, const char *pattern, const char **begin, int &index) {
    if (!strcmp(str, pattern))
        return true;

    size_t len = strlen(pattern);
    for (size_t i = 0; i < len; i++) {
        if (str[i] != pattern[i])
            return false;
    }

    *begin = str + len;
    if (**begin == '=')
        (*begin)++;

    index++;
    return true;
}

int main(int argc, char **argv) {
    command = argv[0];

    if (argc == 1) {
        PrintUsage();
        return -1;
    }

    uint nbThreads = worker::System::getNbCores();

    int argpos = 1;
    for (; argpos < argc; argpos++) {
        const char *curr = argv[argpos];
        const char *next = (argpos == argc - 1) ? NULL : argv[argpos+1];
        if (matchesWithArg(curr, "-n", &next, argpos) || matchesWithArg(curr, "--nthreads", &next, argpos)) {
            if (next == NULL) {
                PrintUsage();
                worker::Fatal("No argument given for \"-n\"");
            }
            int _nbThreads = atoi(next);
            if (_nbThreads < 0) {
                worker::Fatal("Number of threads must be positive, not %d", _nbThreads);
            }
            nbThreads = static_cast<uint>(_nbThreads);
        } else
        if (matchesNoArg(curr, "-h") || matchesNoArg(curr, "--help")) {
            PrintUsage();
            return 1;
        } else
        if (matchesNoArg(curr, "-q") || matchesNoArg(curr, "--quiet")) {
            worker::quiet = true;
            worker::verbose = false;
        } else
        if (matchesNoArg(curr, "-v") || matchesNoArg(curr, "--verbose")) {
            worker::quiet = false;
            worker::verbose = true;
        } else
        if (matchesNoArg(curr, "--")) {
            argpos++;
            break;
        } else
            break;
    }

    worker::Command command(argv[argpos]);
    const uint nbPlaceholders = command.getNbPlaceholders();
    argpos++;

    worker::Debug("Parsed command with %u placeholders", nbPlaceholders);

    if (nbPlaceholders != static_cast<uint>(argc - argpos)) {
        worker::Fatal("Invalid number of arguments given, expected %d placeholder arguments but got %d", nbPlaceholders, argc - argpos + 1);
    }

    vector<string> *jobArguments = new vector<string>[nbPlaceholders];

    for (uint idx = 0; argpos < argc; argpos++, idx++) {
        jobArguments[idx] = worker::parseGlob(argv[argpos]);
    }

    if (nbPlaceholders > 0) {
        uint nbJobs = jobArguments[0].size();
        for (uint i = 1; i < nbPlaceholders; i++) {
            if (jobArguments[i].size() != nbJobs) {
                worker::Fatal("Placeholder %u matches %u items while placeholder 0 matches %u items!", i, jobArguments[i].size(), nbJobs);
            }
        }
    }

    uint nbJobs = (nbPlaceholders == 0) ? 1 : jobArguments[0].size();
    worker::Debug("Using %u jobs", nbJobs);

    worker::ThreadPool threadPool(min(nbThreads, nbJobs));

    for (uint i = 0; i < nbJobs; i++) {
        vector<string> thisArgs;

        for (uint j = 0; j < nbPlaceholders; j++)
            thisArgs.push_back(jobArguments[j][i]);

        threadPool.schedule(command.fillArguments(thisArgs));
    }

    delete[] jobArguments;

    threadPool.join();
}<commit_msg>forgot to change error message<commit_after>#include "api.hpp"
#include "system.hpp"
#include "threadpool.hpp"
#include "command.hpp"

#include "string.h"
#include <string>
#include <iostream>
#include <cstdlib>

using namespace std;

char *command;
void PrintUsage() {
    cerr << "Usage:" << endl;
    cerr << "\t" << command << " [-v] [-q] [-n nthreads] [--] <command> <arguments...>" << endl;
    cerr << endl;
    cerr << "\t\t-v\t\trun verbose" << endl;
    cerr << "\t\t-q\t\trun quiet" << endl;
    cerr << "\t\t-n nthreads\tuse nthreads threads" << endl;
    cerr << "\t\t--\t\tend option parsing" << endl;
    cerr << endl;
    cerr << "\tPlaceholders:" << endl;
    cerr << "\t\tYou can use {} or {i} with i a non-negative integer to refer to placeholders." << endl;
    cerr << "\t\texamples:" << endl;
    cerr << "\t\t\t- ls {}" << endl;
    cerr << "\t\t\t- cat {1} {0}" << endl;
    cerr << "\t\tYou can use bash-style replacements:" << endl;
    cerr << "\t\t\t- mv {} {0/%txt/md}" << endl;
    cerr << endl;
    cerr << "\tExample usage:" << endl;
    cerr << "\t\tThe current directory contains story1, story1.part2, story2 and story2.part2." << endl;
    cerr << "\t\tRunning the following command will result in the files *.part2 being appended" << endl;
    cerr << "\t\tto the other files and being removed:" << endl;
    cerr << "\t\t\t" << command << " 'cat {} >> {} && rm {0}' '*.part2' 'story{1,2}'" << endl;
    cerr << "\t\tThe current directory contains story1.part1, story1.part2, story2.part1 and" << endl;
    cerr << "\t\tstory2.part2. To create files story1 and story2 containing the entire stories:" << endl;
    cerr << "\t\t\t" << command << " 'cat {} {0/%1/2} > {0/%.part1/}' \\*.part1" << endl;
}

bool matchesNoArg(const char *str, const char *pattern) {
    return !strcmp(str, pattern);
}

bool matchesWithArg(const char *str, const char *pattern, const char **begin, int &index) {
    if (!strcmp(str, pattern))
        return true;

    size_t len = strlen(pattern);
    for (size_t i = 0; i < len; i++) {
        if (str[i] != pattern[i])
            return false;
    }

    *begin = str + len;
    if (**begin == '=')
        (*begin)++;

    index++;
    return true;
}

int main(int argc, char **argv) {
    command = argv[0];

    if (argc == 1) {
        PrintUsage();
        return -1;
    }

    uint nbThreads = worker::System::getNbCores();

    int argpos = 1;
    for (; argpos < argc; argpos++) {
        const char *curr = argv[argpos];
        const char *next = (argpos == argc - 1) ? NULL : argv[argpos+1];
        if (matchesWithArg(curr, "-n", &next, argpos) || matchesWithArg(curr, "--nthreads", &next, argpos)) {
            if (next == NULL) {
                PrintUsage();
                worker::Fatal("No argument given for \"-n\"");
            }
            int _nbThreads = atoi(next);
            if (_nbThreads < 0) {
                worker::Fatal("Number of threads must be positive, not %d", _nbThreads);
            }
            nbThreads = static_cast<uint>(_nbThreads);
        } else
        if (matchesNoArg(curr, "-h") || matchesNoArg(curr, "--help")) {
            PrintUsage();
            return 1;
        } else
        if (matchesNoArg(curr, "-q") || matchesNoArg(curr, "--quiet")) {
            worker::quiet = true;
            worker::verbose = false;
        } else
        if (matchesNoArg(curr, "-v") || matchesNoArg(curr, "--verbose")) {
            worker::quiet = false;
            worker::verbose = true;
        } else
        if (matchesNoArg(curr, "--")) {
            argpos++;
            break;
        } else
            break;
    }

    worker::Command command(argv[argpos]);
    const uint nbPlaceholders = command.getNbPlaceholders();
    argpos++;

    worker::Debug("Parsed command with %u placeholders", nbPlaceholders);

    if (nbPlaceholders != static_cast<uint>(argc - argpos)) {
        worker::Fatal("Invalid number of arguments given, expected %d placeholder arguments but got %d", nbPlaceholders, argc - argpos);
    }

    vector<string> *jobArguments = new vector<string>[nbPlaceholders];

    for (uint idx = 0; argpos < argc; argpos++, idx++) {
        jobArguments[idx] = worker::parseGlob(argv[argpos]);
    }

    if (nbPlaceholders > 0) {
        uint nbJobs = jobArguments[0].size();
        for (uint i = 1; i < nbPlaceholders; i++) {
            if (jobArguments[i].size() != nbJobs) {
                worker::Fatal("Placeholder %u matches %u items while placeholder 0 matches %u items!", i, jobArguments[i].size(), nbJobs);
            }
        }
    }

    uint nbJobs = (nbPlaceholders == 0) ? 1 : jobArguments[0].size();
    worker::Debug("Using %u jobs", nbJobs);

    worker::ThreadPool threadPool(min(nbThreads, nbJobs));

    for (uint i = 0; i < nbJobs; i++) {
        vector<string> thisArgs;

        for (uint j = 0; j < nbPlaceholders; j++)
            thisArgs.push_back(jobArguments[j][i]);

        threadPool.schedule(command.fillArguments(thisArgs));
    }

    delete[] jobArguments;

    threadPool.join();
}<|endoftext|>


<commit_before>c3ca9af3-4b02-11e5-8dc3-28cfe9171a43<commit_msg>add file<commit_after>c3dabcfa-4b02-11e5-b1b2-28cfe9171a43<|endoftext|>


<commit_before>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() {}

    Vec3(const float x, const float y, const float z)
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) {
    return Vec3 {
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

float dot(Vec3::InParam left, Vec3::InParam right) {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

// Vec3&& normalize(Vec3&& in) {
//     return Vec3
// }

float length(const float x, const float y) {
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) {
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) {
    return (from * (1.0f - t) + (to * t));
}

Vec3 sample_sky(const Vec3::InParam position, const Vec3::InParam direction) {
    const Vec3 forward{0.0f, 0.0f, 1.0f};
    const Vec3 right{1.0f, 0.0f, 0.0f};
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3 {red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction)
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(direction, world_up)};

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        return lerp(green, light_green, dot_up);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        return lerp(green, light_green, dot_up);
    }
}

Vec3 sample(const Vec3::InParam position, const Vec3::InParam direction) {

    // check for collision against sphere
    const Vec3 sphere_point(0.0f, 7.5f, 50.0f);
    const float sphere_magnitude = 5.0f;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            + length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        const Vec3 half {0.5f, 0.5f, 0.5f};
        const Vec3 color {(normal * 0.5f + half) * 255.0f};
        return color;
    }

    // check for collision against ground
    const Vec3 ground_point(0.0f, 0.0f, 0.0f);
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    const Vec3 to_ground {ground_point - position};
    if (dot(to_ground, direction) > 0.0f) {
        // hit the ground, figure out where
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        return sample_ground(ground_intersection, direction);
    }

    return sample_sky(position, direction);
}

void draw_scene(const int image_width, const int image_height) {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3 {
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}
<commit_msg>Tidy: remove commented-out code<commit_after>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() {}

    Vec3(const float x, const float y, const float z)
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) {
    return Vec3 {
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

float dot(Vec3::InParam left, Vec3::InParam right) {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

float length(const float x, const float y) {
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) {
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) {
    return (from * (1.0f - t) + (to * t));
}

Vec3 sample_sky(const Vec3::InParam position, const Vec3::InParam direction) {
    const Vec3 forward{0.0f, 0.0f, 1.0f};
    const Vec3 right{1.0f, 0.0f, 0.0f};
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3 {red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction)
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(direction, world_up)};

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        return lerp(green, light_green, dot_up);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        return lerp(green, light_green, dot_up);
    }
}

Vec3 sample(const Vec3::InParam position, const Vec3::InParam direction) {

    // check for collision against sphere
    const Vec3 sphere_point(0.0f, 7.5f, 50.0f);
    const float sphere_magnitude = 5.0f;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            + length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        const Vec3 half {0.5f, 0.5f, 0.5f};
        const Vec3 color {(normal * 0.5f + half) * 255.0f};
        return color;
    }

    // check for collision against ground
    const Vec3 ground_point(0.0f, 0.0f, 0.0f);
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    const Vec3 to_ground {ground_point - position};
    if (dot(to_ground, direction) > 0.0f) {
        // hit the ground, figure out where
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        return sample_ground(ground_intersection, direction);
    }

    return sample_sky(position, direction);
}

void draw_scene(const int image_width, const int image_height) {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3 {
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}
<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include "logger.hpp"
#include "notification_center.hpp"
#include "receiver.hpp"
#include "session.hpp"

class connection_manager final {
public:
  connection_manager(const connection_manager&) = delete;

  connection_manager(void) : exit_loop_(false),
                             is_session_active_(false),
                             exit_receiver_starter_(true),
                             sigusr1_source_(0) {
    thread_ = std::thread([this] { this->worker(); });

    notification_center::observe_distributed_notification(this,
                                                          static_console_user_socket_directory_is_ready_callback,
                                                          constants::get_distributed_notification_console_user_socket_directory_is_ready());
  }

  ~connection_manager(void) {
    exit_loop_ = true;
    exit_receiver_starter_ = true;

    receiver_starter_thread_.join();
    thread_.join();

    logger::get_logger().info("connection_manager is destructed");
  }

private:
  void worker(void) {
    while (!exit_loop_) {
      if (auto is_active = session::is_active()) {
        if (is_session_active_ != *is_active) {
          is_session_active_ = *is_active;

          exit_receiver_starter_ = true;
          if (receiver_starter_thread_.joinable()) {
            receiver_starter_thread_.join();
          }
          receiver_.stop();

          if (is_session_active_) {
            exit_receiver_starter_ = false;
            receiver_starter_thread_ = std::thread([this] { this->receiver_starter_worker(); });
          }
        }
      }

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  }

  void receiver_starter_worker(void) {
    while (!exit_receiver_starter_) {
      try {
        receiver_.start();
        break;
      } catch (...) {
        logger::get_logger().error("failed to start receiver_. retrying...");
      }

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  }

  static void static_console_user_socket_directory_is_ready_callback(CFNotificationCenterRef center,
                                                                     void* observer,
                                                                     CFStringRef notification_name,
                                                                     const void* observed_object,
                                                                     CFDictionaryRef user_info) {
    auto self = static_cast<connection_manager*>(observer);
    self->console_user_socket_directory_is_ready_callback();
  }

  void console_user_socket_directory_is_ready_callback(void) {
    logger::get_logger().info("connection_manager::console_user_socket_directory_is_ready_callback");
    // restart receiver.
    is_session_active_ = false;
  }

  std::thread thread_;
  std::atomic<bool> exit_loop_;
  std::atomic<bool> is_session_active_;

  std::thread receiver_starter_thread_;
  std::atomic<bool> exit_receiver_starter_;
  receiver receiver_;

  dispatch_source_t sigusr1_source_;
};
<commit_msg>remove sigusr1_source_<commit_after>#pragma once

#include "constants.hpp"
#include "logger.hpp"
#include "notification_center.hpp"
#include "receiver.hpp"
#include "session.hpp"

class connection_manager final {
public:
  connection_manager(const connection_manager&) = delete;

  connection_manager(void) : exit_loop_(false),
                             is_session_active_(false),
                             exit_receiver_starter_(true) {
    thread_ = std::thread([this] { this->worker(); });

    notification_center::observe_distributed_notification(this,
                                                          static_console_user_socket_directory_is_ready_callback,
                                                          constants::get_distributed_notification_console_user_socket_directory_is_ready());
  }

  ~connection_manager(void) {
    exit_loop_ = true;
    exit_receiver_starter_ = true;

    receiver_starter_thread_.join();
    thread_.join();

    logger::get_logger().info("connection_manager is destructed");
  }

private:
  void worker(void) {
    while (!exit_loop_) {
      if (auto is_active = session::is_active()) {
        if (is_session_active_ != *is_active) {
          is_session_active_ = *is_active;

          exit_receiver_starter_ = true;
          if (receiver_starter_thread_.joinable()) {
            receiver_starter_thread_.join();
          }
          receiver_.stop();

          if (is_session_active_) {
            exit_receiver_starter_ = false;
            receiver_starter_thread_ = std::thread([this] { this->receiver_starter_worker(); });
          }
        }
      }

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  }

  void receiver_starter_worker(void) {
    while (!exit_receiver_starter_) {
      try {
        receiver_.start();
        break;
      } catch (...) {
        logger::get_logger().error("failed to start receiver_. retrying...");
      }

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  }

  static void static_console_user_socket_directory_is_ready_callback(CFNotificationCenterRef center,
                                                                     void* observer,
                                                                     CFStringRef notification_name,
                                                                     const void* observed_object,
                                                                     CFDictionaryRef user_info) {
    auto self = static_cast<connection_manager*>(observer);
    self->console_user_socket_directory_is_ready_callback();
  }

  void console_user_socket_directory_is_ready_callback(void) {
    logger::get_logger().info("connection_manager::console_user_socket_directory_is_ready_callback");
    // restart receiver.
    is_session_active_ = false;
  }

  std::thread thread_;
  std::atomic<bool> exit_loop_;
  std::atomic<bool> is_session_active_;

  std::thread receiver_starter_thread_;
  std::atomic<bool> exit_receiver_starter_;
  receiver receiver_;
};
<|endoftext|>


<commit_before>0f1421dc-ad5c-11e7-a62f-ac87a332f658<commit_msg>Added that feature we discussed on... Was it monday?<commit_after>0f840100-ad5c-11e7-b116-ac87a332f658<|endoftext|>


<commit_before>/*
 * Duke.cpp
 *
 *  Created on: Jan 6, 2013
 *      Author: Guillaume Chatelet
 */

#include "Duke.h"
#include <duke/cmdline/CmdLineParameters.h>
#include <duke/filesystem/FsUtils.h>
#include <duke/time/Clock.h>
#include <duke/engine/rendering/ImageRenderer.h>
#include <duke/engine/rendering/GlyphRenderer.h>
#include <duke/engine/overlay/DukeSplashStream.h>
#include <duke/engine/overlay/AttributesOverlay.h>
#include <duke/engine/streams/DiskMediaStream.h>
#include <duke/attributes/AttributeKeys.h>
#include <duke/gl/GL.h>
#include <glm/glm.hpp>
#include <sequence/Parser.hpp>

#include <sstream>

using sequence::Item;

namespace duke {

const char * const pMetadataTrack = "metadata";

static sequence::Configuration getParserConf() {
	using namespace sequence;
	Configuration conf;
	conf.sort = true;
	conf.bakeSingleton = true;
	conf.mergePadding = true;
	conf.pack = true;
	return conf;
}

Timeline buildTimeline(const CmdLineParameters &parameters) {
	const auto& paths = parameters.additionnalOptions;
	Track track;
	size_t offset = 0;
	for (const std::string &path : paths) {
		const std::string absolutePath = getAbsoluteFilename(path.c_str());
		switch (getFileStatus(absolutePath.c_str())) {
		case FileStatus::NOT_A_FILE:
			throw commandline_error("'" + absolutePath + "' is not a file nor a directory");
		case FileStatus::FILE:
			track.add(offset, Clip { 1, std::make_shared<DiskMediaStream>(Item(absolutePath)), nullptr });
			++offset;
			break;
		case FileStatus::DIRECTORY:
			for (Item item : sequence::parseDir(getParserConf(), absolutePath.c_str()).files) {
				const auto type = item.getType();
				if (type == Item::INVALID)
					throw commandline_error("invalid item while parsing directory");
				if (!item.filename.empty() && item.filename[0] == '.')
					continue; // escaping hidden file
				item.filename = absolutePath + '/' + item.filename;
				switch (type) {
				case Item::SINGLE:
					track.add(offset, Clip { 1, std::make_shared<DiskMediaStream>(item), nullptr });
					++offset;
					break;
				case Item::PACKED: {
					const auto count = item.end - item.start + 1;
					track.add(offset, Clip { count, std::make_shared<DiskMediaStream>(item), nullptr });
					offset += count;
				}
				case Item::INDICED:
				default:
					break;
				}
			}
			break;
		}
	}
	return {track};
}

Duke::Duke(CmdLineParameters parameters) :
		m_Player(parameters) {
	const bool fullscreen = parameters.fullscreen;
	GLFWmonitor* pPrimaryMonitor = glfwGetPrimaryMonitor();
	if (pPrimaryMonitor == nullptr) {
		int monitors = 0;
		GLFWmonitor **pMonitors = nullptr;
		pMonitors = glfwGetMonitors(&monitors);
		if (monitors == 0 || pMonitors == nullptr)
			throw std::runtime_error("No monitor detected");
		pPrimaryMonitor = pMonitors[0];
	}
	GLFWvidmode desktopDefinition = glfwGetVideoMode(pPrimaryMonitor);
	auto windowDefinition = glm::ivec2(desktopDefinition.width, desktopDefinition.height);
	if (!fullscreen)
		windowDefinition /= 2;
	m_pWindow.reset(m_Application.createWindow<DukeWindow>(windowDefinition.x, windowDefinition.y, "", fullscreen ? pPrimaryMonitor : nullptr, nullptr));
	m_pWindow->makeContextCurrent();
	m_pWindow->onWindowResize(windowDefinition.x, windowDefinition.y);

	glfwSwapInterval(parameters.swapBufferInterval);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_DEPTH_TEST);

	auto timeline = buildTimeline(parameters);
	const bool demoMode = timeline.empty();
	if (demoMode) {
		parameters.additionnalOptions.emplace_back("splashscreen");
		timeline = buildTimeline(parameters);
		const Range range = timeline.empty() ? Range(0, 0) : timeline.getRange();
		Track overlay;
		overlay.add(range.first, Clip { range.count(), nullptr, std::make_shared<DukeSplashStream>() });
		timeline.push_back(overlay);
		m_Context.fitMode = FitMode::OUTER;
		m_Player.load(timeline, FrameDuration(1, 15));
		m_Player.setPlaybackSpeed(1);
	} else
		m_Player.load(timeline, FrameDuration::PAL);
}

namespace { // defining channel mask constants

using glm::bvec4;
static const auto r = bvec4(true, false, false, false);
static const auto g = bvec4(false, true, false, false);
static const auto b = bvec4(false, false, true, false);
static const auto a = bvec4(false, false, false, true);
static const auto all = bvec4(false);

}  // namespace

bool setNextMode(FitMode &mode) {
	switch (mode) {
	case FitMode::ACTUAL:
		mode = FitMode::INNER;
		return true;
	case FitMode::INNER:
		mode = FitMode::OUTER;
		return true;
	case FitMode::FREE:
		mode = FitMode::ACTUAL;
		return true;
	case FitMode::OUTER:
		mode = FitMode::FREE;
		return false;
	}
}

void Duke::run() {
// find textures here : http://dwarffortresswiki.org/index.php/Tileset_repository
	const auto pGlyphRenderer = std::make_shared<GlyphRenderer>();
	AttributesOverlay overlay(pGlyphRenderer);
	bool showOverlay = false;

	SharedMesh pSquare = getSquare();
	Metronom metronom(100);
	auto milestone = duke_clock::now();
	bool running = true;
	while (running) {
		glfwPollEvents();
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		// setting up context
		m_Context.viewport = m_pWindow->useViewport(false, false, false, false);
		m_Context.currentFrame = m_Player.getCurrentFrame();
		m_Context.playbackTime = m_Player.getPlaybackTime();
		m_Context.pan = m_pWindow->getPanPos();
		m_Context.zoom = m_pWindow->getScrollPos().y;

		const size_t frame = m_Context.currentFrame.round();

		m_Player.getTextureCache().ensureReady(frame);

		// rendering
		for (const Track &track : m_Player.getTimeline()) {
			if (track.disabled)
				continue;
			const auto pTrackItr = track.clipContaining(frame);
			if (pTrackItr == track.end())
				continue;
			m_Context.pCurrentImage = nullptr;
			const MediaFrameReference mfr = track.getMediaFrameReferenceAt(m_Context.currentFrame.round());
			auto pLoadedTexture = m_Player.getTextureCache().getLoadedTexture(mfr);
			if (pLoadedTexture) {
				m_Context.pCurrentImage = pLoadedTexture;
				auto boundTexture = pLoadedTexture->pTexture->scope_bind_texture();
				glTexParameteri(pLoadedTexture->pTexture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
				glTexParameteri(pLoadedTexture->pTexture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

				renderWithBoundTexture(pSquare.get(), m_Context);
			}
			const auto& pOverlayTrack = pTrackItr->second.pOverlay;
			if (pOverlayTrack)
				pOverlayTrack->render(m_Context);
			if (showOverlay)
				overlay.render(m_Context);
		}

		// displaying
		m_pWindow->glfwSwapBuffers();

		// updating time
		const auto elapsedMicroSeconds = metronom.tick();
		m_Player.offsetPlaybackTime(elapsedMicroSeconds);
		m_Context.liveTime += Time(elapsedMicroSeconds.count(), 1000000);

		// handling input
		auto &keyStrokes = m_pWindow->getPendingKeys();
		for (const int key : keyStrokes) {
			switch (key) {
			case ' ':
				m_Player.setPlaybackSpeed(m_Player.getPlaybackSpeed() == 0 ? 1 : 0);
				break;
			case '4':
				m_Player.setPlaybackSpeed(-1);
				m_Player.offsetPlaybackTime(m_Player.getFrameDuration());
				m_Player.setPlaybackSpeed(0);
				break;
			case '6':
				m_Player.setPlaybackSpeed(1);
				m_Player.offsetPlaybackTime(m_Player.getFrameDuration());
				m_Player.setPlaybackSpeed(0);
				break;
			case 'p':
				m_pWindow->setPan(glm::ivec2());
				break;
			case 'z':
				m_pWindow->setScroll(glm::vec2());
				break;
			case 'r':
				m_Context.channels = m_Context.channels == r ? all : r;
				break;
			case 'g':
				m_Context.channels = m_Context.channels == g ? all : g;
				break;
			case 'b':
				m_Context.channels = m_Context.channels == b ? all : b;
				break;
			case 'a':
				m_Context.channels = m_Context.channels == a ? all : a;
				break;
			case '+':
				m_Context.exposure *= 1.2;
				break;
			case '-':
				m_Context.exposure /= 1.2;
				break;
			case 'o':
				showOverlay = !showOverlay;
				break;
			case 'f':
				if (setNextMode(m_Context.fitMode))
					m_pWindow->setPan(glm::ivec2());
				break;
			}
		}
		keyStrokes.clear();

		// check stop
		running = !(m_pWindow->glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS && m_pWindow->glfwGetWindowParam(GLFW_FOCUSED));

		// dump info every seconds
		const auto now = duke_clock::now();
		if ((now - milestone) > std::chrono::seconds(1)) {
//				metronom.dump();
			milestone = now;
		}
	}
}
} /* namespace duke */
<commit_msg>fixed shutdown with close window icon<commit_after>/*
 * Duke.cpp
 *
 *  Created on: Jan 6, 2013
 *      Author: Guillaume Chatelet
 */

#include "Duke.h"
#include <duke/cmdline/CmdLineParameters.h>
#include <duke/filesystem/FsUtils.h>
#include <duke/time/Clock.h>
#include <duke/engine/rendering/ImageRenderer.h>
#include <duke/engine/rendering/GlyphRenderer.h>
#include <duke/engine/overlay/DukeSplashStream.h>
#include <duke/engine/overlay/AttributesOverlay.h>
#include <duke/engine/streams/DiskMediaStream.h>
#include <duke/attributes/AttributeKeys.h>
#include <duke/gl/GL.h>
#include <glm/glm.hpp>
#include <sequence/Parser.hpp>

#include <sstream>

using sequence::Item;

namespace duke {

const char * const pMetadataTrack = "metadata";

static sequence::Configuration getParserConf() {
	using namespace sequence;
	Configuration conf;
	conf.sort = true;
	conf.bakeSingleton = true;
	conf.mergePadding = true;
	conf.pack = true;
	return conf;
}

Timeline buildTimeline(const CmdLineParameters &parameters) {
	const auto& paths = parameters.additionnalOptions;
	Track track;
	size_t offset = 0;
	for (const std::string &path : paths) {
		const std::string absolutePath = getAbsoluteFilename(path.c_str());
		switch (getFileStatus(absolutePath.c_str())) {
		case FileStatus::NOT_A_FILE:
			throw commandline_error("'" + absolutePath + "' is not a file nor a directory");
		case FileStatus::FILE:
			track.add(offset, Clip { 1, std::make_shared<DiskMediaStream>(Item(absolutePath)), nullptr });
			++offset;
			break;
		case FileStatus::DIRECTORY:
			for (Item item : sequence::parseDir(getParserConf(), absolutePath.c_str()).files) {
				const auto type = item.getType();
				if (type == Item::INVALID)
					throw commandline_error("invalid item while parsing directory");
				if (!item.filename.empty() && item.filename[0] == '.')
					continue; // escaping hidden file
				item.filename = absolutePath + '/' + item.filename;
				switch (type) {
				case Item::SINGLE:
					track.add(offset, Clip { 1, std::make_shared<DiskMediaStream>(item), nullptr });
					++offset;
					break;
				case Item::PACKED: {
					const auto count = item.end - item.start + 1;
					track.add(offset, Clip { count, std::make_shared<DiskMediaStream>(item), nullptr });
					offset += count;
				}
				case Item::INDICED:
				default:
					break;
				}
			}
			break;
		}
	}
	return {track};
}

Duke::Duke(CmdLineParameters parameters) :
		m_Player(parameters) {
	const bool fullscreen = parameters.fullscreen;
	GLFWmonitor* pPrimaryMonitor = glfwGetPrimaryMonitor();
	if (pPrimaryMonitor == nullptr) {
		int monitors = 0;
		GLFWmonitor **pMonitors = nullptr;
		pMonitors = glfwGetMonitors(&monitors);
		if (monitors == 0 || pMonitors == nullptr)
			throw std::runtime_error("No monitor detected");
		pPrimaryMonitor = pMonitors[0];
	}
	GLFWvidmode desktopDefinition = glfwGetVideoMode(pPrimaryMonitor);
	auto windowDefinition = glm::ivec2(desktopDefinition.width, desktopDefinition.height);
	if (!fullscreen)
		windowDefinition /= 2;
	m_pWindow.reset(m_Application.createWindow<DukeWindow>(windowDefinition.x, windowDefinition.y, "", fullscreen ? pPrimaryMonitor : nullptr, nullptr));
	m_pWindow->makeContextCurrent();
	m_pWindow->onWindowResize(windowDefinition.x, windowDefinition.y);

	glfwSwapInterval(parameters.swapBufferInterval);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_DEPTH_TEST);

	auto timeline = buildTimeline(parameters);
	const bool demoMode = timeline.empty();
	if (demoMode) {
		parameters.additionnalOptions.emplace_back("splashscreen");
		timeline = buildTimeline(parameters);
		const Range range = timeline.empty() ? Range(0, 0) : timeline.getRange();
		Track overlay;
		overlay.add(range.first, Clip { range.count(), nullptr, std::make_shared<DukeSplashStream>() });
		timeline.push_back(overlay);
		m_Context.fitMode = FitMode::OUTER;
		m_Player.load(timeline, FrameDuration(1, 15));
		m_Player.setPlaybackSpeed(1);
	} else
		m_Player.load(timeline, FrameDuration::PAL);
}

namespace { // defining channel mask constants

using glm::bvec4;
static const auto r = bvec4(true, false, false, false);
static const auto g = bvec4(false, true, false, false);
static const auto b = bvec4(false, false, true, false);
static const auto a = bvec4(false, false, false, true);
static const auto all = bvec4(false);

}  // namespace

bool setNextMode(FitMode &mode) {
	switch (mode) {
	case FitMode::ACTUAL:
		mode = FitMode::INNER;
		return true;
	case FitMode::INNER:
		mode = FitMode::OUTER;
		return true;
	case FitMode::FREE:
		mode = FitMode::ACTUAL;
		return true;
	case FitMode::OUTER:
		mode = FitMode::FREE;
		return false;
	}
}

void Duke::run() {
// find textures here : http://dwarffortresswiki.org/index.php/Tileset_repository
	const auto pGlyphRenderer = std::make_shared<GlyphRenderer>();
	AttributesOverlay overlay(pGlyphRenderer);
	bool showOverlay = false;

	SharedMesh pSquare = getSquare();
	Metronom metronom(100);
	auto milestone = duke_clock::now();
	bool running = true;
	while (running) {
		glfwPollEvents();
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		// setting up context
		m_Context.viewport = m_pWindow->useViewport(false, false, false, false);
		m_Context.currentFrame = m_Player.getCurrentFrame();
		m_Context.playbackTime = m_Player.getPlaybackTime();
		m_Context.pan = m_pWindow->getPanPos();
		m_Context.zoom = m_pWindow->getScrollPos().y;

		const size_t frame = m_Context.currentFrame.round();

		m_Player.getTextureCache().ensureReady(frame);

		// rendering
		for (const Track &track : m_Player.getTimeline()) {
			if (track.disabled)
				continue;
			const auto pTrackItr = track.clipContaining(frame);
			if (pTrackItr == track.end())
				continue;
			m_Context.pCurrentImage = nullptr;
			const MediaFrameReference mfr = track.getMediaFrameReferenceAt(m_Context.currentFrame.round());
			auto pLoadedTexture = m_Player.getTextureCache().getLoadedTexture(mfr);
			if (pLoadedTexture) {
				m_Context.pCurrentImage = pLoadedTexture;
				auto boundTexture = pLoadedTexture->pTexture->scope_bind_texture();
				glTexParameteri(pLoadedTexture->pTexture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
				glTexParameteri(pLoadedTexture->pTexture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

				renderWithBoundTexture(pSquare.get(), m_Context);
			}
			const auto& pOverlayTrack = pTrackItr->second.pOverlay;
			if (pOverlayTrack)
				pOverlayTrack->render(m_Context);
			if (showOverlay)
				overlay.render(m_Context);
		}

		// displaying
		m_pWindow->glfwSwapBuffers();

		// updating time
		const auto elapsedMicroSeconds = metronom.tick();
		m_Player.offsetPlaybackTime(elapsedMicroSeconds);
		m_Context.liveTime += Time(elapsedMicroSeconds.count(), 1000000);

		// handling input
		auto &keyStrokes = m_pWindow->getPendingKeys();
		for (const int key : keyStrokes) {
			switch (key) {
			case ' ':
				m_Player.setPlaybackSpeed(m_Player.getPlaybackSpeed() == 0 ? 1 : 0);
				break;
			case '4':
				m_Player.setPlaybackSpeed(-1);
				m_Player.offsetPlaybackTime(m_Player.getFrameDuration());
				m_Player.setPlaybackSpeed(0);
				break;
			case '6':
				m_Player.setPlaybackSpeed(1);
				m_Player.offsetPlaybackTime(m_Player.getFrameDuration());
				m_Player.setPlaybackSpeed(0);
				break;
			case 'p':
				m_pWindow->setPan(glm::ivec2());
				break;
			case 'z':
				m_pWindow->setScroll(glm::vec2());
				break;
			case 'r':
				m_Context.channels = m_Context.channels == r ? all : r;
				break;
			case 'g':
				m_Context.channels = m_Context.channels == g ? all : g;
				break;
			case 'b':
				m_Context.channels = m_Context.channels == b ? all : b;
				break;
			case 'a':
				m_Context.channels = m_Context.channels == a ? all : a;
				break;
			case '+':
				m_Context.exposure *= 1.2;
				break;
			case '-':
				m_Context.exposure /= 1.2;
				break;
			case 'o':
				showOverlay = !showOverlay;
				break;
			case 'f':
				if (setNextMode(m_Context.fitMode))
					m_pWindow->setPan(glm::ivec2());
				break;
			}
		}
		keyStrokes.clear();

		// check stop
		running = !(m_pWindow->glfwGetWindowParam(GLFW_SHOULD_CLOSE)
					|| (m_pWindow->glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS && m_pWindow->glfwGetWindowParam(GLFW_FOCUSED)));

		// dump info every seconds
		const auto now = duke_clock::now();
		if ((now - milestone) > std::chrono::seconds(1)) {
//				metronom.dump();
			milestone = now;
		}
	}
}
} /* namespace duke */
<|endoftext|>


<commit_before>/*
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>

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

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

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

#include "duplicatesfinder.h"
#include "personsmodel.h"
#include <QDebug>
#include <QUrl>

using namespace KPeople;

DuplicatesFinder::DuplicatesFinder(PersonsModel *model, QObject *parent)
    : KJob(parent)
    , m_model(model)
{
    m_compareRoles << PersonsModel::FullNamesRole
                   << PersonsModel::NicknamesRole
                   << PersonsModel::EmailsRole
                   << PersonsModel::PhonesRole;
}

void DuplicatesFinder::setSpecificPerson(const QUrl& uri)
{
    m_uri = uri;
}

void DuplicatesFinder::start()
{
    if(!m_uri.isEmpty()) {
        QMetaObject::invokeMethod(this, "doSearch", Qt::QueuedConnection);
    } else {
        QMetaObject::invokeMethod(this, "doSpecificSearch", Qt::QueuedConnection);
    }
}

QVariantList DuplicatesFinder::valuesForIndex(const QModelIndex& idx)
{
    //we gather the values
    QVariantList values;
    Q_FOREACH (int role, m_compareRoles) {
        values += idx.data(role);
    }
    Q_ASSERT(values.size() == m_compareRoles.size());

    return values;
}

//TODO: start providing partial results so that we can start processing matches while it's not done
void DuplicatesFinder::doSearch()
{
    //NOTE: This can probably optimized. I'm just trying to get the semantics right at the moment
    //maybe using nepomuk for the matching would help?

    QVector<QVariantList> collectedValues;
    m_matches.clear();

    for (int i = 0, rows = m_model->rowCount(); i < rows; i++) {
        QModelIndex idx = m_model->index(i, 0);

        //we gather the values
        QVariantList values = valuesForIndex(idx);

        //we check if it matches
        int j = 0;
        Q_FOREACH (const QVariantList &valueToCompare, collectedValues) {
            QList<int> matchedRoles = matchAt(values, valueToCompare);

            if (!matchedRoles.isEmpty()) {
                QPersistentModelIndex i2(m_model->index(j, 0));

                m_matches.append(Match(matchedRoles, idx, i2));
            }
            j++;
        }

        //we add our data for comparing later
        collectedValues.append(values);
    }
    emitResult();
}

void DuplicatesFinder::doSpecificSearch()
{
    m_matches.clear();

    QModelIndex idx = m_model->indexForUri(m_uri);
    QVariantList values = valuesForIndex(idx);

    for(int i = 0, rows = m_model->rowCount(); i<rows; i++) {
        if(i==idx.row()) {
            continue;
        }

        QModelIndex idx2 = m_model->index(i, 0);
        QVariantList values2 = valuesForIndex(idx2);
        QList<int> matchedRoles = matchAt(values, values2);
        if(!matchedRoles.isEmpty()) {
            m_matches.append(Match(matchedRoles, idx, idx2));
        }
    }

    emitResult();
}

QList<int> DuplicatesFinder::matchAt(const QVariantList &value, const QVariantList &toCompare) const
{
    Q_ASSERT(value.size() == toCompare.size());

    QList<int> ret;
    for (int i = 0; i < toCompare.size(); i++) {
        const QVariant &v = value[i];
        bool add = false;

        if (v.type() == QVariant::List) {
            QVariantList listA = v.toList();
            QVariantList listB = toCompare[i].toList();

            if (!listA.isEmpty() && !listB.isEmpty()) {
                Q_FOREACH (const QVariant &v, listB) {
                    if (!v.isNull() && listA.contains(v)) {
                        Q_ASSERT(!ret.contains(m_compareRoles[i]) && "B");
                        add = true;
                        break;
                    }
                }
            }
        } else if (!v.isNull() && v == toCompare[i]
            && (v.type() != QVariant::String || !v.toString().isEmpty()))
        {
            Q_ASSERT(!ret.contains(m_compareRoles[i]) && "A");
            add = true;
        }

        if (add) {
            ret += m_compareRoles[i];
        }
    }
    return ret;
}

QList<Match> DuplicatesFinder::results() const
{
    return m_matches;
}
<commit_msg>Fix conditional in the duplicates finder<commit_after>/*
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>

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

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

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

#include "duplicatesfinder.h"
#include "personsmodel.h"
#include <QDebug>
#include <QUrl>

using namespace KPeople;

DuplicatesFinder::DuplicatesFinder(PersonsModel *model, QObject *parent)
    : KJob(parent)
    , m_model(model)
{
    m_compareRoles << PersonsModel::FullNamesRole
                   << PersonsModel::NicknamesRole
                   << PersonsModel::EmailsRole
                   << PersonsModel::PhonesRole;
}

void DuplicatesFinder::setSpecificPerson(const QUrl& uri)
{
    m_uri = uri;
}

void DuplicatesFinder::start()
{
    if(m_uri.isEmpty()) {
        QMetaObject::invokeMethod(this, "doSearch", Qt::QueuedConnection);
    } else {
        QMetaObject::invokeMethod(this, "doSpecificSearch", Qt::QueuedConnection);
    }
}

QVariantList DuplicatesFinder::valuesForIndex(const QModelIndex& idx)
{
    //we gather the values
    QVariantList values;
    Q_FOREACH (int role, m_compareRoles) {
        values += idx.data(role);
    }
    Q_ASSERT(values.size() == m_compareRoles.size());

    return values;
}

//TODO: start providing partial results so that we can start processing matches while it's not done
void DuplicatesFinder::doSearch()
{
    //NOTE: This can probably optimized. I'm just trying to get the semantics right at the moment
    //maybe using nepomuk for the matching would help?

    QVector<QVariantList> collectedValues;
    m_matches.clear();

    for (int i = 0, rows = m_model->rowCount(); i < rows; i++) {
        QModelIndex idx = m_model->index(i, 0);

        //we gather the values
        QVariantList values = valuesForIndex(idx);

        //we check if it matches
        int j = 0;
        Q_FOREACH (const QVariantList &valueToCompare, collectedValues) {
            QList<int> matchedRoles = matchAt(values, valueToCompare);

            if (!matchedRoles.isEmpty()) {
                QPersistentModelIndex i2(m_model->index(j, 0));

                m_matches.append(Match(matchedRoles, idx, i2));
            }
            j++;
        }

        //we add our data for comparing later
        collectedValues.append(values);
    }
    emitResult();
}

void DuplicatesFinder::doSpecificSearch()
{
    m_matches.clear();

    QModelIndex idx = m_model->indexForUri(m_uri);
    QVariantList values = valuesForIndex(idx);

    for(int i = 0, rows = m_model->rowCount(); i<rows; i++) {
        if(i==idx.row()) {
            continue;
        }

        QModelIndex idx2 = m_model->index(i, 0);
        QVariantList values2 = valuesForIndex(idx2);
        QList<int> matchedRoles = matchAt(values, values2);
        if(!matchedRoles.isEmpty()) {
            m_matches.append(Match(matchedRoles, idx, idx2));
        }
    }

    emitResult();
}

QList<int> DuplicatesFinder::matchAt(const QVariantList &value, const QVariantList &toCompare) const
{
    Q_ASSERT(value.size() == toCompare.size());

    QList<int> ret;
    for (int i = 0; i < toCompare.size(); i++) {
        const QVariant &v = value[i];
        bool add = false;

        if (v.type() == QVariant::List) {
            QVariantList listA = v.toList();
            QVariantList listB = toCompare[i].toList();

            if (!listA.isEmpty() && !listB.isEmpty()) {
                Q_FOREACH (const QVariant &v, listB) {
                    if (!v.isNull() && listA.contains(v)) {
                        Q_ASSERT(!ret.contains(m_compareRoles[i]) && "B");
                        add = true;
                        break;
                    }
                }
            }
        } else if (!v.isNull() && v == toCompare[i]
            && (v.type() != QVariant::String || !v.toString().isEmpty()))
        {
            Q_ASSERT(!ret.contains(m_compareRoles[i]) && "A");
            add = true;
        }

        if (add) {
            ret += m_compareRoles[i];
        }
    }
    return ret;
}

QList<Match> DuplicatesFinder::results() const
{
    return m_matches;
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;
int main()
{
	int level;
	int pv;
	int vel;
	int Errore;
	int fine;
	int exp_agg;
	int exp;
	string Shiny;
	string Pokemon;
	string scheda;
	string fisico = ":fisico:";
	string mosse_apprese;
	string mossa1;
	string mossa2;
	string mossa3;
	string mossa4;
	string azione;
	string lista_mosse_if;
	string nome_pokemon;
	printf("Benvenuto nel generatore schede di Bestfast!\nIniziamo!\nInserisci il nome il numero Pokédex del Pokémon, guarda 'LISTA_POKEMON.txt' per la lista dei Pokémon.\nNome Pokémon: ");

	cin >> Pokemon;
	if(Pokemon == "1" or Pokemon == "Bulbasaur" or Pokemon == "bulbasaur")
		{
			nome_pokemon = "Bulbasaur";
			printf("Hai scelto Bulbasaur!\nIl Pokémon è shiny?\nRispondi con 'Sì' o 'No'\n");
			pv = 23;
			vel = 45;
			cin >> Shiny;
			if(Shiny == "Sì" or Shiny == "sì" or Shiny == "Si" or Shiny == "si")
			{
				printf("Ok, hai selezionato bulbasaur shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/bulbasaur.gif]\nBulbasaur :erba: :veleno:\n";
			}
			if(Shiny == "No" or Shiny == "no")
			{
				printf("Ok, hai selezionato bulbasaur NON shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani/bulbasaur.gif]\nBulbasaur :erba: :veleno:\n";
			}
			exp_agg = 2;
			mosse_apprese = "Affannoseme\nAmnesia\nAttrazione\nAzione\nBullo\nCampo Erboso\nCapocciata\nConfidenza\nCoro\nCrescita\nCuordileone\nDanzaspada\nDoppioteam\nEccheggiavoce\nEnergipalla\nErbapatto\nFacciata\nFango\nFangobomba\nFascino\nFogliamagica\nFoglielama\nFrustata\nFrustazione\nGigassorbimento\nGiornodisole\nIntroforza\nLaccioerboso\nLegatutto\nMaledizione\nMeloderba\nNaturforza\nPetalodanza\nPrivazione\nProfumino\nProtezione\nRadicamento\nResistenza\nRiduttore\nRiposo\nRitorno\nRuggito\nRussare\nSalvaguardia\nSchermoluce\nSdoppiatore\nSemebomba\nSintesi\nSolarraggio\nSonnifero\nSonnolalia\nSostituto\nTossina\nVelenoshock\nVelenpolvere\nVerdebufera\nVigorcolpo";		}
		if(Pokemon == "4" or Pokemon == "Charmander" or Pokemon == "charmander")
		{
			printf("Hai scelto Charmander!\nIl Pokémon è shiny?\nRispondi con 'Sì' o 'No'\n");
			pv = 15;
			vel = 65;
			nome_pokemon = "Charmander";
			cin >> Shiny;
			if(Shiny == "Sì" or Shiny == "sì" or Shiny == "Si" or Shiny == "si")
			{
				printf("Ok, hai selezionato Charmander shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/charmander.gif]\nCharmander :fuoco:\n";
			}
			if(Shiny == "No" or Shiny == "no")
			{
				printf("Ok, hai selezionato Charmander NON shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/charmander.gif]\nCharmander :fuoco:\n";
			}
		}
		printf("Digita il livello del Pokémon!\n");
		cin >> level;
		vel = vel + level - 1;
		int pot_da_aggiungere;
		if(level >= 51)
		{
			pv = (49 * 3) + ((level - 50) * 5) + pv;
			pot_da_aggiungere = 49 + (level - 50) * 2;
		}
		if(level <= 50)
		{
			pv = (level - 1) * 3 + pv;
			pot_da_aggiungere = level - 1;
		}
		int pot_azione = 4 + pot_da_aggiungere;
		printf("Vuoi vedere la lista delle mosse che può imparare questo Pokémon?\n");
		cin >> lista_mosse_if;
		if(lista_mosse_if == "Sì" or lista_mosse_if == "sì" or lista_mosse_if == "Si" or lista_mosse_if == "si")
			{
				cout << nome_pokemon << " può imparare queste mosse:\n" << mosse_apprese << "\n";
			}
		azione = "Azione (-" + to_string(pot_azione) + ") " + fisico + "\n";
		printf("Bene, adesso scrivi la prima mossa del Pokémon.\n");
		cin >> mossa1;
		if(mossa1 == "azione" or mossa1 == "Azione")
		{
			mossa1 = azione;
		}
		printf("Bene! Adesso scegli un altra mossa.\n");
		cin >> mossa2;
		if(mossa2 == "azione" or mossa2 == "Azione")
		{

			mossa2 = azione;
		}
		printf("Ok, hai scelto due mosse. adesso scegline una terza!\n");
		cin >> mossa3;
		if(mossa3 == "azione" or mossa3 == "Azione")
		{

			mossa3 = azione;
		}
		printf("Perfetto! Scegli l'ultima mossa!\n");
		cin >> mossa4;
		if(mossa4 == "azione" or mossa4 == "Azione")
		{

			mossa4 = azione;
		}
		exp = exp_agg * level;
		scheda = Pokemon + "Lv " + to_string(level) + "Pv " + to_string(pv) + "Vel " + to_string(vel) + "\n" + mossa1 + mossa2 + mossa3 + mossa4 + "EXP: 0/" + to_string(exp);
		Pokemon = Pokemon, "Lv ", level ,"Pv ", pv ,"Vel ", vel;
		printf("Ben fatto! Trovi la scheda nel file 'Scheda.txt'!\n");
		FILE * pFile;
		    pFile = fopen ("Scheda.txt","w");
		    if (pFile!=NULL)
		    {
				fputs (scheda.c_str(),pFile);
				fclose (pFile);
			}
}
	// else
	// {
	// 	cout<< "\nQuesto ID non esiste! Sicuro di non aver sbagliato?\nDigita '1' per riavviare il programma, oppure digita '0' per chiudere il programma.\n";
	// 	cin >> Errore;
	// 	if(Errore == 0)
	// 	{
	// 		return 0;
	// 	}
	// 	if(Errore == 1)
	//
	// 	{
	// 		return main();
	// 	}
	// }
	// cout << "Vuoi creare un altra scheda?\nSì = 1 	No = 0\n";
	// cin >> fine;
	// if(fine == 1)
	// {
	// 	return main();
 // 	}
	// if(fine == 0)
	// {
	// 	return 0;
	// }

<commit_msg>Added support for less than 3 moves Pokemon<commit_after>#include <iostream>
using namespace std;
int main()
{
	int level;
	int pv;
	int vel;
	int Errore;
	int fine;
	int exp_agg;
	int exp;
	string Shiny;
	string Pokemon;
	string scheda;
	string fisico = ":fisico:";
	string mosse_apprese;
	string mossa1;
	string mossa2;
	string mossa3;
	string mossa4;
	string azione;
	string lista_mosse_if;
	string nome_pokemon;
	string ant_move;
	printf("Benvenuto nel generatore schede di Bestfast!\nIniziamo!\nInserisci il nome il numero Pokédex del Pokémon, guarda 'LISTA_POKEMON.txt' per la lista dei Pokémon.\nNome Pokémon: ");

	cin >> Pokemon;
	if(Pokemon == "1" or Pokemon == "Bulbasaur" or Pokemon == "bulbasaur")
		{
			nome_pokemon = "Bulbasaur";
			printf("Hai scelto Bulbasaur!\nIl Pokémon è shiny?\nRispondi con 'Sì' o 'No'\n");
			pv = 23;
			vel = 45;
			cin >> Shiny;
			if(Shiny == "Sì" or Shiny == "sì" or Shiny == "Si" or Shiny == "si")
			{
				printf("Ok, hai selezionato bulbasaur shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/bulbasaur.gif]\nBulbasaur :erba: :veleno:\n";
			}
			if(Shiny == "No" or Shiny == "no")
			{
				printf("Ok, hai selezionato bulbasaur NON shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani/bulbasaur.gif]\nBulbasaur :erba: :veleno:\n";
			}
			exp_agg = 2;
			mosse_apprese = "Affannoseme\nAmnesia\nAttrazione\nAzione\nBullo\nCampo Erboso\nCapocciata\nConfidenza\nCoro\nCrescita\nCuordileone\nDanzaspada\nDoppioteam\nEccheggiavoce\nEnergipalla\nErbapatto\nFacciata\nFango\nFangobomba\nFascino\nFogliamagica\nFoglielama\nFrustata\nFrustazione\nGigassorbimento\nGiornodisole\nIntroforza\nLaccioerboso\nLegatutto\nMaledizione\nMeloderba\nNaturforza\nPetalodanza\nPrivazione\nProfumino\nProtezione\nRadicamento\nResistenza\nRiduttore\nRiposo\nRitorno\nRuggito\nRussare\nSalvaguardia\nSchermoluce\nSdoppiatore\nSemebomba\nSintesi\nSolarraggio\nSonnifero\nSonnolalia\nSostituto\nTossina\nVelenoshock\nVelenpolvere\nVerdebufera\nVigorcolpo";		}
		if(Pokemon == "4" or Pokemon == "Charmander" or Pokemon == "charmander")
		{
			printf("Hai scelto Charmander!\nIl Pokémon è shiny?\nRispondi con 'Sì' o 'No'\n");
			pv = 15;
			vel = 65;
			nome_pokemon = "Charmander";
			cin >> Shiny;
			if(Shiny == "Sì" or Shiny == "sì" or Shiny == "Si" or Shiny == "si")
			{
				printf("Ok, hai selezionato Charmander shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/charmander.gif]\nCharmander :fuoco:\n";
			}
			if(Shiny == "No" or Shiny == "no")
			{
				printf("Ok, hai selezionato Charmander NON shiny!\n");
				Pokemon = "[IMG=https://play.pokemonshowdown.com/sprites/xyani-shiny/charmander.gif]\nCharmander :fuoco:\n";
			}
		}
		printf("Digita il livello del Pokémon!\n");
		cin >> level;
		vel = vel + level - 1;
		int pot_da_aggiungere;
		if(level >= 51)
		{
			pv = (49 * 3) + ((level - 50) * 5) + pv;
			pot_da_aggiungere = 49 + (level - 50) * 2;
		}
		if(level <= 50)
		{
			pv = (level - 1) * 3 + pv;
			pot_da_aggiungere = level - 1;
		}
		int pot_azione = 4 + pot_da_aggiungere;
		printf("Vuoi vedere la lista delle mosse che può imparare questo Pokémon?\n");
		cin >> lista_mosse_if;
		if(lista_mosse_if == "Sì" or lista_mosse_if == "sì" or lista_mosse_if == "Si" or lista_mosse_if == "si")
			{
				cout << nome_pokemon << " può imparare queste mosse:\n" << mosse_apprese << "\n";
			}
		azione = "Azione (-" + to_string(pot_azione) + ") " + fisico + "\n";
		printf("Bene, adesso scrivi la prima mossa del Pokémon.\n");
		cin >> mossa1;
		if(mossa1 == "azione" or mossa1 == "Azione")
		{
			mossa1 = azione;
		}
		printf("Vuoi scegliere un'altra mossa?\n");
		cin >> ant_move;
		if(ant_move == "Si" or ant_move == "Sì" or ant_move == "si" or ant_move == "sì")
		{
			printf("Bene! Adesso scegli un altra mossa.\n");
			cin >> mossa2;
			if(mossa2 == "azione" or mossa2 == "Azione")
			{
			mossa2 = azione;
			}
			printf("Vuoi scegliere un'altra mossa?\n");
			cin >> ant_move;
			if(ant_move == "Si" or ant_move == "Sì" or ant_move == "si" or ant_move == "sì")
			{
				printf("Ok, hai scelto due mosse. adesso scegline una terza!\n");
				cin >> mossa3;
				if(mossa3 == "azione" or mossa3 == "Azione")
				{
				mossa3 = azione;
				}
				printf("Vuoi scegliere un'altra mossa?");
				cin >> ant_move;
				if(ant_move == "Si" or ant_move == "Sì" or ant_move == "si" or ant_move == "sì")
				{
					printf("Perfetto! Scegli l'ultima mossa!\n");
					cin >> mossa4;
					if(mossa4 == "azione" or mossa4 == "Azione")
					{
						mossa4 = azione;
					}
				}
			}
		}
		exp = exp_agg * level;
		scheda = Pokemon + "Lv " + to_string(level) + "Pv " + to_string(pv) + "Vel " + to_string(vel) + "\n" + mossa1 + mossa2 + mossa3 + mossa4 + "EXP: 0/" + to_string(exp);
		Pokemon = Pokemon, "Lv ", level ,"Pv ", pv ,"Vel ", vel;
		printf("Ben fatto! Trovi la scheda nel file 'Scheda.txt'!\n");
		FILE * pFile;
		    pFile = fopen ("Scheda.txt","w");
		    if (pFile!=NULL)
		    {
				fputs (scheda.c_str(),pFile);
				fclose (pFile);
			}
}
	// else
	// {
	// 	cout<< "\nQuesto ID non esiste! Sicuro di non aver sbagliato?\nDigita '1' per riavviare il programma, oppure digita '0' per chiudere il programma.\n";
	// 	cin >> Errore;
	// 	if(Errore == 0)
	// 	{
	// 		return 0;
	// 	}
	// 	if(Errore == 1)
	//
	// 	{
	// 		return main();
	// 	}
	// }
	// cout << "Vuoi creare un altra scheda?\nSì = 1 	No = 0\n";
	// cin >> fine;
	// if(fine == 1)
	// {
	// 	return main();
 // 	}
	// if(fine == 0)
	// {
	// 	return 0;
	// }

<|endoftext|>