<commit_before>#include "bigentry.hpp"
#include "log.hpp"
#include <algorithm>
#include <cstdio>
#include <cctype>

#include FILESYSTEM_HEADER
namespace fs = FILESYSTEM_NAMESPACE;

namespace OpenBFME {

uint32_t readUInt32(FILE* file){
    uint8_t val[4];
    fread(val, 1, 4, file);
    return val[0] << 24 | val[1] << 16 | val[2] << 8 | val[3];
}

void writeUInt32(FILE* file, uint32_t value){
    uint8_t val[] { uint8_t(value >> 24), uint8_t(value >> 16), uint8_t(value >> 8), uint8_t(value) };
    fwrite(val, 1, 4, file);
}

string readString(FILE* file, uint32_t limit, char terminator = '\0'){
    string data;
    while(uint32_t(ftell(file)) < limit){
        character c = fgetc(file);
        if(c == '\0' || c == terminator || ferror(file) || feof(file)){
            break;
        }
        data += c;
    }
    return data;
}

BigArchive::BigArchive(const string &filename) : archiveFilename(filename), file(nullptr) {
    std::replace(archiveFilename.begin(), archiveFilename.end(), '\\', '/');
}

BigArchive::~BigArchive(){
    close();
}

bool BigArchive::readHeader(){
    if (fs::is_directory(fs::path(archiveFilename))) {
        backend = Folder;

        for (fs::recursive_directory_iterator dir(archiveFilename), end; dir != end; ++dir) {
            const fs::path& currentPath = dir->path();
            if (fs::is_regular_file(currentPath)) {
                string filename = currentPath.generic_string();
                filename.erase(0, filename.find_first_of('/') + 1);
                uint32_t filesize = uint32_t(fs::file_size(currentPath));

                entries.emplace(*this, 0, filesize, filename);
                Log::debug("File path: \"%s\" length: %#08x", filename, filesize);
            }
        }

        return true;
    }

    backend = BigFile;

    if(!open()){
        return false;
    }

    character id[4] = {0};
    fread(id, 1, 4, file);

    if (id[0] != 'B' || id[1] != 'I' || id[2] != 'G' || (id[3] != '4' && id[3] != 'F')){
        close();
        return false;
    }

    fseek(file, 8, SEEK_SET);

    uint32_t fileCount = readUInt32(file);
    uint32_t headerEnd = readUInt32(file);

    Log::info("File Count: %u Header End: %#08x", fileCount, headerEnd);

    for(uint32_t f = 0; f < fileCount; ++f){
        uint32_t start = readUInt32(file);
        uint32_t end   = start + readUInt32(file);
        string path = readString(file, headerEnd);
        std::replace(path.begin(), path.end(), '\\', '/');

        entries.emplace(*this, start, end, path);

        Log::debug("File #%04d start: %#08x end: %#08x path: \"%s\"", f + 1, start, end, path);
    }

    if(uint32_t(ftell(file)) > headerEnd){
        Log::warning("Reading of file info passed through end of header.");
    }

    return true;
}

bool BigArchive::open(){
    if(file != nullptr){
        return true;
    }

    if(backend == BigFile){
        file = fopen(archiveFilename.c_str(), "rb");
    }

    return file != nullptr;
}

void BigArchive::close(){
    if(file != nullptr){
        fclose(file);
        file = nullptr;
    }
    currentEntry = nullptr;
}

bool BigArchive::openEntry(const BigEntry& entry) {
    entry.resetLineNumber();

    switch (backend) {
    case BigFile:
        if (open()) {
            fseek(file, entry.start, SEEK_SET);
            currentEntry = &entry;
            return true;
        }
        break;
    case Folder:
        close();
        file = fopen((archiveFilename + '/' + entry.filename).c_str(), "rb");
        if (file != nullptr) {
            currentEntry = &entry;
            return true;
        }
        break;
    }
    return false;
}

const BigEntry* BigArchive::openFile(const string &filename){
    auto entry = std::find_if(entries.begin(), entries.end(), [&](const BigEntry& it){ return it.filename == filename; });

    if(entry != entries.end() && openEntry(*entry)){
        return &(*entry);
    }

    return nullptr;
}

string BigArchive::getLine(const BigEntry &entry, bool checkComments){
    if(!open() || eof(entry)){
        return "";
    }
    string str = readString(file, entry.end, '\n');

    if(str.back() == '\r'){
        str.pop_back();
    }

    if(checkComments){
        string::size_type comment = std::min(str.find(';'), str.find("//"));
        if(comment != string::npos)
            str.erase(comment);
    }

    entry.incrementLineNumber();

    return str;
}

character BigArchive::getChar(const BigEntry &entry){
    if (!open() || eof(entry)){
        return 0;
    }

    character ch = fgetc(file);

    if (ch == '\n'){
        entry.incrementLineNumber();
    }

    return ch;
}

void BigArchive::ungetChar(const BigEntry &entry, character c) {
    if (tell(entry) > 0) {
        ungetc(c, file);

        if (c == '\n') {
            entry.decrementLineNumber();
        }
    }
}

bool BigArchive::seek(const BigEntry &entry, uint32_t pos){
    if(&entry != currentEntry){
        openEntry(entry);
    }

    /* Invalidate the stored current line number. */
    entry.invalidateLineNumber();

    pos += entry.start;
    if(pos < entry.end){
        fseek(file, pos, SEEK_SET);
        return true;
    }
    return false;
}

uint32_t BigArchive::tell(const BigEntry &entry){
    if(&entry != currentEntry){
        openEntry(entry);
    }

    uint32_t pos = ftell(file);
    if(pos < entry.start){
        return 0;
    }
    if(pos > entry.end){
        return entry.end - entry.start;
    }
    return pos - entry.start;
}

bool BigArchive::eof(const BigEntry &entry){
    uint32_t cpos = ftell(file);
    return cpos < entry.start || cpos >= entry.end;
}

bool BigArchive::extract(const BigEntry& entry, const string &directory, bool fullPath, bool ignore, bool overwrite){
    if(!openEntry(entry)){
        Log::error("Error opening entry \"%s\"!", entry.filename);
        return false;
    }

    fs::path path = entry.filename;

    path = fs::canonical(fs::path(directory)) / (fullPath ? path : path.filename());

    fs::create_directories(path.parent_path());

    if(fs::exists(path)){
        /* The option to ignore existing files takes precedence over overwriting them. */
        if(ignore){
            Log::info("Skipping existing file: \"%s\".", entry.filename);

            return true;
        }else if(!overwrite){
            character c = 0;

            do{
                Log::info("Overwrite existing file \"%s\"? [Y/N]:", path.generic_string());

                c = std::tolower(std::getchar());

                if(c == '\n') continue;

                /* Only take one letter input. */
                if(std::getchar() != '\n'){
                    c = 0;
                    while(std::getchar() != '\n') continue;
                }
            }while(c != 'n' && c != 'y');

            if(c == 'n'){
                Log::info("Skipping \"%s\".", entry.filename);

                return true;
            }
        }
        Log::info("Overwriting \"%s\"...", entry.filename);
    }else{
        Log::info("Extracting to \"%s\"...", path.generic_string());
    }

    FILE* out = fopen(path.generic_string().c_str(), "wb");

    if(out == nullptr){
        Log::error("Unable to create file \"%s\"!", path.generic_string());
        return false;
    }
    uint32_t length = entry.end - entry.start;
    uint8_t *buffer = new uint8_t[length];

    fread(buffer, 1, length, file);
    fwrite(buffer, 1, length, out);

    fclose(out);
    delete[] buffer;

    Log::info("File successfully extracted.");

    return true;
}

bool BigArchive::extractAll(const string &directory, bool ignore, bool overwrite){
    fs::create_directories(fs::path(directory));
    for(auto &entry : entries){
        if(!extract(entry, directory, true, ignore, overwrite)){
            return false;
        }
    }
    return true;
}

bool BigArchive::writeBig(const std::set<BigEntry>& entries, const string& filename) {
    Log::info("Preparing to write %d files to \"%s\"", integer(entries.size()), filename);

    /* 8 bytes for every entry + 24 at the start and end. */
    uint32_t headerLength = uint32_t(entries.size() * 8) + 20;

    /* Add the length of the filenames to headerLength. */
    for(auto &entry : entries){
        headerLength += uint32_t(entry.filename.size()) + 1;
    }

    Log::debug("Calculated header length: %#08x", headerLength);

    FILE* file = fopen(filename.c_str(), "wb");

    if (file == nullptr) {
        Log::error("Unable to open %s for writing!", filename);
        return false;
    }

    /* Either that or "BIG4". I'm not sure which... */
    fwrite("BIGF", 1, 4, file);

    writeUInt32(file, 0);

    /* General info about the file. */
    writeUInt32(file, uint32_t(entries.size()));
    writeUInt32(file, headerLength);

    /* Put the first file one byte after the end of the header. */
    uint32_t lastEnd = headerLength + 1;

    /* Write all the file information. */
    for(auto &entry : entries){
        uint32_t fileLength = entry.end - entry.start;
        writeUInt32(file, lastEnd);
        writeUInt32(file, fileLength);

        /* Write the filename and terminating null character. */
        fputs(entry.filename.c_str(), file);
        fputc('\0', file);

        /* So we know where the next file will be written. */
        lastEnd += fileLength;
    }

    /* What exactly is this? */
    fputs("L253", file);

    if(uint32_t(ftell(file)) > headerLength){
        Log::error("Calculated header length too short!");
    }

    /* One more byte until where we start the first file... */
    fputc('\0', file);

    /* Write all the files. */
    for(auto &entry : entries){
        entry.seek(0);

        for(character c; !entry.eof();){
            c = entry.getChar();
            fwrite(&c, sizeof(character), 1, file);
        }
    }

    fclose(file);

    Log::info("Finished writing to \"%s\".", filename);

    return true;
}

bool BigArchive::writeBig(const string& filename) {
    /* We only do this on a folder backend, because why would you do it on a .big? */
    if (backend == Folder) {
        return writeBig(entries, filename);
    }
    return false;
}

}
<commit_msg>Fixed incorrect paths in folder backend.<commit_after>#include "bigentry.hpp"
#include "log.hpp"
#include <algorithm>
#include <cstdio>
#include <cctype>

