<commit_before>//
// Copyright (c) 2018 Rokas Kupstys
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Scene/Node.h>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/GraphicsEvents.h>
#include <Urho3D/Graphics/AnimatedModel.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/IO/Log.h>
#include <Urho3D/SystemUI/SystemUI.h>
#include <Urho3D/Graphics/Light.h>
#include <ImGui/imgui_internal.h>
#include <ImGuizmo/ImGuizmo.h>
#include "Gizmo.h"

namespace Urho3D
{

Gizmo::Gizmo(Context* context) : Object(context)
{
    SubscribeToEvent(E_POSTRENDERUPDATE, [&](StringHash, VariantMap&) { RenderDebugInfo(); });
}

Gizmo::~Gizmo()
{
    UnsubscribeFromAllEvents();
}

bool Gizmo::Manipulate(const Camera* camera, Node* node)
{
    Vector<WeakPtr<Node>> nodes;
    nodes.Push(WeakPtr<Node>(node));
    return Manipulate(camera, nodes);
}

bool Gizmo::IsActive() const
{
    return ImGuizmo::IsUsing();
}

bool Gizmo::Manipulate(const Camera* camera, const Vector<WeakPtr<Node>>& nodes)
{
    if (nodes.Empty())
        return false;

    if (!IsActive())
    {
        // Find center point of all nodes
        // It is not clear what should be rotation and scale of center point for multiselection, therefore we limit
        // multiselection operations to world space (see above).
        Vector3 center = Vector3::ZERO;
        auto count = 0;
        for (const auto& node: nodes)
        {
            if (node.Expired() || node->GetType() == Scene::GetTypeStatic())
                continue;
            center += node->GetWorldPosition();
            count++;
        }

        if (count == 0)
            return false;

        center /= count;
        currentOrigin_.SetTranslation(center);
    }

    // Enums are compatible.
    auto operation = static_cast<ImGuizmo::OPERATION>(operation_);
    ImGuizmo::MODE mode = ImGuizmo::WORLD;
    // Scaling only works in local space. Multiselections only work in world space.
    if (transformSpace_ == TS_LOCAL)
        mode = ImGuizmo::LOCAL;
    else if (transformSpace_ == TS_WORLD)
        mode = ImGuizmo::WORLD;

    // Scaling is always done in local space even for multiselections.
    if (operation_ == GIZMOOP_SCALE)
        mode = ImGuizmo::LOCAL;
        // Any other operations on multiselections are done in world space.
    else if (nodes.Size() > 1)
        mode = ImGuizmo::WORLD;

    Matrix4 view = camera->GetView().ToMatrix4().Transpose();
    Matrix4 proj = camera->GetProjection().Transpose();
    Matrix4 tran = currentOrigin_.Transpose();
    Matrix4 delta;

    ImGuiIO& io = ImGui::GetIO();

    auto pos = displayPos_;
    auto size = displaySize_;
    if (size.x == 0 && size.y == 0)
        size = io.DisplaySize;
    ImGuizmo::SetRect(pos.x, pos.y, size.x, size.y);
    ImGuizmo::Manipulate(&view.m00_, &proj.m00_, operation, mode, &tran.m00_, &delta.m00_, nullptr);

    if (IsActive())
    {
        if (!wasActive_)
        {
            // Just started modifying nodes.
            for (const auto& node: nodes)
                initialTransforms_[node] = node->GetTransform();
        }

        wasActive_ = true;
        tran = tran.Transpose();
        delta = delta.Transpose();

        currentOrigin_ = Matrix4(tran);

        for (const auto& node: nodes)
        {
            if (node == nullptr)
            {
                URHO3D_LOGERROR("Gizmo received null pointer of node.");
                continue;
            }

            if (operation_ == GIZMOOP_SCALE)
            {
                // A workaround for ImGuizmo bug where delta matrix returns absolute scale value.
                if (!nodeScaleStart_.Contains(node))
                    nodeScaleStart_[node] = node->GetScale();
                node->SetScale(nodeScaleStart_[node] * delta.Scale());
            }
            else
            {
                // Delta matrix is always in world-space.
                if (operation_ == GIZMOOP_ROTATE)
                    node->RotateAround(currentOrigin_.Translation(), -delta.Rotation(), TS_WORLD);
                else
                    node->Translate(delta.Translation(), TS_WORLD);
            }
        }

        return true;
    }
    else
    {
        if (wasActive_)
        {
            // Just finished modifying nodes.
            using namespace GizmoNodeModified;
            for (const auto& node: nodes)
            {
                if (node.Expired())
                {
                    URHO3D_LOGWARNINGF("Node expired while manipulating it with gizmo.");
                    continue;
                }

                auto it = initialTransforms_.Find(node.Get());
                if (it == initialTransforms_.End())
                {
                    URHO3D_LOGWARNINGF("Gizmo has no record of initial node transform. List of transformed nodes "
                        "changed mid-manipulation?");
                    continue;
                }

                SendEvent(E_GIZMONODEMODIFIED, P_NODE, node.Get(), P_OLDTRANSFORM, it->second_,
                    P_NEWTRANSFORM, node->GetTransform());
            }
        }
        wasActive_ = false;
        initialTransforms_.Clear();
        if (operation_ == GIZMOOP_SCALE && !nodeScaleStart_.Empty())
            nodeScaleStart_.Clear();
    }
    return false;
}

bool Gizmo::ManipulateSelection(const Camera* camera)
{
    ImGuizmo::SetDrawlist();
    return Manipulate(camera, nodeSelection_);
}

void Gizmo::RenderUI()
{
    ui::TextUnformatted("Op:");
    ui::SameLine(60);

    if (ui::RadioButton("Tr", GetOperation() == GIZMOOP_TRANSLATE))
        SetOperation(GIZMOOP_TRANSLATE);
    ui::SameLine();
    if (ui::RadioButton("Rot", GetOperation() == GIZMOOP_ROTATE))
        SetOperation(GIZMOOP_ROTATE);
    ui::SameLine();
    if (ui::RadioButton("Scl", GetOperation() == GIZMOOP_SCALE))
        SetOperation(GIZMOOP_SCALE);

    ui::TextUnformatted("Space:");
    ui::SameLine(60);
    if (ui::RadioButton("World", GetTransformSpace() == TS_WORLD))
        SetTransformSpace(TS_WORLD);
    ui::SameLine();
    if (ui::RadioButton("Local", GetTransformSpace() == TS_LOCAL))
        SetTransformSpace(TS_LOCAL);
}

bool Gizmo::Select(Node* node)
{
    WeakPtr<Node> weakNode(node);
    if (nodeSelection_.Contains(weakNode))
        return false;
    nodeSelection_.Push(weakNode);
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

bool Gizmo::Select(PODVector<Node*> nodes)
{
    bool selectedAny = false;
    for (auto* node : nodes)
    {
        WeakPtr<Node> weakNode(node);
        if (!nodeSelection_.Contains(weakNode))
        {
            nodeSelection_.Push(weakNode);
            selectedAny = true;
        }
    }
    if (selectedAny)
        SendEvent(E_GIZMOSELECTIONCHANGED);

    return selectedAny;
}

bool Gizmo::Unselect(Node* node)
{
    WeakPtr<Node> weakNode(node);
    if (!nodeSelection_.Contains(weakNode))
        return false;
    nodeSelection_.Remove(weakNode);
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

void Gizmo::RenderDebugInfo()
{
    DebugRenderer* debug = nullptr;
    for (auto it = nodeSelection_.Begin(); it != nodeSelection_.End();)
    {
        WeakPtr<Node> node = *it;
        if (node.Expired())
            it = nodeSelection_.Erase(it);
        else
        {
            if (debug == nullptr)
            {
                if (auto scene = node->GetScene())
                    debug = scene->GetComponent<DebugRenderer>();
            }
            if (debug != nullptr)
            {
                for (auto& component: node->GetComponents())
                {
                    if (auto light = dynamic_cast<Light*>(component.Get()))
                        light->DrawDebugGeometry(debug, true);
                    else if (auto drawable = dynamic_cast<Drawable*>(component.Get()))
                        debug->AddBoundingBox(drawable->GetWorldBoundingBox(), Color::WHITE);
                    else
                        component->DrawDebugGeometry(debug, true);
                }
            }
            ++it;
        }
    }
}

void Gizmo::HandleAutoSelection()
{
    if (autoModeCamera_.Null())
        return;

    ManipulateSelection(autoModeCamera_);

    // Discard clicks when interacting with UI
    if (GetUI()->GetFocusElement() != nullptr)
        return;

    // Discard clicks when interacting with SystemUI
    if (GetSystemUI()->IsAnyItemActive() || GetSystemUI()->IsAnyItemHovered())
        return;

    // Discard clicks when gizmo is being manipulated
    if (IsActive())
        return;

    if (GetInput()->GetMouseButtonPress(MOUSEB_LEFT))
    {
        UI* ui = GetSubsystem<UI>();
        IntVector2 pos = ui->GetCursorPosition();
        // Check the cursor is visible and there is no UI element in front of the cursor
        if (!GetInput()->IsMouseVisible() || ui->GetElementAt(pos, true))
            return;

        Graphics* graphics = GetSubsystem<Graphics>();
        Scene* cameraScene = autoModeCamera_->GetScene();
        Ray cameraRay = autoModeCamera_->GetScreenRay((float)pos.x_ / graphics->GetWidth(), (float)pos.y_ / graphics->GetHeight());
        // Pick only geometry objects, not eg. zones or lights, only get the first (closest) hit
        PODVector<RayQueryResult> results;
        RayOctreeQuery query(results, cameraRay, RAY_TRIANGLE, M_INFINITY, DRAWABLE_GEOMETRY);
        cameraScene->GetComponent<Octree>()->RaycastSingle(query);
        if (results.Size())
        {
            WeakPtr<Node> clickNode(results[0].drawable_->GetNode());
            if (!GetInput()->GetKeyDown(KEY_CTRL))
                nodeSelection_.Clear();

            ToggleSelection(clickNode);
        }
    }

    if (GetInput()->GetKeyDown(KEY_SHIFT) && GetInput()->GetKeyPress(KEY_TAB))
        operation_ = static_cast<GizmoOperation>(((size_t)operation_ + 1) % GIZMOOP_MAX);

    if (GetInput()->GetKeyDown(KEY_CTRL) && GetInput()->GetKeyPress(KEY_TAB))
    {
        if (transformSpace_ == TS_WORLD)
            transformSpace_ = TS_LOCAL;
        else if (transformSpace_ == TS_LOCAL)
            transformSpace_ = TS_WORLD;
    }
}

void Gizmo::EnableAutoMode(Camera* camera)
{
    if (autoModeCamera_ == camera)
        return;

    if (camera == nullptr)
        UnsubscribeFromEvent(E_UPDATE);
    else
    {
        Scene* scene = camera->GetScene();
        if (scene == nullptr)
        {
            URHO3D_LOGERROR("Camera which does not belong to scene can not be used for gizmo auto selection.");
            return;
        }

        autoModeCamera_ = camera;

        scene->GetOrCreateComponent<DebugRenderer>();
        SubscribeToEvent(E_UPDATE, [&](StringHash, VariantMap&) { HandleAutoSelection(); });
    }
}

void Gizmo::ToggleSelection(Node* node)
{
    if (IsSelected(node))
        Unselect(node);
    else
        Select(node);
}

bool Gizmo::UnselectAll()
{
    if (nodeSelection_.Empty())
        return false;
    nodeSelection_.Clear();
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

bool Gizmo::IsSelected(Node* node) const
{
    WeakPtr<Node> pNode(node);
    return nodeSelection_.Contains(pNode);
}

void Gizmo::SetScreenRect(const IntVector2& pos, const IntVector2& size)
{
    displayPos_ = ToImGui(pos);
    displaySize_ = ToImGui(size);
}

void Gizmo::SetScreenRect(const IntRect& rect)
{
    displayPos_ = ToImGui(rect.Min());
    displaySize_.x = rect.Width();
    displaySize_.y = rect.Height();
}

}
<commit_msg>Toolbox/SystemUI: Fix gizmo orientation being incorrect in single selection.<commit_after>//
// Copyright (c) 2018 Rokas Kupstys
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Scene/Node.h>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/GraphicsEvents.h>
#include <Urho3D/Graphics/AnimatedModel.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/IO/Log.h>
#include <Urho3D/SystemUI/SystemUI.h>
#include <Urho3D/Graphics/Light.h>
#include <ImGui/imgui_internal.h>
#include <ImGuizmo/ImGuizmo.h>
#include "Gizmo.h"

namespace Urho3D
{

Gizmo::Gizmo(Context* context) : Object(context)
{
    SubscribeToEvent(E_POSTRENDERUPDATE, [&](StringHash, VariantMap&) { RenderDebugInfo(); });
}

Gizmo::~Gizmo()
{
    UnsubscribeFromAllEvents();
}

bool Gizmo::Manipulate(const Camera* camera, Node* node)
{
    Vector<WeakPtr<Node>> nodes;
    nodes.Push(WeakPtr<Node>(node));
    return Manipulate(camera, nodes);
}

bool Gizmo::IsActive() const
{
    return ImGuizmo::IsUsing();
}

bool Gizmo::Manipulate(const Camera* camera, const Vector<WeakPtr<Node>>& nodes)
{
    if (nodes.Empty())
        return false;

    if (!IsActive())
    {
        if (nodes.Size() > 1)
        {
            // Find center point of all nodes
            // It is not clear what should be rotation and scale of center point for multiselection, therefore we limit
            // multiselection operations to world space (see above).
            Vector3
            center = Vector3::ZERO;
            auto count = 0;
            for (const auto& node: nodes)
            {
                if (node.Expired() || node->GetType() == Scene::GetTypeStatic())
                    continue;
                center += node->GetWorldPosition();
                count++;
            }

            if (count == 0)
                return false;

            center /= count;
            currentOrigin_.SetTranslation(center);
        }
        else if (!nodes.Front().Expired())
            currentOrigin_ = nodes.Front()->GetTransform().ToMatrix4();
    }

    // Enums are compatible.
    auto operation = static_cast<ImGuizmo::OPERATION>(operation_);
    ImGuizmo::MODE mode = ImGuizmo::WORLD;
    // Scaling only works in local space. Multiselections only work in world space.
    if (transformSpace_ == TS_LOCAL)
        mode = ImGuizmo::LOCAL;
    else if (transformSpace_ == TS_WORLD)
        mode = ImGuizmo::WORLD;

    // Scaling is always done in local space even for multiselections.
    if (operation_ == GIZMOOP_SCALE)
        mode = ImGuizmo::LOCAL;
        // Any other operations on multiselections are done in world space.
    else if (nodes.Size() > 1)
        mode = ImGuizmo::WORLD;

    Matrix4 view = camera->GetView().ToMatrix4().Transpose();
    Matrix4 proj = camera->GetProjection().Transpose();
    Matrix4 tran = currentOrigin_.Transpose();
    Matrix4 delta;

    ImGuiIO& io = ImGui::GetIO();

    auto pos = displayPos_;
    auto size = displaySize_;
    if (size.x == 0 && size.y == 0)
        size = io.DisplaySize;
    ImGuizmo::SetRect(pos.x, pos.y, size.x, size.y);
    ImGuizmo::Manipulate(&view.m00_, &proj.m00_, operation, mode, &tran.m00_, &delta.m00_, nullptr);

    if (IsActive())
    {
        if (!wasActive_)
        {
            // Just started modifying nodes.
            for (const auto& node: nodes)
                initialTransforms_[node] = node->GetTransform();
        }

        wasActive_ = true;
        tran = tran.Transpose();
        delta = delta.Transpose();

        currentOrigin_ = Matrix4(tran);

        for (const auto& node: nodes)
        {
            if (node == nullptr)
            {
                URHO3D_LOGERROR("Gizmo received null pointer of node.");
                continue;
            }

            if (operation_ == GIZMOOP_SCALE)
            {
                // A workaround for ImGuizmo bug where delta matrix returns absolute scale value.
                if (!nodeScaleStart_.Contains(node))
                    nodeScaleStart_[node] = node->GetScale();
                node->SetScale(nodeScaleStart_[node] * delta.Scale());
            }
            else
            {
                // Delta matrix is always in world-space.
                if (operation_ == GIZMOOP_ROTATE)
                    node->RotateAround(currentOrigin_.Translation(), -delta.Rotation(), TS_WORLD);
                else
                    node->Translate(delta.Translation(), TS_WORLD);
            }
        }

        return true;
    }
    else
    {
        if (wasActive_)
        {
            // Just finished modifying nodes.
            using namespace GizmoNodeModified;
            for (const auto& node: nodes)
            {
                if (node.Expired())
                {
                    URHO3D_LOGWARNINGF("Node expired while manipulating it with gizmo.");
                    continue;
                }

                auto it = initialTransforms_.Find(node.Get());
                if (it == initialTransforms_.End())
                {
                    URHO3D_LOGWARNINGF("Gizmo has no record of initial node transform. List of transformed nodes "
                        "changed mid-manipulation?");
                    continue;
                }

                SendEvent(E_GIZMONODEMODIFIED, P_NODE, node.Get(), P_OLDTRANSFORM, it->second_,
                    P_NEWTRANSFORM, node->GetTransform());
            }
        }
        wasActive_ = false;
        initialTransforms_.Clear();
        if (operation_ == GIZMOOP_SCALE && !nodeScaleStart_.Empty())
            nodeScaleStart_.Clear();
    }
    return false;
}

bool Gizmo::ManipulateSelection(const Camera* camera)
{
    ImGuizmo::SetDrawlist();
    return Manipulate(camera, nodeSelection_);
}

void Gizmo::RenderUI()
{
    ui::TextUnformatted("Op:");
    ui::SameLine(60);

    if (ui::RadioButton("Tr", GetOperation() == GIZMOOP_TRANSLATE))
        SetOperation(GIZMOOP_TRANSLATE);
    ui::SameLine();
    if (ui::RadioButton("Rot", GetOperation() == GIZMOOP_ROTATE))
        SetOperation(GIZMOOP_ROTATE);
    ui::SameLine();
    if (ui::RadioButton("Scl", GetOperation() == GIZMOOP_SCALE))
        SetOperation(GIZMOOP_SCALE);

    ui::TextUnformatted("Space:");
    ui::SameLine(60);
    if (ui::RadioButton("World", GetTransformSpace() == TS_WORLD))
        SetTransformSpace(TS_WORLD);
    ui::SameLine();
    if (ui::RadioButton("Local", GetTransformSpace() == TS_LOCAL))
        SetTransformSpace(TS_LOCAL);
}

bool Gizmo::Select(Node* node)
{
    WeakPtr<Node> weakNode(node);
    if (nodeSelection_.Contains(weakNode))
        return false;
    nodeSelection_.Push(weakNode);
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

bool Gizmo::Select(PODVector<Node*> nodes)
{
    bool selectedAny = false;
    for (auto* node : nodes)
    {
        WeakPtr<Node> weakNode(node);
        if (!nodeSelection_.Contains(weakNode))
        {
            nodeSelection_.Push(weakNode);
            selectedAny = true;
        }
    }
    if (selectedAny)
        SendEvent(E_GIZMOSELECTIONCHANGED);

    return selectedAny;
}

bool Gizmo::Unselect(Node* node)
{
    WeakPtr<Node> weakNode(node);
    if (!nodeSelection_.Contains(weakNode))
        return false;
    nodeSelection_.Remove(weakNode);
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

void Gizmo::RenderDebugInfo()
{
    DebugRenderer* debug = nullptr;
    for (auto it = nodeSelection_.Begin(); it != nodeSelection_.End();)
    {
        WeakPtr<Node> node = *it;
        if (node.Expired())
            it = nodeSelection_.Erase(it);
        else
        {
            if (debug == nullptr)
            {
                if (auto scene = node->GetScene())
                    debug = scene->GetComponent<DebugRenderer>();
            }
            if (debug != nullptr)
            {
                for (auto& component: node->GetComponents())
                {
                    if (auto light = dynamic_cast<Light*>(component.Get()))
                        light->DrawDebugGeometry(debug, true);
                    else if (auto drawable = dynamic_cast<Drawable*>(component.Get()))
                        debug->AddBoundingBox(drawable->GetWorldBoundingBox(), Color::WHITE);
                    else
                        component->DrawDebugGeometry(debug, true);
                }
            }
            ++it;
        }
    }
}

void Gizmo::HandleAutoSelection()
{
    if (autoModeCamera_.Null())
        return;

    ManipulateSelection(autoModeCamera_);

    // Discard clicks when interacting with UI
    if (GetUI()->GetFocusElement() != nullptr)
        return;

    // Discard clicks when interacting with SystemUI
    if (GetSystemUI()->IsAnyItemActive() || GetSystemUI()->IsAnyItemHovered())
        return;

    // Discard clicks when gizmo is being manipulated
    if (IsActive())
        return;

    if (GetInput()->GetMouseButtonPress(MOUSEB_LEFT))
    {
        UI* ui = GetSubsystem<UI>();
        IntVector2 pos = ui->GetCursorPosition();
        // Check the cursor is visible and there is no UI element in front of the cursor
        if (!GetInput()->IsMouseVisible() || ui->GetElementAt(pos, true))
            return;

        Graphics* graphics = GetSubsystem<Graphics>();
        Scene* cameraScene = autoModeCamera_->GetScene();
        Ray cameraRay = autoModeCamera_->GetScreenRay((float)pos.x_ / graphics->GetWidth(), (float)pos.y_ / graphics->GetHeight());
        // Pick only geometry objects, not eg. zones or lights, only get the first (closest) hit
        PODVector<RayQueryResult> results;
        RayOctreeQuery query(results, cameraRay, RAY_TRIANGLE, M_INFINITY, DRAWABLE_GEOMETRY);
        cameraScene->GetComponent<Octree>()->RaycastSingle(query);
        if (results.Size())
        {
            WeakPtr<Node> clickNode(results[0].drawable_->GetNode());
            if (!GetInput()->GetKeyDown(KEY_CTRL))
                nodeSelection_.Clear();

            ToggleSelection(clickNode);
        }
    }

    if (GetInput()->GetKeyDown(KEY_SHIFT) && GetInput()->GetKeyPress(KEY_TAB))
        operation_ = static_cast<GizmoOperation>(((size_t)operation_ + 1) % GIZMOOP_MAX);

    if (GetInput()->GetKeyDown(KEY_CTRL) && GetInput()->GetKeyPress(KEY_TAB))
    {
        if (transformSpace_ == TS_WORLD)
            transformSpace_ = TS_LOCAL;
        else if (transformSpace_ == TS_LOCAL)
            transformSpace_ = TS_WORLD;
    }
}

void Gizmo::EnableAutoMode(Camera* camera)
{
    if (autoModeCamera_ == camera)
        return;

    if (camera == nullptr)
        UnsubscribeFromEvent(E_UPDATE);
    else
    {
        Scene* scene = camera->GetScene();
        if (scene == nullptr)
        {
            URHO3D_LOGERROR("Camera which does not belong to scene can not be used for gizmo auto selection.");
            return;
        }

        autoModeCamera_ = camera;

        scene->GetOrCreateComponent<DebugRenderer>();
        SubscribeToEvent(E_UPDATE, [&](StringHash, VariantMap&) { HandleAutoSelection(); });
    }
}

void Gizmo::ToggleSelection(Node* node)
{
    if (IsSelected(node))
        Unselect(node);
    else
        Select(node);
}

bool Gizmo::UnselectAll()
{
    if (nodeSelection_.Empty())
        return false;
    nodeSelection_.Clear();
    SendEvent(E_GIZMOSELECTIONCHANGED);
    return true;
}

bool Gizmo::IsSelected(Node* node) const
{
    WeakPtr<Node> pNode(node);
    return nodeSelection_.Contains(pNode);
}

void Gizmo::SetScreenRect(const IntVector2& pos, const IntVector2& size)
{
    displayPos_ = ToImGui(pos);
    displaySize_ = ToImGui(size);
}

void Gizmo::SetScreenRect(const IntRect& rect)
{
    displayPos_ = ToImGui(rect.Min());
    displaySize_.x = rect.Width();
    displaySize_.y = rect.Height();
}

}
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/kernels/data/dataset_test_base.h"

namespace tensorflow {
namespace data {
namespace {

constexpr char kNodeName[] = "optimize_dataset";
constexpr char kOpName[] = "OptimizeDataset";

class OptimizeDatasetOpTest : public DatasetOpsTestBase {
 protected:
  // Creates a new `OptimizeDataset` op kernel.
  Status CreateOptimizeDatasetOpKernel(
      const DataTypeVector& output_types,
      const std::vector<PartialTensorShape>& output_shapes,
      const std::vector<string>& optimization_configs,
      std::unique_ptr<OpKernel>* optimize_dataset_op_kernel) {
    NodeDef node_def = test::function::NDef(
        kNodeName, kOpName, {"input_dataset", "optimizations"},
        {{"output_types", output_types},
         {"output_shapes", output_shapes},
         {"optimization_configs", optimization_configs}});
    TF_RETURN_IF_ERROR(CreateOpKernel(node_def, optimize_dataset_op_kernel));
    return Status::OK();
  }

  // Create a new `OptimizeDataset` op kernel context.
  Status CreateOptimizeDatasetContext(
      OpKernel* const op_kernel,
      gtl::InlinedVector<TensorValue, 4>* const inputs,
      std::unique_ptr<OpKernelContext>* context) {
    TF_RETURN_IF_ERROR(CheckOpKernelInput(*op_kernel, *inputs));
    TF_RETURN_IF_ERROR(CreateOpKernelContext(op_kernel, inputs, context));
    return Status::OK();
  }

  // Create a `RangeDataset` dataset as a variant tensor.
  Status MakeRangeDataset(const Tensor& start, const Tensor& stop,
                          const Tensor& step,
                          const DataTypeVector& output_types,
                          const std::vector<PartialTensorShape>& output_shapes,
                          Tensor* range_dataset) {
    GraphConstructorOptions graph_opts;
    graph_opts.allow_internal_ops = true;
    graph_opts.expect_device_spec = false;

    TF_RETURN_IF_ERROR(RunFunction(
        test::function::MakeRangeDataset(),
        /*attrs*/
        {{"output_types", output_types}, {"output_shapes", output_shapes}},
        /*inputs*/ {start, stop, step}, graph_opts,
        /*rets*/ {range_dataset}));
  }

  // Create a `TakeDataset` dataset as a variant tensor.
  Status MakeTakeDataset(const Tensor& input_dataset, int64 count,
                         const DataTypeVector& output_types,
                         const std::vector<PartialTensorShape>& output_shapes,
                         Tensor* take_dataset) {
    GraphConstructorOptions graph_opts;
    graph_opts.allow_internal_ops = true;
    graph_opts.expect_device_spec = false;

    Tensor count_tensor = CreateTensor<int64>(TensorShape({}), {count});
    TF_RETURN_IF_ERROR(RunFunction(
        test::function::MakeTakeDataset(),
        /*attrs*/
        {{"output_types", output_types}, {"output_shapes", output_shapes}},
        /*inputs*/ {input_dataset, count_tensor}, graph_opts,
        /*rets*/ {take_dataset}));

    return Status::OK();
  }
};

TEST_F(OptimizeDatasetOpTest, NoopElimination) {
  int thread_num = 2, cpu_num = 2;
  TF_ASSERT_OK(InitThreadPool(thread_num));
  TF_ASSERT_OK(InitFunctionLibraryRuntime({}, cpu_num));

  Tensor range_dataset_tensor;
  DataTypeVector output_types = DataTypeVector({DT_INT64});
  std::vector<PartialTensorShape> output_shapes =
      std::vector<PartialTensorShape>{PartialTensorShape({})};
  Tensor start = CreateTensor<int64>(TensorShape({}), {-3});
  Tensor stop = CreateTensor<int64>(TensorShape({}), {3});
  Tensor step = CreateTensor<int64>(TensorShape({}), {1});
  TF_ASSERT_OK(MakeRangeDataset(start, stop, step, output_types, output_shapes,
                                &range_dataset_tensor));

  Tensor take_dataset_tensor;
  int count = -3;
  TF_ASSERT_OK(MakeTakeDataset(range_dataset_tensor, count, output_types,
                               output_shapes, &take_dataset_tensor));

  std::unique_ptr<OpKernel> optimize_dataset_kernel;
  TF_ASSERT_OK(CreateOptimizeDatasetOpKernel(output_types, output_shapes,
                                             /*optimization_configs*/ {},
                                             &optimize_dataset_kernel));
  Tensor optimizations =
      CreateTensor<string>(TensorShape({1}), {"noop_elimination"});
  gtl::InlinedVector<TensorValue, 4> inputs(
      {&take_dataset_tensor, &optimizations});
  std::unique_ptr<OpKernelContext> optimize_dataset_context;
  TF_ASSERT_OK(CreateOptimizeDatasetContext(
      optimize_dataset_kernel.get(), &inputs, &optimize_dataset_context));

  DatasetBase* optimize_dataset;
  TF_ASSERT_OK(CreateDataset(optimize_dataset_kernel.get(),
                             optimize_dataset_context.get(),
                             &optimize_dataset));
  core::ScopedUnref scoped_unref(optimize_dataset);

  std::unique_ptr<IteratorContext> iterator_context;
  TF_ASSERT_OK(
      CreateIteratorContext(optimize_dataset_context.get(), &iterator_context));
  std::unique_ptr<IteratorBase> iterator;
  TF_ASSERT_OK(optimize_dataset->MakeIterator(iterator_context.get(),
                                              "Iterator", &iterator));

  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  while (!end_of_sequence) {
    std::vector<Tensor> next;
    TF_EXPECT_OK(
        iterator->GetNext(iterator_context.get(), &next, &end_of_sequence));
    out_tensors.insert(out_tensors.end(), next.begin(), next.end());
  }

  std::vector<Tensor> expected_outputs = {
      CreateTensor<int64>(TensorShape({}), {-3}),
      CreateTensor<int64>(TensorShape({}), {-2}),
      CreateTensor<int64>(TensorShape({}), {-1}),
      CreateTensor<int64>(TensorShape({}), {0}),
      CreateTensor<int64>(TensorShape({}), {1}),
      CreateTensor<int64>(TensorShape({}), {2})};
  TF_EXPECT_OK(ExpectEqual(out_tensors, expected_outputs,
                           /*compare_order*/ true));
}

}  // namespace
}  // namespace data
}  // namespace tensorflow
<commit_msg>Add a missing return status and make TensorValue constructor explicit<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/kernels/data/dataset_test_base.h"

namespace tensorflow {
namespace data {
namespace {

constexpr char kNodeName[] = "optimize_dataset";
constexpr char kOpName[] = "OptimizeDataset";

class OptimizeDatasetOpTest : public DatasetOpsTestBase {
 protected:
  // Creates a new `OptimizeDataset` op kernel.
  Status CreateOptimizeDatasetOpKernel(
      const DataTypeVector& output_types,
      const std::vector<PartialTensorShape>& output_shapes,
      const std::vector<string>& optimization_configs,
      std::unique_ptr<OpKernel>* optimize_dataset_op_kernel) {
    NodeDef node_def = test::function::NDef(
        kNodeName, kOpName, {"input_dataset", "optimizations"},
        {{"output_types", output_types},
         {"output_shapes", output_shapes},
         {"optimization_configs", optimization_configs}});
    TF_RETURN_IF_ERROR(CreateOpKernel(node_def, optimize_dataset_op_kernel));
    return Status::OK();
  }

  // Create a new `OptimizeDataset` op kernel context.
  Status CreateOptimizeDatasetContext(
      OpKernel* const op_kernel,
      gtl::InlinedVector<TensorValue, 4>* const inputs,
      std::unique_ptr<OpKernelContext>* context) {
    TF_RETURN_IF_ERROR(CheckOpKernelInput(*op_kernel, *inputs));
    TF_RETURN_IF_ERROR(CreateOpKernelContext(op_kernel, inputs, context));
    return Status::OK();
  }

  // Create a `RangeDataset` dataset as a variant tensor.
  Status MakeRangeDataset(const Tensor& start, const Tensor& stop,
                          const Tensor& step,
                          const DataTypeVector& output_types,
                          const std::vector<PartialTensorShape>& output_shapes,
                          Tensor* range_dataset) {
    GraphConstructorOptions graph_opts;
    graph_opts.allow_internal_ops = true;
    graph_opts.expect_device_spec = false;
    TF_RETURN_IF_ERROR(RunFunction(
        test::function::MakeRangeDataset(),
        /*attrs*/
        {{"output_types", output_types}, {"output_shapes", output_shapes}},
        /*inputs*/ {start, stop, step}, graph_opts,
        /*rets*/ {range_dataset}));
    return Status::OK();
  }

  // Create a `TakeDataset` dataset as a variant tensor.
  Status MakeTakeDataset(const Tensor& input_dataset, int64 count,
                         const DataTypeVector& output_types,
                         const std::vector<PartialTensorShape>& output_shapes,
                         Tensor* take_dataset) {
    GraphConstructorOptions graph_opts;
    graph_opts.allow_internal_ops = true;
    graph_opts.expect_device_spec = false;

    Tensor count_tensor = CreateTensor<int64>(TensorShape({}), {count});
    TF_RETURN_IF_ERROR(RunFunction(
        test::function::MakeTakeDataset(),
        /*attrs*/
        {{"output_types", output_types}, {"output_shapes", output_shapes}},
        /*inputs*/ {input_dataset, count_tensor}, graph_opts,
        /*rets*/ {take_dataset}));
    return Status::OK();
  }
};

TEST_F(OptimizeDatasetOpTest, NoopElimination) {
  int thread_num = 2, cpu_num = 2;
  TF_ASSERT_OK(InitThreadPool(thread_num));
  TF_ASSERT_OK(InitFunctionLibraryRuntime({}, cpu_num));

  Tensor range_dataset_tensor;
  DataTypeVector output_types = DataTypeVector({DT_INT64});
  std::vector<PartialTensorShape> output_shapes =
      std::vector<PartialTensorShape>{PartialTensorShape({})};
  Tensor start = CreateTensor<int64>(TensorShape({}), {-3});
  Tensor stop = CreateTensor<int64>(TensorShape({}), {3});
  Tensor step = CreateTensor<int64>(TensorShape({}), {1});
  TF_ASSERT_OK(MakeRangeDataset(start, stop, step, output_types, output_shapes,
                                &range_dataset_tensor));

  Tensor take_dataset_tensor;
  int count = -3;
  TF_ASSERT_OK(MakeTakeDataset(range_dataset_tensor, count, output_types,
                               output_shapes, &take_dataset_tensor));

  std::unique_ptr<OpKernel> optimize_dataset_kernel;
  TF_ASSERT_OK(CreateOptimizeDatasetOpKernel(output_types, output_shapes,
                                             /*optimization_configs*/ {},
                                             &optimize_dataset_kernel));
  Tensor optimizations =
      CreateTensor<string>(TensorShape({1}), {"noop_elimination"});
  gtl::InlinedVector<TensorValue, 4> inputs(
      {TensorValue(&take_dataset_tensor), TensorValue(&optimizations)});
  std::unique_ptr<OpKernelContext> optimize_dataset_context;
  TF_ASSERT_OK(CreateOptimizeDatasetContext(
      optimize_dataset_kernel.get(), &inputs, &optimize_dataset_context));

  DatasetBase* optimize_dataset;
  TF_ASSERT_OK(CreateDataset(optimize_dataset_kernel.get(),
                             optimize_dataset_context.get(),
                             &optimize_dataset));
  core::ScopedUnref scoped_unref(optimize_dataset);

  std::unique_ptr<IteratorContext> iterator_context;
  TF_ASSERT_OK(
      CreateIteratorContext(optimize_dataset_context.get(), &iterator_context));
  std::unique_ptr<IteratorBase> iterator;
  TF_ASSERT_OK(optimize_dataset->MakeIterator(iterator_context.get(),
                                              "Iterator", &iterator));

  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  while (!end_of_sequence) {
    std::vector<Tensor> next;
    TF_EXPECT_OK(
        iterator->GetNext(iterator_context.get(), &next, &end_of_sequence));
    out_tensors.insert(out_tensors.end(), next.begin(), next.end());
  }

  std::vector<Tensor> expected_outputs = {
      CreateTensor<int64>(TensorShape({}), {-3}),
      CreateTensor<int64>(TensorShape({}), {-2}),
      CreateTensor<int64>(TensorShape({}), {-1}),
      CreateTensor<int64>(TensorShape({}), {0}),
      CreateTensor<int64>(TensorShape({}), {1}),
      CreateTensor<int64>(TensorShape({}), {2})};
  TF_EXPECT_OK(ExpectEqual(out_tensors, expected_outputs,
                           /*compare_order*/ true));
}

}  // namespace
}  // namespace data
}  // namespace tensorflow
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_SECURE_HASH_STD_HPP_
#define _SNARKFRONT_SECURE_HASH_STD_HPP_

#include <cassert>
#include <cstdint>
#include <ostream>
#include <string>
#include "DataBuffer.hpp"

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// FIPS PUB 180-4, NIST March 2012
//
// Algorithm     Message Size   Block Size   Word Size   Message Digest
//               (bits)         (bits)       (bits)      Size (bits)
// SHA-1         < 2^64         512          32          160
// SHA-224       < 2^64         512          32          224
// SHA-256       < 2^64         512          32          256
// SHA-384       < 2^128        1024         64          384
// SHA-512       < 2^128        1024         64          512
// SHA-512/224   < 2^128        1024         64          224
// SHA-512/256   < 2^128        1024         64          256
//

enum class SHA_BlockSize {
    BLOCK_512, // for: SHA-1, SHA-224, SHA-256
    BLOCK_1024 // for: SHA-384, SHA-512, SHA-512/224, SHA-512/256
};

template <typename CRTP, SHA_BlockSize BLK, typename MSG>
class SHA_Base
{
public:
    virtual ~SHA_Base() = default;

    static void padMessage(DataBuffer<ClearText>& buf) {
        const std::size_t msgLengthBits = buf->sizeBits();

        buf.push8(0x80); // append bit "1" to end of the message

        // keep padding zero bits to the length block at the end
        const size_t stopPadBits = blockSizeBits() - 2 * wordSizeBits();
        while (stopPadBits != buf->sizeBits() % blockSizeBits()) {
            buf.push8(0x00);
        }

        // append length of message
        // (message size is limited to < 2^64 bits in this implementation)
        if (SHA_BlockSize::BLOCK_1024 == BLK) {
            buf.push64(0);
        }
        buf.push64(msgLengthBits);
    }

    static void padMessage(DataBufferStream& buf) {
        padMessage(*buf);
    }

    static bool padNeeded(const DataBuffer<ClearText>& buf) {
        // non-empty message must be even number of message input blocks
        return buf->empty() || 0 != buf->sizeBits() % blockSizeBits();
    }

    static bool padNeeded(DataBufferStream& buf) {
        return padNeeded(*buf);
    }

    // append (possibly lazy) word to message
    template <typename T>
    void msgInput(const T& a) {
        m_message.emplace_back(a);
    }

    // append array of words to message
    template <typename T, std::size_t N>
    void msgInput(const std::array<T, N>& a) {
        for (const auto& b : a)
            msgInput(b);
    }

    void clearMessage() {
        m_message.clear();
    }

    void computeHash() {
#ifdef USE_ASSERT
        assert(inputOK());
#endif

        auto* ptr = static_cast<CRTP*>(this);

        ptr->initHashValue();

        std::size_t msgIndex = 0;
        while (msgIndex < m_message.size()) {
            ptr->prepMsgSchedule(msgIndex);
            ptr->initWorkingVars();
            ptr->workingLoop();
            ptr->updateHash();
        }

        ptr->afterHash();
    }

protected:
    SHA_Base() = default;

    // note: reference not const so assignment can unbox laziness
    MSG& msgWord(std::size_t& index) {
        return m_message[index++];
    }

private:
    static std::size_t blockSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 512;
        case (SHA_BlockSize::BLOCK_1024) : return 1024;
        }
    }

    static std::size_t wordSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 32;
        case (SHA_BlockSize::BLOCK_1024) : return 64;
        }
    }

    bool inputOK() const {
        // non-empty message must be even number of message input blocks
        const std::size_t msgSizeBits = m_message.size() * wordSizeBits();
        return !m_message.empty() && 0 == msgSizeBits % blockSizeBits();
    }

    std::vector<MSG> m_message;
};

////////////////////////////////////////////////////////////////////////////////
// SHA common functions
//

template <typename T, typename U, typename BITWISE>
class SHA_Functions : public BITWISE
{
public:
    static U Ch(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_AND(x, y),
                BITWISE::_AND(BITWISE::_CMPLMNT(x), z));
    }

