<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX
#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX

#include <drawinglayer/drawinglayerdllapi.h>

#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <svtools/ctrlbox.hxx>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace primitive2d
    {
        /** BorderLinePrimitive2D class

            This is the basic primitive to build frames around objects, e.g. tables.
            It defines a single or double line from Start to nd using the LeftWidth,
            Distance and RightWidth definitions.
            The LineStart/End overlap is defined by the Extend(Inner|Outer)(Start|End)
            definitions.
         */
        class DRAWINGLAYER_DLLPUBLIC BorderLinePrimitive2D : public BufferedDecompositionPrimitive2D
        {
        private:
            /// the line definition
            basegfx::B2DPoint                               maStart;
            basegfx::B2DPoint                               maEnd;

            /// the widths of single/double line
            double                                          mfLeftWidth;
            double                                          mfDistance;
            double                                          mfRightWidth;

            /// edge overlap sizes
            double                                          mfExtendLeftStart;
            double                                          mfExtendLeftEnd;
            double                                          mfExtendRightStart;
            double                                          mfExtendRightEnd;

            /// the line colors
            basegfx::BColor                                 maRGBColorRight;
            basegfx::BColor                                 maRGBColorLeft;
            basegfx::BColor                                 maRGBColorGap;
            bool                                            mbHasGapColor;

            short                                           mnStyle;

            /// bitfield
            /// flags to influence inside/outside creation
            unsigned                                        mbCreateInside : 1;
            unsigned                                        mbCreateOutside : 1;

            /// local helpers
            double getWidth(
                    const geometry::ViewInformation2D& rViewInformation) const;

            bool isSolidLine() const
            {
                return (mnStyle==STYLE_SOLID);
            }

            bool isInsideUsed() const
            {
                return !basegfx::fTools::equalZero(mfLeftWidth);
            }

            bool isOutsideUsed() const
            {
                return !basegfx::fTools::equalZero(mfRightWidth);
            }

        protected:
            virtual basegfx::B2DPolyPolygon getClipPolygon(
                    const geometry::ViewInformation2D& rViewInformation) const;

            /// create local decomposition
            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;

        public:
            /// constructor
            BorderLinePrimitive2D(
                const basegfx::B2DPoint& rStart,
                const basegfx::B2DPoint& rEnd,
                double fLeftWidth,
                double fDistance,
                double fRightWidth,
                double fExtendLeftStart,
                double fExtendLeftEnd,
                double fExtendRightStart,
                double fExtendRightEnd,
                const basegfx::BColor& rRGBColorRight,
                const basegfx::BColor& rRGBColorLeft,
                const basegfx::BColor& rRGBColorGap,
                bool bHasGapColor,
                const short nStyle );

            /// data read access
            const basegfx::B2DPoint& getStart() const { return maStart; }
            const basegfx::B2DPoint& getEnd() const { return maEnd; }
            double getLeftWidth() const { return mfLeftWidth; }
            double getDistance() const { return mfDistance; }
            double getRightWidth() const { return mfRightWidth; }
            double getExtendLeftStart() const { return mfExtendLeftStart; }
            double getExtendLeftEnd() const { return mfExtendLeftEnd; }
            double getExtendRightStart() const { return mfExtendRightStart; }
            double getExtendRightEnd() const { return mfExtendRightEnd; }
            const basegfx::BColor& getRGBColorRight () const { return maRGBColorRight; }
            const basegfx::BColor& getRGBColorLeft () const { return maRGBColorLeft; }
            const basegfx::BColor& getRGBColorGap () const { return maRGBColorGap; }
            bool hasGapColor( ) const { return mbHasGapColor; }
            short getStyle () const { return mnStyle; }

            /// compare operator
            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;

            /// provide unique ID
            DeclPrimitrive2DIDBlock()
        };
    } // end of namespace primitive2d
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>-Werror,-Wunused-private-field (Clang towards 3.2)<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX
#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX

#include <drawinglayer/drawinglayerdllapi.h>

#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <svtools/ctrlbox.hxx>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace primitive2d
    {
        /** BorderLinePrimitive2D class

            This is the basic primitive to build frames around objects, e.g. tables.
            It defines a single or double line from Start to nd using the LeftWidth,
            Distance and RightWidth definitions.
            The LineStart/End overlap is defined by the Extend(Inner|Outer)(Start|End)
            definitions.
         */
        class DRAWINGLAYER_DLLPUBLIC BorderLinePrimitive2D : public BufferedDecompositionPrimitive2D
        {
        private:
            /// the line definition
            basegfx::B2DPoint                               maStart;
            basegfx::B2DPoint                               maEnd;

            /// the widths of single/double line
            double                                          mfLeftWidth;
            double                                          mfDistance;
            double                                          mfRightWidth;

            /// edge overlap sizes
            double                                          mfExtendLeftStart;
            double                                          mfExtendLeftEnd;
            double                                          mfExtendRightStart;
            double                                          mfExtendRightEnd;

            /// the line colors
            basegfx::BColor                                 maRGBColorRight;
            basegfx::BColor                                 maRGBColorLeft;
            basegfx::BColor                                 maRGBColorGap;
            bool                                            mbHasGapColor;

            short                                           mnStyle;

            /// local helpers
            double getWidth(
                    const geometry::ViewInformation2D& rViewInformation) const;

            bool isSolidLine() const
            {
                return (mnStyle==STYLE_SOLID);
            }

            bool isInsideUsed() const
            {
                return !basegfx::fTools::equalZero(mfLeftWidth);
            }

            bool isOutsideUsed() const
            {
                return !basegfx::fTools::equalZero(mfRightWidth);
            }

        protected:
            virtual basegfx::B2DPolyPolygon getClipPolygon(
                    const geometry::ViewInformation2D& rViewInformation) const;

            /// create local decomposition
            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;

        public:
            /// constructor
            BorderLinePrimitive2D(
                const basegfx::B2DPoint& rStart,
                const basegfx::B2DPoint& rEnd,
                double fLeftWidth,
                double fDistance,
                double fRightWidth,
                double fExtendLeftStart,
                double fExtendLeftEnd,
                double fExtendRightStart,
                double fExtendRightEnd,
                const basegfx::BColor& rRGBColorRight,
                const basegfx::BColor& rRGBColorLeft,
                const basegfx::BColor& rRGBColorGap,
                bool bHasGapColor,
                const short nStyle );

            /// data read access
            const basegfx::B2DPoint& getStart() const { return maStart; }
            const basegfx::B2DPoint& getEnd() const { return maEnd; }
            double getLeftWidth() const { return mfLeftWidth; }
            double getDistance() const { return mfDistance; }
            double getRightWidth() const { return mfRightWidth; }
            double getExtendLeftStart() const { return mfExtendLeftStart; }
            double getExtendLeftEnd() const { return mfExtendLeftEnd; }
            double getExtendRightStart() const { return mfExtendRightStart; }
            double getExtendRightEnd() const { return mfExtendRightEnd; }
            const basegfx::BColor& getRGBColorRight () const { return maRGBColorRight; }
            const basegfx::BColor& getRGBColorLeft () const { return maRGBColorLeft; }
            const basegfx::BColor& getRGBColorGap () const { return maRGBColorGap; }
            bool hasGapColor( ) const { return mbHasGapColor; }
            short getStyle () const { return mnStyle; }

            /// compare operator
            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;

            /// provide unique ID
            DeclPrimitrive2DIDBlock()
        };
    } // end of namespace primitive2d
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <chrono>

#include "aggregate_bandwidth.cpp"
#include "aggregate_bandwidth.hpp"
#include "bytes_object.hpp"
#include "log_results.hpp"
#include <derecho/conf/conf.hpp>
#include <derecho/core/derecho.hpp>
#include <derecho/mutils-serialization/SerializationSupport.hpp>
#include <derecho/persistent/Persistent.hpp>
#include "partial_senders_allocator.hpp"

using std::endl;
using test::Bytes;
using namespace std::chrono;

/**
 * RPC Object with a single function that accepts a string
 */
class TestObject {
public:
    void fun(const std::string& words) {
    }

    void bytes_fun(const Bytes& bytes) {
    }

    bool finishing_call(int x) {
        return true;
    }

    REGISTER_RPC_FUNCTIONS(TestObject, ORDERED_TARGETS(fun, bytes_fun, finishing_call));
};

struct exp_result {
    int num_nodes;
    uint32_t num_sender_sel;
    long long unsigned int max_msg_size;
    unsigned int window_size;
    uint32_t count;
    double avg_msec;
    double avg_gbps;

    void print(std::ofstream& fout) {
        fout << num_nodes << " " << num_sender_sel << " "
             << max_msg_size << " " << window_size << " "
             << count << " "
             << avg_msec << " " << avg_gbps << endl;
    }
};

#define DEFAULT_PROC_NAME "typed_bw_test"