#include FILESYSTEM_HEADER
namespace fs = FILESYSTEM_NAMESPACE;

namespace OpenBFME {

uint32_t readUInt32(FILE* file){
    uint8_t val[4];
    fread(val, 1, 4, file);
    return val[0] << 24 | val[1] << 16 | val[2] << 8 | val[3];
}

void writeUInt32(FILE* file, uint32_t value){
    uint8_t val[] { uint8_t(value >> 24), uint8_t(value >> 16), uint8_t(value >> 8), uint8_t(value) };
    fwrite(val, 1, 4, file);
}

string readString(FILE* file, uint32_t limit, char terminator = '\0'){
    string data;
    while(uint32_t(ftell(file)) < limit){
        character c = fgetc(file);
        if(c == '\0' || c == terminator || ferror(file) || feof(file)){
            break;
        }
        data += c;
    }
    return data;
}

BigArchive::BigArchive(const string &filename) : archiveFilename(fs::path(filename).generic_string()), file(nullptr) { }

BigArchive::~BigArchive(){
    close();
}

bool BigArchive::readHeader(){
    if (fs::is_directory(fs::path(archiveFilename))) {
        backend = Folder;

        /* Make sure the archiveFilename ends with a '/' */
        if (archiveFilename.back() != '/')
            archiveFilename += '/';

        for (fs::recursive_directory_iterator dir(archiveFilename), end; dir != end; ++dir) {
            const fs::path& currentPath = dir->path();
            if (fs::is_regular_file(currentPath)) {
                string filename = currentPath.generic_string();

                /* Check to see if the filename contains the parent path, and if so remove it. */
                if (filename.compare(0, archiveFilename.size(), archiveFilename, 0, archiveFilename.size()) == 0)
                    filename.erase(0, archiveFilename.size());
                else
                    /* Otherwise fall back to removing the first element in the path. */
                    filename.erase(0, filename.find_first_of('/') + 1);

                uint32_t filesize = uint32_t(fs::file_size(currentPath));

                entries.emplace(*this, 0, filesize, filename);
                Log::debug("File path: \"%s\" length: %#08x", filename, filesize);
            }
        }

        return true;
    }

    backend = BigFile;

    if (!open())
        return false;

    /* The first 4 bytes shoule be either "BIG4" or "BIGF", quit if they aren't. */
    character id[4] = {0};
    fread(id, 1, 4, file);

    if (id[0] != 'B' || id[1] != 'I' || id[2] != 'G' || (id[3] != '4' && id[3] != 'F')) {
        close();
        return false;
    }

    fseek(file, 8, SEEK_SET);

    uint32_t fileCount = readUInt32(file);
    uint32_t headerEnd = readUInt32(file);

    Log::info("File Count: %u Header End: %#08x", fileCount, headerEnd);

    /* Read the individual file information into entries. */
    for (uint32_t f = 0; f < fileCount; ++f) {
        uint32_t start = readUInt32(file);
        uint32_t end   = start + readUInt32(file);
        string path = readString(file, headerEnd);
        std::replace(path.begin(), path.end(), '\\', '/');

        entries.emplace(*this, start, end, path);

        Log::debug("File #%04d start: %#08x end: %#08x path: \"%s\"", f + 1, start, end, path);
    }

    if (uint32_t(ftell(file)) > headerEnd)
        Log::warning("Reading of file info passed through end of header.");

    return true;
}

bool BigArchive::open(){
    if(file != nullptr){
        return true;
    }

    if(backend == BigFile){
        file = fopen(archiveFilename.c_str(), "rb");
    }

    return file != nullptr;
}

void BigArchive::close(){
    if(file != nullptr){
        fclose(file);
        file = nullptr;
    }
    currentEntry = nullptr;
}

bool BigArchive::openEntry(const BigEntry& entry) {
    entry.resetLineNumber();

    switch (backend) {
    case BigFile:
        if (open()) {
            fseek(file, entry.start, SEEK_SET);
            currentEntry = &entry;
            return true;
        }
        break;
    case Folder:
        close();
        file = fopen((archiveFilename + '/' + entry.filename).c_str(), "rb");
        if (file != nullptr) {
            currentEntry = &entry;
            return true;
        }
        break;
    }
    return false;
}

const BigEntry* BigArchive::openFile(const string &filename){
    auto entry = std::find_if(entries.begin(), entries.end(), [&](const BigEntry& it){ return it.filename == filename; });

    if(entry != entries.end() && openEntry(*entry)){
        return &(*entry);
    }

    return nullptr;
}

string BigArchive::getLine(const BigEntry &entry, bool checkComments){
    if(!open() || eof(entry)){
        return "";
    }
    string str = readString(file, entry.end, '\n');

    if(str.back() == '\r'){
        str.pop_back();
    }

    if(checkComments){
        string::size_type comment = std::min(str.find(';'), str.find("//"));
        if(comment != string::npos)
            str.erase(comment);
    }

    entry.incrementLineNumber();

    return str;
}

character BigArchive::getChar(const BigEntry &entry){
    if (!open() || eof(entry)){
        return 0;
    }

    character ch = fgetc(file);

    if (ch == '\n'){
        entry.incrementLineNumber();
    }

    return ch;
}

void BigArchive::ungetChar(const BigEntry &entry, character c) {
    if (tell(entry) > 0) {
        ungetc(c, file);

        if (c == '\n') {
            entry.decrementLineNumber();
        }
    }
}

bool BigArchive::seek(const BigEntry &entry, uint32_t pos){
    if(&entry != currentEntry){
        openEntry(entry);
    }

    /* Invalidate the stored current line number. */
    entry.invalidateLineNumber();

    pos += entry.start;
    if(pos < entry.end){
        fseek(file, pos, SEEK_SET);
        return true;
    }
    return false;
}

uint32_t BigArchive::tell(const BigEntry &entry){
    if(&entry != currentEntry){
        openEntry(entry);
    }

    uint32_t pos = ftell(file);
    if(pos < entry.start){
        return 0;
    }
    if(pos > entry.end){
        return entry.end - entry.start;
    }
    return pos - entry.start;
}

bool BigArchive::eof(const BigEntry &entry){
    uint32_t cpos = ftell(file);
    return cpos < entry.start || cpos >= entry.end;
}

bool BigArchive::extract(const BigEntry& entry, const string &directory, bool fullPath, bool ignore, bool overwrite){
    if(!openEntry(entry)){
        Log::error("Error opening entry \"%s\"!", entry.filename);
        return false;
    }

    fs::path path = entry.filename;

    path = fs::canonical(fs::path(directory)) / (fullPath ? path : path.filename());

    fs::create_directories(path.parent_path());

    if(fs::exists(path)){
        /* The option to ignore existing files takes precedence over overwriting them. */
        if(ignore){
            Log::info("Skipping existing file: \"%s\".", entry.filename);

            return true;
        }else if(!overwrite){
            character c = 0;

            do{
                Log::info("Overwrite existing file \"%s\"? [Y/N]:", path.generic_string());

                c = std::tolower(std::getchar());

                if(c == '\n') continue;

                /* Only take one letter input. */
                if(std::getchar() != '\n'){
                    c = 0;
                    while(std::getchar() != '\n') continue;
                }
            }while(c != 'n' && c != 'y');

            if(c == 'n'){
                Log::info("Skipping \"%s\".", entry.filename);

                return true;
            }
        }
        Log::info("Overwriting \"%s\"...", entry.filename);
    }else{
        Log::info("Extracting to \"%s\"...", path.generic_string());
    }

    FILE* out = fopen(path.generic_string().c_str(), "wb");

    if(out == nullptr){
        Log::error("Unable to create file \"%s\"!", path.generic_string());
        return false;
    }
    uint32_t length = entry.end - entry.start;
    uint8_t *buffer = new uint8_t[length];

    fread(buffer, 1, length, file);
    fwrite(buffer, 1, length, out);

    fclose(out);
    delete[] buffer;

    Log::info("File successfully extracted.");

    return true;
}

bool BigArchive::extractAll(const string &directory, bool ignore, bool overwrite){
    fs::create_directories(fs::path(directory));
    for(auto &entry : entries){
        if(!extract(entry, directory, true, ignore, overwrite)){
            return false;
        }
    }
    return true;
}

bool BigArchive::writeBig(const std::set<BigEntry>& entries, const string& filename) {
    Log::info("Preparing to write %d files to \"%s\"", integer(entries.size()), filename);

    /* 8 bytes for every entry + 24 at the start and end. */
    uint32_t headerLength = uint32_t(entries.size() * 8) + 20;

    /* Add the length of the filenames to headerLength. */
    for(auto &entry : entries){
        headerLength += uint32_t(entry.filename.size()) + 1;
    }

    Log::debug("Calculated header length: %#08x", headerLength);

    FILE* file = fopen(filename.c_str(), "wb");

    if (file == nullptr) {
        Log::error("Unable to open %s for writing!", filename);
        return false;
    }

    /* Either that or "BIG4". I'm not sure which... */
    fwrite("BIGF", 1, 4, file);

    writeUInt32(file, 0);

    /* General info about the file. */
    writeUInt32(file, uint32_t(entries.size()));
    writeUInt32(file, headerLength);

    /* Put the first file one byte after the end of the header. */
    uint32_t lastEnd = headerLength + 1;

    /* Write all the file information. */
    for(auto &entry : entries){
        uint32_t fileLength = entry.end - entry.start;
        writeUInt32(file, lastEnd);
        writeUInt32(file, fileLength);

        /* Write the filename and terminating null character. */
        fputs(entry.filename.c_str(), file);
        fputc('\0', file);

        /* So we know where the next file will be written. */
        lastEnd += fileLength;
    }

    /* What exactly is this? */
    fputs("L253", file);

    if(uint32_t(ftell(file)) > headerLength){
        Log::error("Calculated header length too short!");
    }

    /* One more byte until where we start the first file... */
    fputc('\0', file);

    /* Write all the files. */
    for(auto &entry : entries){
        Log::info("Writing file \"%s\".", entry.filename);
        entry.seek(0);

        for(character c; !entry.eof();){
            c = entry.getChar();
            fwrite(&c, sizeof(character), 1, file);
        }
    }

    fclose(file);

    Log::info("Finished writing to \"%s\".", filename);

    return true;
}

bool BigArchive::writeBig(const string& filename) {
    /* We only do this on a folder backend, because why would you do it on a .big? */
    if (backend == Folder) {
        return writeBig(entries, filename);
    }
    return false;
}

}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Laszlo Papp <djszapi@archlinux.us>
 *
 * 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 "projectdock.h"