    static U Parity(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(x, y),
                z);
    }

    static U Maj(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_AND(x, y),
                    BITWISE::_AND(x, z)),
                BITWISE::_AND(y, z));
    }

    static U f(const T& x, const T& y, const T& z, const std::size_t round) {
        if (round < 20) {
            return Ch(x, y, z);
        } else if (round < 40) {
            return Parity(x, y, z);
        } else if (round < 60) {
            return Maj(x, y, z);
        } else {
            return Parity(x, y, z);
        }
    }

    static U SIGMA_256_0(const T& x) { return SIGMA(x, 2, 13, 22); }
    static U SIGMA_256_1(const T& x) { return SIGMA(x, 6, 11, 25); }
    static U sigma_256_0(const T& x) { return sigma(x, 7, 18, 3); }
    static U sigma_256_1(const T& x) { return sigma(x, 17, 19, 10); }
    static U SIGMA_512_0(const T& x) { return SIGMA(x, 28, 34, 39); }
    static U SIGMA_512_1(const T& x) { return SIGMA(x, 14, 18, 41); }
    static U sigma_512_0(const T& x) { return sigma(x, 1, 8, 7); }
    static U sigma_512_1(const T& x) { return sigma(x, 19, 61, 6); }

private:
    static U SIGMA(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_ROTR(x, c));
    }

    static U sigma(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_SHR(x, c));
    }
};

} // namespace snarkfront

