<commit_before>#include "scene.hpp"

#include <iostream>

#include <Core/camera.hpp>
#include <Models/dynamicmodel.hpp>
#include <Utilities/exceptions.hpp>
#include <Utilities/log.hpp>
#include <Render/renderobject.hpp>
#include <Render/renderchain.hpp>
#include <Resources/resourcehandler.hpp>

using namespace luabridge;
using json = nlohmann::json;

// TODO Implement scene closing
// TODO Implement some sort of multithreading in lua (coroutines?)

// NOTE How slow is calling lua functions?
// NOTE What should lua be capable of doing?

Scene::Scene(const Display* const display, lua_State* luaState, std::string scenename)
        : m_display(display), m_luaState(luaState) {

    m_renderChain = std::make_unique<RenderChain>();
    m_renderChain->setAmbientColor(glm::vec3(1.0f, 0.6f, 0.1f));
    m_renderChain->setAmbientIntensity(1.0f);
    m_resourceHandler = std::make_unique<ResourceHandler>();

    std::string script =  "Resources/Scenes/" + scenename + "/script.lua";
    std::string filename = "Resources/Scenes/" + scenename + "/scene.json";

    buildLuaNamespace();

    luaL_dofile(m_luaState, script.c_str());

    registerLuaFunctions();

    std::string contents;
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
    } else {
        throw GenericException(filename + " doesn't exist");
    }

    try {
        const json scene = json::parse(contents);
        m_resourceHandler->loadResources(scene);

        if(scene.find("staticObjects") != scene.end()) {
            std::vector<json> objects = scene["staticObjects"];
            for(const json& object : objects) {
                try {
                    std::string type = object["type"];
                    IRenderObject* rObject = nullptr;

                    // NOTE Are there other types of render obects i might want to load?
                    if(type == "line") {
                        rObject = m_resourceHandler->generateLine(object);
                    } else if(type == "staticmodel") {
                        rObject = m_resourceHandler->generateModel(object, m_resourceHandler->getResource<Model3D>(object["resource"]));
                    } else if(type == "rawstaticmodel") {
                        rObject = m_resourceHandler->generateModel(object);
                    }

                    if(rObject != nullptr) {
                        m_renderObjects.push_back(std::unique_ptr<IRenderObject>(rObject));
                    }
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }

        // TODO Implement actual dynamic model loading
        // NOTE What is "actual dynamic loading"?
        if(scene.find("dynamicObjects") != scene.end()) {
            std::vector<json> objects = scene["dynamicObjects"];
            for(const json& object : objects) {
                try {
                    auto name = object["name"];
                    //m_dynamicModels[name] = std::make_unique<DynamicModel>(m_resourceHandler->GetResource<Model3D>(object["resource"]));
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }
    } catch(std::exception& error) {
        Log::getErrorLog() << "Parsing of " << filename << " failed: " << error.what() << '\n';
    }

    for(const auto& obj : m_renderObjects) {
        m_renderChain->attach(obj.get());
    }
}

// NOTE Make sure scene is 100% closed when *this* is deleted
Scene::~Scene() {
}

// TODO Implement entity transformation functions
// NOTE What other functions are necessary to expose to lua?
void Scene::buildLuaNamespace() {
    getGlobalNamespace(m_luaState)
        .beginClass<glm::vec2>("vec2")
            .addConstructor<void(*)(float, float)>()
            .addData("x", &glm::vec2::x)
            .addData("y", &glm::vec2::y)
        .endClass()
        .beginClass<glm::vec3>("vec3")
            .addConstructor<void(*)(float, float, float)>()
            .addData("x", &glm::vec3::x)
            .addData("y", &glm::vec3::y)
            .addData("z", &glm::vec3::z)
        .endClass()
        .beginClass<glm::vec4>("vec4")
            .addConstructor<void(*)(float, float, float, float)>()
            .addData("x", &glm::vec4::x)
            .addData("y", &glm::vec4::y)
            .addData("z", &glm::vec4::z)
            .addData("w", &glm::vec4::w)
        .endClass()
        .beginNamespace("Game")
            .beginClass<Camera>("Camera")
                .addFunction("MoveCamera", &Camera::moveCamera)
                .addFunction("SetCamera", &Camera::setPosition)
            .endClass()
            .beginClass<Entity>("Entity")
                .addConstructor<void(*)(void)>()
                .addProperty("visible", &Entity::isVisible, &Entity::setVisible)
                .addProperty("name", &Entity::getName, &Entity::setName)
            .endClass()
            .beginClass<Scene>("Scene")
                .addFunction("BindFunctionToKey", &Scene::bindFunctionToKey)
                .addFunction("GetCamera", &Scene::getCamera)
                .addFunction("AddEntity", &Scene::addEntity)
                .addFunction("GetEntity", &Scene::getEntity)
                .addFunction("Spawn", &Scene::spawn)
            .endClass()
        .endNamespace();

    push(m_luaState, this);
    lua_setglobal(m_luaState, "Level");
}

// NOTE Are there other necessary function the engine might want to call?
void Scene::registerLuaFunctions() {
    m_startFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "Start"));
    if(!m_startFunc->isFunction()) {
        throw GenericException("Start function wasn't found");
    }

    m_renderFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "GameLoop"));
    if(!m_renderFunc->isFunction()) {
        throw GenericException("Render function wasn't found");
    }
}

// Is this the best way to do it?
void Scene::start() {
    (*m_startFunc)();
}

// NOTE Do I want to call the render func or perform a render first?
void Scene::gameLoop() {
    m_renderChain->render(m_display);
    (*m_renderFunc)();
}

// TODO Find some way to expose what keys are pressed to lua
void Scene::bindFunctionToKey(int ikey, LuaRef function, bool repeat) {
    if(!function.isFunction()) {
        throw GenericException("function wasn't found");
    }

    InputKey key = (InputKey)ikey;
    m_luaKeyBinds[key] = std::make_unique<LuaRef>(function);
    if(repeat) {
        m_display->getInputController()->registerWhileKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    } else {
        m_display->getInputController()->registerOnKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    }
}

// NOTE Do i want to be able to easily destroy an entity?
Entity* Scene::spawn(const std::string& name, const std::string& resource, glm::vec3 location) {
    auto res = m_resourceHandler->getResource<Model3D>(resource);
    if(res == nullptr) {
        throw BadResource("resource isn't a model or doesn't exist", resource);
    }

    if(m_entities.find(name) != m_entities.end()) {
        Log::getErrorLog() << "Attempting to spawn entity with name that has already been registered\n";
        return m_entities[name].get();
    }

    auto dyn = new DynamicModel(res);
    dyn->translate(location);
    dyn->bindShader(m_resourceHandler->getShader("shader_staticmodel"));
    m_renderChain->attach(dyn);
    m_renderObjects.push_back(std::unique_ptr<IRenderObject>(dyn));

    auto ent = new Entity();
    ent->bindModel(dyn);
    m_entities[name] = std::unique_ptr<Entity>(ent);

    return ent;
}

// NOTE What is the purpose of this?
void Scene::addEntity(const std::string& name, Entity* const ent) {
    if(m_entities.find(name) != m_entities.end()) {
        Log::error(name + " entity attempted to be added a second time, skipped");
    }

    if(ent != nullptr) {
        m_entities[name] = std::unique_ptr<Entity>(ent);
    } else {
        Log::error(name + " entity was null, skipped");
    }
}

// TODO Expand on the capabilites of an entity, ie. how does the user interact with them?
Entity* Scene::getEntity(const std::string& name) const {
    if(m_entities.find(name) != m_entities.end()) {
        return (*m_entities.find(name)).second.get();
    }
    return nullptr;
}

Camera* Scene::getCamera() const {
    return m_display->getCamera();
}
<commit_msg>small fix<commit_after>#include "scene.hpp"

#include <iostream>

#include <Core/camera.hpp>
#include <Models/dynamicmodel.hpp>
#include <Utilities/exceptions.hpp>
#include <Utilities/log.hpp>
#include <Render/renderobject.hpp>
#include <Render/renderchain.hpp>
#include <Resources/resourcehandler.hpp>

using namespace luabridge;
using json = nlohmann::json;

// TODO Implement scene closing
// TODO Implement some sort of multithreading in lua (coroutines?)

// NOTE How slow is calling lua functions?
// NOTE What should lua be capable of doing?

Scene::Scene(const Display* const display, lua_State* luaState, std::string scenename)
        : m_display(display), m_luaState(luaState) {

    m_renderChain = std::make_unique<RenderChain>();
    m_renderChain->setAmbientColor(glm::vec3(1.0f, 0.6f, 0.1f));
    m_renderChain->setAmbientIntensity(1.0f);
    m_resourceHandler = std::make_unique<ResourceHandler>();

    std::string script =  "Resources/Scenes/" + scenename + "/script.lua";
    std::string filename = "Resources/Scenes/" + scenename + "/scene.json";

    buildLuaNamespace();

    luaL_dofile(m_luaState, script.c_str());

    registerLuaFunctions();

    std::string contents;
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
    } else {
        throw GenericException(filename + " doesn't exist");
    }

    try {
        const json scene = json::parse(contents);
        m_resourceHandler->loadResources(scene);

        if(scene.find("staticObjects") != scene.end()) {
            std::vector<json> objects = scene["staticObjects"];
            for(const json& object : objects) {
                try {
                    std::string type = object["type"];
                    IRenderObject* rObject = nullptr;

                    // NOTE Are there other types of render obects i might want to load?
                    if(type == "line") {
                        rObject = m_resourceHandler->generateLine(object);
                    } else if(type == "staticmodel") {
                        rObject = m_resourceHandler->generateModel(object, m_resourceHandler->getResource<Model3D>(object["resource"]));
                    } else if(type == "rawstaticmodel") {
                        rObject = m_resourceHandler->generateModel(object);
                    }

                    if(rObject != nullptr) {
                        m_renderObjects.push_back(std::unique_ptr<IRenderObject>(rObject));
                    }
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }

        // TODO Implement actual dynamic model loading
        // NOTE What is "actual dynamic loading"?
        if(scene.find("dynamicObjects") != scene.end()) {
            std::vector<json> objects = scene["dynamicObjects"];
            for(const json& object : objects) {
                try {
                    auto name = object["name"];
                    //m_dynamicModels[name] = std::make_unique<DynamicModel>(m_resourceHandler->GetResource<Model3D>(object["resource"]));
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }
    } catch(std::exception& error) {
        Log::getErrorLog() << "Parsing of " << filename << " failed: " << error.what() << '\n';
    }

    for(const auto& obj : m_renderObjects) {
        m_renderChain->attach(obj.get());
    }
}

// NOTE Make sure scene is 100% closed when *this* is deleted
Scene::~Scene() {
}

// TODO Implement entity transformation functions
// NOTE What other functions are necessary to expose to lua?
void Scene::buildLuaNamespace() {
    getGlobalNamespace(m_luaState)
        .beginClass<glm::vec2>("vec2")
            .addConstructor<void(*)(float, float)>()
            .addData("x", &glm::vec2::x)
            .addData("y", &glm::vec2::y)
        .endClass()
        .beginClass<glm::vec3>("vec3")
            .addConstructor<void(*)(float, float, float)>()
            .addData("x", &glm::vec3::x)
            .addData("y", &glm::vec3::y)
            .addData("z", &glm::vec3::z)
        .endClass()
        .beginClass<glm::vec4>("vec4")
            .addConstructor<void(*)(float, float, float, float)>()
            .addData("x", &glm::vec4::x)
            .addData("y", &glm::vec4::y)
            .addData("z", &glm::vec4::z)
            .addData("w", &glm::vec4::w)
        .endClass()
        .beginNamespace("Game")
            .beginClass<Camera>("Camera")
                .addFunction("MoveCamera", &Camera::moveCamera)
                .addFunction("SetCamera", &Camera::setPosition)
            .endClass()
            .beginClass<Entity>("Entity")
                .addConstructor<void(*)(void)>()
                .addProperty("visible", &Entity::isVisible, &Entity::setVisible)
                .addProperty("name", &Entity::getName, &Entity::setName)
            .endClass()
            .beginClass<Scene>("Scene")
                .addFunction("BindFunctionToKey", &Scene::bindFunctionToKey)
                .addFunction("GetCamera", &Scene::getCamera)
                .addFunction("AddEntity", &Scene::addEntity)
                .addFunction("GetEntity", &Scene::getEntity)
                .addFunction("Spawn", &Scene::spawn)
            .endClass()
        .endNamespace();

    push(m_luaState, this);
    lua_setglobal(m_luaState, "Level");
}

// NOTE Are there other necessary function the engine might want to call?
void Scene::registerLuaFunctions() {
    m_startFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "Start"));
    if(!m_startFunc->isFunction()) {
        throw GenericException("Start function wasn't found");
    }

    m_renderFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "GameLoop"));
    if(!m_renderFunc->isFunction()) {
        throw GenericException("Render function wasn't found");
    }
}