#include "filemanager.h"
#include "historymanager.h"
#include "newobjectcommand.h"
#include "objectmanager.h"
#include "selectionmanager.h"
#include "models/projectmodel.h"
#include "models/models.h"
#include "models/modeltest.h"

#include "lib/selectionmanager.h"
#include "objectmanager.h"
#include "filemanager.h"
#include "historymanager.h"
#include "newobjectcommand.h"

#include "core/debughelper.h"
#include "core/gluon_global.h"
#include "engine/asset.h"
#include "engine/game.h"
#include "engine/gameobject.h"
#include "engine/gameproject.h"
#include "lib/selectionmanager.h"
#include "engine/scene.h"

#include <KDE/KIcon>
#include <KDE/KInputDialog>
#include <KDE/KLocalizedString>
#include <KDE/KMessageBox>
#include <KDE/KRun>
#include <KDE/KStandardDirs>
#include <KDE/KToolBar>
#include <KDE/KFileItemListProperties>
#include <KDE/KFileItemActions>
#include <KDE/KFileDialog>

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtGui/QMenu>
#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QToolButton>

using namespace GluonCreator;

class ProjectDock::ProjectDockPrivate
{
    public:
        ProjectDockPrivate( ProjectDock* parent )
        {
            DEBUG_BLOCK
            q = parent;
            view = 0;
            GluonEngine::Asset* theItem;
            const QHash<QString, const QMetaObject*> types = GluonCore::GluonObjectFactory::instance()->objectTypes();
            QHash<QString, const QMetaObject*>::const_iterator i;
            for( i = types.constBegin(); i != types.constEnd(); ++i )
            {
                theItem = qobject_cast<GluonEngine::Asset*>( i.value()->newInstance() );
                if( theItem )
                {
                    const QList<GluonEngine::AssetTemplate*> templates = theItem->templates();
                    for( int j = 0; j < templates.length(); ++j )
                    {
                        assetTemplates.append( templates[j] );
                    }
                }
                else
                {
                    QObject* obj = i.value()->newInstance();
                    if( obj )
                    {
                        if( obj->inherits( "GluonEngine::Asset" ) )
                        {
                            DEBUG_TEXT2( "The Asset class %1 is lacking the Q_INTERFACES(GluonEngine::Asset) macro", i.value()->className() );
                        }
                    }
                }
            }
        }
        ProjectDock* q;
        ProjectModel* model;
        QTreeView* view;
        KToolBar* toolBar;
        QMenu* newMenu;

        QModelIndex currentContextIndex;
        void menuForObject( QModelIndex index, QMenu* menu );
        QList<QAction*> currentContextMenu;
        QList<GluonEngine::AssetTemplate*> assetTemplates;
};

void ProjectDock::ProjectDockPrivate::menuForObject( QModelIndex index, QMenu* menu )
{
    GluonCore::GluonObject* object = static_cast<GluonCore::GluonObject*>( index.internalPointer() );
    if( object )
    {
        const QMetaObject* mobj = object->metaObject();
        if( mobj )
        {
            currentContextIndex = index;
            QAction* action;
            if( object->inherits( "GluonEngine::Asset" ) )
            {
                GluonEngine::Asset* asset = qobject_cast< GluonEngine::Asset* >( object );
                if( asset )
                {
                    if(!asset->inherits("GluonEngine::Scene"))
                    {
                        KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(asset->absolutePath()));
                        KFileItemListProperties properties(KFileItemList() << item );
                        KFileItemActions* openWithActions = new KFileItemActions(menu);
                        openWithActions->setItemListProperties(properties);

                        openWithActions->addOpenWithActionsTo(menu);
                    }

                    menu->addSeparator();

                    QList<QAction*> actions = asset->actions();
                    foreach( QAction * action, actions )
                    {
                        connect( action, SIGNAL( triggered( bool ) ), model, SIGNAL( layoutChanged() ) );
                        menu->addAction(action);
                    }
                }
            }
            else
            {
                menu->addActions(newMenu->actions());
            }

            if( !object->inherits( "GluonEngine::GameProject" ) )
            {
                menu->addSeparator();

                action = new QAction( KIcon( "edit-delete" ), i18n( "Delete \"%1\"...", object->name() ), this->q );
                connect( action, SIGNAL( triggered() ), q, SLOT( deleteActionTriggered() ) );
                menu->addAction( action );
            }
        }
    }
}

ProjectDock::ProjectDock( const QString& title, QWidget* parent, Qt::WindowFlags flags )
    : QDockWidget( title, parent, flags ), d( new ProjectDockPrivate( this ) )
{
    setObjectName( "ProjectDock" );

    d->model = Models::instance()->projectModel();
    new ModelTest( d->model, this );

    d->view = new QTreeView( this );
    d->view->setModel( d->model );
    d->view->setHeaderHidden( true );
    d->view->setDragEnabled( true );
    d->view->setAcceptDrops( true );
    d->view->setContextMenuPolicy( Qt::CustomContextMenu );
    d->view->setEditTriggers( QAbstractItemView::NoEditTriggers );
    connect( d->view, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( showContextMenuRequested( const QPoint& ) ) );
    connect( d->view->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( selectionChanged( QItemSelection, QItemSelection ) ) );

    d->model->setProject( GluonEngine::Game::instance()->gameProject() );
    connect( GluonEngine::Game::instance(), SIGNAL( currentProjectChanged( GluonEngine::GameProject* ) ), SLOT( currentProjectChanged( GluonEngine::GameProject* ) ) );
    connect( d->view, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( activated( QModelIndex ) ) );

    QWidget* widget = new QWidget( this );
    QVBoxLayout* layout = new QVBoxLayout();
    widget->setLayout( layout );

    d->toolBar = new KToolBar( widget );
    d->toolBar->setIconDimensions( 16 );

    d->newMenu = new QMenu(i18n("New"), d->toolBar);

    QToolButton* menuButton = new QToolButton(d->toolBar);
    menuButton->setIcon(KIcon("document-new"));
    menuButton->setText(i18n("Add..."));
    menuButton->setPopupMode(QToolButton::InstantPopup);
    menuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    menuButton->setMenu(d->newMenu);

    d->toolBar->insertWidget(0, menuButton);

    d->newMenu->addAction( KIcon( "folder" ), i18n( "New Folder" ), this, SLOT( newSubMenuTriggered() ) );
    d->newMenu->addAction( KIcon( "document-new" ), i18n( "New Scene" ), ObjectManager::instance(), SLOT( createNewScene() ) );
    d->newMenu->addSeparator();

    // Run through all the templates and add an action for each...
    foreach( const GluonEngine::AssetTemplate * item, d->assetTemplates )
    {
        QAction* action = d->newMenu->addAction( i18n( "New %1" ).arg( item->name ), this, SLOT( newAssetTriggered() ));
        action->setProperty( "newAssetClassname", QString( item->parent()->metaObject()->className() ) );
        action->setProperty( "newAssetName", item->name );
        action->setProperty( "newAssetPluginname", item->pluginname );
        action->setProperty( "newAssetFilename", item->filename );
    }

    d->newMenu->addSeparator();
    d->newMenu->addAction( i18n("Import Assets..."), this, SLOT(importAssetsTriggered()) );

    d->toolBar->addAction( KIcon( "edit-delete" ), i18nc( "Delete selected object from project", "Delete" ), this, SLOT( deleteActionTriggered() ) );

    layout->addWidget( d->toolBar );
    layout->addWidget( d->view );

    setWidget( widget );
}

ProjectDock::~ProjectDock()
{
    delete d;
}

void ProjectDock::activated( QModelIndex index )
{
    DEBUG_FUNC_NAME
    if( !index.isValid() )
    {
        return;
    }

    QObject* obj = static_cast<QObject*>( index.internalPointer() );
    if( !obj )
    {
        return;
    }

    GluonEngine::Scene* scene = qobject_cast<GluonEngine::Scene*>( obj );
    GluonEngine::Asset* asset = qobject_cast<GluonEngine::Asset*>( obj );
    // Scene's a special asset, so we check for that first
    if( scene )
    {
        if( GluonEngine::Game::instance()->currentScene() != scene )
        {
            GluonEngine::Game::instance()->setCurrentScene( scene );
            GluonEngine::Game::instance()->initializeAll();
            GluonEngine::Game::instance()->drawAll();
        }
    }
    else if( asset )
    {
        FileManager::instance()->openAsset( asset );
    }
}

void ProjectDock::selectionChanged( const QItemSelection& selected, const QItemSelection& deselected )
{
    Q_UNUSED( deselected )

    SelectionManager::SelectionList selection;
    foreach( const QItemSelectionRange & range, selected )
    {
        foreach( const QModelIndex & index, range.indexes() )
        {
            GluonCore::GluonObject* obj = static_cast<GluonCore::GluonObject*>( index.internalPointer() );
            selection.append( obj );
        }
    }
    SelectionManager::instance()->setSelection( selection );
}