#endif
<commit_msg>scope header file paths<commit_after>#ifndef _SNARKFRONT_SECURE_HASH_STD_HPP_
#define _SNARKFRONT_SECURE_HASH_STD_HPP_

#include <cassert>
#include <cstdint>
#include <ostream>
#include <string>

#include <snarkfront/DataBuffer.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// FIPS PUB 180-4, NIST March 2012
//
// Algorithm     Message Size   Block Size   Word Size   Message Digest
//               (bits)         (bits)       (bits)      Size (bits)
// SHA-1         < 2^64         512          32          160
// SHA-224       < 2^64         512          32          224
// SHA-256       < 2^64         512          32          256
// SHA-384       < 2^128        1024         64          384
// SHA-512       < 2^128        1024         64          512
// SHA-512/224   < 2^128        1024         64          224
// SHA-512/256   < 2^128        1024         64          256
//

enum class SHA_BlockSize {
    BLOCK_512, // for: SHA-1, SHA-224, SHA-256
    BLOCK_1024 // for: SHA-384, SHA-512, SHA-512/224, SHA-512/256
};

template <typename CRTP, SHA_BlockSize BLK, typename MSG>
class SHA_Base
{
public:
    virtual ~SHA_Base() = default;

    static void padMessage(DataBuffer<ClearText>& buf) {
        const std::size_t msgLengthBits = buf->sizeBits();

        buf.push8(0x80); // append bit "1" to end of the message

        // keep padding zero bits to the length block at the end
        const size_t stopPadBits = blockSizeBits() - 2 * wordSizeBits();
        while (stopPadBits != buf->sizeBits() % blockSizeBits()) {
            buf.push8(0x00);
        }

        // append length of message
        // (message size is limited to < 2^64 bits in this implementation)
        if (SHA_BlockSize::BLOCK_1024 == BLK) {
            buf.push64(0);
        }
        buf.push64(msgLengthBits);
    }