int main(int argc, char* argv[]) {
    int dashdash_pos = argc - 1;
    while(dashdash_pos > 0) {
        if(strcmp(argv[dashdash_pos], "--") == 0) {
            break;
        }
        dashdash_pos--;
    }

    if((argc - dashdash_pos) < 4) {
        std::cout << "Invalid command line arguments." << std::endl;
        std::cout << "USAGE: " << argv[0] << " [ derecho-config-list -- ] <num_nodes> <count> <num_senders_selector> [proc_name]" << std::endl;
        std::cout << "Note: proc_name sets the process's name as displayed in ps and pkill commands, default is " DEFAULT_PROC_NAME << std::endl;
        return -1;
    }

    derecho::Conf::initialize(argc, argv);

    //The maximum number of bytes that can be sent to change_pers_bytes() is not quite MAX_PAYLOAD_SIZE.
    //The serialized Bytes object will include its size field as well as the actual buffer, and
    //the RPC function header contains an InvocationID (which is a size_t) as well as the header
    //fields defined by remote_invocation_utilites::header_space().
    const std::size_t rpc_header_size = sizeof(std::size_t) + sizeof(std::size_t)
                                        + derecho::remote_invocation_utilities::header_space();

    const int num_nodes = std::stoi(argv[dashdash_pos + 1]);
    const uint64_t max_msg_size = derecho::getConfUInt64(CONF_SUBGROUP_DEFAULT_MAX_PAYLOAD_SIZE) - rpc_header_size;
    const uint32_t count = std::stoi(argv[dashdash_pos + 2]);
    const uint32_t num_senders_selector = std::stoi(argv[dashdash_pos + 3]);

    steady_clock::time_point begin_time, send_complete_time;

    // Convert this integer to a more readable enum value
    const PartialSendMode senders_mode = num_senders_selector == 0
                                                 ? PartialSendMode::ALL_SENDERS
                                                 : (num_senders_selector == 1
                                                            ? PartialSendMode::HALF_SENDERS
                                                            : PartialSendMode::ONE_SENDER);

    // Compute the total number of messages that should be delivered
    uint64_t total_num_messages = 0;
    switch(senders_mode) {
        case PartialSendMode::ALL_SENDERS:
            total_num_messages = count * num_nodes;
            break;
        case PartialSendMode::HALF_SENDERS:
            total_num_messages = count * (num_nodes / 2);
            break;
        case PartialSendMode::ONE_SENDER:
            total_num_messages = count;
            break;
    }

    // variable 'done' tracks the end of the test
    volatile bool done = false;
    // callback into the application code at each message delivery
    auto stability_callback = [&done,
                               total_num_messages,
                               num_delivered = 0u,
    			       &send_complete_time](uint32_t subgroup,
                                                   uint32_t sender_id,
                                                   long long int index,
                                                   std::optional<std::pair<char*, long long int>> data,
                                                   persistent::version_t ver) mutable {
        // Count the total number of messages delivered
        ++num_delivered;
        // Check for completion
        if(num_delivered == total_num_messages) {
	    send_complete_time = std::chrono::steady_clock::now();
            done = true;
        }
    };

    if(dashdash_pos + 4 < argc) {
        pthread_setname_np(pthread_self(), argv[dashdash_pos + 3]);
    } else {
        pthread_setname_np(pthread_self(), DEFAULT_PROC_NAME);
    }

    /*******************
    derecho::SubgroupInfo subgroup_info{[num_nodes](
                                                const std::vector<std::type_index>& subgroup_type_order,
                                                const std::unique_ptr<derecho::View>& prev_view, derecho::View& curr_view) {
        if(curr_view.num_members < num_nodes) {
            std::cout << "not enough members yet:" << curr_view.num_members << " < " << num_nodes << std::endl;
            throw derecho::subgroup_provisioning_exception();
        }
        derecho::subgroup_shard_layout_t subgroup_layout(1);

        std::vector<uint32_t> members(num_nodes);
        for(int i = 0; i < num_nodes; i++) {
            members[i] = i;
        }

        subgroup_layout[0].emplace_back(curr_view.make_subview(members));
        curr_view.next_unassigned_rank = std::max(curr_view.next_unassigned_rank, num_nodes);
        derecho::subgroup_allocation_map_t subgroup_allocation;
        subgroup_allocation.emplace(std::type_index(typeid(TestObject)), std::move(subgroup_layout));
        return subgroup_allocation;
    }};
    *****************/

    auto membership_function = PartialSendersAllocator(num_nodes, senders_mode, derecho::Mode::ORDERED);
    derecho::SubgroupInfo subgroup_info(membership_function);

    auto ba_factory = [](persistent::PersistentRegistry*, derecho::subgroup_id_t) { return std::make_unique<TestObject>(); };

    derecho::Group<TestObject> group(derecho::UserMessageCallbacks{stability_callback}, subgroup_info, {}, std::vector<derecho::view_upcall_t>{}, ba_factory);
    std::cout << "Finished constructing/joining Group" << std::endl;

    //std::string str_1k(max_msg_size, 'x');
    char* bbuf = (char*)malloc(max_msg_size);
    bzero(bbuf, max_msg_size);
    Bytes bytes(bbuf, max_msg_size);

    // this function sends all the messages
    auto send_all = [&]() {
        for(uint i = 0; i < count; i++) {
	derecho::Replicated<TestObject>& handle = group.get_subgroup<TestObject>();
        handle.ordered_send<RPC_NAME(bytes_fun)>(bytes);
    }
    };

    int node_rank = group.get_my_rank();

    // Begin Clock Timer
    begin_time = std::chrono::steady_clock::now();

    if(senders_mode == PartialSendMode::ALL_SENDERS) {
        send_all();
    } else if(senders_mode == PartialSendMode::HALF_SENDERS) {
        if(node_rank > (num_nodes - 1) / 2) {
            send_all();
        }
    } else {
        if(node_rank == num_nodes - 1) {
            send_all();
        }
    }

    /*
    if(node_rank == 0) {
        derecho::rpc::QueryResults<bool> results = handle.ordered_send<RPC_NAME(finishing_call)>(0);
        std::cout << "waiting for response..." << std::endl;
#pragma GCC diagnostic ignored "-Wunused-variable"
        decltype(results)::ReplyMap& replies = results.get();
#pragma GCC diagnostic pop
    }
    */

    while(!done){
    }

    free(bbuf);

    int64_t nsec = duration_cast<nanoseconds>(send_complete_time - begin_time).count();

    double thp_gbps = (static_cast<double>(total_num_messages) * max_msg_size) / nsec;
    double msec = (double)nsec / 1000000;
    double thp_ops = ((double)count * 1000000000) / nsec;
    std::cout << "timespan:" << msec << " millisecond." << std::endl;
    std::cout << "throughput:" << thp_gbps << "GB/s." << std::endl;
    std::cout << "throughput:" << thp_ops << "ops." << std::endl;
    std::cout << std::flush;

    // aggregate bandwidth from all nodes
    std::pair<double, double> bw_laten(thp_gbps,msec);

    auto members_order = group.get_members();
    bw_laten = aggregate_bandwidth(members_order, members_order[node_rank], bw_laten);

    double avg_gbps = bw_laten.first;
    double avg_msec = bw_laten.second;

    if(node_rank == 0) {
        log_results(exp_result{num_nodes, num_senders_selector, max_msg_size,
                               derecho::getConfUInt32(CONF_SUBGROUP_DEFAULT_WINDOW_SIZE), count,
                               avg_msec, avg_gbps},
                    "data_derecho_typed_subgroup_bw");
    }

    group.barrier_sync();
    group.leave();
}
<commit_msg>typed subgroup bw test with latency.<commit_after>#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <chrono>

#include "aggregate_bandwidth.cpp"
#include "aggregate_bandwidth.hpp"
#include "bytes_object.hpp"
#include "log_results.hpp"
#include <derecho/conf/conf.hpp>
#include <derecho/core/derecho.hpp>
#include <derecho/mutils-serialization/SerializationSupport.hpp>
#include <derecho/persistent/Persistent.hpp>
#include "partial_senders_allocator.hpp"
#include <derecho/utils/time.h>

using std::endl;
using test::Bytes;
using namespace std::chrono;

/**
 * RPC Object with a single function that accepts a string
 */
class TestObject : public derecho::GroupReference {
public:
    /* group reference */
    using derecho::GroupReference::group;
    void fun(const std::string& words);
    std::tuple<persistent::version_t,uint64_t> bytes_fun(const Bytes& bytes);
    bool finishing_call(int x);

    REGISTER_RPC_FUNCTIONS(TestObject, ORDERED_TARGETS(fun, bytes_fun, finishing_call));
};

void TestObject::fun(const std::string& words) {}

std::tuple<persistent::version_t,uint64_t> TestObject::bytes_fun(const Bytes& bytes) {
    return group->template get_subgroup<TestObject>(this->subgroup_index).get_current_version();
}

bool TestObject::finishing_call(int x) {
    return true;
}

struct exp_result {
    int num_nodes;
    uint32_t num_sender_sel;
    long long unsigned int max_msg_size;
    unsigned int window_size;
    uint32_t count;
    double avg_msec;
    double avg_gbps;

    void print(std::ofstream& fout) {
        fout << num_nodes << " " << num_sender_sel << " "
             << max_msg_size << " " << window_size << " "
             << count << " "
             << avg_msec << " " << avg_gbps << endl;
    }
};

#define DEFAULT_PROC_NAME "typed_bw_test"

