<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: progressbar.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:20:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _UNOCONTROLS_PROGRESSBAR_CTRL_HXX
#define _UNOCONTROLS_PROGRESSBAR_CTRL_HXX

//____________________________________________________________________________________________________________
//  includes of other projects
//____________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XSERVICENAME_HPP_
#include <com/sun/star/lang/XServiceName.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

//____________________________________________________________________________________________________________
//  includes of my own project
//____________________________________________________________________________________________________________

#ifndef _UNOCONTROLS_BASECONTROL_CTRL_HXX
#include "basecontrol.hxx"
#endif

//____________________________________________________________________________________________________________
//  namespaces
//____________________________________________________________________________________________________________

namespace unocontrols{

#define UNO3_REFERENCE                  ::com::sun::star::uno::Reference
#define UNO3_XMULTISERVICEFACTORY       ::com::sun::star::lang::XMultiServiceFactory
#define UNO3_RUNTIMEEXCEPTION           ::com::sun::star::uno::RuntimeException
#define UNO3_XCONTROLMODEL              ::com::sun::star::awt::XControlModel
#define UNO3_XPROGRESSBAR               ::com::sun::star::awt::XProgressBar
#define UNO3_ANY                        ::com::sun::star::uno::Any
#define UNO3_TYPE                       ::com::sun::star::uno::Type
#define UNO3_SEQUENCE                   ::com::sun::star::uno::Sequence
#define UNO3_XGRAPHICS                  ::com::sun::star::awt::XGraphics
#define UNO3_OUSTRING                   ::rtl::OUString
#define UNO3_SIZE                       ::com::sun::star::awt::Size

//____________________________________________________________________________________________________________
//  defines
//____________________________________________________________________________________________________________

#define SERVICENAME_PROGRESSBAR             "com.sun.star.awt.XProgressBar"
#define IMPLEMENTATIONNAME_PROGRESSBAR      "stardiv.UnoControls.ProgressBar"
#define FREESPACE                           4
#define DEFAULT_HORIZONTAL                  sal_True
#define DEFAULT_BLOCKDIMENSION              Size(1,1)
#define DEFAULT_BACKGROUNDCOLOR             TRGB_COLORDATA( 0x00, 0xC0, 0xC0, 0xC0 )    // lightgray
#define DEFAULT_FOREGROUNDCOLOR             TRGB_COLORDATA( 0x00, 0x00, 0x00, 0x80 )    // blue
#define DEFAULT_MINRANGE                    INT_MIN
#define DEFAULT_MAXRANGE                    INT_MAX
#define DEFAULT_BLOCKVALUE                  1
#define DEFAULT_VALUE                       DEFAULT_MINRANGE
#define LINECOLOR_BRIGHT                    TRGB_COLORDATA( 0x00, 0xFF, 0xFF, 0xFF )    // white
#define LINECOLOR_SHADOW                    TRGB_COLORDATA( 0x00, 0x00, 0x00, 0x00 )    // black

//____________________________________________________________________________________________________________
//  classes
//____________________________________________________________________________________________________________

class ProgressBar   : public UNO3_XCONTROLMODEL
                    , public UNO3_XPROGRESSBAR
                    , public BaseControl
{

//____________________________________________________________________________________________________________
//  public methods
//____________________________________________________________________________________________________________

public:

    //________________________________________________________________________________________________________
    //  construct/destruct
    //________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    ProgressBar( const UNO3_REFERENCE< UNO3_XMULTISERVICEFACTORY >& xFactory );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual ~ProgressBar();

    //__________________________________________________________________________________________________________
    //  XInterface
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_ANY SAL_CALL queryInterface( const UNO3_TYPE& aType ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_______________________________________________________________________________________________________
        @short      increment refcount
        @descr      -

        @seealso    XInterface
        @seealso    release()

        @param      -

        @return     -

        @onerror    A RuntimeException is thrown.
    */

    virtual void SAL_CALL acquire() throw();

    /**_______________________________________________________________________________________________________
        @short      decrement refcount
        @descr      -

        @seealso    XInterface
        @seealso    acquire()

        @param      -

        @return     -

        @onerror    A RuntimeException is thrown.
    */

    virtual void SAL_CALL release() throw();

    //__________________________________________________________________________________________________________
    //  XTypeProvider
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_SEQUENCE< UNO3_TYPE > SAL_CALL getTypes() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XAggregation
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    UNO3_ANY SAL_CALL queryAggregation( const UNO3_TYPE& aType ) throw( UNO3_RUNTIMEEXCEPTION );

    //________________________________________________________________________________________________________
    //  XProgressBar
    //________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setForegroundColor( sal_Int32 nColor ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setBackgroundColor( sal_Int32 nColor ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setValue( sal_Int32 nValue ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setRange( sal_Int32   nMin    ,
                                    sal_Int32   nMax    ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual sal_Int32 SAL_CALL getValue() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XWindow
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setPosSize(   sal_Int32   nX      ,
                                        sal_Int32   nY      ,
                                        sal_Int32   nWidth  ,
                                        sal_Int32   nHeight ,
                                        sal_Int16   nFlags  ) throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XControl
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual sal_Bool SAL_CALL setModel( const UNO3_REFERENCE< UNO3_XCONTROLMODEL >& xModel ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_REFERENCE< UNO3_XCONTROLMODEL > SAL_CALL getModel() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  BaseControl
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    static const UNO3_SEQUENCE< UNO3_OUSTRING > impl_getStaticSupportedServiceNames();

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    static const UNO3_OUSTRING impl_getStaticImplementationName();

//____________________________________________________________________________________________________________
//  protected methods
//____________________________________________________________________________________________________________

protected:

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void impl_paint(        sal_Int32                           nX          ,
                                    sal_Int32                           nY          ,
                            const   UNO3_REFERENCE< UNO3_XGRAPHICS >&   xGraphics   );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    void impl_recalcRange();

//____________________________________________________________________________________________________________
//  private variables
//____________________________________________________________________________________________________________

private:

    sal_Bool    m_bHorizontal       ;   // orientation for steps            [true=horizontal/false=vertikal]
    UNO3_SIZE   m_aBlockSize        ;   // width and height of a block      [>=0,0]
    sal_Int32   m_nForegroundColor  ;   //                                  (alpha,r,g,b)
    sal_Int32   m_nBackgroundColor  ;   //                                  (alpha,r,g,b)
    sal_Int32   m_nMinRange         ;   // lowest value  =   0%             [long, <_nMaxRange]
    sal_Int32   m_nMaxRange         ;   // highest value = 100%             [long, >_nMinRange]
    double      m_nBlockValue       ;   // value for one block              [long, >0]
    sal_Int32   m_nValue            ;   // value for progress               [long]

};  // class ProgressBar

}   // namespace unocontrols

#endif  // #ifndef _UNOCONTROLS_PROGRESSBAR_CTRL_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.4.42); FILE MERGED 2008/04/01 12:59:05 thb 1.4.42.2: #i85898# Stripping all external header guards 2008/03/31 13:07:32 rt 1.4.42.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: progressbar.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _UNOCONTROLS_PROGRESSBAR_CTRL_HXX
#define _UNOCONTROLS_PROGRESSBAR_CTRL_HXX

//____________________________________________________________________________________________________________
//  includes of other projects
//____________________________________________________________________________________________________________

#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

//____________________________________________________________________________________________________________
//  includes of my own project
//____________________________________________________________________________________________________________
#include "basecontrol.hxx"

//____________________________________________________________________________________________________________
//  namespaces
//____________________________________________________________________________________________________________

namespace unocontrols{

#define UNO3_REFERENCE                  ::com::sun::star::uno::Reference
#define UNO3_XMULTISERVICEFACTORY       ::com::sun::star::lang::XMultiServiceFactory
#define UNO3_RUNTIMEEXCEPTION           ::com::sun::star::uno::RuntimeException
#define UNO3_XCONTROLMODEL              ::com::sun::star::awt::XControlModel
#define UNO3_XPROGRESSBAR               ::com::sun::star::awt::XProgressBar
#define UNO3_ANY                        ::com::sun::star::uno::Any
#define UNO3_TYPE                       ::com::sun::star::uno::Type
#define UNO3_SEQUENCE                   ::com::sun::star::uno::Sequence
#define UNO3_XGRAPHICS                  ::com::sun::star::awt::XGraphics
#define UNO3_OUSTRING                   ::rtl::OUString
#define UNO3_SIZE                       ::com::sun::star::awt::Size

//____________________________________________________________________________________________________________
//  defines
//____________________________________________________________________________________________________________

#define SERVICENAME_PROGRESSBAR             "com.sun.star.awt.XProgressBar"
#define IMPLEMENTATIONNAME_PROGRESSBAR      "stardiv.UnoControls.ProgressBar"
#define FREESPACE                           4
#define DEFAULT_HORIZONTAL                  sal_True
#define DEFAULT_BLOCKDIMENSION              Size(1,1)
#define DEFAULT_BACKGROUNDCOLOR             TRGB_COLORDATA( 0x00, 0xC0, 0xC0, 0xC0 )    // lightgray
#define DEFAULT_FOREGROUNDCOLOR             TRGB_COLORDATA( 0x00, 0x00, 0x00, 0x80 )    // blue
#define DEFAULT_MINRANGE                    INT_MIN
#define DEFAULT_MAXRANGE                    INT_MAX
#define DEFAULT_BLOCKVALUE                  1
#define DEFAULT_VALUE                       DEFAULT_MINRANGE
#define LINECOLOR_BRIGHT                    TRGB_COLORDATA( 0x00, 0xFF, 0xFF, 0xFF )    // white
#define LINECOLOR_SHADOW                    TRGB_COLORDATA( 0x00, 0x00, 0x00, 0x00 )    // black

//____________________________________________________________________________________________________________
//  classes
//____________________________________________________________________________________________________________

class ProgressBar   : public UNO3_XCONTROLMODEL
                    , public UNO3_XPROGRESSBAR
                    , public BaseControl
{

//____________________________________________________________________________________________________________
//  public methods
//____________________________________________________________________________________________________________

public:

    //________________________________________________________________________________________________________
    //  construct/destruct
    //________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    ProgressBar( const UNO3_REFERENCE< UNO3_XMULTISERVICEFACTORY >& xFactory );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual ~ProgressBar();

    //__________________________________________________________________________________________________________
    //  XInterface
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_ANY SAL_CALL queryInterface( const UNO3_TYPE& aType ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_______________________________________________________________________________________________________
        @short      increment refcount
        @descr      -

        @seealso    XInterface
        @seealso    release()

        @param      -

        @return     -

        @onerror    A RuntimeException is thrown.
    */

    virtual void SAL_CALL acquire() throw();

    /**_______________________________________________________________________________________________________
        @short      decrement refcount
        @descr      -

        @seealso    XInterface
        @seealso    acquire()

        @param      -

        @return     -

        @onerror    A RuntimeException is thrown.
    */

    virtual void SAL_CALL release() throw();

    //__________________________________________________________________________________________________________
    //  XTypeProvider
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_SEQUENCE< UNO3_TYPE > SAL_CALL getTypes() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XAggregation
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    UNO3_ANY SAL_CALL queryAggregation( const UNO3_TYPE& aType ) throw( UNO3_RUNTIMEEXCEPTION );

    //________________________________________________________________________________________________________
    //  XProgressBar
    //________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setForegroundColor( sal_Int32 nColor ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setBackgroundColor( sal_Int32 nColor ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setValue( sal_Int32 nValue ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setRange( sal_Int32   nMin    ,
                                    sal_Int32   nMax    ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual sal_Int32 SAL_CALL getValue() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XWindow
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void SAL_CALL setPosSize(   sal_Int32   nX      ,
                                        sal_Int32   nY      ,
                                        sal_Int32   nWidth  ,
                                        sal_Int32   nHeight ,
                                        sal_Int16   nFlags  ) throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  XControl
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual sal_Bool SAL_CALL setModel( const UNO3_REFERENCE< UNO3_XCONTROLMODEL >& xModel ) throw( UNO3_RUNTIMEEXCEPTION );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual UNO3_REFERENCE< UNO3_XCONTROLMODEL > SAL_CALL getModel() throw( UNO3_RUNTIMEEXCEPTION );

    //__________________________________________________________________________________________________________
    //  BaseControl
    //__________________________________________________________________________________________________________

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    static const UNO3_SEQUENCE< UNO3_OUSTRING > impl_getStaticSupportedServiceNames();

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    static const UNO3_OUSTRING impl_getStaticImplementationName();

//____________________________________________________________________________________________________________
//  protected methods
//____________________________________________________________________________________________________________

protected:

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    virtual void impl_paint(        sal_Int32                           nX          ,
                                    sal_Int32                           nY          ,
                            const   UNO3_REFERENCE< UNO3_XGRAPHICS >&   xGraphics   );

    /**_________________________________________________________________________________________________________
        @short
        @descr

        @seealso

        @param

        @return

        @onerror
    */

    void impl_recalcRange();

//____________________________________________________________________________________________________________
//  private variables
//____________________________________________________________________________________________________________

private:

    sal_Bool    m_bHorizontal       ;   // orientation for steps            [true=horizontal/false=vertikal]
    UNO3_SIZE   m_aBlockSize        ;   // width and height of a block      [>=0,0]
    sal_Int32   m_nForegroundColor  ;   //                                  (alpha,r,g,b)
    sal_Int32   m_nBackgroundColor  ;   //                                  (alpha,r,g,b)
    sal_Int32   m_nMinRange         ;   // lowest value  =   0%             [long, <_nMaxRange]
    sal_Int32   m_nMaxRange         ;   // highest value = 100%             [long, >_nMinRange]
    double      m_nBlockValue       ;   // value for one block              [long, >0]
    sal_Int32   m_nValue            ;   // value for progress               [long]

};  // class ProgressBar

}   // namespace unocontrols

#endif  // #ifndef _UNOCONTROLS_PROGRESSBAR_CTRL_HXX
<|endoftext|>


<commit_before>#include <iostream>
#include <cassert>

#include "EvalCmd.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

// ---------------------------------------------------------------------------

EvalCmd::EvalCmd()
{
    name = "eval";

    field = 0;
    points = 0;
    values = 0;
}

EvalCmd::~EvalCmd()
{
    // XXX:
}

// ---------------------------------------------------------------------------

void EvalCmd::setupOptions(AnyOption *opt)
{
    assert(opt != 0);

    /* setup usage */
    opt->addUsage("Usage:");
    opt->addUsage("   cigma eval [options]");
    opt->addUsage("     --field     Input field");
    opt->addUsage("     --points    Input points");
    opt->addUsage("     --output    Output values");

    /* setup flags and options */
    opt->setFlag("help",'h');
    opt->setFlag("verbose",'v');

    opt->setOption("field"); // XXX: -f short option?
    opt->setOption("field-mesh");
    opt->setOption("field-mesh-coordinates");
    opt->setOption("field-mesh-connectivity");
    opt->setOption("field-function");

    opt->setOption("points"); // XXX: -p short option?
    opt->setOption("output");
}

void EvalCmd::configure(AnyOption *opt)
{
    assert(opt != 0);

    string inputstr;
    char *in;

    // read verbose flag
    verbose = opt->getFlag("verbose");

    /* determine the output values path */
    in = opt->getValue("output");
    if (in == 0)
    {
        cerr << "eval: Please specify an output path for "
             << "the values dataset (missing --output option)"
             << endl;
        exit(1);
    }
    inputstr = in;

    string valuesExt;
    parse_dataset_path(inputstr, valuesLoc, valuesFile, valuesExt);
    valuesWriter = NewWriter(valuesExt.c_str());
    if (valuesWriter->getType() == Writer::NULL_WRITER)
    {
        cerr << "eval: Could not make writer for output file. "
             << "Unsupported extension (" << valuesExt << ")."
             << endl;
        exit(1);
    }
    if ((valuesLoc == "") && (valuesWriter->getType() == Writer::HDF_WRITER))
    {
        valuesLoc = "/values";
    }

    /* determine the input points path */
    in = opt->getValue("points");
    if (in == 0)
    {
        cerr << "eval: Please specify an input path for "
             << "the points dataset (missing --points option)"
             << endl;
        exit(1);
    }

    pointsReader.load_args(opt, "points");
    pointsReader.validate_args("eval");
    pointsReader.load_points();
    if (pointsReader.points == 0)
    {
        cerr << "eval: Could not load points dataset!" << endl;
        exit(1);
    }

    /* determine the input field */
    fieldReader.load_args(opt, "field");
    fieldReader.validate_args("eval");
    fieldReader.load_field();
    if (fieldReader.field == 0)
    {
        cerr << "eval: Could not load field from path "
             << fieldReader.fieldPath
             << endl;
        exit(1);
    }

    if (field->n_dim() != points->n_dim())
    {
        cerr << "eval: Domain dimensions do not match: "
             << "field->dim = " << field->n_dim() << ", "
             << "points->dim = " << points->n_dim()
             << endl;
        exit(1);
    }

}

int EvalCmd::run()
{
    assert(field != 0);
    assert(points != 0);
    assert(values != 0);

    // indices
    int i;
    int e;

    // dimensions
    const int npts = points->n_points();
    const int valdim = field->n_rank();

    // data
    double *phi = new double[npts * valdim];

    for (i = 0; i < npts; i++)
    {
        double *globalPoint = (*points)[i];
        field->eval(globalPoint, &phi[valdim*i]);
    }

    //
    // output values dataset
    //

    int ierr;

    cout << "Creating file " << valuesFile << endl;

    ierr = valuesWriter->open(valuesFile.c_str());
    if (ierr < 0)
    {
        cerr << "eval: Could not open (or create) output file " << valuesFile << endl;
        exit(1);
    }

    ierr = valuesWriter->write_dataset(valuesLoc.c_str(), phi, npts, valdim);
    if (ierr < 0)
    {
        cerr << "eval: Could not create values dataset " << valuesLoc << endl;
        exit(1);
    }

    ierr = valuesWriter->close();
    if (ierr < 0)
    {
        cerr << "eval: Error while closing output file?" << endl;
    }

    //
    // clean up
    //

    delete [] phi; // XXX: auto_ptr?

    return 0;
}

// ---------------------------------------------------------------------------
<commit_msg>Added short option -o to EvalCmd<commit_after>#include <iostream>
#include <cassert>

#include "EvalCmd.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

// ---------------------------------------------------------------------------

EvalCmd::EvalCmd()
{
    name = "eval";

    field = 0;
    points = 0;
    values = 0;
}

EvalCmd::~EvalCmd()
{
    // XXX:
}

// ---------------------------------------------------------------------------

void EvalCmd::setupOptions(AnyOption *opt)
{
    assert(opt != 0);

    /* setup usage */
    opt->addUsage("Usage:");
    opt->addUsage("   cigma eval [options]");
    opt->addUsage("     --field     Input field");
    opt->addUsage("     --points    Input points");
    opt->addUsage("     --output    Output values");

    /* setup flags and options */
    opt->setFlag("help",'h');
    opt->setFlag("verbose",'v');

    opt->setOption("field"); // XXX: -f short option?
    opt->setOption("field-mesh");
    opt->setOption("field-mesh-coordinates");
    opt->setOption("field-mesh-connectivity");
    opt->setOption("field-function");

    opt->setOption("points"); // XXX: -p short option?
    opt->setOption("output",'o');
}

void EvalCmd::configure(AnyOption *opt)
{
    assert(opt != 0);

    string inputstr;
    char *in;

    // read verbose flag
    verbose = opt->getFlag("verbose");

    /* determine the output values path */
    in = opt->getValue("output");
    if (in == 0)
    {
        cerr << "eval: Please specify an output path for "
             << "the values dataset (missing --output option)"
             << endl;
        exit(1);
    }
    inputstr = in;

    string valuesExt;
    parse_dataset_path(inputstr, valuesLoc, valuesFile, valuesExt);
    valuesWriter = NewWriter(valuesExt.c_str());
    if (valuesWriter->getType() == Writer::NULL_WRITER)
    {
        cerr << "eval: Could not make writer for output file. "
             << "Unsupported extension (" << valuesExt << ")."
             << endl;
        exit(1);
    }
    if ((valuesLoc == "") && (valuesWriter->getType() == Writer::HDF_WRITER))
    {
        valuesLoc = "/values";
    }

    /* determine the input points path */
    in = opt->getValue("points");
    if (in == 0)
    {
        cerr << "eval: Please specify an input path for "
             << "the points dataset (missing --points option)"
             << endl;
        exit(1);
    }

    pointsReader.load_args(opt, "points");
    pointsReader.validate_args("eval");
    pointsReader.load_points();
    if (pointsReader.points == 0)
    {
        cerr << "eval: Could not load points dataset!" << endl;
        exit(1);
    }

    /* determine the input field */
    fieldReader.load_args(opt, "field");
    fieldReader.validate_args("eval");
    fieldReader.load_field();
    if (fieldReader.field == 0)
    {
        cerr << "eval: Could not load field from path "
             << fieldReader.fieldPath
             << endl;
        exit(1);
    }

    if (field->n_dim() != points->n_dim())
    {
        cerr << "eval: Domain dimensions do not match: "
             << "field->dim = " << field->n_dim() << ", "
             << "points->dim = " << points->n_dim()
             << endl;
        exit(1);
    }

}

int EvalCmd::run()
{
    assert(field != 0);
    assert(points != 0);
    assert(values != 0);

    // indices
    int i;
    int e;

    // dimensions
    const int npts = points->n_points();
    const int valdim = field->n_rank();

    // data
    double *phi = new double[npts * valdim];

    for (i = 0; i < npts; i++)
    {
        double *globalPoint = (*points)[i];
        field->eval(globalPoint, &phi[valdim*i]);
    }

    //
    // output values dataset
    //

    int ierr;

    cout << "Creating file " << valuesFile << endl;

    ierr = valuesWriter->open(valuesFile.c_str());
    if (ierr < 0)
    {
        cerr << "eval: Could not open (or create) output file " << valuesFile << endl;
        exit(1);
    }

    ierr = valuesWriter->write_dataset(valuesLoc.c_str(), phi, npts, valdim);
    if (ierr < 0)
    {
        cerr << "eval: Could not create values dataset " << valuesLoc << endl;
        exit(1);
    }

    ierr = valuesWriter->close();
    if (ierr < 0)
    {
        cerr << "eval: Error while closing output file?" << endl;
    }

    //
    // clean up
    //

    delete [] phi; // XXX: auto_ptr?

    return 0;
}

// ---------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"

#include "ds_task_typedefs.h"
#include "internal/internal_datastore.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;

namespace You {
namespace DataStore {
namespace UnitTests {

using InternalDataStore = You::DataStore::Internal::InternalDataStore;

// Dummy constants
const std::wstring TASK_ID = L"id";
const std::wstring DESCRIPTION = L"description";
const std::wstring DEADLINE = L"deadline";
const std::wstring PRIORITY = L"priority";
const std::wstring DEPENDENCIES = L"dependency";

// Dummy serialized task
const STask stask = {
		{ TASK_ID, L"0" },
		{ DESCRIPTION, L"bla bla" },
		{ DEADLINE, L"xxxxxx" },
		{ PRIORITY, L"urgent" },
		{ DEPENDENCIES, L"12345" }
};
const STask staskAlt = {
		{ TASK_ID, L"0" },
		{ DESCRIPTION, L"yada yada" },
		{ DEADLINE, L"yyyyyy" },
		{ PRIORITY, L"normal" },
		{ DEPENDENCIES, L"4321" }
};

/// Unit Test Class for InternalDataStore class
TEST_CLASS(DataStoreTest) {
public:
	/// Basic test for retrieving a task
	TEST_METHOD(DataStore_Get_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Test for retrieving task with non-existent task id
	TEST_METHOD(DataStore_Get_NonExistent_Test) {
		InternalDataStore sut;
		boost::variant<bool, STask> response = sut.get(0);
		Assert::IsFalse(boost::get<bool>(response));
	}

	/// Basic test for adding a task
	TEST_METHOD(DataStore_Post_Basic_Test) {
		InternalDataStore sut;

		// Checks if the document is initially empty
		bool isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsTrue(isEmptyDoc);

		// Checks for post return value
		bool result = sut.post(0, stask);
		Assert::IsTrue(result);

		// Updates the boolean
		isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		// Checks if the document is now not empty
		Assert::IsFalse(isEmptyDoc);
	}

	/// Test for adding task with an already existing task id
	TEST_METHOD(DataStore_Post_DuplicateId_Test) {
		InternalDataStore sut;
		bool init = sut.post(0, stask);
		Assert::IsTrue(init);
		bool result = sut.post(0, STask());
		Assert::IsFalse(result);

		// Checks if the content has not changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Basic test for editing a task
	TEST_METHOD(DataStore_Put_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, staskAlt);
		bool result = sut.put(0, stask);
		Assert::IsTrue(result);

		// Checks if the content has changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Test for editing task with non-existent task id
	TEST_METHOD(DataStore_Put_FalseId_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		bool result = sut.put(1, staskAlt);
		Assert::IsFalse(result);

		// Checks if the content has not changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);

		// Checks if the put does not add things to the xml tree
		pugi::xpath_node_set nodeSet = sut.document.select_nodes(L"task");
		Assert::AreEqual(1, static_cast<int>(nodeSet.size()));
	}

	/// Basic test for erasing a task with the specified task id
	TEST_METHOD(DataStore_Erase_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		// Checks if the xml tree is modified
		bool isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsFalse(isEmptyDoc);

		bool result = sut.erase(0);
		Assert::IsTrue(result);

		// Checks if the xml tree is now empty
		isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsTrue(isEmptyDoc);
	}

	/// Test for erasing task with non-existent task id
	TEST_METHOD(DataStore_Erase_NonExistent_Test) {
		InternalDataStore sut;
		bool result = sut.erase(0);
		Assert::IsFalse(result);
	}
};
}  // namespace UnitTests
}  // namespace DataStore
}  // namespace You
<commit_msg>Change static cast to lexical cast<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"

#include "ds_task_typedefs.h"
#include "internal/internal_datastore.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;

namespace You {
namespace DataStore {
namespace UnitTests {

using InternalDataStore = You::DataStore::Internal::InternalDataStore;

// Dummy constants
const std::wstring TASK_ID = L"id";
const std::wstring DESCRIPTION = L"description";
const std::wstring DEADLINE = L"deadline";
const std::wstring PRIORITY = L"priority";
const std::wstring DEPENDENCIES = L"dependency";

// Dummy serialized task
const STask stask = {
		{ TASK_ID, L"0" },
		{ DESCRIPTION, L"bla bla" },
		{ DEADLINE, L"xxxxxx" },
		{ PRIORITY, L"urgent" },
		{ DEPENDENCIES, L"12345" }
};
const STask staskAlt = {
		{ TASK_ID, L"0" },
		{ DESCRIPTION, L"yada yada" },
		{ DEADLINE, L"yyyyyy" },
		{ PRIORITY, L"normal" },
		{ DEPENDENCIES, L"4321" }
};

/// Unit Test Class for InternalDataStore class
TEST_CLASS(DataStoreTest) {
public:
	/// Basic test for retrieving a task
	TEST_METHOD(DataStore_Get_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Test for retrieving task with non-existent task id
	TEST_METHOD(DataStore_Get_NonExistent_Test) {
		InternalDataStore sut;
		boost::variant<bool, STask> response = sut.get(0);
		Assert::IsFalse(boost::get<bool>(response));
	}

	/// Basic test for adding a task
	TEST_METHOD(DataStore_Post_Basic_Test) {
		InternalDataStore sut;

		// Checks if the document is initially empty
		bool isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsTrue(isEmptyDoc);

		// Checks for post return value
		bool result = sut.post(0, stask);
		Assert::IsTrue(result);

		// Updates the boolean
		isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		// Checks if the document is now not empty
		Assert::IsFalse(isEmptyDoc);
	}

	/// Test for adding task with an already existing task id
	TEST_METHOD(DataStore_Post_DuplicateId_Test) {
		InternalDataStore sut;
		bool init = sut.post(0, stask);
		Assert::IsTrue(init);
		bool result = sut.post(0, STask());
		Assert::IsFalse(result);

		// Checks if the content has not changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Basic test for editing a task
	TEST_METHOD(DataStore_Put_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, staskAlt);
		bool result = sut.put(0, stask);
		Assert::IsTrue(result);

		// Checks if the content has changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);
	}

	/// Test for editing task with non-existent task id
	TEST_METHOD(DataStore_Put_FalseId_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		bool result = sut.put(1, staskAlt);
		Assert::IsFalse(result);

		// Checks if the content has not changed
		boost::variant<bool, STask> response = sut.get(0);
		STask task = boost::get<STask>(response);
		Assert::AreEqual(stask.at(TASK_ID), task[TASK_ID]);
		Assert::AreEqual(stask.at(DESCRIPTION), task[DESCRIPTION]);
		Assert::AreEqual(stask.at(DEADLINE), task[DEADLINE]);
		Assert::AreEqual(stask.at(PRIORITY), task[PRIORITY]);
		Assert::AreEqual(stask.at(DEPENDENCIES), task[DEPENDENCIES]);

		// Checks if the put does not add things to the xml tree
		pugi::xpath_node_set nodeSet = sut.document.select_nodes(L"task");
		Assert::AreEqual(1, boost::lexical_cast<int>(nodeSet.size()));
	}

	/// Basic test for erasing a task with the specified task id
	TEST_METHOD(DataStore_Erase_Basic_Test) {
		InternalDataStore sut;
		sut.post(0, stask);
		// Checks if the xml tree is modified
		bool isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsFalse(isEmptyDoc);

		bool result = sut.erase(0);
		Assert::IsTrue(result);

		// Checks if the xml tree is now empty
		isEmptyDoc = sut.document.children().begin() ==
			sut.document.children().end();
		Assert::IsTrue(isEmptyDoc);
	}

	/// Test for erasing task with non-existent task id
	TEST_METHOD(DataStore_Erase_NonExistent_Test) {
		InternalDataStore sut;
		bool result = sut.erase(0);
		Assert::IsFalse(result);
	}
};
}  // namespace UnitTests
}  // namespace DataStore
}  // namespace You
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <memory>
#include <cmath>

#include "../data/histogram.hpp"

#pragma once

namespace vis
{
    class TextHistogram
    {
        public:
            TextHistogram(std::shared_ptr<data::Histogram> const&);

            std::vector<std::string> getHistogram() const;
        protected:
            TextHistogram() = delete;
            TextHistogram(TextHistogram const&) = delete;
            TextHistogram& operator= (TextHistogram const&) = delete;
        private:
            std::shared_ptr<data::Histogram> histogram;
    };
}

<commit_msg>Added documentation to TextHistogram class<commit_after>#include <string>
#include <vector>
#include <memory>
#include <cmath>

#include "../data/histogram.hpp"

#pragma once

namespace vis
{
    /**
     * Class for text histogram.
     * Experimental.
     */
    class TextHistogram
    {
        public:
            /**
             * Constructor.
             *
             * \param Shared pointer to a Histogram object.
             */
            TextHistogram(std::shared_ptr<data::Histogram> const&);

            /**
             * Get strings representing lines of histogram.
             * \return list of strings
             */
            std::vector<std::string> getHistogram() const;
        protected:
            TextHistogram() = delete;
            TextHistogram(TextHistogram const&) = delete;
            TextHistogram& operator= (TextHistogram const&) = delete;
        private:
            /**
             * Histogram.
             */
            std::shared_ptr<data::Histogram> histogram;
    };
}

<|endoftext|>


<commit_before>#include <cstdint>

#include <Mapper0.h>

uint8_t Mapper0::readPrg(uint16_t addr) {
    int index = addr % cartMemory.prg.size();
    return cartMemory.prg[index];
}

uint8_t Mapper0::readChr(uint16_t addr) {
    int index = addr % cartMemory.chr.size();
    return cartMemory.chr[index];
}

void Mapper0::writeChr(uint16_t addr, uint8_t value) {
    if (cartMemory.chrIsRam) {
	int index = addr % cartMemory.chr.size();
        cartMemory.chr[index] = value;
    }
}
<commit_msg>Fix mapper0 readPrg ignoring ram<commit_after>#include <cstdint>

#include <Mapper0.h>

uint8_t Mapper0::readPrg(uint16_t addr) {
    if (addr >= 0x8000) {
	int index = addr % cartMemory.prg.size();
	return cartMemory.prg[index];
    }
    else if (addr >= 0x6000) {
	int index = addr % 0x2000;
	return cartMemory.ram[index];
    }
    else {
	return 0;
    }
}

uint8_t Mapper0::readChr(uint16_t addr) {
    int index = addr % cartMemory.chr.size();
    return cartMemory.chr[index];
}

void Mapper0::writeChr(uint16_t addr, uint8_t value) {
    if (cartMemory.chrIsRam) {
	int index = addr % cartMemory.chr.size();
        cartMemory.chr[index] = value;
    }
}
<|endoftext|>


<commit_before>#include "Message.hpp"
#include "User.hpp"
#include "Channel.hpp"
#include "Role.hpp"
#include "Network.hpp"
#include "PawnDispatcher.hpp"
#include "Callback.hpp"
#include "Logger.hpp"
#include "utils.hpp"
#include "Emoji.hpp"
#include "Embed.hpp"

Message::Message(MessageId_t pawn_id, json const &data) : m_PawnId(pawn_id)
{
	std::string author_id, channel_id;
	_valid =
		utils::TryGetJsonValue(data, m_Id, "id") &&
		utils::TryGetJsonValue(data, author_id, "author", "id") &&
		utils::TryGetJsonValue(data, channel_id, "channel_id") &&
		utils::TryGetJsonValue(data, m_Content, "content") &&
		utils::TryGetJsonValue(data, m_IsTts, "tts") &&
		utils::TryGetJsonValue(data, m_MentionsEveryone, "mention_everyone");

	if (!_valid)
	{
		Logger::Get()->Log(LogLevel::ERROR,
			"can't construct message object: invalid JSON: \"{}\"", data.dump());
		return;
	}

	Channel_t const &channel = ChannelManager::Get()->FindChannelById(channel_id);
	m_Channel = channel ? channel->GetPawnId() : INVALID_CHANNEL_ID;

	User_t const &user = UserManager::Get()->FindUserById(author_id);
	m_Author = user ? user->GetPawnId() : INVALID_USER_ID;

	if (utils::IsValidJson(data, "mentions", json::value_t::array))
	{
		for (auto &c : data["mentions"])
		{
			std::string mu_id;
			if (!utils::TryGetJsonValue(c, mu_id, "id"))
				continue;

			User_t const &mu = UserManager::Get()->FindUserById(mu_id);
			if (mu)
				m_UserMentions.push_back(mu->GetPawnId());
		}
	}

	if (utils::IsValidJson(data, "mention_roles", json::value_t::array))
	{
		for (auto &c : data["mention_roles"])
		{
			std::string mr_id;
			if (!utils::TryGetJsonValue(c, mr_id, "id"))
				continue;

			Role_t const &mr = RoleManager::Get()->FindRoleById(mr_id);
			if (mr)
				m_RoleMentions.push_back(mr->GetPawnId());
		}
	}
}

void Message::DeleteMessage()
{
	Channel_t const &channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return;

	Network::Get()->Http().Delete(fmt::format(
		"/channels/{:s}/messages/{:s}", channel->GetId(), GetId()));
}

void Message::AddReaction(Emoji_t const& emoji)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return;

	std::string emoji_str = emoji->GetName();

	if (emoji->GetSnowflake() != "")
	{
		emoji_str += ":" + emoji->GetSnowflake();
	}
	else
	{
		// This is a sort of hacky way thing, discord wants utf8 in hex: %F0%9F%99%82 (for hammer)
		// I did attempt to just send the unicode to it, but I had a 400 BAD REQUEST, this worked however.
		std::stringstream conversion;
		for (size_t i = 0; i < emoji_str.size(); i++)
		{
			conversion << "%" << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(emoji_str[i]));
		}
		emoji_str = conversion.str();
	}
	Network::Get()->Http().Put(fmt::format(
		"/channels/{:s}/messages/{:s}/reactions/{}/@me", channel->GetId(), GetId(), emoji_str
	));
}

bool Message::DeleteReaction(EmojiId_t const emojiid)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return false;

	std::string url = fmt::format("/channels/{:s}/messages/{:s}/reactions", channel->GetId(), GetId());

	if (emojiid != INVALID_EMOJI_ID)
	{
		const auto& emoji = EmojiManager::Get()->FindEmoji(emojiid);

		if (!emoji)
		{
			Logger::Get()->Log(LogLevel::ERROR, "invalid emoji id '{}'", emojiid);
			return false;
		}

		if (emoji->GetSnowflake() != "")
		{
			// custom emoji
			url += fmt::format("/{:s}:{:s}", emoji->GetName(), emoji->GetSnowflake());
		}
		else
		{
			// unicode emoji
			std::stringstream conversion;
			std::string emoji_name = emoji->GetName();
			for (size_t i = 0; i < emoji_name.size(); i++)
			{
				conversion << "%" << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(emoji_name[i]));
			}
			url += fmt::format("/{:s}", conversion.str());
		}
	}

	Network::Get()->Http().Delete(url);
	return true;
}

void MessageManager::Initialize()
{
	// PAWN callbacks
	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_CREATE, [](json const &data)
	{
		PawnDispatcher::Get()->Dispatch([data]() mutable
		{
			MessageId_t msg = MessageManager::Get()->Create(data);
			if (msg != INVALID_MESSAGE_ID)
			{
				// forward DCC_OnMessageCreate(DCC_Message:message);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageCreate", msg);

				MessageManager::Get()->Delete(msg);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_DELETE, [](json const &data)
	{
		Snowflake_t sfid;
		if (!utils::TryGetJsonValue(data, sfid, "id"))
			return;

		PawnDispatcher::Get()->Dispatch([sfid]() mutable
		{
			auto const &msg = MessageManager::Get()->FindById(sfid);
			if (msg)
			{
				// forward DCC_OnMessageDelete(DCC_Message:message);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageDelete", msg->GetPawnId());

				MessageManager::Get()->Delete(msg->GetPawnId());
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_ADD, [](json const& data)
	{
		Snowflake_t user_id, message_id;
		if (!utils::TryGetJsonValue(data, user_id, "user_id"))
			return;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, user_id, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			auto const& user = UserManager::Get()->FindUserById(user_id);
			if (msg && user)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), user->GetPawnId(), id, static_cast<int>(Message::ReactionType::REACTION_ADD));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE, [](json const& data)
	{
		Snowflake_t user_id, message_id;
		if (!utils::TryGetJsonValue(data, user_id, "user_id"))
			return;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, user_id, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			auto const& user = UserManager::Get()->FindUserById(user_id);
			if (msg && user)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), user->GetPawnId(), id, static_cast<int>(Message::ReactionType::REACTION_REMOVE));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE_ALL, [](json const& data)
	{
		Snowflake_t message_id;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			if (msg)
			{
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), INVALID_USER_ID, INVALID_EMOJI_ID, static_cast<int>(Message::ReactionType::REACTION_REMOVE_ALL));
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE_EMOJI, [](json const& data)
	{
		Snowflake_t  message_id;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			if (msg)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), INVALID_USER_ID, id, static_cast<int>(Message::ReactionType::REACTION_REMOVE_EMOJI));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});
}

bool Message::EditMessage(const std::string& msg, const EmbedId_t embedid)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return false;

	json data = {
		{ "content", msg }
	};

	if (embedid != INVALID_EMBED_ID)
	{
		const auto& embed = EmbedManager::Get()->FindEmbed(embedid);
		if (!embed)
		{
			Logger::Get()->Log(LogLevel::ERROR, "invalid embed id {}", embedid);
			return false;
		}

		data["embed"] =
		{
			{ "title", embed->GetTitle() },
			{ "description", embed->GetDescription() },
			{ "url", embed->GetUrl() },
			{ "timestamp", embed->GetTimestamp() },
			{ "color", embed->GetColor() },
			{ "footer", {
				{"text", embed->GetFooterText()},
				{"icon_url", embed->GetFooterIconUrl()},
			}},
			{"thumbnail", {
				{"url", embed->GetThumbnailUrl()}
			}},
			{"image", {
				{"url", embed->GetImageUrl()}
			}}
		};

		if (embed->GetFields().size())
		{
			json field_array = json::array();
			for (const auto& i : embed->GetFields())
			{
				field_array.push_back({
					{"name", i._name},
					{"value", i._value},
					{"inline", i._inline_}
				});
			}
			data["embed"]["fields"] = field_array;
		}
		EmbedManager::Get()->DeleteEmbed(embedid);
	}

	std::string json_str;
	if (!utils::TryDumpJson(data, json_str))
		Logger::Get()->Log(LogLevel::ERROR, "can't serialize JSON: {}", json_str);

	Network::Get()->Http().Patch(fmt::format("/channels/{:s}/messages/{:s}", channel->GetId(), GetId()), json_str);
	return true;
}

MessageId_t MessageManager::Create(json const &data)
{
	MessageId_t id = 1;
	while (m_Messages.find(id) != m_Messages.end())
		++id;

	if (!m_Messages.emplace(id, Message_t(new Message(id, data))).first->second)
	{
		Logger::Get()->Log(LogLevel::ERROR,
			"can't create message: duplicate key '{}'", id);
		return INVALID_USER_ID;
	}

	Logger::Get()->Log(LogLevel::DEBUG, "created message with id '{}'", id);
	return id;
}

bool MessageManager::Delete(MessageId_t id)
{
	auto it = m_Messages.find(id);
	if (it == m_Messages.end())
		return false;

	m_Messages.erase(it);
	Logger::Get()->Log(LogLevel::DEBUG, "deleted message with id '{}'", id);
	return true;
}

Message_t const &MessageManager::Find(MessageId_t id)
{
	static Message_t invalid_msg;
	auto it = m_Messages.find(id);
	if (it == m_Messages.end())
		return invalid_msg;
	return it->second;
}

Message_t const &MessageManager::FindById(Snowflake_t const &sfid)
{
	static Message_t invalid_msg;
	for (auto const &u : m_Messages)
	{
		auto const &msg = u.second;
		if (msg->GetId().compare(sfid) == 0)
			return msg;
	}
	return invalid_msg;
}
<commit_msg>Move Message::EditMessage away from inbetween two MessageManager functions.<commit_after>#include "Message.hpp"
#include "User.hpp"
#include "Channel.hpp"
#include "Role.hpp"
#include "Network.hpp"
#include "PawnDispatcher.hpp"
#include "Callback.hpp"
#include "Logger.hpp"
#include "utils.hpp"
#include "Emoji.hpp"
#include "Embed.hpp"

Message::Message(MessageId_t pawn_id, json const &data) : m_PawnId(pawn_id)
{
	std::string author_id, channel_id;
	_valid =
		utils::TryGetJsonValue(data, m_Id, "id") &&
		utils::TryGetJsonValue(data, author_id, "author", "id") &&
		utils::TryGetJsonValue(data, channel_id, "channel_id") &&
		utils::TryGetJsonValue(data, m_Content, "content") &&
		utils::TryGetJsonValue(data, m_IsTts, "tts") &&
		utils::TryGetJsonValue(data, m_MentionsEveryone, "mention_everyone");

	if (!_valid)
	{
		Logger::Get()->Log(LogLevel::ERROR,
			"can't construct message object: invalid JSON: \"{}\"", data.dump());
		return;
	}

	Channel_t const &channel = ChannelManager::Get()->FindChannelById(channel_id);
	m_Channel = channel ? channel->GetPawnId() : INVALID_CHANNEL_ID;

	User_t const &user = UserManager::Get()->FindUserById(author_id);
	m_Author = user ? user->GetPawnId() : INVALID_USER_ID;

	if (utils::IsValidJson(data, "mentions", json::value_t::array))
	{
		for (auto &c : data["mentions"])
		{
			std::string mu_id;
			if (!utils::TryGetJsonValue(c, mu_id, "id"))
				continue;

			User_t const &mu = UserManager::Get()->FindUserById(mu_id);
			if (mu)
				m_UserMentions.push_back(mu->GetPawnId());
		}
	}

	if (utils::IsValidJson(data, "mention_roles", json::value_t::array))
	{
		for (auto &c : data["mention_roles"])
		{
			std::string mr_id;
			if (!utils::TryGetJsonValue(c, mr_id, "id"))
				continue;

			Role_t const &mr = RoleManager::Get()->FindRoleById(mr_id);
			if (mr)
				m_RoleMentions.push_back(mr->GetPawnId());
		}
	}
}

void Message::DeleteMessage()
{
	Channel_t const &channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return;

	Network::Get()->Http().Delete(fmt::format(
		"/channels/{:s}/messages/{:s}", channel->GetId(), GetId()));
}

void Message::AddReaction(Emoji_t const& emoji)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return;

	std::string emoji_str = emoji->GetName();

	if (emoji->GetSnowflake() != "")
	{
		emoji_str += ":" + emoji->GetSnowflake();
	}
	else
	{
		// This is a sort of hacky way thing, discord wants utf8 in hex: %F0%9F%99%82 (for hammer)
		// I did attempt to just send the unicode to it, but I had a 400 BAD REQUEST, this worked however.
		std::stringstream conversion;
		for (size_t i = 0; i < emoji_str.size(); i++)
		{
			conversion << "%" << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(emoji_str[i]));
		}
		emoji_str = conversion.str();
	}
	Network::Get()->Http().Put(fmt::format(
		"/channels/{:s}/messages/{:s}/reactions/{}/@me", channel->GetId(), GetId(), emoji_str
	));
}

bool Message::DeleteReaction(EmojiId_t const emojiid)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return false;

	std::string url = fmt::format("/channels/{:s}/messages/{:s}/reactions", channel->GetId(), GetId());

	if (emojiid != INVALID_EMOJI_ID)
	{
		const auto& emoji = EmojiManager::Get()->FindEmoji(emojiid);

		if (!emoji)
		{
			Logger::Get()->Log(LogLevel::ERROR, "invalid emoji id '{}'", emojiid);
			return false;
		}

		if (emoji->GetSnowflake() != "")
		{
			// custom emoji
			url += fmt::format("/{:s}:{:s}", emoji->GetName(), emoji->GetSnowflake());
		}
		else
		{
			// unicode emoji
			std::stringstream conversion;
			std::string emoji_name = emoji->GetName();
			for (size_t i = 0; i < emoji_name.size(); i++)
			{
				conversion << "%" << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(emoji_name[i]));
			}
			url += fmt::format("/{:s}", conversion.str());
		}
	}

