<commit_before>/*************************************************************************
 *
 *  $RCSfile: kdedata.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-07 09:25:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Jan Holesovsky <kendy@artax.karlin.mff.cuni.cz>
 *                  Michael Meeks <michael@ximian.com>
 *
 ************************************************************************/

#define _SV_SALDATA_CXX

#define Region QtXRegion
#include <kaboutdata.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <qpaintdevice.h>
#undef Region

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>
#ifdef FREEBSD
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#ifndef _VCL_KDEDATA_HXX
#include <plugins/kde/kdedata.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <osl/module.h>

#include <tools/debug.hxx>

#ifndef _SAL_I18N_INPUTMETHOD_HXX
#include "i18n_im.hxx"
#endif
#ifndef _SAL_I18N_XKBDEXTENSION_HXX
#include "i18n_xkb.hxx"
#endif

#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _VOS_MUTEX_HXX
#include <vos/mutex.hxx>
#endif

/***************************************************************************
 * class KDEXLib                                                           *
 ***************************************************************************/

class KDEXLib : public SalXLib
{
public:
    KDEXLib() : SalXLib() {}
    virtual ~KDEXLib() {}
    virtual void Init();
};

void KDEXLib::Init()
{
    SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
    pInputMethod->SetLocale();
    XrmInitialize();

    KAboutData *kAboutData = new KAboutData( "OpenOffice.org",
            I18N_NOOP( "OpenOffice.org" ),
            "1.1.0",
            I18N_NOOP( "OpenOffice.org with KDE Native Widget Support." ),
            KAboutData::License_LGPL,
            "(c) 2003, 2004 Novell, Inc",
            I18N_NOOP( "OpenOffice.org is an office suite.\n" ),
            "http://kde.openoffice.org/index.html",
            "dev@kde.openoffice.org");
    kAboutData->addAuthor( "Jan Holesovsky",
            I18N_NOOP( "Original author and maintainer of the KDE NWF." ),
            "kendy@artax.karlin.mff.cuni.cz",
            "http://artax.karlin.mff.cuni.cz/~kendy" );

    int nFakeArgc = 1;
    char** pFakeArgv = NULL;
    USHORT nIdx;
    vos::OExtCommandLine aCommandLine;
    int nParams = aCommandLine.getCommandArgCount();
    rtl::OString aDisplay;
    rtl::OUString aParam, aBin;

    for ( nIdx = 0; nIdx < nParams; ++nIdx )
    {
        aCommandLine.getCommandArg( nIdx, aParam );
        if ( !pFakeArgv && aParam.equalsAscii( "-display" ) && nIdx + 1 < nParams )
        {
            aCommandLine.getCommandArg( nIdx + 1, aParam );
            aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() );

            nFakeArgc = 3;
            pFakeArgv = new char*[ nFakeArgc ];
            pFakeArgv[ 1 ] = strdup( "-display" );
            pFakeArgv[ 2 ] = strdup( aDisplay.getStr() );
        }
    }
    if ( !pFakeArgv )
        pFakeArgv = new char*[ nFakeArgc ];

    osl_getExecutableFile( &aParam.pData );
    osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
    pFakeArgv[0] = strdup( rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() ).getStr() );

    KCmdLineArgs::init( nFakeArgc, pFakeArgv, kAboutData );

    KApplication::disableAutoDcopRegistration();
    new KApplication();

    Display* pDisp = QPaintDevice::x11AppDisplay();
    XVisualInfo aVI;
    Colormap    aColMap;
    int         nScreen = DefaultScreen( pDisp );
    if( SalDisplay::BestVisual( pDisp, nScreen, aVI ) ) // DefaultVisual
        aColMap = DefaultColormap( pDisp, nScreen );
    else
        aColMap = XCreateColormap( pDisp,
                                   RootWindow( pDisp, nScreen ),
                                   aVI.visual,
                                   AllocNone );

    SalDisplay *pSalDisplay = new SalX11Display( pDisp, aVI.visual, aColMap );

    pInputMethod->CreateMethod( pDisp );
    pInputMethod->AddConnectionWatch( pDisp, (void*)this );
    pSalDisplay->SetInputMethod( pInputMethod );

    sal_Bool bOldErrorSetting = GetIgnoreXErrors();
    SetIgnoreXErrors( True );
    SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
    XSync( pDisp, False );

    pKbdExtension->UseExtension( ! WasXError() );
    SetIgnoreXErrors( bOldErrorSetting );

    pSalDisplay->SetKbdExtension( pKbdExtension );
}

/**********************************************************************
 * class KDEData                                                      *
 **********************************************************************/

KDEData::~KDEData()
{
}

void KDEData::Init()
{
    pXLib_ = new KDEXLib();
    pXLib_->Init();
}

/**********************************************************************
 * plugin entry point                                                 *
 **********************************************************************/

extern "C" {
    SalInstance* create_SalInstance( oslModule pModule )
    {
        KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        SalData *pSalData = new KDEData();
        SetSalData( pSalData );
        pSalData->pInstance_ = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        return pInstance;
    }
}
<commit_msg>INTEGRATION: CWS vclcompact (1.2.82); FILE MERGED 2004/12/03 10:25:09 dv 1.2.82.1: #i37763# Reduce vcl exports<commit_after>/*************************************************************************
 *
 *  $RCSfile: kdedata.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-13 18:13:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Jan Holesovsky <kendy@artax.karlin.mff.cuni.cz>
 *                  Michael Meeks <michael@ximian.com>
 *
 ************************************************************************/

#define _SV_SALDATA_CXX

#define Region QtXRegion
#include <kaboutdata.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <qpaintdevice.h>
#undef Region

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>
#ifdef FREEBSD
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#ifndef _VCL_KDEDATA_HXX
#include <plugins/kde/kdedata.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <osl/module.h>

#include <tools/debug.hxx>

#ifndef _SAL_I18N_INPUTMETHOD_HXX
#include "i18n_im.hxx"
#endif
#ifndef _SAL_I18N_XKBDEXTENSION_HXX
#include "i18n_xkb.hxx"
#endif

#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _VOS_MUTEX_HXX
#include <vos/mutex.hxx>
#endif

/***************************************************************************
 * class KDEXLib                                                           *
 ***************************************************************************/

class KDEXLib : public SalXLib
{
public:
    KDEXLib() : SalXLib() {}
    virtual ~KDEXLib() {}
    virtual void Init();
};

void KDEXLib::Init()
{
    SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
    pInputMethod->SetLocale();
    XrmInitialize();

    KAboutData *kAboutData = new KAboutData( "OpenOffice.org",
            I18N_NOOP( "OpenOffice.org" ),
            "1.1.0",
            I18N_NOOP( "OpenOffice.org with KDE Native Widget Support." ),
            KAboutData::License_LGPL,
            "(c) 2003, 2004 Novell, Inc",
            I18N_NOOP( "OpenOffice.org is an office suite.\n" ),
            "http://kde.openoffice.org/index.html",
            "dev@kde.openoffice.org");
    kAboutData->addAuthor( "Jan Holesovsky",
            I18N_NOOP( "Original author and maintainer of the KDE NWF." ),
            "kendy@artax.karlin.mff.cuni.cz",
            "http://artax.karlin.mff.cuni.cz/~kendy" );

    int nFakeArgc = 1;
    char** pFakeArgv = NULL;
    USHORT nIdx;
    vos::OExtCommandLine aCommandLine;
    int nParams = aCommandLine.getCommandArgCount();
    rtl::OString aDisplay;
    rtl::OUString aParam, aBin;

    for ( nIdx = 0; nIdx < nParams; ++nIdx )
    {
        aCommandLine.getCommandArg( nIdx, aParam );
        if ( !pFakeArgv && aParam.equalsAscii( "-display" ) && nIdx + 1 < nParams )
        {
            aCommandLine.getCommandArg( nIdx + 1, aParam );
            aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() );

            nFakeArgc = 3;
            pFakeArgv = new char*[ nFakeArgc ];
            pFakeArgv[ 1 ] = strdup( "-display" );
            pFakeArgv[ 2 ] = strdup( aDisplay.getStr() );
        }
    }
    if ( !pFakeArgv )
        pFakeArgv = new char*[ nFakeArgc ];

    osl_getExecutableFile( &aParam.pData );
    osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
    pFakeArgv[0] = strdup( rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() ).getStr() );

    KCmdLineArgs::init( nFakeArgc, pFakeArgv, kAboutData );

    KApplication::disableAutoDcopRegistration();
    new KApplication();

    Display* pDisp = QPaintDevice::x11AppDisplay();
    XVisualInfo aVI;
    Colormap    aColMap;
    int         nScreen = DefaultScreen( pDisp );
    if( SalDisplay::BestVisual( pDisp, nScreen, aVI ) ) // DefaultVisual
        aColMap = DefaultColormap( pDisp, nScreen );
    else
        aColMap = XCreateColormap( pDisp,
                                   RootWindow( pDisp, nScreen ),
                                   aVI.visual,
                                   AllocNone );

    SalDisplay *pSalDisplay = new SalX11Display( pDisp, aVI.visual, aColMap );

    pInputMethod->CreateMethod( pDisp );
    pInputMethod->AddConnectionWatch( pDisp, (void*)this );
    pSalDisplay->SetInputMethod( pInputMethod );

    sal_Bool bOldErrorSetting = GetIgnoreXErrors();
    SetIgnoreXErrors( True );
    SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
    XSync( pDisp, False );

    pKbdExtension->UseExtension( ! WasXError() );
    SetIgnoreXErrors( bOldErrorSetting );

    pSalDisplay->SetKbdExtension( pKbdExtension );
}