int main(int argc, char* argv[]) {
    int dashdash_pos = argc - 1;
    while(dashdash_pos > 0) {
        if(strcmp(argv[dashdash_pos], "--") == 0) {
            break;
        }
        dashdash_pos--;
    }

    if((argc - dashdash_pos) < 4) {
        std::cout << "Invalid command line arguments." << std::endl;
        std::cout << "USAGE: " << argv[0] << " [ derecho-config-list -- ] <num_nodes> <count> <num_senders_selector> [proc_name]" << std::endl;
        std::cout << "Note: proc_name sets the process's name as displayed in ps and pkill commands, default is " DEFAULT_PROC_NAME << std::endl;
        return -1;
    }

    derecho::Conf::initialize(argc, argv);

    //The maximum number of bytes that can be sent to change_pers_bytes() is not quite MAX_PAYLOAD_SIZE.
    //The serialized Bytes object will include its size field as well as the actual buffer, and
    //the RPC function header contains an InvocationID (which is a size_t) as well as the header
    //fields defined by remote_invocation_utilites::header_space().
    const std::size_t rpc_header_size = sizeof(std::size_t) + sizeof(std::size_t)
                                        + derecho::remote_invocation_utilities::header_space();

    const int num_nodes = std::stoi(argv[dashdash_pos + 1]);
    const uint64_t max_msg_size = derecho::getConfUInt64(CONF_SUBGROUP_DEFAULT_MAX_PAYLOAD_SIZE) - rpc_header_size;
    const uint32_t count = std::stoi(argv[dashdash_pos + 2]);
    const uint32_t num_senders_selector = std::stoi(argv[dashdash_pos + 3]);

    steady_clock::time_point begin_time, send_complete_time;

    // Convert this integer to a more readable enum value
    const PartialSendMode senders_mode = num_senders_selector == 0
                                                 ? PartialSendMode::ALL_SENDERS
                                                 : (num_senders_selector == 1
                                                            ? PartialSendMode::HALF_SENDERS
                                                            : PartialSendMode::ONE_SENDER);

    // Compute the total number of messages that should be delivered
    uint64_t total_num_messages = 0;
    switch(senders_mode) {
        case PartialSendMode::ALL_SENDERS:
            total_num_messages = count * num_nodes;
            break;
        case PartialSendMode::HALF_SENDERS:
            total_num_messages = count * (num_nodes / 2);
            break;
        case PartialSendMode::ONE_SENDER:
            total_num_messages = count;
            break;
    }

    // map from version to timestamp in ns.
    std::map <persistent::version_t,uint64_t> stable_ts;
    std::vector<std::tuple<persistent::version_t,uint64_t,uint64_t>> timestamp_log;
    timestamp_log.reserve(total_num_messages);

    // variable 'done' tracks the end of the test
    volatile bool done = false;
    // callback into the application code at each message delivery
    auto stability_callback = [&done,
                               total_num_messages,
                               num_delivered = 0u,
                               &stable_ts,
    			               &send_complete_time](uint32_t subgroup,
                                                    uint32_t sender_id,
                                                    long long int index,
                                                    std::optional<std::pair<char*, long long int>> data,
                                                    persistent::version_t ver) mutable {
        // Count the total number of messages delivered
        ++num_delivered;
        stable_ts.emplace(ver,get_walltime());
        // Check for completion
        if(num_delivered == total_num_messages) {
	        send_complete_time = std::chrono::steady_clock::now();
            done = true;
        }
    };

    if(dashdash_pos + 4 < argc) {
        pthread_setname_np(pthread_self(), argv[dashdash_pos + 3]);
    } else {
        pthread_setname_np(pthread_self(), DEFAULT_PROC_NAME);
    }

    auto membership_function = PartialSendersAllocator(num_nodes, senders_mode, derecho::Mode::ORDERED);
    derecho::SubgroupInfo subgroup_info(membership_function);

    auto ba_factory = [](persistent::PersistentRegistry*, derecho::subgroup_id_t) { return std::make_unique<TestObject>(); };

    derecho::Group<TestObject> group(derecho::UserMessageCallbacks{stability_callback}, subgroup_info, {}, std::vector<derecho::view_upcall_t>{}, ba_factory);
    std::cout << "Finished constructing/joining Group" << std::endl;

    //std::string str_1k(max_msg_size, 'x');
    char* bbuf = (char*)malloc(max_msg_size);
    bzero(bbuf, max_msg_size);
    Bytes bytes(bbuf, max_msg_size);

    // this function sends all the messages
    auto send_all = [&](std::vector<std::tuple<persistent::version_t,uint64_t,uint64_t>>& timestamp_log) {
        // 1 - synchronization data structures
        uint32_t window_size = derecho::getConfUInt32(CONF_SUBGROUP_DEFAULT_WINDOW_SIZE);
        uint32_t window_slots = window_size*2;
        std::mutex window_slots_mutex;
        std::condition_variable window_slots_cv;
        std::queue<std::pair<uint64_t,derecho::QueryResults<std::tuple<persistent::version_t,uint64_t>>>> futures;
        std::mutex futures_mutex;
        std::condition_variable futures_cv;
        std::atomic<bool> all_sent(false);
        // 2 - query thread
        std::thread query_thread(
            [&timestamp_log,&window_slots,&window_slots_mutex,&window_slots_cv,&futures,&futures_mutex,&futures_cv,&all_sent](){
            std::unique_lock<std::mutex> futures_lck{futures_mutex};
            while(!all_sent || (futures.size()>0)) {
                // pick pending futures
                using namespace std::chrono_literals;
                while(!futures_cv.wait_for(futures_lck,500ms,[&futures,&all_sent]{return(futures.size()>0)||all_sent;}));
                std::decay_t<decltype(futures)> pending_futures;
                futures.swap(pending_futures);
                futures_lck.unlock();

                // queue unlocked
                while (pending_futures.size()>0) {
                    auto& replies = pending_futures.front().second.get();
                    for (auto& reply: replies) {
                        auto version = std::get<0>(reply.second.get());
                        uint64_t reply_timestamp_ns = get_walltime();
                        uint64_t send_timestamp_ns = pending_futures.front().first;
                        timestamp_log.emplace_back(version, send_timestamp_ns, reply_timestamp_ns);
                        break;
                    }
                    pending_futures.pop();
                    {
                        std::lock_guard<std::mutex> window_slots_lock{window_slots_mutex};
                        window_slots ++;
                    }
                    window_slots_cv.notify_one();
                }
                futures_lck.lock();
            }
        });

        for(uint i = 0; i < count; i++) {
            // acquire a window_slot
            {
                std::unique_lock<std::mutex> window_slots_lock{window_slots_mutex};
                window_slots_cv.wait(window_slots_lock,[&window_slots]{return (window_slots >0);});
                window_slots --;
            }
            // send
            derecho::Replicated<TestObject>& handle = group.get_subgroup<TestObject>();
            auto qr = handle.ordered_send<RPC_NAME(bytes_fun)>(bytes);
            // insert future
            {
                uint64_t timestamp_ns = get_walltime();
                std::unique_lock<std::mutex> future_lock{futures_mutex};
                futures.emplace(timestamp_ns,std::move(qr));
            }
            futures_cv.notify_one();
        }
        all_sent.store(true);
        query_thread.join();
    };

    int node_rank = group.get_my_rank();

    // Begin Clock Timer
    begin_time = std::chrono::steady_clock::now();

    if(senders_mode == PartialSendMode::ALL_SENDERS) {
        send_all(timestamp_log);
    } else if(senders_mode == PartialSendMode::HALF_SENDERS) {
        if(node_rank > (num_nodes - 1) / 2) {
            send_all(timestamp_log);
        }
    } else {
        if(node_rank == num_nodes - 1) {
            send_all(timestamp_log);
        }
    }

    while(!done);

    free(bbuf);

    int64_t nsec = duration_cast<nanoseconds>(send_complete_time - begin_time).count();

    double thp_gbps = (static_cast<double>(total_num_messages) * max_msg_size) / nsec;
    double msec = (double)nsec / 1000000;
    double thp_ops = ((double)count * 1000000000) / nsec;
    std::cout << "timespan:" << msec << " millisecond." << std::endl;
    std::cout << "throughput:" << thp_gbps << "GB/s." << std::endl;
    std::cout << "throughput:" << thp_ops << "ops." << std::endl;
    std::cout << std::flush;

    // aggregate bandwidth from all nodes
    std::pair<double, double> bw_laten(thp_gbps,msec);

    auto members_order = group.get_members();
    bw_laten = aggregate_bandwidth(members_order, members_order[node_rank], bw_laten);

    double avg_gbps = bw_laten.first;
    double avg_msec = bw_laten.second;

    if(node_rank == 0) {
        log_results(exp_result{num_nodes, num_senders_selector, max_msg_size,
                               derecho::getConfUInt32(CONF_SUBGROUP_DEFAULT_WINDOW_SIZE), count,
                               avg_msec, avg_gbps},
                    "data_derecho_typed_subgroup_bw");
    }

    // write timestamp log into file
    std::ofstream ofile(DEFAULT_PROC_NAME);
    ofile << "#ver send(us) stable(us) acked(us)" << std::endl;
    for (auto t: timestamp_log) {
        auto ver = std::get<0>(t);
        ofile << ver << "\t" << std::get<1>(t)/1000 << "\t" << stable_ts.at(ver)/1000 << "\t" << std::get<2>(t)/1000 << std::endl;
    }

    group.barrier_sync();
    group.leave();
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include <fstream>
#include <streambuf>
#include <string>

// xerces
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/util/XMLString.hpp>

// wiki xml dump lib
#include "../../s3_recursiveFillCategories.h"
#include "../helpers/buildArtificialDump.h"
#include "../../../core/wikiDataCache.h"
#include "../../sortTitlesHelper.h"
#include "../../wikiArticleHandlers/articleDatesAndCategoriesHandler.h"
#include "../../wikiArticleHandlers/allLinksArticleHandler.h"
#include "../../../../libs/wiki_xml_dump_xerces/src/parsers/singleCoreParser.hpp"
#include "../../../../libs/wiki_xml_dump_xerces/src/handlers/wikiDumpHandlerProperties.hpp"
#include "../../../../libs/wiki_xml_dump_xerces/src/handlers/basicTitleFilters.hpp"

BOOST_AUTO_TEST_SUITE(category_has_article_tests)

BOOST_AUTO_TEST_CASE(check_if_recursive_articles_are_detected_articial)
{
	std::vector<std::string> titles = { "A", "B", "C", "D", "E", "Category:C1", "Category:C2", "Category:C3" };
	std::vector<std::pair<std::string,std::string>> expected_links = {
		{ "A", "C" },
		{ "A", "D" },
		{ "C", "D" },
		{ "D", "E" },
		{ "D", "A" },
		{ "D", "C" },
		{ "E", "A" },
		{ "A", "Category:C3" },
		{ "B", "Category:C3" },
		{ "C", "Category:C2" },
		{ "D", "Category:C1" },
		{ "Category:C2", "Category:C1" },
		{ "Category:C3", "Category:C2" },
	};

	std::vector<std::pair<std::string,std::string>> expected_category_containment = {
		{ "A", "Category:C1" },
		{ "A", "Category:C2" },
		{ "A", "Category:C3" },
	};

	std::string content = build_artificial_dump(titles, expected_links);

	WikiXmlDumpXerces::WikiDumpHandlerProperties parser_properties;
	parser_properties.TitleFilter = WikiXmlDumpXerces::only_articles_and_categories();

	// init xerces
	xercesc::XMLPlatformUtils::Initialize();

	// run parsing
	auto article_titles_stream = std::make_shared<std::stringstream>();
	auto article_dates_stream = std::make_shared<std::stringstream>();
	auto category_titles_stream = std::make_shared<std::stringstream>();
	auto redirects_stream = std::make_shared<std::stringstream>();
	std::mutex article_titles_mutex;
	std::mutex category_titles_mutex;
	std::mutex redirect_mutex;
	ArticleDatesAndCategoriesHandler art_handler(*article_titles_stream, *article_dates_stream, *category_titles_stream, *redirects_stream, article_titles_mutex, category_titles_mutex, redirect_mutex);
	art_handler.ExtractOnlyArticlesWithDates = false;
	WikiXmlDumpXerces::SingleCoreParser parser(art_handler, parser_properties);
	parser.RunOnString(content);

	article_titles_stream->seekg(0);
	article_dates_stream->seekg(0);
	category_titles_stream->seekg(0);
	redirects_stream->seekg(0);

	// terminate xerces

	auto article_titles_sorted_stream = std::make_shared<std::stringstream>();
	auto article_dates_sorted_stream = std::make_shared<std::stringstream>();
	auto category_titles_sorted_stream = std::make_shared<std::stringstream>();
	sort_article_files(*article_titles_stream, *article_dates_stream, *article_titles_sorted_stream, *article_dates_sorted_stream);
	sort_category_files(*category_titles_stream, *category_titles_sorted_stream);

	article_titles_sorted_stream->seekg(0);
	category_titles_sorted_stream->seekg(0);

	WikiMainPath::WikiDataCache wiki_data_cache(article_titles_sorted_stream, article_dates_sorted_stream, category_titles_sorted_stream, redirects_stream);
	auto& article_titles = wiki_data_cache.article_titles();
	auto& category_titles = wiki_data_cache.category_titles();
	auto& redirects = wiki_data_cache.redirects();
	std::vector<boost::container::flat_set<std::size_t>> category_has_article(category_titles.size());
	AllLinksArticleHander::CategoryHirachyGraph category_hirachy_graph(category_titles.size());
	std::vector<boost::container::flat_set<std::size_t>> article_adjacency_list(article_titles.size());
	VectorMutex<1000> vector_mutex;

	AllLinksArticleHander all_links_handler(article_titles, category_titles, redirects, category_has_article, category_hirachy_graph, article_adjacency_list, vector_mutex);
	WikiXmlDumpXerces::SingleCoreParser parser2(all_links_handler, parser_properties);
	parser2.RunOnString(content);

	xercesc::XMLPlatformUtils::Terminate();

	recursiveFillCategories(category_hirachy_graph, category_has_article);

	for (auto containment : expected_category_containment) {
		auto it_1 = std::find(article_titles.begin(), article_titles.end(), containment.first);
		auto it_2 = std::find(category_titles.begin(), category_titles.end(), containment.second);

		bool found_article = it_1 != article_titles.end();
		bool found_category= it_2 != category_titles.end();

		BOOST_CHECK(found_article);
		BOOST_CHECK(found_category);

		std::size_t i_article = it_1-article_titles.begin();
		std::size_t i_category = it_2-category_titles.begin();

		if(found_article && found_category)
		{
			bool found = std::find(category_has_article[i_category].begin(), category_has_article[i_category].end(), i_article) != category_has_article[i_category].end();
			if(!found)
				std::cout << containment.first << " - " << containment.second << std::endl;
			BOOST_CHECK(found);
		}

	}
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Identified some error in category has article<commit_after>#include <boost/test/unit_test.hpp>

#include <fstream>
#include <streambuf>
#include <string>

// xerces
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/util/XMLString.hpp>

// wiki xml dump lib
#include "../../s3_recursiveFillCategories.h"
#include "../helpers/buildArtificialDump.h"
#include "../../../core/wikiDataCache.h"
#include "../../sortTitlesHelper.h"
#include "../../wikiArticleHandlers/articleDatesAndCategoriesHandler.h"
#include "../../wikiArticleHandlers/allLinksArticleHandler.h"
#include "../../../../libs/wiki_xml_dump_xerces/src/parsers/singleCoreParser.hpp"
#include "../../../../libs/wiki_xml_dump_xerces/src/handlers/wikiDumpHandlerProperties.hpp"
#include "../../../../libs/wiki_xml_dump_xerces/src/handlers/basicTitleFilters.hpp"

BOOST_AUTO_TEST_SUITE(category_has_article_tests)

BOOST_AUTO_TEST_CASE(check_if_recursive_articles_are_detected_articial)
{
	std::vector<std::string> titles = { "A", "B", "C", "D", "E", "Category:C1", "Category:C2", "Category:C3" };
	std::vector<std::pair<std::string,std::string>> expected_links = {
		{ "A", "C" },
		{ "A", "D" },
		{ "C", "D" },
		{ "D", "E" },
		{ "D", "A" },
		{ "D", "C" },
		{ "E", "A" },
		{ "A", "Category:C3" },
		{ "B", "Category:C3" },
		{ "C", "Category:C2" },
		{ "D", "Category:C1" },
		{ "Category:C2", "Category:C1" },
		{ "Category:C3", "Category:C2" },
	};

	std::vector<std::pair<std::string,std::string>> expected_category_containment = {
		{ "A", "C1" },
		{ "A", "C2" },
		{ "A", "C3" },
	};

	std::string content = build_artificial_dump(titles, expected_links);

	WikiXmlDumpXerces::WikiDumpHandlerProperties parser_properties;
	parser_properties.TitleFilter = WikiXmlDumpXerces::only_articles_and_categories();

	// init xerces
	xercesc::XMLPlatformUtils::Initialize();

	// run parsing
	auto article_titles_stream = std::make_shared<std::stringstream>();
	auto article_dates_stream = std::make_shared<std::stringstream>();
	auto category_titles_stream = std::make_shared<std::stringstream>();
	auto redirects_stream = std::make_shared<std::stringstream>();
	std::mutex article_titles_mutex;
	std::mutex category_titles_mutex;
	std::mutex redirect_mutex;
	ArticleDatesAndCategoriesHandler art_handler(*article_titles_stream, *article_dates_stream, *category_titles_stream, *redirects_stream, article_titles_mutex, category_titles_mutex, redirect_mutex);
	art_handler.ExtractOnlyArticlesWithDates = false;
	WikiXmlDumpXerces::SingleCoreParser parser(art_handler, parser_properties);
	parser.RunOnString(content);

	article_titles_stream->seekg(0);
	article_dates_stream->seekg(0);
	category_titles_stream->seekg(0);
	redirects_stream->seekg(0);

	// terminate xerces

	auto article_titles_sorted_stream = std::make_shared<std::stringstream>();
	auto article_dates_sorted_stream = std::make_shared<std::stringstream>();
	auto category_titles_sorted_stream = std::make_shared<std::stringstream>();
	sort_article_files(*article_titles_stream, *article_dates_stream, *article_titles_sorted_stream, *article_dates_sorted_stream);
	sort_category_files(*category_titles_stream, *category_titles_sorted_stream);

	article_titles_sorted_stream->seekg(0);
	category_titles_sorted_stream->seekg(0);

	WikiMainPath::WikiDataCache wiki_data_cache(article_titles_sorted_stream, article_dates_sorted_stream, category_titles_sorted_stream, redirects_stream);
	auto& article_titles = wiki_data_cache.article_titles();
	auto& category_titles = wiki_data_cache.category_titles();
	auto& redirects = wiki_data_cache.redirects();
	std::vector<boost::container::flat_set<std::size_t>> category_has_article(category_titles.size());
	AllLinksArticleHander::CategoryHirachyGraph category_hirachy_graph(category_titles.size());
	std::vector<boost::container::flat_set<std::size_t>> article_adjacency_list(article_titles.size());
	VectorMutex<1000> vector_mutex;

	AllLinksArticleHander all_links_handler(article_titles, category_titles, redirects, category_has_article, category_hirachy_graph, article_adjacency_list, vector_mutex);
	WikiXmlDumpXerces::SingleCoreParser parser2(all_links_handler, parser_properties);
	parser2.RunOnString(content);

	xercesc::XMLPlatformUtils::Terminate();

	for (auto title : category_titles) {
		std::cout << title << std::endl;
	}

	recursiveFillCategories(category_hirachy_graph, category_has_article);

	for (auto containment : expected_category_containment) {
		auto it_1 = std::find(article_titles.begin(), article_titles.end(), containment.first);
		auto it_2 = std::find(category_titles.begin(), category_titles.end(), containment.second);

		bool found_article = it_1 != article_titles.end();
		bool found_category= it_2 != category_titles.end();

		BOOST_CHECK(found_article);
		BOOST_CHECK(found_category);

		std::size_t i_article = it_1-article_titles.begin();
		std::size_t i_category = it_2-category_titles.begin();

		if(found_article && found_category)
		{
			bool found = std::find(category_has_article[i_category].begin(), category_has_article[i_category].end(), i_article) != category_has_article[i_category].end();
			if(!found)
				std::cout << containment.first << " - " << containment.second << std::endl;
			BOOST_CHECK(found);
		}

	}
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "navigatortreemodel.h"

#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <abstractview.h>
#include <qmlitemnode.h>
#include <invalididexception.h>

#include <QMimeData>

namespace QmlDesigner {

NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
    : QStandardItemModel(parent)
{
    invisibleRootItem()->setFlags(Qt::NoItemFlags);

    setHorizontalHeaderItem(0,  new QStandardItem(tr("Name")));
    setHorizontalHeaderItem(1,  new QStandardItem(tr("Type")));
    setHorizontalHeaderItem(2,  new QStandardItem(tr("Show in Editor")));

    setSupportedDragActions(Qt::LinkAction);

    connect(this, SIGNAL(itemChanged(QStandardItem*)),
            this, SLOT(handleChangedItem(QStandardItem*)));
}

NavigatorTreeModel::~NavigatorTreeModel()
{
}

Qt::DropActions NavigatorTreeModel::supportedDropActions() const
{
    return Qt::LinkAction;
}

QStringList NavigatorTreeModel::mimeTypes() const
{
     QStringList types;
     types << "application/vnd.modelnode.list";
     return types;
}

QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
{
     QMimeData *mimeData = new QMimeData();
     QByteArray encodedData;

     QSet<QModelIndex> rowAlreadyUsedSet;

     QDataStream stream(&encodedData, QIODevice::WriteOnly);

     foreach (const QModelIndex &index, indexList) {
         if (!index.isValid())
             continue;
         QModelIndex idIndex = index.sibling(index.row(), 0);
         if (rowAlreadyUsedSet.contains(idIndex))
             continue;

         rowAlreadyUsedSet.insert(idIndex);
         stream << idIndex.data(Qt::UserRole).toUInt();
     }

     mimeData->setData("application/vnd.modelnode.list", encodedData);

     return mimeData;
}

static bool isAnchestorInList(const ModelNode &node, const QList<ModelNode> &nodeList)
{
    foreach (const ModelNode &nodeInList, nodeList) {
        if (nodeInList.isAncestorOf(node))
            return true;
    }

    return false;
}

bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
                  Qt::DropAction action,
                  int row,
                  int column,
                  const QModelIndex &parentIndex)
{
    if (action == Qt::IgnoreAction)
        return true;
    if (action != Qt::LinkAction)
        return false;
    if (!data->hasFormat("application/vnd.modelnode.list"))
        return false;
    if (column > 1)
        return false;
    if (parentIndex.model() != this)
        return false;

    QModelIndex parentIdIndex = parentIndex;
    parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);

    Q_ASSERT(parentIdIndex.isValid());

    int targetIndex = 0;
    if (row > -1) {
        targetIndex = row;
    } else {
        targetIndex = rowCount(parentIdIndex);
    }

    QByteArray encodedData = data->data("application/vnd.modelnode.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    uint nodeHash = parentIdIndex.data(Qt::UserRole).toUInt();
    QmlItemNode parentItemNode(nodeForHash(nodeHash));

    QList<ModelNode> nodeList;

    while (!stream.atEnd()) {
        uint nodeHash;
        stream >> nodeHash;
        ModelNode node(nodeForHash(nodeHash));
        if (!node.isValid() || node.isAncestorOf(parentItemNode))
            return false;
        nodeList.append(node);
    }

    RewriterTransaction transaction = m_view->beginRewriterTransaction();
    foreach (const ModelNode &node, nodeList) {
        if (!isAnchestorInList(node, nodeList)) {
            if (node.parentProperty().parentModelNode() != parentItemNode) {
                QmlItemNode itemNode(node);
                if (node != parentItemNode) {
                    itemNode.setParent(parentItemNode);
                }
            }

            if (node.parentProperty().isNodeListProperty()) {
                int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
                if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
                    --targetIndex;
                }
                if (index != targetIndex) {
                    node.parentProperty().toNodeListProperty().slide(index, targetIndex);
                }
            }
        }
    }

    return false; // don't let the view do drag&drop on its own
}

NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &node)
{
    Q_ASSERT(node.isValid());

    uint hash = qHash(node);

    QStandardItem *idItem = new QStandardItem;
    idItem->setDragEnabled(true);
    idItem->setDropEnabled(node.metaInfo().isContainer());
    idItem->setEditable(true);
    idItem->setData(hash, Qt::UserRole);

    QStandardItem *typeItem = new QStandardItem;
    typeItem->setDragEnabled(true);
    idItem->setDropEnabled(node.metaInfo().isContainer());
    typeItem->setEditable(false);
    typeItem->setData(hash, Qt::UserRole);

    QStandardItem *visibilityItem = new QStandardItem;
    visibilityItem->setDropEnabled(node.metaInfo().isContainer());
    visibilityItem->setCheckable(true);
    visibilityItem->setData(hash, Qt::UserRole);

    return ItemRow(idItem, typeItem, visibilityItem);
}

void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
{
    items.idItem->setText(node.id());
    items.typeItem->setText(node.simplifiedTypeName());
    items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
}

/**
  Update the information shown for a node / property
  */
void NavigatorTreeModel::updateItemRow(const ModelNode &node)
{
    if (!containsNode(node))
        return;
    updateItemRow(node, itemRowForNode(node));
}

/**
  Updates the sibling position of the item, depending on the position in the model.
  */
void NavigatorTreeModel::updateItemRowOrder(const ModelNode &node)
{
    if (!containsNode(node))
        return;
    ItemRow itemRow = itemRowForNode(node);
    int currentRow = itemRow.idItem->row();
    int newRow = currentRow;
    if (node.parentProperty().parentModelNode().isValid())
        newRow = modelNodeChildren(node.parentProperty().parentModelNode()).indexOf(node);
    Q_ASSERT(newRow >= 0);

    if (currentRow != newRow) {
        QStandardItem *parentIdItem = itemRow.idItem->parent();
        QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
        parentIdItem->insertRow(newRow, items);
    }
}

void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
{
    uint nodeHash = item->data(Qt::UserRole).toUInt();
    Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
    ModelNode node = nodeForHash(nodeHash);

    ItemRow itemRow = itemRowForNode(node);
    if (item == itemRow.idItem) {
        try {
            if (ModelNode::isValidId(item->text()))
                node.setId(item->text());
            else
                item->setText(node.id());
        } catch (InvalidIdException &) {
            item->setText(node.id());
        }
    } else if (item == itemRow.visibilityItem) {
        bool invisible = (item->checkState() == Qt::Unchecked);

        node.setAuxiliaryData("invisible", invisible);
    }
}

ModelNode NavigatorTreeModel::nodeForHash(uint hash) const
{
    ModelNode node = m_nodeHash.value(hash);
    Q_ASSERT(node.isValid());
    return node;
}

bool NavigatorTreeModel::containsNodeHash(uint hash) const
{
    return m_nodeHash.contains(hash);
}

bool NavigatorTreeModel::containsNode(const ModelNode &node) const
{
    return m_nodeItemHash.contains(node);
}

NavigatorTreeModel::ItemRow NavigatorTreeModel::itemRowForNode(const ModelNode &node)
{
    Q_ASSERT(node.isValid());
    return m_nodeItemHash.value(node);
}

void NavigatorTreeModel::setView(AbstractView *view)
{
    m_view = view;
    addSubTree(view->rootModelNode());
}

void NavigatorTreeModel::clearView()
{
    m_view.clear();
    m_nodeHash.clear();
    m_nodeItemHash.clear();
    clear();
}

QModelIndex NavigatorTreeModel::indexForNode(const ModelNode &node) const
{
    Q_ASSERT(node.isValid());
    if (!containsNode(node))
        return QModelIndex();
    ItemRow row = m_nodeItemHash.value(node);
    return row.idItem->index();
}

ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
    uint hash = index.data(Qt::UserRole).toUInt();
    Q_ASSERT(hash);
    Q_ASSERT(containsNodeHash(hash));
    return nodeForHash(hash);
}