    static void padMessage(DataBufferStream& buf) {
        padMessage(*buf);
    }

    static bool padNeeded(const DataBuffer<ClearText>& buf) {
        // non-empty message must be even number of message input blocks
        return buf->empty() || 0 != buf->sizeBits() % blockSizeBits();
    }

    static bool padNeeded(DataBufferStream& buf) {
        return padNeeded(*buf);
    }

    // append (possibly lazy) word to message
    template <typename T>
    void msgInput(const T& a) {
        m_message.emplace_back(a);
    }

    // append array of words to message
    template <typename T, std::size_t N>
    void msgInput(const std::array<T, N>& a) {
        for (const auto& b : a)
            msgInput(b);
    }

    void clearMessage() {
        m_message.clear();
    }

    void computeHash() {
#ifdef USE_ASSERT
        assert(inputOK());
#endif

        auto* ptr = static_cast<CRTP*>(this);

        ptr->initHashValue();

        std::size_t msgIndex = 0;
        while (msgIndex < m_message.size()) {
            ptr->prepMsgSchedule(msgIndex);
            ptr->initWorkingVars();
            ptr->workingLoop();
            ptr->updateHash();
        }

        ptr->afterHash();
    }

protected:
    SHA_Base() = default;

    // note: reference not const so assignment can unbox laziness
    MSG& msgWord(std::size_t& index) {
        return m_message[index++];
    }

private:
    static std::size_t blockSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 512;
        case (SHA_BlockSize::BLOCK_1024) : return 1024;
        }
    }

    static std::size_t wordSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 32;
        case (SHA_BlockSize::BLOCK_1024) : return 64;
        }
    }

    bool inputOK() const {
        // non-empty message must be even number of message input blocks
        const std::size_t msgSizeBits = m_message.size() * wordSizeBits();
        return !m_message.empty() && 0 == msgSizeBits % blockSizeBits();
    }

    std::vector<MSG> m_message;
};