	Network::Get()->Http().Delete(url);
	return true;
}

bool Message::EditMessage(const std::string& msg, const EmbedId_t embedid)
{
	Channel_t const& channel = ChannelManager::Get()->FindChannel(GetChannel());
	if (!channel)
		return false;

	json data = {
		{ "content", msg }
	};

	if (embedid != INVALID_EMBED_ID)
	{
		const auto& embed = EmbedManager::Get()->FindEmbed(embedid);
		if (!embed)
		{
			Logger::Get()->Log(LogLevel::ERROR, "invalid embed id {}", embedid);
			return false;
		}

		data["embed"] =
		{
			{ "title", embed->GetTitle() },
			{ "description", embed->GetDescription() },
			{ "url", embed->GetUrl() },
			{ "timestamp", embed->GetTimestamp() },
			{ "color", embed->GetColor() },
			{ "footer", {
				{"text", embed->GetFooterText()},
				{"icon_url", embed->GetFooterIconUrl()},
			}},
			{"thumbnail", {
				{"url", embed->GetThumbnailUrl()}
			}},
			{"image", {
				{"url", embed->GetImageUrl()}
			}}
		};

		if (embed->GetFields().size())
		{
			json field_array = json::array();
			for (const auto& i : embed->GetFields())
			{
				field_array.push_back({
					{"name", i._name},
					{"value", i._value},
					{"inline", i._inline_}
					});
			}
			data["embed"]["fields"] = field_array;
		}
		EmbedManager::Get()->DeleteEmbed(embedid);
	}

	std::string json_str;
	if (!utils::TryDumpJson(data, json_str))
		Logger::Get()->Log(LogLevel::ERROR, "can't serialize JSON: {}", json_str);

	Network::Get()->Http().Patch(fmt::format("/channels/{:s}/messages/{:s}", channel->GetId(), GetId()), json_str);
	return true;
}