/**********************************************************************
 * class KDEData                                                      *
 **********************************************************************/

KDEData::~KDEData()
{
}

void KDEData::Init()
{
    pXLib_ = new KDEXLib();
    pXLib_->Init();
}

/**********************************************************************
 * plugin entry point                                                 *
 **********************************************************************/

extern "C" {
    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
    {
        KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        SalData *pSalData = new KDEData();
        SetSalData( pSalData );
        pSalData->pInstance_ = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        return pInstance;
    }
}
<|endoftext|>


<commit_before>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

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

cphVB 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 Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cphvb.h>
#include "array.h"
#include <cmath>
#include <cstring>
#include <vector>
#include <cassert>
#include "pgrid.h"

static cphvb_error find_largest_chunk(const cphvb_instruction *inst,
                                      std::vector<cphvb_array>& chunks,
                                      std::vector<array_ext>& chunks_ext,
                                      const cphvb_intp start_coord[],
                                      const cphvb_intp end_coord[],
                                      cphvb_intp new_coord[])
{
    cphvb_intp first_chunk = chunks.size();
    cphvb_intp ndim = inst->operand[0]->ndim;
    cphvb_intp shape[CPHVB_MAXDIM];
    for(cphvb_intp d=0; d < ndim; ++d)
        shape[d] = -1;

    cphvb_intp nop = cphvb_operands_in_instruction(inst);
    for(cphvb_intp o=0; o < nop; ++o)
    {
        const cphvb_array *ary = inst->operand[o];
        if(ary == NULL)//Operand is a constant
        {
            //Save a dummy chunk
            cphvb_array chunk;
            array_ext chunk_ext;
            chunks.push_back(chunk);
            chunks_ext.push_back(chunk_ext);
            continue;
        }

        //Compute the global offset based on the dimension offset
        cphvb_intp offset = ary->start;
        for(cphvb_intp d=0; d < ndim; ++d)
            offset += start_coord[d] * ary->stride[d];

        //Compute total array base size
        cphvb_intp totalsize = cphvb_nelements(cphvb_base_array(ary)->ndim,
                                               cphvb_base_array(ary)->shape);

        //Compute local array base size for nrank-1
        cphvb_intp localsize = totalsize / pgrid_worldsize;

        //Find rank and local offset
        cphvb_intp rank;
        if(localsize > 0)
        {
            rank = offset / localsize;
            offset = offset % localsize;
        }
        else
        {
            rank = pgrid_worldsize-1;
        }

        //Convert localsize to be specific for this rank
        if(rank == pgrid_worldsize-1)
           localsize = totalsize / pgrid_worldsize + totalsize % pgrid_worldsize;

        //Find the largest possible shape
        for(cphvb_intp d=0; d < ndim; ++d)
        {
            cphvb_intp max_dim = end_coord[d] - start_coord[d];
            cphvb_intp dim = max_dim;
            if(ary->stride[d] > 0)
                dim = (cphvb_intp) ceil((localsize - offset) / (double) ary->stride[d]);
            if(dim > max_dim)
                dim = max_dim;
            if(shape[d] == -1 || dim < shape[d])//We only save the smallest shape
                shape[d] = dim;
        }
        //Save the chunk
        cphvb_array chunk;
        array_ext chunk_ext;
        chunk_ext.rank = rank;
        chunk.base     = array_get_local(cphvb_base_array(ary));
        chunk.type     = ary->type;
        chunk.ndim     = ary->ndim;
        chunk.data     = NULL;
        chunk.start    = offset;
        memcpy(chunk.stride, ary->stride, ary->ndim * sizeof(cphvb_intp));
        chunks.push_back(chunk);
        chunks_ext.push_back(chunk_ext);
    }

    //Save the largest possible shape found to all chunks
    for(cphvb_intp d=0; d < ndim; ++d)
    {
        assert(shape[d] > 0);
        for(cphvb_intp o=0; o < nop; ++o)
            chunks[first_chunk+o].shape[d] = shape[d];
    }

    //Update coord
    for(cphvb_intp d=0; d < ndim; ++d)
        new_coord[d] = start_coord[d] + shape[d];

    return CPHVB_SUCCESS;
}

static cphvb_error get_chunks(const cphvb_instruction *inst,
                              std::vector<cphvb_array>& chunks,
                              std::vector<array_ext>& chunks_ext,
                              const cphvb_intp start_coord[],
                              const cphvb_intp end_coord[])
{
    cphvb_intp ndim = inst->operand[0]->ndim;
    cphvb_intp new_start_coord[CPHVB_MAXDIM];
    cphvb_error err;

    //We are finished when one of the coordinates are out of bound
    for(cphvb_intp d=0; d < ndim; ++d)
        if(start_coord[d] >= end_coord[d])
            return CPHVB_SUCCESS;

    if((err = find_largest_chunk(inst, chunks, chunks_ext,
              start_coord, end_coord, new_start_coord)) != CPHVB_SUCCESS)
        return err;

    cphvb_intp corner[CPHVB_MAXDIM];
    memset(corner, 0, ndim * sizeof(cphvb_intp));
    ++corner[ndim-1];
    while(1)//Lets start a new chunk search at each corner of the current chunk.
    {
        //Find start and end coord based on the current corner
        cphvb_intp start[CPHVB_MAXDIM];
        cphvb_intp end[CPHVB_MAXDIM];
        for(cphvb_intp d=0; d < ndim; ++d)
        {
            if(corner[d] == 1)
            {
                start[d] = new_start_coord[d];
                end[d] = end_coord[d];
            }
            else
            {
                start[d] = start_coord[d];
                end[d] = new_start_coord[d];
            }
        }

        //Goto the next start cood
        if((err = get_chunks(inst, chunks, chunks_ext, start, end)) != CPHVB_SUCCESS)
            return err;

        //Go to next corner
        for(cphvb_intp d=ndim-1; d >= 0; --d)
        {
            if(++corner[d] > 1)
            {
                corner[d] = 0;
                if(d == 0)
                    return CPHVB_SUCCESS;
            }
            else
                break;
        }
    }
    return CPHVB_ERROR;//This shouldn't be possible
}