void ProjectDock::currentProjectChanged( GluonEngine::GameProject* project )
{
    d->model->setProject( project );

    if( !d->toolBar->isEnabled() )
        d->toolBar->setEnabled( true );

    d->view->expandAll();
}

void ProjectDock::showContextMenuRequested( const QPoint& pos )
{
    QModelIndex index = d->view->indexAt( pos );
    if( !index.isValid() )
        index = d->model->index( 0, 0 );

    QMenu menu( static_cast<GluonCore::GluonObject*>( index.internalPointer() )->name(), this );
    d->menuForObject(index, &menu);
    menu.exec( d->view->mapToGlobal( pos ) );
    connect( &menu, SIGNAL( aboutToHide() ), SLOT( contextMenuHiding() ) );
}

void ProjectDock::contextMenuHiding()
{
    d->currentContextIndex = QModelIndex();
}

void ProjectDock::deleteActionTriggered()
{
    DEBUG_BLOCK
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->view->selectionModel()->currentIndex();

    if( !d->currentContextIndex.isValid() )
        return;

    GluonCore::GluonObject* object = static_cast<GluonCore::GluonObject*>( d->currentContextIndex.internalPointer() );
    DEBUG_TEXT( QString( "Requested deletion of %1" ).arg( object->fullyQualifiedName() ) );
    if( KMessageBox::questionYesNo( this, i18n( "Are you sure you wish to delete %1?\nThis will delete the item and all its children!" ).arg( object->name() ), i18n( "Really Delete?" ) ) == KMessageBox::Yes )
    {
        ObjectManager::instance()->assetDeleted( static_cast<GluonEngine::Asset*>( object ) );

        d->view->selectionModel()->select( d->currentContextIndex.parent(), QItemSelectionModel::ClearAndSelect );
        d->model->removeRows( d->currentContextIndex.row(), 1, d->currentContextIndex.parent() );

        d->currentContextIndex = QModelIndex();
    }
}

void ProjectDock::newSubMenuTriggered()
{
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->model->index(0, 0);

    QModelIndex newFolder = d->model->addChild( new GluonCore::GluonObject( i18n("New Folder") ), d->currentContextIndex );
    d->view->edit(newFolder);
}

void GluonCreator::ProjectDock::newAssetTriggered()
{
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->model->index(0, 0);

    QAction* menuItem = qobject_cast< QAction* >( QObject::sender() );
    if( menuItem )
    {
        QString templateFilename = QString( "gluon/templates/%1/%2" ).arg( menuItem->property( "newAssetPluginname" ).toString() ).arg( menuItem->property( "newAssetFilename" ).toString() );
        QString fileName = GluonCore::Global::dataDirectory() + '/' + templateFilename;
        if( fileName.isEmpty() )
        {
            DEBUG_BLOCK
            DEBUG_TEXT( "Failed at finding the template file!" );
            return;
        }

        GluonEngine::Asset* newAsset = ObjectManager::instance()->createNewAsset(fileName,
                                                                                menuItem->property( "newAssetClassname" ).toString(),
                                                                                menuItem->property( "newAssetName" ).toString() );

        if( newAsset )
        {
            d->model->addChild( newAsset, d->currentContextIndex );
        }
    }
}

void ProjectDock::importAssetsTriggered()
{
    ObjectManager::instance()->createAssets(KFileDialog::getOpenFileNames());
}
<commit_msg>Creator: Set a proper range for the quaternion PWI.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Laszlo Papp <djszapi@archlinux.us>
 *
 * 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 "projectdock.h"

#include "filemanager.h"
#include "historymanager.h"
#include "newobjectcommand.h"
#include "objectmanager.h"
#include "selectionmanager.h"
#include "models/projectmodel.h"
#include "models/models.h"
#include "models/modeltest.h"

#include "lib/selectionmanager.h"
#include "objectmanager.h"
#include "filemanager.h"
#include "historymanager.h"
#include "newobjectcommand.h"

#include "core/debughelper.h"
#include "core/gluon_global.h"
#include "engine/asset.h"
#include "engine/game.h"
#include "engine/gameobject.h"
#include "engine/gameproject.h"
#include "lib/selectionmanager.h"
#include "engine/scene.h"

#include <KDE/KIcon>
#include <KDE/KInputDialog>
#include <KDE/KLocalizedString>
#include <KDE/KMessageBox>
#include <KDE/KRun>
#include <KDE/KStandardDirs>
#include <KDE/KToolBar>
#include <KDE/KFileItemListProperties>
#include <KDE/KFileItemActions>
#include <KDE/KFileDialog>

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtGui/QMenu>
#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QToolButton>

using namespace GluonCreator;

class ProjectDock::ProjectDockPrivate
{
    public:
        ProjectDockPrivate( ProjectDock* parent )
        {
            DEBUG_BLOCK
            q = parent;
            view = 0;
            GluonEngine::Asset* theItem;
            const QHash<QString, const QMetaObject*> types = GluonCore::GluonObjectFactory::instance()->objectTypes();
            QHash<QString, const QMetaObject*>::const_iterator i;
            for( i = types.constBegin(); i != types.constEnd(); ++i )
            {
                theItem = qobject_cast<GluonEngine::Asset*>( i.value()->newInstance() );
                if( theItem )
                {
                    const QList<GluonEngine::AssetTemplate*> templates = theItem->templates();
                    for( int j = 0; j < templates.length(); ++j )
                    {
                        assetTemplates.append( templates[j] );
                    }
                }
                else
                {
                    QObject* obj = i.value()->newInstance();
                    if( obj )
                    {
                        if( obj->inherits( "GluonEngine::Asset" ) )
                        {
                            DEBUG_TEXT2( "The Asset class %1 is lacking the Q_INTERFACES(GluonEngine::Asset) macro", i.value()->className() );
                        }
                    }
                }
            }
        }
        ProjectDock* q;
        ProjectModel* model;
        QTreeView* view;
        KToolBar* toolBar;
        QMenu* newMenu;

        QModelIndex currentContextIndex;
        void menuForObject( QModelIndex index, QMenu* menu );
        QList<QAction*> currentContextMenu;
        QList<GluonEngine::AssetTemplate*> assetTemplates;
};

void ProjectDock::ProjectDockPrivate::menuForObject( QModelIndex index, QMenu* menu )
{
    GluonCore::GluonObject* object = static_cast<GluonCore::GluonObject*>( index.internalPointer() );
    if( object )
    {
        const QMetaObject* mobj = object->metaObject();
        if( mobj )
        {
            currentContextIndex = index;
            QAction* action;
            if( object->inherits( "GluonEngine::Asset" ) )
            {
                GluonEngine::Asset* asset = qobject_cast< GluonEngine::Asset* >( object );
                if( asset )
                {
                    if(!asset->inherits("GluonEngine::Scene"))
                    {
                        KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(asset->absolutePath()));
                        KFileItemListProperties properties(KFileItemList() << item );
                        KFileItemActions* openWithActions = new KFileItemActions(menu);
                        openWithActions->setItemListProperties(properties);

                        openWithActions->addOpenWithActionsTo(menu);
                    }

                    menu->addSeparator();

                    QList<QAction*> actions = asset->actions();
                    foreach( QAction * action, actions )
                    {
                        connect( action, SIGNAL( triggered( bool ) ), model, SIGNAL( layoutChanged() ) );
                        menu->addAction(action);
                    }
                }
            }
            else
            {
                menu->addActions(newMenu->actions());
            }

            if( !object->inherits( "GluonEngine::GameProject" ) )
            {
                menu->addSeparator();

                action = new QAction( KIcon( "edit-delete" ), i18n( "Delete \"%1\"...", object->name() ), this->q );
                connect( action, SIGNAL( triggered() ), q, SLOT( deleteActionTriggered() ) );
                menu->addAction( action );
            }
        }
    }
}

ProjectDock::ProjectDock( const QString& title, QWidget* parent, Qt::WindowFlags flags )
    : QDockWidget( title, parent, flags ), d( new ProjectDockPrivate( this ) )
{
    setObjectName( "ProjectDock" );

    d->model = Models::instance()->projectModel();
    new ModelTest( d->model, this );

    d->view = new QTreeView( this );
    d->view->setModel( d->model );
    d->view->setHeaderHidden( true );
    d->view->setDragEnabled( true );
    d->view->setAcceptDrops( true );
    d->view->setContextMenuPolicy( Qt::CustomContextMenu );
    d->view->setEditTriggers( QAbstractItemView::NoEditTriggers );
    connect( d->view, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( showContextMenuRequested( const QPoint& ) ) );
    connect( d->view->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( selectionChanged( QItemSelection, QItemSelection ) ) );

    d->model->setProject( GluonEngine::Game::instance()->gameProject() );
    connect( GluonEngine::Game::instance(), SIGNAL( currentProjectChanged( GluonEngine::GameProject* ) ), SLOT( currentProjectChanged( GluonEngine::GameProject* ) ) );
    connect( d->view, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( activated( QModelIndex ) ) );

    QWidget* widget = new QWidget( this );
    QVBoxLayout* layout = new QVBoxLayout();
    widget->setLayout( layout );

    d->toolBar = new KToolBar( widget );
    d->toolBar->setIconDimensions( 16 );

    d->newMenu = new QMenu(i18n("New"), d->toolBar);

    QToolButton* menuButton = new QToolButton(d->toolBar);
    menuButton->setIcon(KIcon("document-new"));
    menuButton->setText(i18n("Add..."));
    menuButton->setPopupMode(QToolButton::InstantPopup);
    menuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    menuButton->setMenu(d->newMenu);

    d->toolBar->insertWidget(0, menuButton);

    d->newMenu->addAction( KIcon( "folder" ), i18n( "New Folder" ), this, SLOT( newSubMenuTriggered() ) );
    d->newMenu->addAction( KIcon( "document-new" ), i18n( "New Scene" ), ObjectManager::instance(), SLOT( createNewScene() ) );
    d->newMenu->addSeparator();

    // Run through all the templates and add an action for each...
    foreach( const GluonEngine::AssetTemplate * item, d->assetTemplates )
    {
        QAction* action = d->newMenu->addAction( i18n( "New %1" ).arg( item->name ), this, SLOT( newAssetTriggered() ));
        action->setProperty( "newAssetClassname", QString( item->parent()->metaObject()->className() ) );
        action->setProperty( "newAssetName", item->name );
        action->setProperty( "newAssetPluginname", item->pluginname );
        action->setProperty( "newAssetFilename", item->filename );
    }

    d->newMenu->addSeparator();
    d->newMenu->addAction( KIcon("document-import"), i18n("Import Assets..."), this, SLOT(importAssetsTriggered()) );

    d->toolBar->addAction( KIcon( "edit-delete" ), i18nc( "Delete selected object from project", "Delete" ), this, SLOT( deleteActionTriggered() ) );

    layout->addWidget( d->toolBar );
    layout->addWidget( d->view );

    setWidget( widget );
}