void MessageManager::Initialize()
{
	// PAWN callbacks
	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_CREATE, [](json const &data)
	{
		PawnDispatcher::Get()->Dispatch([data]() mutable
		{
			MessageId_t msg = MessageManager::Get()->Create(data);
			if (msg != INVALID_MESSAGE_ID)
			{
				// forward DCC_OnMessageCreate(DCC_Message:message);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageCreate", msg);

				MessageManager::Get()->Delete(msg);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_DELETE, [](json const &data)
	{
		Snowflake_t sfid;
		if (!utils::TryGetJsonValue(data, sfid, "id"))
			return;

		PawnDispatcher::Get()->Dispatch([sfid]() mutable
		{
			auto const &msg = MessageManager::Get()->FindById(sfid);
			if (msg)
			{
				// forward DCC_OnMessageDelete(DCC_Message:message);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageDelete", msg->GetPawnId());

				MessageManager::Get()->Delete(msg->GetPawnId());
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_ADD, [](json const& data)
	{
		Snowflake_t user_id, message_id;
		if (!utils::TryGetJsonValue(data, user_id, "user_id"))
			return;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, user_id, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			auto const& user = UserManager::Get()->FindUserById(user_id);
			if (msg && user)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), user->GetPawnId(), id, static_cast<int>(Message::ReactionType::REACTION_ADD));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE, [](json const& data)
	{
		Snowflake_t user_id, message_id;
		if (!utils::TryGetJsonValue(data, user_id, "user_id"))
			return;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, user_id, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			auto const& user = UserManager::Get()->FindUserById(user_id);
			if (msg && user)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), user->GetPawnId(), id, static_cast<int>(Message::ReactionType::REACTION_REMOVE));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE_ALL, [](json const& data)
	{
		Snowflake_t message_id;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			if (msg)
			{
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), INVALID_USER_ID, INVALID_EMOJI_ID, static_cast<int>(Message::ReactionType::REACTION_REMOVE_ALL));
			}
		});
	});

	Network::Get()->WebSocket().RegisterEvent(WebSocket::Event::MESSAGE_REACTION_REMOVE_EMOJI, [](json const& data)
	{
		Snowflake_t  message_id;

		if (!utils::TryGetJsonValue(data, message_id, "message_id"))
			return;

		PawnDispatcher::Get()->Dispatch([data, message_id]() mutable
		{
			auto const& msg = MessageManager::Get()->FindById(message_id);
			if (msg)
			{
				Snowflake_t emoji_id;
				std::string name;
				utils::TryGetJsonValue(data["emoji"], emoji_id, "id");
				if (!utils::TryGetJsonValue(data["emoji"], name, "name"))
					return;

				auto const id = EmojiManager::Get()->AddEmoji(emoji_id, name);
				// forward DCC_OnMessageReactionAdd(DCC_Message:message, DCC_User:reaction_user, DCC_Emoji:emoji, DCC_MessageReactionType:reaction_type);
				pawn_cb::Error error;
				pawn_cb::Callback::CallFirst(error, "DCC_OnMessageReaction", msg->GetPawnId(), INVALID_USER_ID, id, static_cast<int>(Message::ReactionType::REACTION_REMOVE_EMOJI));
				EmojiManager::Get()->DeleteEmoji(id);
			}
		});
	});
}

MessageId_t MessageManager::Create(json const &data)
{
	MessageId_t id = 1;
	while (m_Messages.find(id) != m_Messages.end())
		++id;

	if (!m_Messages.emplace(id, Message_t(new Message(id, data))).first->second)
	{
		Logger::Get()->Log(LogLevel::ERROR,
			"can't create message: duplicate key '{}'", id);
		return INVALID_USER_ID;
	}

	Logger::Get()->Log(LogLevel::DEBUG, "created message with id '{}'", id);
	return id;
}

bool MessageManager::Delete(MessageId_t id)
{
	auto it = m_Messages.find(id);
	if (it == m_Messages.end())
		return false;

	m_Messages.erase(it);
	Logger::Get()->Log(LogLevel::DEBUG, "deleted message with id '{}'", id);
	return true;
}

Message_t const &MessageManager::Find(MessageId_t id)
{
	static Message_t invalid_msg;
	auto it = m_Messages.find(id);
	if (it == m_Messages.end())
		return invalid_msg;
	return it->second;
}

Message_t const &MessageManager::FindById(Snowflake_t const &sfid)
{
	static Message_t invalid_msg;
	for (auto const &u : m_Messages)
	{
		auto const &msg = u.second;
		if (msg->GetId().compare(sfid) == 0)
			return msg;
	}
	return invalid_msg;
}
<|endoftext|>


<commit_before>#include "NTClient.h"
using namespace std;

NTClient::NTClient(int interval, double _accuracy) {
	typeIntervalMS = interval;
	accuracy = _accuracy;
	hasError = false;
	firstConnect = true;
	connected = false;
	lessonLen = 0;
	lidx = 0;
	log = new NTLogger("(Not logged in)");
}
NTClient::~NTClient() {
	delete log;
	if (wsh != nullptr) {
		delete wsh;
		wsh = nullptr;
	}
}
bool NTClient::login(string username, string password) {
	log->type(LOG_HTTP);
	log->wr("Logging into the NitroType account...\n");
	log->setUsername(username);
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				log->type(LOG_HTTP);
				log->wr("Resolved ntuserrem login token.\n");
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream uristream;
	uristream  << "wss://realtime1.nitrotype.com:443/realtime/?_primuscb=" << tnow << "-0&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "&b64=1";
	string wsURI = uristream.str();
	log->type(LOG_CONN);
	log->wr("Attempting to open a WebSocket on NitroType realtime server...\n");
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	log->type(LOG_HTTP);
	log->wr("Resolving Primus SID...\n");
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		log->type(LOG_HTTP);
		log->wr("Resolved Primus SID successfully.\n");
		// addCookie("io", primusSid);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	stringstream ss;
	ss << "4{\"stream\":\"race\",\"msg\":\"join\",\"payload\":{\"debugging\":false,\"avgSpeed\":"
	<< avgSpeed
	<< ",\"forceEarlyPlace\":true,\"track\":\"desert\",\"music\":\"city_nights\"}}";
	return ss.str();
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		log->type(LOG_CONN);
		log->wr("Established a WebSocket connection with the realtime server.\n");
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		log->type(LOG_CONN);
		log->wr("Disconnected from the realtime server.\n");
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::handleData(WebSocket<CLIENT>* ws, json* j) {
	// Uncomment to dump all raw JSON packets
	// cout << "Recieved json data:" << endl << j->dump(4) << endl;
	if (j->operator[]("msg") == "setup") {
		log->type(LOG_RACE);
		log->wr("I joined a new race.\n");
	} else if (j->operator[]("msg") == "joined") {
		string joinedName = j->operator[]("payload")["profile"]["username"];
		string dispName;
		try {
			dispName = j->operator[]("payload")["profile"]["displayName"];
		} catch (const exception& e) {
			dispName = "[None]";
		}
		log->type(LOG_RACE);
		if (joinedName == "bot") {
			log->wr("Bot user '");
			log->wrs(dispName);
			log->wrs("' joined the race.\n");
		} else {
			log->wr("Human user '");
			log->wrs(joinedName);
			log->wrs("' joined the race.\n");
		}
	} else if (j->operator[]("msg") == "status" && j->operator[]("payload")["status"] == "countdown") {
		log->type(LOG_RACE);
		log->wr("The race has started.\n");
		lesson = j->operator[]("payload")["l"];
		lessonLen = lesson.length();
		lidx = 0;
		this_thread::sleep_for(chrono::milliseconds(50));
		type(ws);
	}
}
void NTClient::onMessage(WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
	if (opCode != OpCode::TEXT) {
		cout << "The realtime server did not send a text packet for some reason, ignoring.\n";
		return;
	}
	string smsg = string(msg, len);
	if (smsg == "3probe") {
		// Response to initial connection probe
		ws->send("5", OpCode::TEXT);
		// Join packet
		this_thread::sleep_for(chrono::seconds(1));
		string joinTo = getJoinPacket(20); // 20 WPM just to test
		ws->send(joinTo.c_str(), OpCode::TEXT);
	} else if (smsg.length() > 2 && smsg[0] == '4' && smsg[1] == '{') {
		string rawJData = smsg.substr(1, smsg.length());
		json jdata;
		try {
			jdata = json::parse(rawJData);
		} catch (const exception& e) {
			// Some error parsing real race data, something must be wrong
			cout << "There was an issue parsing server data: " << e.what() << endl;
			return;
		}
		handleData(ws, &jdata);
	} else {
		cout << "Recieved unknown WebSocket message: '" << smsg << "'\n";
	}
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
}
void NTClient::sendTypePacket(WebSocket<CLIENT>* ws, int idx, bool isRight) {
	json p = {
		{"stream", "race"},
		{"msg", "update"},
		{"payload", {}}
	};
	if (isRight) {
		p["payload"]["t"] = idx;
	} else {
		p["payload"]["e"] = idx;
	}
	string packet = "4" + p.dump();
	ws->send(packet.c_str(), OpCode::TEXT);
}
void NTClient::type(WebSocket<CLIENT>* ws) {
	if (lidx > lessonLen) {
		// All characters have been typed
		return;
	}
	int low = typeIntervalMS - 10;
	int high = typeIntervalMS + 10;
	bool isRight = Utils::randBool(accuracy);
	if (low < 10) {
		low = 10;
	}
}<commit_msg>Add sleeping to typing function<commit_after>#include "NTClient.h"
using namespace std;

NTClient::NTClient(int interval, double _accuracy) {
	typeIntervalMS = interval;
	accuracy = _accuracy;
	hasError = false;
	firstConnect = true;
	connected = false;
	lessonLen = 0;
	lidx = 0;
	log = new NTLogger("(Not logged in)");
}
NTClient::~NTClient() {
	delete log;
	if (wsh != nullptr) {
		delete wsh;
		wsh = nullptr;
	}
}
bool NTClient::login(string username, string password) {
	log->type(LOG_HTTP);
	log->wr("Logging into the NitroType account...\n");
	log->setUsername(username);
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				log->type(LOG_HTTP);
				log->wr("Resolved ntuserrem login token.\n");
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream uristream;
	uristream  << "wss://realtime1.nitrotype.com:443/realtime/?_primuscb=" << tnow << "-0&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "&b64=1";
	string wsURI = uristream.str();
	log->type(LOG_CONN);
	log->wr("Attempting to open a WebSocket on NitroType realtime server...\n");
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	log->type(LOG_HTTP);
	log->wr("Resolving Primus SID...\n");
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		log->type(LOG_HTTP);
		log->wr("Resolved Primus SID successfully.\n");
		// addCookie("io", primusSid);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	stringstream ss;
	ss << "4{\"stream\":\"race\",\"msg\":\"join\",\"payload\":{\"debugging\":false,\"avgSpeed\":"
	<< avgSpeed
	<< ",\"forceEarlyPlace\":true,\"track\":\"desert\",\"music\":\"city_nights\"}}";
	return ss.str();
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		log->type(LOG_CONN);
		log->wr("Established a WebSocket connection with the realtime server.\n");
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		log->type(LOG_CONN);
		log->wr("Disconnected from the realtime server.\n");
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::handleData(WebSocket<CLIENT>* ws, json* j) {
	// Uncomment to dump all raw JSON packets
	// cout << "Recieved json data:" << endl << j->dump(4) << endl;
	if (j->operator[]("msg") == "setup") {
		log->type(LOG_RACE);
		log->wr("I joined a new race.\n");
	} else if (j->operator[]("msg") == "joined") {
		string joinedName = j->operator[]("payload")["profile"]["username"];
		string dispName;
		try {
			dispName = j->operator[]("payload")["profile"]["displayName"];
		} catch (const exception& e) {
			dispName = "[None]";
		}
		log->type(LOG_RACE);
		if (joinedName == "bot") {
			log->wr("Bot user '");
			log->wrs(dispName);
			log->wrs("' joined the race.\n");
		} else {
			log->wr("Human user '");
			log->wrs(joinedName);
			log->wrs("' joined the race.\n");
		}
	} else if (j->operator[]("msg") == "status" && j->operator[]("payload")["status"] == "countdown") {
		log->type(LOG_RACE);
		log->wr("The race has started.\n");
		lesson = j->operator[]("payload")["l"];
		lessonLen = lesson.length();
		lidx = 0;
		this_thread::sleep_for(chrono::milliseconds(50));
		type(ws);
	}
}
void NTClient::onMessage(WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
	if (opCode != OpCode::TEXT) {
		cout << "The realtime server did not send a text packet for some reason, ignoring.\n";
		return;
	}
	string smsg = string(msg, len);
	if (smsg == "3probe") {
		// Response to initial connection probe
		ws->send("5", OpCode::TEXT);
		// Join packet
		this_thread::sleep_for(chrono::seconds(1));
		string joinTo = getJoinPacket(20); // 20 WPM just to test
		ws->send(joinTo.c_str(), OpCode::TEXT);
	} else if (smsg.length() > 2 && smsg[0] == '4' && smsg[1] == '{') {
		string rawJData = smsg.substr(1, smsg.length());
		json jdata;
		try {
			jdata = json::parse(rawJData);
		} catch (const exception& e) {
			// Some error parsing real race data, something must be wrong
			cout << "There was an issue parsing server data: " << e.what() << endl;
			return;
		}
		handleData(ws, &jdata);
	} else {
		cout << "Recieved unknown WebSocket message: '" << smsg << "'\n";
	}
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
}
void NTClient::sendTypePacket(WebSocket<CLIENT>* ws, int idx, bool isRight) {
	json p = {
		{"stream", "race"},
		{"msg", "update"},
		{"payload", {}}
	};
	if (isRight) {
		p["payload"]["t"] = idx;
	} else {
		p["payload"]["e"] = idx;
	}
	string packet = "4" + p.dump();
	ws->send(packet.c_str(), OpCode::TEXT);
}
void NTClient::type(WebSocket<CLIENT>* ws) {
	if (lidx > lessonLen) {
		// All characters have been typed
		return;
	}
	int low = typeIntervalMS - 10;
	int high = typeIntervalMS + 10;
	bool isRight = Utils::randBool(accuracy);
	if (low < 10) {
		low = 10;
	}
	sendTypePacket(ws, lidx, isRight);
	lidx++;
	int sleepFor = Utils::randInt(low, high);
	this_thread::sleep_for(chrono::milliseconds(sleepFor));
	type(ws); // Call the function until the lesson has been "typed"
}<|endoftext|>