// Is this the best way to do it?
void Scene::start() {
    (*m_startFunc)();
}

// NOTE Do I want to call the render func or perform a render first?
void Scene::gameLoop() {
    m_renderChain->render(m_display);
    (*m_renderFunc)();
}

// TODO Find some way to expose what keys are pressed to lua
void Scene::bindFunctionToKey(int ikey, LuaRef function, bool repeat) {
    if(!function.isFunction()) {
        throw GenericException("function wasn't found");
    }

    InputKey key = (InputKey)ikey;
    m_luaKeyBinds[key] = std::make_unique<LuaRef>(function);
    if(repeat) {
        m_display->getInputController()->registerWhileKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    } else {
        m_display->getInputController()->registerOnKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    }
}

// NOTE Do i want to be able to easily destroy an entity?
Entity* Scene::spawn(const std::string& name, const std::string& resource, glm::vec3 location) {
    auto res = m_resourceHandler->getResource<Model3D>(resource);
    if(res == nullptr) {
        throw BadResource("resource isn't a model or doesn't exist", resource);
    }

    if(m_entities.find(name) != m_entities.end()) {
        Log::getErrorLog() << "Attempting to spawn entity with name that has already been registered\n";
        return m_entities[name].get();
    }

    auto dyn = new DynamicModel(res);
    dyn->translate(location);
    dyn->bindShader(m_resourceHandler->getShader("shader_staticmodel"));
    m_renderChain->attach(dyn);
    m_renderObjects.push_back(std::unique_ptr<IRenderObject>(dyn));

    auto ent = new Entity();
    ent->bindModel(dyn);
    m_entities[name] = std::unique_ptr<Entity>(ent);

    return ent;
}

// NOTE What is the purpose of this?
void Scene::addEntity(const std::string& name, Entity* const ent) {
    if(m_entities.find(name) != m_entities.end()) {
        Log::error(name + " entity attempted to be added a second time, skipped");
    }

    if(ent != nullptr) {
        m_entities[name] = std::unique_ptr<Entity>(ent);
    } else {
        Log::error(name + " entity was null, skipped");
    }
}

// TODO Expand on the capabilites of an entity, ie. how does the user interact with them?
Entity* Scene::getEntity(const std::string& name) const {
    if(m_entities.find(name) != m_entities.end()) {
        return m_entities.find(name)->second.get();
    }
    return nullptr;
}

Camera* Scene::getCamera() const {
    return m_display->getCamera();
}
<|endoftext|>


<commit_before><commit_msg>Prediction: involve adc is_protected in interaction predictor<commit_after><|endoftext|>


<commit_before>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include <sys/ioctl.h>
#include <sys/wait.h>
#include <termios.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/optional.hpp>
#include <boost/scope_exit.hpp>

#include <iomanip>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <vector>

#include "BuildHistory.hpp"
#include "FilePrinter.hpp"
#include "Repository.hpp"
#include "SubCommand.hpp"
#include "TablePrinter.hpp"
#include "decoration.hpp"

static void printBuildHeader(const Build &build);
static void printFile(const Repository *repo, const Build &build,
                      const File &file, FilePrinter &printer);
static void printFileHeader(const File &file);
static void printLineSeparator();

class CovInfo
{
public:
    CovInfo() = default;
    template <typename T>
    explicit CovInfo(const T &coverable)
        : coveredCount(coverable.getCoveredCount()),
          uncoveredCount(coverable.getUncoveredCount())
    {
    }

public:
    void addCovered(int num)
    {
        coveredCount += num;
    }

    void addUncovered(int num)
    {
        uncoveredCount += num;
    }

    int getCoveredCount() const
    {
        return coveredCount;
    }

    int getUncoveredCount() const
    {
        return uncoveredCount;
    }

    std::string formatCoverageRate() const
    {
        if (getRelevantLines() == 0) {
            return "100";
        }

        auto rate = 100*coveredCount/static_cast<float>(getRelevantLines());

        std::ostringstream oss;
        oss << std::fixed << std::right
            << std::setprecision(2) << rate;
        return oss.str();
    }

    std::string formatLines(const std::string &separator) const
    {
        return std::to_string(coveredCount) + separator
             + std::to_string(getRelevantLines());
    }

private:
    int getRelevantLines() const
    {
        return coveredCount + uncoveredCount;
    }

private:
    int coveredCount = 0;
    int uncoveredCount = 0;
};

class RedirectToPager
{
    template <typename T>
    using stream_buffer = boost::iostreams::stream_buffer<T>;
    using file_descriptor_sink = boost::iostreams::file_descriptor_sink;

public:
    RedirectToPager()
    {
        int pipePair[2];
        if (pipe(pipePair) != 0) {
            throw std::runtime_error("Failed to create a pipe");
        }
        BOOST_SCOPE_EXIT_ALL(pipePair) { close(pipePair[0]); };

        pid = fork();
        if (pid == -1) {
            close(pipePair[1]);
            throw std::runtime_error("Fork has failed");
        }
        if (pid == 0) {
            close(pipePair[1]);
            if (dup2(pipePair[0], STDIN_FILENO) == -1) {
                _Exit(EXIT_FAILURE);
            }
            close(pipePair[0]);
            // XXX: hard-coded invocation of less.
            execlp("less", "less", "-R", static_cast<char *>(nullptr));
            _Exit(127);
        }

        out.open(file_descriptor_sink(pipePair[1],
                                      boost::iostreams::close_handle));
        rdbuf = std::cout.rdbuf(&out);

        // XXX: here we could add a custom stream buffer, which would collect up
        //      to <terminal height> lines and if buffer is closed with this
        //      limit not reached, put lines on the screen as is; if we hit the
        //      limit in the process, open a pipe and redirect everything we got
        //      and all new output there.
    }

    ~RedirectToPager()
    {
        std::cout.rdbuf(rdbuf);
        out.close();
        int wstatus;
        waitpid(pid, &wstatus, 0);
    }

private:
    stream_buffer<file_descriptor_sink> out;
    std::streambuf *rdbuf;
    pid_t pid;
};

/**
 * @brief Retrieves terminal width.
 *
 * @returns Actual terminal width, or maximum possible value for the type.
 */
static unsigned int
getTerminalWidth()
{
    winsize ws;
    if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != 0) {
        return std::numeric_limits<unsigned int>::max();
    }

    return ws.ws_col;
}

namespace
{

namespace CmdUtils
{
    Build
    getBuild(BuildHistory *bh, int buildId)
    {
        boost::optional<Build> build = bh->getBuild(buildId);
        if (!build) {
            throw std::runtime_error {
                "Can't find build #" + std::to_string(buildId)
            };
        }
        return *build;
    }

    File &
    getFile(const Build &build, const std::string &path)
    {
        boost::optional<File &> file = build.getFile(path);
        if (!file) {
            throw std::runtime_error("Can't find file: " + path +
                                     " in build #" +
                                     std::to_string(build.getId()) + " of " +
                                     build.getRefName() + " at " +
                                     build.getRef());
        }
        return *file;
    }
}

}

class BuildsCmd : public AutoSubCommand<BuildsCmd>
{
public:
    BuildsCmd() : parent("builds")
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &/*args*/) override
    {
        // TODO: calculate and display change of coverage (both in percents and
        //       in covered/relevant lines).
        // TODO: by default limit number of builds to display to N (e.g., 10).

        // TODO: colorize percents?
        TablePrinter tablePrinter {
            { "Build", "Coverage", "Lines", "Branch", "Commit" },
            getTerminalWidth()
        };

        std::string sharp("#"), percent(" %"), sep(" / ");
        for (const Build &build : bh->getBuilds()) {
            CovInfo covInfo(build);

            tablePrinter.append({
                sharp + std::to_string(build.getId()),
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep),
                build.getRefName(),
                build.getRef()
            });
        }

        tablePrinter.print(std::cout);
    }
};