bool NavigatorTreeModel::isInTree(const ModelNode &node) const
{
    return m_nodeHash.keys().contains(qHash(node));
}

/**
  Adds node & all children to the visible tree hierarchy (if node should be visible at all).

  It always adds the node to the _end_ of the list of items.
  */
void NavigatorTreeModel::addSubTree(const ModelNode &node)
{
    Q_ASSERT(node.isValid());
    Q_ASSERT(!containsNodeHash(qHash(node)));

    // only add items that are in the modelNodeChildren list (that means, visible in the editor)
    if (!node.isRootNode()
        && !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
        return;
    }

    ItemRow newRow = createItemRow(node);
    m_nodeHash.insert(qHash(node), node);
    m_nodeItemHash.insert(node, newRow);

    updateItemRow(node, newRow);

    foreach (const ModelNode &childNode, modelNodeChildren(node))
        addSubTree(childNode);

    // We assume that the node is always added to the _end_ of the property list.
    if (node.hasParentProperty()) {
        ItemRow parentRow = itemRowForNode(node.parentProperty().parentModelNode());
        if (parentRow.idItem)
            parentRow.idItem->appendRow(newRow.toList());
    } else {
        appendRow(newRow.toList());
    }
}

/**
  Deletes visual representation for the node (subtree).
  */