/* Creates a list of loca array chunks that enables local
 * execution of the instruction
 *
 * @inst The instruction to map
 * @chunks The output chunks
 * @chunks_ext The output chunks extention
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error mapping_chunks(const cphvb_instruction *inst,
                           std::vector<cphvb_array>& chunks,
                           std::vector<array_ext>& chunks_ext)
{
    cphvb_intp coord[CPHVB_MAXDIM];
    memset(coord, 0, inst->operand[0]->ndim * sizeof(cphvb_intp));
    return get_chunks(inst, chunks, chunks_ext, coord, inst->operand[0]->shape);
}

<commit_msg>Fixed a BUG where the rank would overspill because the local size of the last process may be larger then the 'localsize'<commit_after>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

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

cphVB 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 Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cphvb.h>
#include "array.h"
#include <cmath>
#include <cstring>
#include <vector>
#include <cassert>
#include "pgrid.h"

static cphvb_error find_largest_chunk(const cphvb_instruction *inst,
                                      std::vector<cphvb_array>& chunks,
                                      std::vector<array_ext>& chunks_ext,
                                      const cphvb_intp start_coord[],
                                      const cphvb_intp end_coord[],
                                      cphvb_intp new_coord[])
{
    cphvb_intp first_chunk = chunks.size();
    cphvb_intp ndim = inst->operand[0]->ndim;
    cphvb_intp shape[CPHVB_MAXDIM];
    for(cphvb_intp d=0; d < ndim; ++d)
        shape[d] = -1;

    cphvb_intp nop = cphvb_operands_in_instruction(inst);
    for(cphvb_intp o=0; o < nop; ++o)
    {
        const cphvb_array *ary = inst->operand[o];
        if(ary == NULL)//Operand is a constant
        {
            //Save a dummy chunk
            cphvb_array chunk;
            array_ext chunk_ext;
            chunks.push_back(chunk);
            chunks_ext.push_back(chunk_ext);
            continue;
        }

        //Compute the global offset based on the dimension offset
        cphvb_intp offset = ary->start;
        for(cphvb_intp d=0; d < ndim; ++d)
            offset += start_coord[d] * ary->stride[d];

        //Compute total array base size
        cphvb_intp totalsize = cphvb_nelements(cphvb_base_array(ary)->ndim,
                                               cphvb_base_array(ary)->shape);

        //Compute local array base size for nrank-1
        cphvb_intp localsize = totalsize / pgrid_worldsize;

        //Find rank and local offset
        cphvb_intp rank;
        if(localsize > 0)
        {
            rank = offset / localsize;
            //There may be rank overspill because the local size of
            //the last process may be larger then the 'localsize'
            if(rank > pgrid_worldsize-1)
                rank = pgrid_worldsize-1;
            offset -= rank * localsize;
        }
        else
            rank = pgrid_worldsize-1;

        //Convert localsize to be specific for this rank
        if(rank == pgrid_worldsize-1)
           localsize = totalsize / pgrid_worldsize + totalsize % pgrid_worldsize;

        //Find the largest possible shape
        for(cphvb_intp d=0; d < ndim; ++d)
        {
            cphvb_intp max_dim = end_coord[d] - start_coord[d];
            cphvb_intp dim = max_dim;
            if(ary->stride[d] > 0)
                dim = (cphvb_intp) ceil((localsize - offset) / (double) ary->stride[d]);
            if(dim > max_dim)
                dim = max_dim;
            if(shape[d] == -1 || dim < shape[d])//We only save the smallest shape
                shape[d] = dim;
        }
        //Save the chunk
        cphvb_array chunk;
        array_ext chunk_ext;
        chunk_ext.rank = rank;
        chunk.base     = array_get_local(cphvb_base_array(ary));
        chunk.type     = ary->type;
        chunk.ndim     = ary->ndim;
        chunk.data     = NULL;
        chunk.start    = offset;
        memcpy(chunk.stride, ary->stride, ary->ndim * sizeof(cphvb_intp));
        chunks.push_back(chunk);
        chunks_ext.push_back(chunk_ext);
        assert(0 <= rank && rank < pgrid_worldsize);
    }

    //Save the largest possible shape found to all chunks
    for(cphvb_intp d=0; d < ndim; ++d)
    {
        assert(shape[d] > 0);
        for(cphvb_intp o=0; o < nop; ++o)
            chunks[first_chunk+o].shape[d] = shape[d];
    }

    //Update coord
    for(cphvb_intp d=0; d < ndim; ++d)
        new_coord[d] = start_coord[d] + shape[d];

    return CPHVB_SUCCESS;
}

static cphvb_error get_chunks(const cphvb_instruction *inst,
                              std::vector<cphvb_array>& chunks,
                              std::vector<array_ext>& chunks_ext,
                              const cphvb_intp start_coord[],
                              const cphvb_intp end_coord[])
{
    cphvb_intp ndim = inst->operand[0]->ndim;
    cphvb_intp new_start_coord[CPHVB_MAXDIM];
    cphvb_error err;

    //We are finished when one of the coordinates are out of bound
    for(cphvb_intp d=0; d < ndim; ++d)
        if(start_coord[d] >= end_coord[d])
            return CPHVB_SUCCESS;

    if((err = find_largest_chunk(inst, chunks, chunks_ext,
              start_coord, end_coord, new_start_coord)) != CPHVB_SUCCESS)
        return err;

    cphvb_intp corner[CPHVB_MAXDIM];
    memset(corner, 0, ndim * sizeof(cphvb_intp));
    ++corner[ndim-1];
    while(1)//Lets start a new chunk search at each corner of the current chunk.
    {
        //Find start and end coord based on the current corner
        cphvb_intp start[CPHVB_MAXDIM];
        cphvb_intp end[CPHVB_MAXDIM];
        for(cphvb_intp d=0; d < ndim; ++d)
        {
            if(corner[d] == 1)
            {
                start[d] = new_start_coord[d];
                end[d] = end_coord[d];
            }
            else
            {
                start[d] = start_coord[d];
                end[d] = new_start_coord[d];
            }
        }

        //Goto the next start cood
        if((err = get_chunks(inst, chunks, chunks_ext, start, end)) != CPHVB_SUCCESS)
            return err;

        //Go to next corner
        for(cphvb_intp d=ndim-1; d >= 0; --d)
        {
            if(++corner[d] > 1)
            {
                corner[d] = 0;
                if(d == 0)
                    return CPHVB_SUCCESS;
            }
            else
                break;
        }
    }
    return CPHVB_ERROR;//This shouldn't be possible
}

/* Creates a list of loca array chunks that enables local
 * execution of the instruction
 *
 * @inst The instruction to map
 * @chunks The output chunks
 * @chunks_ext The output chunks extention
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error mapping_chunks(const cphvb_instruction *inst,
                           std::vector<cphvb_array>& chunks,
                           std::vector<array_ext>& chunks_ext)
{
    cphvb_intp coord[CPHVB_MAXDIM];
    memset(coord, 0, inst->operand[0]->ndim * sizeof(cphvb_intp));
    return get_chunks(inst, chunks, chunks_ext, coord, inst->operand[0]->shape);
}

<|endoftext|>


<commit_before>#pragma once

#include <functional>

#include <boost/asio.hpp>

#include <rapidjson/document.h>

#include <swarm/logger.h>
#include <swarm/urlfetcher/boost_event_loop.hpp>
#include <swarm/urlfetcher/stream.hpp>
#include <swarm/urlfetcher/url_fetcher.hpp>

#include "log.hpp"
#include "response/extract.hpp"
#include "request/method.hpp"

namespace elasticsearch {

struct urlfetcher_t {
    typedef boost::asio::io_service loop_type;

    typedef ioremap::swarm::url url_type;
    typedef ioremap::swarm::simple_stream stream_type;
    typedef ioremap::swarm::url_fetcher::request request_type;
    typedef ioremap::swarm::url_fetcher::response response_type;

    loop_type& loop;
    loop_type::work work;
    ioremap::swarm::logger logger;
    ioremap::swarm::boost_event_loop loop_wrapper;
    ioremap::swarm::url_fetcher manager;

    urlfetcher_t(loop_type& loop) :
        loop(loop),
        work(loop),
        loop_wrapper(loop),
        manager(loop_wrapper, logger)
    {}
};

template<class Action>
struct callback {
    typedef std::function<void(typename Action::result_type)> type;
};

template<class Action>
class response_handler_t {
public:
    typedef blackhole::synchronized<blackhole::logger_base_t> logger_type;

    typedef Action action_type;
    typedef typename action_type::result_type result_type;
    typedef typename action_type::response_type response_type;
    typedef typename callback<action_type>::type callback_type;

private:
    callback_type callback;
    logger_type& log;

public:
    response_handler_t(callback_type callback, logger_type& log) :
        callback(callback),
        log(log)
    {}

    void operator()(const urlfetcher_t::response_type& response,
                    const std::string& data,
                    const boost::system::error_code& ec) {
        const int status = response.code();

        LOG(log, "response received from '%s' [%d] (%s): %s",
            response.url().to_string(), status, ec.value(), data);

        if (ec) {
            LOG(log, "request failed with error: %s", ec.message());
            callback(result_type(ec));
            return;
        }

        rapidjson::Document doc;
        doc.Parse<0>(data.c_str());
        if (doc.HasParseError()) {
            LOG(log, "request failed with error: %s", doc.GetParseError());
            callback(result_type(boost::system::errc::make_error_code(
                boost::system::errc::bad_message)));
            return;
        }

        if (has_error(status)) {
            const rapidjson::Value& error = doc["error"];
            LOG(log, "request failed with error: %s",
                error.IsString() ? error.GetString() : "unknown");

            callback(result_type(boost::system::errc::make_error_code(
                boost::system::errc::io_error)));
            return;
        }

        try {
            callback(result_type(
                extractor_t<response_type>::extract(doc)
            ));
        } catch (const std::exception& err) {
            LOG(log, "response parsing failed: %s", err.what());
            callback(result_type(boost::system::errc::make_error_code(
                    boost::system::errc::io_error)));
        }
    }

private:
    static inline bool has_error(int status) {
        const int type = status / 100;
        return type == 4 || type == 5;
    }
};

class http_connection_t {
public:
    typedef blackhole::synchronized<blackhole::logger_base_t> logger_type;

    typedef boost::asio::io_service loop_type;
    typedef boost::asio::ip::tcp protocol_type;
    typedef protocol_type::endpoint endpoint_type;

private:
    endpoint_type endpoint_;
    urlfetcher_t urlfetcher;
    logger_type& log;

public:
    http_connection_t(endpoint_type endpoint, loop_type& loop, logger_type& log) :
        endpoint_(endpoint),
        urlfetcher(loop),
        log(log)
    {
        //!@todo: Make configurable.
        urlfetcher.manager.set_total_limit(20);
    }

    endpoint_type endpoint() const {
        return endpoint_;
    }

    std::string address() const {
        if (endpoint_.address().is_v6()) {
            std::string result;
            result.push_back('[');
            result.append(endpoint().address().to_string());
            result.push_back(']');
            return result;
        }

        return endpoint_.address().to_string();
    }

    std::uint16_t port() const {
        return endpoint_.port();
    }

    template<class Action>
    void perform(Action&& action, typename callback<Action>::type callback) {
        urlfetcher_t::url_type url;
        url.set_scheme("http");
        url.set_host(address());
        url.set_port(port());
        url.set_path(action.path());

        urlfetcher_t::request_type request;
        request.set_url(url);
        request.headers().set_keep_alive();

        response_handler_t<Action> handler(callback, log);
        std::shared_ptr<urlfetcher_t::stream_type> stream = std::move(
            urlfetcher_t::stream_type::create(handler)
        );
        LOG(log, "requesting '%s' ...", request.url().to_string());
        perform(std::move(action), std::move(request), std::move(stream));
    }

private:
    template<class Action>
    typename std::enable_if<
        Action::method_value == request::method_t::get
    >::type
    perform(Action&&,
            urlfetcher_t::request_type&& request,
            std::shared_ptr<urlfetcher_t::stream_type>&& stream) {
        LOG(log, "method: get");
        urlfetcher.manager.get(stream, std::move(request));
    }

    template<class Action>
    typename std::enable_if<
        Action::method_value == request::method_t::post
    >::type
    perform(Action&& action,
            urlfetcher_t::request_type&& request,
            std::shared_ptr<urlfetcher_t::stream_type>&& stream) {
        LOG(log, "method: post");
        urlfetcher.manager.post(stream, std::move(request), action.body());
    }
};

} // namespace elasticsearch
<commit_msg>[Elasticsearch] Drop useless messages.<commit_after>#pragma once

#include <functional>

#include <boost/asio.hpp>

#include <rapidjson/document.h>

#include <swarm/logger.h>
#include <swarm/urlfetcher/boost_event_loop.hpp>
#include <swarm/urlfetcher/stream.hpp>
#include <swarm/urlfetcher/url_fetcher.hpp>

#include "log.hpp"
#include "response/extract.hpp"
#include "request/method.hpp"

namespace elasticsearch {

struct urlfetcher_t {
    typedef boost::asio::io_service loop_type;

    typedef ioremap::swarm::url url_type;
    typedef ioremap::swarm::simple_stream stream_type;
    typedef ioremap::swarm::url_fetcher::request request_type;
    typedef ioremap::swarm::url_fetcher::response response_type;

    loop_type& loop;
    loop_type::work work;
    ioremap::swarm::logger logger;
    ioremap::swarm::boost_event_loop loop_wrapper;
    ioremap::swarm::url_fetcher manager;

    urlfetcher_t(loop_type& loop) :
        loop(loop),
        work(loop),
        loop_wrapper(loop),
        manager(loop_wrapper, logger)
    {}
};

template<class Action>
struct callback {
    typedef std::function<void(typename Action::result_type)> type;
};

template<class Action>
class response_handler_t {
public:
    typedef blackhole::synchronized<blackhole::logger_base_t> logger_type;

    typedef Action action_type;
    typedef typename action_type::result_type result_type;
    typedef typename action_type::response_type response_type;
    typedef typename callback<action_type>::type callback_type;

private:
    callback_type callback;
    logger_type& log;

public:
    response_handler_t(callback_type callback, logger_type& log) :
        callback(callback),
        log(log)
    {}

    void operator()(const urlfetcher_t::response_type& response,
                    const std::string& data,
                    const boost::system::error_code& ec) {
        const int status = response.code();

        LOG(log, "response received from '%s' [%d] (%s): %s",
            response.url().to_string(), status, ec.value(), data);

        if (ec) {
            LOG(log, "request failed with error: %s", ec.message());
            callback(result_type(ec));
            return;
        }

        rapidjson::Document doc;
        doc.Parse<0>(data.c_str());
        if (doc.HasParseError()) {
            LOG(log, "request failed with error: %s", doc.GetParseError());
            callback(result_type(boost::system::errc::make_error_code(
                boost::system::errc::bad_message)));
            return;
        }

        if (has_error(status)) {
            const rapidjson::Value& error = doc["error"];
            LOG(log, "request failed with error: %s",
                error.IsString() ? error.GetString() : "unknown");

            callback(result_type(boost::system::errc::make_error_code(
                boost::system::errc::io_error)));
            return;
        }

        try {
            callback(result_type(
                extractor_t<response_type>::extract(doc)
            ));
        } catch (const std::exception& err) {
            LOG(log, "response parsing failed: %s", err.what());
            callback(result_type(boost::system::errc::make_error_code(
                    boost::system::errc::io_error)));
        }
    }

private:
    static inline bool has_error(int status) {
        const int type = status / 100;
        return type == 4 || type == 5;
    }
};

class http_connection_t {
public:
    typedef blackhole::synchronized<blackhole::logger_base_t> logger_type;

    typedef boost::asio::io_service loop_type;
    typedef boost::asio::ip::tcp protocol_type;
    typedef protocol_type::endpoint endpoint_type;

private:
    endpoint_type endpoint_;
    urlfetcher_t urlfetcher;
    logger_type& log;

public:
    http_connection_t(endpoint_type endpoint, loop_type& loop, logger_type& log) :
        endpoint_(endpoint),
        urlfetcher(loop),
        log(log)
    {
        //!@todo: Make configurable.
        urlfetcher.manager.set_total_limit(20);
    }

    endpoint_type endpoint() const {
        return endpoint_;
    }

    std::string address() const {
        if (endpoint_.address().is_v6()) {
            std::string result;
            result.push_back('[');
            result.append(endpoint().address().to_string());
            result.push_back(']');
            return result;
        }

        return endpoint_.address().to_string();
    }

    std::uint16_t port() const {
        return endpoint_.port();
    }

    template<class Action>
    void perform(Action&& action, typename callback<Action>::type callback) {
        urlfetcher_t::url_type url;
        url.set_scheme("http");
        url.set_host(address());
        url.set_port(port());
        url.set_path(action.path());

        urlfetcher_t::request_type request;
        request.set_url(url);
        request.headers().set_keep_alive();

        response_handler_t<Action> handler(callback, log);
        std::shared_ptr<urlfetcher_t::stream_type> stream = std::move(
            urlfetcher_t::stream_type::create(handler)
        );
        LOG(log, "requesting '%s' ...", request.url().to_string());
        perform(std::move(action), std::move(request), std::move(stream));
    }

private:
    template<class Action>
    typename std::enable_if<
        Action::method_value == request::method_t::get
    >::type
    perform(Action&&,
            urlfetcher_t::request_type&& request,
            std::shared_ptr<urlfetcher_t::stream_type>&& stream) {
        urlfetcher.manager.get(stream, std::move(request));
    }

    template<class Action>
    typename std::enable_if<
        Action::method_value == request::method_t::post
    >::type
    perform(Action&& action,
            urlfetcher_t::request_type&& request,
            std::shared_ptr<urlfetcher_t::stream_type>&& stream) {
        urlfetcher.manager.post(stream, std::move(request), action.body());
    }
};

} // namespace elasticsearch
<|endoftext|>


<commit_before>/*
 * mainGame.cpp
 *
 *  Created on: Nov 26, 2017
 *      Author: lowji
 */