ProjectDock::~ProjectDock()
{
    delete d;
}

void ProjectDock::activated( QModelIndex index )
{
    DEBUG_FUNC_NAME
    if( !index.isValid() )
    {
        return;
    }

    QObject* obj = static_cast<QObject*>( index.internalPointer() );
    if( !obj )
    {
        return;
    }

    GluonEngine::Scene* scene = qobject_cast<GluonEngine::Scene*>( obj );
    GluonEngine::Asset* asset = qobject_cast<GluonEngine::Asset*>( obj );
    // Scene's a special asset, so we check for that first
    if( scene )
    {
        if( GluonEngine::Game::instance()->currentScene() != scene )
        {
            GluonEngine::Game::instance()->setCurrentScene( scene );
            GluonEngine::Game::instance()->initializeAll();
            GluonEngine::Game::instance()->drawAll();
        }
    }
    else if( asset )
    {
        FileManager::instance()->openAsset( asset );
    }
}

void ProjectDock::selectionChanged( const QItemSelection& selected, const QItemSelection& deselected )
{
    Q_UNUSED( deselected )

    SelectionManager::SelectionList selection;
    foreach( const QItemSelectionRange & range, selected )
    {
        foreach( const QModelIndex & index, range.indexes() )
        {
            GluonCore::GluonObject* obj = static_cast<GluonCore::GluonObject*>( index.internalPointer() );
            selection.append( obj );
        }
    }
    SelectionManager::instance()->setSelection( selection );
}

void ProjectDock::currentProjectChanged( GluonEngine::GameProject* project )
{
    d->model->setProject( project );

    if( !d->toolBar->isEnabled() )
        d->toolBar->setEnabled( true );

    d->view->expandAll();
}

void ProjectDock::showContextMenuRequested( const QPoint& pos )
{
    QModelIndex index = d->view->indexAt( pos );
    if( !index.isValid() )
        index = d->model->index( 0, 0 );

    QMenu menu( static_cast<GluonCore::GluonObject*>( index.internalPointer() )->name(), this );
    d->menuForObject(index, &menu);
    menu.exec( d->view->mapToGlobal( pos ) );
    connect( &menu, SIGNAL( aboutToHide() ), SLOT( contextMenuHiding() ) );
}

void ProjectDock::contextMenuHiding()
{
    d->currentContextIndex = QModelIndex();
}

void ProjectDock::deleteActionTriggered()
{
    DEBUG_BLOCK
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->view->selectionModel()->currentIndex();

    if( !d->currentContextIndex.isValid() )
        return;

    GluonCore::GluonObject* object = static_cast<GluonCore::GluonObject*>( d->currentContextIndex.internalPointer() );
    DEBUG_TEXT( QString( "Requested deletion of %1" ).arg( object->fullyQualifiedName() ) );
    if( KMessageBox::questionYesNo( this, i18n( "Are you sure you wish to delete %1?\nThis will delete the item and all its children!" ).arg( object->name() ), i18n( "Really Delete?" ) ) == KMessageBox::Yes )
    {
        ObjectManager::instance()->assetDeleted( static_cast<GluonEngine::Asset*>( object ) );

        d->view->selectionModel()->select( d->currentContextIndex.parent(), QItemSelectionModel::ClearAndSelect );
        d->model->removeRows( d->currentContextIndex.row(), 1, d->currentContextIndex.parent() );

        d->currentContextIndex = QModelIndex();
    }
}

void ProjectDock::newSubMenuTriggered()
{
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->model->index(0, 0);

    QModelIndex newFolder = d->model->addChild( new GluonCore::GluonObject( i18n("New Folder") ), d->currentContextIndex );
    d->view->edit(newFolder);
}

void GluonCreator::ProjectDock::newAssetTriggered()
{
    if( !d->currentContextIndex.isValid() )
        d->currentContextIndex = d->model->index(0, 0);

    QAction* menuItem = qobject_cast< QAction* >( QObject::sender() );
    if( menuItem )
    {
        QString templateFilename = QString( "gluon/templates/%1/%2" ).arg( menuItem->property( "newAssetPluginname" ).toString() ).arg( menuItem->property( "newAssetFilename" ).toString() );
        QString fileName = GluonCore::Global::dataDirectory() + '/' + templateFilename;
        if( fileName.isEmpty() )
        {
            DEBUG_BLOCK
            DEBUG_TEXT( "Failed at finding the template file!" );
            return;
        }

        GluonEngine::Asset* newAsset = ObjectManager::instance()->createNewAsset(fileName,
                                                                                menuItem->property( "newAssetClassname" ).toString(),
                                                                                menuItem->property( "newAssetName" ).toString() );

        if( newAsset )
        {
            d->model->addChild( newAsset, d->currentContextIndex );
        }
    }
}

void ProjectDock::importAssetsTriggered()
{
    ObjectManager::instance()->createAssets(KFileDialog::getOpenFileNames());
}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-10-14 21:35:05
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
ll q;
ll x[2010];
ll p[2010];
ll r[2010];
int ok[2010];