////////////////////////////////////////////////////////////////////////////////
// SHA common functions
//

template <typename T, typename U, typename BITWISE>
class SHA_Functions : public BITWISE
{
public:
    static U Ch(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_AND(x, y),
                BITWISE::_AND(BITWISE::_CMPLMNT(x), z));
    }

    static U Parity(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(x, y),
                z);
    }

    static U Maj(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_AND(x, y),
                    BITWISE::_AND(x, z)),
                BITWISE::_AND(y, z));
    }

    static U f(const T& x, const T& y, const T& z, const std::size_t round) {
        if (round < 20) {
            return Ch(x, y, z);
        } else if (round < 40) {
            return Parity(x, y, z);
        } else if (round < 60) {
            return Maj(x, y, z);
        } else {
            return Parity(x, y, z);
        }
    }

    static U SIGMA_256_0(const T& x) { return SIGMA(x, 2, 13, 22); }
    static U SIGMA_256_1(const T& x) { return SIGMA(x, 6, 11, 25); }
    static U sigma_256_0(const T& x) { return sigma(x, 7, 18, 3); }
    static U sigma_256_1(const T& x) { return sigma(x, 17, 19, 10); }
    static U SIGMA_512_0(const T& x) { return SIGMA(x, 28, 34, 39); }
    static U SIGMA_512_1(const T& x) { return SIGMA(x, 14, 18, 41); }
    static U sigma_512_0(const T& x) { return sigma(x, 1, 8, 7); }
    static U sigma_512_1(const T& x) { return sigma(x, 19, 61, 6); }

private:
    static U SIGMA(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_ROTR(x, c));
    }

    static U sigma(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_SHR(x, c));
    }
};

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>// Copyright 2013 Yangqing Jia

#include <cmath>
#include <cstring>
#include <cuda_runtime.h>

#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;

template <typename Dtype>
class SoftmaxLayerTest : public ::testing::Test {
 protected:
  SoftmaxLayerTest()
      : blob_bottom_(new Blob<Dtype>(2, 10, 1, 1)),
        blob_top_(new Blob<Dtype>()) {
    // fill the values
    FillerParameter filler_param;
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_);
    blob_bottom_vec_.push_back(blob_bottom_);
    blob_top_vec_.push_back(blob_top_);
  };
  virtual ~SoftmaxLayerTest() { delete blob_bottom_; delete blob_top_; }
  Blob<Dtype>* const blob_bottom_;
  Blob<Dtype>* const blob_top_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

typedef ::testing::Types<float, double> Dtypes;
TYPED_TEST_CASE(SoftmaxLayerTest, Dtypes);

TYPED_TEST(SoftmaxLayerTest, TestForwardCPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  SoftmaxLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
  layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
  for (int i = 0; i < this->blob_bottom_->num(); ++i) {
    TypeParam scale = 0;
    for (int j = 0; j < this->blob_bottom_->channels(); ++j) {
      scale += exp(this->blob_bottom_->data_at(i, j, 0, 0));
    }
    for (int j = 0; j < this->blob_bottom_->channels(); ++j) {
      EXPECT_GE(this->blob_top_->data_at(i, j, 0, 0) + 1e-4,
          exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale)
          << "debug: " << i << " " << j;
      EXPECT_LE(this->blob_top_->data_at(i, j, 0, 0) - 1e-4,
          exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale)
          << "debug: " << i << " " << j;
    }
  }
}

TYPED_TEST(SoftmaxLayerTest, TestGradientCPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  SoftmaxLayer<TypeParam> layer(layer_param);
  GradientChecker<TypeParam> checker(1e-2, 1e-3);
  checker.CheckGradientExhaustive(layer, this->blob_bottom_vec_, this->blob_top_vec_);
}

}
<commit_msg>softmax test<commit_after>// Copyright 2013 Yangqing Jia

#include <cmath>
#include <cstring>
#include <cuda_runtime.h>

#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;

template <typename Dtype>
class SoftmaxLayerTest : public ::testing::Test {
 protected:
  SoftmaxLayerTest()
      : blob_bottom_(new Blob<Dtype>(2, 10, 1, 1)),
        blob_top_(new Blob<Dtype>()) {
    // fill the values
    FillerParameter filler_param;
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_);
    blob_bottom_vec_.push_back(blob_bottom_);
    blob_top_vec_.push_back(blob_top_);
  };
  virtual ~SoftmaxLayerTest() { delete blob_bottom_; delete blob_top_; }
  Blob<Dtype>* const blob_bottom_;
  Blob<Dtype>* const blob_top_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

typedef ::testing::Types<float, double> Dtypes;
TYPED_TEST_CASE(SoftmaxLayerTest, Dtypes);

TYPED_TEST(SoftmaxLayerTest, TestForwardCPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  SoftmaxLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
  layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
  // Test sum
  for (int i = 0; i < this->blob_bottom_->num(); ++i) {
    TypeParam sum = 0;
    for (int j = 0; j < this->blob_top_->channels(); ++j) {
      sum += this->blob_top_->data_at(i, j, 0, 0);
    }
    EXPECT_GE(sum, 0.999);
    EXPECT_LE(sum, 1.001);
  }
  // Test exact values
  for (int i = 0; i < this->blob_bottom_->num(); ++i) {
    TypeParam scale = 0;
    for (int j = 0; j < this->blob_bottom_->channels(); ++j) {
      scale += exp(this->blob_bottom_->data_at(i, j, 0, 0));
    }
    for (int j = 0; j < this->blob_bottom_->channels(); ++j) {
      EXPECT_GE(this->blob_top_->data_at(i, j, 0, 0) + 1e-4,
          exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale)
          << "debug: " << i << " " << j;
      EXPECT_LE(this->blob_top_->data_at(i, j, 0, 0) - 1e-4,
          exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale)
          << "debug: " << i << " " << j;
    }
  }
}

TYPED_TEST(SoftmaxLayerTest, TestGradientCPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  SoftmaxLayer<TypeParam> layer(layer_param);
  GradientChecker<TypeParam> checker(1e-2, 1e-3);
  checker.CheckGradientExhaustive(layer, this->blob_bottom_vec_, this->blob_top_vec_);
}

}
<|endoftext|>


<commit_before>#include <cmd_hints_handler.h>
#include <QJsonArray>

CmdHintsHandler::CmdHintsHandler(){
	m_vInputs.push_back(CmdInputDef("questid").required().integer_().description("Quest id"));
}

QString CmdHintsHandler::cmd(){
	return "hints";
}

bool CmdHintsHandler::accessUnauthorized(){
	return true;
}

bool CmdHintsHandler::accessUser(){
	return true;
}

bool CmdHintsHandler::accessTester(){
	return true;
}

bool CmdHintsHandler::accessAdmin(){
	return true;
}

const QVector<CmdInputDef> &CmdHintsHandler::inputs(){
	return m_vInputs;
};

QString CmdHintsHandler::description(){
	return "Output: list of hints, Input: questid";
}

QStringList CmdHintsHandler::errors(){
	QStringList	list;
	return list;
}

void CmdHintsHandler::handle(QWebSocket *pClient, IWebSocketServer *pWebSocketServer, QString m, QJsonObject obj){
	IUserToken *pUserToken = pWebSocketServer->getUserToken(pClient);

	if(pUserToken == NULL){
		pWebSocketServer->sendMessageError(pClient, cmd(), m, Errors::NotAuthorizedRequest());
		return;
	}

	int questid = obj["questid"].toInt();
	if(questid == 0){
		pWebSocketServer->sendMessageError(pClient, cmd(), m, Errors::QuestIDMustBeNotZero());
		return;
	}

	QJsonArray hints;
	QSqlDatabase db = *(pWebSocketServer->database());
	QSqlQuery query(db);
	query.prepare("SELECT * FROM quests_hints WHERE questid = :questid");
	query.bindValue(":questid", questid);
	query.exec();
	while (query.next()) {
		QSqlRecord record = query.record();
		int hintid = record.value("id").toInt();
		int questid2 = record.value("questid").toInt();
		QString text = record.value("text").toString();
		QString dt = record.value("dt").toString();
		QJsonObject hint;
		hint["hintid"] = hintid;
		hint["questid"] = questid2;
		hint["text"] = text;
		hint["dt"] = dt;
		hints.push_back(hint);
	}

	QJsonObject jsonData;
	jsonData["cmd"] = QJsonValue(cmd());
	jsonData["result"] = QJsonValue("DONE");
	jsonData["m"] = QJsonValue(m);
	jsonData["data"] = hints;
	pWebSocketServer->sendMessage(pClient, jsonData);
}
<commit_msg>Fixed hints handler<commit_after>#include <cmd_hints_handler.h>
#include <QJsonArray>

CmdHintsHandler::CmdHintsHandler(){
	m_vInputs.push_back(CmdInputDef("questid").required().integer_().description("Quest id"));
}

QString CmdHintsHandler::cmd(){
	return "hints";
}

bool CmdHintsHandler::accessUnauthorized(){
	return true;
}

bool CmdHintsHandler::accessUser(){
	return true;
}

bool CmdHintsHandler::accessTester(){
	return true;
}

bool CmdHintsHandler::accessAdmin(){
	return true;
}

const QVector<CmdInputDef> &CmdHintsHandler::inputs(){
	return m_vInputs;
};

QString CmdHintsHandler::description(){
	return "Output: list of hints, Input: questid";
}

QStringList CmdHintsHandler::errors(){
	QStringList	list;
	return list;
}

void CmdHintsHandler::handle(QWebSocket *pClient, IWebSocketServer *pWebSocketServer, QString m, QJsonObject obj){
	IUserToken *pUserToken = pWebSocketServer->getUserToken(pClient);

	if(pUserToken == NULL){
		pWebSocketServer->sendMessageError(pClient, cmd(), m, Errors::NotAuthorizedRequest());
		return;
	}

	int questid = obj["questid"].toInt();
	if(questid == 0){
		pWebSocketServer->sendMessageError(pClient, cmd(), m, Errors::QuestIDMustBeNotZero());
		return;
	}

	QJsonArray hints;
	QSqlDatabase db = *(pWebSocketServer->database());
	QSqlQuery query(db);
	query.prepare("SELECT * FROM quests_hints WHERE questid = :questid");
	query.bindValue(":questid", questid);
	query.exec();
	while (query.next()) {
		QSqlRecord record = query.record();
		int hintid = record.value("id").toInt();
		int questid2 = record.value("questid").toInt();
		QString text = record.value("text").toString();
		QString dt = record.value("dt").toString();
		QJsonObject hint;
        hint["id"] = hintid;
		hint["questid"] = questid2;
		hint["text"] = text;
		hint["dt"] = dt;
		hints.push_back(hint);
	}

	QJsonObject jsonData;
	jsonData["cmd"] = QJsonValue(cmd());
	jsonData["result"] = QJsonValue("DONE");
	jsonData["m"] = QJsonValue(m);
	jsonData["data"] = hints;
	pWebSocketServer->sendMessage(pClient, jsonData);
}
<|endoftext|>