void NavigatorTreeModel::removeSubTree(const ModelNode &node)
{
    Q_ASSERT(node.isValid());

    if (!containsNode(node))
        return;

    QList<QStandardItem*> rowList;
    ItemRow itemRow = itemRowForNode(node);
    if (itemRow.idItem->parent()) {
        rowList = itemRow.idItem->parent()->takeRow(itemRow.idItem->row());
    }

    foreach (const ModelNode &node, modelNodeChildren(node)) {
        removeSubTree(node);
    }

    qDeleteAll(rowList);

    m_nodeHash.remove(qHash(node));
    m_nodeItemHash.remove(node);
}

QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
{
    QList<ModelNode> children;
    if (QmlItemNode(parentNode).isValid())
        foreach (const QmlItemNode &childNode, QmlItemNode(parentNode).children())
            children << childNode.modelNode();
    return children;
}

}

<commit_msg>Fix crash in QmlDesigner navigator<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "navigatortreemodel.h"

#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <abstractview.h>
#include <qmlitemnode.h>
#include <invalididexception.h>

#include <QMimeData>

namespace QmlDesigner {

NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
    : QStandardItemModel(parent)
{
    invisibleRootItem()->setFlags(Qt::NoItemFlags);

    setHorizontalHeaderItem(0,  new QStandardItem(tr("Name")));
    setHorizontalHeaderItem(1,  new QStandardItem(tr("Type")));
    setHorizontalHeaderItem(2,  new QStandardItem(tr("Show in Editor")));

    setSupportedDragActions(Qt::LinkAction);

    connect(this, SIGNAL(itemChanged(QStandardItem*)),
            this, SLOT(handleChangedItem(QStandardItem*)));
}

NavigatorTreeModel::~NavigatorTreeModel()
{
}

Qt::DropActions NavigatorTreeModel::supportedDropActions() const
{
    return Qt::LinkAction;
}

QStringList NavigatorTreeModel::mimeTypes() const
{
     QStringList types;
     types << "application/vnd.modelnode.list";
     return types;
}

QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
{
     QMimeData *mimeData = new QMimeData();
     QByteArray encodedData;

     QSet<QModelIndex> rowAlreadyUsedSet;

     QDataStream stream(&encodedData, QIODevice::WriteOnly);

     foreach (const QModelIndex &index, indexList) {
         if (!index.isValid())
             continue;
         QModelIndex idIndex = index.sibling(index.row(), 0);
         if (rowAlreadyUsedSet.contains(idIndex))
             continue;

         rowAlreadyUsedSet.insert(idIndex);
         stream << idIndex.data(Qt::UserRole).toUInt();
     }

     mimeData->setData("application/vnd.modelnode.list", encodedData);

     return mimeData;
}

static bool isAnchestorInList(const ModelNode &node, const QList<ModelNode> &nodeList)
{
    foreach (const ModelNode &nodeInList, nodeList) {
        if (nodeInList.isAncestorOf(node))
            return true;
    }

    return false;
}

bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
                  Qt::DropAction action,
                  int row,
                  int column,
                  const QModelIndex &parentIndex)
{
    if (action == Qt::IgnoreAction)
        return true;
    if (action != Qt::LinkAction)
        return false;
    if (!data->hasFormat("application/vnd.modelnode.list"))
        return false;
    if (column > 1)
        return false;
    if (parentIndex.model() != this)
        return false;

    QModelIndex parentIdIndex = parentIndex;
    parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);

    Q_ASSERT(parentIdIndex.isValid());

    int targetIndex = 0;
    if (row > -1) {
        targetIndex = row;
    } else {
        targetIndex = rowCount(parentIdIndex);
    }

    QByteArray encodedData = data->data("application/vnd.modelnode.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    QmlItemNode parentItemNode(nodeForIndex(parentIdIndex));

    QList<ModelNode> nodeList;

    while (!stream.atEnd()) {
        uint nodeHash;
        stream >> nodeHash;
        ModelNode node(nodeForHash(nodeHash));
        if (!node.isValid() || (parentItemNode == node) || node.isAncestorOf(parentItemNode))
            continue;
        nodeList.append(node);
    }

    RewriterTransaction transaction = m_view->beginRewriterTransaction();
    foreach (const ModelNode &node, nodeList) {
        if (!isAnchestorInList(node, nodeList)) {
            if (node.parentProperty().parentModelNode() != parentItemNode) {
                QmlItemNode itemNode(node);
                if (node != parentItemNode) {
                    itemNode.setParent(parentItemNode);
                }
            }

            if (node.parentProperty().isNodeListProperty()) {
                int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
                if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
                    --targetIndex;
                }
                if (index != targetIndex) {
                    node.parentProperty().toNodeListProperty().slide(index, targetIndex);
                }
            }
        }
    }

    return false; // don't let the view do drag&drop on its own
}

NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &node)
{
    Q_ASSERT(node.isValid());

    uint hash = qHash(node);

    QStandardItem *idItem = new QStandardItem;
    idItem->setDragEnabled(true);
    idItem->setDropEnabled(node.metaInfo().isContainer());
    idItem->setEditable(true);
    idItem->setData(hash, Qt::UserRole);

    QStandardItem *typeItem = new QStandardItem;
    typeItem->setDragEnabled(true);
    idItem->setDropEnabled(node.metaInfo().isContainer());
    typeItem->setEditable(false);
    typeItem->setData(hash, Qt::UserRole);

    QStandardItem *visibilityItem = new QStandardItem;
    visibilityItem->setDropEnabled(node.metaInfo().isContainer());
    visibilityItem->setCheckable(true);
    visibilityItem->setData(hash, Qt::UserRole);

    return ItemRow(idItem, typeItem, visibilityItem);
}

void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
{
    items.idItem->setText(node.id());
    items.typeItem->setText(node.simplifiedTypeName());
    items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
}

/**
  Update the information shown for a node / property
  */
void NavigatorTreeModel::updateItemRow(const ModelNode &node)
{
    if (!containsNode(node))
        return;
    updateItemRow(node, itemRowForNode(node));
}

/**
  Updates the sibling position of the item, depending on the position in the model.
  */