class DiffCmd : public AutoSubCommand<DiffCmd>
{
public:
    DiffCmd() : parent("diff", 3U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        // TODO: allow diffing whole builds.

        const int oldBuildId = std::stoi(args[0]);
        const int newBuildId = std::stoi(args[1]);

        Build oldBuild = CmdUtils::getBuild(bh, oldBuildId);
        Build newBuild = CmdUtils::getBuild(bh, newBuildId);

        File &oldFile = CmdUtils::getFile(oldBuild, args[2]);
        File &newFile = CmdUtils::getFile(newBuild, args[2]);

        Text oldVersion = repo->readFile(oldBuild.getRef(),
                                         oldFile.getPath());
        Text newVersion = repo->readFile(newBuild.getRef(),
                                         newFile.getPath());
        const std::vector<int> &oldCov = oldFile.getCoverage();
        const std::vector<int> &newCov = newFile.getCoverage();

        if (oldVersion.size() != oldCov.size() ||
            newVersion.size() != newCov.size()) {
            std::cerr << "Coverage information is not accurate\n";
            return error();
        }

        RedirectToPager redirectToPager;

        printLineSeparator();
        printBuildHeader(oldBuild);
        printFileHeader(oldFile);
        printLineSeparator();
        printBuildHeader(newBuild);
        printFileHeader(newFile);
        printLineSeparator();

        FilePrinter filePrinter;
        filePrinter.printDiff(args[2], oldVersion, oldCov, newVersion, newCov);

        // TODO: print some totals/stats here.
    }
};

class DirsCmd : public AutoSubCommand<DirsCmd>
{
public:
    DirsCmd() : parent("dirs", 1U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        namespace fs = boost::filesystem;

        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);

        std::map<std::string, CovInfo> dirs;
        for (const std::string &filePath : build.getPaths()) {
            fs::path dirPath = filePath;
            dirPath.remove_filename();

            File &file = *build.getFile(filePath);
            CovInfo &info = dirs[dirPath.string()];

            info.addCovered(file.getCoveredCount());
            info.addUncovered(file.getUncoveredCount());
        }

        // TODO: colorize percents?
        TablePrinter tablePrinter({ "-Directory", "Coverage", "#" },
                                  getTerminalWidth());

        std::string slash("/"), percent(" %"), sep(" / ");
        for (const auto &entry : dirs) {
            const CovInfo &covInfo = entry.second;
            tablePrinter.append({
                entry.first + slash,
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep)
            });
        }

        tablePrinter.print(std::cout);
    }
};

class FilesCmd : public AutoSubCommand<FilesCmd>
{
public:
    FilesCmd() : parent("files", 1U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);

        // TODO: colorize percents?
        TablePrinter tablePrinter({ "-File", "Coverage", "#" },
                                  getTerminalWidth());

        std::string percent(" %"), sep(" / ");
        for (const std::string &filePath : build.getPaths()) {
            CovInfo covInfo(*build.getFile(filePath));
            tablePrinter.append({
                filePath,
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep)
            });
        }

        tablePrinter.print(std::cout);
    }
};

class GetCmd : public AutoSubCommand<GetCmd>
{
public:
    GetCmd() : parent("get", 2U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);
        File &file = CmdUtils::getFile(build, args[1]);

        std::cout << build.getRef() << '\n';
        for (int hits : file.getCoverage()) {
            std::cout << hits << '\n';
        }
    }
};

class NewCmd : public AutoSubCommand<NewCmd>
{
public:
    NewCmd() : parent("new")
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &/*args*/) override
    {
        std::string ref, refName;
        std::cin >> ref >> refName;

        const std::unordered_map<std::string, std::string> files =
            repo->listFiles(ref);

        BuildData bd(std::move(ref), refName);

        for (std::string path, sha1Hash; std::cin >> path >> sha1Hash; ) {
            int nLines;
            std::cin >> nLines;

            std::vector<int> coverage;
            coverage.reserve(nLines);

            while (nLines-- > 0) {
                int i;
                std::cin >> i;
                coverage.push_back(i);
            }

            const auto file = files.find(path);
            if (file == files.cend()) {
                std::cerr << "Skipping file missing in " << refName << ": "
                          << path << '\n';
            } else if (!boost::iequals(file->second, sha1Hash)) {
                std::cerr << path << " file at " << refName
                          << " doesn't match reported SHA-1\n";
                error();
            } else {
                bd.addFile(File(std::move(path), std::move(coverage)));
            }
        }

        if (!isFailed()) {
            Build build = bh->addBuild(bd);
            printBuildHeader(build);
            // TODO: display change of coverage since previous build.
        }
    }
};

class ShowCmd : public AutoSubCommand<ShowCmd>
{
public:
    ShowCmd() : parent("show", 1U, 2U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        // TODO: maybe allow passing in path to directory, which would cause
        //       printing all files in that sub-tree (or only directly in it?).

        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);
        FilePrinter printer;

        if (args.size() == 1U) {
            RedirectToPager redirectToPager;
            printBuildHeader(build);
            for (const std::string &path : build.getPaths()) {
                printFile(repo, build, *build.getFile(path), printer);
            }
        } else if (boost::optional<File &> file = build.getFile(args[1])) {
            RedirectToPager redirectToPager;
            printBuildHeader(build);
            printFile(repo, build, *file, printer);
        } else {
            std::cerr << "Can't find file: " << args[1] << '\n';
            error();
        }
    }
};

static void
printBuildHeader(const Build &build)
{
    CovInfo covInfo(build);
    // TODO: colorize percents?
    std::cout << (decor::bold << "Build:") << " #" << build.getId() << ", "
              << covInfo.formatCoverageRate() << "% "
              << '(' << covInfo.formatLines("/") << "), "
              << build.getRefName() << " (" << build.getRef() << ")\n";
}

static void
printFile(const Repository *repo, const Build &build, const File &file,
          FilePrinter &printer)
{
    printLineSeparator();
    printFileHeader(file);
    printLineSeparator();

    const std::string &path = file.getPath();
    const std::string &ref = build.getRef();
    printer.print(path, repo->readFile(ref, path), file.getCoverage());
}

static void
printFileHeader(const File &file)
{
    CovInfo covInfo(file);
    // TODO: colorize percents?
    std::cout << (decor::bold << "File: ") << file.getPath() << ", "
              << covInfo.formatCoverageRate() << "% "
              << '(' << covInfo.formatLines("/") << ")\n";
}

static void
printLineSeparator()
{
    std::cout << std::setfill('-') << std::setw(80) << '\n'
              << std::setfill(' ');
}
<commit_msg>Use "ref at commit" instead of "ref (commit)"<commit_after>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include <sys/ioctl.h>
#include <sys/wait.h>
#include <termios.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/optional.hpp>
#include <boost/scope_exit.hpp>

#include <iomanip>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <vector>

#include "BuildHistory.hpp"
#include "FilePrinter.hpp"
#include "Repository.hpp"
#include "SubCommand.hpp"
#include "TablePrinter.hpp"
#include "decoration.hpp"

static void printBuildHeader(const Build &build);
static void printFile(const Repository *repo, const Build &build,
                      const File &file, FilePrinter &printer);
static void printFileHeader(const File &file);
static void printLineSeparator();

class CovInfo
{
public:
    CovInfo() = default;
    template <typename T>
    explicit CovInfo(const T &coverable)
        : coveredCount(coverable.getCoveredCount()),
          uncoveredCount(coverable.getUncoveredCount())
    {
    }

public:
    void addCovered(int num)
    {
        coveredCount += num;
    }

    void addUncovered(int num)
    {
        uncoveredCount += num;
    }

    int getCoveredCount() const
    {
        return coveredCount;
    }

    int getUncoveredCount() const
    {
        return uncoveredCount;
    }

    std::string formatCoverageRate() const
    {
        if (getRelevantLines() == 0) {
            return "100";
        }

        auto rate = 100*coveredCount/static_cast<float>(getRelevantLines());

        std::ostringstream oss;
        oss << std::fixed << std::right
            << std::setprecision(2) << rate;
        return oss.str();
    }

    std::string formatLines(const std::string &separator) const
    {
        return std::to_string(coveredCount) + separator
             + std::to_string(getRelevantLines());
    }

private:
    int getRelevantLines() const
    {
        return coveredCount + uncoveredCount;
    }

private:
    int coveredCount = 0;
    int uncoveredCount = 0;
};

class RedirectToPager
{
    template <typename T>
    using stream_buffer = boost::iostreams::stream_buffer<T>;
    using file_descriptor_sink = boost::iostreams::file_descriptor_sink;

public:
    RedirectToPager()
    {
        int pipePair[2];
        if (pipe(pipePair) != 0) {
            throw std::runtime_error("Failed to create a pipe");
        }
        BOOST_SCOPE_EXIT_ALL(pipePair) { close(pipePair[0]); };

        pid = fork();
        if (pid == -1) {
            close(pipePair[1]);
            throw std::runtime_error("Fork has failed");
        }
        if (pid == 0) {
            close(pipePair[1]);
            if (dup2(pipePair[0], STDIN_FILENO) == -1) {
                _Exit(EXIT_FAILURE);
            }
            close(pipePair[0]);
            // XXX: hard-coded invocation of less.
            execlp("less", "less", "-R", static_cast<char *>(nullptr));
            _Exit(127);
        }

        out.open(file_descriptor_sink(pipePair[1],
                                      boost::iostreams::close_handle));
        rdbuf = std::cout.rdbuf(&out);

        // XXX: here we could add a custom stream buffer, which would collect up
        //      to <terminal height> lines and if buffer is closed with this
        //      limit not reached, put lines on the screen as is; if we hit the
        //      limit in the process, open a pipe and redirect everything we got
        //      and all new output there.
    }

    ~RedirectToPager()
    {
        std::cout.rdbuf(rdbuf);
        out.close();
        int wstatus;
        waitpid(pid, &wstatus, 0);
    }

private:
    stream_buffer<file_descriptor_sink> out;
    std::streambuf *rdbuf;
    pid_t pid;
};

/**
 * @brief Retrieves terminal width.
 *
 * @returns Actual terminal width, or maximum possible value for the type.
 */
static unsigned int
getTerminalWidth()
{
    winsize ws;
    if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != 0) {
        return std::numeric_limits<unsigned int>::max();
    }

    return ws.ws_col;
}

namespace
{

namespace CmdUtils
{
    Build
    getBuild(BuildHistory *bh, int buildId)
    {
        boost::optional<Build> build = bh->getBuild(buildId);
        if (!build) {
            throw std::runtime_error {
                "Can't find build #" + std::to_string(buildId)
            };
        }
        return *build;
    }

    File &
    getFile(const Build &build, const std::string &path)
    {
        boost::optional<File &> file = build.getFile(path);
        if (!file) {
            throw std::runtime_error("Can't find file: " + path +
                                     " in build #" +
                                     std::to_string(build.getId()) + " of " +
                                     build.getRefName() + " at " +
                                     build.getRef());
        }
        return *file;
    }
}

}

