<commit_before>/*************************************************************************
 *
 *  $RCSfile: propertyids.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2006-12-20 12:24:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

#ifndef _CONNECTIVITY_PROPERTYIDS_HXX_
#define _CONNECTIVITY_PROPERTYIDS_HXX_

// this define has to be set to split the names into different dll's or so's
// every dll has his own set of property names
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _MAP_
#include <map>
#endif

namespace connectivity
{
namespace skeleton
{
    class OPropertyMap
    {
        ::std::map<sal_Int32 , rtl_uString*> m_aPropertyMap;

        ::rtl::OUString fillValue(sal_Int32 _nIndex);
    public:
        OPropertyMap()
        {
        }
        ~OPropertyMap();
        ::rtl::OUString getNameByIndex(sal_Int32 _nIndex) const;

        static OPropertyMap& getPropMap()
        {
            static OPropertyMap s_aPropMap;
            return s_aPropMap;
        }
    };

        typedef const sal_Char* (*PVFN)();

        struct UStringDescription
        {
            const sal_Char* pZeroTerminatedName;
            sal_Int32 nLength;

            UStringDescription(PVFN _fCharFkt);
            operator ::rtl::OUString() const { return ::rtl::OUString(pZeroTerminatedName,nLength,RTL_TEXTENCODING_ASCII_US); }
            ~UStringDescription();
        private:
            UStringDescription();
        };
    }
}

//------------------------------------------------------------------------------
#define DECL_PROP1IMPL(varname, type) \
pProperties[nPos++] = ::com::sun::star::beans::Property(OPropertyMap::getPropMap().getNameByIndex(PROPERTY_ID_##varname), PROPERTY_ID_##varname, ::cppu::UnoType< type >::get(),
//------------------------------------------------------------------------------
#define DECL_PROP0(varname, type)   \
    DECL_PROP1IMPL(varname, type) 0)
//------------------------------------------------------------------------------
#define DECL_BOOL_PROP1IMPL(varname) \
        pProperties[nPos++] = ::com::sun::star::beans::Property(OPropertyMap::getPropMap().getNameByIndex(PROPERTY_ID_##varname), PROPERTY_ID_##varname, ::getBooleanCppuType(),
//------------------------------------------------------------------------------
#define DECL_BOOL_PROP0(varname)    \
    DECL_BOOL_PROP1IMPL(varname) 0)

#define PROPERTY_ID_QUERYTIMEOUT                    1
#define PROPERTY_ID_MAXFIELDSIZE                    2
#define PROPERTY_ID_MAXROWS                         3
#define PROPERTY_ID_CURSORNAME                      4
#define PROPERTY_ID_RESULTSETCONCURRENCY            5
#define PROPERTY_ID_RESULTSETTYPE                   6
#define PROPERTY_ID_FETCHDIRECTION                  7
#define PROPERTY_ID_FETCHSIZE                       8
#define PROPERTY_ID_ESCAPEPROCESSING                9
#define PROPERTY_ID_USEBOOKMARKS                    10
// Column
#define PROPERTY_ID_NAME                            11
#define PROPERTY_ID_TYPE                            12
#define PROPERTY_ID_TYPENAME                        13
#define PROPERTY_ID_PRECISION                       14
#define PROPERTY_ID_SCALE                           15
#define PROPERTY_ID_ISNULLABLE                      16
#define PROPERTY_ID_ISAUTOINCREMENT                 17
#define PROPERTY_ID_ISROWVERSION                    18
#define PROPERTY_ID_DESCRIPTION                     19
#define PROPERTY_ID_DEFAULTVALUE                    20

#define PROPERTY_ID_REFERENCEDTABLE                 21
#define PROPERTY_ID_UPDATERULE                      22
#define PROPERTY_ID_DELETERULE                      23
#define PROPERTY_ID_CATALOG                         24
#define PROPERTY_ID_ISUNIQUE                        25
#define PROPERTY_ID_ISPRIMARYKEYINDEX               26
#define PROPERTY_ID_ISCLUSTERED                     27
#define PROPERTY_ID_ISASCENDING                     28
#define PROPERTY_ID_SCHEMANAME                      29
#define PROPERTY_ID_CATALOGNAME                     30

#define PROPERTY_ID_COMMAND                         31
#define PROPERTY_ID_CHECKOPTION                     32
#define PROPERTY_ID_PASSWORD                        33
#define PROPERTY_ID_RELATEDCOLUMN                   34

#define PROPERTY_ID_FUNCTION                        35
#define PROPERTY_ID_TABLENAME                       36
#define PROPERTY_ID_REALNAME                        37
#define PROPERTY_ID_DBASEPRECISIONCHANGED           38
#define PROPERTY_ID_ISCURRENCY                      39
#define PROPERTY_ID_ISBOOKMARKABLE                  40

#define PROPERTY_ID_INVALID_INDEX                   41
#define PROPERTY_ID_ERRORMSG_SEQUENCE               42
#define PROPERTY_ID_HY010                           43
#define PROPERTY_ID_HY0000                          44
#define PROPERTY_ID_DELIMITER                       45
#define PROPERTY_ID_FORMATKEY                       46
#define PROPERTY_ID_LOCALE                          47
#define PROPERTY_ID_IM001                           48

#define PROPERTY_ID_AUTOINCREMENTCREATION           49

#define PROPERTY_ID_PRIVILEGES                      50

#endif // _CONNECTIVITY_PROPERTYIDS_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.5.90); FILE MERGED 2008/04/01 12:31:56 thb 1.5.90.1: #i85898# Stripping all external header guards<commit_after>/*************************************************************************
 *
 *  $RCSfile: propertyids.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2008-04-10 16:38:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

#ifndef _CONNECTIVITY_PROPERTYIDS_HXX_
#define _CONNECTIVITY_PROPERTYIDS_HXX_

// this define has to be set to split the names into different dll's or so's
// every dll has his own set of property names
#include <rtl/ustring.hxx>
#ifndef _MAP_
#include <map>
#endif

namespace connectivity
{
namespace skeleton
{
    class OPropertyMap
    {
        ::std::map<sal_Int32 , rtl_uString*> m_aPropertyMap;

        ::rtl::OUString fillValue(sal_Int32 _nIndex);
    public:
        OPropertyMap()
        {
        }
        ~OPropertyMap();
        ::rtl::OUString getNameByIndex(sal_Int32 _nIndex) const;

        static OPropertyMap& getPropMap()
        {
            static OPropertyMap s_aPropMap;
            return s_aPropMap;
        }
    };

        typedef const sal_Char* (*PVFN)();

        struct UStringDescription
        {
            const sal_Char* pZeroTerminatedName;
            sal_Int32 nLength;

            UStringDescription(PVFN _fCharFkt);
            operator ::rtl::OUString() const { return ::rtl::OUString(pZeroTerminatedName,nLength,RTL_TEXTENCODING_ASCII_US); }
            ~UStringDescription();
        private:
            UStringDescription();
        };
    }
}

//------------------------------------------------------------------------------
#define DECL_PROP1IMPL(varname, type) \
pProperties[nPos++] = ::com::sun::star::beans::Property(OPropertyMap::getPropMap().getNameByIndex(PROPERTY_ID_##varname), PROPERTY_ID_##varname, ::cppu::UnoType< type >::get(),
//------------------------------------------------------------------------------
#define DECL_PROP0(varname, type)   \
    DECL_PROP1IMPL(varname, type) 0)
//------------------------------------------------------------------------------
#define DECL_BOOL_PROP1IMPL(varname) \
        pProperties[nPos++] = ::com::sun::star::beans::Property(OPropertyMap::getPropMap().getNameByIndex(PROPERTY_ID_##varname), PROPERTY_ID_##varname, ::getBooleanCppuType(),
//------------------------------------------------------------------------------
#define DECL_BOOL_PROP0(varname)    \
    DECL_BOOL_PROP1IMPL(varname) 0)

#define PROPERTY_ID_QUERYTIMEOUT                    1
#define PROPERTY_ID_MAXFIELDSIZE                    2
#define PROPERTY_ID_MAXROWS                         3
#define PROPERTY_ID_CURSORNAME                      4
#define PROPERTY_ID_RESULTSETCONCURRENCY            5
#define PROPERTY_ID_RESULTSETTYPE                   6
#define PROPERTY_ID_FETCHDIRECTION                  7
#define PROPERTY_ID_FETCHSIZE                       8
#define PROPERTY_ID_ESCAPEPROCESSING                9
#define PROPERTY_ID_USEBOOKMARKS                    10
// Column
#define PROPERTY_ID_NAME                            11
#define PROPERTY_ID_TYPE                            12
#define PROPERTY_ID_TYPENAME                        13
#define PROPERTY_ID_PRECISION                       14
#define PROPERTY_ID_SCALE                           15
#define PROPERTY_ID_ISNULLABLE                      16
#define PROPERTY_ID_ISAUTOINCREMENT                 17
#define PROPERTY_ID_ISROWVERSION                    18
#define PROPERTY_ID_DESCRIPTION                     19
#define PROPERTY_ID_DEFAULTVALUE                    20

#define PROPERTY_ID_REFERENCEDTABLE                 21
#define PROPERTY_ID_UPDATERULE                      22
#define PROPERTY_ID_DELETERULE                      23
#define PROPERTY_ID_CATALOG                         24
#define PROPERTY_ID_ISUNIQUE                        25
#define PROPERTY_ID_ISPRIMARYKEYINDEX               26
#define PROPERTY_ID_ISCLUSTERED                     27
#define PROPERTY_ID_ISASCENDING                     28
#define PROPERTY_ID_SCHEMANAME                      29
#define PROPERTY_ID_CATALOGNAME                     30

#define PROPERTY_ID_COMMAND                         31
#define PROPERTY_ID_CHECKOPTION                     32
#define PROPERTY_ID_PASSWORD                        33
#define PROPERTY_ID_RELATEDCOLUMN                   34

#define PROPERTY_ID_FUNCTION                        35
#define PROPERTY_ID_TABLENAME                       36
#define PROPERTY_ID_REALNAME                        37
#define PROPERTY_ID_DBASEPRECISIONCHANGED           38
#define PROPERTY_ID_ISCURRENCY                      39
#define PROPERTY_ID_ISBOOKMARKABLE                  40

#define PROPERTY_ID_INVALID_INDEX                   41
#define PROPERTY_ID_ERRORMSG_SEQUENCE               42
#define PROPERTY_ID_HY010                           43
#define PROPERTY_ID_HY0000                          44
#define PROPERTY_ID_DELIMITER                       45
#define PROPERTY_ID_FORMATKEY                       46
#define PROPERTY_ID_LOCALE                          47
#define PROPERTY_ID_IM001                           48

#define PROPERTY_ID_AUTOINCREMENTCREATION           49

#define PROPERTY_ID_PRIVILEGES                      50

#endif // _CONNECTIVITY_PROPERTYIDS_HXX_

<|endoftext|>


<commit_before>
/************************/
/* Contour finder class */
/************************/
#include "nebulaContourFinder.h"