//created this source file to make the compiler work properly
#include <sstream>
#include <iostream>
#include <string>
#include "Player.h"
#include "ConsoleUI.h"
#include "Card.h"
#include "Deck.h"
#include "Board.h"
//method to determine if a string is an integer
bool isInt(string input){
	//Reference: https://stackoverflow.com/questions/20287186/how-to-check-if-the-input-is-a-valid-integer-without-any-other-chars

	int x; //temporary int variable for checking input validity
	char c; //temporary char variable for checking input validity
	istringstream s(input);

	if (!(s >> x)) {
		return false;
	}

	if (s >> c) {
		return false;
	}

	return true;
}

int main(){

	//set up user interface
  	ConsoleUI* ui = new ConsoleUI();

    ui->welcome();

	string inputTemp;
	inputTemp = ui->input("Input your name: ");
	Player* human = new Player(inputTemp);
	Player* AI = new Player("AI");

	//Preflop
	inputTemp=ui->input("How much do you want the blind to be? ");
	while(!isInt(inputTemp)){
		ui->output("Invalid input. Blind must be an integer.");
		inputTemp=ui->input("How much do you want the blind to be? ");
	}
	const int BLIND=inputTemp;

	ui->output("Your name is "+human->getName());
	ui->output("Your opponent name is "+AI->getName());

	//shuffling(automatic shuffled)
    Deck* deck = new Deck();
	//draw cards
    human->addOne(deck->draw());
	human->addTwo(deck->draw());

	//print user's hand
	ui->output("Print "+ human->getName()+"'s hand");
    (human->getHandOne()).printCard();
    (human->getHandTwo()).printCard();

	//print table: your stack, small blind, big blind, pot(needs to make)
<<<<<<< HEAD
cout<<"print board: "<<endl;
Board* board = new Board(human, AI);
board->printBoard();
=======
    Board* board = new Board(human, AI);

>>>>>>> 5e09d891de898fa80122dd23d0b9e077dbf610fb
	//prompt user decision: raise, bet, check=bet(0), fold

	//Postflop: prompt user, update pot and each player stack size(money), user's decision, draw 3 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//Turn:  prompt user, update pot and each player stack size(money), user's decision, draw 1 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//River: repeat Turn, and go back to preflop...
}