<commit_before>#include "pixelboost/debug/assert.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/message/update.h"
#include "pixelboost/logic/scene.h"
#include "pixelboost/logic/system.h"

using namespace pb;

Scene::Scene()
{
    _NextFreeUid = (1<<24) + 1;
}

Scene::~Scene()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        delete it->second;
    }

    for (DelayedMessageList::iterator it = _DelayedMessages.begin(); it != _DelayedMessages.end(); ++it)
    {
        delete it->second.second;
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        delete it->second;
    }
}

void Scene::Update(float time)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end();)
    {
        if (it->second->GetState() == Entity::kEntityDestroyed)
        {
            delete it->second;
            _Entities.erase(it++);
        } else {
            ++it;
        }
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
#ifndef PIXELBOOST_DISABLE_DEBUG
        PbAssert(_Entities.find(it->first) == _Entities.end());
#endif
        _Entities[it->first] = it->second;
    }
    _NewEntities.clear();

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Update(this, time);
    }

    for (DelayedMessageList::iterator it = _DelayedMessages.begin(); it != _DelayedMessages.end();)
    {
        it->first -= time;

        if (it->first < 0)
        {
            if (it->second.first == 0)
            {
                BroadcastMessage(*it->second.second);
            } else {
                SendMessage(it->second.first, *it->second.second);
            }
            delete it->second.second;
            it = _DelayedMessages.erase(it);
        } else {
            ++it;
        }
    }

    UpdateMessage message(time);

    BroadcastMessage(message);
}

void Scene::Render(Viewport* viewport)
{
    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Render(this, viewport);
    }
}

bool Scene::AddSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
        return false;

    _Systems[system->GetType()] = system;

    return true;
}

void Scene::RemoveSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
    {
        _Systems.erase(it);
    }
}

pb::Uid Scene::GenerateEntityId()
{
    return _NextFreeUid++;
}

void Scene::AddEntity(Entity* entity)
{
#ifndef PIXELBOOST_DISABLE_DEBUG
    PbAssert(_NewEntities.find(entity->GetUid()) == _NewEntities.end());
#endif
    _NewEntities[entity->GetUid()] = entity;
}

void Scene::DestroyEntity(Entity* entity)
{
    entity->Destroy();
}

void Scene::DestroyAllEntities()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        it->second->Destroy();
    }
}

Entity* Scene::GetEntityById(Uid uid)
{
    EntityMap::iterator it = _Entities.find(uid);

    if (it != _Entities.end())
        return it->second;

    it = _NewEntities.find(uid);

    if (it != _NewEntities.end())
        return it->second;

    return 0;
}

void Scene::BroadcastMessage(const Message& message)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        if (it->second->GetState() != Entity::kEntityDestroyed)
            it->second->HandleMessage(message);
    }
}

void Scene::SendMessage(Uid uid, const Message& message)
{
    Entity* entity = GetEntityById(uid);

    if (entity && entity->GetState() != Entity::kEntityDestroyed)
        entity->HandleMessage(message);
}

void Scene::BroadcastDelayedMessage(float delay, const Message* message)
{
    _DelayedMessages.push_back(std::pair<float, DelayedMessage>(delay, DelayedMessage(0, message)));
}

void Scene::SendDelayedMessage(Uid uid, float delay, const Message* message)
{
    _DelayedMessages.push_back(std::pair<float, DelayedMessage>(delay, DelayedMessage(uid, message)));
}
<commit_msg>Send messages to scene systems<commit_after>#include "pixelboost/debug/assert.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/message/update.h"
#include "pixelboost/logic/scene.h"
#include "pixelboost/logic/system.h"

using namespace pb;

Scene::Scene()
{
    _NextFreeUid = (1<<24) + 1;
}

Scene::~Scene()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        delete it->second;
    }

    for (DelayedMessageList::iterator it = _DelayedMessages.begin(); it != _DelayedMessages.end(); ++it)
    {
        delete it->second.second;
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        delete it->second;
    }
}

void Scene::Update(float time)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end();)
    {
        if (it->second->GetState() == Entity::kEntityDestroyed)
        {
            delete it->second;
            _Entities.erase(it++);
        } else {
            ++it;
        }
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
#ifndef PIXELBOOST_DISABLE_DEBUG
        PbAssert(_Entities.find(it->first) == _Entities.end());
#endif
        _Entities[it->first] = it->second;
    }
    _NewEntities.clear();

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Update(this, time);
    }

    for (DelayedMessageList::iterator it = _DelayedMessages.begin(); it != _DelayedMessages.end();)
    {
        it->first -= time;

        if (it->first < 0)
        {
            if (it->second.first == 0)
            {
                BroadcastMessage(*it->second.second);
            } else {
                SendMessage(it->second.first, *it->second.second);
            }
            delete it->second.second;
            it = _DelayedMessages.erase(it);
        } else {
            ++it;
        }
    }

    UpdateMessage message(time);

    BroadcastMessage(message);
}

void Scene::Render(Viewport* viewport)
{
    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Render(this, viewport);
    }
}

bool Scene::AddSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
        return false;

    _Systems[system->GetType()] = system;

    return true;
}

void Scene::RemoveSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
    {
        _Systems.erase(it);
    }
}

pb::Uid Scene::GenerateEntityId()
{
    return _NextFreeUid++;
}

void Scene::AddEntity(Entity* entity)
{
#ifndef PIXELBOOST_DISABLE_DEBUG
    PbAssert(_NewEntities.find(entity->GetUid()) == _NewEntities.end());
#endif
    _NewEntities[entity->GetUid()] = entity;
}

void Scene::DestroyEntity(Entity* entity)
{
    entity->Destroy();
}

void Scene::DestroyAllEntities()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        it->second->Destroy();
    }
}

Entity* Scene::GetEntityById(Uid uid)
{
    EntityMap::iterator it = _Entities.find(uid);

    if (it != _Entities.end())
        return it->second;

    it = _NewEntities.find(uid);

    if (it != _NewEntities.end())
        return it->second;

    return 0;
}

void Scene::BroadcastMessage(const Message& message)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        if (it->second->GetState() != Entity::kEntityDestroyed)
            it->second->HandleMessage(message);
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->HandleMessage(this, message);
    }
}

void Scene::SendMessage(Uid uid, const Message& message)
{
    Entity* entity = GetEntityById(uid);

    if (entity && entity->GetState() != Entity::kEntityDestroyed)
        entity->HandleMessage(message);
}

void Scene::BroadcastDelayedMessage(float delay, const Message* message)
{
    _DelayedMessages.push_back(std::pair<float, DelayedMessage>(delay, DelayedMessage(0, message)));
}