void nebulaContourFinder::setup(){
  // setup contour finder parameter GUI
  guiGrp.setName("Blob tracker");
  guiGrp.add(enabled.set("enable",true));
  guiGrp.add(minAreaRad.set("minimum area radius",1,0,240));
  guiGrp.add(maxAreaRad.set("maximum area radius",100,0,240));
  guiGrp.add(threshold.set("threshold",15,0,255));
  guiGrp.add(erodeAmount.set("erode",1,0,10));
  guiGrp.add(blurAmount.set("blur",10,0,100));
  guiGrp.add(persistence.set("persistence", 15,0,200));
  guiGrp.add(maxDistance.set("max distance",32,0,200));
  guiGrp.add(showLabels.set("show label",true));

  minAreaRad.addListener(this, &nebulaContourFinder::minAreaCb);
  maxAreaRad.addListener(this, &nebulaContourFinder::maxAreaCb);
  threshold.addListener(this, &nebulaContourFinder::thresholdCb);
  persistence.addListener(this, &nebulaContourFinder::persistenceCb);
  maxDistance.addListener(this, &nebulaContourFinder::maxDistanceCb);
  showLabels.addListener(this, &nebulaContourFinder::showLabelsCb);

  finder.setMinAreaRadius(minAreaRad);
  finder.setMaxAreaRadius(maxAreaRad);
  finder.setThreshold(threshold);
  // wait for half a frame before forgetting something
  finder.getTracker().setPersistence(persistence);
  // an object can move up to 32 pixels per frame
  finder.getTracker().setMaximumDistance(maxDistance);
}

void nebulaContourFinder::draw(int x, int y, int w, int h){
    if(!enabled || blurred.size() == cv::Size(0,0)) return;
  ofxCv::RectTracker& tracker = finder.getTracker();

  ofPushMatrix();
  ofScale(w/blurred.cols, h/blurred.rows);
  ofTranslate(x,y);

  if(showLabels) {
    finder.draw();
    for(int i = 0; i < finder.size(); i++) {
      ofPoint center = ofxCv::toOf(finder.getCenter(i));
      ofPushMatrix();
      ofTranslate(center.x, center.y);
      int label = finder.getLabel(i);
      string msg = ofToString(label) + ":" + ofToString(tracker.getAge(label));
      ofDrawBitmapString(msg, 0, 0);
      ofDrawCircle(0,0,2);
      msg = ofToString(finder.getCentroid(i));
      ofDrawBitmapString(msg, 0, 12);
      ofVec2f velocity = ofxCv::toOf(finder.getVelocity(i));
      ofScale(5, 5);
      ofDrawLine(0, 0, velocity.x, velocity.y);
      ofPopMatrix();
    }
  } else {
    for(int i = 0; i < finder.size(); i++) {
      unsigned int label = finder.getLabel(i);
      // only draw a line if this is not a new label
      if(tracker.existsPrevious(label)) {
        // use the label to pick a random color
        ofSeedRandom(label << 24);
        ofSetColor(ofColor::fromHsb(ofRandom(255), 255, 255));
        // get the tracked object (cv::Rect) at current and previous position
        const cv::Rect& previous = tracker.getPrevious(label);
        const cv::Rect& current = tracker.getCurrent(label);
        // get the centers of the rectangles
        ofVec2f previousPosition(previous.x + previous.width / 2, previous.y + previous.height / 2);
        ofVec2f currentPosition(current.x + current.width / 2, current.y + current.height / 2);
        ofDrawLine(previousPosition, currentPosition);
      }
    }
  }

  ofTranslate(x,y);
  // this chunk of code visualizes the creation and destruction of labels
  const vector<unsigned int>& currentLabels = tracker.getCurrentLabels();
  const vector<unsigned int>& previousLabels = tracker.getPreviousLabels();
  const vector<unsigned int>& newLabels = tracker.getNewLabels();
  const vector<unsigned int>& deadLabels = tracker.getDeadLabels();
  ofSetColor(ofxCv::cyanPrint);
  for(int i = 0; i < currentLabels.size(); i++) {
    int j = currentLabels[i];
    ofDrawLine(j, 0, j, 4);
  }
  ofSetColor(ofxCv::magentaPrint);
  for(int i = 0; i < previousLabels.size(); i++) {
    int j = previousLabels[i];
    ofDrawLine(j, 4, j, 8);
  }
  ofSetColor(ofxCv::yellowPrint);
  for(int i = 0; i < newLabels.size(); i++) {
    int j = newLabels[i];
    ofDrawLine(j, 8, j, 12);
  }
  ofSetColor(ofColor::white);
  for(int i = 0; i < deadLabels.size(); i++) {
    int j = deadLabels[i];
    ofDrawLine(j, 12, j, 16);
  }
  ofPopMatrix();
  ofPopStyle();
}

void nebulaContourFinder::showLabelsCb(bool& flag){
  if (!flag){
    fbo.begin();
    ofClear(0,0,0,0); // clear sceen before drawing
    fbo.end();
  }
}

void nebulaContourFinder::minAreaCb(int& val){
  finder.setMinAreaRadius(val);
}

void nebulaContourFinder::maxAreaCb(int& val){
  finder.setMaxAreaRadius(val);
}

void nebulaContourFinder::thresholdCb(int& val){
  finder.setThreshold(val);
}

void nebulaContourFinder::persistenceCb(int& val){
  finder.getTracker().setPersistence(val);
}

void nebulaContourFinder::maxDistanceCb(int& val){
  finder.getTracker().setMaximumDistance(val);
}

vector<ofPoint> nebulaContourFinder::getCentroids(){
  vector<ofPoint> centroids;
  for (int i = 0; i < finder.size(); i++){
       centroids.push_back(ofxCv::toOf(finder.getCentroid(i)));
    }
  return centroids;
}
<commit_msg>move comment<commit_after>
/************************/
/* Contour finder class */
/************************/
#include "nebulaContourFinder.h"

void nebulaContourFinder::setup(){
  // setup contour finder parameter GUI
  guiGrp.setName("Blob tracker");
  guiGrp.add(enabled.set("enable",true));
  guiGrp.add(minAreaRad.set("minimum area radius",1,0,240));
  guiGrp.add(maxAreaRad.set("maximum area radius",100,0,240));
  guiGrp.add(threshold.set("threshold",15,0,255));
  guiGrp.add(erodeAmount.set("erode",1,0,10));
  guiGrp.add(blurAmount.set("blur",10,0,100));
  // time to wait before forgetting something
  guiGrp.add(persistence.set("persistence", 15,0,200));
  // this is the maximum distance a pixel can move between 2 frames
  guiGrp.add(maxDistance.set("max distance",32,0,200));
  guiGrp.add(showLabels.set("show label",true));

  minAreaRad.addListener(this, &nebulaContourFinder::minAreaCb);
  maxAreaRad.addListener(this, &nebulaContourFinder::maxAreaCb);
  threshold.addListener(this, &nebulaContourFinder::thresholdCb);
  persistence.addListener(this, &nebulaContourFinder::persistenceCb);
  maxDistance.addListener(this, &nebulaContourFinder::maxDistanceCb);
  showLabels.addListener(this, &nebulaContourFinder::showLabelsCb);

  finder.setMinAreaRadius(minAreaRad);
  finder.setMaxAreaRadius(maxAreaRad);
  finder.setThreshold(threshold);
  finder.getTracker().setPersistence(persistence);
  finder.getTracker().setMaximumDistance(maxDistance);
}

void nebulaContourFinder::draw(int x, int y, int w, int h){
    if(!enabled || blurred.size() == cv::Size(0,0)) return;
  ofxCv::RectTracker& tracker = finder.getTracker();

  ofPushMatrix();
  ofScale(w/blurred.cols, h/blurred.rows);
  ofTranslate(x,y);

  if(showLabels) {
    finder.draw();
    for(int i = 0; i < finder.size(); i++) {
      ofPoint center = ofxCv::toOf(finder.getCenter(i));
      ofPushMatrix();
      ofTranslate(center.x, center.y);
      int label = finder.getLabel(i);
      string msg = ofToString(label) + ":" + ofToString(tracker.getAge(label));
      ofDrawBitmapString(msg, 0, 0);
      ofDrawCircle(0,0,2);
      msg = ofToString(finder.getCentroid(i));
      ofDrawBitmapString(msg, 0, 12);
      ofVec2f velocity = ofxCv::toOf(finder.getVelocity(i));
      ofScale(5, 5);
      ofDrawLine(0, 0, velocity.x, velocity.y);
      ofPopMatrix();
    }
  } else {
    for(int i = 0; i < finder.size(); i++) {
      unsigned int label = finder.getLabel(i);
      // only draw a line if this is not a new label
      if(tracker.existsPrevious(label)) {
        // use the label to pick a random color
        ofSeedRandom(label << 24);
        ofSetColor(ofColor::fromHsb(ofRandom(255), 255, 255));
        // get the tracked object (cv::Rect) at current and previous position
        const cv::Rect& previous = tracker.getPrevious(label);
        const cv::Rect& current = tracker.getCurrent(label);
        // get the centers of the rectangles
        ofVec2f previousPosition(previous.x + previous.width / 2, previous.y + previous.height / 2);
        ofVec2f currentPosition(current.x + current.width / 2, current.y + current.height / 2);
        ofDrawLine(previousPosition, currentPosition);
      }
    }
  }

  ofTranslate(x,y);
  // this chunk of code visualizes the creation and destruction of labels
  const vector<unsigned int>& currentLabels = tracker.getCurrentLabels();
  const vector<unsigned int>& previousLabels = tracker.getPreviousLabels();
  const vector<unsigned int>& newLabels = tracker.getNewLabels();
  const vector<unsigned int>& deadLabels = tracker.getDeadLabels();
  ofSetColor(ofxCv::cyanPrint);
  for(int i = 0; i < currentLabels.size(); i++) {
    int j = currentLabels[i];
    ofDrawLine(j, 0, j, 4);
  }
  ofSetColor(ofxCv::magentaPrint);
  for(int i = 0; i < previousLabels.size(); i++) {
    int j = previousLabels[i];
    ofDrawLine(j, 4, j, 8);
  }
  ofSetColor(ofxCv::yellowPrint);
  for(int i = 0; i < newLabels.size(); i++) {
    int j = newLabels[i];
    ofDrawLine(j, 8, j, 12);
  }
  ofSetColor(ofColor::white);
  for(int i = 0; i < deadLabels.size(); i++) {
    int j = deadLabels[i];
    ofDrawLine(j, 12, j, 16);
  }
  ofPopMatrix();
  ofPopStyle();
}