class BuildsCmd : public AutoSubCommand<BuildsCmd>
{
public:
    BuildsCmd() : parent("builds")
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &/*args*/) override
    {
        // TODO: calculate and display change of coverage (both in percents and
        //       in covered/relevant lines).
        // TODO: by default limit number of builds to display to N (e.g., 10).

        // TODO: colorize percents?
        TablePrinter tablePrinter {
            { "Build", "Coverage", "Lines", "Branch", "Commit" },
            getTerminalWidth()
        };

        std::string sharp("#"), percent(" %"), sep(" / ");
        for (const Build &build : bh->getBuilds()) {
            CovInfo covInfo(build);

            tablePrinter.append({
                sharp + std::to_string(build.getId()),
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep),
                build.getRefName(),
                build.getRef()
            });
        }

        tablePrinter.print(std::cout);
    }
};

class DiffCmd : public AutoSubCommand<DiffCmd>
{
public:
    DiffCmd() : parent("diff", 3U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        // TODO: allow diffing whole builds.

        const int oldBuildId = std::stoi(args[0]);
        const int newBuildId = std::stoi(args[1]);

        Build oldBuild = CmdUtils::getBuild(bh, oldBuildId);
        Build newBuild = CmdUtils::getBuild(bh, newBuildId);

        File &oldFile = CmdUtils::getFile(oldBuild, args[2]);
        File &newFile = CmdUtils::getFile(newBuild, args[2]);

        Text oldVersion = repo->readFile(oldBuild.getRef(),
                                         oldFile.getPath());
        Text newVersion = repo->readFile(newBuild.getRef(),
                                         newFile.getPath());
        const std::vector<int> &oldCov = oldFile.getCoverage();
        const std::vector<int> &newCov = newFile.getCoverage();

        if (oldVersion.size() != oldCov.size() ||
            newVersion.size() != newCov.size()) {
            std::cerr << "Coverage information is not accurate\n";
            return error();
        }

        RedirectToPager redirectToPager;

        printLineSeparator();
        printBuildHeader(oldBuild);
        printFileHeader(oldFile);
        printLineSeparator();
        printBuildHeader(newBuild);
        printFileHeader(newFile);
        printLineSeparator();

        FilePrinter filePrinter;
        filePrinter.printDiff(args[2], oldVersion, oldCov, newVersion, newCov);

        // TODO: print some totals/stats here.
    }
};

class DirsCmd : public AutoSubCommand<DirsCmd>
{
public:
    DirsCmd() : parent("dirs", 1U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        namespace fs = boost::filesystem;

        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);

        std::map<std::string, CovInfo> dirs;
        for (const std::string &filePath : build.getPaths()) {
            fs::path dirPath = filePath;
            dirPath.remove_filename();

            File &file = *build.getFile(filePath);
            CovInfo &info = dirs[dirPath.string()];

            info.addCovered(file.getCoveredCount());
            info.addUncovered(file.getUncoveredCount());
        }

        // TODO: colorize percents?
        TablePrinter tablePrinter({ "-Directory", "Coverage", "#" },
                                  getTerminalWidth());

        std::string slash("/"), percent(" %"), sep(" / ");
        for (const auto &entry : dirs) {
            const CovInfo &covInfo = entry.second;
            tablePrinter.append({
                entry.first + slash,
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep)
            });
        }

        tablePrinter.print(std::cout);
    }
};

class FilesCmd : public AutoSubCommand<FilesCmd>
{
public:
    FilesCmd() : parent("files", 1U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);

        // TODO: colorize percents?
        TablePrinter tablePrinter({ "-File", "Coverage", "#" },
                                  getTerminalWidth());

        std::string percent(" %"), sep(" / ");
        for (const std::string &filePath : build.getPaths()) {
            CovInfo covInfo(*build.getFile(filePath));
            tablePrinter.append({
                filePath,
                covInfo.formatCoverageRate() + percent,
                covInfo.formatLines(sep)
            });
        }

        tablePrinter.print(std::cout);
    }
};

class GetCmd : public AutoSubCommand<GetCmd>
{
public:
    GetCmd() : parent("get", 2U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);
        File &file = CmdUtils::getFile(build, args[1]);

        std::cout << build.getRef() << '\n';
        for (int hits : file.getCoverage()) {
            std::cout << hits << '\n';
        }
    }
};

class NewCmd : public AutoSubCommand<NewCmd>
{
public:
    NewCmd() : parent("new")
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &/*args*/) override
    {
        std::string ref, refName;
        std::cin >> ref >> refName;

        const std::unordered_map<std::string, std::string> files =
            repo->listFiles(ref);

        BuildData bd(std::move(ref), refName);

        for (std::string path, sha1Hash; std::cin >> path >> sha1Hash; ) {
            int nLines;
            std::cin >> nLines;

            std::vector<int> coverage;
            coverage.reserve(nLines);

            while (nLines-- > 0) {
                int i;
                std::cin >> i;
                coverage.push_back(i);
            }

            const auto file = files.find(path);
            if (file == files.cend()) {
                std::cerr << "Skipping file missing in " << refName << ": "
                          << path << '\n';
            } else if (!boost::iequals(file->second, sha1Hash)) {
                std::cerr << path << " file at " << refName
                          << " doesn't match reported SHA-1\n";
                error();
            } else {
                bd.addFile(File(std::move(path), std::move(coverage)));
            }
        }

        if (!isFailed()) {
            Build build = bh->addBuild(bd);
            printBuildHeader(build);
            // TODO: display change of coverage since previous build.
        }
    }
};

class ShowCmd : public AutoSubCommand<ShowCmd>
{
public:
    ShowCmd() : parent("show", 1U, 2U)
    {
    }

private:
    virtual void
    execImpl(const std::vector<std::string> &args) override
    {
        // TODO: maybe allow passing in path to directory, which would cause
        //       printing all files in that sub-tree (or only directly in it?).

        const int buildId = std::stoi(args[0]);
        Build build = CmdUtils::getBuild(bh, buildId);
        FilePrinter printer;

        if (args.size() == 1U) {
            RedirectToPager redirectToPager;
            printBuildHeader(build);
            for (const std::string &path : build.getPaths()) {
                printFile(repo, build, *build.getFile(path), printer);
            }
        } else if (boost::optional<File &> file = build.getFile(args[1])) {
            RedirectToPager redirectToPager;
            printBuildHeader(build);
            printFile(repo, build, *file, printer);
        } else {
            std::cerr << "Can't find file: " << args[1] << '\n';
            error();
        }
    }
};

static void
printBuildHeader(const Build &build)
{
    CovInfo covInfo(build);
    // TODO: colorize percents?
    std::cout << (decor::bold << "Build:") << " #" << build.getId() << ", "
              << covInfo.formatCoverageRate() << "% "
              << '(' << covInfo.formatLines("/") << "), "
              << build.getRefName() << " at " << build.getRef() << '\n';
}

static void
printFile(const Repository *repo, const Build &build, const File &file,
          FilePrinter &printer)
{
    printLineSeparator();
    printFileHeader(file);
    printLineSeparator();

    const std::string &path = file.getPath();
    const std::string &ref = build.getRef();
    printer.print(path, repo->readFile(ref, path), file.getCoverage());
}

static void
printFileHeader(const File &file)
{
    CovInfo covInfo(file);
    // TODO: colorize percents?
    std::cout << (decor::bold << "File: ") << file.getPath() << ", "
              << covInfo.formatCoverageRate() << "% "
              << '(' << covInfo.formatLines("/") << ")\n";
}

static void
printLineSeparator()
{
    std::cout << std::setfill('-') << std::setw(80) << '\n'
              << std::setfill(' ');
}
<|endoftext|>


<commit_before>/*
 Service Discovery Protocol - data collector
 @author: Sebastien Soudan <sebastien.soudan@gmail.com>
*/

#include "message.h"
#include "SDP.h"

#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <boost/assign/list_of.hpp>
#include "stream.h"
using namespace std;

#include "Serial.h"

#define LOCAL_ADDR64_HIGH 0x0013a200
#define LOCAL_ADDR64_LOW  0x408b60d9

class Record {
public:
	uint32_t date;
	float cellar_Temperature;
	float cellar_Humidity;
	float terrace_Temperature;
	bool cellar_FanState;
	float room_1_Temperature;
	float room_1_Pressure;
	float kitchen_Temperature;
	float kitchen_Light;
	float stairs_Light;
	bool stairs_LedState;
	bool stairs_Movement;

private:
	friend std::ostream& operator<<(std::ostream&, const Record&);

};

	const string currentDateTime(time_t date) {
	    time_t     now = date;
	    struct tm  tstruct;
	    char       buf[80];
	    tstruct = *localtime(&now);
	    strftime(buf, sizeof(buf), "%Y%m%d%H%M", &tstruct);

	    return buf;
	};

std::ostream& operator<<(std::ostream &strm, const Record &a) {
  return strm 	<< currentDateTime(a.date) << "\t"
				<< a.cellar_Temperature << "\t"
				<< a.cellar_Humidity << "\t"
				<< a.terrace_Temperature << "\t"
				<< a.cellar_FanState << "\t"
				<< a.room_1_Temperature << "\t"
				<< a.room_1_Pressure << "\t"
				<< a.kitchen_Temperature << "\t"
				<< a.kitchen_Light << "\t"
				<< a.stairs_Light << "\t"
				<< a.stairs_LedState << "\t"
				<< a.stairs_Movement
				<< endl;
}

Record record;

class ClientSDP : public SDP {
private:

	static std::map<std::string, ServiceDiscovery::ServiceLocation> serviceLocationString2EnumMap;
	static std::map<ServiceDiscovery::ServiceLocation, std::string> serviceLocationEnum2StringMap;

	static std::map<std::string, ServiceDiscovery::ServiceType> serviceTypeString2EnumMap;
	static std::map<ServiceDiscovery::ServiceType, std::string> serviceTypeEnum2StringMap;

	static std::map<std::string, ServiceDiscovery::ActionType> actionTypeString2EnumMap;
	static std::map<ServiceDiscovery::ActionType, std::string> actionTypeEnum2StringMap;

	boost::asio::io_service io;
	boost::asio::serial_port port;
	Serial serial;
public:

	ClientSDP(string device, XBeeAddress64 local64) : io(), port(io, device), serial(&port, 1500) {

		port.set_option(boost::asio::serial_port_base::baud_rate(9600));
		// Set hardware flow control (RTS/CTS)
		// port.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::hardware));

		setXBee(new XBee(serial));
		setLocal64(local64);

	};