<commit_msg>Solved merge issue<commit_after>/*
 * mainGame.cpp
 *
 *  Created on: Nov 26, 2017
 *      Author: lowji
 */

//created this source file to make the compiler work properly
#include <sstream>
#include <iostream>
#include <string>
#include "Player.h"
#include "ConsoleUI.h"
#include "Card.h"
#include "Deck.h"
#include "Board.h"
//method to determine if a string is an integer
bool isInt(string input){
	//Reference: https://stackoverflow.com/questions/20287186/how-to-check-if-the-input-is-a-valid-integer-without-any-other-chars

	int x; //temporary int variable for checking input validity
	char c; //temporary char variable for checking input validity
	istringstream s(input);

	if (!(s >> x)) {
		return false;
	}

	if (s >> c) {
		return false;
	}

	return true;
}

int main(){

	//set up user interface
  	ConsoleUI* ui = new ConsoleUI();

    ui->welcome();

	string inputTemp;
	inputTemp = ui->input("Input your name: ");
	Player* human = new Player(inputTemp);
	Player* AI = new Player("AI");

	//Preflop
	inputTemp=ui->input("How much do you want the blind to be? ");
	while(!isInt(inputTemp)){
		ui->output("Invalid input. Blind must be an integer.");
		inputTemp=ui->input("How much do you want the blind to be? ");
	}
	const int BLIND=inputTemp;

	ui->output("Your name is "+human->getName());
	ui->output("Your opponent name is "+AI->getName());

	//shuffling(automatic shuffled)
    Deck* deck = new Deck();
	//draw cards
    human->addOne(deck->draw());
	human->addTwo(deck->draw());

	//print user's hand
	ui->output("Print "+ human->getName()+"'s hand");
    (human->getHandOne()).printCard();
    (human->getHandTwo()).printCard();

	//print table: your stack, small blind, big blind, pot(needs to make)

    Board* board = new Board(human, AI);

	//prompt user decision: raise, bet, check=bet(0), fold

	//Postflop: prompt user, update pot and each player stack size(money), user's decision, draw 3 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//Turn:  prompt user, update pot and each player stack size(money), user's decision, draw 1 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//River: repeat Turn, and go back to preflop...
}

<|endoftext|>


<commit_before>{
  {
    mode: "dorian",
    progression: "1,2,1,5,5,2,2,4,5,2",
    origin: "white stripes - little apple blossom"
  },
  {
    mode: "dorian",
    progression: "1,7,4,4",
    origin: "depeche mode - never let me down"
  },
  {
    mode: "minor",
    progression: "1,7,4,6",
    origin: "cure - the figurehead"
  },
  {
    mode: "minor",
    progression: "1,3,6,4",
    origin: "??"
  },
  {
    mode: "minor",
    progression: "1,4,6,4",
    origin: "??"
  },
  {
    mode: "harmonic_minor",
    progression: "1,4,6,5",
    origin: "amy whinehouse - back to black"
  }
}
<commit_msg>added progression for jolene<commit_after>{
  {
    mode: "dorian",
    progression: "1,2,1,5,5,2,2,4,5,2",
    origin: "white stripes - little apple blossom"
  },
  {
    mode: "dorian",
    progression: "1,7,4,4",
    origin: "depeche mode - never let me down"
  },
  {
    mode: "minor",
    progression: "1,7,4,6",
    origin: "cure - the figurehead"
  },
  {
    mode: "minor",
    progression: "1,3,6,4",
    origin: "??"
  },
  {
    mode: "minor",
    progression: "1,4,6,4",
    origin: "??"
  },
  {
    mode: "harmonic_minor",
    progression: "1,4,6,57",
    origin: "amy whinehouse - back to black"
  },
    {
      mode: "minor",
      progression: "1,3,7,1,7,5,1,1",
      origin: "dolly parton - jolene"
    }
}
<|endoftext|>


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

#include "StableHeaders.h"
#include "CameraControllable.h"
#include "EntityComponent/EC_NetworkPosition.h"
#include "SceneEvents.h"
#include "Entity.h"
#include "SceneManager.h"
#include "EC_OgrePlaceable.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EntityComponent/EC_AvatarAppearance.h"
//#include "RexTypes.h"
#include "InputEvents.h"
#include "InputServiceInterface.h"
#include <Ogre.h>

