<commit_before>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <CommDbConnPref.h>     // connection prefs (iap)

#include "push/FSocket.h"
#include "base/SymbianLog.h"
#include "base/util/stringUtils.h"
#include "base/util/symbianUtils.h"

StringBuffer FSocket::lIP;

FSocket* FSocket::createSocket(const StringBuffer& peer, int32_t port)
{
    return FSocket::NewL(peer, port);
}

FSocket* FSocket::NewL(const StringBuffer& peer, int32_t port)
{
    FSocket* self = FSocket::NewLC(peer, port);
    CleanupStack::Pop( self );
    return self;
}

FSocket* FSocket::NewLC(const StringBuffer& peer, int32_t port)
{
    FSocket* self = new ( ELeave ) FSocket();
    CleanupStack::PushL( self );
    self->ConstructL(peer, port);
    return self;
}

void FSocket::ConstructL(const StringBuffer& peer, int32_t port)
{
    LOG.debug("FSocket::ConstructL");
    StringBuffer errorMsg;

    RBuf serverName;
    serverName.Assign(stringBufferToNewBuf(peer));

    // Create the socket session
    iSocketSession.Connect();

    // Open the Client Socket tcp/ip
    TInt res = iSocket.Open(iSocketSession, KAfInet, KSockStream, KProtocolInetTcp);
    if (res != KErrNone) {
        iStatus = -1;
        errorMsg = "Error opening socket";
        goto error;
    }

    // --- Resolve the host address ---
    LOG.debug("resolve IP address...");
    RHostResolver resolver;
    res = resolver.Open(iSocketSession, KAfInet, KProtocolInetTcp);
    if (res != KErrNone) {
        iStatus = -2;
        errorMsg = "Host resolver open failed";
        goto error;
    }

    TNameEntry hostAddress;
    resolver.GetByName(serverName, hostAddress, iStatus);
    User::WaitForRequest(iStatus);
    resolver.Close();
    if (iStatus != KErrNone) {
        errorMsg = "DNS lookup failed";
        goto error;
    }

    // Set the socket server address/port
    TInetAddr address = hostAddress().iAddr;
    address.SetPort(port);

    // --- Connect to host ---
    LOG.debug("connect...");
    iSocket.Connect(address, iStatus);
    User::WaitForRequest(iStatus);
    if (iStatus != KErrNone) {
        errorMsg = "Failed to connect to Server";
        goto error;
    }

    return;

error:
    LOG.error(errorMsg.c_str());    // msgBox?
    iSocketSession.Close();
    return;
}

FSocket::FSocket()
{
    iStatus = 0;
}

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

int32_t FSocket::writeBuffer(const int8_t* const buffer, int32_t len)
{
    // This doesn't copy the buffer in memory.
    TPtr8 data((TUint8*)buffer, len);

    // Sends data to the remote host.
    iSocket.Write(data, iStatus);
    User::WaitForRequest(iStatus);

    if (iStatus == KErrNone) {
        return len;
    }
    else {
        LOG.error("FSocket: error writing on socket (status = %d)", iStatus.Int());
        return -1;
    }
}

int32_t FSocket::readBuffer(int8_t* buffer, int32_t maxLen)
{
    RBuf8 data;
    data.CreateL(maxLen);

    // Receives data from a remote host and completes when data is available.
    do {
        TSockXfrLength len;
        iSocket.RecvOneOrMore(data, 0, iStatus, len);
        User::WaitForRequest(iStatus);
        LOG.debug("received %d bytes...", data.Length());
    } while (iStatus == KErrNone);
    //
    // TODO: status error codes?
    //

    if (iStatus == KErrNone) {
        const char* ret = buf8ToNewChar(data);
        buffer = (int8_t*)ret;
        return data.Length();
    }
    else {
        LOG.error("FSocket: error reading on socket (status = %d)", iStatus.Int());
        buffer = NULL;
        return -1;
    }
}

void FSocket::close()
{
    LOG.debug("FSocket::close");
    //iSocket.CancelAll();
    iSocket.Close();
    iSocketSession.Close();
}

const StringBuffer& FSocket::address() const {
    return lAddress;
}

const StringBuffer& FSocket::peerAddress() const {
    return pAddress;
}

const StringBuffer& FSocket::localIP() {
    return lIP;
}

void FSocket::startConnection()
{
    RConnection connection;
    RSocketServ socketServ;
    User::LeaveIfError(socketServ.Connect());

    // Use the default IAP without prompting the user
    TUint32 UidAP=0;
    TCommDbConnPref prefs;
    prefs.SetDialogPreference (ECommDbDialogPrefDoNotPrompt);
    prefs.SetDirection (ECommDbConnectionDirectionUnknown);
    prefs.SetIapId (UidAP);

    User::LeaveIfError (connection.Open (socketServ, KAfInet));
    User::LeaveIfError (connection.Start (prefs));

    // use this to search for a particular IAP to use
    // withouth prompting the user
#if defined(PREDEFINED_IAP)
    CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
    CleanupStack::PushL(commDb);
    CApSelect* select = CApSelect::NewLC(*commDb,KEApIspTypeAll,EApBearerTypeAll,KEApSortUidAscending);
    TBuf<256> accessPoint;
    TInt UidAP= 0;
    TBool ok = select->MoveToFirst();
    for (TInt32 i = 0; ok&&(i<select->Count()); i++)
        {
        if ( select->Name ()==_L(PREDEFINED_IAP))
            {
            UidAP = select->Uid ();
            TCommDbConnPref prefs;
            prefs.SetDialogPreference (ECommDbDialogPrefDoNotPrompt);
            prefs.SetDirection (ECommDbConnectionDirectionUnknown);
            prefs.SetIapId (UidAP);

            User::LeaveIfError (iConnection.Open (iSocketSession, KAfInet));
            User::LeaveIfError (iConnection.Start (prefs));

            }
        else
            {
            ok = select->MoveNext ();
            }
        }
#else
    // use this if you want prompt user for IAP
    TCommDbConnPref pref;
    pref.SetDirection(ECommDbConnectionDirectionUnknown);

    connection.Open(socketServ, KAfInet);
    connection.Start(pref);
#endif

    socketServ.Close();
}

<commit_msg>moved local variable declarations at the beginning of the method, for compiler errors<commit_after>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <CommDbConnPref.h>     // connection prefs (iap)

#include "push/FSocket.h"
#include "base/SymbianLog.h"
#include "base/util/stringUtils.h"
#include "base/util/symbianUtils.h"

StringBuffer FSocket::lIP;

FSocket* FSocket::createSocket(const StringBuffer& peer, int32_t port)
{
    return FSocket::NewL(peer, port);
}

FSocket* FSocket::NewL(const StringBuffer& peer, int32_t port)
{
    FSocket* self = FSocket::NewLC(peer, port);
    CleanupStack::Pop( self );
    return self;
}

FSocket* FSocket::NewLC(const StringBuffer& peer, int32_t port)
{
    FSocket* self = new ( ELeave ) FSocket();
    CleanupStack::PushL( self );
    self->ConstructL(peer, port);
    return self;
}

void FSocket::ConstructL(const StringBuffer& peer, int32_t port)
{
    LOG.debug("FSocket::ConstructL");

    StringBuffer  errorMsg;
    RHostResolver resolver;
    RBuf          serverName;
    TNameEntry    hostAddress;
    TInetAddr     address;

    serverName.Assign(stringBufferToNewBuf(peer));

    // Create the socket session
    iSocketSession.Connect();

    // Open the Client Socket tcp/ip
    TInt res = iSocket.Open(iSocketSession, KAfInet, KSockStream, KProtocolInetTcp);
    if (res != KErrNone) {
        iStatus = -1;
        errorMsg = "Error opening socket";
        goto error;
    }

    // --- Resolve the host address ---
    LOG.debug("resolve IP address...");
    res = resolver.Open(iSocketSession, KAfInet, KProtocolInetTcp);
    if (res != KErrNone) {
        iStatus = -2;
        errorMsg = "Host resolver open failed";
        goto error;
    }

    resolver.GetByName(serverName, hostAddress, iStatus);
    User::WaitForRequest(iStatus);
    resolver.Close();
    if (iStatus != KErrNone) {
        errorMsg = "DNS lookup failed";
        goto error;
    }

    // Set the socket server address/port
    address = hostAddress().iAddr;
    address.SetPort(port);

    // --- Connect to host ---
    LOG.debug("connect...");
    iSocket.Connect(address, iStatus);
    User::WaitForRequest(iStatus);
    if (iStatus != KErrNone) {
        errorMsg = "Failed to connect to Server";
        goto error;
    }

    return;

error:
    LOG.error(errorMsg.c_str());    // msgBox?
    iSocketSession.Close();
    return;
}

FSocket::FSocket()
{
    iStatus = 0;
}

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

int32_t FSocket::writeBuffer(const int8_t* const buffer, int32_t len)
{
    // This doesn't copy the buffer in memory.
    TPtr8 data((TUint8*)buffer, len);

    // Sends data to the remote host.
    iSocket.Write(data, iStatus);
    User::WaitForRequest(iStatus);

    if (iStatus == KErrNone) {
        return len;
    }
    else {
        LOG.error("FSocket: error writing on socket (status = %d)", iStatus.Int());
        return -1;
    }
}

int32_t FSocket::readBuffer(int8_t* buffer, int32_t maxLen)
{
    RBuf8 data;
    data.CreateL(maxLen);

    // Receives data from a remote host and completes when data is available.
    do {
        TSockXfrLength len;
        iSocket.RecvOneOrMore(data, 0, iStatus, len);
        User::WaitForRequest(iStatus);
        LOG.debug("received %d bytes...", data.Length());
    } while (iStatus == KErrNone);
    //
    // TODO: status error codes?
    //

    if (iStatus == KErrNone) {
        const char* ret = buf8ToNewChar(data);
        buffer = (int8_t*)ret;
        return data.Length();
    }
    else {
        LOG.error("FSocket: error reading on socket (status = %d)", iStatus.Int());
        buffer = NULL;
        return -1;
    }
}

void FSocket::close()
{
    LOG.debug("FSocket::close");
    //iSocket.CancelAll();
    iSocket.Close();
    iSocketSession.Close();
}

const StringBuffer& FSocket::address() const {
    return lAddress;
}

const StringBuffer& FSocket::peerAddress() const {
    return pAddress;
}

const StringBuffer& FSocket::localIP() {
    return lIP;
}