void NavigatorTreeModel::updateItemRowOrder(const ModelNode &node)
{
    if (!containsNode(node))
        return;
    ItemRow itemRow = itemRowForNode(node);
    int currentRow = itemRow.idItem->row();
    int newRow = currentRow;
    if (node.parentProperty().parentModelNode().isValid())
        newRow = modelNodeChildren(node.parentProperty().parentModelNode()).indexOf(node);
    Q_ASSERT(newRow >= 0);

    if (currentRow != newRow) {
        QStandardItem *parentIdItem = itemRow.idItem->parent();
        QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
        parentIdItem->insertRow(newRow, items);
    }
}

void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
{
    uint nodeHash = item->data(Qt::UserRole).toUInt();
    Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
    ModelNode node = nodeForHash(nodeHash);

    ItemRow itemRow = itemRowForNode(node);
    if (item == itemRow.idItem) {
        try {
            if (ModelNode::isValidId(item->text()))
                node.setId(item->text());
            else
                item->setText(node.id());
        } catch (InvalidIdException &) {
            item->setText(node.id());
        }
    } else if (item == itemRow.visibilityItem) {
        bool invisible = (item->checkState() == Qt::Unchecked);

        node.setAuxiliaryData("invisible", invisible);
    }
}

ModelNode NavigatorTreeModel::nodeForHash(uint hash) const
{
    ModelNode node = m_nodeHash.value(hash);
    Q_ASSERT(node.isValid());
    return node;
}

bool NavigatorTreeModel::containsNodeHash(uint hash) const
{
    return m_nodeHash.contains(hash);
}

bool NavigatorTreeModel::containsNode(const ModelNode &node) const
{
    return m_nodeItemHash.contains(node);
}

NavigatorTreeModel::ItemRow NavigatorTreeModel::itemRowForNode(const ModelNode &node)
{
    Q_ASSERT(node.isValid());
    return m_nodeItemHash.value(node);
}

void NavigatorTreeModel::setView(AbstractView *view)
{
    m_view = view;
    addSubTree(view->rootModelNode());
}

void NavigatorTreeModel::clearView()
{
    m_view.clear();
    m_nodeHash.clear();
    m_nodeItemHash.clear();
    clear();
}

QModelIndex NavigatorTreeModel::indexForNode(const ModelNode &node) const
{
    Q_ASSERT(node.isValid());
    if (!containsNode(node))
        return QModelIndex();
    ItemRow row = m_nodeItemHash.value(node);
    return row.idItem->index();
}

ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
    uint hash = index.data(Qt::UserRole).toUInt();
    Q_ASSERT(hash);
    Q_ASSERT(containsNodeHash(hash));
    return nodeForHash(hash);
}

bool NavigatorTreeModel::isInTree(const ModelNode &node) const
{
    return m_nodeHash.keys().contains(qHash(node));
}

/**
  Adds node & all children to the visible tree hierarchy (if node should be visible at all).

  It always adds the node to the _end_ of the list of items.
  */
void NavigatorTreeModel::addSubTree(const ModelNode &node)
{
    Q_ASSERT(node.isValid());
    Q_ASSERT(!containsNodeHash(qHash(node)));

    // only add items that are in the modelNodeChildren list (that means, visible in the editor)
    if (!node.isRootNode()
        && !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
        return;
    }

    ItemRow newRow = createItemRow(node);
    m_nodeHash.insert(qHash(node), node);
    m_nodeItemHash.insert(node, newRow);

    updateItemRow(node, newRow);

    foreach (const ModelNode &childNode, modelNodeChildren(node))
        addSubTree(childNode);

    // We assume that the node is always added to the _end_ of the property list.
    if (node.hasParentProperty()) {
        ItemRow parentRow = itemRowForNode(node.parentProperty().parentModelNode());
        if (parentRow.idItem)
            parentRow.idItem->appendRow(newRow.toList());
    } else {
        appendRow(newRow.toList());
    }
}

/**
  Deletes visual representation for the node (subtree).
  */
void NavigatorTreeModel::removeSubTree(const ModelNode &node)
{
    Q_ASSERT(node.isValid());

    if (!containsNode(node))
        return;

    QList<QStandardItem*> rowList;
    ItemRow itemRow = itemRowForNode(node);
    if (itemRow.idItem->parent()) {
        rowList = itemRow.idItem->parent()->takeRow(itemRow.idItem->row());
    }

    foreach (const ModelNode &node, modelNodeChildren(node)) {
        removeSubTree(node);
    }

    qDeleteAll(rowList);

    m_nodeHash.remove(qHash(node));
    m_nodeItemHash.remove(node);
}

QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
{
    QList<ModelNode> children;
    if (QmlItemNode(parentNode).isValid())
        foreach (const QmlItemNode &childNode, QmlItemNode(parentNode).children())
            children << childNode.modelNode();
    return children;
}

}

<|endoftext|>