namespace RexLogic
{
    CameraControllable::CameraControllable(Foundation::Framework *fw) :
        framework_(fw)
      , action_event_category_(fw->GetEventManager()->QueryEventCategory("Action"))
      , current_state_(ThirdPerson)
      , firstperson_pitch_(0)
      , firstperson_yaw_(0)
      , drag_pitch_(0)
      , drag_yaw_(0)
    {
        camera_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "default_distance", 20.f);
        camera_min_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "min_distance", 1.f);
        camera_max_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "max_distance", 50.f);

        camera_offset_ = ParseString<Vector3df>(
            framework_->GetDefaultConfig().DeclareSetting("Camera", "third_person_offset", ToString(Vector3df(0, 0, 1.8f))));

        camera_offset_firstperson_ = ParseString<Vector3df>(
            framework_->GetDefaultConfig().DeclareSetting("Camera", "first_person_offset", ToString(Vector3df(0.5f, 0, 0.8f))));

        sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "translation_sensitivity", 25.f);
        zoom_sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "zoom_sensitivity", 0.015f);
        firstperson_sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "mouselook_rotation_sensitivity", 1.3f);

        action_trans_[RexTypes::Actions::MoveForward] = Vector3df::NEGATIVE_UNIT_Z;
        action_trans_[RexTypes::Actions::MoveBackward] = Vector3df::UNIT_Z;
        action_trans_[RexTypes::Actions::MoveLeft] = Vector3df::NEGATIVE_UNIT_X;
        action_trans_[RexTypes::Actions::MoveRight] = Vector3df::UNIT_X;
        action_trans_[RexTypes::Actions::MoveUp] = Vector3df::UNIT_Y;
        action_trans_[RexTypes::Actions::MoveDown] = Vector3df::NEGATIVE_UNIT_Y;

        movement_.x_.rel_ = 0;
        movement_.y_.rel_ = 0;
    }

    void CameraControllable::SetCameraEntity(Scene::EntityPtr camera)
    {
        camera_entity_ = camera;
    }

    bool CameraControllable::HandleSceneEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        //! \todo This is where our user agent model design breaks down. We assume only one controllable entity exists and that it is a target for the camera.
        //!       Should be changed so in some way the target can be changed and is not automatically assigned. -cm
        if (event_id == Scene::Events::EVENT_CONTROLLABLE_ENTITY)
            target_entity_ = checked_static_cast<Scene::Events::EntityEventData*>(data)->entity;

        return false;
    }

    bool CameraControllable::HandleInputEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        if (event_id == Input::Events::INPUTSTATE_THIRDPERSON && current_state_ != ThirdPerson)
        {
            current_state_ = ThirdPerson;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::INPUTSTATE_FIRSTPERSON && current_state_ != FirstPerson)
        {
            current_state_ = FirstPerson;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::INPUTSTATE_FREECAMERA && current_state_ != FreeLook)
        {
            current_state_ = FreeLook;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::SCROLL)
        {
            CameraZoomEvent event_data;
            event_data.entity = camera_entity_.lock();
            event_data.amount = checked_static_cast<Input::Events::SingleAxisMovement*>(data)->z_.rel_;
            if (event_data.entity) // only send the event if we have an existing entity, no point otherwise
                framework_->GetEventManager()->SendEvent(action_event_category_, RexTypes::Actions::Zoom, &event_data);
        }

        if (event_id == Input::Events::MOUSELOOK)
        {
            Input::Events::Movement *m = checked_static_cast <Input::Events::Movement *> (data);

            movement_.x_.rel_ = m->x_.rel_;
            movement_.y_.rel_ = m->y_.rel_;
            movement_.x_.abs_ = m->x_.abs_;
            movement_.y_.abs_ = m->y_.abs_;
        }

        return false;
    }

    bool CameraControllable::HandleActionEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        if (event_id == RexTypes::Actions::Zoom)
        {
            Real value = checked_static_cast<CameraZoomEvent*>(data)->amount;

            camera_distance_ -= (value * zoom_sensitivity_);
            camera_distance_ = clamp(camera_distance_, camera_min_distance_, camera_max_distance_);
        }

        if (current_state_ == FreeLook)
        {
            ActionTransMap::const_iterator it = action_trans_.find(event_id);
            if (it != action_trans_.end())
            {
                // start movement
                const Vector3df &vec = it->second;
                free_translation_.x = ( vec.x == 0 ) ? free_translation_.x : vec.x;
                free_translation_.y = ( vec.y == 0 ) ? free_translation_.y : vec.y;
                free_translation_.z = ( vec.z == 0 ) ? free_translation_.z : vec.z;
            }
            it = action_trans_.find(event_id - 1);
            if (it != action_trans_.end())
            {
                // stop movement
                const Vector3df &vec = it->second;
                free_translation_.x = ( vec.x == 0 ) ? free_translation_.x : 0;
                free_translation_.y = ( vec.y == 0 ) ? free_translation_.y : 0;
                free_translation_.z = ( vec.z == 0 ) ? free_translation_.z : 0;
            }
            normalized_free_translation_ = free_translation_;
            normalized_free_translation_.normalize();
        }

        return false;
    }

    void CameraControllable::AddTime(f64 frametime)
    {
        drag_yaw_ = static_cast<Real>(movement_.x_.rel_) * -0.005f;
        drag_pitch_ = static_cast<Real>(movement_.y_.rel_) * -0.005f;
        movement_.x_.rel_ = 0;
        movement_.y_.rel_ = 0;

        boost::shared_ptr<OgreRenderer::Renderer> renderer = framework_->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
        Scene::EntityPtr target = target_entity_.lock();
        Scene::EntityPtr camera = camera_entity_.lock();

        if (renderer && target && camera)
        {
            OgreRenderer::EC_OgrePlaceable *camera_placeable =
                checked_static_cast<OgreRenderer::EC_OgrePlaceable*>(camera->GetComponent(OgreRenderer::EC_OgrePlaceable::NameStatic()).get());

            // for smoothness, we apparently need to get rotation from network position and position from placeable. Go figure. -cm
            EC_NetworkPosition *netpos = checked_static_cast<EC_NetworkPosition*>(target->GetComponent(EC_NetworkPosition::NameStatic()).get());
            OgreRenderer::EC_OgrePlaceable *placeable =
                checked_static_cast<OgreRenderer::EC_OgrePlaceable*>(target->GetComponent(OgreRenderer::EC_OgrePlaceable::NameStatic()).get());
            if (netpos && placeable)
            {
                Vector3df avatar_pos = placeable->GetPosition();
                Quaternion avatar_orientation = netpos->orientation_;

                if (current_state_ == FirstPerson || current_state_ == ThirdPerson)
                {
                    // this is mostly for third person camera, but also needed by first person camera since it sets proper initial orientation for the camera
                    Vector3df pos = avatar_pos;
                    pos += (avatar_orientation * Vector3df::NEGATIVE_UNIT_X * camera_distance_);
                    pos += (avatar_orientation * camera_offset_);
                    camera_placeable->SetPosition(pos);

                    Vector3df lookat = avatar_pos + avatar_orientation * camera_offset_;
                    camera_placeable->LookAt(lookat);
                }

                if (current_state_ == FirstPerson)
                {
                    bool fallback = true;
                    // Try to use head bone from target entity to get the first person camera position
                    Foundation::ComponentPtr mesh_ptr = target->GetComponent(OgreRenderer::EC_OgreMesh::NameStatic());
                    Foundation::ComponentPtr appearance_ptr = target->GetComponent(EC_AvatarAppearance::NameStatic());
                    if (mesh_ptr && appearance_ptr)
                    {
                        OgreRenderer::EC_OgreMesh& mesh = *checked_static_cast<OgreRenderer::EC_OgreMesh*>(mesh_ptr.get());
                        EC_AvatarAppearance& appearance = *checked_static_cast<EC_AvatarAppearance*>(appearance_ptr.get());
                        Ogre::Entity* ent = mesh.GetEntity();
                        if (ent)
                        {
                            Ogre::SkeletonInstance* skel = ent->getSkeleton();

                            std::string view_bone_name;
                            Real adjustheight = mesh.GetAdjustPosition().z;

                            if (appearance.HasProperty("viewbone"))
                            {
                                // This bone property is exclusively for view tracking & assumed to be correct position, no offset
                                view_bone_name = appearance.GetProperty("viewbone");
                            }
                            else if (appearance.HasProperty("headbone"))
                            {
                                view_bone_name = appearance.GetProperty("headbone");
                                // The biped head bone is anchored at the neck usually. Therefore a guessed fixed offset is needed,
                                // which is not preferable, but necessary
                                adjustheight += 0.15;
                            }

                            if (!view_bone_name.empty())
                            {
                                if (skel && skel->hasBone(view_bone_name))
                                {
                                    // Hack: force Ogre to update skeleton with current animation state, even if avatar invisible
                                    if (ent->getAllAnimationStates())
                                        skel->setAnimationState(*ent->getAllAnimationStates());

                                    Ogre::Bone* bone = skel->getBone(view_bone_name);
                                    Ogre::Vector3 headpos = bone->_getDerivedPosition();
                                    Vector3df ourheadpos(-headpos.z + 0.5f, -headpos.x, headpos.y + adjustheight);
                                    RexTypes::Vector3 campos = avatar_pos + (avatar_orientation * ourheadpos);
                                    camera_placeable->SetPosition(campos);
                                    fallback = false;
                                }
                            }
                        }
                    }
                    // Fallback using fixed position
                    if (fallback)
                    {
                        RexTypes::Vector3 campos = avatar_pos + (avatar_orientation * camera_offset_firstperson_);
                        camera_placeable->SetPosition(campos);
                    }

                    // update camera pitch
                    if (drag_pitch_ != 0)
                    {
                        firstperson_pitch_ += drag_pitch_ * firstperson_sensitivity_;
                        firstperson_pitch_ = clamp(firstperson_pitch_, -HALF_PI, HALF_PI);
                    }
                    camera_placeable->Pitch(firstperson_pitch_);
                }

                if (current_state_ == FreeLook)
                {
                    const float trans_dt = (float)frametime * sensitivity_;

                    RexTypes::Vector3 pos = camera_placeable->GetPosition();
                    pos += camera_placeable->GetOrientation() * normalized_free_translation_ * trans_dt;
                    camera_placeable->SetPosition(pos);

                    camera_placeable->Pitch(drag_pitch_ * firstperson_sensitivity_);
                    camera_placeable->Yaw(drag_yaw_ * firstperson_sensitivity_);
                }
            }
        }

        // switch between first and third person modes, depending on how close we are to the avatar
        switch (current_state_)
        {
        case FirstPerson:
            {
                if (camera_distance_ != camera_min_distance_)
                {
                    current_state_ = ThirdPerson;
                    event_category_id_t event_category = framework_->GetEventManager()->QueryEventCategory("Input");
                    framework_->GetEventManager()->SendEvent(event_category, Input::Events::INPUTSTATE_THIRDPERSON, 0);

                    firstperson_pitch_ = 0.0f;
                }
                break;
            }
        case ThirdPerson:
            {
                if (camera_distance_ == camera_min_distance_)
                {
                    event_category_id_t event_category = framework_->GetEventManager()->QueryEventCategory("Input");
                    framework_->GetEventManager()->SendEvent(event_category, Input::Events::INPUTSTATE_FIRSTPERSON, 0);
                    current_state_ = FirstPerson;

                    firstperson_pitch_ = 0.0f;
                }
                break;
            }
		}
    }

	//experimental for py api
	void CameraControllable::SetYawPitch(Real newyaw, Real newpitch)
	{
		firstperson_yaw_ = newyaw;
		firstperson_pitch_ = newpitch;
	}
}