void nebulaContourFinder::showLabelsCb(bool& flag){
  if (!flag){
    fbo.begin();
    ofClear(0,0,0,0); // clear sceen before drawing
    fbo.end();
  }
}

void nebulaContourFinder::minAreaCb(int& val){
  finder.setMinAreaRadius(val);
}

void nebulaContourFinder::maxAreaCb(int& val){
  finder.setMaxAreaRadius(val);
}

void nebulaContourFinder::thresholdCb(int& val){
  finder.setThreshold(val);
}

void nebulaContourFinder::persistenceCb(int& val){
  finder.getTracker().setPersistence(val);
}

void nebulaContourFinder::maxDistanceCb(int& val){
  finder.getTracker().setMaximumDistance(val);
}

vector<ofPoint> nebulaContourFinder::getCentroids(){
  vector<ofPoint> centroids;
  for (int i = 0; i < finder.size(); i++){
       centroids.push_back(ofxCv::toOf(finder.getCentroid(i)));
    }
  return centroids;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <arrow-glib/array.hpp>
#include <arrow-glib/uint32-array.h>

G_BEGIN_DECLS

/**
 * SECTION: uint32-array
 * @short_description: 32-bit unsigned integer array class
 *
 * #GArrowUInt32Array is a class for 32-bit unsigned integer array. It
 * can store zero or more 32-bit unsigned integer data.
 *
 * #GArrowUInt32Array is immutable. You need to use
 * #GArrowUInt32ArrayBuilder to create a new array.
 */

G_DEFINE_TYPE(GArrowUInt32Array,               \
              garrow_uint32_array,             \
              GARROW_TYPE_ARRAY)

static void
garrow_uint32_array_init(GArrowUInt32Array *object)
{
}

static void
garrow_uint32_array_class_init(GArrowUInt32ArrayClass *klass)
{
}

/**
 * garrow_uint32_array_get_value:
 * @array: A #GArrowUInt32Array.
 * @i: The index of the target value.
 *
 * Returns: The i-th value.
 */
guint32
garrow_uint32_array_get_value(GArrowUInt32Array *array,
                             gint64 i)
{
  auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array));
  return static_cast<arrow::UInt32Array *>(arrow_array.get())->Value(i);
}

G_END_DECLS
<commit_msg>ARROW-793: [GLib] Fix indent<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <arrow-glib/array.hpp>
#include <arrow-glib/uint32-array.h>

G_BEGIN_DECLS

/**
 * SECTION: uint32-array
 * @short_description: 32-bit unsigned integer array class
 *
 * #GArrowUInt32Array is a class for 32-bit unsigned integer array. It
 * can store zero or more 32-bit unsigned integer data.
 *
 * #GArrowUInt32Array is immutable. You need to use
 * #GArrowUInt32ArrayBuilder to create a new array.
 */

G_DEFINE_TYPE(GArrowUInt32Array,               \
              garrow_uint32_array,             \
              GARROW_TYPE_ARRAY)

static void
garrow_uint32_array_init(GArrowUInt32Array *object)
{
}

static void
garrow_uint32_array_class_init(GArrowUInt32ArrayClass *klass)
{
}

/**
 * garrow_uint32_array_get_value:
 * @array: A #GArrowUInt32Array.
 * @i: The index of the target value.
 *
 * Returns: The i-th value.
 */
guint32
garrow_uint32_array_get_value(GArrowUInt32Array *array,
                              gint64 i)
{
  auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array));
  return static_cast<arrow::UInt32Array *>(arrow_array.get())->Value(i);
}

G_END_DECLS
<|endoftext|>


<commit_before>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitCore
 *    File: $Id: RooBMixDecay.cc,v 1.8 2001/11/05 18:53:48 verkerke Exp $
 * Authors:
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   05-Jun-2001 WV Created initial version
 *
 * Copyright (C) 2001 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [PDF] --
//

#include <iostream.h>
#include "RooFitCore/RooRealVar.hh"
#include "RooFitModels/RooBMixDecay.hh"
#include "RooFitCore/RooRandom.hh"

ClassImp(RooBMixDecay)
;

RooBMixDecay::RooBMixDecay(const char *name, const char *title,
			   RooRealVar& t, RooAbsCategory& mixState,
			   RooAbsCategory& tagFlav,
			   RooAbsReal& tau, RooAbsReal& dm,
			   RooAbsReal& mistag, RooAbsReal& delMistag,
			   const RooResolutionModel& model,
			   DecayType type) :
  RooConvolutedPdf(name,title,model,t),
  _mistag("mistag","Mistag rate",this,mistag),
  _mixState("mixState","Mixing state",this,mixState),
  _tagFlav("tagFlav","Flavour of tagged B0",this,tagFlav),
  _delMistag("delMistag","Delta mistag rate",this,delMistag),
  _type(type),
  _tau("tau","Mixing life time",this,tau),
  _dm("dm","Mixing frequency",this,dm),
  _t("_t","time",this,t), _genMixFrac(0)
{
  // Constructor
  switch(type) {
  case SingleSided:
    _basisExp = declareBasis("exp(-@0/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case Flipped:
    _basisExp = declareBasis("exp(@0)/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case DoubleSided:
    _basisExp = declareBasis("exp(-abs(@0)/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-abs(@0)/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  }
}

RooBMixDecay::RooBMixDecay(const RooBMixDecay& other, const char* name) :
  RooConvolutedPdf(other,name),
  _mistag("mistag",this,other._mistag),
  _mixState("mixState",this,other._mixState),
  _tagFlav("tagFlav",this,other._tagFlav),
  _delMistag("delMistag",this,other._delMistag),
  _tau("tau",this,other._tau),
  _dm("dm",this,other._dm),
  _t("t",this,other._t),
  _basisExp(other._basisExp),
  _basisCos(other._basisCos),
  _type(other._type),
  _genMixFrac(other._genMixFrac),
  _genFlavFrac(other._genFlavFrac),
  _genFlavFracMix(other._genFlavFracMix),
  _genFlavFracUnmix(other._genFlavFracUnmix)
{
  // Copy constructor
}

RooBMixDecay::~RooBMixDecay()
{
  // Destructor
}

Double_t RooBMixDecay::coefficient(Int_t basisIndex) const
{
  // Comp with tFit MC: must be (1 - tagFlav*...)
  if (basisIndex==_basisExp) {
    return (1 - _tagFlav*_delMistag) ;
  }

  if (basisIndex==_basisCos) {
    return _mixState*(1-2*_mistag) ;
  }

  return 0 ;
}

Int_t RooBMixDecay::getCoefAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars) const
{
  if (matchArgs(allVars,analVars,_mixState,_tagFlav)) return 3 ;
  if (matchArgs(allVars,analVars,_mixState)) return 2 ;
  if (matchArgs(allVars,analVars,_tagFlav)) return 1 ;
  return 0 ;
}

Double_t RooBMixDecay::coefAnalyticalIntegral(Int_t basisIndex, Int_t code) const
{
  switch(code) {
    // No integration
  case 0: return coefficient(basisIndex) ;

    // Integration over 'mixState' and 'tagFlav'
  case 3:
    if (basisIndex==_basisExp) {
      return 4.0 ;
    }
    if (basisIndex==_basisCos) {
      return 0.0 ;
    }

    // Integration over 'mixState'
  case 2:
    if (basisIndex==_basisExp) {
      return 2.0*coefficient(basisIndex) ;
    }
    if (basisIndex==_basisCos) {
      return 0.0 ;
    }

    // Integration over 'tagFlav'
  case 1:
    if (basisIndex==_basisExp) {
      return 2.0 ;
    }
    if (basisIndex==_basisCos) {
      return 2.0*coefficient(basisIndex) ;
    }
  default:
    assert(0) ;
  }

  return 0 ;
}

Int_t RooBMixDecay::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars) const
{
  if (matchArgs(directVars,generateVars,_t,_mixState,_tagFlav)) return 4 ;
  if (matchArgs(directVars,generateVars,_t,_mixState)) return 3 ;
  if (matchArgs(directVars,generateVars,_t,_tagFlav)) return 2 ;
  if (matchArgs(directVars,generateVars,_t)) return 1 ;
  return 0 ;
}

void RooBMixDecay::initGenerator(Int_t code)
{
  switch (code) {
  case 2:
    {
      // Calculate the fraction of mixed events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_mixState.arg())).getVal() ;
      _mixState = -1 ; // mixed
      Double_t mixInt = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg())).getVal() ;
      _genMixFrac = mixInt/sumInt ;
      break ;
    }
  case 3:
    {
      // Calculate the fraction of B0bar events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_tagFlav.arg())).getVal() ;
      _tagFlav = 1 ; // B0
      Double_t flavInt = RooRealIntegral("flavInt","flav integral",*this,RooArgSet(_t.arg())).getVal() ;
      _genFlavFrac = flavInt/sumInt ;
      break ;
    }
  case 4:
    {
      // Calculate the fraction of mixed events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_mixState.arg(),_tagFlav.arg())).getVal() ;
      _mixState = -1 ; // mixed
      Double_t mixInt = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg(),_tagFlav.arg())).getVal() ;
      _genMixFrac = mixInt/sumInt ;

      // Calculate the fractio of B0bar tags for mixed and unmixed
      RooRealIntegral dtInt("mixInt","mix integral",*this,RooArgSet(_t.arg())) ;
      _mixState = -1 ; // Mixed
      _tagFlav  =  1 ; // B0
      _genFlavFracMix   = dtInt.getVal() / mixInt ;
      _mixState =  1 ; // Unmixed
      _tagFlav  =  1 ; // B0
      _genFlavFracUnmix = dtInt.getVal() / (sumInt - mixInt) ;
      break ;
    }
  }
}