void Scene::SendDelayedMessage(Uid uid, float delay, const Message* message)
{
    _DelayedMessages.push_back(std::pair<float, DelayedMessage>(delay, DelayedMessage(uid, message)));
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <SurgSim/Framework/Assert.h>

#include <SurgSim/Physics/Fem3DRepresentation.h>

namespace
{
	void transformVectorByBlockOf3(const SurgSim::Math::RigidTransform3d& transform,
										  Vector* x, bool rotationOnly = false)
	{
		unsigned int numNodes = x->size() / 3;
		SURGSIM_ASSERT(static_cast<int>(numNodes * 3) == x->size()) <<
			"Unexpected number of dof in a Fem3D state vector (not a multiple of 3)";

		for (unsigned int nodeId = 0; nodeId < numNodes; nodeId++)
		{
			SurgSim::Math::Vector3d xi = SurgSim::Math::getSubVector(*x, nodeId, 3);
			SurgSim::Math::Vector3d xiTransformed;
			if (rotationOnly)
			{
				xiTransformed = transform.linear() * xi;
			}
			else
			{
				xiTransformed = transform * xi;
			}
			SurgSim::Math::setSubVector(xiTransformed, nodeId, 3, x);
		}
	}
}

namespace SurgSim
{

namespace Physics
{

Fem3DRepresentation::Fem3DRepresentation(const std::string& name) :
	FemRepresentation(name)
{
	// Reminder: m_numDofPerNode is held by DeformableRepresentation
	// but needs to be set by all concrete derived classes
	m_numDofPerNode = 3;
}

Fem3DRepresentation::~Fem3DRepresentation()
{
}

RepresentationType Fem3DRepresentation::getType() const
{
	return REPRESENTATION_TYPE_FEM3D;
}

void Fem3DRepresentation::transformState(std::shared_ptr<DeformableRepresentationState> state,
	const SurgSim::Math::RigidTransform3d& transform)
{
	transformVectorByBlockOf3(transform, &state->getPositions());
	transformVectorByBlockOf3(transform, &state->getVelocities(), true);
	transformVectorByBlockOf3(transform, &state->getAccelerations(), true);
}

} // namespace Physics

} // namespace SurgSim
<commit_msg>Fem3DRep: Fix namespace indentation + use proper Vector::Index type<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <SurgSim/Framework/Assert.h>

#include <SurgSim/Physics/Fem3DRepresentation.h>

namespace
{
void transformVectorByBlockOf3(const SurgSim::Math::RigidTransform3d& transform,
										Vector* x, bool rotationOnly = false)
{
	typedef Vector::Index IndexType;

	IndexType numNodes = x->size() / 3;
	SURGSIM_ASSERT(numNodes * 3 == x->size()) <<
		"Unexpected number of dof in a Fem3D state vector (not a multiple of 3)";

	for (IndexType nodeId = 0; nodeId < numNodes; nodeId++)
	{
		SurgSim::Math::Vector3d xi = SurgSim::Math::getSubVector(*x, nodeId, 3);
		SurgSim::Math::Vector3d xiTransformed;
		if (rotationOnly)
		{
			xiTransformed = transform.linear() * xi;
		}
		else
		{
			xiTransformed = transform * xi;
		}
		SurgSim::Math::setSubVector(xiTransformed, nodeId, 3, x);
	}
}
}

namespace SurgSim
{

namespace Physics
{

Fem3DRepresentation::Fem3DRepresentation(const std::string& name) :
	FemRepresentation(name)
{
	// Reminder: m_numDofPerNode is held by DeformableRepresentation
	// but needs to be set by all concrete derived classes
	m_numDofPerNode = 3;
}

Fem3DRepresentation::~Fem3DRepresentation()
{
}

RepresentationType Fem3DRepresentation::getType() const
{
	return REPRESENTATION_TYPE_FEM3D;
}

void Fem3DRepresentation::transformState(std::shared_ptr<DeformableRepresentationState> state,
	const SurgSim::Math::RigidTransform3d& transform)
{
	transformVectorByBlockOf3(transform, &state->getPositions());
	transformVectorByBlockOf3(transform, &state->getVelocities(), true);
	transformVectorByBlockOf3(transform, &state->getAccelerations(), true);
}

} // namespace Physics

} // namespace SurgSim
<|endoftext|>


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

/* \author Ioan Sucan */

#include "ompl/extension/kinematic/extension/kpiece/KPIECE1.h"
#include <ros/console.h>

bool ompl::kinematic::KPIECE1::solve(double solveTime)
{
    SpaceInformationKinematic *si = dynamic_cast<SpaceInformationKinematic*>(m_si);
    base::GoalRegion      *goal_r = dynamic_cast<base::GoalRegion*>(si->getGoal());
    GoalRegionKinematic   *goal_k = dynamic_cast<GoalRegionKinematic*>(si->getGoal());
    base::GoalState       *goal_s = dynamic_cast<base::GoalState*>(si->getGoal());
    unsigned int              dim = si->getStateDimension();

    if (!goal_s && !goal_r)
    {
	ROS_ERROR("KPIECE1: Unknown type of goal (or goal undefined)");
	return false;
    }

    ros::WallTime endTime = ros::WallTime::now() + ros::WallDuration(solveTime);

    if (m_tree.grid.size() == 0)
    {
	for (unsigned int i = 0 ; i < m_si->getStartStateCount() ; ++i)
	{
	    Motion *motion = new Motion(dim);
	    si->copyState(motion->state, si->getStartState(i));
	    if (si->satisfiesBounds(motion->state) && si->isValid(motion->state))
		addMotion(motion, 1.0);
	    else
	    {
		ROS_ERROR("KPIECE1: Initial state is invalid!");
		delete motion;
	    }
	}
    }

    if (m_tree.grid.size() == 0)
    {
	ROS_ERROR("KPIECE1: There are no valid initial states!");
	return false;
    }

    ROS_INFO("KPIECE1: Starting with %u states", m_tree.size);

    std::vector<double> range(dim);
    for (unsigned int i = 0 ; i < dim ; ++i)
	range[i] = m_rho * (si->getStateComponent(i).maxValue - si->getStateComponent(i).minValue);

    Motion *solution  = NULL;
    Motion *approxsol = NULL;
    double  approxdif = INFINITY;
    base::State *xstate = new base::State(dim);

    double improveValue = 0.01;

    while (ros::WallTime::now() < endTime)
    {
	m_tree.iteration++;

	/* Decide on a state to expand from */
	Motion     *existing = NULL;
	Grid::Cell *ecell = NULL;
	selectMotion(existing, ecell);
	assert(existing);

	/* sample random state (with goal biasing) */
	if (m_rng.uniform(0.0, 1.0) < m_goalBias)
	{
	    if (goal_s)
		si->copyState(xstate, goal_s->state);
	    else
		if (goal_k)
		    goal_k->sampleNearGoal(xstate);
		else
		{
		    if (approxsol)
		    {
			si->copyState(xstate, approxsol->state);
			if (!m_hcik.tryToImprove(xstate, improveValue))
			{
			    m_sCore.sampleNear(xstate, existing->state, range);
			    improveValue /= 2.0;
			}
		    }
		    else
			m_sCore.sampleNear(xstate, existing->state, range);
		}
	}
	else
	    m_sCore.sampleNear(xstate, existing->state, range);

	double failTime = 0.0;
	bool keep = si->checkMotionIncremental(existing->state, xstate, xstate, &failTime);
	if (!keep && failTime > m_minValidPathPercentage)
	    keep = true;

	if (keep)
	{
	    /* create a motion */
	    Motion *motion = new Motion(dim);
	    si->copyState(motion->state, xstate);
	    motion->parent = existing;

	    double dist = 0.0;
	    bool solved = goal_r->isSatisfied(motion->state, &dist);
	    addMotion(motion, dist);

	    if (solved)
	    {
		approxdif = dist;
		solution = motion;
		break;
	    }
	    if (dist < approxdif)
	    {
		approxdif = dist;
		approxsol = motion;
	    }
	    ecell->data->score *= m_goodScoreFactor;
	}
	else
	    ecell->data->score *= m_badScoreFactor;

	m_tree.grid.update(ecell);
    }

    bool approximate = false;
    if (solution == NULL)
    {
	solution = approxsol;
	approximate = true;
    }

    if (solution != NULL)
    {
	/* construct the solution path */
	std::vector<Motion*> mpath;
	while (solution != NULL)
	{
	    mpath.push_back(solution);
	    solution = solution->parent;
	}

	/* set the solution path */
	PathKinematic *path = new PathKinematic(m_si);
   	for (int i = mpath.size() - 1 ; i >= 0 ; --i)
	{
	    base::State *st = new base::State(dim);
	    si->copyState(st, mpath[i]->state);
	    path->states.push_back(st);
	}
	goal_r->setDifference(approxdif);
	goal_r->setSolutionPath(path, approximate);

	if (approximate)
	    ROS_WARN("KPIECE1: Found approximate solution");
    }

    delete xstate;

    ROS_INFO("KPIECE1: Created %u states in %u cells (%u internal + %u external)", m_tree.size, m_tree.grid.size(),
	     m_tree.grid.countInternal(), m_tree.grid.countExternal());

    return goal_r->isAchieved();
}

bool ompl::kinematic::KPIECE1::selectMotion(Motion* &smotion, Grid::Cell* &scell)
{
    scell = m_rng.uniform() < std::max(m_selectBorderPercentage, m_tree.grid.fracExternal()) ?
	m_tree.grid.topExternal() : m_tree.grid.topInternal();
    if (scell && !scell->data->motions.empty())
    {
	scell->data->selections++;
	smotion = scell->data->motions[m_rng.halfNormalInt(0, scell->data->motions.size() - 1)];
	return true;
    }
    else
	return false;
}

unsigned int ompl::kinematic::KPIECE1::addMotion(Motion *motion, double dist)
{
    Grid::Coord coord;
    m_projectionEvaluator->computeCoordinates(motion->state, coord);
    Grid::Cell* cell = m_tree.grid.getCell(coord);
    unsigned int created = 0;
    if (cell)
    {
	cell->data->motions.push_back(motion);
	cell->data->coverage += 1.0;
	m_tree.grid.update(cell);
    }
    else
    {
	cell = m_tree.grid.createCell(coord);
	cell->data = new CellData();
	cell->data->motions.push_back(motion);
	cell->data->coverage = 1.0;
	cell->data->iteration = m_tree.iteration;
	cell->data->selections = 1;
	cell->data->score = 1.0 / (1e-3 + dist);
	m_tree.grid.add(cell);
	created = 1;
    }
    m_tree.size++;
    return created;
}

void ompl::kinematic::KPIECE1::getStates(std::vector<const base::State*> &states) const
{
    states.resize(0);
    states.reserve(m_tree.size);

    std::vector<CellData*> cdata;
    m_tree.grid.getContent(cdata);
    for (unsigned int i = 0 ; i < cdata.size() ; ++i)
	for (unsigned int j = 0 ; j < cdata[i]->motions.size() ; ++j)
	    states.push_back(cdata[i]->motions[j]->state);
}
<commit_msg>add a debugging msg<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2008, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* \author Ioan Sucan */

#include "ompl/extension/kinematic/extension/kpiece/KPIECE1.h"
#include <ros/console.h>

bool ompl::kinematic::KPIECE1::solve(double solveTime)
{
    SpaceInformationKinematic *si = dynamic_cast<SpaceInformationKinematic*>(m_si);
    base::GoalRegion      *goal_r = dynamic_cast<base::GoalRegion*>(si->getGoal());
    GoalRegionKinematic   *goal_k = dynamic_cast<GoalRegionKinematic*>(si->getGoal());
    base::GoalState       *goal_s = dynamic_cast<base::GoalState*>(si->getGoal());
    unsigned int              dim = si->getStateDimension();

    if (!goal_s && !goal_r)
    {
	ROS_ERROR("KPIECE1: Unknown type of goal (or goal undefined)");
	return false;
    }

    ros::WallTime endTime = ros::WallTime::now() + ros::WallDuration(solveTime);

    if (m_tree.grid.size() == 0)
    {
	for (unsigned int i = 0 ; i < m_si->getStartStateCount() ; ++i)
	{
	    Motion *motion = new Motion(dim);
	    si->copyState(motion->state, si->getStartState(i));
	    if (si->satisfiesBounds(motion->state) && si->isValid(motion->state))
		addMotion(motion, 1.0);
	    else
	    {
		ROS_ERROR("KPIECE1: Initial state is invalid!");
		delete motion;
	    }
	}
    }

    if (m_tree.grid.size() == 0)
    {
	ROS_ERROR("KPIECE1: There are no valid initial states!");
	return false;
    }

    ROS_INFO("KPIECE1: Starting with %u states", m_tree.size);

    std::vector<double> range(dim);
    for (unsigned int i = 0 ; i < dim ; ++i)
	range[i] = m_rho * (si->getStateComponent(i).maxValue - si->getStateComponent(i).minValue);

    Motion *solution  = NULL;
    Motion *approxsol = NULL;
    double  approxdif = INFINITY;
    base::State *xstate = new base::State(dim);

    double improveValue = 0.01;

    while (ros::WallTime::now() < endTime)
    {
	m_tree.iteration++;

	/* Decide on a state to expand from */
	Motion     *existing = NULL;
	Grid::Cell *ecell = NULL;
	selectMotion(existing, ecell);
	assert(existing);

	/* sample random state (with goal biasing) */
	if (m_rng.uniform(0.0, 1.0) < m_goalBias)
	{
	    if (goal_s)
		si->copyState(xstate, goal_s->state);
	    else
		if (goal_k)
		    goal_k->sampleNearGoal(xstate);
		else
		{
		    if (approxsol)
		    {
			si->copyState(xstate, approxsol->state);
			ROS_DEBUG("Start Running HCIK...");
			if (!m_hcik.tryToImprove(xstate, improveValue))
			{
			    m_sCore.sampleNear(xstate, existing->state, range);
			    improveValue /= 2.0;
			}
			ROS_DEBUG("End Running HCIK");
		    }
		    else
			m_sCore.sampleNear(xstate, existing->state, range);
		}
	}
	else
	    m_sCore.sampleNear(xstate, existing->state, range);

	double failTime = 0.0;
	bool keep = si->checkMotionIncremental(existing->state, xstate, xstate, &failTime);
	if (!keep && failTime > m_minValidPathPercentage)
	    keep = true;

	if (keep)
	{
	    /* create a motion */
	    Motion *motion = new Motion(dim);
	    si->copyState(motion->state, xstate);
	    motion->parent = existing;

	    double dist = 0.0;
	    bool solved = goal_r->isSatisfied(motion->state, &dist);
	    addMotion(motion, dist);

	    if (solved)
	    {
		approxdif = dist;
		solution = motion;
		break;
	    }
	    if (dist < approxdif)
	    {
		approxdif = dist;
		approxsol = motion;
	    }
	    ecell->data->score *= m_goodScoreFactor;
	}
	else
	    ecell->data->score *= m_badScoreFactor;

	m_tree.grid.update(ecell);
    }

    bool approximate = false;
    if (solution == NULL)
    {
	solution = approxsol;
	approximate = true;
    }

    if (solution != NULL)
    {
	/* construct the solution path */
	std::vector<Motion*> mpath;
	while (solution != NULL)
	{
	    mpath.push_back(solution);
	    solution = solution->parent;
	}

	/* set the solution path */
	PathKinematic *path = new PathKinematic(m_si);
   	for (int i = mpath.size() - 1 ; i >= 0 ; --i)
	{
	    base::State *st = new base::State(dim);
	    si->copyState(st, mpath[i]->state);
	    path->states.push_back(st);
	}
	goal_r->setDifference(approxdif);
	goal_r->setSolutionPath(path, approximate);

	if (approximate)
	    ROS_WARN("KPIECE1: Found approximate solution");
    }

    delete xstate;

    ROS_INFO("KPIECE1: Created %u states in %u cells (%u internal + %u external)", m_tree.size, m_tree.grid.size(),
	     m_tree.grid.countInternal(), m_tree.grid.countExternal());

    return goal_r->isAchieved();
}

bool ompl::kinematic::KPIECE1::selectMotion(Motion* &smotion, Grid::Cell* &scell)
{
    scell = m_rng.uniform() < std::max(m_selectBorderPercentage, m_tree.grid.fracExternal()) ?
	m_tree.grid.topExternal() : m_tree.grid.topInternal();
    if (scell && !scell->data->motions.empty())
    {
	scell->data->selections++;
	smotion = scell->data->motions[m_rng.halfNormalInt(0, scell->data->motions.size() - 1)];
	return true;
    }
    else
	return false;
}

unsigned int ompl::kinematic::KPIECE1::addMotion(Motion *motion, double dist)
{
    Grid::Coord coord;
    m_projectionEvaluator->computeCoordinates(motion->state, coord);
    Grid::Cell* cell = m_tree.grid.getCell(coord);
    unsigned int created = 0;
    if (cell)
    {
	cell->data->motions.push_back(motion);
	cell->data->coverage += 1.0;
	m_tree.grid.update(cell);
    }
    else
    {
	cell = m_tree.grid.createCell(coord);
	cell->data = new CellData();
	cell->data->motions.push_back(motion);
	cell->data->coverage = 1.0;
	cell->data->iteration = m_tree.iteration;
	cell->data->selections = 1;
	cell->data->score = 1.0 / (1e-3 + dist);
	m_tree.grid.add(cell);
	created = 1;
    }
    m_tree.size++;
    return created;
}

void ompl::kinematic::KPIECE1::getStates(std::vector<const base::State*> &states) const
{
    states.resize(0);
    states.reserve(m_tree.size);

    std::vector<CellData*> cdata;
    m_tree.grid.getContent(cdata);
    for (unsigned int i = 0 ; i < cdata.size() ; ++i)
	for (unsigned int j = 0 ; j < cdata[i]->motions.size() ; ++j)
	    states.push_back(cdata[i]->motions[j]->state);
}
<|endoftext|>


<commit_before>#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TCompactProtocol.h>
#include "proxy/AccumuloProxy.h"

using namespace std;
using namespace accumulo;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace boost;

class Connector {

	string login;

	shared_ptr<TSocket> socket;
	shared_ptr<TTransport> transport;
	shared_ptr<TProtocol> protocol;

	AccumuloProxyClient *client;

	public:

		Connector(const string& host, int port, const string& username, const string& password);
		void createTable(const string& tableName);
		void createBatchWriter(string &tableName, uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads);
		void close();

};

Connector::Connector(const string& host, int port, const string& username, const string& password) {

	shared_ptr<TSocket> newSocket(new TSocket(host, port));
	shared_ptr<TTransport> newTransport(new TFramedTransport(newSocket));
	shared_ptr<TProtocol> newProtocol(new TCompactProtocol(newTransport));

	socket = newSocket;
	transport = newTransport;
	protocol = newProtocol;

	transport->open();

	string passKey("password");

  	map<string, string> m;
  	m.insert(make_pair(passKey, password));

	AccumuloProxyClient newClient(protocol);

	client = &newClient;
  	client->login(login, username, m);
}

void Connector::createTable(const string& tableName) {
	client->createTable(login, tableName, true, TimeType::MILLIS);
}

void Connector::close() {
	transport->close();
}

class Mutation {

	string rowId;

	public:
		Mutation(string &rowId);
		void put(string& colFam, string& colQual, string& colVis, uint32_t timestamp, string& value);

};

Mutation::Mutation(string& rowId) {
	this->rowId = rowId;
}

class BatchWriter {

	AccumuloProxyClient *client;
	string login;
	string writerToken;
	string tableName;

	public:

		BatchWriter(AccumuloProxyClient *client, string &login, string &tableName,
				uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads);
		void addMutation(Mutation *mutation);
		void flush();
		void close();
};

BatchWriter::BatchWriter(AccumuloProxyClient *client, string &login, string &tableName,
		uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads) {

	WriterOptions writerOptions;
	writerOptions.__set_maxMemory(maxMemory);
	writerOptions.__set_latencyMs(latencyMs);
	writerOptions.__set_timeoutMs(timeoutMs);
	writerOptions.__set_threads(numThreads);

	this->client = client;
	this->tableName = tableName;
	this->login = login;

	client->createWriter(writerToken, login, tableName, writerOptions);
}

void BatchWriter::flush() {

	client->flush(writerToken);
}

void BatchWriter::close() {
	client->closeWriter(writerToken);
}

void Mutation::put(string& colFam, string& colQual, string& colVis, uint32_t timestamp, string& value) {

	ColumnUpdate cUpdate;
	cUpdate.__set_colFamily(string("colFam"));
	cUpdate.__set_colQualifier(string("colQual"));
	cUpdate.__set_colVisibility(string(""));
	cUpdate.__set_timestamp(5000);
	cUpdate.__set_value(string(""));
}

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

	if(argc != 3) {
		cout << "Enter a hostname and port\n";
		return 1;
	}

	Connector connector(argv[1], atoi(argv[2]), string("root"), string("secret"));
	connector.close();

	//   string tableName("testTable");
	//
	//
	//   // client.createTable(login, tableName, true, TimeType::MILLIS);
	//
	//
	//   WriterOptions writerOptions;
	//   writerOptions.__set_maxMemory(5000);
	//   writerOptions.__set_latencyMs(5000);
	//   writerOptions.__set_timeoutMs(200000);
	//   writerOptions.__set_threads(5);
	//
	//   string writer;
	//   client.createWriter(writer, login, tableName, writerOptions);
	//
	// ColumnUpdate cUpdate;
	// cUpdate.__set_colFamily(string("colFam"));
	// cUpdate.__set_colQualifier(string("colQual"));
	// cUpdate.__set_colVisibility(string(""));
	// cUpdate.__set_timestamp(5000);
	// cUpdate.__set_value(string(""));
	//
	//    map<string, vector<ColumnUpdate> > cells;
	//
	//   string rowId("rowId");
	//
	//   ColumnUpdate upArr[]  = { cUpdate };
	//
	//   vector<ColumnUpdate> ud(upArr, upArr + sizeof(upArr) / sizeof(ColumnUpdate));
	//
	//   cells.insert(make_pair(rowId, ud));
	//
	//   for(int i = 0; i < 50000; i++) {
	//     client.update(writer, cells);
	//   }
	//
	//
	//
	//   transport->close();
  return 0;
}
<commit_msg>Finishing out methods for adding a mutation to BatchWriter<commit_after>#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TCompactProtocol.h>
#include "proxy/AccumuloProxy.h"