<commit_msg>Default camera distance changed to 10.<commit_after>
// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "CameraControllable.h"
#include "EntityComponent/EC_NetworkPosition.h"
#include "SceneEvents.h"
#include "Entity.h"
#include "SceneManager.h"
#include "EC_OgrePlaceable.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EntityComponent/EC_AvatarAppearance.h"
//#include "RexTypes.h"
#include "InputEvents.h"
#include "InputServiceInterface.h"
#include <Ogre.h>

namespace RexLogic
{
    CameraControllable::CameraControllable(Foundation::Framework *fw) :
        framework_(fw)
      , action_event_category_(fw->GetEventManager()->QueryEventCategory("Action"))
      , current_state_(ThirdPerson)
      , firstperson_pitch_(0)
      , firstperson_yaw_(0)
      , drag_pitch_(0)
      , drag_yaw_(0)
    {
        camera_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "default_distance", 10.f);
        camera_min_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "min_distance", 1.f);
        camera_max_distance_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "max_distance", 50.f);

        camera_offset_ = ParseString<Vector3df>(
            framework_->GetDefaultConfig().DeclareSetting("Camera", "third_person_offset", ToString(Vector3df(0, 0, 1.8f))));

        camera_offset_firstperson_ = ParseString<Vector3df>(
            framework_->GetDefaultConfig().DeclareSetting("Camera", "first_person_offset", ToString(Vector3df(0.5f, 0, 0.8f))));

        sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "translation_sensitivity", 25.f);
        zoom_sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "zoom_sensitivity", 0.015f);
        firstperson_sensitivity_ = framework_->GetDefaultConfig().DeclareSetting("Camera", "mouselook_rotation_sensitivity", 1.3f);

        action_trans_[RexTypes::Actions::MoveForward] = Vector3df::NEGATIVE_UNIT_Z;
        action_trans_[RexTypes::Actions::MoveBackward] = Vector3df::UNIT_Z;
        action_trans_[RexTypes::Actions::MoveLeft] = Vector3df::NEGATIVE_UNIT_X;
        action_trans_[RexTypes::Actions::MoveRight] = Vector3df::UNIT_X;
        action_trans_[RexTypes::Actions::MoveUp] = Vector3df::UNIT_Y;
        action_trans_[RexTypes::Actions::MoveDown] = Vector3df::NEGATIVE_UNIT_Y;

        movement_.x_.rel_ = 0;
        movement_.y_.rel_ = 0;
    }

    void CameraControllable::SetCameraEntity(Scene::EntityPtr camera)
    {
        camera_entity_ = camera;
    }

    bool CameraControllable::HandleSceneEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        //! \todo This is where our user agent model design breaks down. We assume only one controllable entity exists and that it is a target for the camera.
        //!       Should be changed so in some way the target can be changed and is not automatically assigned. -cm
        if (event_id == Scene::Events::EVENT_CONTROLLABLE_ENTITY)
            target_entity_ = checked_static_cast<Scene::Events::EntityEventData*>(data)->entity;

        return false;
    }

    bool CameraControllable::HandleInputEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        if (event_id == Input::Events::INPUTSTATE_THIRDPERSON && current_state_ != ThirdPerson)
        {
            current_state_ = ThirdPerson;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::INPUTSTATE_FIRSTPERSON && current_state_ != FirstPerson)
        {
            current_state_ = FirstPerson;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::INPUTSTATE_FREECAMERA && current_state_ != FreeLook)
        {
            current_state_ = FreeLook;
            firstperson_pitch_ = 0.0f;
        }

        if (event_id == Input::Events::SCROLL)
        {
            CameraZoomEvent event_data;
            event_data.entity = camera_entity_.lock();
            event_data.amount = checked_static_cast<Input::Events::SingleAxisMovement*>(data)->z_.rel_;
            if (event_data.entity) // only send the event if we have an existing entity, no point otherwise
                framework_->GetEventManager()->SendEvent(action_event_category_, RexTypes::Actions::Zoom, &event_data);
        }

        if (event_id == Input::Events::MOUSELOOK)
        {
            Input::Events::Movement *m = checked_static_cast <Input::Events::Movement *> (data);

            movement_.x_.rel_ = m->x_.rel_;
            movement_.y_.rel_ = m->y_.rel_;
            movement_.x_.abs_ = m->x_.abs_;
            movement_.y_.abs_ = m->y_.abs_;
        }

        return false;
    }

    bool CameraControllable::HandleActionEvent(event_id_t event_id, Foundation::EventDataInterface* data)
    {
        if (event_id == RexTypes::Actions::Zoom)
        {
            Real value = checked_static_cast<CameraZoomEvent*>(data)->amount;

            camera_distance_ -= (value * zoom_sensitivity_);
            camera_distance_ = clamp(camera_distance_, camera_min_distance_, camera_max_distance_);
        }

        if (current_state_ == FreeLook)
        {
            ActionTransMap::const_iterator it = action_trans_.find(event_id);
            if (it != action_trans_.end())
            {
                // start movement
                const Vector3df &vec = it->second;
                free_translation_.x = ( vec.x == 0 ) ? free_translation_.x : vec.x;
                free_translation_.y = ( vec.y == 0 ) ? free_translation_.y : vec.y;
                free_translation_.z = ( vec.z == 0 ) ? free_translation_.z : vec.z;
            }
            it = action_trans_.find(event_id - 1);
            if (it != action_trans_.end())
            {
                // stop movement
                const Vector3df &vec = it->second;
                free_translation_.x = ( vec.x == 0 ) ? free_translation_.x : 0;
                free_translation_.y = ( vec.y == 0 ) ? free_translation_.y : 0;
                free_translation_.z = ( vec.z == 0 ) ? free_translation_.z : 0;
            }
            normalized_free_translation_ = free_translation_;
            normalized_free_translation_.normalize();
        }

        return false;
    }

    void CameraControllable::AddTime(f64 frametime)
    {
        drag_yaw_ = static_cast<Real>(movement_.x_.rel_) * -0.005f;
        drag_pitch_ = static_cast<Real>(movement_.y_.rel_) * -0.005f;
        movement_.x_.rel_ = 0;
        movement_.y_.rel_ = 0;

        boost::shared_ptr<OgreRenderer::Renderer> renderer = framework_->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
        Scene::EntityPtr target = target_entity_.lock();
        Scene::EntityPtr camera = camera_entity_.lock();

        if (renderer && target && camera)
        {
            OgreRenderer::EC_OgrePlaceable *camera_placeable =
                checked_static_cast<OgreRenderer::EC_OgrePlaceable*>(camera->GetComponent(OgreRenderer::EC_OgrePlaceable::NameStatic()).get());

            // for smoothness, we apparently need to get rotation from network position and position from placeable. Go figure. -cm
            EC_NetworkPosition *netpos = checked_static_cast<EC_NetworkPosition*>(target->GetComponent(EC_NetworkPosition::NameStatic()).get());
            OgreRenderer::EC_OgrePlaceable *placeable =
                checked_static_cast<OgreRenderer::EC_OgrePlaceable*>(target->GetComponent(OgreRenderer::EC_OgrePlaceable::NameStatic()).get());
            if (netpos && placeable)
            {
                Vector3df avatar_pos = placeable->GetPosition();
                Quaternion avatar_orientation = netpos->orientation_;

                if (current_state_ == FirstPerson || current_state_ == ThirdPerson)
                {
                    // this is mostly for third person camera, but also needed by first person camera since it sets proper initial orientation for the camera
                    Vector3df pos = avatar_pos;
                    pos += (avatar_orientation * Vector3df::NEGATIVE_UNIT_X * camera_distance_);
                    pos += (avatar_orientation * camera_offset_);
                    camera_placeable->SetPosition(pos);

                    Vector3df lookat = avatar_pos + avatar_orientation * camera_offset_;
                    camera_placeable->LookAt(lookat);
                }

                if (current_state_ == FirstPerson)
                {
                    bool fallback = true;
                    // Try to use head bone from target entity to get the first person camera position
                    Foundation::ComponentPtr mesh_ptr = target->GetComponent(OgreRenderer::EC_OgreMesh::NameStatic());
                    Foundation::ComponentPtr appearance_ptr = target->GetComponent(EC_AvatarAppearance::NameStatic());
                    if (mesh_ptr && appearance_ptr)
                    {
                        OgreRenderer::EC_OgreMesh& mesh = *checked_static_cast<OgreRenderer::EC_OgreMesh*>(mesh_ptr.get());
                        EC_AvatarAppearance& appearance = *checked_static_cast<EC_AvatarAppearance*>(appearance_ptr.get());
                        Ogre::Entity* ent = mesh.GetEntity();
                        if (ent)
                        {
                            Ogre::SkeletonInstance* skel = ent->getSkeleton();

                            std::string view_bone_name;
                            Real adjustheight = mesh.GetAdjustPosition().z;

                            if (appearance.HasProperty("viewbone"))
                            {
                                // This bone property is exclusively for view tracking & assumed to be correct position, no offset
                                view_bone_name = appearance.GetProperty("viewbone");
                            }
                            else if (appearance.HasProperty("headbone"))
                            {
                                view_bone_name = appearance.GetProperty("headbone");
                                // The biped head bone is anchored at the neck usually. Therefore a guessed fixed offset is needed,
                                // which is not preferable, but necessary
                                adjustheight += 0.15;
                            }

                            if (!view_bone_name.empty())
                            {
                                if (skel && skel->hasBone(view_bone_name))
                                {
                                    // Hack: force Ogre to update skeleton with current animation state, even if avatar invisible
                                    if (ent->getAllAnimationStates())
                                        skel->setAnimationState(*ent->getAllAnimationStates());

                                    Ogre::Bone* bone = skel->getBone(view_bone_name);
                                    Ogre::Vector3 headpos = bone->_getDerivedPosition();
                                    Vector3df ourheadpos(-headpos.z + 0.5f, -headpos.x, headpos.y + adjustheight);
                                    RexTypes::Vector3 campos = avatar_pos + (avatar_orientation * ourheadpos);
                                    camera_placeable->SetPosition(campos);
                                    fallback = false;
                                }
                            }
                        }
                    }
                    // Fallback using fixed position
                    if (fallback)
                    {
                        RexTypes::Vector3 campos = avatar_pos + (avatar_orientation * camera_offset_firstperson_);
                        camera_placeable->SetPosition(campos);
                    }

                    // update camera pitch
                    if (drag_pitch_ != 0)
                    {
                        firstperson_pitch_ += drag_pitch_ * firstperson_sensitivity_;
                        firstperson_pitch_ = clamp(firstperson_pitch_, -HALF_PI, HALF_PI);
                    }
                    camera_placeable->Pitch(firstperson_pitch_);
                }

                if (current_state_ == FreeLook)
                {
                    const float trans_dt = (float)frametime * sensitivity_;

                    RexTypes::Vector3 pos = camera_placeable->GetPosition();
                    pos += camera_placeable->GetOrientation() * normalized_free_translation_ * trans_dt;
                    camera_placeable->SetPosition(pos);

                    camera_placeable->Pitch(drag_pitch_ * firstperson_sensitivity_);
                    camera_placeable->Yaw(drag_yaw_ * firstperson_sensitivity_);
                }
            }
        }

        // switch between first and third person modes, depending on how close we are to the avatar
        switch (current_state_)
        {
        case FirstPerson:
            {
                if (camera_distance_ != camera_min_distance_)
                {
                    current_state_ = ThirdPerson;
                    event_category_id_t event_category = framework_->GetEventManager()->QueryEventCategory("Input");
                    framework_->GetEventManager()->SendEvent(event_category, Input::Events::INPUTSTATE_THIRDPERSON, 0);

                    firstperson_pitch_ = 0.0f;
                }
                break;
            }
        case ThirdPerson:
            {
                if (camera_distance_ == camera_min_distance_)
                {
                    event_category_id_t event_category = framework_->GetEventManager()->QueryEventCategory("Input");
                    framework_->GetEventManager()->SendEvent(event_category, Input::Events::INPUTSTATE_FIRSTPERSON, 0);
                    current_state_ = FirstPerson;

                    firstperson_pitch_ = 0.0f;
                }
                break;
            }
		}
    }

	//experimental for py api
	void CameraControllable::SetYawPitch(Real newyaw, Real newpitch)
	{
		firstperson_yaw_ = newyaw;
		firstperson_pitch_ = newpitch;
	}
}

<|endoftext|>