int main()
{
  cin >> N >> M >> q;
  for (auto i = 0; i < M; i++)
  {
    cin >> x[i] >> p[i];
  }
  for (auto i = 0; i < M; i++)
  {
    r[i] = p[i] * N / q;
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  ll rem = N;
  for (auto i = 0; i < M; i++)
  {
    rem -= r[i];
  }
  cerr << "rem = " << rem << endl;
  for (auto i = 0; i < M; i++)
  {
    if (abs(p[i] * N - r[i] * q) > abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 2;
    }
    else if (abs(p[i] * N - r[i] * q) == abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 1;
    }
    else
    {
      ok[i] = 0;
    }
    cerr << "ok[" << i << "] = " << ok[i] << endl;
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 2 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 1 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  r[0] += rem;
  for (auto i = 0; i < M; i++)
  {
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  double E_init = 0;
  for (auto i = 0; i < M; i++)
  {
    E_init += r[i] * x[i];
  }
  E_init /= N;
  cerr << "E_init = " << E_init << endl;
  double E = 0;
  for (auto i = 0; i < M; i++)
  {
    E += abs(p[i] / (double)q - r[i] / (double)N) * abs(x[i] - E_init);
  }
  cout << fixed << setprecision(12) << E * N << endl;
}<commit_msg>tried D.cpp to 'D'<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-10-14 21:35:05
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
ll q;
ll x[2010];
ll p[2010];
ll r[2010];
int ok[2010];

int main()
{
  cin >> N >> M >> q;
  for (auto i = 0; i < M; i++)
  {
    cin >> x[i] >> p[i];
  }
  for (auto i = 0; i < M; i++)
  {
    r[i] = p[i] * N / q;
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  ll rem = N;
  for (auto i = 0; i < M; i++)
  {
    rem -= r[i];
  }
  cerr << "rem = " << rem << endl;
  for (auto i = 0; i < M; i++)
  {
    if (abs(p[i] * N - r[i] * q) > abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 2;
    }
    else if (abs(p[i] * N - r[i] * q) == abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 1;
    }
    else
    {
      ok[i] = 0;
    }
    cerr << "ok[" << i << "] = " << ok[i] << endl;
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 2 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 1 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  r[0] += rem;
  for (auto i = 0; i < M; i++)
  {
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  double E_init = 0;
  for (auto i = 0; i < M; i++)
  {
    E_init += p[i] * x[i];
  }
  E_init /= q;
  cerr << "E_init = " << E_init << endl;
  double E = 0;
  for (auto i = 0; i < M; i++)
  {
    E += abs(p[i] / (double)q - r[i] / (double)N) * abs(x[i] - E_init);
  }
  cout << fixed << setprecision(12) << E * N << endl;
}<|endoftext|>


<commit_before>/*******************************************************************************
 * c7a/api/zip_node.hpp
 *
 * DIANode for a reduce operation. Performs the actual reduce operation
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_ZIP_NODE_HEADER
#define C7A_API_ZIP_NODE_HEADER

#include <c7a/api/dop_node.hpp>
#include <c7a/api/context.hpp>
#include <c7a/api/function_stack.hpp>
#include <c7a/common/logger.hpp>
#include <c7a/net/collective_communication.hpp>

#include <functional>
#include <string>
#include <vector>

namespace c7a {
    namespace api {

//! \addtogroup api Interface
//! \{

/*!
 * A DIANode which performs a Zip operation. Zip combines two DIAs
 * element-by-element. The ZipNode stores the zip_function UDF. The chainable
 * LOps are stored in the Stack.
 *
 *

 *                ParentStack1 ParentStack2
 *                 +--------+   +--------+
 *                 |        |   |        |  A ParentStackX is called with
 *                 |        |   |        |  ParentInputX, and must deliver
 *                 |        |   |        |  a ZipArgX item.
 *               +-+--------+---+--------+-+
 *               | | PreOp1 |   | PreOp2 | |
 *               | +--------+   +--------+ |
 * DIARef<T> --> |           Zip           |
 *               |        +-------+        |
 *               |        |PostOp |        |
 *               +--------+-------+--------+
 *                        |       | New DIARef<T>::stack_ is started
 *                        |       | with PostOp to chain next nodes.
 *                        +-------+
 *

 *
 * \tparam ValueType Output type of the Zip operation.
 *
 * \tparam ParentStack1 Function stack, which contains the chained lambdas
 * between the last and this DIANode for first input DIA.
 *
 * \tparam ParentStack2 Function stack, which contains the chained lambdas
 * between the last and this DIANode for second input DIA.
 *
 * \tparam ZipFunction Type of the ZipFunction.
 */
template <typename ValueType,
typename ParentStack1, typename ParentStack2,
typename ZipFunction>
class TwoZipNode : public DOpNode<ValueType>
{
    static const bool debug = false;

    using Super = DOpNode<ValueType>;
    using Super::context_;

    using ZipArg0 =
    typename common::FunctionTraits<ZipFunction>::template arg<0>;
    using ZipArg1 =
    typename common::FunctionTraits<ZipFunction>::template arg<1>;

    using ParentInput1 = typename ParentStack1::Input;
    using ParentInput2 = typename ParentStack2::Input;

public:
    /*!
     * Constructor for a ZipNode.
     *
     * \param ctx Reference to the Context, which gives iterators for data
     * \param parent1 First parent of the ZipNode
     * \param parent2 Second parent of the ZipNode
     * \param parent_stack1 Function stack with all lambdas between the parent and this node for first DIA
     * \param parent_stack2 Function stack with all lambdas between the parent and this node for second DIA
     * \param zip_function Zip function used to zip elements.
     */
    TwoZipNode(Context& ctx,
               std::shared_ptr<DIANode<ParentInput1>> parent1,
               std::shared_ptr<DIANode<ParentInput2>> parent2,
               ParentStack1& parent_stack1,
               ParentStack2& parent_stack2,
               ZipFunction zip_function)
            : DOpNode<ValueType>(ctx, { parent1, parent2 }),
              zip_function_(zip_function)
    {
        // Hook PreOp(s)
        auto pre_op1_fn = [=](const ZipArg0& input) {
            emit1_(input);
        };
        auto pre_op2_fn = [=](const ZipArg1& input) {
            emit2_(input);
        };

        // close the function stacks with our pre ops and register it at parent
        // nodes for output
        auto lop_chain1 = parent_stack1.push(pre_op1_fn).emit();
        auto lop_chain2 = parent_stack2.push(pre_op2_fn).emit();

        parent1->RegisterChild(lop_chain1);
        parent2->RegisterChild(lop_chain2);

        // Setup Emitters
        for (size_t i = 0; i < num_dias_; ++i) {
            id_[i] = context_.get_data_manager().AllocateDIA();
        }
        emit1_ = context_.get_data_manager().
                template GetLocalEmitter<ZipArg0>(id_[0]);
        emit2_ = context_.get_data_manager().
                template GetLocalEmitter<ZipArg1>(id_[1]);
    }

    /*!
     * Actually executes the zip operation. Uses the member functions PreOp,
     * MainOp and PostOp.
     */
    void Execute() override {
        MainOp();
        // get data from data manager
        auto it1 = context_.get_data_manager().
                template GetIterator<ZipArg0>(id_[0]);
        auto it2 = context_.get_data_manager().
                template GetIterator<ZipArg1>(id_[1]);
        do {
            it1.WaitForMore();
            it2.WaitForMore();
            // Iterate over smaller DIA
            while (it1.HasNext() && it2.HasNext()) {
                auto item = std::make_pair(it1.Next(), it2.Next());
                for (auto func : DIANode<ValueType>::callbacks_) {
                    func(item);
                }
            }
        } while (!it1.IsClosed() && !it2.IsClosed());
    }

    /*!
     * Creates empty stack.
     */
    auto ProduceStack() {
        // Hook PostOp
        auto post_op_fn = [=](ValueType elem, auto emit_func) {
            return PostOp(elem, emit_func);
        };

        return MakeFunctionStack<ValueType>(post_op_fn);
    }

    /*!
     * Returns "[ZipNode]" as a string.
     * \return "[ZipNode]"
     */
    std::string ToString() override {
        return "[ZipNode]";
    }

private:
    //! Zip function
    ZipFunction zip_function_;

    //! Number of storage DIAs backing
    static const size_t num_dias_ = 2;

    //! Ids of storage DIAs
    std::array<data::DIAId, num_dias_> id_;

    //! Emitter
    data::Emitter<ZipArg0> emit1_;
    data::Emitter<ZipArg1> emit2_;

    //!Receive elements from other workers.
    void MainOp() {
        //net::Group flow_group = context_.get_flow_net_group();
        net::FlowControlChannel& channel = context_.get_flow_control_channel();

        data::Manager &data_manager = context_.get_data_manager();
        size_t workers = context_.number_worker();

        // Offsets to declare which target gets which block
        std::vector<size_t> blocks(num_dias_, 0);

        for (size_t i = 0; i < num_dias_; ++i) {
            size_t numElems = data_manager.GetNumElements(id_[i]);
            //net::PrefixSum(flow_group, prefix);
            size_t prefixNumElems = channel.PrefixSum(numElems, common::SumOp<ValueType>(), false);
            //flow_group.TotalSum(prefix);
            size_t totalNumElems = channel.AllReduce(numElems);
            //size_t total = data_manager.GetNumElements(id_[i]);
            size_t per_pe = totalNumElems / workers;
            // offsets for scattering
            std::vector<size_t> offsets(num_dias_, 0);

            size_t offset = 0;
            size_t count = std::min(per_pe - prefixNumElems % per_pe, numElems);
            size_t target = prefixNumElems / per_pe;

            while (numElems > 0) {
                offsets[target] = offset + count - 1;
                prefixNumElems += count;
                numElems -= count;
                offset += count;
                count = std::min(per_pe - prefixNumElems % per_pe, numElems);
                target++;
            }

            for (size_t x = target; x < workers; x++)
                offsets[x] = offsets[x-1];

            data_manager.Scatter(id_[i], data_manager.AllocateNetworkChannel(), offsets);
        }
    }

    //! Use the ZipFunction to Zip workers
    template <typename Emitter>
    void PostOp(ValueType input, Emitter emit_func) {
        emit_func(zip_function_(input.first, input.second));
    }
};

template <typename CurrentType, typename Stack>
template <typename ZipFunction, typename SecondDIA>
auto DIARef<CurrentType, Stack>::Zip(
        const ZipFunction &zip_function, SecondDIA second_dia) {

    using ZipResult
    = typename common::FunctionTraits<ZipFunction>::result_type;

    using ZipResultNode
    = TwoZipNode<ZipResult, Stack, typename SecondDIA::Stack,
            ZipFunction>;

    auto zip_node
<<<<<<< HEAD
            = std::make_shared<ZipResultNode>(node_->get_context(),
                                              node_.get(),
                                              second_dia.get_node(),
                                              local_stack_,
                                              second_dia.get_stack(),
                                              zip_function);
=======
        = std::make_shared<ZipResultNode>(node_->get_context(),
                                          node_,
                                          second_dia.get_node(),
                                          local_stack_,
                                          second_dia.get_stack(),
                                          zip_function);
>>>>>>> origin/master

    auto zip_stack = zip_node->ProduceStack();

    return DIARef<ZipResultNode, decltype(zip_stack)>(
            std::move(zip_node), zip_stack);
}

} // namespace api
} // namespace c7a

//! \}

#endif // !C7A_API_ZIP_NODE_HEADER

/******************************************************************************/<commit_msg>fixed artefacts after merge conflict<commit_after>/*******************************************************************************
 * c7a/api/zip_node.hpp
 *
 * DIANode for a reduce operation. Performs the actual reduce operation
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_ZIP_NODE_HEADER
#define C7A_API_ZIP_NODE_HEADER

#include <c7a/api/dop_node.hpp>
#include <c7a/api/context.hpp>
#include <c7a/api/function_stack.hpp>
#include <c7a/common/logger.hpp>
#include <c7a/net/collective_communication.hpp>

#include <functional>
#include <string>
#include <vector>

namespace c7a {
    namespace api {

//! \addtogroup api Interface
//! \{

/*!
 * A DIANode which performs a Zip operation. Zip combines two DIAs
 * element-by-element. The ZipNode stores the zip_function UDF. The chainable
 * LOps are stored in the Stack.
 *
 *

 *                ParentStack1 ParentStack2
 *                 +--------+   +--------+
 *                 |        |   |        |  A ParentStackX is called with
 *                 |        |   |        |  ParentInputX, and must deliver
 *                 |        |   |        |  a ZipArgX item.
 *               +-+--------+---+--------+-+
 *               | | PreOp1 |   | PreOp2 | |
 *               | +--------+   +--------+ |
 * DIARef<T> --> |           Zip           |
 *               |        +-------+        |
 *               |        |PostOp |        |
 *               +--------+-------+--------+
 *                        |       | New DIARef<T>::stack_ is started
 *                        |       | with PostOp to chain next nodes.
 *                        +-------+
 *

 *
 * \tparam ValueType Output type of the Zip operation.
 *
 * \tparam ParentStack1 Function stack, which contains the chained lambdas
 * between the last and this DIANode for first input DIA.
 *
 * \tparam ParentStack2 Function stack, which contains the chained lambdas
 * between the last and this DIANode for second input DIA.
 *
 * \tparam ZipFunction Type of the ZipFunction.
 */
template <typename ValueType,
typename ParentStack1, typename ParentStack2,
typename ZipFunction>
class TwoZipNode : public DOpNode<ValueType>
{
    static const bool debug = false;

    using Super = DOpNode<ValueType>;
    using Super::context_;

    using ZipArg0 =
    typename common::FunctionTraits<ZipFunction>::template arg<0>;
    using ZipArg1 =
    typename common::FunctionTraits<ZipFunction>::template arg<1>;

    using ParentInput1 = typename ParentStack1::Input;
    using ParentInput2 = typename ParentStack2::Input;

public:
    /*!
     * Constructor for a ZipNode.
     *
     * \param ctx Reference to the Context, which gives iterators for data
     * \param parent1 First parent of the ZipNode
     * \param parent2 Second parent of the ZipNode
     * \param parent_stack1 Function stack with all lambdas between the parent and this node for first DIA
     * \param parent_stack2 Function stack with all lambdas between the parent and this node for second DIA
     * \param zip_function Zip function used to zip elements.
     */
    TwoZipNode(Context& ctx,
               std::shared_ptr<DIANode<ParentInput1>> parent1,
               std::shared_ptr<DIANode<ParentInput2>> parent2,
               ParentStack1& parent_stack1,
               ParentStack2& parent_stack2,
               ZipFunction zip_function)
            : DOpNode<ValueType>(ctx, { parent1, parent2 }),
              zip_function_(zip_function)
    {
        // Hook PreOp(s)
        auto pre_op1_fn = [=](const ZipArg0& input) {
            emit1_(input);
        };
        auto pre_op2_fn = [=](const ZipArg1& input) {
            emit2_(input);
        };

        // close the function stacks with our pre ops and register it at parent
        // nodes for output
        auto lop_chain1 = parent_stack1.push(pre_op1_fn).emit();
        auto lop_chain2 = parent_stack2.push(pre_op2_fn).emit();

        parent1->RegisterChild(lop_chain1);
        parent2->RegisterChild(lop_chain2);

        // Setup Emitters
        for (size_t i = 0; i < num_dias_; ++i) {
            id_[i] = context_.get_data_manager().AllocateDIA();
        }
        emit1_ = context_.get_data_manager().
                template GetLocalEmitter<ZipArg0>(id_[0]);
        emit2_ = context_.get_data_manager().
                template GetLocalEmitter<ZipArg1>(id_[1]);
    }

    /*!
     * Actually executes the zip operation. Uses the member functions PreOp,
     * MainOp and PostOp.
     */
    void Execute() override {
        MainOp();
        // get data from data manager
        auto it1 = context_.get_data_manager().
                template GetIterator<ZipArg0>(id_[0]);
        auto it2 = context_.get_data_manager().
                template GetIterator<ZipArg1>(id_[1]);
        do {
            it1.WaitForMore();
            it2.WaitForMore();
            // Iterate over smaller DIA
            while (it1.HasNext() && it2.HasNext()) {
                auto item = std::make_pair(it1.Next(), it2.Next());
                for (auto func : DIANode<ValueType>::callbacks_) {
                    func(item);
                }
            }
        } while (!it1.IsClosed() && !it2.IsClosed());
    }

    /*!
     * Creates empty stack.
     */
    auto ProduceStack() {
        // Hook PostOp
        auto post_op_fn = [=](ValueType elem, auto emit_func) {
            return PostOp(elem, emit_func);
        };

        return MakeFunctionStack<ValueType>(post_op_fn);
    }

    /*!
     * Returns "[ZipNode]" as a string.
     * \return "[ZipNode]"
     */
    std::string ToString() override {
        return "[ZipNode]";
    }

private:
    //! Zip function
    ZipFunction zip_function_;

    //! Number of storage DIAs backing
    static const size_t num_dias_ = 2;

    //! Ids of storage DIAs
    std::array<data::DIAId, num_dias_> id_;

    //! Emitter
    data::Emitter<ZipArg0> emit1_;
    data::Emitter<ZipArg1> emit2_;

    //!Receive elements from other workers.
    void MainOp() {
        //net::Group flow_group = context_.get_flow_net_group();
        net::FlowControlChannel& channel = context_.get_flow_control_channel();

        data::Manager &data_manager = context_.get_data_manager();
        size_t workers = context_.number_worker();

        // Offsets to declare which target gets which block
        std::vector<size_t> blocks(num_dias_, 0);

        for (size_t i = 0; i < num_dias_; ++i) {
            size_t numElems = data_manager.GetNumElements(id_[i]);
            //net::PrefixSum(flow_group, prefix);
            size_t prefixNumElems = channel.PrefixSum(numElems, common::SumOp<ValueType>(), false);
            //flow_group.TotalSum(prefix);
            size_t totalNumElems = channel.AllReduce(numElems);
            //size_t total = data_manager.GetNumElements(id_[i]);
            size_t per_pe = totalNumElems / workers;
            // offsets for scattering
            std::vector<size_t> offsets(num_dias_, 0);

            size_t offset = 0;
            size_t count = std::min(per_pe - prefixNumElems % per_pe, numElems);
            size_t target = prefixNumElems / per_pe;

            while (numElems > 0) {
                offsets[target] = offset + count - 1;
                prefixNumElems += count;
                numElems -= count;
                offset += count;
                count = std::min(per_pe - prefixNumElems % per_pe, numElems);
                target++;
            }

            for (size_t x = target; x < workers; x++)
                offsets[x] = offsets[x-1];

            data_manager.Scatter(id_[i], data_manager.AllocateNetworkChannel(), offsets);
        }
    }

    //! Use the ZipFunction to Zip workers
    template <typename Emitter>
    void PostOp(ValueType input, Emitter emit_func) {
        emit_func(zip_function_(input.first, input.second));
    }
};

template <typename CurrentType, typename Stack>
template <typename ZipFunction, typename SecondDIA>
auto DIARef<CurrentType, Stack>::Zip(
        const ZipFunction &zip_function, SecondDIA second_dia) {

    using ZipResult
    = typename common::FunctionTraits<ZipFunction>::result_type;

    using ZipResultNode
    = TwoZipNode<ZipResult, Stack, typename SecondDIA::Stack,
            ZipFunction>;

    auto zip_node
        = std::make_shared<ZipResultNode>(node_->get_context(),
                                          node_,
                                          second_dia.get_node(),
                                          local_stack_,
                                          second_dia.get_stack(),
                                          zip_function);

    auto zip_stack = zip_node->ProduceStack();

    return DIARef<ZipResultNode, decltype(zip_stack)>(
            std::move(zip_node), zip_stack);
}

} // namespace api
} // namespace c7a

//! \}

#endif // !C7A_API_ZIP_NODE_HEADER

/******************************************************************************/<|endoftext|>


<commit_before>//C++ 11ʵֵlexical_castΪ˰boost
//: https://github.com/qicosmos/cosmos

#ifndef CPP_11_LEXICAL_CAST_HPP
#define CPP_11_LEXICAL_CAST_HPP

#include <type_traits>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <stdexcept>
#include <cctype>
#include <cstring>
using namespace std;

namespace detail
{
static const char* strue = "true";
static const char* sfalse = "false";

template <typename To, typename From>
struct Converter
{
};

//to numeric
template <typename From>
struct Converter<int, From>
{
    static int convert(const string& from)
    {
        return std::atoi(from.c_str());
    }

    static int convert(const char* from)
    {
        return std::atoi(from);
    }
};

template <typename From>
struct Converter<long, From>
{
    static long convert(const string& from)
    {
        return std::atol(from.c_str());
    }

    static long convert(const char* from)
    {
        return std::atol(from);
    }
};

template <typename From>
struct Converter<long long, From>
{
    static long long convert(const string& from)
    {
        return std::atoll(from.c_str());
    }

    static long long convert(const char* from)
    {
        return std::atoll(from);
    }
};

template <typename From>
struct Converter<double, From>
{
    static double convert(const string& from)
    {
        return std::atof(from.c_str());
    }

    static double convert(const char* from)
    {
        return std::atof(from);
    }
};

template <typename From>
struct Converter<float, From>
{
    static float convert(const string& from)
    {
        return (float)std::atof(from.c_str());
    }

    static float convert(const char* from)
    {
        return (float)std::atof(from);
    }
};

//to bool
template <typename From>
struct Converter<bool, From>
{
    static typename std::enable_if<std::is_integral<From>::value, bool>::type convert(From from)
    {
        return !!from;
    }
};

static bool checkbool(const char* from, const size_t len, const char* s)
{
    for(size_t i = 0; i < len; i++)
    {
        if(from[i] != s[i])
        {
            return false;
        }
    }

    return true;
}

static bool convert(const char* from)
{
    const unsigned int len = strlen(from);
    if(len != 4 && len != 5)
        throw std::invalid_argument("argument is invalid");

    bool r = true;
    if(len == 4)
    {
        //"true"
        r = checkbool(from, len, strue);

        if(r)
            return true;
    }
    else if(len == 5)
    {
        //"false"
        r = checkbool(from, len, sfalse);

        if(r)
            return false;
    }
    else
    {
        // תΪbool
        int value = Converter<int, const char*>::convert(from);
        return (value > 0);
    }

    throw std::invalid_argument("argument is invalid");
}

template <>
struct Converter<bool, string>
{
    static bool convert(const string& from)
    {
        return detail::convert(from.c_str());
    }
};

template <>
struct Converter<bool, const char*>
{
    static bool convert(const char* from)
    {
        return detail::convert(from);
    }
};

template <>
struct Converter<bool, char*>
{
    static bool convert(char* from)
    {
        return detail::convert(from);
    }
};

template <unsigned N>
struct Converter<bool, const char[N]>
{
    static bool convert(const char(&from)[N])
    {
        return detail::convert(from);
    }
};

template <unsigned N>
struct Converter<bool, char[N]>
{
    static bool convert(const char(&from)[N])
    {
        return detail::convert(from);
    }
};

//to string
template <typename From>
struct Converter<string, From>
{
    static string convert(const From& from)
    {
        return std::to_string(from);
    }
};
}

template <typename To, typename From>
typename std::enable_if < !std::is_same<To, From>::value, To >::type lexical_cast(const From& from)
{
    return detail::Converter<To, From>::convert(from);
}

template <typename To, typename From>
typename std::enable_if<std::is_same<To, From>::value, To>::type lexical_cast(const From& from)
{
    return from;
}

template<typename ValueTYPE>
bool ValueFromString(const std::string& strValue, ValueTYPE& nValue)
{
    try
    {
        nValue = lexical_cast<ValueTYPE>(strValue);
        return true;
    }
    catch(...)
    {
        return false;
    }

    return false;
}

template<typename ValueTYPE>
bool ValueToString(const ValueTYPE& nValue, std::string& strData)
{
    try
    {
        strData = lexical_cast<std::string>(nValue);
        return true;
    }
    catch(...)
    {
        return false;
    }

    return false;
}
#endif //!CPP_11_LEXICAL_CAST_HPP<commit_msg>fix lexical_cast bug when convert number string to boolean<commit_after>//C++ 11ʵֵlexical_castΪ˰boost
//: https://github.com/qicosmos/cosmos

#ifndef CPP_11_LEXICAL_CAST_HPP
#define CPP_11_LEXICAL_CAST_HPP

#include <type_traits>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <stdexcept>
#include <cctype>
#include <cstring>
using namespace std;

namespace detail
{
static const char* strue = "true";
static const char* sfalse = "false";

template <typename To, typename From>
struct Converter
{
};

//to numeric
template <typename From>
struct Converter<int, From>
{
    static int convert(const string& from)
    {
        return std::atoi(from.c_str());
    }

    static int convert(const char* from)
    {
        return std::atoi(from);
    }
};

template <typename From>
struct Converter<long, From>
{
    static long convert(const string& from)
    {
        return std::atol(from.c_str());
    }

    static long convert(const char* from)
    {
        return std::atol(from);
    }
};

template <typename From>
struct Converter<long long, From>
{
    static long long convert(const string& from)
    {
        return std::atoll(from.c_str());
    }

    static long long convert(const char* from)
    {
        return std::atoll(from);
    }
};

template <typename From>
struct Converter<double, From>
{
    static double convert(const string& from)
    {
        return std::atof(from.c_str());
    }

    static double convert(const char* from)
    {
        return std::atof(from);
    }
};

template <typename From>
struct Converter<float, From>
{
    static float convert(const string& from)
    {
        return (float)std::atof(from.c_str());
    }

    static float convert(const char* from)
    {
        return (float)std::atof(from);
    }
};

//to bool
template <typename From>
struct Converter<bool, From>
{
    static typename std::enable_if<std::is_integral<From>::value, bool>::type convert(From from)
    {
        return !!from;
    }
};

static bool checkbool(const char* from, const size_t len, const char* s)
{
    for(size_t i = 0; i < len; i++)
    {
        if(from[i] != s[i])
        {
            return false;
        }
    }

    return true;
}

static bool convert(const char* from)
{
    const unsigned int len = strlen(from);
    //if(len != 4 && len != 5)
    //    throw std::invalid_argument("argument is invalid");

    bool r = true;
    if(len == 4)
    {
        //"true"
        r = checkbool(from, len, strue);

        if(r)
            return true;
    }
    else if(len == 5)
    {
        //"false"
        r = checkbool(from, len, sfalse);

        if(r)
            return false;
    }
    else
    {
        // תΪbool
        int value = Converter<int, const char*>::convert(from);
        return (value > 0);
    }

    throw std::invalid_argument("argument is invalid");
}

template <>
struct Converter<bool, string>
{
    static bool convert(const string& from)
    {
        return detail::convert(from.c_str());
    }
};

template <>
struct Converter<bool, const char*>
{
    static bool convert(const char* from)
    {
        return detail::convert(from);
    }
};

template <>
struct Converter<bool, char*>
{
    static bool convert(char* from)
    {
        return detail::convert(from);
    }
};

template <unsigned N>
struct Converter<bool, const char[N]>
{
    static bool convert(const char(&from)[N])
    {
        return detail::convert(from);
    }
};

template <unsigned N>
struct Converter<bool, char[N]>
{
    static bool convert(const char(&from)[N])
    {
        return detail::convert(from);
    }
};

//to string
template <typename From>
struct Converter<string, From>
{
    static string convert(const From& from)
    {
        return std::to_string(from);
    }
};
}

template <typename To, typename From>
typename std::enable_if < !std::is_same<To, From>::value, To >::type lexical_cast(const From& from)
{
    return detail::Converter<To, From>::convert(from);
}

template <typename To, typename From>
typename std::enable_if<std::is_same<To, From>::value, To>::type lexical_cast(const From& from)
{
    return from;
}

template<typename ValueTYPE>
bool ValueFromString(const std::string& strValue, ValueTYPE& nValue)
{
    try
    {
        nValue = lexical_cast<ValueTYPE>(strValue);
        return true;
    }
    catch(...)
    {
        return false;
    }

    return false;
}

template<typename ValueTYPE>
bool ValueToString(const ValueTYPE& nValue, std::string& strData)
{
    try
    {
        strData = lexical_cast<std::string>(nValue);
        return true;
    }
    catch(...)
    {
        return false;
    }

    return false;
}
#endif //!CPP_11_LEXICAL_CAST_HPP<|endoftext|>


<commit_before>/***********************************************************************
 simple1.cpp - Example showing the simplest way to get data from a MySQL
    database with MySQL++.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ 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.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>

using namespace std;

int
main(int argc, char *argv[])
{
	// Connect to the sample database.
	mysqlpp::Connection con(false);
	if (!connect_to_db(argc, argv, con)) {
		return 1;
	}

	// Retrieve the sample stock table set up by resetdb
	mysqlpp::Query query = con.query();
	query << "select * from stock";
	mysqlpp::Result res = query.store();

	// Display results
	if (res) {
		// Display header
		cout.setf(ios::left);
		cout << setw(21) << "Item" <<
				setw(10) << "Num" <<
				setw(10) << "Weight" <<
				setw(10) << "Price" <<
				"Date" << endl << endl;

		// Get each row in result set, and print its contents
		mysqlpp::Row row;
		mysqlpp::Row::size_type i;
		for (i = 0; row = res.at(i); ++i) {
			cout << setw(20) << row["item"] << ' ' <<
					setw(9) << row["num"] << ' ' <<
					setw(9) << row["weight"] << ' ' <<
					setw(9) << row["price"] << ' ' <<
					setw(9) << row["sdate"] <<
					endl;
		}
	}
	else {
		cerr << "Failed to get stock item: " << query.error() << endl;
		return 1;
	}

	return 0;
}
<commit_msg>New simple1.cpp, simpler than simple2.cpp; basically, an exception-less and SSQLS-free version of custom6.<commit_after>/***********************************************************************
 simple1.cpp - Example showing the simplest way to get data from a MySQL
    table with MySQL++.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ 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.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>

using namespace std;

int
main(int argc, char *argv[])
{
	// Connect to the sample database.
	mysqlpp::Connection con(false);
	if (!connect_to_db(argc, argv, con)) {
		return 1;
	}

	// Retrieve a subset of the sample stock table set up by resetdb
	mysqlpp::Query query = con.query();
	query << "select item from stock";
	vector<mysqlpp::Row> res;
	query.storein(res);

	// Display the result set
	cout << "We have:" << endl;
	vector<mysqlpp::Row>::iterator it;
	for (it = res.begin(); it != res.end(); ++it) {
		cout << '\t' << it->at(0) << endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "make_random_data/make_random_data.hpp"
#include "sort/merge.hpp"
#include "sort/selection.hpp"
#include "sort/insertion.hpp"
#include "sort/bubble.hpp"

#define MIN_SIZE    100
#define MAX_SIZE    100000
#define SIZE_STEP   10

int main(void)
{
    int *original = make_random_data(MAX_SIZE);

    for(int size_of_data = MIN_SIZE; size_of_data <= MAX_SIZE; size_of_data *= SIZE_STEP)
    {
        printf("SIZE OF DATA: %d\n", size_of_data);

        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            merge(data, size_of_data);

            clock_t after = clock();

            printf("%12s\t%lf\n", "Merge: ", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            selection(data, size_of_data);

            clock_t after = clock();

            printf("%12s\t%lf\n", "Selection: ", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            insertion(data, size_of_data);

            clock_t after = clock();

            printf("%12s%lf\n", "Insertion: ", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            bubble(data, size_of_data);

            clock_t after = clock();

            printf("%12s%lf\n", "Bubble: ", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }

        putchar('\n');
    }

    free_random_data(original);

    return 0;
}
<commit_msg>Align the output<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "make_random_data/make_random_data.hpp"
#include "sort/merge.hpp"
#include "sort/selection.hpp"
#include "sort/insertion.hpp"
#include "sort/bubble.hpp"

#define MIN_SIZE    100
#define MAX_SIZE    100000
#define SIZE_STEP   10

int main(void)
{
    int *original = make_random_data(MAX_SIZE);

    for(int size_of_data = MIN_SIZE; size_of_data <= MAX_SIZE; size_of_data *= SIZE_STEP)
    {
        printf("SIZE OF DATA: %d\n", size_of_data);

        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            merge(data, size_of_data);

            clock_t after = clock();

            printf("Merge:\t\t%lf\n", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            selection(data, size_of_data);

            clock_t after = clock();

            printf("Selection:\t%lf\n", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            insertion(data, size_of_data);

            clock_t after = clock();

            printf("Insertion:\t%lf\n", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }
        {
            int *data = (int *)malloc(sizeof(int) * size_of_data);
            memcpy(data, original, size_of_data);

            clock_t before = clock();

            bubble(data, size_of_data);

            clock_t after = clock();

            printf("Bubble:\t\t%lf\n", (double)(after - before)/CLOCKS_PER_SEC);
            free(data);
        }

        putchar('\n');
    }

    free_random_data(original);

    return 0;
}
<|endoftext|>