	/**
		Test DoAction Encoding/Decoding
	*/
	void doAction(string service, string location, string action,  void (*method)(uint8_t *buffer, uint8_t size)) {

#if defined(DEBUG)
		cerr << "[..] doAction(" << service << ", " << location << ", " << action << ")" << std::endl;
#endif

		ActionStatus as = UNDEF_STATUS;
		SDPState state = UNKNOWN_STATE;

		int counter = 20;
		while (counter-- > 0) {
			as = SDP::doAction(serviceTypeString2EnumMap[service], serviceLocationString2EnumMap[location], actionTypeString2EnumMap[action], 0, NULL, method);

#if defined(DEBUG)
			if (as == REQUESTED)
				cerr << "Action " << action << " requested" << endl;
#endif
			state = readPackets();

			if (state == DAR_RECEIVED) {
#if defined(DEBUG)
				cerr << "state:  DAR_RECEIVED" << endl;
#endif
				return;
			}
#if defined(DEBUG)
			else
				cerr << "state: " << (unsigned int) state << endl;
#endif
		}

	}

};

std::map<std::string, ServiceDiscovery::ServiceLocation> ClientSDP::serviceLocationString2EnumMap = boost::assign::map_list_of("UNDEF_LOCATION", UNDEF_LOCATION)("TERRACE", TERRACE)("CELLAR", CELLAR)("ROOM_1", ROOM_1)("KITCHEN", KITCHEN)("STAIRS", STAIRS);
std::map<ServiceDiscovery::ServiceLocation, std::string> ClientSDP::serviceLocationEnum2StringMap = boost::assign::map_list_of(UNDEF_LOCATION, "UNDEF_LOCATION")(TERRACE, "TERRACE")(CELLAR, "CELLAR")(ROOM_1, "ROOM_1")(KITCHEN, "KITCHEN")(STAIRS, "STAIRS");

std::map<std::string, ServiceDiscovery::ServiceType> ClientSDP::serviceTypeString2EnumMap = boost::assign::map_list_of("UNDEF_SERVICE", UNDEF_SERVICE)("SDP_RTC", SDP_RTC)("TEMPERATURE",TEMPERATURE)("PRESSURE", PRESSURE)("FAN", FAN)("HUMIDITY", HUMIDITY)("LIGHT", LIGHT)("MOVEMENT", MOVEMENT)("LED", LED);
std::map<ServiceDiscovery::ServiceType, std::string> ClientSDP::serviceTypeEnum2StringMap = boost::assign::map_list_of(UNDEF_SERVICE, "UNDEF_SERVICE")(SDP_RTC, "SDP_RTC")(TEMPERATURE,"TEMPERATURE")(PRESSURE, "PRESSURE")(FAN, "FAN")(HUMIDITY, "HUMIDITY")(LIGHT, "LIGHT")(MOVEMENT, "MOVEMENT")(LED, "LED");

std::map<std::string, ServiceDiscovery::ActionType> ClientSDP::actionTypeString2EnumMap = boost::assign::map_list_of("UNDEF_ACTION", UNDEF_ACTION) ("GET_VALUE", GET_VALUE) ("SET_VALUE", SET_VALUE)  ("GET_STATE", GET_STATE) ("START", START) ("STOP", STOP) ("AUTO", AUTO);
std::map<ServiceDiscovery::ActionType, std::string> ClientSDP::actionTypeEnum2StringMap = boost::assign::map_list_of(UNDEF_ACTION, "UNDEF_ACTION") (GET_VALUE, "GET_VALUE") (SET_VALUE, "SET_VALUE")  (GET_STATE, "GET_STATE") (START, "START") (STOP, "STOP") (AUTO, "AUTO");

void humidity_callback(uint8_t *buffer, uint8_t size) {
	float humidity;

	memcpy(&humidity, buffer, 4);

	record.cellar_Humidity = humidity;

#if defined(DEBUG)
	cerr << "humidity (%): " << humidity << endl;
#endif
}

void cellar_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.cellar_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void kitchen_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.kitchen_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void kitchen_light_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.kitchen_Light = temp;

#if defined(DEBUG)
	cerr << "light (%): " << temp << endl;
#endif
}

void stairs_light_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.stairs_Light = temp;

#if defined(DEBUG)
	cerr << "light (%): " << temp << endl;
#endif
}

void terrace_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.terrace_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void room1_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.room_1_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void room1_pressure_callback(uint8_t *buffer, uint8_t size) {
	float pressure;

	memcpy(&pressure, buffer, 4);

	record.room_1_Pressure = pressure;

#if defined(DEBUG)
	cerr << "pressure (kPa): " << pressure << endl;
#endif
}

void fan_state_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.cellar_FanState = state;

#if defined(DEBUG)
	cerr << "Fan state: " << state << endl;
#endif
}

void stairs_movement_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.stairs_Movement = state;

#if defined(DEBUG)
	cerr << "Movement: " << state << endl;
#endif
}

void stairs_led_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.stairs_LedState = state;

#if defined(DEBUG)
	cerr << "LED state: " << state << endl;
#endif
}

void rtc_callback(uint8_t *buffer, uint8_t size) {
  uint32_t date = convertArraytoUint32(buffer);

  record.date = date;

#if defined(DEBUG)
  cerr << "epoc: " << (unsigned int) date << endl;
#endif
}

int main(int argc, char ** argv) {

	string device = "/dev/tty.usbserial-AD025F4I";

	if (argc > 1)
		device = argv[1];

	// TODO get the local address from command line too

 	try {
		ClientSDP sdp(device,  XBeeAddress64(LOCAL_ADDR64_HIGH, LOCAL_ADDR64_LOW));

		uint32_t date;
		float cellar_Temperature;
		float cellar_Humidity;
		float terrace_Temperature;
		bool cellar_FanState;
		float room_1_Temperature;
		float room_1_Pressure;

		cout<< "date\tCellar(Temp/C)\tCellar(Humidity/%)\tTerrace(Temp/C)\tCellar(State)\tRoom1(Temp/C)\tRoom1(Pressure/kPa)\tKitchen(Temp/C)\tKitchen(Light/%)\tStairs(Light/%)\tStairs(LED)\tStairs(Movement)"  << endl;

		while (true) {

			sdp.doAction("TEMPERATURE", "CELLAR", "GET_VALUE", &cellar_temperature_callback);

			sdp.doAction("HUMIDITY", "CELLAR", "GET_VALUE", &humidity_callback);

			sdp.doAction("FAN", "CELLAR", "GET_STATE", &fan_state_callback);

			sdp.doAction("TEMPERATURE", "TERRACE", "GET_VALUE", &terrace_temperature_callback);

			sdp.doAction("TEMPERATURE", "ROOM_1", "GET_VALUE", &room1_temperature_callback);

			sdp.doAction("PRESSURE", "ROOM_1", "GET_VALUE", &room1_pressure_callback);

			sdp.doAction("SDP_RTC", "UNDEF_LOCATION", "GET_VALUE", &rtc_callback);

			sdp.doAction("TEMPERATURE", "KITCHEN", "GET_VALUE", &kitchen_temperature_callback);

			sdp.doAction("LIGHT", "KITCHEN", "GET_VALUE", &kitchen_light_callback);

			sdp.doAction("LIGHT", "STAIRS", "GET_VALUE", &stairs_light_callback);

			sdp.doAction("LED", "STAIRS", "GET_STATE", &stairs_led_callback);

			sdp.doAction("MOVEMENT", "STAIRS", "GET_VALUE", &stairs_movement_callback);

			cout << record;

			sleep(6);
		}
	} catch (exception& e) {
        cerr << "Exception: " << e.what() << endl;
        cerr << "Check " << device << " is the tty to your XBee." << endl;
        return -1;
    }

}

<commit_msg>[fix] missed reset of count...<commit_after>/*
 Service Discovery Protocol - data collector
 @author: Sebastien Soudan <sebastien.soudan@gmail.com>
*/

#include "message.h"
#include "SDP.h"

#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <fstream>
#include <boost/assign/list_of.hpp>
#include "stream.h"
using namespace std;

#include "Serial.h"

#define LOCAL_ADDR64_HIGH 0x0013a200
#define LOCAL_ADDR64_LOW  0x408b60d9

#define MAX_ROW 2000

class Record {
public:
	uint32_t date;
	float cellar_Temperature;
	float cellar_Humidity;
	float terrace_Temperature;
	bool cellar_FanState;
	float room_1_Temperature;
	float room_1_Pressure;
	float kitchen_Temperature;
	float kitchen_Light;
	float stairs_Light;
	bool stairs_LedState;
	bool stairs_Movement;

private:
	friend std::ostream& operator<<(std::ostream&, const Record&);

};

	const string currentDateTime(time_t date) {
	    time_t     now = date;
	    struct tm  tstruct;
	    char       buf[80];
	    tstruct = *localtime(&now);
	    strftime(buf, sizeof(buf), "%Y%m%d%H%M", &tstruct);

	    return buf;
	};

std::ostream& operator<<(std::ostream &strm, const Record &a) {
  return strm 	<< currentDateTime(a.date) << "\t"
				<< a.cellar_Temperature << "\t"
				<< a.cellar_Humidity << "\t"
				<< a.terrace_Temperature << "\t"
				<< a.cellar_FanState << "\t"
				<< a.room_1_Temperature << "\t"
				<< a.room_1_Pressure << "\t"
				<< a.kitchen_Temperature << "\t"
				<< a.kitchen_Light << "\t"
				<< a.stairs_Light << "\t"
				<< a.stairs_LedState << "\t"
				<< a.stairs_Movement
				<< endl;
}

Record record;

class ClientSDP : public SDP {
private:

	static std::map<std::string, ServiceDiscovery::ServiceLocation> serviceLocationString2EnumMap;
	static std::map<ServiceDiscovery::ServiceLocation, std::string> serviceLocationEnum2StringMap;

	static std::map<std::string, ServiceDiscovery::ServiceType> serviceTypeString2EnumMap;
	static std::map<ServiceDiscovery::ServiceType, std::string> serviceTypeEnum2StringMap;

	static std::map<std::string, ServiceDiscovery::ActionType> actionTypeString2EnumMap;
	static std::map<ServiceDiscovery::ActionType, std::string> actionTypeEnum2StringMap;

	boost::asio::io_service io;
	boost::asio::serial_port port;
	Serial serial;
public:

	ClientSDP(string device, XBeeAddress64 local64) : io(), port(io, device), serial(&port, 1500) {

		port.set_option(boost::asio::serial_port_base::baud_rate(9600));
		// Set hardware flow control (RTS/CTS)
		// port.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::hardware));

		setXBee(new XBee(serial));
		setLocal64(local64);

	};