<commit_before>/*

    Copyright Eli Dupree and Isaac Dupree, 2014

    This file is part of Lasercake.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#define GLM_FORCE_RADIANS
//#define GLM_PRECISION_MEDIUMP_FLOAT

#include <iostream>
#include <cstddef>

#include "green_caves.cpp"
#include "../testcase_draw.cpp"

gl_data_format::color green_color(0x00ff00ff);
gl_data_format::color black_color(0x000000ff);

struct gl_draw_funcs {
  gl_draw_funcs(gl_triangles& triangles) : triangles(triangles){}
  gl_triangles& triangles;
  void circle(double cx, double cy, double r) {
    gl_data_format::vertex_with_color first;
    gl_data_format::vertex_with_color prev;
    gl_data_format::vertex_with_color center(cx, cy, 0, green_color);
    for (double theta = 0; ; theta += 0.3) {
      gl_data_format::vertex_with_color cur(
        cx + std::cos(theta)*r,
        cy + std::sin(theta)*r,
        0,
        green_color);
      if (theta == 0) {
        first = cur;
      }
      else {
        if (theta >= 6.283) {
          triangles.push_back(gl_triangle{{{ center, prev, first }}});
          break;
        }
        else {
          triangles.push_back(gl_triangle{{{ center, prev, cur }}});
        }
      }
      prev = cur;
    }
  }
  void rect(double x0, double y0, double x1, double y1, bool color) {
    gl_data_format::color c = color ? green_color : black_color;
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0, y0, 0, c),
      gl_data_format::vertex_with_color(x1, y0, 0, c),
      gl_data_format::vertex_with_color(x1, y1, 0, c) }}});
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0, y0, 0, c),
      gl_data_format::vertex_with_color(x0, y1, 0, c),
      gl_data_format::vertex_with_color(x1, y1, 0, c) }}});
  }
  void segment(double x0, double y0, double x1, double y1, double width) {
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0+width, y0, 0, green_color),
      gl_data_format::vertex_with_color(x0-width, y0, 0, green_color),
      gl_data_format::vertex_with_color(x1, y1, 0, green_color) }}});
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0, y0+width, 0, green_color),
      gl_data_format::vertex_with_color(x0, y0-width, 0, green_color),
      gl_data_format::vertex_with_color(x1, y1, 0, green_color) }}});
  }
};

gl_triangles display(green_caves_ui_backend& backend) {
  gl_triangles triangles;
  gl_draw_funcs draw(triangles);
  backend.draw(draw);

  return triangles;
}

#if 0
std::string read_file(const char* filename) {
  // https://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
  // " Turns out that this method, while following STL idioms well, is actually surprisingly inefficient! Don't do this with large files. "
  std::ifstream t(filename);
  std::string str((std::istreambuf_iterator<char>(t)),
                   std::istreambuf_iterator<char>());
  return str;
}
#endif

void shader_debug_info(GLuint obj) {
  int infologLength = 0;
  int charsWritten  = 0;
  char* infoLog;

  glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);

  if(infologLength > 0) {
    infoLog = (char *)malloc(infologLength);
    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
    printf("%s\n",infoLog);
    free(infoLog);
  }
}

void program_debug_info(GLuint obj) {
  int infologLength = 0;
  int charsWritten  = 0;
  char* infoLog;

  glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);

  if(infologLength > 0) {
    infoLog = (char *)malloc(infologLength);
    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
    printf("%s\n",infoLog);
    free(infoLog);
  }
}
GLuint shader_program_name;
void add_shaders() {
  GLuint v,f,f2,p;

  v = glCreateShader(GL_VERTEX_SHADER);
  f = glCreateShader(GL_FRAGMENT_SHADER);
 // f2 = glCreateShader(GL_FRAGMENT_SHADER);

  //std::string vs = read_file("horrible.vert");
  //std::string fs = read_file("horrible.frag");
  const char* vs =
#ifdef EMSCRIPTEN
"precision mediump float;\n"
#endif
"uniform mat4 transformation;\n"
"attribute vec3 position;\n"
"attribute vec4 color;\n"
"varying vec4 colorV;\n"
"void main() {\n"
"  colorV = color;\n"
// This is the deprecated way to do it that doesn't work at all in OpenGL ES 2.0 / WebGL:
//"  gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);\n"
"  gl_Position = transformation * vec4(position, 1.0);\n"
"}\n"
;
  const char* fs =
#ifdef EMSCRIPTEN
"precision mediump float;\n"
#endif
"varying vec4 colorV;\n"
"void main() {\n"
"  gl_FragColor = colorV;\n"
"}\n"
;

  glShaderSource(v, 1, &vs, NULL);
  glShaderSource(f, 1, &fs, NULL);

  glCompileShader(v);
  glCompileShader(f);

  shader_debug_info(v);
  shader_debug_info(f);

  p = glCreateProgram();
  glAttachShader(p,v);
  glAttachShader(p,f);

  glLinkProgram(p);
  program_debug_info(p);

  glUseProgram(p);

  glEnableVertexAttribArray(0);
  shader_program_name = p;
}

void do_gl(green_caves_ui_backend& backend) {
  static bool first_time = true;//hack
  if(first_time) {
    add_shaders();
    first_time = false;
  }
  //std::cerr<<"hi.\n";
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);

  gl_triangles data = display(backend);
  if(const size_t count = data.size()*3) {
    GLuint triangles_VBO_name;
    glGenBuffers(1, &triangles_VBO_name);
    glBindBuffer(GL_ARRAY_BUFFER, triangles_VBO_name);
    glBufferData(GL_ARRAY_BUFFER, count*sizeof(gl_data_format::vertex_with_color), &data[0], GL_STREAM_DRAW);
    //glBufferData(GL_ARRAY_BUFFER, count*sizeof(vertex_with_color), data.vertices, GL_STREAM_DRAW);
    auto position_attrib_location = glGetAttribLocation(shader_program_name, "position");
    auto color_attrib_location = glGetAttribLocation(shader_program_name, "color");
        if(GLEW_VERSION_2_0) {
          //std::cerr << "GLEW_VERSION_2_0\n";
#define BUFFER_OFFSET(i) ((void*)(i))
          glVertexAttribPointer(color_attrib_location, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(gl_data_format::vertex_with_color), BUFFER_OFFSET(0+offsetof(gl_data_format::vertex_with_color, c)));
          glVertexAttribPointer(position_attrib_location, 3, GL_FLOAT, GL_FALSE, sizeof(gl_data_format::vertex_with_color), BUFFER_OFFSET(0+offsetof(gl_data_format::vertex_with_color, v)));
          glEnableVertexAttribArray(color_attrib_location);
          glEnableVertexAttribArray(position_attrib_location);
          glBindBuffer(GL_ARRAY_BUFFER, 0);
        }else {
          glInterleavedArrays(GL_C4UB_V3F, 0, (void*)(0));
        }
        glDrawArrays(GL_TRIANGLES, 0, count);
        //glDrawElements for indexed mode
        if(GLEW_VERSION_2_0) {
          glDisableVertexAttribArray(position_attrib_location);
          glDisableVertexAttribArray(color_attrib_location);
        }
    //glVertexAttribPointer(, 3, GL_FLOAT, GL_FALSE, sizeof(gl_data_format::vertex_with_color), (void*)4);
    //glEnableVertexAttribArray(glGetAttribLocation(shader_program_name, "position"));
    //      glBindBuffer(GL_ARRAY_BUFFER, 0);
    //glInterleavedArrays(GL_C4UB_V3F, 0, (void*)(0));
    //glDrawArrays(GL_TRIANGLES, 0, count);
    glDeleteBuffers(1, &triangles_VBO_name);
    //glDisableVertexAttribArray(glGetAttribLocation(shader_program_name, "position"));
  }
}

void gl_reshape(int width, int height) {
  glViewport(0,0,width,height);
  const GLint uniform_id = glGetUniformLocation(shader_program_name, "transformation");
  const glm::mat4 transformation = glm::ortho(0.0f, GLfloat(width), 0.0f, GLfloat(height));
  glUniformMatrix4fv(uniform_id, 1, GL_FALSE, glm::value_ptr(transformation));
// This is the deprecated way to do it that doesn't work at all in OpenGL ES 2.0 / WebGL:
//  glLoadIdentity();
//  gluOrtho2D(0, GLdouble(width), 0, GLdouble(height));
}
<commit_msg>Made green-caves lines look better in GL UI<commit_after>/*

    Copyright Eli Dupree and Isaac Dupree, 2014

    This file is part of Lasercake.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#define GLM_FORCE_RADIANS
//#define GLM_PRECISION_MEDIUMP_FLOAT

#include <iostream>
#include <cstddef>

#include "green_caves.cpp"
#include "../testcase_draw.cpp"

gl_data_format::color green_color(0x00ff00ff);
gl_data_format::color black_color(0x000000ff);

struct gl_draw_funcs {
  gl_draw_funcs(gl_triangles& triangles) : triangles(triangles){}
  gl_triangles& triangles;
  void circle(double cx, double cy, double r) {
    gl_data_format::vertex_with_color first;
    gl_data_format::vertex_with_color prev;
    gl_data_format::vertex_with_color center(cx, cy, 0, green_color);
    for (double theta = 0; ; theta += 0.3) {
      gl_data_format::vertex_with_color cur(
        cx + std::cos(theta)*r,
        cy + std::sin(theta)*r,
        0,
        green_color);
      if (theta == 0) {
        first = cur;
      }
      else {
        if (theta >= 6.283) {
          triangles.push_back(gl_triangle{{{ center, prev, first }}});
          break;
        }
        else {
          triangles.push_back(gl_triangle{{{ center, prev, cur }}});
        }
      }
      prev = cur;
    }
  }
  void rect(double x0, double y0, double x1, double y1, bool color) {
    gl_data_format::color c = color ? green_color : black_color;
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0, y0, 0, c),
      gl_data_format::vertex_with_color(x1, y0, 0, c),
      gl_data_format::vertex_with_color(x1, y1, 0, c) }}});
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0, y0, 0, c),
      gl_data_format::vertex_with_color(x0, y1, 0, c),
      gl_data_format::vertex_with_color(x1, y1, 0, c) }}});
  }
  void segment(double x0, double y0, double x1, double y1, double width) {
    double m = std::sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
    double dx = (y1-y0)*width/m/2;
    double dy = -(x1-x0)*width/m/2;
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x0+dx, y0+dy, 0, green_color),
      gl_data_format::vertex_with_color(x0-dx, y0-dy, 0, green_color),
      gl_data_format::vertex_with_color(x1+dx, y1+dy, 0, green_color) }}});
    triangles.push_back(gl_triangle{{{
      gl_data_format::vertex_with_color(x1+dx, y1+dy, 0, green_color),
      gl_data_format::vertex_with_color(x1-dx, y1-dy, 0, green_color),
      gl_data_format::vertex_with_color(x0-dx, y0-dy, 0, green_color) }}});
  }
};

gl_triangles display(green_caves_ui_backend& backend) {
  gl_triangles triangles;
  gl_draw_funcs draw(triangles);
  backend.draw(draw);

  return triangles;
}

#if 0
std::string read_file(const char* filename) {
  // https://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
  // " Turns out that this method, while following STL idioms well, is actually surprisingly inefficient! Don't do this with large files. "
  std::ifstream t(filename);
  std::string str((std::istreambuf_iterator<char>(t)),
                   std::istreambuf_iterator<char>());
  return str;
}
#endif

void shader_debug_info(GLuint obj) {
  int infologLength = 0;
  int charsWritten  = 0;
  char* infoLog;

  glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);

  if(infologLength > 0) {
    infoLog = (char *)malloc(infologLength);
    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
    printf("%s\n",infoLog);
    free(infoLog);
  }
}

void program_debug_info(GLuint obj) {
  int infologLength = 0;
  int charsWritten  = 0;
  char* infoLog;

  glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);

  if(infologLength > 0) {
    infoLog = (char *)malloc(infologLength);
    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
    printf("%s\n",infoLog);
    free(infoLog);
  }
}
GLuint shader_program_name;
void add_shaders() {
  GLuint v,f,f2,p;

  v = glCreateShader(GL_VERTEX_SHADER);
  f = glCreateShader(GL_FRAGMENT_SHADER);
 // f2 = glCreateShader(GL_FRAGMENT_SHADER);

  //std::string vs = read_file("horrible.vert");
  //std::string fs = read_file("horrible.frag");
  const char* vs =
#ifdef EMSCRIPTEN
"precision mediump float;\n"
#endif
"uniform mat4 transformation;\n"
"attribute vec3 position;\n"
"attribute vec4 color;\n"
"varying vec4 colorV;\n"
"void main() {\n"
"  colorV = color;\n"
// This is the deprecated way to do it that doesn't work at all in OpenGL ES 2.0 / WebGL:
//"  gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);\n"
"  gl_Position = transformation * vec4(position, 1.0);\n"
"}\n"
;
  const char* fs =
#ifdef EMSCRIPTEN
"precision mediump float;\n"
#endif
"varying vec4 colorV;\n"
"void main() {\n"
"  gl_FragColor = colorV;\n"
"}\n"
;

  glShaderSource(v, 1, &vs, NULL);
  glShaderSource(f, 1, &fs, NULL);

  glCompileShader(v);
  glCompileShader(f);

  shader_debug_info(v);
  shader_debug_info(f);

  p = glCreateProgram();
  glAttachShader(p,v);
  glAttachShader(p,f);

  glLinkProgram(p);
  program_debug_info(p);

  glUseProgram(p);

  glEnableVertexAttribArray(0);
  shader_program_name = p;
}

void do_gl(green_caves_ui_backend& backend) {
  static bool first_time = true;//hack
  if(first_time) {
    add_shaders();
    first_time = false;
  }
  //std::cerr<<"hi.\n";
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);

  gl_triangles data = display(backend);
  if(const size_t count = data.size()*3) {
    GLuint triangles_VBO_name;
    glGenBuffers(1, &triangles_VBO_name);
    glBindBuffer(GL_ARRAY_BUFFER, triangles_VBO_name);
    glBufferData(GL_ARRAY_BUFFER, count*sizeof(gl_data_format::vertex_with_color), &data[0], GL_STREAM_DRAW);
    //glBufferData(GL_ARRAY_BUFFER, count*sizeof(vertex_with_color), data.vertices, GL_STREAM_DRAW);
    auto position_attrib_location = glGetAttribLocation(shader_program_name, "position");
    auto color_attrib_location = glGetAttribLocation(shader_program_name, "color");
        if(GLEW_VERSION_2_0) {
          //std::cerr << "GLEW_VERSION_2_0\n";
#define BUFFER_OFFSET(i) ((void*)(i))
          glVertexAttribPointer(color_attrib_location, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(gl_data_format::vertex_with_color), BUFFER_OFFSET(0+offsetof(gl_data_format::vertex_with_color, c)));
          glVertexAttribPointer(position_attrib_location, 3, GL_FLOAT, GL_FALSE, sizeof(gl_data_format::vertex_with_color), BUFFER_OFFSET(0+offsetof(gl_data_format::vertex_with_color, v)));
          glEnableVertexAttribArray(color_attrib_location);
          glEnableVertexAttribArray(position_attrib_location);
          glBindBuffer(GL_ARRAY_BUFFER, 0);
        }else {
          glInterleavedArrays(GL_C4UB_V3F, 0, (void*)(0));
        }
        glDrawArrays(GL_TRIANGLES, 0, count);
        //glDrawElements for indexed mode
        if(GLEW_VERSION_2_0) {
          glDisableVertexAttribArray(position_attrib_location);
          glDisableVertexAttribArray(color_attrib_location);
        }
    //glVertexAttribPointer(, 3, GL_FLOAT, GL_FALSE, sizeof(gl_data_format::vertex_with_color), (void*)4);
    //glEnableVertexAttribArray(glGetAttribLocation(shader_program_name, "position"));
    //      glBindBuffer(GL_ARRAY_BUFFER, 0);
    //glInterleavedArrays(GL_C4UB_V3F, 0, (void*)(0));
    //glDrawArrays(GL_TRIANGLES, 0, count);
    glDeleteBuffers(1, &triangles_VBO_name);
    //glDisableVertexAttribArray(glGetAttribLocation(shader_program_name, "position"));
  }
}

void gl_reshape(int width, int height) {
  glViewport(0,0,width,height);
  const GLint uniform_id = glGetUniformLocation(shader_program_name, "transformation");
  const glm::mat4 transformation = glm::ortho(0.0f, GLfloat(width), 0.0f, GLfloat(height));
  glUniformMatrix4fv(uniform_id, 1, GL_FALSE, glm::value_ptr(transformation));
// This is the deprecated way to do it that doesn't work at all in OpenGL ES 2.0 / WebGL:
//  glLoadIdentity();
//  gluOrtho2D(0, GLdouble(width), 0, GLdouble(height));
}
<|endoftext|>


<commit_before><commit_msg>Update factory classes<commit_after><|endoftext|>


<commit_before>#include "Genes/Look_Ahead_Gene.h"

#include <cassert>
#include <memory>
#include <algorithm>

#include "Genes/Gene.h"
#include "Utility.h"
#include "Game/Board.h"
#include "Game/Clock.h"

class Move;

Look_Ahead_Gene::Look_Ahead_Gene() :
    mean_game_length(50),
    game_length_uncertainty(0.5),
    speculation_constant(1.0),
    capturing_speculation_constant(1.0)
{
}

void Look_Ahead_Gene::reset_properties() const
{
    properties["Mean Game Length"] = mean_game_length;
    properties["Game Length Uncertainty"] = game_length_uncertainty;
    properties["Speculation Constant"] = speculation_constant;
    properties["Capturing Speculation Constant"] = capturing_speculation_constant;
}

void Look_Ahead_Gene::load_properties()
{
    mean_game_length = properties["Mean Game Length"];
    game_length_uncertainty = properties["Game Length Uncertainty"];
    speculation_constant = properties["Speculation Constant"];
    capturing_speculation_constant = properties["Capturing Speculation Constant"];
}

double Look_Ahead_Gene::time_to_examine(const Board& board, const Clock& clock) const
{
    auto time_left = clock.time_left(board.whose_turn());
    auto moves_to_reset = clock.moves_to_reset(board.whose_turn());

    auto moves_so_far = board.get_game_record().size()/2; // only count moves by this player
    auto moves_left = Math::average_moves_left(mean_game_length, game_length_uncertainty, moves_so_far);

    return time_left/std::min(moves_left, double(moves_to_reset));
}

void Look_Ahead_Gene::gene_specific_mutation()
{
    switch(Random::random_integer(1, 4))
    {
        case 1:
            mean_game_length = std::max(1.0, mean_game_length + Random::random_normal(1.0));
            break;
        case 2:
            game_length_uncertainty = std::abs(game_length_uncertainty + Random::random_normal(0.05));
            break;
        case 3:
            speculation_constant += Random::random_normal(0.05);
            break;
        case 4:
            capturing_speculation_constant += Random::random_normal(0.05);
            break;
        default:
            assert(false); // If here, random_integer() called with wrong parameters
            break;
    }
}

std::unique_ptr<Gene> Look_Ahead_Gene::duplicate() const
{
    return std::make_unique<Look_Ahead_Gene>(*this);
}

std::string Look_Ahead_Gene::name() const
{
    return "Look Ahead Gene";
}

double Look_Ahead_Gene::score_board(const Board&) const
{
    return 0.0;
}

double Look_Ahead_Gene::speculation_time_factor(const Board& board) const
{
    return board.capture_possible() ? capturing_speculation_constant : speculation_constant;
}
<commit_msg>More neutral starting point for clock control<commit_after>#include "Genes/Look_Ahead_Gene.h"

#include <cassert>
#include <memory>
#include <algorithm>

#include "Genes/Gene.h"
#include "Utility.h"
#include "Game/Board.h"
#include "Game/Clock.h"

class Move;

Look_Ahead_Gene::Look_Ahead_Gene() :
    mean_game_length(50),
    game_length_uncertainty(0.5),
    speculation_constant(0.0),
    capturing_speculation_constant(0.0)
{
}

void Look_Ahead_Gene::reset_properties() const
{
    properties["Mean Game Length"] = mean_game_length;
    properties["Game Length Uncertainty"] = game_length_uncertainty;
    properties["Speculation Constant"] = speculation_constant;
    properties["Capturing Speculation Constant"] = capturing_speculation_constant;
}

void Look_Ahead_Gene::load_properties()
{
    mean_game_length = properties["Mean Game Length"];
    game_length_uncertainty = properties["Game Length Uncertainty"];
    speculation_constant = properties["Speculation Constant"];
    capturing_speculation_constant = properties["Capturing Speculation Constant"];
}

double Look_Ahead_Gene::time_to_examine(const Board& board, const Clock& clock) const
{
    auto time_left = clock.time_left(board.whose_turn());
    auto moves_to_reset = clock.moves_to_reset(board.whose_turn());

    auto moves_so_far = board.get_game_record().size()/2; // only count moves by this player
    auto moves_left = Math::average_moves_left(mean_game_length, game_length_uncertainty, moves_so_far);

    return time_left/std::min(moves_left, double(moves_to_reset));
}

void Look_Ahead_Gene::gene_specific_mutation()
{
    switch(Random::random_integer(1, 4))
    {
        case 1:
            mean_game_length = std::max(1.0, mean_game_length + Random::random_normal(1.0));
            break;
        case 2:
            game_length_uncertainty = std::abs(game_length_uncertainty + Random::random_normal(0.05));
            break;
        case 3:
            speculation_constant += Random::random_normal(0.05);
            break;
        case 4:
            capturing_speculation_constant += Random::random_normal(0.05);
            break;
        default:
            assert(false); // If here, random_integer() called with wrong parameters
            break;
    }
}

std::unique_ptr<Gene> Look_Ahead_Gene::duplicate() const
{
    return std::make_unique<Look_Ahead_Gene>(*this);
}

std::string Look_Ahead_Gene::name() const
{
    return "Look Ahead Gene";
}

double Look_Ahead_Gene::score_board(const Board&) const
{
    return 0.0;
}

double Look_Ahead_Gene::speculation_time_factor(const Board& board) const
{
    return board.capture_possible() ? capturing_speculation_constant : speculation_constant;
}
<|endoftext|>


<commit_before>#include "Genes/Look_Ahead_Gene.h"

#include <cmath>
#include <cassert>
#include <memory>

#include "Genes/Gene.h"
#include "Utility.h"
#include "Game/Board.h"
#include "Game/Clock.h"
#include "Moves/Move.h"

Look_Ahead_Gene::Look_Ahead_Gene() :
    mean_game_length(50),
    game_length_uncertainty(0.5),
    speculation_constant(1.0),
    capturing_speculation_constant(1.0)
{
}

void Look_Ahead_Gene::reset_properties() const
{
    properties["Mean Game Length"] = mean_game_length;
    properties["Game Length Uncertainty"] = game_length_uncertainty;
    properties["Speculation Constant"] = speculation_constant;
    properties["Capturing Speculation Constant"] = capturing_speculation_constant;
}

void Look_Ahead_Gene::load_properties()
{
    mean_game_length = properties["Mean Game Length"];
    game_length_uncertainty = properties["Game Length Uncertainty"];
    speculation_constant = properties["Speculation Constant"];
    capturing_speculation_constant = properties["Capturing Speculation Constant"];
}

double Look_Ahead_Gene::time_to_examine(const Board& board, const Clock& clock) const
{
    auto time_left = clock.time_left(board.whose_turn());
    auto moves_to_reset = clock.moves_to_reset(board.whose_turn());

    auto moves_so_far = board.get_game_record().size()/2; // only count moves by this player
    auto moves_left = Math::average_moves_left(mean_game_length, game_length_uncertainty, moves_so_far);

    return time_left/std::min(moves_left, double(moves_to_reset));
}

void Look_Ahead_Gene::gene_specific_mutation()
{
    switch(Random::random_integer(1, 4))
    {
        case 1:
            mean_game_length = std::max(1.0, mean_game_length + Random::random_normal(1.0));
            break;
        case 2:
            game_length_uncertainty = std::abs(game_length_uncertainty + Random::random_normal(0.05));
            break;
        case 3:
            speculation_constant += Random::random_normal(0.01);
            break;
        case 4:
            capturing_speculation_constant += Random::random_normal(0.01);
            break;
        default:
            assert(false); // If here, random_integer() called with wrong parameters
            break;
    }
}

std::unique_ptr<Gene> Look_Ahead_Gene::duplicate() const
{
    return std::make_unique<Look_Ahead_Gene>(*this);
}

std::string Look_Ahead_Gene::name() const
{
    return "Look Ahead Gene";
}

double Look_Ahead_Gene::score_board(const Board&) const
{
    return 0.0;
}

double Look_Ahead_Gene::speculation_time_factor(const Board& board) const
{
    return board.capture_possible() ? capturing_speculation_constant : speculation_constant;
}
<commit_msg>Adjust includes<commit_after>#include "Genes/Look_Ahead_Gene.h"

#include <cassert>
#include <memory>
#include <algorithm>

#include "Genes/Gene.h"
#include "Utility.h"
#include "Game/Board.h"
#include "Game/Clock.h"

class Move;

Look_Ahead_Gene::Look_Ahead_Gene() :
    mean_game_length(50),
    game_length_uncertainty(0.5),
    speculation_constant(1.0),
    capturing_speculation_constant(1.0)
{
}

void Look_Ahead_Gene::reset_properties() const
{
    properties["Mean Game Length"] = mean_game_length;
    properties["Game Length Uncertainty"] = game_length_uncertainty;
    properties["Speculation Constant"] = speculation_constant;
    properties["Capturing Speculation Constant"] = capturing_speculation_constant;
}

void Look_Ahead_Gene::load_properties()
{
    mean_game_length = properties["Mean Game Length"];
    game_length_uncertainty = properties["Game Length Uncertainty"];
    speculation_constant = properties["Speculation Constant"];
    capturing_speculation_constant = properties["Capturing Speculation Constant"];
}

double Look_Ahead_Gene::time_to_examine(const Board& board, const Clock& clock) const
{
    auto time_left = clock.time_left(board.whose_turn());
    auto moves_to_reset = clock.moves_to_reset(board.whose_turn());

    auto moves_so_far = board.get_game_record().size()/2; // only count moves by this player
    auto moves_left = Math::average_moves_left(mean_game_length, game_length_uncertainty, moves_so_far);

    return time_left/std::min(moves_left, double(moves_to_reset));
}

void Look_Ahead_Gene::gene_specific_mutation()
{
    switch(Random::random_integer(1, 4))
    {
        case 1:
            mean_game_length = std::max(1.0, mean_game_length + Random::random_normal(1.0));
            break;
        case 2:
            game_length_uncertainty = std::abs(game_length_uncertainty + Random::random_normal(0.05));
            break;
        case 3:
            speculation_constant += Random::random_normal(0.01);
            break;
        case 4:
            capturing_speculation_constant += Random::random_normal(0.01);
            break;
        default:
            assert(false); // If here, random_integer() called with wrong parameters
            break;
    }
}

std::unique_ptr<Gene> Look_Ahead_Gene::duplicate() const
{
    return std::make_unique<Look_Ahead_Gene>(*this);
}

std::string Look_Ahead_Gene::name() const
{
    return "Look Ahead Gene";
}

double Look_Ahead_Gene::score_board(const Board&) const
{
    return 0.0;
}

double Look_Ahead_Gene::speculation_time_factor(const Board& board) const
{
    return board.capture_possible() ? capturing_speculation_constant : speculation_constant;
}
<|endoftext|>