void RooBMixDecay::generateEvent(Int_t code)
{
  // Generate mix-state dependent
  switch(code) {
  case 2:
    {
      Double_t rand = RooRandom::uniform() ;
      _mixState = (Int_t) ((rand<=_genMixFrac) ? -1 : 1) ;
      break ;
    }
  case 3:
    {
      Double_t rand = RooRandom::uniform() ;
      _tagFlav = (Int_t) ((rand<=_genFlavFrac) ?  1 : -1) ;
      break ;
    }
  case 4:
    {
      Double_t rand = RooRandom::uniform() ;
      _mixState = (Int_t) ((rand<=_genMixFrac) ? -1 : 1) ;

      rand = RooRandom::uniform() ;
      Double_t genFlavFrac = (_mixState==-1) ? _genFlavFracMix : _genFlavFracUnmix ;
      _tagFlav = (Int_t) ((rand<=genFlavFrac) ?  1 : -1) ;
      break ;
    }
  }

  // Generate delta-t dependent
  while(1) {
    Double_t rand = RooRandom::uniform() ;
    Double_t tval(0) ;

    switch(_type) {
    case SingleSided:
      tval = -_tau*log(rand);
      break ;
    case Flipped:
      tval= +_tau*log(rand);
      break ;
    case DoubleSided:
      tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5)) ;
      break ;
    }

    // Accept event if T is in generated range
    Double_t dil = fabs(1-2*_mistag) ;
    Double_t maxAcceptProb = 1 + fabs(_delMistag) + dil ;
    Double_t acceptProb = (1-_tagFlav*_delMistag) + _mixState*dil*cos(_dm*tval);
    Bool_t mixAccept = maxAcceptProb*RooRandom::uniform() < acceptProb ? kTRUE : kFALSE ;

    if (tval<_t.max() && tval>_t.min() && mixAccept) {
      _t = tval ;
      break ;
    }
  }
}
<commit_msg><commit_after>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitCore
 *    File: $Id: RooBMixDecay.cc,v 1.9 2001/11/14 19:15:30 verkerke Exp $
 * Authors:
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   05-Jun-2001 WV Created initial version
 *
 * Copyright (C) 2001 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [PDF] --
//

#include <iostream.h>
#include "RooFitCore/RooRealVar.hh"
#include "RooFitModels/RooBMixDecay.hh"
#include "RooFitCore/RooRandom.hh"

ClassImp(RooBMixDecay)
;

RooBMixDecay::RooBMixDecay(const char *name, const char *title,
			   RooRealVar& t, RooAbsCategory& mixState,
			   RooAbsCategory& tagFlav,
			   RooAbsReal& tau, RooAbsReal& dm,
			   RooAbsReal& mistag, RooAbsReal& delMistag,
			   const RooResolutionModel& model,
			   DecayType type) :
  RooConvolutedPdf(name,title,model,t),
  _mistag("mistag","Mistag rate",this,mistag),
  _mixState("mixState","Mixing state",this,mixState),
  _tagFlav("tagFlav","Flavour of tagged B0",this,tagFlav),
  _delMistag("delMistag","Delta mistag rate",this,delMistag),
  _type(type),
  _tau("tau","Mixing life time",this,tau),
  _dm("dm","Mixing frequency",this,dm),
  _t("_t","time",this,t), _genMixFrac(0)
{
  // Constructor
  switch(type) {
  case SingleSided:
    _basisExp = declareBasis("exp(-@0/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case Flipped:
    _basisExp = declareBasis("exp(@0)/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case DoubleSided:
    _basisExp = declareBasis("exp(-abs(@0)/@1)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-abs(@0)/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  }
}

RooBMixDecay::RooBMixDecay(const RooBMixDecay& other, const char* name) :
  RooConvolutedPdf(other,name),
  _mistag("mistag",this,other._mistag),
  _mixState("mixState",this,other._mixState),
  _tagFlav("tagFlav",this,other._tagFlav),
  _delMistag("delMistag",this,other._delMistag),
  _tau("tau",this,other._tau),
  _dm("dm",this,other._dm),
  _t("t",this,other._t),
  _basisExp(other._basisExp),
  _basisCos(other._basisCos),
  _type(other._type),
  _genMixFrac(other._genMixFrac),
  _genFlavFrac(other._genFlavFrac),
  _genFlavFracMix(other._genFlavFracMix),
  _genFlavFracUnmix(other._genFlavFracUnmix)
{
  // Copy constructor
}

RooBMixDecay::~RooBMixDecay()
{
  // Destructor
}

Double_t RooBMixDecay::coefficient(Int_t basisIndex) const
{
  // Comp with tFit MC: must be (1 - tagFlav*...)
  if (basisIndex==_basisExp) {
    return (1 - _tagFlav*_delMistag) ;
  }

  if (basisIndex==_basisCos) {
    return _mixState*(1-2*_mistag) ;
  }

  return 0 ;
}

Int_t RooBMixDecay::getCoefAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars) const
{
//   cout << "RooBMixDecay::getCoefAI " ; allVars.Print("1") ;

  if (matchArgs(allVars,analVars,_mixState,_tagFlav)) return 3 ;
  if (matchArgs(allVars,analVars,_mixState)) return 2 ;
  if (matchArgs(allVars,analVars,_tagFlav)) return 1 ;
  return 0 ;
}

Double_t RooBMixDecay::coefAnalyticalIntegral(Int_t basisIndex, Int_t code) const
{
  switch(code) {
    // No integration
  case 0: return coefficient(basisIndex) ;

    // Integration over 'mixState' and 'tagFlav'
  case 3:
    if (basisIndex==_basisExp) {
      return 4.0 ;
    }
    if (basisIndex==_basisCos) {
      return 0.0 ;
    }

    // Integration over 'mixState'
  case 2:
    if (basisIndex==_basisExp) {
      return 2.0*coefficient(basisIndex) ;
    }
    if (basisIndex==_basisCos) {
      return 0.0 ;
    }

    // Integration over 'tagFlav'
  case 1:
    if (basisIndex==_basisExp) {
      return 2.0 ;
    }
    if (basisIndex==_basisCos) {
      return 2.0*coefficient(basisIndex) ;
    }
  default:
    assert(0) ;
  }

  return 0 ;
}

Int_t RooBMixDecay::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars) const
{
  if (matchArgs(directVars,generateVars,_t,_mixState,_tagFlav)) return 4 ;
  if (matchArgs(directVars,generateVars,_t,_mixState)) return 3 ;
  if (matchArgs(directVars,generateVars,_t,_tagFlav)) return 2 ;
  if (matchArgs(directVars,generateVars,_t)) return 1 ;
  return 0 ;
}

void RooBMixDecay::initGenerator(Int_t code)
{
  switch (code) {
  case 2:
    {
      // Calculate the fraction of B0bar events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_tagFlav.arg())).getVal() ;
      _tagFlav = 1 ; // B0
      Double_t flavInt = RooRealIntegral("flavInt","flav integral",*this,RooArgSet(_t.arg())).getVal() ;
      _genFlavFrac = flavInt/sumInt ;
      break ;
    }
  case 3:
    {
      // Calculate the fraction of mixed events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_mixState.arg())).getVal() ;
      _mixState = -1 ; // mixed
      Double_t mixInt = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg())).getVal() ;
      _genMixFrac = mixInt/sumInt ;
      break ;
    }
  case 4:
    {
      // Calculate the fraction of mixed events to generate
      Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_mixState.arg(),_tagFlav.arg())).getVal() ;
      _mixState = -1 ; // mixed
      Double_t mixInt = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg(),_tagFlav.arg())).getVal() ;
      _genMixFrac = mixInt/sumInt ;

      // Calculate the fractio of B0bar tags for mixed and unmixed
      RooRealIntegral dtInt("mixInt","mix integral",*this,RooArgSet(_t.arg())) ;
      _mixState = -1 ; // Mixed
      _tagFlav  =  1 ; // B0
      _genFlavFracMix   = dtInt.getVal() / mixInt ;
      _mixState =  1 ; // Unmixed
      _tagFlav  =  1 ; // B0
      _genFlavFracUnmix = dtInt.getVal() / (sumInt - mixInt) ;
      break ;
    }
  }
}