	/**
		Test DoAction Encoding/Decoding
	*/
	void doAction(string service, string location, string action,  void (*method)(uint8_t *buffer, uint8_t size)) {

#if defined(DEBUG)
		cerr << "[..] doAction(" << service << ", " << location << ", " << action << ")" << std::endl;
#endif

		ActionStatus as = UNDEF_STATUS;
		SDPState state = UNKNOWN_STATE;

		int counter = 20;
		while (counter-- > 0) {
			as = SDP::doAction(serviceTypeString2EnumMap[service], serviceLocationString2EnumMap[location], actionTypeString2EnumMap[action], 0, NULL, method);

#if defined(DEBUG)
			if (as == REQUESTED)
				cerr << "Action " << action << " requested" << endl;
#endif
			state = readPackets();

			if (state == DAR_RECEIVED) {
#if defined(DEBUG)
				cerr << "state:  DAR_RECEIVED" << endl;
#endif
				return;
			}
#if defined(DEBUG)
			else
				cerr << "state: " << (unsigned int) state << endl;
#endif
		}

	}

};

std::map<std::string, ServiceDiscovery::ServiceLocation> ClientSDP::serviceLocationString2EnumMap = boost::assign::map_list_of("UNDEF_LOCATION", UNDEF_LOCATION)("TERRACE", TERRACE)("CELLAR", CELLAR)("ROOM_1", ROOM_1)("KITCHEN", KITCHEN)("STAIRS", STAIRS);
std::map<ServiceDiscovery::ServiceLocation, std::string> ClientSDP::serviceLocationEnum2StringMap = boost::assign::map_list_of(UNDEF_LOCATION, "UNDEF_LOCATION")(TERRACE, "TERRACE")(CELLAR, "CELLAR")(ROOM_1, "ROOM_1")(KITCHEN, "KITCHEN")(STAIRS, "STAIRS");

std::map<std::string, ServiceDiscovery::ServiceType> ClientSDP::serviceTypeString2EnumMap = boost::assign::map_list_of("UNDEF_SERVICE", UNDEF_SERVICE)("SDP_RTC", SDP_RTC)("TEMPERATURE",TEMPERATURE)("PRESSURE", PRESSURE)("FAN", FAN)("HUMIDITY", HUMIDITY)("LIGHT", LIGHT)("MOVEMENT", MOVEMENT)("LED", LED);
std::map<ServiceDiscovery::ServiceType, std::string> ClientSDP::serviceTypeEnum2StringMap = boost::assign::map_list_of(UNDEF_SERVICE, "UNDEF_SERVICE")(SDP_RTC, "SDP_RTC")(TEMPERATURE,"TEMPERATURE")(PRESSURE, "PRESSURE")(FAN, "FAN")(HUMIDITY, "HUMIDITY")(LIGHT, "LIGHT")(MOVEMENT, "MOVEMENT")(LED, "LED");

std::map<std::string, ServiceDiscovery::ActionType> ClientSDP::actionTypeString2EnumMap = boost::assign::map_list_of("UNDEF_ACTION", UNDEF_ACTION) ("GET_VALUE", GET_VALUE) ("SET_VALUE", SET_VALUE)  ("GET_STATE", GET_STATE) ("START", START) ("STOP", STOP) ("AUTO", AUTO);
std::map<ServiceDiscovery::ActionType, std::string> ClientSDP::actionTypeEnum2StringMap = boost::assign::map_list_of(UNDEF_ACTION, "UNDEF_ACTION") (GET_VALUE, "GET_VALUE") (SET_VALUE, "SET_VALUE")  (GET_STATE, "GET_STATE") (START, "START") (STOP, "STOP") (AUTO, "AUTO");

void humidity_callback(uint8_t *buffer, uint8_t size) {
	float humidity;

	memcpy(&humidity, buffer, 4);

	record.cellar_Humidity = humidity;

#if defined(DEBUG)
	cerr << "humidity (%): " << humidity << endl;
#endif
}

void cellar_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.cellar_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void kitchen_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.kitchen_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void kitchen_light_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.kitchen_Light = temp;

#if defined(DEBUG)
	cerr << "light (%): " << temp << endl;
#endif
}

void stairs_light_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.stairs_Light = temp;

#if defined(DEBUG)
	cerr << "light (%): " << temp << endl;
#endif
}

void terrace_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.terrace_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void room1_temperature_callback(uint8_t *buffer, uint8_t size) {
	float temp;

	memcpy(&temp, buffer, 4);

	record.room_1_Temperature = temp;

#if defined(DEBUG)
	cerr << "temp (C): " << temp << endl;
#endif
}

void room1_pressure_callback(uint8_t *buffer, uint8_t size) {
	float pressure;

	memcpy(&pressure, buffer, 4);

	record.room_1_Pressure = pressure;

#if defined(DEBUG)
	cerr << "pressure (kPa): " << pressure << endl;
#endif
}

void fan_state_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.cellar_FanState = state;

#if defined(DEBUG)
	cerr << "Fan state: " << state << endl;
#endif
}

void stairs_movement_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.stairs_Movement = state;

#if defined(DEBUG)
	cerr << "Movement: " << state << endl;
#endif
}

void stairs_led_callback(uint8_t *buffer, uint8_t size) {
	bool state;

	memcpy(&state, buffer, 1);

	record.stairs_LedState = state;

#if defined(DEBUG)
	cerr << "LED state: " << state << endl;
#endif
}

void rtc_callback(uint8_t *buffer, uint8_t size) {
  uint32_t date = convertArraytoUint32(buffer);

  record.date = date;

#if defined(DEBUG)
  cerr << "epoc: " << (unsigned int) date << endl;
#endif
}

int main(int argc, char ** argv) {

	string device = "/dev/tty.usbserial-AD025F4I";

	if (argc > 1)
		device = argv[1];

	// TODO get the local address from command line too

 	try {
		ClientSDP sdp(device,  XBeeAddress64(LOCAL_ADDR64_HIGH, LOCAL_ADDR64_LOW));

		uint32_t date;
		float cellar_Temperature;
		float cellar_Humidity;
		float terrace_Temperature;
		bool cellar_FanState;
		float room_1_Temperature;
		float room_1_Pressure;

		std::fstream outputFile;
		int count = 0;
		outputFile.open ("/var/www/last-data.tsv", std::fstream::out | std::fstream::trunc);

		outputFile << "date\tCellar(Temp/C)\tCellar(Humidity/%)\tTerrace(Temp/C)\tCellar(State)\tRoom1(Temp/C)\tRoom1(Pressure/kPa)\tKitchen(Temp/C)\tKitchen(Light/%)\tStairs(Light/%)\tStairs(LED)\tStairs(Movement)"  << endl;

		cout << "date\tCellar(Temp/C)\tCellar(Humidity/%)\tTerrace(Temp/C)\tCellar(State)\tRoom1(Temp/C)\tRoom1(Pressure/kPa)\tKitchen(Temp/C)\tKitchen(Light/%)\tStairs(Light/%)\tStairs(LED)\tStairs(Movement)"  << endl;

		while (true) {

			sdp.doAction("TEMPERATURE", "CELLAR", "GET_VALUE", &cellar_temperature_callback);

			sdp.doAction("HUMIDITY", "CELLAR", "GET_VALUE", &humidity_callback);

			sdp.doAction("FAN", "CELLAR", "GET_STATE", &fan_state_callback);

			sdp.doAction("TEMPERATURE", "TERRACE", "GET_VALUE", &terrace_temperature_callback);

			sdp.doAction("TEMPERATURE", "ROOM_1", "GET_VALUE", &room1_temperature_callback);

			sdp.doAction("PRESSURE", "ROOM_1", "GET_VALUE", &room1_pressure_callback);

			sdp.doAction("SDP_RTC", "UNDEF_LOCATION", "GET_VALUE", &rtc_callback);

			sdp.doAction("TEMPERATURE", "KITCHEN", "GET_VALUE", &kitchen_temperature_callback);

			sdp.doAction("LIGHT", "KITCHEN", "GET_VALUE", &kitchen_light_callback);

			sdp.doAction("LIGHT", "STAIRS", "GET_VALUE", &stairs_light_callback);

			sdp.doAction("LED", "STAIRS", "GET_STATE", &stairs_led_callback);

			sdp.doAction("MOVEMENT", "STAIRS", "GET_VALUE", &stairs_movement_callback);

			cout << record;
			outputFile << record;

			count ++;

			if (count > MAX_ROW) {
				count = 0;

				// close
				outputFile.close();

				// open/truncate
				outputFile.open ("/var/www/last-data.tsv", std::fstream::out | std::fstream::trunc);

				// add header
				outputFile << "date\tCellar(Temp/C)\tCellar(Humidity/%)\tTerrace(Temp/C)\tCellar(State)\tRoom1(Temp/C)\tRoom1(Pressure/kPa)\tKitchen(Temp/C)\tKitchen(Light/%)\tStairs(Light/%)\tStairs(LED)\tStairs(Movement)"  << endl;

			}

			sleep(6);
		}
	} catch (exception& e) {
        cerr << "Exception: " << e.what() << endl;
        cerr << "Check " << device << " is the tty to your XBee." << endl;
        return -1;
    }

}

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// 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
//
//-----------------------------------------------------------------------el-

// C++
#include <iostream>

// This class
#include "grins/grins_enums.h"
#include "grins/mesh_builder.h"

// GRINS
#include "grins/common.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/string_to_enum.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_modification.h"
#include "libmesh/mesh_refinement.h"
#include "libmesh/parallel_mesh.h"
#include "libmesh/parsed_function.h"
#include "libmesh/serial_mesh.h"

namespace GRINS
{

  MeshBuilder::MeshBuilder()
  {
    return;
  }

  MeshBuilder::~MeshBuilder()
  {
    return;
  }