using namespace std;
using namespace accumulo;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace boost;

class Connector {

	string login;

	shared_ptr<TSocket> socket;
	shared_ptr<TTransport> transport;
	shared_ptr<TProtocol> protocol;

	AccumuloProxyClient *client;

	public:

		Connector(const string& host, int port, const string& username, const string& password);
		void createTable(const string& tableName);
		void createBatchWriter(string &tableName, uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads);
		void close();

};

Connector::Connector(const string& host, int port, const string& username, const string& password) {

	shared_ptr<TSocket> newSocket(new TSocket(host, port));
	shared_ptr<TTransport> newTransport(new TFramedTransport(newSocket));
	shared_ptr<TProtocol> newProtocol(new TCompactProtocol(newTransport));

	socket = newSocket;
	transport = newTransport;
	protocol = newProtocol;

	transport->open();

	string passKey("password");

  	map<string, string> m;
  	m.insert(make_pair(passKey, password));

	AccumuloProxyClient newClient(protocol);

	client = &newClient;
  	client->login(login, username, m);
}

void Connector::createTable(const string& tableName) {
	client->createTable(login, tableName, true, TimeType::MILLIS);
}

void Connector::close() {
	transport->close();
}

class Mutation {

	string rowId;
	vector<ColumnUpdate> updates;

	public:
		Mutation(string &rowId);
		void put(string& colFam, string& colQual, string& colVis, uint32_t timestamp, string& value);
		string getRowId();
		vector<ColumnUpdate> getUpdates();

};

Mutation::Mutation(string& rowId) {
	this->rowId = rowId;
}

void Mutation::put(string& colFam, string& colQual, string& colVis, uint32_t timestamp, string& value) {

	ColumnUpdate cUpdate;
	cUpdate.__set_colFamily(colFam);
	cUpdate.__set_colQualifier(colQual);
	cUpdate.__set_colVisibility(colVis);
	cUpdate.__set_timestamp(timestamp);
	cUpdate.__set_value(value);

	updates.push_back(cUpdate);
}

string Mutation::getRowId() {
	return rowId;
}

vector<ColumnUpdate> Mutation::getUpdates() {
	return updates;
}

class BatchWriter {

	AccumuloProxyClient *client;
	string login;
	string writerToken;
	string tableName;

	public:

		BatchWriter(AccumuloProxyClient *client, string &login, string &tableName,
				uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads);
		void addMutation(Mutation &mutation);
		void flush();
		void close();
};

BatchWriter::BatchWriter(AccumuloProxyClient *client, string &login, string &tableName,
		uint32_t maxMemory, uint32_t latencyMs, uint32_t timeoutMs, uint32_t numThreads) {

	WriterOptions writerOptions;
	writerOptions.__set_maxMemory(maxMemory);
	writerOptions.__set_latencyMs(latencyMs);
	writerOptions.__set_timeoutMs(timeoutMs);
	writerOptions.__set_threads(numThreads);

	this->client = client;
	this->tableName = tableName;
	this->login = login;

	client->createWriter(writerToken, login, tableName, writerOptions);
}

void BatchWriter::addMutation(Mutation &mutation) {

	map<string, vector<ColumnUpdate> > cells;

	vector<ColumnUpdate> updates = mutation.getUpdates();

	cells.insert(make_pair(mutation.getRowId(), updates));
	client->update(writerToken, cells);

	updates.clear();
}

void BatchWriter::flush() {

	client->flush(writerToken);
}

void BatchWriter::close() {
	client->closeWriter(writerToken);
}

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

	if(argc != 3) {
		cout << "Enter a hostname and port\n";
		return 1;
	}

	Connector connector(argv[1], atoi(argv[2]), string("root"), string("secret"));
	connector.close();

	//   string tableName("testTable");
	//
	//
	//   // client.createTable(login, tableName, true, TimeType::MILLIS);
	//
	//
	//   WriterOptions writerOptions;
	//   writerOptions.__set_maxMemory(5000);
	//   writerOptions.__set_latencyMs(5000);
	//   writerOptions.__set_timeoutMs(200000);
	//   writerOptions.__set_threads(5);
	//
	//   string writer;
	//   client.createWriter(writer, login, tableName, writerOptions);
	//
	// ColumnUpdate cUpdate;
	// cUpdate.__set_colFamily(string("colFam"));
	// cUpdate.__set_colQualifier(string("colQual"));
	// cUpdate.__set_colVisibility(string(""));
	// cUpdate.__set_timestamp(5000);
	// cUpdate.__set_value(string(""));
	//
	//    map<string, vector<ColumnUpdate> > cells;
	//
	//   string rowId("rowId");
	//
	//
	//   vector<ColumnUpdate> ud(upArr, upArr + sizeof(upArr) / sizeof(ColumnUpdate));
	//
	//   cells.insert(make_pair(rowId, ud));
	//
	//   for(int i = 0; i < 50000; i++) {
	//     client.update(writer, cells);
	//   }
	//
	//
	//
	//   transport->close();
  return 0;
}
<|endoftext|>