void RooBMixDecay::generateEvent(Int_t code)
{
  // Generate mix-state dependent
  switch(code) {
  case 2:
    {
      Double_t rand = RooRandom::uniform() ;
      _tagFlav = (Int_t) ((rand<=_genFlavFrac) ?  1 : -1) ;
      break ;
    }
  case 3:
    {
      Double_t rand = RooRandom::uniform() ;
      _mixState = (Int_t) ((rand<=_genMixFrac) ? -1 : 1) ;
      break ;
    }
  case 4:
    {
      Double_t rand = RooRandom::uniform() ;
      _mixState = (Int_t) ((rand<=_genMixFrac) ? -1 : 1) ;

      rand = RooRandom::uniform() ;
      Double_t genFlavFrac = (_mixState==-1) ? _genFlavFracMix : _genFlavFracUnmix ;
      _tagFlav = (Int_t) ((rand<=genFlavFrac) ?  1 : -1) ;
      break ;
    }
  }

  // Generate delta-t dependent
  while(1) {
    Double_t rand = RooRandom::uniform() ;
    Double_t tval(0) ;

    switch(_type) {
    case SingleSided:
      tval = -_tau*log(rand);
      break ;
    case Flipped:
      tval= +_tau*log(rand);
      break ;
    case DoubleSided:
      tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5)) ;
      break ;
    }

    // Accept event if T is in generated range
    Double_t dil = fabs(1-2*_mistag) ;
    Double_t maxAcceptProb = 1 + fabs(_delMistag) + dil ;
    Double_t acceptProb = (1-_tagFlav*_delMistag) + _mixState*dil*cos(_dm*tval);
    Bool_t mixAccept = maxAcceptProb*RooRandom::uniform() < acceptProb ? kTRUE : kFALSE ;

    if (tval<_t.max() && tval>_t.min() && mixAccept) {
      _t = tval ;
      break ;
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Changes tab dragging code to continue iterating through windows if window's rect contains the point but the window region doesn't. This is necessary as some apps create a window the size of the desktop and set a window region on it. Without this check we don't allow docking when these apps are running.<commit_after><|endoftext|>


<commit_before>#ifndef K3_RUNTIME_QUEUE_H
#define K3_RUNTIME_QUEUE_H

#include <list>
#include <map>
#include <memory>
#include <queue>
#include <tuple>
#include <boost/lockfree/queue.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/externally_locked.hpp>

#include <Common.hpp>

namespace K3 {

  // using namespace std;
  using namespace boost;
  using std::shared_ptr;

  using mutex = boost::mutex;

  //-------------
  // Queue types.

  template<typename Value>
  class MsgQueue {
  public:
    virtual bool push(Value& v) = 0;
    virtual bool pop(Value& v) = 0;
    virtual bool empty() = 0;
    virtual size_t size() = 0;
  };

  template<typename Value>
  class LockfreeMsgQueue : public MsgQueue<Value> {
  public:
    LockfreeMsgQueue() {}
    bool empty()        { return queue.empty(); }
    bool push(Value& v) { ++qSize; return queue.push(v); }
    bool pop(Value& v)  { --qSize; return queue.pop(v); }
    size_t size()       { return qSize; }
  protected:
    boost::lockfree::queue<Value> queue;
    size_t qSize; // TODO: synchronize.
  };

  template<typename Value>
  class LockingMsgQueue
    : public MsgQueue<Value>, public basic_lockable_adapter<mutex>
  {
  public:
    typedef basic_lockable_adapter<mutex> qlockable;
    LockingMsgQueue () : qlockable(), queue(*this) {}

    bool empty() {
      strict_lock<LockingMsgQueue> guard(*this);
      return queue.get(guard).empty();
    }

    bool push(Value& v) {
      strict_lock<LockingMsgQueue> guard(*this);
      ++qSize;
      queue.get(guard).push(v);
      return true;
    }

    bool pop(Value& v) {
      strict_lock<LockingMsgQueue> guard(*this);
      bool r = false;
      if ( !queue.get(guard).empty() ) {
        --qSize;
        v = queue.get(guard).front();
        queue.get(guard).pop();
        r = true;
      }
      return r;
    }

    size_t size() { return qSize; }

  protected:
    externally_locked<std::queue<Value>, LockingMsgQueue> queue;
    size_t qSize; // TODO: synchronize
  };

  //------------------
  // Queue containers.

  class MessageQueues : public virtual LogMT {
  public:
    MessageQueues() : LogMT("queue") {}
    virtual void enqueue(Message m) = 0; // TODO: use a ref / rvalue ref to avoid copying
    virtual shared_ptr<Message> dequeue() = 0;
    virtual size_t size() = 0;
  };

  template<typename QueueIndex, typename Queue>
  class IndexedMessageQueues : public MessageQueues
  {
  public:
    IndexedMessageQueues() : LogMT("IndexedMessageQueues") {}

    // TODO: use a ref / rvalue ref to avoid copying
    void enqueue(Message m)
    {
      if ( validTarget(m) ) { enqueue(m, queue(m)); }
      else {
        BOOST_LOG(*this) << "Invalid message target: "
                         << addressAsString(m.address()) << ":" << m.id();
      }
    }

    // TODO: fair queueing policy.
    shared_ptr<Message> dequeue()
    {
      shared_ptr<Message> r;
      tuple<QueueIndex, shared_ptr<Queue> > idxQ = nonEmptyQueue();
      if ( get<1>(idxQ) ) { r = dequeue(idxQ); }
      else {
        BOOST_LOG(*this) << "Invalid non-empty queue on dequeue";
      }
      return r;
    }

  protected:
    virtual bool validTarget(Message& m) = 0;

    virtual shared_ptr<Queue> queue(Message& m) = 0;
    virtual tuple<QueueIndex, shared_ptr<Queue> > nonEmptyQueue() = 0;

    virtual void enqueue(Message& m, shared_ptr<Queue> q) = 0;
    virtual shared_ptr<Message> dequeue(const tuple<QueueIndex, shared_ptr<Queue> >& q) = 0;
  };

  class SinglePeerQueue
    : public IndexedMessageQueues<Address, MsgQueue<tuple<Identifier, Value> > >
  {
  public:
    typedef Address QueueKey;
    //typedef LockfreeMsgQueue<tuple<Identifier, Value> > Queue;
    typedef LockingMsgQueue<tuple<Identifier, Value> > Queue;
    typedef tuple<QueueKey, shared_ptr<Queue> > PeerMessages;

    SinglePeerQueue() : LogMT("SinglePeerQueue") {}

    SinglePeerQueue(Address addr)
      : LogMT("SinglePeerQueue"), peerMsgs(addr, shared_ptr<Queue>(new Queue()))
    {}

    size_t size() { return get<1>(peerMsgs)->size(); }

  protected:
    typedef MsgQueue<tuple<Identifier, Value> > BaseQueue;
    PeerMessages peerMsgs;

    bool validTarget(Message& m) { return m.address() == get<0>(peerMsgs); }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(get<1>(peerMsgs));
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      shared_ptr<Queue> r = get<1>(peerMsgs);
      shared_ptr<BaseQueue> br =
        r->empty()? shared_ptr<BaseQueue>() : dynamic_pointer_cast<BaseQueue, Queue>(r);
      return make_tuple(get<0>(peerMsgs), br);
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q)
    {
      tuple<Identifier, Value> entry = make_tuple(m.id(), m.contents());
      if ( !(q && q->push(entry)) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message> dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message>  r;
      tuple<Identifier, Value> entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(idxQ);
        const Identifier& id = get<0>(entry);
        const Value& v       = get<1>(entry);
        r = shared_ptr<Message>(new Message(addr, id, v));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  // TODO: for dynamic changes to the queues container, use a shared lock
  class MultiPeerQueue
    : public IndexedMessageQueues<Address, MsgQueue<tuple<Identifier, Value> > >
  {
  public:
    typedef Address QueueKey;
    //typedef LockfreeMsgQueue<tuple<Identifier, Value> > Queue;
    typedef LockingMsgQueue<tuple<Identifier, Value> > Queue;
    typedef map<QueueKey, shared_ptr<Queue> > MultiPeerMessages;

    MultiPeerQueue() : LogMT("MultiPeerQueue") {}
    MultiPeerQueue(const list<Address>& addresses) : LogMT("MultiPeerQueue") {
      for ( auto x : addresses ) {
        multiPeerMsgs.insert(make_pair(x, shared_ptr<Queue>(new Queue())));
      }
    }

    size_t size() {
      size_t r = 0;
      for ( auto x : multiPeerMsgs ) { r += x.second? x.second->size() : 0; }
      return r;
    }

  protected:
    typedef MsgQueue<tuple<Identifier, Value> > BaseQueue;
    MultiPeerMessages multiPeerMsgs;

    bool validTarget(Message& m) {
      return multiPeerMsgs.find(m.address()) != multiPeerMsgs.end();
    }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(multiPeerMsgs[m.address()]);
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      tuple<QueueKey, shared_ptr<BaseQueue> > r;

      MultiPeerMessages::iterator it =
        find_if(multiPeerMsgs.begin(), multiPeerMsgs.end(),
          [](MultiPeerMessages::value_type& x){ return x.second->empty(); });

      if ( it != multiPeerMsgs.end() ) {
        r = make_tuple(it->first, dynamic_pointer_cast<BaseQueue, Queue>(it->second));
      }
      return r;
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q)
    {
      tuple<Identifier, Value> entry = make_tuple(m.id(), m.contents());
      if ( !(q && q->push(entry)) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message> dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message> r;
      tuple<Identifier, Value> entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(idxQ);
        const Identifier& id = get<0>(entry);
        const Value& v       = get<1>(entry);
        r = shared_ptr<Message >(new Message(addr, id, v));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  // TODO: for dynamic changes to the queues container, use a shared lock
  class MultiTriggerQueue
    : public IndexedMessageQueues<tuple<Address, Identifier>, MsgQueue<Value> >
  {
  public:
    typedef tuple<Address, Identifier> QueueKey;
    //typedef LockfreeMsgQueue<Value> Queue;
    typedef LockingMsgQueue<Value> Queue;
    typedef map<QueueKey, shared_ptr<Queue> > MultiTriggerMessages;

    MultiTriggerQueue() : LogMT("MultiTriggerQueue") {}

    MultiTriggerQueue(const list<Address>& addresses, const list<Identifier>& triggerIds)
      : LogMT("MultiTriggerQueue")
    {
      for ( auto addr : addresses ) {
        for ( auto id : triggerIds ) {
          multiTriggerMsgs.insert(
            make_pair(make_tuple(addr, id), shared_ptr<Queue>(new Queue())));
        }
      }
    }

    size_t size() {
      size_t r = 0;
      for ( auto x : multiTriggerMsgs ) { r += x.second? x.second->size() : 0; }
      return r;
    }

  protected:
    typedef MsgQueue<Value> BaseQueue;
    MultiTriggerMessages multiTriggerMsgs;

    bool validTarget(Message& m) {
      return multiTriggerMsgs.find(make_tuple(m.address(), m.id())) != multiTriggerMsgs.end();
    }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(
                multiTriggerMsgs[make_tuple(m.address(), m.id())]);
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      tuple<QueueKey, shared_ptr<BaseQueue> > r;

      MultiTriggerMessages::iterator it =
        find_if(multiTriggerMsgs.begin(), multiTriggerMsgs.end(),
          [](MultiTriggerMessages::value_type& x) { return x.second->empty(); });

      if ( it != multiTriggerMsgs.end() ) {
        r = make_tuple(it->first, dynamic_pointer_cast<BaseQueue, Queue>(it->second));
      }
      return r;
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q) {
      if ( !(q && q->push(m.contents())) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message > dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message > r;
      Value entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(get<0>(idxQ));
        const Identifier& id = get<1>(get<0>(idxQ));
        r = shared_ptr<Message >(new Message(addr, id, entry));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  //--------------------
  // Queue constructors.

  shared_ptr<MessageQueues> simpleQueues(Address addr)
  {
    return shared_ptr<MessageQueues>(new SinglePeerQueue(addr));
  }

  shared_ptr<MessageQueues> perPeerQueues(const list<Address>& addresses)
  {
    return shared_ptr<MessageQueues>(new MultiPeerQueue(addresses));
  }

  shared_ptr<MessageQueues>
  perTriggerQueues(const list<Address>& addresses, const list<Identifier>& triggerIds)
  {
    return shared_ptr<MessageQueues>(new MultiTriggerQueue(addresses, triggerIds));
  }
}

#endif
<commit_msg>Fixed MessageQueues' enqueue arg to be a reference rather than a copy<commit_after>#ifndef K3_RUNTIME_QUEUE_H
#define K3_RUNTIME_QUEUE_H

#include <list>
#include <map>
#include <memory>
#include <queue>
#include <tuple>
#include <boost/lockfree/queue.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/externally_locked.hpp>

#include <Common.hpp>

namespace K3 {

  // using namespace std;
  using namespace boost;
  using std::shared_ptr;

  using mutex = boost::mutex;

  //-------------
  // Queue types.

  // TODO: r-ref overloads for push and pop
  template<typename Value>
  class MsgQueue {
  public:
    virtual bool push(Value& v) = 0;
    virtual bool pop(Value& v) = 0;
    virtual bool empty() = 0;
    virtual size_t size() = 0;
  };

  // TODO: r-ref overloads for push and pop
  template<typename Value>
  class LockfreeMsgQueue : public MsgQueue<Value> {
  public:
    LockfreeMsgQueue() {}
    bool empty()        { return queue.empty(); }
    bool push(Value& v) { ++qSize; return queue.push(v); }
    bool pop(Value& v)  { --qSize; return queue.pop(v); }
    size_t size()       { return qSize; }
  protected:
    boost::lockfree::queue<Value> queue;
    size_t qSize; // TODO: synchronize.
  };

  // TODO: r-ref overloads for push and pop
  template<typename Value>
  class LockingMsgQueue
    : public MsgQueue<Value>, public basic_lockable_adapter<mutex>
  {
  public:
    typedef basic_lockable_adapter<mutex> qlockable;
    LockingMsgQueue () : qlockable(), queue(*this) {}

    bool empty() {
      strict_lock<LockingMsgQueue> guard(*this);
      return queue.get(guard).empty();
    }

    bool push(Value& v) {
      strict_lock<LockingMsgQueue> guard(*this);
      ++qSize;
      queue.get(guard).push(v);
      return true;
    }

    bool pop(Value& v) {
      strict_lock<LockingMsgQueue> guard(*this);
      bool r = false;
      if ( !queue.get(guard).empty() ) {
        --qSize;
        v = queue.get(guard).front();
        queue.get(guard).pop();
        r = true;
      }
      return r;
    }

    size_t size() { return qSize; }

  protected:
    externally_locked<std::queue<Value>, LockingMsgQueue> queue;
    size_t qSize; // TODO: synchronize
  };

  //------------------
  // Queue containers.

  // TODO: r-ref overload for enqueue
  class MessageQueues : public virtual LogMT {
  public:
    MessageQueues() : LogMT("queue") {}
    virtual void enqueue(Message& m) = 0;
    virtual shared_ptr<Message> dequeue() = 0;
    virtual size_t size() = 0;
  };

  // TODO: r-ref overload for enqueue
  template<typename QueueIndex, typename Queue>
  class IndexedMessageQueues : public MessageQueues
  {
  public:
    IndexedMessageQueues() : LogMT("IndexedMessageQueues") {}

    void enqueue(Message& m)
    {
      if ( validTarget(m) ) { enqueue(m, queue(m)); }
      else {
        BOOST_LOG(*this) << "Invalid message target: "
                         << addressAsString(m.address()) << ":" << m.id();
      }
    }

    // TODO: fair queueing policy.
    shared_ptr<Message> dequeue()
    {
      shared_ptr<Message> r;
      tuple<QueueIndex, shared_ptr<Queue> > idxQ = nonEmptyQueue();
      if ( get<1>(idxQ) ) { r = dequeue(idxQ); }
      else {
        BOOST_LOG(*this) << "Invalid non-empty queue on dequeue";
      }
      return r;
    }

  protected:
    virtual bool validTarget(Message& m) = 0;

    virtual shared_ptr<Queue> queue(Message& m) = 0;
    virtual tuple<QueueIndex, shared_ptr<Queue> > nonEmptyQueue() = 0;

    virtual void enqueue(Message& m, shared_ptr<Queue> q) = 0;
    virtual shared_ptr<Message> dequeue(const tuple<QueueIndex, shared_ptr<Queue> >& q) = 0;
  };

  class SinglePeerQueue
    : public IndexedMessageQueues<Address, MsgQueue<tuple<Identifier, Value> > >
  {
  public:
    typedef Address QueueKey;
    //typedef LockfreeMsgQueue<tuple<Identifier, Value> > Queue;
    typedef LockingMsgQueue<tuple<Identifier, Value> > Queue;
    typedef tuple<QueueKey, shared_ptr<Queue> > PeerMessages;

    SinglePeerQueue() : LogMT("SinglePeerQueue") {}

    SinglePeerQueue(Address addr)
      : LogMT("SinglePeerQueue"), peerMsgs(addr, shared_ptr<Queue>(new Queue()))
    {}

    size_t size() { return get<1>(peerMsgs)->size(); }

  protected:
    typedef MsgQueue<tuple<Identifier, Value> > BaseQueue;
    PeerMessages peerMsgs;

    bool validTarget(Message& m) { return m.address() == get<0>(peerMsgs); }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(get<1>(peerMsgs));
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      shared_ptr<Queue> r = get<1>(peerMsgs);
      shared_ptr<BaseQueue> br =
        r->empty()? shared_ptr<BaseQueue>() : dynamic_pointer_cast<BaseQueue, Queue>(r);
      return make_tuple(get<0>(peerMsgs), br);
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q)
    {
      tuple<Identifier, Value> entry = make_tuple(m.id(), m.contents());
      if ( !(q && q->push(entry)) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message> dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message>  r;
      tuple<Identifier, Value> entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(idxQ);
        const Identifier& id = get<0>(entry);
        const Value& v       = get<1>(entry);
        r = shared_ptr<Message>(new Message(addr, id, v));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  // TODO: r-ref overload for enqueue
  // TODO: for dynamic changes to the queues container, use a shared lock
  class MultiPeerQueue
    : public IndexedMessageQueues<Address, MsgQueue<tuple<Identifier, Value> > >
  {
  public:
    typedef Address QueueKey;
    //typedef LockfreeMsgQueue<tuple<Identifier, Value> > Queue;
    typedef LockingMsgQueue<tuple<Identifier, Value> > Queue;
    typedef map<QueueKey, shared_ptr<Queue> > MultiPeerMessages;

    MultiPeerQueue() : LogMT("MultiPeerQueue") {}
    MultiPeerQueue(const list<Address>& addresses) : LogMT("MultiPeerQueue") {
      for ( auto x : addresses ) {
        multiPeerMsgs.insert(make_pair(x, shared_ptr<Queue>(new Queue())));
      }
    }

    size_t size() {
      size_t r = 0;
      for ( auto x : multiPeerMsgs ) { r += x.second? x.second->size() : 0; }
      return r;
    }

  protected:
    typedef MsgQueue<tuple<Identifier, Value> > BaseQueue;
    MultiPeerMessages multiPeerMsgs;

    bool validTarget(Message& m) {
      return multiPeerMsgs.find(m.address()) != multiPeerMsgs.end();
    }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(multiPeerMsgs[m.address()]);
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      tuple<QueueKey, shared_ptr<BaseQueue> > r;

      MultiPeerMessages::iterator it =
        find_if(multiPeerMsgs.begin(), multiPeerMsgs.end(),
          [](MultiPeerMessages::value_type& x){ return x.second->empty(); });

      if ( it != multiPeerMsgs.end() ) {
        r = make_tuple(it->first, dynamic_pointer_cast<BaseQueue, Queue>(it->second));
      }
      return r;
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q)
    {
      tuple<Identifier, Value> entry = make_tuple(m.id(), m.contents());
      if ( !(q && q->push(entry)) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message> dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message> r;
      tuple<Identifier, Value> entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(idxQ);
        const Identifier& id = get<0>(entry);
        const Value& v       = get<1>(entry);
        r = shared_ptr<Message >(new Message(addr, id, v));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  // TODO: r-ref overload for enqueue
  // TODO: for dynamic changes to the queues container, use a shared lock
  class MultiTriggerQueue
    : public IndexedMessageQueues<tuple<Address, Identifier>, MsgQueue<Value> >
  {
  public:
    typedef tuple<Address, Identifier> QueueKey;
    //typedef LockfreeMsgQueue<Value> Queue;
    typedef LockingMsgQueue<Value> Queue;
    typedef map<QueueKey, shared_ptr<Queue> > MultiTriggerMessages;

    MultiTriggerQueue() : LogMT("MultiTriggerQueue") {}

    MultiTriggerQueue(const list<Address>& addresses, const list<Identifier>& triggerIds)
      : LogMT("MultiTriggerQueue")
    {
      for ( auto addr : addresses ) {
        for ( auto id : triggerIds ) {
          multiTriggerMsgs.insert(
            make_pair(make_tuple(addr, id), shared_ptr<Queue>(new Queue())));
        }
      }
    }

    size_t size() {
      size_t r = 0;
      for ( auto x : multiTriggerMsgs ) { r += x.second? x.second->size() : 0; }
      return r;
    }

  protected:
    typedef MsgQueue<Value> BaseQueue;
    MultiTriggerMessages multiTriggerMsgs;

    bool validTarget(Message& m) {
      return multiTriggerMsgs.find(make_tuple(m.address(), m.id())) != multiTriggerMsgs.end();
    }

    shared_ptr<BaseQueue> queue(Message& m) {
      return dynamic_pointer_cast<BaseQueue, Queue>(
                multiTriggerMsgs[make_tuple(m.address(), m.id())]);
    }

    tuple<QueueKey, shared_ptr<BaseQueue> > nonEmptyQueue()
    {
      tuple<QueueKey, shared_ptr<BaseQueue> > r;

      MultiTriggerMessages::iterator it =
        find_if(multiTriggerMsgs.begin(), multiTriggerMsgs.end(),
          [](MultiTriggerMessages::value_type& x) { return x.second->empty(); });

      if ( it != multiTriggerMsgs.end() ) {
        r = make_tuple(it->first, dynamic_pointer_cast<BaseQueue, Queue>(it->second));
      }
      return r;
    }

    void enqueue(Message& m, shared_ptr<BaseQueue> q) {
      if ( !(q && q->push(m.contents())) ) {
        BOOST_LOG(*this) << "Invalid destination queue during enqueue";
      }
    }

    shared_ptr<Message > dequeue(const tuple<QueueKey, shared_ptr<BaseQueue> >& idxQ)
    {
      shared_ptr<Message > r;
      Value entry;

      shared_ptr<BaseQueue> q = get<1>(idxQ);
      if ( q && q->pop(entry) ) {
        const Address& addr  = get<0>(get<0>(idxQ));
        const Identifier& id = get<1>(get<0>(idxQ));
        r = shared_ptr<Message >(new Message(addr, id, entry));
      } else {
        BOOST_LOG(*this) << "Invalid source queue during dequeue";
      }
      return r;
    }
  };

  //--------------------
  // Queue constructors.

  shared_ptr<MessageQueues> simpleQueues(Address addr)
  {
    return shared_ptr<MessageQueues>(new SinglePeerQueue(addr));
  }

  shared_ptr<MessageQueues> perPeerQueues(const list<Address>& addresses)
  {
    return shared_ptr<MessageQueues>(new MultiPeerQueue(addresses));
  }

  shared_ptr<MessageQueues>
  perTriggerQueues(const list<Address>& addresses, const list<Identifier>& triggerIds)
  {
    return shared_ptr<MessageQueues>(new MultiTriggerQueue(addresses, triggerIds));
  }
}

#endif
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "EC_Light.h"
#include "ModuleInterface.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "Entity.h"
#include "OgreConversionUtils.h"
#include "XMLUtilities.h"
#include "RexNetworkUtils.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Light")

#include <Ogre.h>

#include <QDomDocument>

using namespace RexTypes;
using namespace OgreRenderer;

EC_Light::EC_Light(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    light_(0),
    attached_(false),
    typeAttr_(this, "light type", LT_Point),
    directionAttr_(this, "direction", Vector3df(0.0f, 0.0f, 1.0f)),
    diffColorAttr_(this, "diffuse color", Color(1.0f, 1.0f, 1.0f)),
    specColorAttr_(this, "specular color", Color(0.0f, 0.0f, 0.0f)),
    castShadowsAttr_(this, "cast shadows", false),
    rangeAttr_(this, "light range", 10.0f),
    constAttenAttr_(this, "constant atten", 1.0f),
    linearAttenAttr_(this, "linear atten", 0.0f),
    quadraAttenAttr_(this, "quadratic atten", 0.0f),
    innerAngleAttr_(this, "light inner angle", 30.0f),
    outerAngleAttr_(this, "light outer angle", 40.0f)
{
    static AttributeMetadata typeAttrData;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        typeAttrData.enums[LT_Point]       = "Point";
        typeAttrData.enums[LT_Spot]        = "Spot";
        typeAttrData.enums[LT_Directional] = "Directional";
        metadataInitialized = true;
    }
    typeAttr_.SetMetadata(&typeAttrData);

    boost::shared_ptr<Renderer> renderer = module->GetFramework()->GetServiceManager()->GetService
        <Renderer>(Foundation::Service::ST_Renderer).lock();
    if (!renderer)
        return;

    Ogre::SceneManager* scene_mgr = renderer->GetSceneManager();
    light_ = scene_mgr->createLight(renderer->GetUniqueObjectName());

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateOgreLight()));

}

EC_Light::~EC_Light()
{
    if (!GetFramework())
        return;

    boost::shared_ptr<Renderer> renderer = GetFramework()->GetServiceManager()->GetService
        <Renderer>(Foundation::Service::ST_Renderer).lock();
    if (!renderer)
        return;

    if (light_)
    {
        DetachLight();
        Ogre::SceneManager* scene_mgr = renderer->GetSceneManager();
        scene_mgr->destroyLight(light_);
        light_ = 0;
    }
}

void EC_Light::SetPlaceable(Foundation::ComponentPtr placeable)
{
    if (dynamic_cast<EC_OgrePlaceable*>(placeable.get()) == 0)
    {
        LogError("Attempted to set a placeable which is not a placeable");
        return;
    }

    if (placeable_ == placeable)
        return;

    DetachLight();
    placeable_ = placeable;
    AttachLight();
}

void EC_Light::AttachLight()
{
    if ((placeable_) && (!attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->attachObject(light_);
        attached_ = true;
    }
}

void EC_Light::DetachLight()
{
    if ((placeable_) && (attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->detachObject(light_);
        attached_ = false;
    }
}

void EC_Light::UpdateOgreLight()
{
    // Now the true hack: because we don't (yet) store EC links/references, we hope to find a valid placeable from the entity, and to set it
    if (parent_entity_)
    {
        Foundation::ComponentPtr placeable = parent_entity_->GetComponent(EC_OgrePlaceable::TypeNameStatic());
        if (placeable)
            SetPlaceable(placeable);
        else
            LogError("No EC_OgrePlaceable in entity, EC_Light could not attach itself to scenenode");
    }
    else
        LogError("Parent entity not set, EC_Light could not auto-set placeable");

    Ogre::Light::LightTypes ogre_type = Ogre::Light::LT_POINT;

    switch (typeAttr_.Get())
    {
        case LT_Spot:
        ogre_type = Ogre::Light::LT_SPOTLIGHT;
        break;

        case LT_Directional:
        ogre_type = Ogre::Light::LT_DIRECTIONAL;
        break;
    }

    try
    {
        light_->setType(ogre_type);
        light_->setDirection(ToOgreVector3(directionAttr_.Get()));
        light_->setDiffuseColour(ToOgreColor(diffColorAttr_.Get()));
        light_->setSpecularColour(ToOgreColor(specColorAttr_.Get()));
        light_->setAttenuation(rangeAttr_.Get(), constAttenAttr_.Get(), linearAttenAttr_.Get(), quadraAttenAttr_.Get());
        // Note: Ogre throws exception if we try to set this when light is not spotlight
        if (typeAttr_.Get() == LT_Spot)
            light_->setSpotlightRange(Ogre::Degree(innerAngleAttr_.Get()), Ogre::Degree(outerAngleAttr_.Get()));
    }
    catch (Ogre::Exception& e)
    {
        LogError("Exception while setting EC_Light parameters to Ogre: " + std::string(e.what()));
    }
}

<commit_msg>Better EC_Light default values so it looks nicer when added in comp editor. New default values courtesy of Manaluusuas ogre/math brain.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "EC_Light.h"
#include "ModuleInterface.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "Entity.h"
#include "OgreConversionUtils.h"
#include "XMLUtilities.h"
#include "RexNetworkUtils.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Light")

#include <Ogre.h>

#include <QDomDocument>

using namespace RexTypes;
using namespace OgreRenderer;

EC_Light::EC_Light(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    light_(0),
    attached_(false),
    typeAttr_(this, "light type", LT_Point),
    directionAttr_(this, "direction", Vector3df(0.0f, 0.0f, 1.0f)),
    diffColorAttr_(this, "diffuse color", Color(1.0f, 1.0f, 1.0f)),
    specColorAttr_(this, "specular color", Color(0.0f, 0.0f, 0.0f)),
    castShadowsAttr_(this, "cast shadows", false),
    rangeAttr_(this, "light range", 100.0f),
    constAttenAttr_(this, "constant atten", 0.0f),
    linearAttenAttr_(this, "linear atten", 0.01f),
    quadraAttenAttr_(this, "quadratic atten", 0.01f),
    innerAngleAttr_(this, "light inner angle", 30.0f),
    outerAngleAttr_(this, "light outer angle", 40.0f)
{
    static AttributeMetadata typeAttrData;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        typeAttrData.enums[LT_Point]       = "Point";
        typeAttrData.enums[LT_Spot]        = "Spot";
        typeAttrData.enums[LT_Directional] = "Directional";
        metadataInitialized = true;
    }
    typeAttr_.SetMetadata(&typeAttrData);

    boost::shared_ptr<Renderer> renderer = module->GetFramework()->GetServiceManager()->GetService
        <Renderer>(Foundation::Service::ST_Renderer).lock();
    if (!renderer)
        return;

    Ogre::SceneManager* scene_mgr = renderer->GetSceneManager();
    light_ = scene_mgr->createLight(renderer->GetUniqueObjectName());

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateOgreLight()));

}

EC_Light::~EC_Light()
{
    if (!GetFramework())
        return;

    boost::shared_ptr<Renderer> renderer = GetFramework()->GetServiceManager()->GetService
        <Renderer>(Foundation::Service::ST_Renderer).lock();
    if (!renderer)
        return;

    if (light_)
    {
        DetachLight();
        Ogre::SceneManager* scene_mgr = renderer->GetSceneManager();
        scene_mgr->destroyLight(light_);
        light_ = 0;
    }
}

void EC_Light::SetPlaceable(Foundation::ComponentPtr placeable)
{
    if (dynamic_cast<EC_OgrePlaceable*>(placeable.get()) == 0)
    {
        LogError("Attempted to set a placeable which is not a placeable");
        return;
    }

    if (placeable_ == placeable)
        return;

    DetachLight();
    placeable_ = placeable;
    AttachLight();
}

void EC_Light::AttachLight()
{
    if ((placeable_) && (!attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->attachObject(light_);
        attached_ = true;
    }
}

void EC_Light::DetachLight()
{
    if ((placeable_) && (attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->detachObject(light_);
        attached_ = false;
    }
}

void EC_Light::UpdateOgreLight()
{
    // Now the true hack: because we don't (yet) store EC links/references, we hope to find a valid placeable from the entity, and to set it
    if (parent_entity_)
    {
        Foundation::ComponentPtr placeable = parent_entity_->GetComponent(EC_OgrePlaceable::TypeNameStatic());
        if (placeable)
            SetPlaceable(placeable);
        else
            LogError("No EC_OgrePlaceable in entity, EC_Light could not attach itself to scenenode");
    }
    else
        LogError("Parent entity not set, EC_Light could not auto-set placeable");

    Ogre::Light::LightTypes ogre_type = Ogre::Light::LT_POINT;

    switch (typeAttr_.Get())
    {
        case LT_Spot:
        ogre_type = Ogre::Light::LT_SPOTLIGHT;
        break;

        case LT_Directional:
        ogre_type = Ogre::Light::LT_DIRECTIONAL;
        break;
    }

    try
    {
        light_->setType(ogre_type);
        light_->setDirection(ToOgreVector3(directionAttr_.Get()));
        light_->setDiffuseColour(ToOgreColor(diffColorAttr_.Get()));
        light_->setSpecularColour(ToOgreColor(specColorAttr_.Get()));
        light_->setAttenuation(rangeAttr_.Get(), constAttenAttr_.Get(), linearAttenAttr_.Get(), quadraAttenAttr_.Get());
        // Note: Ogre throws exception if we try to set this when light is not spotlight
        if (typeAttr_.Get() == LT_Spot)
            light_->setSpotlightRange(Ogre::Degree(innerAngleAttr_.Get()), Ogre::Degree(outerAngleAttr_.Get()));
    }
    catch (Ogre::Exception& e)
    {
        LogError("Exception while setting EC_Light parameters to Ogre: " + std::string(e.what()));
    }
}

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// All code is property of Dictator Developers Inc
// Contact at Loesby.dev@gmail.com for permission to use
// Or to discuss ideas
// (c) 2018

// Systems/CaravanTrade.cpp
// When a Caravan is at the end of a route, perform the trade and turn around

#include "../Core/typedef.h"

#include "Systems.h"

#include "../ECS/System.h"
#include "../ECS/ECS.h"

#include <algorithm>

void CaravanTrade::ProgramInit() {}
void CaravanTrade::SetupGameplay() {}

enum class TradeType
{
	PREFER_EXCHANGE,
	HIGHEST_AVAILABLE
};

void PerformTrade(
	ECS_Core::Components::C_ResourceInventory& caravanInventory,
	ECS_Core::Components::C_ResourceInventory& buildingInventory,
	ECS_Core::Manager& manager,
	TradeType tradeType)
{
	using namespace ECS_Core;
	// Drop off everything but some food
	for (auto&& resource : caravanInventory.m_collectedYields)
	{
		auto amountToMove = resource.first == Components::Yields::FOOD ?
			(resource.second > 100 ? (resource.second - 100) : 0)
			: resource.second;
		buildingInventory.m_collectedYields[resource.first] += amountToMove;
		resource.second -= amountToMove;
	}
	// Then take the most available yields in the inventory of the base, preferring those not carried back this way
	std::vector<std::pair<ECS_Core::Components::YieldType, f64>> heldResources;
	for (auto&& resource : buildingInventory.m_collectedYields)
	{
		heldResources.push_back(resource);
	}
	if (tradeType == TradeType::PREFER_EXCHANGE)
	{
		std::sort(
			heldResources.begin(),
			heldResources.end(),
			[&caravanInventory](auto& left, auto& right) -> bool {
				if (caravanInventory.m_collectedYields.count(left.first) && !caravanInventory.m_collectedYields.count(right.first))
				{
					return false;
				}
				if (!caravanInventory.m_collectedYields.count(left.first) && caravanInventory.m_collectedYields.count(right.first))
				{
					return true;
				}
				if (left.second < right.second) return false;
				if (left.second > right.second) return true;
				return left.first < right.first;
			});
	}
	else
	{
		std::sort(
			heldResources.begin(),
			heldResources.end(),
			[](auto& left, auto& right) -> bool {
				if (left.second < right.second) return false;
				if (left.second > right.second) return true;
				return left.first < right.first;
			});
	}
	// Reset inventory
	auto remainingFood = caravanInventory.m_collectedYields[Components::Yields::FOOD];
	caravanInventory.m_collectedYields.clear();
	auto foodToTake = min<f64>(100 - remainingFood, buildingInventory.m_collectedYields[Components::Yields::FOOD]);
	buildingInventory.m_collectedYields[Components::Yields::FOOD] -= foodToTake;
	caravanInventory.m_collectedYields[Components::Yields::FOOD] = remainingFood + foodToTake;
	auto resourcesMoved{ 0 };
	for (auto&& resource : heldResources)
	{
		if (resource.second <= 100) continue;
		caravanInventory.m_collectedYields[resource.first] = 100;
		buildingInventory.m_collectedYields[resource.first] -= 100;
		if (++resourcesMoved >= 3)
		{
			break;
		}
	}
}

void CaravanTrade::Operate(GameLoopPhase phase, const timeuS& frameDuration)
{
	using namespace ECS_Core;
	switch (phase)
	{
	case GameLoopPhase::ACTION_RESPONSE:
		m_managerRef.forEntitiesMatching<ECS_Core::Signatures::S_CaravanUnit>([&manager = m_managerRef](
			const ecs::EntityIndex&,
			const Components::C_TilePosition& position,
			Components::C_MovingUnit& mover,
			Components::C_ResourceInventory& inventory,
			const Components::C_Population&,
			Components::C_CaravanPath& path)
		{
			if (position.m_position == path.m_basePath.m_path.front().m_tile
				&& path.m_isReturning)
			{
				// Trade with home base and turn around
				if (!mover.m_currentMovement
					|| !std::holds_alternative<Components::MoveToPoint>(*mover.m_currentMovement))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				if (!manager.hasComponent<Components::C_ResourceInventory>(path.m_originBuildingHandle))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				auto& baseInventory = manager.getComponent<Components::C_ResourceInventory>(path.m_originBuildingHandle);
				PerformTrade(inventory, baseInventory, manager, TradeType::HIGHEST_AVAILABLE);

				auto& moveToPoint = std::get<Components::MoveToPoint>(*mover.m_currentMovement);
				std::reverse(moveToPoint.m_path.begin(), moveToPoint.m_path.end());
				moveToPoint.m_currentPathIndex = 0;
				moveToPoint.m_currentMovementProgress = 0;
				moveToPoint.m_targetPosition = moveToPoint.m_path.back().m_tile;
				path.m_isReturning = false;
			}
			else if (position.m_position == path.m_basePath.m_path.back().m_tile
				&& !path.m_isReturning)
			{
				// Trade with target and turn around
				if (!mover.m_currentMovement
					|| !std::holds_alternative<Components::MoveToPoint>(*mover.m_currentMovement))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				if (!manager.hasComponent<Components::C_ResourceInventory>(path.m_targetBuildingHandle))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				PerformTrade(inventory,
					manager.getComponent<Components::C_ResourceInventory>(path.m_targetBuildingHandle),
					manager,
					TradeType::PREFER_EXCHANGE);

				auto& moveToPoint = std::get<Components::MoveToPoint>(*mover.m_currentMovement);
				std::reverse(moveToPoint.m_path.begin(), moveToPoint.m_path.end());
				moveToPoint.m_currentPathIndex = 0;
				moveToPoint.m_currentMovementProgress = 0;
				moveToPoint.m_targetPosition = moveToPoint.m_path.back().m_tile;
				path.m_isReturning = true;
			}
			return ecs::IterationBehavior::CONTINUE;
		});
		break;
	case GameLoopPhase::PREPARATION:
	case GameLoopPhase::INPUT:
	case GameLoopPhase::ACTION:
	case GameLoopPhase::RENDER:
	case GameLoopPhase::CLEANUP:
		return;
	}
}

bool CaravanTrade::ShouldExit()
{
	return false;
}

DEFINE_SYSTEM_INSTANTIATION(CaravanTrade);<commit_msg>No more food hole on caravans<commit_after>//-----------------------------------------------------------------------------
// All code is property of Dictator Developers Inc
// Contact at Loesby.dev@gmail.com for permission to use
// Or to discuss ideas
// (c) 2018

// Systems/CaravanTrade.cpp
// When a Caravan is at the end of a route, perform the trade and turn around

#include "../Core/typedef.h"

#include "Systems.h"

#include "../ECS/System.h"
#include "../ECS/ECS.h"

#include <algorithm>

void CaravanTrade::ProgramInit() {}
void CaravanTrade::SetupGameplay() {}

enum class TradeType
{
	PREFER_EXCHANGE,
	HIGHEST_AVAILABLE
};

void PerformTrade(
	ECS_Core::Components::C_ResourceInventory& caravanInventory,
	ECS_Core::Components::C_ResourceInventory& buildingInventory,
	ECS_Core::Manager& manager,
	TradeType tradeType)
{
	using namespace ECS_Core;
	// Drop off everything but some food
	for (auto&& resource : caravanInventory.m_collectedYields)
	{
		auto amountToMove = resource.first == Components::Yields::FOOD ?
			(resource.second > 100 ? (resource.second - 100) : 0)
			: resource.second;
		buildingInventory.m_collectedYields[resource.first] += amountToMove;
		resource.second -= amountToMove;
	}
	// Then take the most available yields in the inventory of the base, preferring those not carried back this way
	std::vector<std::pair<ECS_Core::Components::YieldType, f64>> heldResources;
	for (auto&& resource : buildingInventory.m_collectedYields)
	{
		heldResources.push_back(resource);
	}
	if (tradeType == TradeType::PREFER_EXCHANGE)
	{
		std::sort(
			heldResources.begin(),
			heldResources.end(),
			[&caravanInventory](auto& left, auto& right) -> bool {
				if (caravanInventory.m_collectedYields.count(left.first) && !caravanInventory.m_collectedYields.count(right.first))
				{
					return false;
				}
				if (!caravanInventory.m_collectedYields.count(left.first) && caravanInventory.m_collectedYields.count(right.first))
				{
					return true;
				}
				if (left.second < right.second) return false;
				if (left.second > right.second) return true;
				return left.first < right.first;
			});
	}
	else
	{
		std::sort(
			heldResources.begin(),
			heldResources.end(),
			[](auto& left, auto& right) -> bool {
				if (left.second < right.second) return false;
				if (left.second > right.second) return true;
				return left.first < right.first;
			});
	}
	// Reset inventory
	auto remainingFood = caravanInventory.m_collectedYields[Components::Yields::FOOD];
	caravanInventory.m_collectedYields.clear();
	auto foodToTake = min<f64>(100 - remainingFood, buildingInventory.m_collectedYields[Components::Yields::FOOD]);
	buildingInventory.m_collectedYields[Components::Yields::FOOD] -= foodToTake;
	caravanInventory.m_collectedYields[Components::Yields::FOOD] = remainingFood + foodToTake;
	auto resourcesMoved{ 0 };
	for (auto&& resource : heldResources)
	{
		if (resource.second <= 100) continue;
		caravanInventory.m_collectedYields[resource.first] += 100;
		buildingInventory.m_collectedYields[resource.first] -= 100;
		if (++resourcesMoved >= 3)
		{
			break;
		}
	}
}

void CaravanTrade::Operate(GameLoopPhase phase, const timeuS& frameDuration)
{
	using namespace ECS_Core;
	switch (phase)
	{
	case GameLoopPhase::ACTION_RESPONSE:
		m_managerRef.forEntitiesMatching<ECS_Core::Signatures::S_CaravanUnit>([&manager = m_managerRef](
			const ecs::EntityIndex&,
			const Components::C_TilePosition& position,
			Components::C_MovingUnit& mover,
			Components::C_ResourceInventory& inventory,
			const Components::C_Population&,
			Components::C_CaravanPath& path)
		{
			if (position.m_position == path.m_basePath.m_path.front().m_tile
				&& path.m_isReturning)
			{
				// Trade with home base and turn around
				if (!mover.m_currentMovement
					|| !std::holds_alternative<Components::MoveToPoint>(*mover.m_currentMovement))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				if (!manager.hasComponent<Components::C_ResourceInventory>(path.m_originBuildingHandle))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				auto& baseInventory = manager.getComponent<Components::C_ResourceInventory>(path.m_originBuildingHandle);
				PerformTrade(inventory, baseInventory, manager, TradeType::HIGHEST_AVAILABLE);

				auto& moveToPoint = std::get<Components::MoveToPoint>(*mover.m_currentMovement);
				std::reverse(moveToPoint.m_path.begin(), moveToPoint.m_path.end());
				moveToPoint.m_currentPathIndex = 0;
				moveToPoint.m_currentMovementProgress = 0;
				moveToPoint.m_targetPosition = moveToPoint.m_path.back().m_tile;
				path.m_isReturning = false;
			}
			else if (position.m_position == path.m_basePath.m_path.back().m_tile
				&& !path.m_isReturning)
			{
				// Trade with target and turn around
				if (!mover.m_currentMovement
					|| !std::holds_alternative<Components::MoveToPoint>(*mover.m_currentMovement))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				if (!manager.hasComponent<Components::C_ResourceInventory>(path.m_targetBuildingHandle))
				{
					return ecs::IterationBehavior::CONTINUE;
				}
				PerformTrade(inventory,
					manager.getComponent<Components::C_ResourceInventory>(path.m_targetBuildingHandle),
					manager,
					TradeType::PREFER_EXCHANGE);

				auto& moveToPoint = std::get<Components::MoveToPoint>(*mover.m_currentMovement);
				std::reverse(moveToPoint.m_path.begin(), moveToPoint.m_path.end());
				moveToPoint.m_currentPathIndex = 0;
				moveToPoint.m_currentMovementProgress = 0;
				moveToPoint.m_targetPosition = moveToPoint.m_path.back().m_tile;
				path.m_isReturning = true;
			}
			return ecs::IterationBehavior::CONTINUE;
		});
		break;
	case GameLoopPhase::PREPARATION:
	case GameLoopPhase::INPUT:
	case GameLoopPhase::ACTION:
	case GameLoopPhase::RENDER:
	case GameLoopPhase::CLEANUP:
		return;
	}
}

bool CaravanTrade::ShouldExit()
{
	return false;
}

DEFINE_SYSTEM_INSTANTIATION(CaravanTrade);<|endoftext|>