  std::tr1::shared_ptr<libMesh::UnstructuredMesh> MeshBuilder::build
    (const GetPot& input,
     const libMesh::Parallel::Communicator &comm)
  {
    // User needs to tell us if we are generating or reading a mesh
    if( !input.have_variable("mesh-options/mesh_option") &&
        !input.have_variable("MeshOptions/type") )
      {
        libmesh_error_msg("ERROR: Must specify MeshOptions/type in input.");
      }

    // Are we generating the mesh or are we reading one in from a file?
    std::string mesh_build_type = input("MeshOptions/type", "DIE!");
    if( input.have_variable("mesh-options/mesh_option") )
      {
        std::string warning = "WARNING: mesh-options/mesh_option is DEPRECATED.\n";
        warning += "         Please update to use MeshOptions/type.\n";
        warning += "         MeshOptions/type can take values: generate, read\n";
        grins_warning(warning);

        mesh_build_type = input("mesh-options/mesh_option", "DIE!");
      }

    // Make sure the user gave a valid option
    /*! \todo Can remove last 4 checks once mesh-options/mesh_option support is removed. */
    if( mesh_build_type != std::string("generate") &&
        mesh_build_type != std::string("read") &&
        mesh_build_type != std::string("read_mesh_from_file") &&
        mesh_build_type != std::string("create_1D_mesh") &&
        mesh_build_type != std::string("create_2D_mesh") &&
        mesh_build_type != std::string("create_3D_mesh") )
      {
        std::string error = "ERROR: Invalid value of "+mesh_build_type+" for MeshOptions/type.\n";
          error += "       Valid values are: generate\n";
          error += "                         read\n";
          libmesh_error_msg(error);
      }

    // Create UnstructuredMesh object (defaults to dimension 1).
    libMesh::UnstructuredMesh* mesh;

    // Were we specifically asked to use a ParallelMesh or SerialMesh?
    {
      std::string mesh_class = input("MeshOptions/mesh_class", "default");

      if( input.have_variable("mesh-options/mesh_class") )
        {
          std::string warning = "WARNING: mesh-options/mesh_class is DEPRECATED.\n";
          warning += "         Please update to use MeshOptions/mesh_class.\n";
          warning += "         MeshOptions/mesh_class can take values: serial, parallel\n";
          grins_warning(warning);

          mesh_class = input("mesh-options/mesh_class", "default");
        }

      if (mesh_class == "parallel")
        mesh = new libMesh::ParallelMesh(comm);
      else if (mesh_class == "serial")
        mesh = new libMesh::SerialMesh(comm);
      else if (mesh_class == "default")
        mesh = new libMesh::Mesh(comm);
      else
        {
          std::string error = "ERROR: Invalid mesh_class "+mesh_class+" input for MeshOptions/mesh_class.\n";
            error += "       Valid choices are: serial, parallel.\n";
            libmesh_error_msg(error);
        }
    }

    // Read mesh from file
    if(mesh_build_type =="read_mesh_from_file" /* This is deprecated */ ||
       mesh_build_type == "read" )
      {
        // Make sure the user set the filename to read
        if( !input.have_variable("mesh-options/mesh_filename") /* This is deprecated */ &&
            !input.have_variable("MeshOptions/Read/filename") )
          {
            libmesh_error_msg("ERROR: Must specify MeshOptions/Read/filename for reading mesh.");
          }

        std::string mesh_filename = input("MeshOptions/Read/filename", "DIE!");

        if( input.have_variable("mesh-options/mesh_filename") )
          {
            std::string warning = "WARNING: mesh-options/mesh_filename is DEPRECATED.\n";
            warning += "         Please update to use MeshOptions/Read/filename.\n";
            grins_warning(warning);

            mesh_filename = input("mesh-options/mesh_filename", "DIE!");
          }

	// According to Roy Stogner, the only read format
	// that won't properly reset the dimension is gmsh.
	/*! \todo Need to a check a GMSH meshes */
	mesh->read(mesh_filename);
      }

    // Generate the mesh using built-in libMesh functions
    else if(mesh_build_type=="create_1D_mesh" /* This is deprecated */ ||
            mesh_build_type=="create_2D_mesh" /* This is deprecated */ ||
            mesh_build_type=="create_3D_mesh" /* This is deprecated */ ||
            mesh_build_type=="generate")
      {
        this->generate_mesh(mesh_build_type,input,mesh);
      }

    else
      {
        // Shouldn't have gotten here
        libmesh_error();
      }

    /* Only do the mesh refinement here if we don't have a restart file.
       Otherwise, we need to wait until we've read in the restart file.
       That is done in Simulation::check_for_restart */
    if( !input.have_variable("restart-options/restart_file") )
      {
        this->do_mesh_refinement_from_input( input, comm, *mesh );
      }

    return std::tr1::shared_ptr<libMesh::UnstructuredMesh>(mesh);
  }