void FSocket::startConnection()
{
    RConnection connection;
    RSocketServ socketServ;
    User::LeaveIfError(socketServ.Connect());

    // Use the default IAP without prompting the user
    TUint32 UidAP=0;
    TCommDbConnPref prefs;
    prefs.SetDialogPreference (ECommDbDialogPrefDoNotPrompt);
    prefs.SetDirection (ECommDbConnectionDirectionUnknown);
    prefs.SetIapId (UidAP);

    User::LeaveIfError (connection.Open (socketServ, KAfInet));
    User::LeaveIfError (connection.Start (prefs));

    // use this to search for a particular IAP to use
    // withouth prompting the user
#if defined(PREDEFINED_IAP)
    CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
    CleanupStack::PushL(commDb);
    CApSelect* select = CApSelect::NewLC(*commDb,KEApIspTypeAll,EApBearerTypeAll,KEApSortUidAscending);
    TBuf<256> accessPoint;
    TInt UidAP= 0;
    TBool ok = select->MoveToFirst();
    for (TInt32 i = 0; ok&&(i<select->Count()); i++)
        {
        if ( select->Name ()==_L(PREDEFINED_IAP))
            {
            UidAP = select->Uid ();
            TCommDbConnPref prefs;
            prefs.SetDialogPreference (ECommDbDialogPrefDoNotPrompt);
            prefs.SetDirection (ECommDbConnectionDirectionUnknown);
            prefs.SetIapId (UidAP);

            User::LeaveIfError (iConnection.Open (iSocketSession, KAfInet));
            User::LeaveIfError (iConnection.Start (prefs));

            }
        else
            {
            ok = select->MoveNext ();
            }
        }
#else
    // use this if you want prompt user for IAP
    TCommDbConnPref pref;
    pref.SetDirection(ECommDbConnectionDirectionUnknown);

    connection.Open(socketServ, KAfInet);
    connection.Start(pref);
#endif

    socketServ.Close();
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAntiAliasBinaryImageFilter.txx"
#include "itkBalloonForce3DFilter.txx"
#include "itkBalloonForceFilter.txx"
#include "itkBinaryMask3DMeshSource.txx"
#include "itkBinaryMinMaxCurvatureFlowFunction.txx"
#include "itkBinaryMinMaxCurvatureFlowImageFilter.txx"
#include "itkClassifierBase.txx"
#include "itkConnectedRegionsMeshFilter.txx"
#include "itkCurvatureFlowFunction.txx"
#include "itkCurvatureFlowImageFilter.txx"
#include "itkDeformableMesh3DFilter.txx"
#include "itkDeformableMeshFilter.txx"
#include "itkDemonsRegistrationFilter.txx"
#include "itkDemonsRegistrationFunction.txx"
#include "itkExtensionVelocitiesImageFilter.txx"
#include "itkFEMRegistrationFilter.txx"
#include "itkFastMarchingExtensionImageFilter.txx"
#include "itkFastMarchingImageFilter.txx"
//#include "itkFEMRegistrationFilter.txx"
#include "itkGeodesicActiveContourImageFilter.txx"
#include "itkGibbsPriorFilter.txx"
#include "itkGradientVectorFlowImageFilter.txx"
#include "itkHistogramMatchingImageFilter.txx"
#include "itkHybridFilter.txx"
#include "itkImageClassifierBase.txx"
#include "itkImageGaussianModelEstimator.txx"
#include "itkImageKmeansModelEstimator.txx"
#include "itkImageModelEstimatorBase.txx"
#include "itkImageMomentsCalculator.txx"
#include "itkImageRegistrationMethod.txx"
#include "itkImageToImageMetric.txx"
#include "itkKLMRegionGrowImageFilter.txx"
#include "itkKalmanLinearEstimator.h"
#include "itkLaplacianSegmentationLevelSetFunction.txx"
#include "itkLaplacianSegmentationLevelSetImageFilter.txx"
#include "itkLevelSetImageFilter.txx"
#include "itkLevelSetNeighborhoodExtractor.txx"
#include "itkLevelSetVelocityNeighborhoodExtractor.txx"
#include "itkMRASlabIdentifier.txx"
#include "itkMRFImageFilter.txx"
#include "itkMRIBiasFieldCorrectionFilter.txx"
#include "itkMeanSquaresImageToImageMetric.txx"
#include "itkMeanSquaresPointSetToImageMetric.txx"
#include "itkMinMaxCurvatureFlowFunction.txx"
#include "itkMinMaxCurvatureFlowImageFilter.txx"
#include "itkMultiResolutionImageRegistrationMethod.txx"
#include "itkMultiResolutionPDEDeformableRegistration.txx"
#include "itkMultiResolutionPyramidImageFilter.txx"
#include "itkMutualInformationImageToImageMetric.txx"
#include "itkNormalizedCorrelationImageToImageMetric.txx"
#include "itkNormalizedCorrelationPointSetToImageMetric.txx"
#include "itkOtsuThresholdImageCalculator.txx"
#include "itkPDEDeformableRegistrationFilter.txx"
#include "itkPDEDeformableRegistrationFunction.h"
#include "itkPatternIntensityImageToImageMetric.txx"
#include "itkPatternIntensityPointSetToImageMetric.txx"
#include "itkRGBGibbsPriorFilter.txx"
#include "itkRecursiveMultiResolutionPyramidImageFilter.txx"
#include "itkRegionGrowImageFilter.txx"
#include "itkRegistrationMethod.txx"
#include "itkReinitializeLevelSetImageFilter.txx"
#include "itkSegmentationLevelSetImageFilter.txx"
#include "itkShapeDetectionLevelSetFilter.txx"
#include "itkSimpleFuzzyConnectednessImageFilterBase.txx"
#include "itkSimpleFuzzyConnectednessRGBImageFilter.txx"
#include "itkSimpleFuzzyConnectednessScalarImageFilter.txx"
#include "itkSphereMeshSource.txx"
#include "itkSphereSource.txx"
#include "itkThresholdSegmentationLevelSetFunction.txx"
#include "itkThresholdSegmentationLevelSetImageFilter.txx"
#include "itkVectorFuzzyConnectednessImageFilter.txx"
#include "itkVoronoiDiagram2D.txx"
#include "itkVoronoiDiagram2DGenerator.txx"
#include "itkVoronoiSegmentationImageFilter.txx"
#include "itkVoronoiSegmentationImageFilterBase.txx"
#include "itkVoronoiSegmentationRGBImageFilter.txx"
#include "itkWatershedBoundary.txx"
#include "itkWatershedBoundaryResolver.txx"
#include "itkWatershedEquivalenceRelabeler.txx"
#include "itkWatershedEquivalencyTable.txx"
#include "itkWatershedImageFilter.txx"
#include "itkWatershedMiniPipelineProgressCommand.h"
#include "itkWatershedOneWayEquivalencyTable.txx"
#include "itkWatershedRelabeler.txx"
#include "itkWatershedSegmentTable.txx"
#include "itkWatershedSegmentTree.txx"
#include "itkWatershedSegmentTreeGenerator.txx"
#include "itkWatershedSegmenter.txx"

int main ( int argc, char* argv )
{

  return 0;
}

<commit_msg>ENH: Updated to latest headers<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAntiAliasBinaryImageFilter.txx"
#include "itkBalloonForce3DFilter.txx"
#include "itkBalloonForceFilter.txx"
#include "itkBinaryMask3DMeshSource.txx"
#include "itkBinaryMinMaxCurvatureFlowFunction.txx"
#include "itkBinaryMinMaxCurvatureFlowImageFilter.txx"
#include "itkClassifierBase.txx"
#include "itkConnectedRegionsMeshFilter.txx"
#include "itkCurvatureFlowFunction.txx"
#include "itkCurvatureFlowImageFilter.txx"
#include "itkDeformableMesh3DFilter.txx"
#include "itkDeformableMeshFilter.txx"
#include "itkDemonsRegistrationFilter.txx"
#include "itkDemonsRegistrationFunction.txx"
#include "itkExtensionVelocitiesImageFilter.txx"
#include "itkFEMRegistrationFilter.txx"
#include "itkFastMarchingExtensionImageFilter.txx"
#include "itkFastMarchingImageFilter.txx"
#include "itkGeodesicActiveContourImageFilter.txx"
#include "itkGibbsPriorFilter.txx"
#include "itkGradientVectorFlowImageFilter.txx"
#include "itkHistogramMatchingImageFilter.txx"
#include "itkHybridFilter.txx"
#include "itkImageClassifierBase.txx"
#include "itkImageGaussianModelEstimator.txx"
#include "itkImageKmeansModelEstimator.txx"
#include "itkImageModelEstimatorBase.txx"
#include "itkImageMomentsCalculator.txx"
#include "itkImageRegistrationMethod.txx"
#include "itkImageToImageMetric.txx"
#include "itkKLMRegionGrowImageFilter.txx"
#include "itkKalmanLinearEstimator.h"
#include "itkLaplacianSegmentationLevelSetFunction.txx"
#include "itkLaplacianSegmentationLevelSetImageFilter.txx"
#include "itkLevelSetImageFilter.txx"
#include "itkLevelSetNeighborhoodExtractor.txx"
#include "itkLevelSetVelocityNeighborhoodExtractor.txx"
#include "itkMRASlabIdentifier.txx"
#include "itkMRFImageFilter.txx"
#include "itkMRIBiasFieldCorrectionFilter.txx"
#include "itkMeanSquaresImageToImageMetric.txx"
#include "itkMeanSquaresPointSetToImageMetric.txx"
#include "itkMinMaxCurvatureFlowFunction.txx"
#include "itkMinMaxCurvatureFlowImageFilter.txx"
#include "itkMultiResolutionImageRegistrationMethod.txx"
#include "itkMultiResolutionPDEDeformableRegistration.txx"
#include "itkMultiResolutionPyramidImageFilter.txx"
#include "itkMutualInformationImageToImageMetric.txx"
#include "itkNormalizedCorrelationImageToImageMetric.txx"
#include "itkNormalizedCorrelationPointSetToImageMetric.txx"
#include "itkOtsuThresholdImageCalculator.txx"
#include "itkPDEDeformableRegistrationFilter.txx"
#include "itkPDEDeformableRegistrationFunction.h"
#include "itkPatternIntensityImageToImageMetric.txx"
#include "itkPatternIntensityPointSetToImageMetric.txx"
#include "itkRGBGibbsPriorFilter.txx"
#include "itkRecursiveMultiResolutionPyramidImageFilter.txx"
#include "itkRegionGrowImageFilter.txx"
#include "itkRegistrationMethod.txx"
#include "itkReinitializeLevelSetImageFilter.txx"
#include "itkSegmentationLevelSetImageFilter.txx"
#include "itkShapeDetectionLevelSetFilter.txx"
#include "itkSimpleFuzzyConnectednessImageFilterBase.txx"
#include "itkSimpleFuzzyConnectednessRGBImageFilter.txx"
#include "itkSimpleFuzzyConnectednessScalarImageFilter.txx"
#include "itkSphereMeshSource.txx"
#include "itkSphereSource.txx"
#include "itkThresholdSegmentationLevelSetFunction.txx"
#include "itkThresholdSegmentationLevelSetImageFilter.txx"
#include "itkVectorFuzzyConnectednessImageFilter.txx"
#include "itkVoronoiDiagram2D.txx"
#include "itkVoronoiDiagram2DGenerator.txx"
#include "itkVoronoiSegmentationImageFilter.txx"
#include "itkVoronoiSegmentationImageFilterBase.txx"
#include "itkVoronoiSegmentationRGBImageFilter.txx"
#include "itkWatershedBoundary.txx"
#include "itkWatershedBoundaryResolver.txx"
#include "itkWatershedEquivalenceRelabeler.txx"
#include "itkWatershedEquivalencyTable.txx"
#include "itkWatershedImageFilter.txx"
#include "itkWatershedMiniPipelineProgressCommand.h"
#include "itkWatershedOneWayEquivalencyTable.txx"
#include "itkWatershedRelabeler.txx"
#include "itkWatershedSegmentTable.txx"
#include "itkWatershedSegmentTree.txx"
#include "itkWatershedSegmentTreeGenerator.txx"
#include "itkWatershedSegmenter.txx"

int main ( int argc, char* argv )
{

  return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkGeometricalQuadEdgeTest1.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkGeometricalQuadEdge.h"
#include <iostream>

class itkGeometricalQuadEdgeTest1Helper
{
public:
  typedef unsigned int PointIdentifier;
  typedef unsigned int FaceIdentifier;
  typedef float        PointData;
  typedef std::string  FaceData;

  typedef itk::GeometricalQuadEdge<
     PointIdentifier, FaceIdentifier,
     PointData, FaceData, true >        PrimalQuadEdgeType;

  typedef itk::GeometricalQuadEdge<
     PointIdentifier, FaceIdentifier,
     PointData, FaceData, false >       DualQuadEdgeType;

  static PrimalQuadEdgeType * MakeQuadEdges()
  {
    PrimalQuadEdgeType * e1 = new PrimalQuadEdgeType();
    DualQuadEdgeType   * e2 = new DualQuadEdgeType();
    PrimalQuadEdgeType * e3 = new PrimalQuadEdgeType();
    DualQuadEdgeType   * e4 = new DualQuadEdgeType();

    e1->SetRot( e2 );
    e2->SetRot( e3 );
    e3->SetRot( e4 );
    e4->SetRot( e1 );

    e1->SetOnext( e1 );
    e2->SetOnext( e4 );
    e3->SetOnext( e3 );
    e4->SetOnext( e4 );

    return e1;
  }
};

int itkGeometricalQuadEdgeTest1( int , char* [] )
{

  typedef itkGeometricalQuadEdgeTest1Helper  HelperType;

  typedef HelperType::PrimalQuadEdgeType     PrimalQuadEdgeType;
  typedef HelperType::DualQuadEdgeType       DualQuadEdgeType;

  { // Define a local scope for testing constructors

  DualQuadEdgeType     dummyQuadEdge1;  // test constructor
  PrimalQuadEdgeType   dummyQuadEdge2;  // test constructor

  dummyQuadEdge1.SetRot( &dummyQuadEdge2 );  // Test SetRot()
  }

  PrimalQuadEdgeType * e1 = HelperType::MakeQuadEdges();

  return EXIT_SUCCESS;
}

<commit_msg>ENH: Replacing typedef for the DualType trying to solve link problem in the SGIs.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkGeometricalQuadEdgeTest1.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkGeometricalQuadEdge.h"
#include <iostream>

class itkGeometricalQuadEdgeTest1Helper
{
public:
  typedef unsigned int PointIdentifier;
  typedef unsigned int FaceIdentifier;
  typedef float        PointData;
  typedef std::string  FaceData;

  typedef itk::GeometricalQuadEdge<
     PointIdentifier, FaceIdentifier,
     PointData, FaceData, true >        PrimalQuadEdgeType;

  typedef PrimalQuadEdgeType::DualType  DualQuadEdgeType;

  static PrimalQuadEdgeType * MakeQuadEdges()
  {
    PrimalQuadEdgeType * e1 = new PrimalQuadEdgeType();
    DualQuadEdgeType   * e2 = new DualQuadEdgeType();
    PrimalQuadEdgeType * e3 = new PrimalQuadEdgeType();
    DualQuadEdgeType   * e4 = new DualQuadEdgeType();

    e1->SetRot( e2 );
    e2->SetRot( e3 );
    e3->SetRot( e4 );
    e4->SetRot( e1 );

    e1->SetOnext( e1 );
    e2->SetOnext( e4 );
    e3->SetOnext( e3 );
    e4->SetOnext( e4 );

    return e1;
  }
};

int itkGeometricalQuadEdgeTest1( int , char* [] )
{

  typedef itkGeometricalQuadEdgeTest1Helper  HelperType;

  typedef HelperType::PrimalQuadEdgeType     PrimalQuadEdgeType;
  typedef HelperType::DualQuadEdgeType       DualQuadEdgeType;

  { // Define a local scope for testing constructors

  DualQuadEdgeType     dummyQuadEdge1;  // test constructor
  PrimalQuadEdgeType   dummyQuadEdge2;  // test constructor

  dummyQuadEdge1.SetRot( &dummyQuadEdge2 );  // Test SetRot()
  }

  PrimalQuadEdgeType * e1 = HelperType::MakeQuadEdges();

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include <iostream>

int main() {
  std::cout << "Hello world!" << std::endl;
  return 0; // 不返回的话也不会报错，那么加上这个返回值的原因是？
}
<commit_msg>main函数返回值，对程序运行的影响<commit_after>#include <iostream>

int main() {
  std::cout << "Hello world!" << std::endl;
  return 0; // 不返回的话也不会报错
//  return -1; // 甚至返回-1运行的时候也没有任何区别，那么加上这个返回值的原因是？
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007 Apple 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 Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
 */

#include "WebKitInitializer.h"

// Needed to get SetDllDirectory
#define _WIN32_WINNT 0x0502

#include <shlwapi.h>
#include <tchar.h>
#include <windows.h>

static TCHAR* getStringValue(HKEY key, LPCTSTR valueName)
{
    DWORD type = 0;
    DWORD bufferSize = 0;
    if (RegQueryValueEx(key, valueName, 0, &type, 0, &bufferSize) != ERROR_SUCCESS || type != REG_SZ)
        return 0;

    TCHAR* buffer = new TCHAR[bufferSize / sizeof(TCHAR)];
    if (RegQueryValueEx(key, 0, 0, &type, reinterpret_cast<LPBYTE>(buffer), &bufferSize) != ERROR_SUCCESS) {
        delete [] buffer;
        return 0;
    }

    return buffer;
}

static LPOLESTR getWebViewCLSID()
{
    // FIXME <rdar://5505062>: Once WebKit switches to truly version-independent
    // ProgIDs, this should just become "WebKit.WebView".
    LPCTSTR webViewProgID = TEXT("WebKit.WebView.3");

    CLSID clsid = CLSID_NULL;
    HRESULT hr = CLSIDFromProgID(webViewProgID, &clsid);
    if (FAILED(hr)) {
        _ftprintf(stderr, TEXT("Failed to get CLSID for %s\n"), webViewProgID);
        return 0;
    }

    LPOLESTR clsidString = 0;
    if (FAILED(StringFromCLSID(clsid, &clsidString))) {
        _ftprintf(stderr, TEXT("Failed to get string representation of CLSID for WebView\n"));
        return 0;
    }

    return clsidString;
}

static TCHAR* getInstalledWebKitDirectory()
{
    LPCTSTR keyPrefix = TEXT("SOFTWARE\\Classes\\CLSID\\");
    LPCTSTR keySuffix = TEXT("\\InprocServer32");

    LPOLESTR clsid = getWebViewCLSID();
    if (!clsid)
        return 0;

    size_t keyBufferLength = _tcslen(keyPrefix) + _tcslen(clsid) + _tcslen(keySuffix) + 1;
    TCHAR* keyString = new TCHAR[keyBufferLength];

    int ret = _sntprintf_s(keyString, keyBufferLength, keyBufferLength - 1, TEXT("%s%s%s"), keyPrefix, clsid, keySuffix);
    CoTaskMemFree(clsid);
    if (ret == -1) {
        _ftprintf(stderr, TEXT("Failed to construct InprocServer32 key\n"));
        return 0;
    }

    HKEY serverKey = 0;
    LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyString, 0, KEY_READ, &serverKey);
    delete [] keyString;
    if (error != ERROR_SUCCESS) {
        _ftprintf(stderr, TEXT("Failed to open registry key %s\n"), keyString);
        return 0;
    }

    TCHAR* webKitPath = getStringValue(serverKey, 0);
    RegCloseKey(serverKey);
    if (!webKitPath) {
        _ftprintf(stderr, TEXT("Couldn't retrieve value for registry key %s\n"), keyString);
        return 0;
    }

    TCHAR* startOfFileName = PathFindFileName(webKitPath);
    if (startOfFileName == webKitPath) {
        _ftprintf(stderr, TEXT("Couldn't find filename from path %s\n"), webKitPath);
        delete [] webKitPath;
        return 0;
    }

    *startOfFileName = '\0';
    return webKitPath;
}

bool initializeWebKit()
{
    static bool haveInitialized;
    static bool success;
    if (haveInitialized)
        return success;
    haveInitialized = true;

#ifdef NDEBUG
    LPCTSTR webKitDLL = TEXT("WebKit.dll");
#else
    LPCTSTR webKitDLL = TEXT("WebKit_debug.dll");
#endif

    HMODULE webKitModule = LoadLibrary(webKitDLL);
    if (!webKitModule) {
        _ftprintf(stderr, TEXT("LoadLibrary(%s) failed\n"), webKitDLL);
        return false;
    }

    FARPROC dllRegisterServer = GetProcAddress(webKitModule, "DllRegisterServer");
    if (!dllRegisterServer) {
        _ftprintf(stderr, TEXT("GetProcAddress(webKitModule, \"DllRegisterServer\") failed\n"));
        return false;
    }

    dllRegisterServer();

    TCHAR* directory = getInstalledWebKitDirectory();
    if (!directory) {
        _ftprintf(stderr, TEXT("Couldn't determine installed WebKit directory\n"));
        return false;
    }

    SetDllDirectory(directory);
    delete [] directory;

    success = true;
    return success;
}
<commit_msg>Touch it again so it rebuilds<commit_after>/*
 * Copyright (C) 2007 Apple 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 Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
 */

#include "WebKitInitializer.h"

// Needed to get SetDllDirectory
#define _WIN32_WINNT 0x0502

#include <shlwapi.h>
#include <tchar.h>
#include <windows.h>

static TCHAR* getStringValue(HKEY key, LPCTSTR valueName)
{
    DWORD type = 0;
    DWORD bufferSize = 0;
    if (RegQueryValueEx(key, valueName, 0, &type, 0, &bufferSize) != ERROR_SUCCESS || type != REG_SZ)
        return 0;

    TCHAR* buffer = new TCHAR[bufferSize / sizeof(TCHAR)];
    if (RegQueryValueEx(key, 0, 0, &type, reinterpret_cast<LPBYTE>(buffer), &bufferSize) != ERROR_SUCCESS) {
        delete [] buffer;
        return 0;
    }

    return buffer;
}

static LPOLESTR getWebViewCLSID()
{
    // FIXME <rdar://5505062>: Once WebKit switches to truly version-independent
    // ProgIDs, this should just become "WebKit.WebView".
    LPCTSTR webViewProgID = TEXT("WebKit.WebView.3");

    CLSID clsid = CLSID_NULL;
    HRESULT hr = CLSIDFromProgID(webViewProgID, &clsid);
    if (FAILED(hr)) {
        _ftprintf(stderr, TEXT("Failed to get CLSID for %s\n"), webViewProgID);
        return 0;
    }

    LPOLESTR clsidString = 0;
    if (FAILED(StringFromCLSID(clsid, &clsidString))) {
        _ftprintf(stderr, TEXT("Failed to get string representation of CLSID for WebView\n"));
        return 0;
    }

    return clsidString;
}

static TCHAR* getInstalledWebKitDirectory()
{
    LPCTSTR keyPrefix = TEXT("SOFTWARE\\Classes\\CLSID\\");
    LPCTSTR keySuffix = TEXT("\\InprocServer32");

    LPOLESTR clsid = getWebViewCLSID();
    if (!clsid)
        return 0;

    size_t keyBufferLength = _tcslen(keyPrefix) + _tcslen(clsid) + _tcslen(keySuffix) + 1;
    TCHAR* keyString = new TCHAR[keyBufferLength];

    int ret = _sntprintf_s(keyString, keyBufferLength, keyBufferLength - 1, TEXT("%s%s%s"), keyPrefix, clsid, keySuffix);
    CoTaskMemFree(clsid);
    if (ret == -1) {
        _ftprintf(stderr, TEXT("Failed to construct InprocServer32 key\n"));
        return 0;
    }

    HKEY serverKey = 0;
    LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyString, 0, KEY_READ, &serverKey);
    delete [] keyString;
    if (error != ERROR_SUCCESS) {
        _ftprintf(stderr, TEXT("Failed to open registry key %s\n"), keyString);
        return 0;
    }

    TCHAR* webKitPath = getStringValue(serverKey, 0);
    RegCloseKey(serverKey);
    if (!webKitPath) {
        _ftprintf(stderr, TEXT("Couldn't retrieve value for registry key %s\n"), keyString);
        return 0;
    }

    TCHAR* startOfFileName = PathFindFileName(webKitPath);
    if (startOfFileName == webKitPath) {
        _ftprintf(stderr, TEXT("Couldn't find filename from path %s\n"), webKitPath);
        delete [] webKitPath;
        return 0;
    }

    *startOfFileName = '\0';
    return webKitPath;
}

bool initializeWebKit()
{
    static bool haveInitialized;
    static bool success;
    if (haveInitialized)
        return success;

    haveInitialized = true;

#ifdef NDEBUG
    LPCTSTR webKitDLL = TEXT("WebKit.dll");
#else
    LPCTSTR webKitDLL = TEXT("WebKit_debug.dll");
#endif

    HMODULE webKitModule = LoadLibrary(webKitDLL);
    if (!webKitModule) {
        _ftprintf(stderr, TEXT("LoadLibrary(%s) failed\n"), webKitDLL);
        return false;
    }

    FARPROC dllRegisterServer = GetProcAddress(webKitModule, "DllRegisterServer");
    if (!dllRegisterServer) {
        _ftprintf(stderr, TEXT("GetProcAddress(webKitModule, \"DllRegisterServer\") failed\n"));
        return false;
    }

    dllRegisterServer();

    TCHAR* directory = getInstalledWebKitDirectory();
    if (!directory) {
        _ftprintf(stderr, TEXT("Couldn't determine installed WebKit directory\n"));
        return false;
    }

    SetDllDirectory(directory);
    delete [] directory;

    success = true;
    return success;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2019.  All rights reserved
 */
#include "Stroika/Foundation/StroikaPreComp.h"

#include "Stroika/Foundation/Characters/String.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Containers/Collection.h"
#include "Stroika/Foundation/Containers/SortedCollection.h"
#include "Stroika/Foundation/Debug/Trace.h"

// Not generally included, but you can include these if you want to select a particular backend implementation
#include "Stroika/Foundation/Containers/Concrete/Collection_Array.h"
#include "Stroika/Foundation/Containers/Concrete/Collection_LinkedList.h"
#include "Stroika/Foundation/Containers/Concrete/Collection_stdforward_list.h"

#include "Stroika/Foundation/Debug/Assertions.h"

#include "Collection.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Containers;

using Characters::CompareOptions;

namespace {
    void SimplestCollectionTest_ ()
    {
        /*
         *  A Collection is the simplest form of Stroika container. You can add things, and remove them, and iterate over them.
         *  View the class declaration, with all the methods well documented, must with examples of usage.
         */
        Collection<int> c;
        c.Add (3);
        c += 13;
        for ([[maybe_unused]] int i : c) {
            Lambda_Arg_Unused_BWA (i); // warning C4189: 'i': local variable is initialized but not referenced
            Assert (i == 3 or i == 13);
        }
        Assert (c.size () == 2);
    }
}

namespace {
    void UseParticularConcreteRepresentation_ ()
    {
        {
            Collection<int> c{3, 5, 19, 3040, 34, 1, 33, 33, 4, 19};

            // Unclear what the performance characteristics of this will be - with a linked list - O(1), but with array, O(N) worst case.
            c += 4;

            // 'c' will now operate identically (same API) - but use a differnt backend datastructure for storage,
            // always showing O(1) worst case addition time
            c = Concrete::Collection_stdforward_list<int>{c};
            c += 4;
        }
        {
            using Characters::String;
            Collection<String> fruits;
            fruits += L"apple";
            fruits += L"bananas";
            fruits += L"cherries";
            fruits += L"APPLE";
            // Print (to debugger/tracelog) the fruits - but now they could come out in any order
            DbgTrace (L"fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.size () == 4); // they are all there

            // Like changing the backend. But this still respects all the rules of a Collection (no order specified) -
            // except now it will happen to be ordered (using the default compare function)
            fruits = SortedCollection<String>{fruits};
            DbgTrace (L"sorted fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.size () == 4); // only one apple or the other (case squished)
            // note they must now be in alphabetic order
            Assert (fruits.SequenceEquals (initializer_list<String>{L"APPLE", L"apple", L"bananas", L"cherries"}));

            // But, we can do the same thing with a compare function that sorts case insensitively
            fruits = SortedCollection<String>{String::LessComparer{CompareOptions::eCaseInsensitive}, fruits};
            DbgTrace (L"sorted case insensitve fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.SequenceEquals (initializer_list<String>{L"apple", L"APPLE", L"bananas", L"cherries"}) or
                    fruits.SequenceEquals (initializer_list<String>{L"APPLE", L"apple", L"bananas", L"cherries"}));
        }
    }
}

namespace {
    void InterfaceWithSTLContainers_ ()
    {
        vector<int>     aVector{1, 3, 5, 7, 9, 11};
        Collection<int> c{aVector};

        // CANNOT guarantee the ordering is the same, as Collection guarantees it keeps all the same elements,
        // but does not guarantee maintaining order.
        Assert (c.SetEquals (aVector));
        Assert (c.SequnceEquals (aVector) or not c.SequnceEquals (aVector));

        vector<int> v2 = c.As<vector<int>> ();
        // V will contain all the same elements as aVector, but maybe not in the same order.
        // it will be in the order the 'c' collection happened to produce
    }
}

namespace {
    void PrintTheContentsOfAContainerToTheTraceLog_ ()
    {
        /*
         *  Use DbgTrace and Characters::ToString () to echo objects to a tracelog file (and/or debugger output under windows)
         */
        Debug::TraceContextBumper ctx{L"PrintTheContentsOfAContainerToTheTraceLog_"};
        Collection<int>           tmp{1, 3, 5, 7, 9};
        DbgTrace (L"tmp=%s", Characters::ToString (tmp).c_str ());
    }
}

namespace {
    void StoreOtherSortsOfElements_ ()
    {
        Debug::TraceContextBumper ctx{L"StoreOtherSortsOfElements_"};
        using Characters::String;
        Collection<String> fruits;
        fruits += L"apple";
        fruits += L"bananas";
        fruits += L"cherries";
        DbgTrace (L"fruits=%s", Characters::ToString (fruits).c_str ());
    }
}

namespace {
    void UseLinqLikeFunctionalAPIs_ ()
    {
        Debug::TraceContextBumper ctx{L"PrintTheContentsOfAContainerToTheTraceLog_"};
        /*
         *  See the Iterable<> template in Iterable.h - for a ton more of this functional style linq-like operations
         *  you can do on any Stroika container.
         */
        {
            Collection<int> tmp{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
            auto            whereTestResult = tmp.Where ([] (int i) { return i % 2 == 1; });
            DbgTrace (L"tmp=%s", Characters::ToString (whereTestResult).c_str ());
        }
        {
            Collection<int> tmp{1, 2, 3, 4, 5, 1, 2, 3, 4, 5};
            auto            d = tmp.Distinct ();
            DbgTrace (L"d=%s", Characters::ToString (d).c_str ());
            Assert (d.SetEquals (initializer_list<int>{1, 2, 3, 4, 5}));
        }
        {
            using Characters::String;
            Collection<String> fruits;
            fruits += L"apple";
            fruits += L"APPLE";
            fruits += L"bananas";
            fruits += L"cherries";
            DbgTrace (L"fruits=%s", Characters::ToString (fruits.Distinct (String::EqualsComparer{CompareOptions::eCaseInsensitive})).c_str ());
            Assert (fruits.Distinct (String::EqualsComparer{CompareOptions::eCaseInsensitive}).size () == 3); // only one apple or the other (case squished)
        }
    }
}

namespace {
    void CollectionOfThingsWithNoOpEqualsAndNotDefaultConstructibleEtc_ ()
    {
        struct MyFunnyObject_ {
            MyFunnyObject_ () = delete; // no need to be default constructible
            MyFunnyObject_ (int /*n*/)
            {
                // need some constructor to test
            }
            MyFunnyObject_ (const MyFunnyObject_&) = default; // OK, but you do need to be copyable
        };
        Collection<MyFunnyObject_> myObjects;
        myObjects.Add (MyFunnyObject_{3});
        myObjects += MyFunnyObject_{4}; // use whatever add syntax you want

        // THIS WONT WORK, because no operator== defined
        //      myObjects.Remove (MyFunnyObject_{3});
        // but this will remove the first object found
        Assert (myObjects.size () == 2);
        myObjects.Remove (MyFunnyObject_{3}, [] (const MyFunnyObject_&, const MyFunnyObject_&) { return true; });
        Assert (myObjects.size () == 1);
    }
}

namespace {
    void IteratorsAndSafeUpdateIteration_ ()
    {
        using Characters::String;
        Collection<String> fruits;
        fruits += L"apple";
        fruits += L"APPLE";
        fruits += L"bananas";
        fruits += L"cherries";

        {
            Iterator<String> i = fruits.FindFirstThat ([] (String i) { return i == L"apple"; });
            Assert (i != fruits.end ());
            Assert (fruits.size () == 4);
        }
        for (Iterator<String> i = fruits.begin (); i != fruits.end (); ++i) {
            if (String::EqualsComparer{CompareOptions::eCaseInsensitive}(*i, L"apple")) {
                fruits.Remove (i);
                // with STL containers, it would be illegal to reference i again, as in i++.
                // However, with Stroika iterators, they are smart about doing the right thing,
                // when they point to a deleted item, and this code will work as expected.
            }
        }
        Assert (fruits.size () == 2);
    }
}

void Samples::Containers::Collection::RunDemo ()
{
    SimplestCollectionTest_ ();
    UseParticularConcreteRepresentation_ ();
    InterfaceWithSTLContainers_ ();
    PrintTheContentsOfAContainerToTheTraceLog_ ();
    StoreOtherSortsOfElements_ ();
    UseLinqLikeFunctionalAPIs_ ();
    CollectionOfThingsWithNoOpEqualsAndNotDefaultConstructibleEtc_ ();
    IteratorsAndSafeUpdateIteration_ ();
}
<commit_msg>react to name change<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2019.  All rights reserved
 */
#include "Stroika/Foundation/StroikaPreComp.h"

#include "Stroika/Foundation/Characters/String.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Containers/Collection.h"
#include "Stroika/Foundation/Containers/SortedCollection.h"
#include "Stroika/Foundation/Debug/Trace.h"

// Not generally included, but you can include these if you want to select a particular backend implementation
#include "Stroika/Foundation/Containers/Concrete/Collection_Array.h"
#include "Stroika/Foundation/Containers/Concrete/Collection_LinkedList.h"
#include "Stroika/Foundation/Containers/Concrete/Collection_stdforward_list.h"

#include "Stroika/Foundation/Debug/Assertions.h"

#include "Collection.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Containers;

using Characters::CompareOptions;

namespace {
    void SimplestCollectionTest_ ()
    {
        /*
         *  A Collection is the simplest form of Stroika container. You can add things, and remove them, and iterate over them.
         *  View the class declaration, with all the methods well documented, must with examples of usage.
         */
        Collection<int> c;
        c.Add (3);
        c += 13;
        for ([[maybe_unused]] int i : c) {
            Lambda_Arg_Unused_BWA (i); // warning C4189: 'i': local variable is initialized but not referenced
            Assert (i == 3 or i == 13);
        }
        Assert (c.size () == 2);
    }
}

namespace {
    void UseParticularConcreteRepresentation_ ()
    {
        {
            Collection<int> c{3, 5, 19, 3040, 34, 1, 33, 33, 4, 19};

            // Unclear what the performance characteristics of this will be - with a linked list - O(1), but with array, O(N) worst case.
            c += 4;

            // 'c' will now operate identically (same API) - but use a differnt backend datastructure for storage,
            // always showing O(1) worst case addition time
            c = Concrete::Collection_stdforward_list<int>{c};
            c += 4;
        }
        {
            using Characters::String;
            Collection<String> fruits;
            fruits += L"apple";
            fruits += L"bananas";
            fruits += L"cherries";
            fruits += L"APPLE";
            // Print (to debugger/tracelog) the fruits - but now they could come out in any order
            DbgTrace (L"fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.size () == 4); // they are all there

            // Like changing the backend. But this still respects all the rules of a Collection (no order specified) -
            // except now it will happen to be ordered (using the default compare function)
            fruits = SortedCollection<String>{fruits};
            DbgTrace (L"sorted fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.size () == 4); // only one apple or the other (case squished)
            // note they must now be in alphabetic order
            Assert (fruits.SequenceEquals (initializer_list<String>{L"APPLE", L"apple", L"bananas", L"cherries"}));

            // But, we can do the same thing with a compare function that sorts case insensitively
            fruits = SortedCollection<String>{String::LessComparer{CompareOptions::eCaseInsensitive}, fruits};
            DbgTrace (L"sorted case insensitve fruits=%s", Characters::ToString (fruits).c_str ());
            Assert (fruits.SequenceEquals (initializer_list<String>{L"apple", L"APPLE", L"bananas", L"cherries"}) or
                    fruits.SequenceEquals (initializer_list<String>{L"APPLE", L"apple", L"bananas", L"cherries"}));
        }
    }
}

namespace {
    void InterfaceWithSTLContainers_ ()
    {
        vector<int>     aVector{1, 3, 5, 7, 9, 11};
        Collection<int> c{aVector};

        // CANNOT guarantee the ordering is the same, as Collection guarantees it keeps all the same elements,
        // but does not guarantee maintaining order.
        Assert (c.SetEquals (aVector));
        Assert (c.SequenceEquals (aVector) or not c.SequenceEquals (aVector));

        vector<int> v2 = c.As<vector<int>> ();
        // V will contain all the same elements as aVector, but maybe not in the same order.
        // it will be in the order the 'c' collection happened to produce
    }
}

namespace {
    void PrintTheContentsOfAContainerToTheTraceLog_ ()
    {
        /*
         *  Use DbgTrace and Characters::ToString () to echo objects to a tracelog file (and/or debugger output under windows)
         */
        Debug::TraceContextBumper ctx{L"PrintTheContentsOfAContainerToTheTraceLog_"};
        Collection<int>           tmp{1, 3, 5, 7, 9};
        DbgTrace (L"tmp=%s", Characters::ToString (tmp).c_str ());
    }
}

namespace {
    void StoreOtherSortsOfElements_ ()
    {
        Debug::TraceContextBumper ctx{L"StoreOtherSortsOfElements_"};
        using Characters::String;
        Collection<String> fruits;
        fruits += L"apple";
        fruits += L"bananas";
        fruits += L"cherries";
        DbgTrace (L"fruits=%s", Characters::ToString (fruits).c_str ());
    }
}

namespace {
    void UseLinqLikeFunctionalAPIs_ ()
    {
        Debug::TraceContextBumper ctx{L"PrintTheContentsOfAContainerToTheTraceLog_"};
        /*
         *  See the Iterable<> template in Iterable.h - for a ton more of this functional style linq-like operations
         *  you can do on any Stroika container.
         */
        {
            Collection<int> tmp{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
            auto            whereTestResult = tmp.Where ([] (int i) { return i % 2 == 1; });
            DbgTrace (L"tmp=%s", Characters::ToString (whereTestResult).c_str ());
        }
        {
            Collection<int> tmp{1, 2, 3, 4, 5, 1, 2, 3, 4, 5};
            auto            d = tmp.Distinct ();
            DbgTrace (L"d=%s", Characters::ToString (d).c_str ());
            Assert (d.SetEquals (initializer_list<int>{1, 2, 3, 4, 5}));
        }
        {
            using Characters::String;
            Collection<String> fruits;
            fruits += L"apple";
            fruits += L"APPLE";
            fruits += L"bananas";
            fruits += L"cherries";
            DbgTrace (L"fruits=%s", Characters::ToString (fruits.Distinct (String::EqualsComparer{CompareOptions::eCaseInsensitive})).c_str ());
            Assert (fruits.Distinct (String::EqualsComparer{CompareOptions::eCaseInsensitive}).size () == 3); // only one apple or the other (case squished)
        }
    }
}

namespace {
    void CollectionOfThingsWithNoOpEqualsAndNotDefaultConstructibleEtc_ ()
    {
        struct MyFunnyObject_ {
            MyFunnyObject_ () = delete; // no need to be default constructible
            MyFunnyObject_ (int /*n*/)
            {
                // need some constructor to test
            }
            MyFunnyObject_ (const MyFunnyObject_&) = default; // OK, but you do need to be copyable
        };
        Collection<MyFunnyObject_> myObjects;
        myObjects.Add (MyFunnyObject_{3});
        myObjects += MyFunnyObject_{4}; // use whatever add syntax you want

        // THIS WONT WORK, because no operator== defined
        //      myObjects.Remove (MyFunnyObject_{3});
        // but this will remove the first object found
        Assert (myObjects.size () == 2);
        myObjects.Remove (MyFunnyObject_{3}, [] (const MyFunnyObject_&, const MyFunnyObject_&) { return true; });
        Assert (myObjects.size () == 1);
    }
}

namespace {
    void IteratorsAndSafeUpdateIteration_ ()
    {
        using Characters::String;
        Collection<String> fruits;
        fruits += L"apple";
        fruits += L"APPLE";
        fruits += L"bananas";
        fruits += L"cherries";

        {
            Iterator<String> i = fruits.FindFirstThat ([] (String i) { return i == L"apple"; });
            Assert (i != fruits.end ());
            Assert (fruits.size () == 4);
        }
        for (Iterator<String> i = fruits.begin (); i != fruits.end (); ++i) {
            if (String::EqualsComparer{CompareOptions::eCaseInsensitive}(*i, L"apple")) {
                fruits.Remove (i);
                // with STL containers, it would be illegal to reference i again, as in i++.
                // However, with Stroika iterators, they are smart about doing the right thing,
                // when they point to a deleted item, and this code will work as expected.
            }
        }
        Assert (fruits.size () == 2);
    }
}

void Samples::Containers::Collection::RunDemo ()
{
    SimplestCollectionTest_ ();
    UseParticularConcreteRepresentation_ ();
    InterfaceWithSTLContainers_ ();
    PrintTheContentsOfAContainerToTheTraceLog_ ();
    StoreOtherSortsOfElements_ ();
    UseLinqLikeFunctionalAPIs_ ();
    CollectionOfThingsWithNoOpEqualsAndNotDefaultConstructibleEtc_ ();
    IteratorsAndSafeUpdateIteration_ ();
}
<|endoftext|>


<commit_before>/**
 * @file lars_test.cpp
 *
 * Test for LARS
 */

// Note: We don't use BOOST_REQUIRE_CLOSE in the code below because we need
// to use FPC_WEAK, and it's not at all intuitive how to do that.

#include <armadillo>
#include <mlpack/methods/lars/lars.hpp>

#include <boost/test/unit_test.hpp>

using namespace mlpack;
using namespace mlpack::regression;

BOOST_AUTO_TEST_SUITE(LARSTest);

void GenerateProblem(arma::mat& X, arma::vec& y, size_t nPoints, size_t nDims)
{
  X = arma::randn(nPoints, nDims);
  arma::vec beta = arma::randn(nDims, 1);
  y = X * beta;
}

void VerifyCorrectness(arma::vec beta, arma::vec errCorr, double lambda)
{
  size_t nDims = beta.n_elem;
  const double tol = 1e-12;
  for(size_t j = 0; j < nDims; j++)
  {
    if (beta(j) == 0)
    {
      // make sure that errCorr(j) <= lambda
      BOOST_REQUIRE_SMALL(std::max(errCorr(j) - lambda, 0.0), tol);
    }
    else if (beta(j) < 0)
    {
      // make sure that errCorr(j) == lambda
      BOOST_REQUIRE_SMALL(errCorr(j) - lambda, tol);
    }
    else
    { // beta(j) > 0
      // make sure that errCorr(j) == -lambda
      BOOST_REQUIRE_SMALL(errCorr(j) + lambda, tol);
    }
  }
}

void LassoTest(size_t nPoints, size_t nDims, bool elasticNet, bool useCholesky)
{
  arma::mat X;
  arma::vec y;

  for(size_t i = 0; i < 100; i++)
  {
    GenerateProblem(X, y, nPoints, nDims);

    // Armadillo's median is broken, so...
    arma::vec sortedAbsCorr = sort(abs(trans(X) * y));
    double lambda1 = sortedAbsCorr(nDims/2);
    double lambda2;
    if (elasticNet)
      lambda2 = lambda1 / 2;
    else
      lambda2 = 0;

    LARS lars(useCholesky, lambda1, lambda2);
    lars.DoLARS(X, y);

    arma::vec betaOpt;
    lars.Solution(betaOpt);
    arma::vec errCorr = (arma::trans(X) * X + lambda2 *
        arma::eye(nDims, nDims)) * betaOpt - arma::trans(X) * y;

    VerifyCorrectness(betaOpt, errCorr, lambda1);
  }
}

BOOST_AUTO_TEST_CASE(LARSTestLassoCholesky)
{
  LassoTest(100, 10, true, false);
}

BOOST_AUTO_TEST_CASE(LARSTestLassoGram)
{
  LassoTest(100, 10, false, false);
}

BOOST_AUTO_TEST_CASE(LARSTestElasticNetCholesky)
{
  LassoTest(100, 10, true, true);
}

BOOST_AUTO_TEST_CASE(LARSTestElasticNetGram)
{
  LassoTest(100, 10, true, false);
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>fixed a bug in how we were checking the optimality conditions for the LASSO. holy shit, an error in the test case itself!<commit_after>/**
 * @file lars_test.cpp
 *
 * Test for LARS
 */

// Note: We don't use BOOST_REQUIRE_CLOSE in the code below because we need
// to use FPC_WEAK, and it's not at all intuitive how to do that.

#include <armadillo>
#include <mlpack/methods/lars/lars.hpp>

#include <boost/test/unit_test.hpp>

using namespace mlpack;
using namespace mlpack::regression;

BOOST_AUTO_TEST_SUITE(LARSTest);

void GenerateProblem(arma::mat& X, arma::vec& y, size_t nPoints, size_t nDims)
{
  X = arma::randn(nPoints, nDims);
  arma::vec beta = arma::randn(nDims, 1);
  y = X * beta;
}

void VerifyCorrectness(arma::vec beta, arma::vec errCorr, double lambda)
{
  size_t nDims = beta.n_elem;
  const double tol = 1e-12;
  for(size_t j = 0; j < nDims; j++)
  {
    if (beta(j) == 0)
    {
      // make sure that |errCorr(j)| <= lambda
      BOOST_REQUIRE_SMALL(std::max(fabs(errCorr(j)) - lambda, 0.0), tol);
    }
    else if (beta(j) < 0)
    {
      // make sure that errCorr(j) == lambda
      BOOST_REQUIRE_SMALL(errCorr(j) - lambda, tol);
    }
    else
    { // beta(j) > 0
      // make sure that errCorr(j) == -lambda
      BOOST_REQUIRE_SMALL(errCorr(j) + lambda, tol);
    }
  }
}

void LassoTest(size_t nPoints, size_t nDims, bool elasticNet, bool useCholesky)
{
  arma::mat X;
  arma::vec y;

  for(size_t i = 0; i < 100; i++)
  {
    GenerateProblem(X, y, nPoints, nDims);

    // Armadillo's median is broken, so...
    arma::vec sortedAbsCorr = sort(abs(trans(X) * y));
    double lambda1 = sortedAbsCorr(nDims/2);
    double lambda2;
    if (elasticNet)
      lambda2 = lambda1 / 2;
    else
      lambda2 = 0;

    LARS lars(useCholesky, lambda1, lambda2);
    lars.DoLARS(X, y);

    arma::vec betaOpt;
    lars.Solution(betaOpt);
    arma::vec errCorr = (arma::trans(X) * X + lambda2 *
        arma::eye(nDims, nDims)) * betaOpt - arma::trans(X) * y;

    VerifyCorrectness(betaOpt, errCorr, lambda1);
  }
}

BOOST_AUTO_TEST_CASE(LARSTestLassoCholesky)
{
  LassoTest(100, 10, true, false);
}

BOOST_AUTO_TEST_CASE(LARSTestLassoGram)
{
  LassoTest(100, 10, false, false);
}

BOOST_AUTO_TEST_CASE(LARSTestElasticNetCholesky)
{
  LassoTest(100, 10, true, true);
}

BOOST_AUTO_TEST_CASE(LARSTestElasticNetGram)
{
  LassoTest(100, 10, true, false);
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>
#include "../Flare.h"
#include "../Game/FlareWorld.h"
#include "../Game/FlareGame.h"
#include "../Game/FlareSimulatedSector.h"
#include "../Spacecrafts/FlareSimulatedSpacecraft.h"

#include "FlarePeople.h"

#define LOCTEXT_NAMESPACE "FlarePeopleInfo"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlarePeople::UFlarePeople(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

/*----------------------------------------------------
   Save
----------------------------------------------------*/

void UFlarePeople::Load(UFlareSimulatedSector* ParentSector, const FFlarePeopleSave& Data)
{
	Game = ParentSector->GetGame();

	PeopleData = Data;
	Parent = ParentSector;
}

FFlarePeopleSave* UFlarePeople::Save()
{
	return &PeopleData;
}

/*----------------------------------------------------
   Gameplay
----------------------------------------------------*/

static uint32 BIRTH_POINT_TRESHOLD = 7120;
static uint32 DEATH_POINT_TRESHOLD = 29200;
static uint32 MONETARY_CREATION = 1000;

void UFlarePeople::Simulate()
{
	if(PeopleData.Population == 0)
	{
		return;
	}

	FLOGV("Simulate people for sector %s. Population=%u", *Parent->GetSectorName().ToString(), PeopleData.Population)

	SimulateResourcePurchase();

	float Happiness = GetHappiness();

	// Death of old age : 1 death for 80 years per inhabitant = 1 death per 29200 inhabitant days
	// Sickness increase with hunger and sadness
	//	- 4 times normal sickness if happiness is 0
	//  - normal sickness if happiness is 1.5
	//  - half sickness if happiness 2
	//  Formula : sickness = 0.5 + (happiness -2)^2
	//
	//  Hunger is add to population death point
	//
	float Sickness = 0.5 + FMath::Square(Happiness - 2);
	PeopleData.DeathPoint += (PeopleData.Population + PeopleData.HungerPoint * 2) * Sickness;
	KillPeople(PeopleData.DeathPoint / DEATH_POINT_TRESHOLD);
	PeopleData.DeathPoint = PeopleData.DeathPoint % DEATH_POINT_TRESHOLD;

	// Births : 1 birth for 20 years per inhabitant = 1 birth per 7120 inhabitant days
	// Fertility increase with happiness :
	//	 - no fertility if hapinness is less of 50%
	//   - normal fertility at 100 % happiness
	//   - triple fertility at 200%
	//   Formula : fertility = 2 * happiness -1
	float Fertility = FMath::Max(2 * Happiness -1, 0.0f);

	PeopleData.BirthPoint += PeopleData.Population * Fertility;
	GiveBirth(PeopleData.BirthPoint / BIRTH_POINT_TRESHOLD);
	PeopleData.BirthPoint = PeopleData.BirthPoint % BIRTH_POINT_TRESHOLD;

	// Eat
	// Each inhabitant eat 1 kg of food a day as vital food.
	// TODO dynamic consumtion
	// If an inhabitant don't heat, happiness decrease heavily and  hunger is increase
	// If some inhabitant heat, the hunger deaseapear and some happiness is gain
	uint32 FoodConsumption = PeopleData.Population;
	uint32 EatenFood = FMath::Min(FoodConsumption, PeopleData.FoodStock);
	// Reduce stock
	PeopleData.FoodStock -= EatenFood;
	IncreaseHappiness(EatenFood / 10);

	// Reduce hunger (100% if everybody eat)
	float FeedPeopleRatio = (float) EatenFood / (float) FoodConsumption;

	PeopleData.HungerPoint *= 1 - FeedPeopleRatio;

	// Add hunger (0 if everybody eat)
	uint32 Hunger = FoodConsumption - EatenFood;
	PeopleData.HungerPoint += Hunger + PeopleData.HungerPoint / 10;
	DecreaseHappiness(Hunger * 10);

	FLOGV(" - happiness: %f", Happiness);
	FLOGV(" - Sickness: %f", Sickness);
	FLOGV(" - Fertility: %f", Fertility);

	FLOGV(" - Food: %u", PeopleData.FoodStock);
	FLOGV(" - FoodConsumption: %u", FoodConsumption);
	FLOGV(" - EatenFood: %u", EatenFood);
	FLOGV(" - FeedPeopleRatio: %f", FeedPeopleRatio);
	FLOGV(" - Delta Hunger: %u", Hunger);
	FLOGV(" - Hunger: %u", PeopleData.HungerPoint);

	FLOGV(" - Money: %u", PeopleData.Money);
	FLOGV(" - Dept: %u", PeopleData.Dept);
}

void UFlarePeople::SimulateResourcePurchase()
{
	FFlareResourceDescription* Food = Game->GetResourceCatalog()->Get("food");
	FFlareResourceDescription* Fuel = Game->GetResourceCatalog()->Get("fuel");
	FFlareResourceDescription* Tools = Game->GetResourceCatalog()->Get("tools");
	FFlareResourceDescription* Tech = Game->GetResourceCatalog()->Get("tech");

	// Buy at food for 15 days
	uint32 FoodToHave =  PeopleData.Population * 15; // In kg
	if(FoodToHave > PeopleData.FoodStock)
	{
		uint32 FoodToBuy = FoodToHave - PeopleData.FoodStock;
		FLOGV("  FoodToBuy: %u", FoodToBuy);
		uint32 BoughtFood = BuyResourcesInSector(Food, FoodToBuy / 1000); // In Tons
		FLOGV("  BoughtFood: %u", BoughtFood);
		PeopleData.FoodStock += BoughtFood * 1000; // In kg
	}

	// Todo stock
	uint32 BoughtFuel = BuyResourcesInSector(Fuel, PeopleData.Population / 1000); // In Tons
	uint32 BoughtTools = BuyResourcesInSector(Tools, PeopleData.Population / 1000); // In Tons
	uint32 BoughtTech = BuyResourcesInSector(Tech, PeopleData.Population / 1000); // In Tons

	PeopleData.HappinessPoint += BoughtFuel + BoughtTools + BoughtTech;

}

uint32 UFlarePeople::BuyResourcesInSector(FFlareResourceDescription* Resource, uint32 Quantity)
{
	// Find companies selling the ressource

	TArray<UFlareSimulatedSpacecraft*> SellingStations;
	TArray<UFlareCompany*> SellingCompanies;

	for (int32 SpacecraftIndex = 0; SpacecraftIndex < Parent->GetSectorStations().Num(); SpacecraftIndex++)
	{
		UFlareSimulatedSpacecraft* Station = Parent->GetSectorStations()[SpacecraftIndex];

		if(!Station->HasCapability(EFlareSpacecraftCapability::Consumer))
		{
			continue;
		}
		SellingStations.Add(Station);
		SellingCompanies.AddUnique(Station->GetCompany());
	}

	// Limit quantity to buy with money
	uint32 ResourceToBuy = FMath::Min(Quantity, PeopleData.Money / Parent->GetResourcePrice(Resource));

	while(ResourceToBuy > 0 && SellingCompanies.Num() > 0)
	{
		uint32 ReputationSum = 0;
		uint32 InitialResourceToBuy = ResourceToBuy;

		// Compute company reputation sum to share market part
		for (int32 CompanyIndex = 0; CompanyIndex < SellingCompanies.Num(); CompanyIndex++)
		{
			FFlareCompanyReputationSave* Reputation = GetCompanyReputation(SellingCompanies[CompanyIndex]);

			ReputationSum += Reputation->Reputation;
		}

		for (int32 CompanyIndex = SellingCompanies.Num()-1; CompanyIndex >= 0; CompanyIndex--)
		{
			FFlareCompanyReputationSave* Reputation = GetCompanyReputation(SellingCompanies[CompanyIndex]);

			uint32 PartToBuy = (InitialResourceToBuy * Reputation->Reputation) / ReputationSum;

			uint32 BoughtQuantity = BuyInStationForCompany(Resource, PartToBuy, SellingCompanies[CompanyIndex], SellingStations);
			ResourceToBuy -= BoughtQuantity;
			if(PartToBuy == 0 || BoughtQuantity < PartToBuy)
			{
				SellingCompanies.RemoveAt(CompanyIndex);
			}
		}
	}

	return Quantity - ResourceToBuy;
}

uint32 UFlarePeople::BuyInStationForCompany(FFlareResourceDescription* Resource, uint32 Quantity, UFlareCompany* Company, TArray<UFlareSimulatedSpacecraft*>& Stations)
{
	uint32 RemainingQuantity = Quantity;

	for (int32 StationIndex = 0; StationIndex < Stations.Num(); StationIndex++)
	{
		UFlareSimulatedSpacecraft* Station = Stations[StationIndex];

		if(Station->GetCompany() != Company)
		{
			continue;
		}

		uint32 TakenQuantity = Station->GetCargoBay()->TakeResources(Resource, RemainingQuantity);
		RemainingQuantity -= TakenQuantity;
		uint32 Price = Parent->GetResourcePrice(Resource) * TakenQuantity;
		PeopleData.Money -= Price;
		Company->GiveMoney(Price);
	}

	return Quantity - RemainingQuantity;
}

void UFlarePeople::GiveBirth(uint32 BirthCount)
{
	if(BirthCount == 0)
	{
		return;
	}

	FLOGV("Give birth %u people for sector %s", BirthCount, *Parent->GetSectorName().ToString());

	// Increase population
	PeopleData.Population += BirthCount;

	// Money creation
	PeopleData.Money += BirthCount * MONETARY_CREATION;

	IncreaseHappiness(BirthCount * 100 * 2);
	PeopleData.HappinessPoint += BirthCount * 100 * 2; // Birth happiness bonus
}

void UFlarePeople::KillPeople(uint32 KillCount)
{

	uint32 PeopleToKill = FMath::Min(KillCount, PeopleData.Population);
	if(PeopleToKill == 0)
	{
		return;
	}

	FLOGV("Kill %u people for sector %s", KillCount, *Parent->GetSectorName().ToString());

	float KillRatio = (float) PeopleToKill / (float)PeopleData.Population;
	// Decrease population
	PeopleData.Population -= KillCount;

	// Money destruction
	PeopleData.Dept += KillCount * MONETARY_CREATION;

	DecreaseHappiness(KillCount * 100 * 2); // Death happiness malus

	//Cancel dead hunger
	PeopleData.HungerPoint = (1 - KillRatio) * PeopleData.HungerPoint;

	if(PeopleToKill == 0)
	{
		ResetPeople();
	}
}

void UFlarePeople::IncreaseHappiness(uint32 HappinessPoints)
{
	// Max happiness is 2 so Happiness max is 200 x population
	// Gain happiness is boost when sad and difficult when happy
	//  - Normal gain for 1 as happiness
	//  - 4 times gain for 0 as happiness
	//  - No gain for 2 as happiness
	// Formula: gain = (happiness - 2) ^ 2
	float Happiness = GetHappiness();
	float Gain = FMath::Square(Happiness - 2);
	PeopleData.HappinessPoint += HappinessPoints * Gain;
	PeopleData.HappinessPoint = FMath::Min(PeopleData.HappinessPoint, PeopleData.Population * 200);
}

void UFlarePeople::DecreaseHappiness(uint32 SadnessPoints)
{
	// Same as for increase but gain are inverted
	float Happiness = GetHappiness();
	float Gain = FMath::Square(Happiness);
	PeopleData.HappinessPoint -= SadnessPoints * Gain;
	PeopleData.HappinessPoint = FMath::Max(PeopleData.HappinessPoint, (uint32) 0);
}

void UFlarePeople::SetHappiness(float Happiness)
{
	PeopleData.HappinessPoint = PeopleData.Population * 100 * Happiness;
}

void UFlarePeople::Pay(uint32 Amount)
{
	FLOGV("Pay to people for sector %s Amount=%u", *Parent->GetSectorName().ToString(), Amount)

	uint32 Repayment = 0;
	if(PeopleData.Dept > 0)
	{
		Repayment = FMath::Min(PeopleData.Dept, Amount / 10);
		PeopleData.Dept -= Repayment;
	}
	PeopleData.Money += Amount - Repayment;
}

void UFlarePeople::ResetPeople()
{
	PeopleData.Population = 0;
	PeopleData.BirthPoint = 0;
	PeopleData.DeathPoint = 0;
	PeopleData.FoodStock = 0;
	PeopleData.HappinessPoint = 0;
	PeopleData.HungerPoint = 0;

	// Don't reset money to avoid moyen lost

}

/*----------------------------------------------------
	Getters
----------------------------------------------------*/

float UFlarePeople::GetHappiness()
{
	if(PeopleData.Population == 0)
	{
		return 0;
	}
	return (float) PeopleData.HappinessPoint / (100 * (float) PeopleData.Population);
}

FFlareCompanyReputationSave* UFlarePeople::GetCompanyReputation(UFlareCompany* Company)
{
	for(int ReputationIndex = 0; ReputationIndex < PeopleData.CompanyReputations.Num(); ReputationIndex++)
	{
		if(PeopleData.CompanyReputations[ReputationIndex].CompanyIdentifier == Company->GetIdentifier())
		{
			return &PeopleData.CompanyReputations[ReputationIndex];
		}
	}

	//Init Reputation
	FFlareCompanyReputationSave NewReputation;
	NewReputation.CompanyIdentifier = Company->GetIdentifier();
	NewReputation.Reputation = 1000 * PeopleData.Population;
	PeopleData.CompanyReputations.Add(NewReputation);

	return GetCompanyReputation(Company);
}

#undef LOCTEXT_NAMESPACE
<commit_msg>People buy the resources 105% of the market price to give margin to final reseller<commit_after>
#include "../Flare.h"
#include "../Game/FlareWorld.h"
#include "../Game/FlareGame.h"
#include "../Game/FlareSimulatedSector.h"
#include "../Spacecrafts/FlareSimulatedSpacecraft.h"

#include "FlarePeople.h"

#define LOCTEXT_NAMESPACE "FlarePeopleInfo"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlarePeople::UFlarePeople(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

/*----------------------------------------------------
   Save
----------------------------------------------------*/

void UFlarePeople::Load(UFlareSimulatedSector* ParentSector, const FFlarePeopleSave& Data)
{
	Game = ParentSector->GetGame();

	PeopleData = Data;
	Parent = ParentSector;
}

FFlarePeopleSave* UFlarePeople::Save()
{
	return &PeopleData;
}

/*----------------------------------------------------
   Gameplay
----------------------------------------------------*/

static uint32 BIRTH_POINT_TRESHOLD = 7120;
static uint32 DEATH_POINT_TRESHOLD = 29200;
static uint32 MONETARY_CREATION = 1000;

void UFlarePeople::Simulate()
{
	if(PeopleData.Population == 0)
	{
		return;
	}

	FLOGV("Simulate people for sector %s. Population=%u", *Parent->GetSectorName().ToString(), PeopleData.Population)

	SimulateResourcePurchase();

	float Happiness = GetHappiness();

	// Death of old age : 1 death for 80 years per inhabitant = 1 death per 29200 inhabitant days
	// Sickness increase with hunger and sadness
	//	- 4 times normal sickness if happiness is 0
	//  - normal sickness if happiness is 1.5
	//  - half sickness if happiness 2
	//  Formula : sickness = 0.5 + (happiness -2)^2
	//
	//  Hunger is add to population death point
	//
	float Sickness = 0.5 + FMath::Square(Happiness - 2);
	PeopleData.DeathPoint += (PeopleData.Population + PeopleData.HungerPoint * 2) * Sickness;
	KillPeople(PeopleData.DeathPoint / DEATH_POINT_TRESHOLD);
	PeopleData.DeathPoint = PeopleData.DeathPoint % DEATH_POINT_TRESHOLD;

	// Births : 1 birth for 20 years per inhabitant = 1 birth per 7120 inhabitant days
	// Fertility increase with happiness :
	//	 - no fertility if hapinness is less of 50%
	//   - normal fertility at 100 % happiness
	//   - triple fertility at 200%
	//   Formula : fertility = 2 * happiness -1
	float Fertility = FMath::Max(2 * Happiness -1, 0.0f);

	PeopleData.BirthPoint += PeopleData.Population * Fertility;
	GiveBirth(PeopleData.BirthPoint / BIRTH_POINT_TRESHOLD);
	PeopleData.BirthPoint = PeopleData.BirthPoint % BIRTH_POINT_TRESHOLD;

	// Eat
	// Each inhabitant eat 1 kg of food a day as vital food.
	// TODO dynamic consumtion
	// If an inhabitant don't heat, happiness decrease heavily and  hunger is increase
	// If some inhabitant heat, the hunger deaseapear and some happiness is gain
	uint32 FoodConsumption = PeopleData.Population;
	uint32 EatenFood = FMath::Min(FoodConsumption, PeopleData.FoodStock);
	// Reduce stock
	PeopleData.FoodStock -= EatenFood;
	IncreaseHappiness(EatenFood / 10);

	// Reduce hunger (100% if everybody eat)
	float FeedPeopleRatio = (float) EatenFood / (float) FoodConsumption;

	PeopleData.HungerPoint *= 1 - FeedPeopleRatio;

	// Add hunger (0 if everybody eat)
	uint32 Hunger = FoodConsumption - EatenFood;
	PeopleData.HungerPoint += Hunger + PeopleData.HungerPoint / 10;
	DecreaseHappiness(Hunger * 10);

	FLOGV(" - happiness: %f", Happiness);
	FLOGV(" - Sickness: %f", Sickness);
	FLOGV(" - Fertility: %f", Fertility);

	FLOGV(" - Food: %u", PeopleData.FoodStock);
	FLOGV(" - FoodConsumption: %u", FoodConsumption);
	FLOGV(" - EatenFood: %u", EatenFood);
	FLOGV(" - FeedPeopleRatio: %f", FeedPeopleRatio);
	FLOGV(" - Delta Hunger: %u", Hunger);
	FLOGV(" - Hunger: %u", PeopleData.HungerPoint);

	FLOGV(" - Money: %u", PeopleData.Money);
	FLOGV(" - Dept: %u", PeopleData.Dept);
}

void UFlarePeople::SimulateResourcePurchase()
{
	FFlareResourceDescription* Food = Game->GetResourceCatalog()->Get("food");
	FFlareResourceDescription* Fuel = Game->GetResourceCatalog()->Get("fuel");
	FFlareResourceDescription* Tools = Game->GetResourceCatalog()->Get("tools");
	FFlareResourceDescription* Tech = Game->GetResourceCatalog()->Get("tech");

	// Buy at food for 15 days
	uint32 FoodToHave =  PeopleData.Population * 15; // In kg
	if(FoodToHave > PeopleData.FoodStock)
	{
		uint32 FoodToBuy = FoodToHave - PeopleData.FoodStock;
		FLOGV("  FoodToBuy: %u", FoodToBuy);
		uint32 BoughtFood = BuyResourcesInSector(Food, FoodToBuy / 1000); // In Tons
		FLOGV("  BoughtFood: %u", BoughtFood);
		PeopleData.FoodStock += BoughtFood * 1000; // In kg
	}

	// Todo stock
	uint32 BoughtFuel = BuyResourcesInSector(Fuel, PeopleData.Population / 1000); // In Tons
	uint32 BoughtTools = BuyResourcesInSector(Tools, PeopleData.Population / 1000); // In Tons
	uint32 BoughtTech = BuyResourcesInSector(Tech, PeopleData.Population / 1000); // In Tons

	PeopleData.HappinessPoint += BoughtFuel + BoughtTools + BoughtTech;

}

uint32 UFlarePeople::BuyResourcesInSector(FFlareResourceDescription* Resource, uint32 Quantity)
{
	// Find companies selling the ressource

	TArray<UFlareSimulatedSpacecraft*> SellingStations;
	TArray<UFlareCompany*> SellingCompanies;

	for (int32 SpacecraftIndex = 0; SpacecraftIndex < Parent->GetSectorStations().Num(); SpacecraftIndex++)
	{
		UFlareSimulatedSpacecraft* Station = Parent->GetSectorStations()[SpacecraftIndex];

		if(!Station->HasCapability(EFlareSpacecraftCapability::Consumer))
		{
			continue;
		}
		SellingStations.Add(Station);
		SellingCompanies.AddUnique(Station->GetCompany());
	}

	// Limit quantity to buy with money
	uint32 ResourceToBuy = FMath::Min(Quantity, PeopleData.Money / (uint32) (Parent->GetResourcePrice(Resource)*1.05));

	while(ResourceToBuy > 0 && SellingCompanies.Num() > 0)
	{
		uint32 ReputationSum = 0;
		uint32 InitialResourceToBuy = ResourceToBuy;

		// Compute company reputation sum to share market part
		for (int32 CompanyIndex = 0; CompanyIndex < SellingCompanies.Num(); CompanyIndex++)
		{
			FFlareCompanyReputationSave* Reputation = GetCompanyReputation(SellingCompanies[CompanyIndex]);

			ReputationSum += Reputation->Reputation;
		}

		for (int32 CompanyIndex = SellingCompanies.Num()-1; CompanyIndex >= 0; CompanyIndex--)
		{
			FFlareCompanyReputationSave* Reputation = GetCompanyReputation(SellingCompanies[CompanyIndex]);

			uint32 PartToBuy = (InitialResourceToBuy * Reputation->Reputation) / ReputationSum;

			uint32 BoughtQuantity = BuyInStationForCompany(Resource, PartToBuy, SellingCompanies[CompanyIndex], SellingStations);
			ResourceToBuy -= BoughtQuantity;
			if(PartToBuy == 0 || BoughtQuantity < PartToBuy)
			{
				SellingCompanies.RemoveAt(CompanyIndex);
			}
		}
	}

	return Quantity - ResourceToBuy;
}

uint32 UFlarePeople::BuyInStationForCompany(FFlareResourceDescription* Resource, uint32 Quantity, UFlareCompany* Company, TArray<UFlareSimulatedSpacecraft*>& Stations)
{
	uint32 RemainingQuantity = Quantity;

	for (int32 StationIndex = 0; StationIndex < Stations.Num(); StationIndex++)
	{
		UFlareSimulatedSpacecraft* Station = Stations[StationIndex];

		if(Station->GetCompany() != Company)
		{
			continue;
		}

		uint32 TakenQuantity = Station->GetCargoBay()->TakeResources(Resource, RemainingQuantity);
		RemainingQuantity -= TakenQuantity;
		uint32 Price = (uint32) (Parent->GetResourcePrice(Resource)*1.05) * TakenQuantity;
		PeopleData.Money -= Price;
		Company->GiveMoney(Price);
	}

	return Quantity - RemainingQuantity;
}

void UFlarePeople::GiveBirth(uint32 BirthCount)
{
	if(BirthCount == 0)
	{
		return;
	}

	FLOGV("Give birth %u people for sector %s", BirthCount, *Parent->GetSectorName().ToString());

	// Increase population
	PeopleData.Population += BirthCount;

	// Money creation
	PeopleData.Money += BirthCount * MONETARY_CREATION;

	IncreaseHappiness(BirthCount * 100 * 2);
	PeopleData.HappinessPoint += BirthCount * 100 * 2; // Birth happiness bonus
}

void UFlarePeople::KillPeople(uint32 KillCount)
{

	uint32 PeopleToKill = FMath::Min(KillCount, PeopleData.Population);
	if(PeopleToKill == 0)
	{
		return;
	}

	FLOGV("Kill %u people for sector %s", KillCount, *Parent->GetSectorName().ToString());

	float KillRatio = (float) PeopleToKill / (float)PeopleData.Population;
	// Decrease population
	PeopleData.Population -= KillCount;

	// Money destruction
	PeopleData.Dept += KillCount * MONETARY_CREATION;

	DecreaseHappiness(KillCount * 100 * 2); // Death happiness malus

	//Cancel dead hunger
	PeopleData.HungerPoint = (1 - KillRatio) * PeopleData.HungerPoint;

	if(PeopleToKill == 0)
	{
		ResetPeople();
	}
}

void UFlarePeople::IncreaseHappiness(uint32 HappinessPoints)
{
	// Max happiness is 2 so Happiness max is 200 x population
	// Gain happiness is boost when sad and difficult when happy
	//  - Normal gain for 1 as happiness
	//  - 4 times gain for 0 as happiness
	//  - No gain for 2 as happiness
	// Formula: gain = (happiness - 2) ^ 2
	float Happiness = GetHappiness();
	float Gain = FMath::Square(Happiness - 2);
	PeopleData.HappinessPoint += HappinessPoints * Gain;
	PeopleData.HappinessPoint = FMath::Min(PeopleData.HappinessPoint, PeopleData.Population * 200);
}

void UFlarePeople::DecreaseHappiness(uint32 SadnessPoints)
{
	// Same as for increase but gain are inverted
	float Happiness = GetHappiness();
	float Gain = FMath::Square(Happiness);
	PeopleData.HappinessPoint -= SadnessPoints * Gain;
	PeopleData.HappinessPoint = FMath::Max(PeopleData.HappinessPoint, (uint32) 0);
}

void UFlarePeople::SetHappiness(float Happiness)
{
	PeopleData.HappinessPoint = PeopleData.Population * 100 * Happiness;
}

void UFlarePeople::Pay(uint32 Amount)
{
	FLOGV("Pay to people for sector %s Amount=%u", *Parent->GetSectorName().ToString(), Amount)

	uint32 Repayment = 0;
	if(PeopleData.Dept > 0)
	{
		Repayment = FMath::Min(PeopleData.Dept, Amount / 10);
		PeopleData.Dept -= Repayment;
	}
	PeopleData.Money += Amount - Repayment;
}

void UFlarePeople::ResetPeople()
{
	PeopleData.Population = 0;
	PeopleData.BirthPoint = 0;
	PeopleData.DeathPoint = 0;
	PeopleData.FoodStock = 0;
	PeopleData.HappinessPoint = 0;
	PeopleData.HungerPoint = 0;

	// Don't reset money to avoid moyen lost

}

/*----------------------------------------------------
	Getters
----------------------------------------------------*/

float UFlarePeople::GetHappiness()
{
	if(PeopleData.Population == 0)
	{
		return 0;
	}
	return (float) PeopleData.HappinessPoint / (100 * (float) PeopleData.Population);
}

FFlareCompanyReputationSave* UFlarePeople::GetCompanyReputation(UFlareCompany* Company)
{
	for(int ReputationIndex = 0; ReputationIndex < PeopleData.CompanyReputations.Num(); ReputationIndex++)
	{
		if(PeopleData.CompanyReputations[ReputationIndex].CompanyIdentifier == Company->GetIdentifier())
		{
			return &PeopleData.CompanyReputations[ReputationIndex];
		}
	}

	//Init Reputation
	FFlareCompanyReputationSave NewReputation;
	NewReputation.CompanyIdentifier = Company->GetIdentifier();
	NewReputation.Reputation = 1000 * PeopleData.Population;
	PeopleData.CompanyReputations.Add(NewReputation);

	return GetCompanyReputation(Company);
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>/*
 * opencog/atoms/base/Link.cc
 *
 * Copyright (C) 2008-2010 OpenCog Foundation
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <stdio.h>

#include <opencog/util/exceptions.h>
#include <opencog/util/Logger.h>

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/base/Node.h>
#include <opencog/atomspace/AtomTable.h>

#include <boost/range/algorithm.hpp>

#include "Link.h"

//#define DPRINTF printf
#define DPRINTF(...)

using namespace opencog;

void Link::resort(void)
{
    // Caution: this comparison function MUST BE EXACTLY THE SAME as
    // the one in AtomTable.cc, used for Unordered links. Changing
    // this without changing the other one will break things!
    std::sort(_outgoing.begin(), _outgoing.end(), handle_less());
}

void Link::init(const HandleSeq& outgoingVector)
{
    if (not classserver().isA(_type, LINK)) {
        throw InvalidParamException(TRACE_INFO,
            "Link ctor: Atom type is not a Link: '%d' %s.",
            _type, classserver().getTypeName(_type).c_str());
    }

    _outgoing = outgoingVector;
    // If the link is unordered, it will be normalized by sorting the
    // elements in the outgoing list.
    if (classserver().isA(_type, UNORDERED_LINK)) {
        resort();
    }
}

Link::~Link()
{
    DPRINTF("Deleting link:\n%s\n", this->toString().c_str());
}

std::string Link::toShortString(const std::string& indent) const
{
    std::stringstream answer;
    std::string more_indent = indent + "  ";

    answer << indent << "(" << classserver().getTypeName(_type);
    if (not getTruthValue()->isDefaultTV())
        answer << " " << getTruthValue()->toString();
    answer << "\n";

    // Here the target string is made. If a target is a node, its name is
    // concatenated. If it's a link, all its properties are concatenated.
    for (const Handle& h : _outgoing) {
        if (h.operator->() != NULL)
            answer << h->toShortString(more_indent);
        else
            answer << more_indent << "Undefined Atom!\n";
    }

    answer << indent << ") ; [" << _uuid << "]";

    if (_atomTable)
        answer << "[" << _atomTable->get_uuid() << "]\n";
    else
        answer << "[NULL]\n";

    return answer.str();
}

std::string Link::toString(const std::string& indent) const
{
    std::string answer = indent;
    std::string more_indent = indent + "  ";

    answer += "(" + classserver().getTypeName(_type);

    // Print the TV and AV only if its not the default.
    if (not getAttentionValue()->isDefaultAV())
        answer += " (av " +
             std::to_string(getAttentionValue()->getSTI()) + " " +
             std::to_string(getAttentionValue()->getLTI()) + " " +
             std::to_string(getAttentionValue()->getVLTI()) + ")";

    if (not getTruthValue()->isDefaultTV())
        answer += " " + getTruthValue()->toString();

    answer += "\n";
    // Here, the outset string is made. If a target is a node,
    // its name is concatenated. If it's a link, then recurse.
    for (const Handle& h : _outgoing) {
        if (h.operator->() != NULL)
            answer += h->toString(more_indent);
        else
            answer += more_indent + "Undefined Atom!\n";
    }

    answer += indent + ") ; [" +
            std::to_string(_uuid) + "][" +
            std::to_string(_atomTable? _atomTable->get_uuid() : -1) +
            "]\n";

    return answer;
}

// Content-based comparison.
bool Link::operator==(const Atom& other) const
{
    // Rule out obvious mis-matches, based on the hash.
    if (get_hash() != other.get_hash()) return false;
    if (getType() != other.getType()) return false;

    Arity sz = getArity();
    if (sz != other.getArity()) return false;

    const HandleSeq& rhs = other.getOutgoingSet();
    for (Arity i = 0; i < sz; i++)
    {
        if (_outgoing[i] != rhs[i])
            return false;
    }
    return true;
}

// Content-based ordering.
bool Link::operator<(const Atom& other) const
{
    if (get_hash() < other.get_hash()) return true;
    if (other.get_hash() < get_hash()) return false;

    // We get to here only if the hashes are equal.
    // Compare the contents directly, for this
    // (hopefully rare) case.
    if (getType() == other.getType()) {
        const HandleSeq& outgoing = getOutgoingSet();
        const HandleSeq& other_outgoing = other.getOutgoingSet();
        Arity arity = outgoing.size();
        Arity other_arity = other_outgoing.size();
        if (arity == other_arity) {
            Arity i = 0;
            while (i < arity) {
                Handle ll = outgoing[i];
                Handle rl = other_outgoing[i];
                if (ll == rl)
                    i++;
                else
                    return ll->operator<(*rl.atom_ptr());
            }
            return false;
        } else
            return arity < other_arity;
    } else
        return getType() < other.getType();
}

/// Returns a Merkle tree hash -- that is, the hash of this link
/// chains the hash values of the child atoms, as well.
ContentHash Link::compute_hash() const
{
	// djb hash
	ContentHash hsh = 5381;
	hsh += (hsh <<5) + getType();

	for (const Handle& h: _outgoing)
	{
		hsh += (hsh <<5) + h->get_hash(); // recursive!
	}

	// Links will always have the MSB set.
	ContentHash mask = ((ContentHash) 1UL) << (8*sizeof(ContentHash) - 1);
	hsh |= mask;

	if (Handle::INVALID_HASH == hsh) hsh -= 1;
	_content_hash = hsh;
	return _content_hash;
}
<commit_msg>Bug-fix the content-compare for links.<commit_after>/*
 * opencog/atoms/base/Link.cc
 *
 * Copyright (C) 2008-2010 OpenCog Foundation
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <stdio.h>

#include <opencog/util/exceptions.h>
#include <opencog/util/Logger.h>

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/base/Node.h>
#include <opencog/atomspace/AtomTable.h>

#include <boost/range/algorithm.hpp>

#include "Link.h"

//#define DPRINTF printf
#define DPRINTF(...)

using namespace opencog;

void Link::resort(void)
{
    // Caution: this comparison function MUST BE EXACTLY THE SAME as
    // the one in AtomTable.cc, used for Unordered links. Changing
    // this without changing the other one will break things!
    std::sort(_outgoing.begin(), _outgoing.end(), handle_less());
}

void Link::init(const HandleSeq& outgoingVector)
{
    if (not classserver().isA(_type, LINK)) {
        throw InvalidParamException(TRACE_INFO,
            "Link ctor: Atom type is not a Link: '%d' %s.",
            _type, classserver().getTypeName(_type).c_str());
    }

    _outgoing = outgoingVector;
    // If the link is unordered, it will be normalized by sorting the
    // elements in the outgoing list.
    if (classserver().isA(_type, UNORDERED_LINK)) {
        resort();
    }
}

Link::~Link()
{
    DPRINTF("Deleting link:\n%s\n", this->toString().c_str());
}

std::string Link::toShortString(const std::string& indent) const
{
    std::stringstream answer;
    std::string more_indent = indent + "  ";

    answer << indent << "(" << classserver().getTypeName(_type);
    if (not getTruthValue()->isDefaultTV())
        answer << " " << getTruthValue()->toString();
    answer << "\n";

    // Here the target string is made. If a target is a node, its name is
    // concatenated. If it's a link, all its properties are concatenated.
    for (const Handle& h : _outgoing) {
        if (h.operator->() != NULL)
            answer << h->toShortString(more_indent);
        else
            answer << more_indent << "Undefined Atom!\n";
    }

    answer << indent << ") ; [" << _uuid << "]";

    if (_atomTable)
        answer << "[" << _atomTable->get_uuid() << "]\n";
    else
        answer << "[NULL]\n";

    return answer.str();
}

std::string Link::toString(const std::string& indent) const
{
    std::string answer = indent;
    std::string more_indent = indent + "  ";

    answer += "(" + classserver().getTypeName(_type);

    // Print the TV and AV only if its not the default.
    if (not getAttentionValue()->isDefaultAV())
        answer += " (av " +
             std::to_string(getAttentionValue()->getSTI()) + " " +
             std::to_string(getAttentionValue()->getLTI()) + " " +
             std::to_string(getAttentionValue()->getVLTI()) + ")";

    if (not getTruthValue()->isDefaultTV())
        answer += " " + getTruthValue()->toString();

    answer += "\n";
    // Here, the outset string is made. If a target is a node,
    // its name is concatenated. If it's a link, then recurse.
    for (const Handle& h : _outgoing) {
        if (h.operator->() != NULL)
            answer += h->toString(more_indent);
        else
            answer += more_indent + "Undefined Atom!\n";
    }

    answer += indent + ") ; [" +
            std::to_string(_uuid) + "][" +
            std::to_string(_atomTable? _atomTable->get_uuid() : -1) +
            "]\n";

    return answer;
}

// Content-based comparison.
bool Link::operator==(const Atom& other) const
{
    // If other points to this, then have equality.
    if (this == &other) return true;

    // Rule out obvious mis-matches, based on the hash.
    if (get_hash() != other.get_hash()) return false;
    if (getType() != other.getType()) return false;

    Arity sz = getArity();
    if (sz != other.getArity()) return false;

    // Perform a content-compare on the outgoing set.
    const HandleSeq& rhs = other.getOutgoingSet();
    for (Arity i = 0; i < sz; i++)
    {
        if (*((AtomPtr)_outgoing[i]) != *((AtomPtr)rhs[i]))
            return false;
    }
    return true;
}

// Content-based ordering.
bool Link::operator<(const Atom& other) const
{
    if (get_hash() < other.get_hash()) return true;
    if (other.get_hash() < get_hash()) return false;

    // We get to here only if the hashes are equal.
    // Compare the contents directly, for this
    // (hopefully rare) case.
    if (getType() == other.getType()) {
        const HandleSeq& outgoing = getOutgoingSet();
        const HandleSeq& other_outgoing = other.getOutgoingSet();
        Arity arity = outgoing.size();
        Arity other_arity = other_outgoing.size();
        if (arity == other_arity) {
            Arity i = 0;
            while (i < arity) {
                Handle ll = outgoing[i];
                Handle rl = other_outgoing[i];
                if (ll == rl)
                    i++;
                else
                    return ll->operator<(*rl.atom_ptr());
            }
            return false;
        } else
            return arity < other_arity;
    } else
        return getType() < other.getType();
}

/// Returns a Merkle tree hash -- that is, the hash of this link
/// chains the hash values of the child atoms, as well.
ContentHash Link::compute_hash() const
{
	// djb hash
	ContentHash hsh = 5381;
	hsh += (hsh <<5) + getType();

	for (const Handle& h: _outgoing)
	{
		hsh += (hsh <<5) + h->get_hash(); // recursive!
	}

	// Links will always have the MSB set.
	ContentHash mask = ((ContentHash) 1UL) << (8*sizeof(ContentHash) - 1);
	hsh |= mask;

	if (Handle::INVALID_HASH == hsh) hsh -= 1;
	_content_hash = hsh;
	return _content_hash;
}
<|endoftext|>