  void MeshBuilder::generate_mesh( const std::string& mesh_build_type, const GetPot& input,
                                   libMesh::UnstructuredMesh* mesh )
  {
    unsigned int dimension = input("MeshOptions/Generation/dimension",0);

    if( !input.have_variable("mesh-options/mesh_option") /* Deprecated */ &&
        !input.have_variable("MeshOptions/Generation/dimension") )
      {
        libmesh_error_msg("ERROR: Must specify MeshOptions/Generation/dimension for generating mesh.");
      }

    /* Remove these once suport for mesh-options/mesh_option is removed */
    if( mesh_build_type == "create_1D_mesh" /* This is deprecated */ )
      dimension = 1;

    if( mesh_build_type=="create_2D_mesh" /* This is deprecated */ )
      dimension = 2;

    if( mesh_build_type=="create_3D_mesh" /* This is deprecated */ )
      dimension = 3;

    // Set the mesh dimension
    mesh->set_mesh_dimension(dimension);

    libMesh::Real domain_x1_min = input("mesh-options/domain_x1_min", 0.0);
    libMesh::Real domain_x2_min = input("mesh-options/domain_x2_min", 0.0);
    libMesh::Real domain_x3_min = input("mesh-options/domain_x3_min", 0.0);

    libMesh::Real domain_x1_max = input("mesh-options/domain_x1_max", 1.0);
    libMesh::Real domain_x2_max = input("mesh-options/domain_x2_max", 1.0);
    libMesh::Real domain_x3_max = input("mesh-options/domain_x3_max", 1.0);

    int mesh_nx1 = input("mesh-options/mesh_nx1", -1);
    int mesh_nx2 = input("mesh-options/mesh_nx2", -1);
    int mesh_nx3 = input("mesh-options/mesh_nx3", -1);

    std::string element_type = input("mesh-options/element_type", "NULL");

    if( dimension == 1 )
      {
        if(element_type=="NULL")
	  {
	    element_type = "EDGE3";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_line(*mesh,
						   mesh_nx1,
						   domain_x1_min,
						   domain_x1_max,
						   element_enum_type);
      }

    else if( dimension == 2 )
      {
	if(element_type=="NULL")
	  {
	    element_type = "TRI6";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_square(*mesh,
						     mesh_nx1,
						     mesh_nx2,
						     domain_x1_min,
						     domain_x1_max,
						     domain_x2_min,
						     domain_x2_max,
						     element_enum_type);
      }

    else if( dimension == 3 )
      {
	if(element_type=="NULL")
	  {
	    element_type = "TET10";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_cube(*mesh,
						   mesh_nx1,
						   mesh_nx2,
						   mesh_nx3,
						   domain_x1_min,
						   domain_x1_max,
						   domain_x2_min,
						   domain_x2_max,
						   domain_x3_min,
						   domain_x3_max,
						   element_enum_type);
      }

    else
      {
        // This shouldn't have happened
	libmesh_error();
      }
  }

  void MeshBuilder::do_mesh_refinement_from_input( const GetPot& input,
                                                   const libMesh::Parallel::Communicator &comm,
                                                   libMesh::UnstructuredMesh& mesh ) const
  {
    std::string redistribution_function_string =
            input("mesh-options/redistribute", std::string("0"));

    if (redistribution_function_string != "0")
      {
        libMesh::ParsedFunction<libMesh::Real>
          redistribution_function(redistribution_function_string);

        libMesh::MeshTools::Modification::redistribute
          (mesh, redistribution_function);

        // Redistribution can create distortions *within* second-order
        // elements, which can then be magnified by refinement.  Let's
        // undistort everything by converting to first order and back
        // if necessary.

        // FIXME - this only works for meshes with uniform geometry
        // order equal to FIRST or (full-order) SECOND.

        const libMesh::Elem *elem = *mesh.elements_begin();

        if (elem->default_order() != libMesh::FIRST)
          {
            mesh.all_first_order();
            mesh.all_second_order();
          }
      }

    int uniformly_refine = input("mesh-options/uniformly_refine", 0);

    if( uniformly_refine > 0 )
      {
        libMesh::MeshRefinement(mesh).uniformly_refine(uniformly_refine);
      }

    std::string h_refinement_function_string =
            input("mesh-options/locally_h_refine", std::string("0"));

    if (h_refinement_function_string != "0")
      {
        libMesh::ParsedFunction<libMesh::Real>
          h_refinement_function(h_refinement_function_string);

        libMesh::MeshRefinement mesh_refinement(mesh);

        libMesh::dof_id_type found_refinements = 0;
        do {
          found_refinements = 0;
          unsigned int max_level_refining = 0;

          libMesh::MeshBase::element_iterator elem_it =
                  mesh.active_elements_begin();
          libMesh::MeshBase::element_iterator elem_end =
                  mesh.active_elements_end();
          for (; elem_it != elem_end; ++elem_it)
            {
              libMesh::Elem *elem = *elem_it;

              const libMesh::Real refinement_val =
                h_refinement_function(elem->centroid());

	      const unsigned int n_refinements = refinement_val > 0 ?
                refinement_val : 0;

              if (elem->level() - uniformly_refine < n_refinements)
                {
                  elem->set_refinement_flag(libMesh::Elem::REFINE);
                  found_refinements++;
		  max_level_refining = std::max(max_level_refining,
                                                elem->level());
                }
            }

          comm.max(found_refinements);
          comm.max(max_level_refining);

          if (found_refinements)
            {
	      std::cout << "Found up to " << found_refinements <<
                " elements to refine on each processor," << std::endl;
	      std::cout << "with max level " << max_level_refining << std::endl;
              mesh_refinement.refine_and_coarsen_elements();

              if( input.have_variable("restart-options/restart_file") )
                {
                  std::cout << "Warning: it is known that locally_h_refine is broken when restarting." << std::endl
                            << "         and multiple refinement passes are done. We are forcibly" << std::endl
                            << "         limiting the refinement to one pass until this issue is resolved." << std::endl;
                  break;
                }
            }

        } while(found_refinements);

      }

    return;
  }

} // namespace GRINS
<commit_msg>Renamed local variables<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// 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
//
//-----------------------------------------------------------------------el-

// C++
#include <iostream>

// This class
#include "grins/grins_enums.h"
#include "grins/mesh_builder.h"

// GRINS
#include "grins/common.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/string_to_enum.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_modification.h"
#include "libmesh/mesh_refinement.h"
#include "libmesh/parallel_mesh.h"
#include "libmesh/parsed_function.h"
#include "libmesh/serial_mesh.h"

namespace GRINS
{

  MeshBuilder::MeshBuilder()
  {
    return;
  }

  MeshBuilder::~MeshBuilder()
  {
    return;
  }

  std::tr1::shared_ptr<libMesh::UnstructuredMesh> MeshBuilder::build
    (const GetPot& input,
     const libMesh::Parallel::Communicator &comm)
  {
    // User needs to tell us if we are generating or reading a mesh
    if( !input.have_variable("mesh-options/mesh_option") &&
        !input.have_variable("MeshOptions/type") )
      {
        libmesh_error_msg("ERROR: Must specify MeshOptions/type in input.");
      }

    // Are we generating the mesh or are we reading one in from a file?
    std::string mesh_build_type = input("MeshOptions/type", "DIE!");
    if( input.have_variable("mesh-options/mesh_option") )
      {
        std::string warning = "WARNING: mesh-options/mesh_option is DEPRECATED.\n";
        warning += "         Please update to use MeshOptions/type.\n";
        warning += "         MeshOptions/type can take values: generate, read\n";
        grins_warning(warning);

        mesh_build_type = input("mesh-options/mesh_option", "DIE!");
      }

    // Make sure the user gave a valid option
    /*! \todo Can remove last 4 checks once mesh-options/mesh_option support is removed. */
    if( mesh_build_type != std::string("generate") &&
        mesh_build_type != std::string("read") &&
        mesh_build_type != std::string("read_mesh_from_file") &&
        mesh_build_type != std::string("create_1D_mesh") &&
        mesh_build_type != std::string("create_2D_mesh") &&
        mesh_build_type != std::string("create_3D_mesh") )
      {
        std::string error = "ERROR: Invalid value of "+mesh_build_type+" for MeshOptions/type.\n";
          error += "       Valid values are: generate\n";
          error += "                         read\n";
          libmesh_error_msg(error);
      }

    // Create UnstructuredMesh object (defaults to dimension 1).
    libMesh::UnstructuredMesh* mesh;

    // Were we specifically asked to use a ParallelMesh or SerialMesh?
    {
      std::string mesh_class = input("MeshOptions/mesh_class", "default");

      if( input.have_variable("mesh-options/mesh_class") )
        {
          std::string warning = "WARNING: mesh-options/mesh_class is DEPRECATED.\n";
          warning += "         Please update to use MeshOptions/mesh_class.\n";
          warning += "         MeshOptions/mesh_class can take values: serial, parallel\n";
          grins_warning(warning);

          mesh_class = input("mesh-options/mesh_class", "default");
        }

      if (mesh_class == "parallel")
        mesh = new libMesh::ParallelMesh(comm);
      else if (mesh_class == "serial")
        mesh = new libMesh::SerialMesh(comm);
      else if (mesh_class == "default")
        mesh = new libMesh::Mesh(comm);
      else
        {
          std::string error = "ERROR: Invalid mesh_class "+mesh_class+" input for MeshOptions/mesh_class.\n";
            error += "       Valid choices are: serial, parallel.\n";
            libmesh_error_msg(error);
        }
    }

    // Read mesh from file
    if(mesh_build_type =="read_mesh_from_file" /* This is deprecated */ ||
       mesh_build_type == "read" )
      {
        // Make sure the user set the filename to read
        if( !input.have_variable("mesh-options/mesh_filename") /* This is deprecated */ &&
            !input.have_variable("MeshOptions/Read/filename") )
          {
            libmesh_error_msg("ERROR: Must specify MeshOptions/Read/filename for reading mesh.");
          }

        std::string mesh_filename = input("MeshOptions/Read/filename", "DIE!");

        if( input.have_variable("mesh-options/mesh_filename") )
          {
            std::string warning = "WARNING: mesh-options/mesh_filename is DEPRECATED.\n";
            warning += "         Please update to use MeshOptions/Read/filename.\n";
            grins_warning(warning);

            mesh_filename = input("mesh-options/mesh_filename", "DIE!");
          }

	// According to Roy Stogner, the only read format
	// that won't properly reset the dimension is gmsh.
	/*! \todo Need to a check a GMSH meshes */
	mesh->read(mesh_filename);
      }

    // Generate the mesh using built-in libMesh functions
    else if(mesh_build_type=="create_1D_mesh" /* This is deprecated */ ||
            mesh_build_type=="create_2D_mesh" /* This is deprecated */ ||
            mesh_build_type=="create_3D_mesh" /* This is deprecated */ ||
            mesh_build_type=="generate")
      {
        this->generate_mesh(mesh_build_type,input,mesh);
      }

    else
      {
        // Shouldn't have gotten here
        libmesh_error();
      }

    /* Only do the mesh refinement here if we don't have a restart file.
       Otherwise, we need to wait until we've read in the restart file.
       That is done in Simulation::check_for_restart */
    if( !input.have_variable("restart-options/restart_file") )
      {
        this->do_mesh_refinement_from_input( input, comm, *mesh );
      }

    return std::tr1::shared_ptr<libMesh::UnstructuredMesh>(mesh);
  }

  void MeshBuilder::generate_mesh( const std::string& mesh_build_type, const GetPot& input,
                                   libMesh::UnstructuredMesh* mesh )
  {
    unsigned int dimension = input("MeshOptions/Generation/dimension",0);

    if( !input.have_variable("mesh-options/mesh_option") /* Deprecated */ &&
        !input.have_variable("MeshOptions/Generation/dimension") )
      {
        libmesh_error_msg("ERROR: Must specify MeshOptions/Generation/dimension for generating mesh.");
      }

    /* Remove these once suport for mesh-options/mesh_option is removed */
    if( mesh_build_type == "create_1D_mesh" /* This is deprecated */ )
      dimension = 1;

    if( mesh_build_type=="create_2D_mesh" /* This is deprecated */ )
      dimension = 2;

    if( mesh_build_type=="create_3D_mesh" /* This is deprecated */ )
      dimension = 3;

    // Set the mesh dimension
    mesh->set_mesh_dimension(dimension);

    libMesh::Real x_min = input("mesh-options/domain_x1_min", 0.0);
    libMesh::Real y_min = input("mesh-options/domain_x2_min", 0.0);
    libMesh::Real z_min = input("mesh-options/domain_x3_min", 0.0);

    libMesh::Real x_max = input("mesh-options/domain_x1_max", 1.0);
    libMesh::Real y_max = input("mesh-options/domain_x2_max", 1.0);
    libMesh::Real z_max = input("mesh-options/domain_x3_max", 1.0);

    int n_elems_x = input("mesh-options/mesh_nx1", -1);
    int n_elems_y = input("mesh-options/mesh_nx2", -1);
    int n_elems_z = input("mesh-options/mesh_nx3", -1);

    std::string element_type = input("mesh-options/element_type", "NULL");

    if( dimension == 1 )
      {
        if(element_type=="NULL")
	  {
	    element_type = "EDGE3";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_line(*mesh,
                                                   n_elems_x,
                                                   x_min,
                                                   x_max,
						   element_enum_type);
      }

    else if( dimension == 2 )
      {
	if(element_type=="NULL")
	  {
	    element_type = "TRI6";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_square(*mesh,
                                                     n_elems_x,
                                                     n_elems_y,
                                                     x_min,
                                                     x_max,
                                                     y_min,
                                                     y_max,
						     element_enum_type);
      }

    else if( dimension == 3 )
      {
	if(element_type=="NULL")
	  {
	    element_type = "TET10";
	  }

        GRINSEnums::ElemType element_enum_type =
	  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);

	libMesh::MeshTools::Generation::build_cube(*mesh,
                                                   n_elems_x,
                                                   n_elems_y,
                                                   n_elems_z,
                                                   x_min,
                                                   x_max,
                                                   y_min,
                                                   y_max,
                                                   z_min,
                                                   z_max,
						   element_enum_type);
      }

    else
      {
        // This shouldn't have happened
	libmesh_error();
      }
  }

  void MeshBuilder::do_mesh_refinement_from_input( const GetPot& input,
                                                   const libMesh::Parallel::Communicator &comm,
                                                   libMesh::UnstructuredMesh& mesh ) const
  {
    std::string redistribution_function_string =
            input("mesh-options/redistribute", std::string("0"));

    if (redistribution_function_string != "0")
      {
        libMesh::ParsedFunction<libMesh::Real>
          redistribution_function(redistribution_function_string);

        libMesh::MeshTools::Modification::redistribute
          (mesh, redistribution_function);

        // Redistribution can create distortions *within* second-order
        // elements, which can then be magnified by refinement.  Let's
        // undistort everything by converting to first order and back
        // if necessary.

        // FIXME - this only works for meshes with uniform geometry
        // order equal to FIRST or (full-order) SECOND.

        const libMesh::Elem *elem = *mesh.elements_begin();

        if (elem->default_order() != libMesh::FIRST)
          {
            mesh.all_first_order();
            mesh.all_second_order();
          }
      }

    int uniformly_refine = input("mesh-options/uniformly_refine", 0);

    if( uniformly_refine > 0 )
      {
        libMesh::MeshRefinement(mesh).uniformly_refine(uniformly_refine);
      }

    std::string h_refinement_function_string =
            input("mesh-options/locally_h_refine", std::string("0"));

    if (h_refinement_function_string != "0")
      {
        libMesh::ParsedFunction<libMesh::Real>
          h_refinement_function(h_refinement_function_string);

        libMesh::MeshRefinement mesh_refinement(mesh);

        libMesh::dof_id_type found_refinements = 0;
        do {
          found_refinements = 0;
          unsigned int max_level_refining = 0;

          libMesh::MeshBase::element_iterator elem_it =
                  mesh.active_elements_begin();
          libMesh::MeshBase::element_iterator elem_end =
                  mesh.active_elements_end();
          for (; elem_it != elem_end; ++elem_it)
            {
              libMesh::Elem *elem = *elem_it;

              const libMesh::Real refinement_val =
                h_refinement_function(elem->centroid());

	      const unsigned int n_refinements = refinement_val > 0 ?
                refinement_val : 0;

              if (elem->level() - uniformly_refine < n_refinements)
                {
                  elem->set_refinement_flag(libMesh::Elem::REFINE);
                  found_refinements++;
		  max_level_refining = std::max(max_level_refining,
                                                elem->level());
                }
            }

          comm.max(found_refinements);
          comm.max(max_level_refining);

          if (found_refinements)
            {
	      std::cout << "Found up to " << found_refinements <<
                " elements to refine on each processor," << std::endl;
	      std::cout << "with max level " << max_level_refining << std::endl;
              mesh_refinement.refine_and_coarsen_elements();

              if( input.have_variable("restart-options/restart_file") )
                {
                  std::cout << "Warning: it is known that locally_h_refine is broken when restarting." << std::endl
                            << "         and multiple refinement passes are done. We are forcibly" << std::endl
                            << "         limiting the refinement to one pass until this issue is resolved." << std::endl;
                  break;
                }
            }

        } while(found_refinements);

      }

    return;
  }

} // namespace GRINS
<|endoftext|>