<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "fileopendialog.hxx"
#include <sal/types.h>
#include "pppoptimizertoken.hxx"
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
#include <com/sun/star/ui/dialogs/FilePicker.hpp>
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
#include <com/sun/star/ui/dialogs/XFilterManager.hpp>
#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/view/XControlAccess.hpp>
#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>

#include <rtl/ustrbuf.hxx>

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::view;
using namespace ::com::sun::star::ui::dialogs;

FileOpenDialog::FileOpenDialog( const Reference< XComponentContext >& rxContext )
{
    mxFilePicker = FilePicker::createWithMode( rxContext, TemplateDescription::FILESAVE_AUTOEXTENSION);
    mxFilePicker->setMultiSelectionMode( sal_False );

    Reference< XFilePickerControlAccess > xAccess( mxFilePicker, UNO_QUERY );
    if ( xAccess.is() )
    {
        Any aValue( static_cast< sal_Bool >( sal_True ) );
        try
        {
            xAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue );
        }
        catch( com::sun::star::uno::Exception& )
        {}
    }

    // collecting a list of impress filters
    Reference< XNameAccess > xFilters( rxContext->getServiceManager()->createInstanceWithContext(
        OUString( "com.sun.star.document.FilterFactory" ), rxContext ), UNO_QUERY_THROW );
    Sequence< OUString > aFilterList( xFilters->getElementNames() );
    for ( int i = 0; i < aFilterList.getLength(); i++ )
    {
        try
        {
            Sequence< PropertyValue > aFilterProperties;
            if ( xFilters->getByName( aFilterList[ i ] ) >>= aFilterProperties )
            {
                FilterEntry aFilterEntry;
                sal_Bool bImpressFilter = sal_False;
                for ( int j = 0; j < aFilterProperties.getLength(); j++ )
                {
                    PropertyValue& rProperty( aFilterProperties[ j ] );
                    switch( TKGet( rProperty.Name ) )
                    {
                        case TK_DocumentService :
                        {
                            OUString sDocumentService;
                            rProperty.Value >>= sDocumentService;
                            if ( sDocumentService == "com.sun.star.presentation.PresentationDocument" )
                                bImpressFilter = sal_True;
                            else
                                j = aFilterProperties.getLength();
                        }
                        break;
                        case TK_Name :      rProperty.Value >>= aFilterEntry.maName; break;
                        case TK_UIName :    rProperty.Value >>= aFilterEntry.maUIName; break;
                        case TK_Type :      rProperty.Value >>= aFilterEntry.maType; break;
                        case TK_Flags :     rProperty.Value >>= aFilterEntry.maFlags; break;
                        default : break;
                    }
                }
                if ( bImpressFilter && ( ( aFilterEntry.maFlags & 3 ) == 3 ) )
                {
                    aFilterEntryList.push_back( aFilterEntry );
                }
            }
        }
        catch( Exception& )
        {
        }
    }

    Reference< XNameAccess > xTypes( rxContext->getServiceManager()->createInstanceWithContext(
        OUString( "com.sun.star.document.TypeDetection" ), rxContext ), UNO_QUERY_THROW );

    for( std::vector< FilterEntry >::const_iterator aIter(aFilterEntryList.begin()), aEnd(aFilterEntryList.end()); aIter != aEnd; ++aIter )
    {
        Sequence< PropertyValue > aTypeProperties;
        try
        {
            if ( xTypes->getByName( aIter->maType ) >>= aTypeProperties )
            {
                Sequence< OUString > aExtensions;
                for ( int i = 0; i < aTypeProperties.getLength(); i++ )
                {
                    if( aTypeProperties[ i ].Name == "Extensions" )
                    {
                        aTypeProperties[ i ].Value >>= aExtensions;
                        break;
                    }
                }
                if ( aExtensions.getLength() )
                {
                    OUString aExtension = aExtensions[0];

                    const char filter[] = "*.";
                    // the filter title must be formed in the same it is currently done
                    // in the internal implementation: "UIName (.<extension>)"
                    OUStringBuffer aUIName;
                    // the filter must be in the form "*.<extension>"
                    OUStringBuffer aFilter;

                    // form the title: "<UIName> (.<extension)"
                    aUIName.append( aIter->maUIName );
                    aUIName.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (." ));
                    aUIName.append( aExtension );
                    aUIName.append( sal_Unicode( ')' ) );
                    // form the filter: "(*.<extension>)"
                    aFilter.appendAscii( RTL_CONSTASCII_STRINGPARAM( filter ) );
                    aFilter.append( aExtensions[0] );

                    mxFilePicker->appendFilter( aUIName.makeStringAndClear(),
                                                  aFilter.makeStringAndClear() );

                    if ( aIter->maFlags & 0x100 )
                        mxFilePicker->setCurrentFilter( aIter->maUIName );
                }
            }
        }
        catch ( const Exception& )
        {
        }
    }
}
FileOpenDialog::~FileOpenDialog()
{
}
sal_Int16 FileOpenDialog::execute()
{
    return mxFilePicker->execute();
}
void FileOpenDialog::setDefaultName( const OUString& rDefaultName )
{
    mxFilePicker->setDefaultName( rDefaultName );
}
OUString FileOpenDialog::getURL() const
{
    Sequence< OUString > aFileSeq( mxFilePicker->getFiles() );
    return aFileSeq.getLength() ? aFileSeq[ 0 ] : OUString();
};
OUString FileOpenDialog::getFilterName() const
{
    OUString aFilterName;
    Reference< XFilterManager > xFilterManager( mxFilePicker, UNO_QUERY_THROW );
    OUString aUIName( xFilterManager->getCurrentFilter() );
    for( std::vector< FilterEntry >::const_iterator aIter(aFilterEntryList.begin()), aEnd(aFilterEntryList.end()); aIter != aEnd; ++aIter )
    {
        if ( aIter->maUIName == aUIName )
        {
            aFilterName = aIter->maName;
            break;
        }
    }
    return aFilterName;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Minimizer: *.mini was saved w/o .odp etc. extension (and clean up)<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "fileopendialog.hxx"
#include <sal/types.h>
#include "pppoptimizertoken.hxx"
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
#include <com/sun/star/ui/dialogs/FilePicker.hpp>
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
#include <com/sun/star/ui/dialogs/XFilterManager.hpp>
#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/view/XControlAccess.hpp>
#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::view;
using namespace ::com::sun::star::ui::dialogs;

FileOpenDialog::FileOpenDialog( const Reference< XComponentContext >& rxContext )
{
    mxFilePicker = FilePicker::createWithMode( rxContext, TemplateDescription::FILESAVE_AUTOEXTENSION);
    mxFilePicker->setMultiSelectionMode( sal_False );

    Reference< XFilePickerControlAccess > xAccess( mxFilePicker, UNO_QUERY );
    if ( xAccess.is() )
    {
        Any aValue( static_cast< sal_Bool >( sal_True ) );
        try
        {
            xAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue );
        }
        catch( com::sun::star::uno::Exception& )
        {}
    }

    // collecting a list of impress filters
    Reference< XNameAccess > xFilters( rxContext->getServiceManager()->createInstanceWithContext(
        OUString( "com.sun.star.document.FilterFactory" ), rxContext ), UNO_QUERY_THROW );
    Sequence< OUString > aFilterList( xFilters->getElementNames() );
    for ( int i = 0; i < aFilterList.getLength(); i++ )
    {
        try
        {
            Sequence< PropertyValue > aFilterProperties;
            if ( xFilters->getByName( aFilterList[ i ] ) >>= aFilterProperties )
            {
                FilterEntry aFilterEntry;
                sal_Bool bImpressFilter = sal_False;
                for ( int j = 0; j < aFilterProperties.getLength(); j++ )
                {
                    PropertyValue& rProperty( aFilterProperties[ j ] );
                    switch( TKGet( rProperty.Name ) )
                    {
                        case TK_DocumentService :
                        {
                            OUString sDocumentService;
                            rProperty.Value >>= sDocumentService;
                            if ( sDocumentService == "com.sun.star.presentation.PresentationDocument" )
                                bImpressFilter = sal_True;
                            else
                                j = aFilterProperties.getLength();
                        }
                        break;
                        case TK_Name :      rProperty.Value >>= aFilterEntry.maName; break;
                        case TK_UIName :    rProperty.Value >>= aFilterEntry.maUIName; break;
                        case TK_Type :      rProperty.Value >>= aFilterEntry.maType; break;
                        case TK_Flags :     rProperty.Value >>= aFilterEntry.maFlags; break;
                        default : break;
                    }
                }
                if ( bImpressFilter && ( ( aFilterEntry.maFlags & 3 ) == 3 ) )
                {
                    aFilterEntryList.push_back( aFilterEntry );
                }
            }
        }
        catch( Exception& )
        {
        }
    }

    Reference< XNameAccess > xTypes( rxContext->getServiceManager()->createInstanceWithContext(
        OUString( "com.sun.star.document.TypeDetection" ), rxContext ), UNO_QUERY_THROW );

    for( std::vector< FilterEntry >::const_iterator aIter(aFilterEntryList.begin()), aEnd(aFilterEntryList.end()); aIter != aEnd; ++aIter )
    {
        Sequence< PropertyValue > aTypeProperties;
        try
        {
            if ( xTypes->getByName( aIter->maType ) >>= aTypeProperties )
            {
                Sequence< OUString > aExtensions;
                for ( int i = 0; i < aTypeProperties.getLength(); i++ )
                {
                    if( aTypeProperties[ i ].Name == "Extensions" )
                    {
                        aTypeProperties[ i ].Value >>= aExtensions;
                        break;
                    }
                }
                if ( aExtensions.getLength() )
                {
                    // The filter title must be formed in the same way it is
                    // currently done in the internal implementation:
                    OUString aTitle(
                        aIter->maUIName + " (." + aExtensions[0] + ")");
                    OUString aFilter("*." + aExtensions[0]);
                    mxFilePicker->appendFilter(aTitle, aFilter);
                    if ( aIter->maFlags & 0x100 )
                        mxFilePicker->setCurrentFilter(aTitle);
                }
            }
        }
        catch ( const Exception& )
        {
        }
    }
}
FileOpenDialog::~FileOpenDialog()
{
}
sal_Int16 FileOpenDialog::execute()
{
    return mxFilePicker->execute();
}
void FileOpenDialog::setDefaultName( const OUString& rDefaultName )
{
    mxFilePicker->setDefaultName( rDefaultName );
}
OUString FileOpenDialog::getURL() const
{
    Sequence< OUString > aFileSeq( mxFilePicker->getFiles() );
    return aFileSeq.getLength() ? aFileSeq[ 0 ] : OUString();
};
OUString FileOpenDialog::getFilterName() const
{
    OUString aFilterName;
    Reference< XFilterManager > xFilterManager( mxFilePicker, UNO_QUERY_THROW );
    OUString aUIName( xFilterManager->getCurrentFilter() );
    for( std::vector< FilterEntry >::const_iterator aIter(aFilterEntryList.begin()), aEnd(aFilterEntryList.end()); aIter != aEnd; ++aIter )
    {
        if ( aIter->maUIName == aUIName )
        {
            aFilterName = aIter->maName;
            break;
        }
    }
    return aFilterName;
};

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


<commit_before>/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2018 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#include "NewtonEuler5DR.hpp"
#include "Interaction.hpp"
#include "BlockVector.hpp"
#include "RotationQuaternion.hpp"
#include "op3x3.h"

// #define DEBUG_NOCOLOR
// #define DEBUG_STDOUT
// #define DEBUG_MESSAGES
#include "debug.h"

/*
See devNotes.pdf for details. A detailed documentation is available in DevNotes.pdf: chapter 'NewtonEulerR: computation of \nabla q H'. Subsection 'Case RFC3D: using the local frame local velocities'
*/
void NewtonEuler5DR::initialize(Interaction& inter)
{
  DEBUG_BEGIN("NewtonEuler5DR::NewtonEuler5DR::initialize(Interaction& inter)\n");
  NewtonEuler1DR::initialize(inter);
  unsigned int qSize = 7 * (inter.getSizeOfDS() / 6);
  /*keep only the distance.*/
  _jachq.reset(new SimpleMatrix(5, qSize));

  _rotationAbsoluteToContactFrame.reset(new SimpleMatrix(3, 3));
  _AUX2.reset(new SimpleMatrix(3, 3));
  //  _isContact=1;
  DEBUG_END("NewtonEuler5DR::NewtonEuler5DR::initialize(Interaction& inter)\n");
}
void NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)
{
  DEBUG_BEGIN("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)\n");
  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Nz = _Nc->getValue(2);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double Pz = _Pc1->getValue(2);
  double G1x = q1->getValue(0);
  double G1y = q1->getValue(1);
  double G1z = q1->getValue(2);

  DEBUG_PRINT("contact normal:\n");
  DEBUG_EXPR(_Nc->display(););
  DEBUG_PRINTF("_Nc->norm2() -1.0 = %e\n",_Nc->norm2()-1.0);
  DEBUG_PRINT("contact point :\n");
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_PRINT("center of mass :\n");
  DEBUG_EXPR(q1->display(););

  assert(_Nc->norm2() >0.0
         && std::abs(_Nc->norm2()-1.0) < 1e-6
         && "NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Normal vector not consistent ") ;

  double t[6];
  double * pt = t;

  // 1 - Construction of the local contact frame from the normal vector

  if (orthoBaseFromVector(&Nx, &Ny, &Nz, pt, pt + 1, pt + 2, pt + 3, pt + 4, pt + 5))
    RuntimeException::selfThrow("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Problem in calling orthoBaseFromVector");

  // 2 - Construction of the rotation matrix from the absolute frame to the local contact frame
  pt = t;
  _rotationAbsoluteToContactFrame->setValue(0, 0, Nx);
  _rotationAbsoluteToContactFrame->setValue(1, 0, *pt);
  _rotationAbsoluteToContactFrame->setValue(2, 0, *(pt + 3));
  _rotationAbsoluteToContactFrame->setValue(0, 1, Ny);
  _rotationAbsoluteToContactFrame->setValue(1, 1, *(pt + 1));
  _rotationAbsoluteToContactFrame->setValue(2, 1, *(pt + 4));
  _rotationAbsoluteToContactFrame->setValue(0, 2, Nz);
  _rotationAbsoluteToContactFrame->setValue(1, 2, *(pt + 2));
  _rotationAbsoluteToContactFrame->setValue(2, 2, *(pt + 5));
  DEBUG_PRINT("_rotationAbsoluteToContactFrame:\n");
  DEBUG_EXPR(_rotationAbsoluteToContactFrame->display(););

  // 3 - Construction of the lever arm matrix in  the absolute frame
  _NPG1->zero();
  (*_NPG1)(0, 0) = 0;
  (*_NPG1)(0, 1) = -(G1z - Pz);
  (*_NPG1)(0, 2) = (G1y - Py);
  (*_NPG1)(1, 0) = (G1z - Pz);
  (*_NPG1)(1, 1) = 0;
  (*_NPG1)(1, 2) = -(G1x - Px);
  (*_NPG1)(2, 0) = -(G1y - Py);
  (*_NPG1)(2, 1) = (G1x - Px);
  (*_NPG1)(2, 2) = 0;

  DEBUG_PRINT("lever arm skew matrix :\n");
  DEBUG_EXPR(_NPG1->display(););

  /* The Jacobian matrix (H) is given by the product
   * H = _rotationAbsoluteToContactFrame
   * for the translation part and
   * H = _rotationAbsoluteToContactFrame * leverArmMatrix * _rotationBodyToAbsoluteFrame
   * for the rotation part and
   */

  // 4 - Compute the rotation matrix from the body-fixed frame to the absolute frame
  computeRotationMatrix(q1,_rotationBodyToAbsoluteFrame);
  DEBUG_EXPR(_rotationBodyToAbsoluteFrame->display(););

  // 5 - compose the body lever arm matrix with the rotation matrix
  prod(*_NPG1, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  DEBUG_EXPR(_rotationBodyToAbsoluteFrame->display(););
  DEBUG_EXPR(_AUX1->display(););

  // 6 -  Rotate the resulting matric in the contact frame
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);
  DEBUG_EXPR(_rotationAbsoluteToContactFrame->display(););
  DEBUG_EXPR(_AUX2->display(););

  // 7 - fill the Jacobian
  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj, _rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii-2, jj-3));

  DEBUG_EXPR(_jachqT->display(););

  // DEBUG_EXPR_WE(
  //   SP::SimpleMatrix jaux(new SimpleMatrix(*_jachqT));
  //   jaux->trans();
  //   SP::SiconosVector v(new SiconosVector(3));
  //   SP::SiconosVector vRes(new SiconosVector(6));
  //   v->zero();
  //   v->setValue(0, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   v->zero();
  //   v->setValue(1, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   v->zero();
  //   v->setValue(2, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   );
  DEBUG_END("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)\n");
  //getchar();
}

void NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)
{
  DEBUG_BEGIN("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)\n");
  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Nz = _Nc->getValue(2);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double Pz = _Pc1->getValue(2);
  double G1x = q1->getValue(0);
  double G1y = q1->getValue(1);
  double G1z = q1->getValue(2);
  double G2x = q2->getValue(0);
  double G2y = q2->getValue(1);
  double G2z = q2->getValue(2);

  DEBUG_PRINT("contact normal:\n");
  DEBUG_EXPR(_Nc->display(););
  DEBUG_PRINT("contact point :\n");
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_PRINT("center of mass :\n");
  DEBUG_EXPR(q1->display(););

  double t[6];
  double * pt = t;
  if(orthoBaseFromVector(&Nx, &Ny, &Nz, pt, pt + 1, pt + 2, pt + 3, pt + 4, pt + 5))
    RuntimeException::selfThrow("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Problem in calling orthoBaseFromVector");
  pt = t;
  _rotationAbsoluteToContactFrame->setValue(0, 0, Nx);
  _rotationAbsoluteToContactFrame->setValue(1, 0, *pt);
  _rotationAbsoluteToContactFrame->setValue(2, 0, *(pt + 3));
  _rotationAbsoluteToContactFrame->setValue(0, 1, Ny);
  _rotationAbsoluteToContactFrame->setValue(1, 1, *(pt + 1));
  _rotationAbsoluteToContactFrame->setValue(2, 1, *(pt + 4));
  _rotationAbsoluteToContactFrame->setValue(0, 2, Nz);
  _rotationAbsoluteToContactFrame->setValue(1, 2, *(pt + 2));
  _rotationAbsoluteToContactFrame->setValue(2, 2, *(pt + 5));

  _NPG1->zero();

  (*_NPG1)(0, 0) = 0;
  (*_NPG1)(0, 1) = -(G1z - Pz);
  (*_NPG1)(0, 2) = (G1y - Py);
  (*_NPG1)(1, 0) = (G1z - Pz);
  (*_NPG1)(1, 1) = 0;
  (*_NPG1)(1, 2) = -(G1x - Px);
  (*_NPG1)(2, 0) = -(G1y - Py);
  (*_NPG1)(2, 1) = (G1x - Px);
  (*_NPG1)(2, 2) = 0;

  _NPG2->zero();

  (*_NPG2)(0, 0) = 0;
  (*_NPG2)(0, 1) = -(G2z - Pz);
  (*_NPG2)(0, 2) = (G2y - Py);
  (*_NPG2)(1, 0) = (G2z - Pz);
  (*_NPG2)(1, 1) = 0;
  (*_NPG2)(1, 2) = -(G2x - Px);
  (*_NPG2)(2, 0) = -(G2y - Py);
  (*_NPG2)(2, 1) = (G2x - Px);
  (*_NPG2)(2, 2) = 0;

  computeRotationMatrix(q1,_rotationBodyToAbsoluteFrame);
  prod(*_NPG1, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj, _rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii-2, jj-3));

  computeRotationMatrix(q2,_rotationBodyToAbsoluteFrame);
  prod(*_NPG2, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj + 6, -_rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj + 6, -_AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii-2, jj-3));

  DEBUG_EXPR(_jachqT->display(););

  DEBUG_END("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)\n");

}

void NewtonEuler5DR::computeJachqT(Interaction& inter, SP::BlockVector q0)
{
  DEBUG_BEGIN("NewtonEuler5DR::computeJachqT(Interaction& inter,  SP::BlockVector q0)\n");
  if (q0->numberOfBlocks()>1)
  {
    RFC3DcomputeJachqTFromContacts((q0->getAllVect())[0], (q0->getAllVect())[1]);
  }
  else
  {
    RFC3DcomputeJachqTFromContacts((q0->getAllVect())[0]);
  }
  DEBUG_END("NewtonEuler5DR::computeJachqT(Interaction& inter,  SP::BlockVector q0)\n");

}
<commit_msg>[kernel] correct sign bug in NewtonEuler5DR<commit_after>/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2018 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#include "NewtonEuler5DR.hpp"
#include "Interaction.hpp"
#include "BlockVector.hpp"
#include "RotationQuaternion.hpp"
#include "op3x3.h"

// #define DEBUG_NOCOLOR
// #define DEBUG_STDOUT
// #define DEBUG_MESSAGES
#include "debug.h"

/*
See devNotes.pdf for details. A detailed documentation is available in DevNotes.pdf: chapter 'NewtonEulerR: computation of \nabla q H'. Subsection 'Case RFC3D: using the local frame local velocities'
*/
void NewtonEuler5DR::initialize(Interaction& inter)
{
  DEBUG_BEGIN("NewtonEuler5DR::NewtonEuler5DR::initialize(Interaction& inter)\n");
  NewtonEuler1DR::initialize(inter);
  unsigned int qSize = 7 * (inter.getSizeOfDS() / 6);
  /*keep only the distance.*/
  _jachq.reset(new SimpleMatrix(5, qSize));

  _rotationAbsoluteToContactFrame.reset(new SimpleMatrix(3, 3));
  _AUX2.reset(new SimpleMatrix(3, 3));
  //  _isContact=1;
  DEBUG_END("NewtonEuler5DR::NewtonEuler5DR::initialize(Interaction& inter)\n");
}
void NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)
{
  DEBUG_BEGIN("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)\n");
  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Nz = _Nc->getValue(2);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double Pz = _Pc1->getValue(2);
  double G1x = q1->getValue(0);
  double G1y = q1->getValue(1);
  double G1z = q1->getValue(2);

  DEBUG_PRINT("contact normal:\n");
  DEBUG_EXPR(_Nc->display(););
  DEBUG_PRINTF("_Nc->norm2() -1.0 = %e\n",_Nc->norm2()-1.0);
  DEBUG_PRINT("contact point :\n");
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_PRINT("center of mass :\n");
  DEBUG_EXPR(q1->display(););

  assert(_Nc->norm2() >0.0
         && std::abs(_Nc->norm2()-1.0) < 1e-6
         && "NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Normal vector not consistent ") ;

  double t[6];
  double * pt = t;

  // 1 - Construction of the local contact frame from the normal vector

  if (orthoBaseFromVector(&Nx, &Ny, &Nz, pt, pt + 1, pt + 2, pt + 3, pt + 4, pt + 5))
    RuntimeException::selfThrow("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Problem in calling orthoBaseFromVector");

  // 2 - Construction of the rotation matrix from the absolute frame to the local contact frame
  pt = t;
  _rotationAbsoluteToContactFrame->setValue(0, 0, Nx);
  _rotationAbsoluteToContactFrame->setValue(1, 0, *pt);
  _rotationAbsoluteToContactFrame->setValue(2, 0, *(pt + 3));
  _rotationAbsoluteToContactFrame->setValue(0, 1, Ny);
  _rotationAbsoluteToContactFrame->setValue(1, 1, *(pt + 1));
  _rotationAbsoluteToContactFrame->setValue(2, 1, *(pt + 4));
  _rotationAbsoluteToContactFrame->setValue(0, 2, Nz);
  _rotationAbsoluteToContactFrame->setValue(1, 2, *(pt + 2));
  _rotationAbsoluteToContactFrame->setValue(2, 2, *(pt + 5));
  DEBUG_PRINT("_rotationAbsoluteToContactFrame:\n");
  DEBUG_EXPR(_rotationAbsoluteToContactFrame->display(););

  // 3 - Construction of the lever arm matrix in  the absolute frame
  _NPG1->zero();
  (*_NPG1)(0, 0) = 0;
  (*_NPG1)(0, 1) = -(G1z - Pz);
  (*_NPG1)(0, 2) = (G1y - Py);
  (*_NPG1)(1, 0) = (G1z - Pz);
  (*_NPG1)(1, 1) = 0;
  (*_NPG1)(1, 2) = -(G1x - Px);
  (*_NPG1)(2, 0) = -(G1y - Py);
  (*_NPG1)(2, 1) = (G1x - Px);
  (*_NPG1)(2, 2) = 0;

  DEBUG_PRINT("lever arm skew matrix :\n");
  DEBUG_EXPR(_NPG1->display(););

  /* The Jacobian matrix (H) is given by the product
   * H = _rotationAbsoluteToContactFrame
   * for the translation part and
   * H = _rotationAbsoluteToContactFrame * leverArmMatrix * _rotationBodyToAbsoluteFrame
   * for the rotation part and
   */

  // 4 - Compute the rotation matrix from the body-fixed frame to the absolute frame
  computeRotationMatrix(q1,_rotationBodyToAbsoluteFrame);
  DEBUG_EXPR(_rotationBodyToAbsoluteFrame->display(););

  // 5 - compose the body lever arm matrix with the rotation matrix
  prod(*_NPG1, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  DEBUG_EXPR(_rotationBodyToAbsoluteFrame->display(););
  DEBUG_EXPR(_AUX1->display(););

  // 6 -  Rotate the resulting matric in the contact frame
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);
  DEBUG_EXPR(_rotationAbsoluteToContactFrame->display(););
  DEBUG_EXPR(_AUX2->display(););

  // 7 - fill the Jacobian
  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj, _rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii-2, jj-3));

  DEBUG_EXPR(_jachqT->display(););

  // DEBUG_EXPR_WE(
  //   SP::SimpleMatrix jaux(new SimpleMatrix(*_jachqT));
  //   jaux->trans();
  //   SP::SiconosVector v(new SiconosVector(3));
  //   SP::SiconosVector vRes(new SiconosVector(6));
  //   v->zero();
  //   v->setValue(0, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   v->zero();
  //   v->setValue(1, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   v->zero();
  //   v->setValue(2, 1);
  //   prod(*jaux, *v, *vRes, true);
  //   vRes->display();
  //   );
  DEBUG_END("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1)\n");
  //getchar();
}

void NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)
{
  DEBUG_BEGIN("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)\n");
  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Nz = _Nc->getValue(2);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double Pz = _Pc1->getValue(2);
  double G1x = q1->getValue(0);
  double G1y = q1->getValue(1);
  double G1z = q1->getValue(2);
  double G2x = q2->getValue(0);
  double G2y = q2->getValue(1);
  double G2z = q2->getValue(2);

  DEBUG_PRINT("contact normal:\n");
  DEBUG_EXPR(_Nc->display(););
  DEBUG_PRINT("contact point :\n");
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_PRINT("center of mass :\n");
  DEBUG_EXPR(q1->display(););

  double t[6];
  double * pt = t;
  if(orthoBaseFromVector(&Nx, &Ny, &Nz, pt, pt + 1, pt + 2, pt + 3, pt + 4, pt + 5))
    RuntimeException::selfThrow("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts. Problem in calling orthoBaseFromVector");
  pt = t;
  _rotationAbsoluteToContactFrame->setValue(0, 0, Nx);
  _rotationAbsoluteToContactFrame->setValue(1, 0, *pt);
  _rotationAbsoluteToContactFrame->setValue(2, 0, *(pt + 3));
  _rotationAbsoluteToContactFrame->setValue(0, 1, Ny);
  _rotationAbsoluteToContactFrame->setValue(1, 1, *(pt + 1));
  _rotationAbsoluteToContactFrame->setValue(2, 1, *(pt + 4));
  _rotationAbsoluteToContactFrame->setValue(0, 2, Nz);
  _rotationAbsoluteToContactFrame->setValue(1, 2, *(pt + 2));
  _rotationAbsoluteToContactFrame->setValue(2, 2, *(pt + 5));

  _NPG1->zero();

  (*_NPG1)(0, 0) = 0;
  (*_NPG1)(0, 1) = -(G1z - Pz);
  (*_NPG1)(0, 2) = (G1y - Py);
  (*_NPG1)(1, 0) = (G1z - Pz);
  (*_NPG1)(1, 1) = 0;
  (*_NPG1)(1, 2) = -(G1x - Px);
  (*_NPG1)(2, 0) = -(G1y - Py);
  (*_NPG1)(2, 1) = (G1x - Px);
  (*_NPG1)(2, 2) = 0;

  _NPG2->zero();

  (*_NPG2)(0, 0) = 0;
  (*_NPG2)(0, 1) = -(G2z - Pz);
  (*_NPG2)(0, 2) = (G2y - Py);
  (*_NPG2)(1, 0) = (G2z - Pz);
  (*_NPG2)(1, 1) = 0;
  (*_NPG2)(1, 2) = -(G2x - Px);
  (*_NPG2)(2, 0) = -(G2y - Py);
  (*_NPG2)(2, 1) = (G2x - Px);
  (*_NPG2)(2, 2) = 0;

  computeRotationMatrix(q1,_rotationBodyToAbsoluteFrame);
  prod(*_NPG1, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj, _rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, _AUX2->getValue(ii-2, jj-3));

  computeRotationMatrix(q2,_rotationBodyToAbsoluteFrame);
  prod(*_NPG2, *_rotationBodyToAbsoluteFrame, *_AUX1, true);
  prod(*_rotationAbsoluteToContactFrame, *_AUX1, *_AUX2, true);

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 0; jj < 3; jj++)
      _jachqT->setValue(ii, jj + 6, -_rotationAbsoluteToContactFrame->getValue(ii, jj));

  for (unsigned int ii = 0; ii < 3; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj + 6, -_AUX2->getValue(ii, jj - 3));

  prod(*_rotationAbsoluteToContactFrame, *_rotationBodyToAbsoluteFrame, *_AUX2, true);
  DEBUG_EXPR(_AUX2->display(););

  for (unsigned int ii = 3; ii < 5; ii++)
    for (unsigned int jj = 3; jj < 6; jj++)
      _jachqT->setValue(ii, jj, -_AUX2->getValue(ii-2, jj-3));

  DEBUG_EXPR(_jachqT->display(););

  DEBUG_END("NewtonEuler5DR::RFC3DcomputeJachqTFromContacts(SP::SiconosVector q1, SP::SiconosVector q2)\n");

}

void NewtonEuler5DR::computeJachqT(Interaction& inter, SP::BlockVector q0)
{
  DEBUG_BEGIN("NewtonEuler5DR::computeJachqT(Interaction& inter,  SP::BlockVector q0)\n");
  if (q0->numberOfBlocks()>1)
  {
    RFC3DcomputeJachqTFromContacts((q0->getAllVect())[0], (q0->getAllVect())[1]);
  }
  else
  {
    RFC3DcomputeJachqTFromContacts((q0->getAllVect())[0]);
  }
  DEBUG_END("NewtonEuler5DR::computeJachqT(Interaction& inter,  SP::BlockVector q0)\n");

}
<|endoftext|>


<commit_before>
#include "ksp_plugin/interface.hpp"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ksp_plugin_test/fake_plugin.hpp"
#include "testing_utilities/componentwise.hpp"
#include "testing_utilities/is_near.hpp"
#include "testing_utilities/matchers.hpp"
#include "testing_utilities/solar_system_factory.hpp"

namespace principia {
namespace interface {

using astronomy::ICRFJ2000Equator;
using base::make_not_null_unique;
using ksp_plugin::GUID;
using ksp_plugin::Navigation;
using ksp_plugin::PartId;
using ksp_plugin::FakePlugin;
using ksp_plugin::Vessel;
using physics::SolarSystem;
using quantities::si::Hour;
using quantities::si::Kilo;
using quantities::si::Kilogram;
using quantities::si::Metre;
using quantities::si::Micro;
using quantities::si::Newton;
using quantities::si::Tonne;
using testing_utilities::Componentwise;
using testing_utilities::IsOk;
using testing_utilities::IsNear;
using testing_utilities::SolarSystemFactory;
using ::testing::Eq;

namespace {

constexpr PartId part_id = 1729;
constexpr char const* vessel_guid = "NCC 1701-D";
constexpr char const* part_name = "Picard's desk";
constexpr char const* vessel_name = "Enterprise";

}  // namespace

class InterfaceExternalTest : public ::testing::Test {
 protected:
  InterfaceExternalTest()
      : plugin_(SolarSystem<ICRFJ2000Equator>(
            SOLUTION_DIR / "astronomy" / "sol_gravity_model.proto.txt",
            SOLUTION_DIR / "astronomy" /
                "sol_initial_state_jd_2451545_000000000.proto.txt")) {
    physics::KeplerianElements<Barycentric> low_earth_orbit;
    low_earth_orbit.eccentricity = 0;
    low_earth_orbit.semimajor_axis = 6783 * Kilo(Metre);
    low_earth_orbit.inclination = 0 * Degree;
    low_earth_orbit.longitude_of_ascending_node = 0 * Radian;
    low_earth_orbit.argument_of_periapsis = 0 * Radian;
    low_earth_orbit.mean_anomaly = 0 * Radian;
    vessel_ = &plugin_.AddVesselInEarthOrbit(
        vessel_guid, vessel_name, part_id, part_name, low_earth_orbit);
  }

  FakePlugin plugin_;
  Vessel* vessel_;
};

TEST_F(InterfaceExternalTest, GetNearestPlannedCoastDegreesOfFreedom) {
  plugin_.CreateFlightPlan(
      vessel_guid, plugin_.CurrentTime() + 24 * Hour, 1 * Tonne);
  vessel_->flight_plan().Append(ksp_plugin::Burn{
      180 * Kilo(Newton),
      4.56 * Kilo(Newton) * Second / Kilogram,
      plugin_.NewBodyCentredNonRotatingNavigationFrame(
          SolarSystemFactory::Earth),
      plugin_.CurrentTime() + 30 * Second,
      Velocity<Frenet<Navigation>>(
          {1000 * Metre / Second, 0 * Metre / Second, 0 * Metre / Second}),
      /*is_inertially_fixed=*/false});
  QP result;
  auto const to_world =
      plugin_.renderer().BarycentricToWorld(plugin_.PlanetariumRotation());
  auto const status = principia__ExternalGetNearestPlannedCoastDegreesOfFreedom(
      &plugin_,
      SolarSystemFactory::Earth,
      vessel_guid,
      /*manoeuvre_index=*/0,
      /*reference_position=*/ToXYZ(
          to_world(Displacement<Barycentric>(
              {-100'000 * Kilo(Metre), 0 * Metre, 0 * Metre})).coordinates() /
                  Metre),
      &result);
  EXPECT_THAT(base::Status(static_cast<base::Error>(status.error), ""), IsOk());
  auto const barycentric_result =
      to_world.Inverse()(FromQP<RelativeDegreesOfFreedom<World>>(result));
  // The reference position is far above the apoapsis, so the result is roughly
  // the apoapsis.
  EXPECT_THAT(barycentric_result,
              Componentwise(Componentwise(IsNear(-12'000 * Kilo(Metre)),
                                          IsNear(-120 * Kilo(Metre)),
                                          IsNear(2.2 * Metre)),
                            Componentwise(IsNear(-6.6 * Metre / Second),
                                          IsNear(-4.9 * Kilo(Metre) / Second),
                                          IsNear(54 * Micro(Metre) / Second))));
}

}  // namespace interface
}  // namespace principia
<commit_msg>Work around an MSVC bug.<commit_after>
#include "ksp_plugin/interface.hpp"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ksp_plugin_test/fake_plugin.hpp"
#include "testing_utilities/componentwise.hpp"
#include "testing_utilities/is_near.hpp"
#include "testing_utilities/matchers.hpp"
#include "testing_utilities/solar_system_factory.hpp"

namespace principia {
namespace interface {

using astronomy::ICRFJ2000Equator;
using base::make_not_null_unique;
using ksp_plugin::GUID;
using ksp_plugin::Navigation;
using ksp_plugin::PartId;
using ksp_plugin::FakePlugin;
using ksp_plugin::Vessel;
using physics::SolarSystem;
using quantities::si::Hour;
using quantities::si::Kilo;
using quantities::si::Kilogram;
using quantities::si::Metre;
using quantities::si::Micro;
using quantities::si::Newton;
using quantities::si::Tonne;
using testing_utilities::Componentwise;
using testing_utilities::IsOk;
using testing_utilities::IsNear;
using testing_utilities::SolarSystemFactory;
using ::testing::Eq;

namespace {

constexpr PartId part_id = 1729;
constexpr char const* vessel_guid = "NCC 1701-D";
constexpr char const* part_name = "Picard's desk";
constexpr char const* vessel_name = "Enterprise";

}  // namespace

class InterfaceExternalTest : public ::testing::Test {
 protected:
  InterfaceExternalTest()
      : plugin_(SolarSystem<ICRFJ2000Equator>(
            SOLUTION_DIR / "astronomy" / "sol_gravity_model.proto.txt",
            SOLUTION_DIR / "astronomy" /
                "sol_initial_state_jd_2451545_000000000.proto.txt")) {
    physics::KeplerianElements<Barycentric> low_earth_orbit;
    low_earth_orbit.eccentricity = 0;
    low_earth_orbit.semimajor_axis = 6783 * Kilo(Metre);
    low_earth_orbit.inclination = 0 * Degree;
    low_earth_orbit.longitude_of_ascending_node = 0 * Radian;
    low_earth_orbit.argument_of_periapsis = 0 * Radian;
    low_earth_orbit.mean_anomaly = 0 * Radian;
    vessel_ = &plugin_.AddVesselInEarthOrbit(
        vessel_guid, vessel_name, part_id, part_name, low_earth_orbit);
  }

  FakePlugin plugin_;
  Vessel* vessel_;
};

TEST_F(InterfaceExternalTest, GetNearestPlannedCoastDegreesOfFreedom) {
  plugin_.CreateFlightPlan(
      vessel_guid, plugin_.CurrentTime() + 24 * Hour, 1 * Tonne);
  // This variable is necessary in VS 2017 15.8 preview 3 because putting the
  // list initialization directly in the call below causes the frame to be
  // destroyed after the call.
  auto burn = ksp_plugin::Burn{
      180 * Kilo(Newton),
      4.56 * Kilo(Newton) * Second / Kilogram,
      plugin_.NewBodyCentredNonRotatingNavigationFrame(
          SolarSystemFactory::Earth),
      plugin_.CurrentTime() + 30 * Second,
      Velocity<Frenet<Navigation>>(
          {1000 * Metre / Second, 0 * Metre / Second, 0 * Metre / Second}),
      /*is_inertially_fixed=*/false};
  vessel_->flight_plan().Append(std::move(burn));
  QP result;
  auto const to_world =
      plugin_.renderer().BarycentricToWorld(plugin_.PlanetariumRotation());
  auto const status = principia__ExternalGetNearestPlannedCoastDegreesOfFreedom(
      &plugin_,
      SolarSystemFactory::Earth,
      vessel_guid,
      /*manoeuvre_index=*/0,
      /*reference_position=*/ToXYZ(
          to_world(Displacement<Barycentric>(
              {-100'000 * Kilo(Metre), 0 * Metre, 0 * Metre})).coordinates() /
                  Metre),
      &result);
  EXPECT_THAT(base::Status(static_cast<base::Error>(status.error), ""), IsOk());
  auto const barycentric_result =
      to_world.Inverse()(FromQP<RelativeDegreesOfFreedom<World>>(result));
  // The reference position is far above the apoapsis, so the result is roughly
  // the apoapsis.
  EXPECT_THAT(barycentric_result,
              Componentwise(Componentwise(IsNear(-12'000 * Kilo(Metre)),
                                          IsNear(-120 * Kilo(Metre)),
                                          IsNear(2.2 * Metre)),
                            Componentwise(IsNear(-6.6 * Metre / Second),
                                          IsNear(-4.9 * Kilo(Metre) / Second),
                                          IsNear(54 * Micro(Metre) / Second))));
}

}  // namespace interface
}  // namespace principia
<|endoftext|>


<commit_before>#include "rshell.h"

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <vector>
#include <sstream>

using namespace std;

//  Constructors
//  Default constructor (creates an Rshell object for commands)
Rshell::Rshell()
{}

//  Rshell functions
//  These functions takes command input from the user and parses them
//  parseCommand(string& input, char line[][256], char* argv[][64]) -
//      parses out whitespace and puts charaters from string into array of char
void Rshell::parseCommand(string& input, char line[][256], char* argv[][64])
{
    unsigned row = 0;
    unsigned col = 0;
    bool quote = false;     //  Has a flag if the argument is in quotations
    clearArray(line);       //  Cleans array

    //  Parses string into the array (takes out whitespace)
    for(unsigned i = 0; i < input.size(); ++i)
    {
        if(!quote)
        {
            if(input.at(i) == '#')  //  Finishes with a comment
            {
                break;
            }
            if((input.at(i) == ' ') || (input.at(i) == '\t') ||
                (input.at(i) == '\n'))  //  Replaces whitespace with ' ' if dne
            {
                if((col > 0) &&
                    !((input.at(i + 1) == '&') ||
                    (input.at(i + 1) == '|') ||
                    (input.at(i + 1) == ';')))  //  Makes sure !connector
                {
                    if(line[row][col-1] != ' ')
                    {
                        line[row][col] = ' ';
                        ++col;
                    }
                }
            }
            else if(input.at(i) == ';')     //  Treat ';' as a newline
            {
                row++;
                col = 0;
            }
            else if(input.at(i) == '&')     //  Checks for &&
            {
                parseConnect(input, i, line, '&', row, col);
            }
            else if(input.at(i) == '|')     //  Checks for ||
            {
                parseConnect(input, i, line, '|', row, col);
            }
            else    //  Any other character
            {
                line[row][col] = input.at(i);
                col++;
                if(input.at(i) == '"')      //  Checks for "
                {
                    quote = true;
                }
            }
        }
        else    //  Character is in quotes
        {
            line[row][col] = input.at(i);
            col++;
            if(input.at(i) == '"')
            {
                quote = false;
            }
        }
    }

    //  Sets up the argv array
    row = 0;
    col = 0;
    quote = false;
    clearArrayP(argv);

    //  Looks thrugh lin eand replaces any ' ' with \0'
    for(unsigned i = 0; line[i][0] != '\0'; ++i)
    {
        for(unsigned j = 0; line[i][j] != '\0'; ++j)
        {
            if(j == 0)  //  Gets the command
            {
                argv[row][col] = &line[i][j];
                ++col;
            }
            if(!quote && (line[i][j] == ' '))   //  Replaces space with '\0'
            {
                line[i][j] = '\0';
                argv[row][col] = &line[i][j + 1];
                ++col;
            }
            if(line[i][j] == '"')   //  Triggers quotes
            {
                quote = !quote;
            }
        }
        ++row;      //  Goes to the next row
        col = 0;
    }

   //  Shows all addresses in argv
    for(unsigned i = 0; argv[i][0] != '\0'; ++i)
    {
        cout << "Argument " << i << ": " << argv[row] << endl;
        for(unsigned j = 0; argv[i][j] != '\0'; ++j)
        {
            cout << "Argument [" << i << "][" << j << "]: " << argv[i][j]
                    << endl;
        }
        cout << endl;
    }
    return;
}

//  void parseConnect(string&, unsigned, char [][], char, unsigned&, unsigned&)-
//      checks if an '&' or '|'  is a connector or not
void Rshell::parseConnect(string& input, unsigned pos, char line[][256], char con, unsigned& row, unsigned& col)
{
    if(col == 1)
    {
        line[row][col] = input.at(pos);
        col++;
        if(line[row][0] == con)         //  if prev char is connector
        {
            row++;
            col = 0;
        }
    }
    else
    {
        if(input.at(pos + 1) == con)    //  if next char is connector
        {
            row++;
            col = 0;
        }
        line[row][col] = input.at(pos);
        col++;
    }
    return;
}

//  void clearArray(char line[100][256]) - puts '\0' for all spots in the array
void Rshell::clearArray(char line[][256])
{
    for(unsigned row = 0; line[row][0] != '\0'; ++row)
    {
        for(unsigned col = 0; col < 256; ++col)
        {
            line[row][col] = '\0';
        }
    }
    return;
}

//  void clearArrayP(char* argv[][]) - puts '\0' for all spots in the pointer
//      array
void Rshell::clearArrayP(char* argv[][64])
{
    for(unsigned row = 0; argv[row][0] != '\0'; ++row)
    {
        for(unsigned col = 0; argv[row][col] != '\0'; ++col)
        {
            argv[row][col] = '\0';
        }
    }
    return;
}
<commit_msg>added executeCommand function<commit_after>#include "rshell.h"

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <vector>
#include <sstream>

using namespace std;

//  Constructors
//  Default constructor (creates an Rshell object for commands)
Rshell::Rshell()
{}

//  Rshell functions
//  These functions takes command input from the user and parses them
//  parseCommand(string& input, char line[][256], char* argv[][64]) -
//      parses out whitespace and puts charaters from string into array of char
void Rshell::parseCommand(string& input, char line[][256], char* argv[][64])
{
    unsigned row = 0;
    unsigned col = 0;
    bool quote = false;     //  Has a flag if the argument is in quotations
    clearArray(line);       //  Cleans array

    //  Parses string into the array (takes out whitespace)
    for(unsigned i = 0; i < input.size(); ++i)
    {
        if(!quote)
        {
            if(input.at(i) == '#')  //  Finishes with a comment
            {
                break;
            }
            if((input.at(i) == ' ') || (input.at(i) == '\t') ||
                (input.at(i) == '\n'))  //  Replaces whitespace with ' ' if dne
            {
                if((col > 0) &&
                    !((input.at(i + 1) == '&') ||
                    (input.at(i + 1) == '|') ||
                    (input.at(i + 1) == ';')))  //  Makes sure !connector
                {
                    if(line[row][col-1] != ' ')
                    {
                        line[row][col] = ' ';
                        ++col;
                    }
                }
            }
            else if(input.at(i) == ';')     //  Treat ';' as a newline
            {
                row++;
                col = 0;
            }
            else if(input.at(i) == '&')     //  Checks for &&
            {
                parseConnect(input, i, line, '&', row, col);
            }
            else if(input.at(i) == '|')     //  Checks for ||
            {
                parseConnect(input, i, line, '|', row, col);
            }
            else    //  Any other character
            {
                line[row][col] = input.at(i);
                col++;
                if(input.at(i) == '"')      //  Checks for "
                {
                    quote = true;
                }
            }
        }
        else    //  Character is in quotes
        {
            line[row][col] = input.at(i);
            col++;
            if(input.at(i) == '"')
            {
                quote = false;
            }
        }
    }

    //  Sets up the argv array
    row = 0;
    col = 0;
    quote = false;
    clearArrayP(argv);

    //  Looks thrugh lin eand replaces any ' ' with \0'
    for(unsigned i = 0; line[i][0] != '\0'; ++i)
    {
        for(unsigned j = 0; line[i][j] != '\0'; ++j)
        {
            if(j == 0)  //  Gets the command
            {
                argv[row][col] = &line[i][j];
                ++col;
            }
            if(!quote && (line[i][j] == ' '))   //  Replaces space with '\0'
            {
                line[i][j] = '\0';
                argv[row][col] = &line[i][j + 1];
                ++col;
            }
            if(line[i][j] == '"')   //  Triggers quotes
            {
                quote = !quote;
            }
        }
        ++row;      //  Goes to the next row
        col = 0;
    }

   //  Shows all addresses in argv
    for(unsigned i = 0; argv[i][0] != '\0'; ++i)
    {
        cout << "Argument " << i << ": " << argv[row] << endl;
        for(unsigned j = 0; argv[i][j] != '\0'; ++j)
        {
            cout << "Argument [" << i << "][" << j << "]: " << argv[i][j]
                    << endl;
        }
        cout << endl;
    }
    return;
}

//  void parseConnect(string&, unsigned, char [][], char, unsigned&, unsigned&)-
//      checks if an '&' or '|'  is a connector or not
void Rshell::parseConnect(string& input, unsigned pos, char line[][256], char con, unsigned& row, unsigned& col)
{
    if(col == 1)
    {
        line[row][col] = input.at(pos);
        col++;
        if(line[row][0] == con)         //  if prev char is connector
        {
            row++;
            col = 0;
        }
    }
    else
    {
        if(input.at(pos + 1) == con)    //  if next char is connector
        {
            row++;
            col = 0;
        }
        line[row][col] = input.at(pos);
        col++;
    }
    return;
}

//  void clearArray(char line[100][256]) - puts '\0' for all spots in the array
void Rshell::clearArray(char line[][256])
{
    for(unsigned row = 0; line[row][0] != '\0'; ++row)
    {
        for(unsigned col = 0; col < 256; ++col)
        {
            line[row][col] = '\0';
        }
    }
    return;
}

//  void clearArrayP(char* argv[][]) - puts '\0' for all spots in the pointer
//      array
void Rshell::clearArrayP(char* argv[][64])
{
    for(unsigned row = 0; argv[row][0] != '\0'; ++row)
    {
        for(unsigned col = 0; argv[row][col] != '\0'; ++col)
        {
            argv[row][col] = '\0';
        }
    }
    return;
}

//  void executeCommand(char* argv[][]) - takes the array of commands and
//      executes them
void Rshell::executeCommand(char* argv[][64])
{

    return;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <boost/tokenizer.hpp>
#include <list>

using namespace std;
using namespace boost;

int main()
{
	char hostname[256];
	gethostname(hostname, 256);

	while(1)
	{
		string input_cmd;
		list<string> parse_list;

		//FIXME: Doesn't output after fg, error check if host/user dne
		//
		//outputs user login and host name along with command prompt
		cout << getlogin() << "@" << hostname << "$ ";

		//takes in commands
		getline(cin, input_cmd);

		//parse command input
		char_separator<char> delim(" ;&|");
		tokenizer< char_separator<char> > mytok(input_cmd, delim);
		for(auto it = mytok.begin(); it != mytok.end(); ++it)
		{
			parse_list.push_back(*it);
		}

		//if exit entered, exit shell
		if(input_cmd == "exit")
		{
			break;
		}
	}

	return 0;
}
<commit_msg>added code for fork and exec<commit_after>#include <iostream>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <boost/tokenizer.hpp>
#include <list>

using namespace std;
using namespace boost;

int main()
{
	char hostname[256];
	gethostname(hostname, 256);

	while(1)
	{
		string input_cmd;
		list<string> parse_list;

		//FIXME: Doesn't output after fg, error check if host/user dne
		//
		//outputs user login and host name along with command prompt
		cout << getlogin() << "@" << hostname << "$ ";

		//takes in commands
		getline(cin, input_cmd);

		//parse command input
		char_separator<char> delim(" ;&|");
		tokenizer< char_separator<char> > mytok(input_cmd, delim);
		for(auto it = mytok.begin(); it != mytok.end(); ++it)
		{
			parse_list.push_back(*it);
		}

		vector<string> cmd_line;
		vector<char*> arg;

		for(unsigned int i = 0; i < cmd_line.size(); ++i)
		{
			arg[i] = &cmd_line[i][0];
		}

		//TODO: CHECK FOR COMMENTS #
		//DO FORK AND EXEC
		//CONNECTORS

		int pid = fork();
		//error with fork
		if(pid < 0)
		{
			perror("fork().");
			exit(1);
		}
		//child process
		else if(pid == 0)
		{
			if(-1 == execvp(arg[0], arg.data()))//insert arg
			{
				perror("execvp().");
				_exit(1);
			}
		}
		//parent process
		else if(pid > 0)
		{
			if(-1 == wait(0))
			{
				perror("wait().");
				exit(1);
			}

		}
		//if exit entered, exit shell
		if(input_cmd == "exit")
		{
			exit(0);
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>// RSHELL.CPP
// Main source code for rshell

//#define RSHELL_DEBUG
// prepend "[RSHELL]" to prompt, helps to differ from bash
//#define RSHELL_PREPEND

#include "unistd.h"
#include "sys/wait.h"
#include "stdio.h"
#include "errno.h"

#include <iostream>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>

#include "rshell.h"

const char* CONN_AMP = "&&";
const char* CONN_PIPE = "||";
const char* CONN_SEMIC = ";";
const char* TOK_COMMENT = "#";

/* Initialize environment */
void init() {}

/* Main loop - controls command line, parsing, and execution logic */
int run() {

    std::vector<std::string> tokens_conn;
    std::vector<std::string> tokens_word;
    std::string usr_input;
    int prev_exit_code = 0;
    bool skip_cmd = false;

    while(true) {

        usr_input = prompt();

        tokens_conn = tokenize(usr_input, "(\\|\\||\\&\\&|;|#)");
        for(unsigned int i = 0; i < tokens_conn.size(); i++) {
//            std::cout << prev_exit_code << std::endl;
#ifdef RSHELL_DEBUG
            std::cout << "<" << tokens_conn.at(i) << ">" << std::endl;
#endif

            if(tokens_conn.at(i) == "") continue;

            // assumption: a connector token has no whitespace
            if(         tokens_conn.at(i) == std::string(CONN_AMP)) {
                if(prev_exit_code != 0  && i != 0) {
                    skip_cmd = true;
                    continue;
                } else if(i == 0) {
                    std::cout << "syntax error: unexpected token \"" << CONN_AMP << "\"\n";
                    break;
                } else continue;
            } else if(  tokens_conn.at(i) == std::string(CONN_PIPE)) {
                if(prev_exit_code == 0 && i != 0) {
                    skip_cmd = true;
                    continue;
                } else if(i == 0) {
                    std::cout << "syntax error: unexpected token \"" << CONN_PIPE << "\"\n";
                    break;
                } else continue;
            } else if(  tokens_conn.at(i) == std::string(CONN_SEMIC)) {
                if(i == 0)  {
                    std::cout << "syntax error: unexpected token \"" << CONN_SEMIC << "\"\n";
                    break;
                } else {
                    prev_exit_code = 0;
                    skip_cmd = false;
                    continue;
                }
            } else if(  tokens_conn.at(i) == std::string(TOK_COMMENT)) {
                break;
            }

            if(skip_cmd) continue;

            tokens_word = toksplit(tokens_conn.at(i), " ");
            for(unsigned int j = 0; j < tokens_word.size(); j++) {

                std::string word = tokens_word.at(j);
                // kill empty words
                if(word == "") tokens_word.erase(tokens_word.begin() + j);

                // using boost for convenience - this can be implemented manually
                boost::trim_if(word, boost::is_any_of(" \t"));
            }

            // if ls is invoked, add colors flag
            if(tokens_word.at(0) == "ls") tokens_word.push_back("--color");

            std::vector<char*> cmd_argv(tokens_word.size() + 1);
            for(unsigned int k = 0; k < tokens_word.size(); k++) {
               cmd_argv[k] = &tokens_word[k][0];
#ifdef RSHELL_DEBUG
               std::cout << "\t" << "<" << tokens_word.at(k) << ">" << std::endl;
#endif
            }

            // exit only if first word is "exit", after formatting
            if(tokens_word.at(0) == "exit") return 0;

            prev_exit_code = execute(cmd_argv[0], cmd_argv.data());

            // if execvp returned and had error, stop the process
          //  if(err_num == 1) return 1;
        }
    }

    return 0;
}

/* Prints prompt text and takes in raw command line input */
std::string prompt() {

    char hostname[HOST_NAME_MAX];
    if(gethostname(hostname, HOST_NAME_MAX) == -1)
        perror("gethostname");

#ifdef RSHELL_PREPEND
    std::cout << "[RSHELL] ";
#endif

    std::cout << getlogin() << "@" << hostname;
    std::cout << "$ " << std::flush;

    std::string input_raw;
    std::getline(std::cin, input_raw);

    return input_raw;
}

/* fork and exec a program, complete error checking */
int execute(const char* path, char* const argv[]) {

#ifdef RSHELL_DEBUG
    std::cout << "executing " << path << std::endl;
#endif

    int pid = fork();

#ifdef RSHELL_DEBUG
    std::cout << "created process with id " << pid << std::endl;
#endif

    if(pid == -1) {
        perror("fork");
        return -1;
    } else if(pid == 0) {
        execvp(path, argv);
        perror(path);
        exit(1);
    } else {

        int exit_code;

        // pass exit code along
        if(waitpid(pid, &exit_code, 0) == -1) perror("waitpid");
        return exit_code;
    }

    return 0;
}

/* Overload to tokenize by whitespace */
std::vector<std::string> tokenize(std::string s) {
    return tokenize(s, "\\s");
}

/* Tokenize a string using boost regex */
std::vector<std::string> tokenize(std::string s, std::string r) {

    std::vector<std::string> token_vec;

//    boost::algorithm::split_regex(token_vec, s, boost::regex(r));

    std::string::const_iterator s_start, s_end;
    s_start = s.begin();
    s_end = s.end();

    boost::match_results<std::string::const_iterator> results;
    boost::match_flag_type flags = boost::match_default;
    while(boost::regex_search(s_start, s_end, results, boost::regex(r), flags)) {

        token_vec.push_back(std::string(s_start, results[0].first));
        token_vec.push_back(results[0]);

        s_start = results[0].second;
        flags |= boost::match_prev_avail;
        flags |= boost::match_not_bob;
    }

    token_vec.push_back(std::string(s_start, s_end));

    // scrub vector of empty fields

    for(unsigned int i = 0; i < token_vec.size(); i++) {
#ifdef RSHELL_DEBUG
        std::cout << "[" << token_vec.at(i) << "]" << std::endl;
#endif
        if(token_vec.at(i) == "") token_vec.erase(token_vec.begin() + i);
    }

    return token_vec;
}

/* Tokenize a string using boost split */
std::vector<std::string> toksplit(std::string s, std::string toks) {

    std::vector<std::string> token_vec;
    boost::split(token_vec, s, boost::is_any_of(toks), boost::token_compress_on);
    return token_vec;
}
<commit_msg>initial ls commit<commit_after>// RSHELL.CPP
// Main source code for rshell

//#define RSHELL_DEBUG
// prepend "[RSHELL]" to prompt, helps to differ from bash
#define RSHELL_PREPEND

#define COL_DEFAULT "\033[39m"
#define COL_PREPEND "\033[32m"

#include "unistd.h"
#include "sys/wait.h"
#include "stdio.h"
#include "errno.h"

#include <iostream>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>

#include "rshell.h"

const char* CONN_AMP = "&&";
const char* CONN_PIPE = "||";
const char* CONN_SEMIC = ";";
const char* TOK_COMMENT = "#";

/* Initialize environment */
void init() {}

/* Main loop - controls command line, parsing, and execution logic */
int run() {

    std::vector<std::string> tokens_spc;
    std::vector<std::string> tokens_word;
    std::string usr_input;
    int prev_exit_code = 0;
    bool skip_cmd = false;

    while(true) {

        usr_input = prompt();

        tokens_spc = tokenize(usr_input, "(\\|\\||\\&\\&|;|#)");
        for(unsigned int i = 0; i < tokens_spc.size(); i++) {
//            std::cout << prev_exit_code << std::endl;

            std::string spc = tokens_spc.at(i);

#ifdef RSHELL_DEBUG
            std::cout << "<" << spc << ">" << std::endl;
#endif

            if(spc == "") continue;

            // assumption: a connector token has no whitespace
            if(         spc == std::string(CONN_AMP)) {
                if(prev_exit_code != 0  && i != 0) {
                    skip_cmd = true;
                    continue;
                } else if(i == 0) {
                    std::cout << "syntax error: unexpected token \"" << CONN_AMP << "\"\n";
                    break;
                } else continue;
            } else if(  spc == std::string(CONN_PIPE)) {
                if(prev_exit_code == 0 && i != 0) {
                    skip_cmd = true;
                    continue;
                } else if(i == 0) {
                    std::cout << "syntax error: unexpected token \"" << CONN_PIPE << "\"\n";
                    break;
                } else continue;
            } else if(  spc == std::string(CONN_SEMIC)) {
                if(i == 0)  {
                    std::cout << "syntax error: unexpected token \"" << CONN_SEMIC << "\"\n";
                    break;
                } else {
                    prev_exit_code = 0;
                    skip_cmd = false;
                    continue;
                }
            } else if(  spc == std::string(TOK_COMMENT)) {
                break;
            }

            if(skip_cmd) continue;

            tokens_word = toksplit(spc, " ");
            for(unsigned int j = 0; j < tokens_word.size(); j++) {

                std::string word = tokens_word.at(j);
                // kill empty words
                if(word == "") tokens_word.erase(tokens_word.begin() + j);

                // using boost for convenience - this can be implemented manually
                boost::trim_if(word, boost::is_any_of(" \t"));
            }

            // if ls is invoked, print apology
            if(tokens_word.at(0) == "ls") {
                std::cout << "sorry, not implemented yet...\n";
                continue;
            }

            std::vector<char*> cmd_argv(tokens_word.size() + 1);
            for(unsigned int k = 0; k < tokens_word.size(); k++) {
               cmd_argv[k] = &tokens_word[k][0];
#ifdef RSHELL_DEBUG
               std::cout << "\t" << "<" << tokens_word.at(k) << ">" << std::endl;
#endif
            }

            // exit only if first word is "exit", after formatting
            if(tokens_word.at(0) == "exit") return 0;

            prev_exit_code = execute(cmd_argv[0], cmd_argv.data());

            // if execvp returned and had error, stop the process
          //  if(err_num == 1) return 1;
        }
    }

    return 0;
}

/* Prints prompt text and takes in raw command line input */
std::string prompt() {

    char hostname[HOST_NAME_MAX];
    if(gethostname(hostname, HOST_NAME_MAX) == -1)
        perror("gethostname");

#ifdef RSHELL_PREPEND
    std::cout << COL_PREPEND << "[RSHELL] ";
#endif

    std::cout << COL_DEFAULT;

    std::cout << getlogin() << "@" << hostname;
    std::cout << "$ " << std::flush;

    std::string input_raw;
    std::getline(std::cin, input_raw);

    return input_raw;
}

/* fork and exec a program, complete error checking */
int execute(const char* path, char* const argv[]) {

#ifdef RSHELL_DEBUG
    std::cout << "executing " << path << std::endl;
#endif

    int pid = fork();

#ifdef RSHELL_DEBUG
    std::cout << "created process with id " << pid << std::endl;
#endif

    if(pid == -1) {
        perror("fork");
        return -1;
    } else if(pid == 0) {
        execvp(path, argv);
        perror(path);
        exit(1);
    } else {

        int exit_code;

        // pass exit code along
        if(waitpid(pid, &exit_code, 0) == -1) perror("waitpid");
        return exit_code;
    }

    return 0;
}

/* Overload to tokenize by whitespace */
std::vector<std::string> tokenize(std::string s) {
    return tokenize(s, "\\s");
}

/* Tokenize a string using boost regex */
std::vector<std::string> tokenize(std::string s, std::string r) {

    std::vector<std::string> token_vec;

//    boost::algorithm::split_regex(token_vec, s, boost::regex(r));

    std::string::const_iterator s_start, s_end;
    s_start = s.begin();
    s_end = s.end();

    boost::match_results<std::string::const_iterator> results;
    boost::match_flag_type flags = boost::match_default;
    while(boost::regex_search(s_start, s_end, results, boost::regex(r), flags)) {

        token_vec.push_back(std::string(s_start, results[0].first));
        token_vec.push_back(results[0]);

        s_start = results[0].second;
        flags |= boost::match_prev_avail;
        flags |= boost::match_not_bob;
    }

    token_vec.push_back(std::string(s_start, s_end));

    // scrub vector of empty fields

    for(unsigned int i = 0; i < token_vec.size(); i++) {
#ifdef RSHELL_DEBUG
        std::cout << "[" << token_vec.at(i) << "]" << std::endl;
#endif
        if(token_vec.at(i) == "") token_vec.erase(token_vec.begin() + i);
    }

    return token_vec;
}

/* Tokenize a string using boost split */
std::vector<std::string> toksplit(std::string s, std::string toks) {

    std::vector<std::string> token_vec;
    boost::split(token_vec, s, boost::is_any_of(toks), boost::token_compress_on);
    return token_vec;
}
<|endoftext|>


<commit_before>/**
 * Exercise 5 : Read in a gph-file, computes the longest (with respect to the edge weights) shortest path from any vertex to the vertex with index 1.
 *
 * @author FirstSanny
 */

#include <iostream>
#include <fstream>
#include <utility>
#include <vector>
#include <climits>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/timer/timer.hpp>
#include "Dijkstra.h"

// Constants
namespace {

const char* FILEEND = ".gph";
const char* OWNALGO = "-m1";
const char* LIBALGO = "-m2";

}

// declaring print
using std::cout;
using std::endl;
using std::cerr;
using std::string;

// declaring types
using Graph = boost::adjacency_list<boost::listS, boost::vecS,
  boost::undirectedS, boost::no_property,
  boost::property<boost::edge_weight_t, int>> ;
using VertexDescriptor = boost::graph_traits < Graph >::vertex_descriptor;
using Directions = std::vector<VertexDescriptor >;
using Edge = std::pair<int, int>;
using Edges = std::vector<Edge >;
using Weights = std::vector<int >;

/** check which method should be used for computing the shortest path */
char checkPreferredAlgo(char* argv[], int argn) {
	if(argn == 2){
		return 0;
	}
	string command = argv[1];
	const string::size_type indexCommandOwnAlgo = command.find(OWNALGO);
	if(indexCommandOwnAlgo != string::npos){
		return 1;
	}
	const string::size_type indexCommandLibAlgo = command.find(LIBALGO);
	if(indexCommandLibAlgo != string::npos){
		return 0;
	}
	return 0;
}

/** add's fileending and opens the via ifstream */
std::ifstream openFile(char* argv[], int argn) {
	string filename;
	if(argn == 2){
		filename = argv[1];
	} else {
		filename = argv[2];
	}
	filename += FILEEND;
	cout << "Going to parse the file " << filename << endl;
	std::ifstream fileStream;
	fileStream.open(filename.c_str(), std::ios::in);
	return fileStream;
}

/** Reading in a Graphfile, computes the longest shortest path */
int main(int argn, char *argv[]) {
	boost::timer::auto_cpu_timer t;
	if (argn <= 1) {
		cerr << "ERROR : There was no filename" << endl;
		return 1;
	}

	char useOwnAlgo = checkPreferredAlgo(argv, argn);
	if(useOwnAlgo){
		cout << "Using own algorithm..." << endl;
	} else {
		cout << "Using algorithm from boost-libary..." << endl;
	}

	std::ifstream fileStream = openFile(argv, argn);

	if ( (fileStream.rdstate()) != 0 ){
		std::perror("ERROR : Encoutered Problem opening file");
		return 1;
	}

	string line;

	unsigned int edgeCount;
	unsigned int vertexCount;

	if(std::getline(fileStream, line)){
		sscanf(line.c_str(), "%d %d", &vertexCount, &edgeCount);
		cout << "Vertexcount: " << vertexCount << endl;
		cout << "Edgecount: " << edgeCount << endl;
		line.clear();
		vertexCount++;
	} else {
		cerr << "ERROR : File was empty" << endl;
		return 1;
	}

	Edges* edges = new Edges(edgeCount);
	Weights* weights = new Weights(edgeCount);

	cout << "Reading edges..." << endl;
	while (getline(fileStream, line)) {
		int start;
		int end;
		int weight;
		int count = sscanf(line.c_str(), "%d %d %d", &start, &end, &weight);
		if (count != 3) {
			line.clear();
			continue;
		}
		edges->push_back(std::make_pair(start, end));
		weights->push_back(weight);
		line.clear();
	}

	cout << "Creating graph..." << endl;
	Graph g{edges->begin(), edges->end(), weights->begin(), vertexCount};

	Directions* directions = new std::vector<VertexDescriptor>(vertexCount);
	Weights weightsForShortestpath;

	if(useOwnAlgo){
		cout << "Compute shortest paths via Dijkstra(own)..." << endl;
		Dijkstra* d = new Dijkstra();
		weightsForShortestpath = d->dijkstra(vertexCount, *edges, *weights, 1);
	} else {
		cout << "Compute shortest paths via Dijkstra(boost)..." << endl;
		std::vector<int>* weightMapPointer = new std::vector<int>(vertexCount);
		boost::dijkstra_shortest_paths(g, 1,
			boost::predecessor_map(//
					boost::make_iterator_property_map(directions->begin(), boost::get(boost::vertex_index, g))) //
				.distance_map(//
					boost::make_iterator_property_map(weightMapPointer->begin(), boost::get(boost::vertex_index, g))));
		weightsForShortestpath = *weightMapPointer;
		delete weightMapPointer;
	}

	cout << "Search longest shortest path..." << endl;
	int vertex = 1;
	int distance = 0;

	for(unsigned int i=2; i<vertexCount; i++){
		if(weightsForShortestpath[i]>distance){
			distance = weightsForShortestpath[i];
			vertex = i;
		}
	}

	cout << "RESULT VERTEX " << vertex << endl;
	cout << "RESULT DIST " << distance << endl;

	delete edges;
	delete weights;
	delete directions;

	return 0;
}
<commit_msg>swapped m1 and m2 for lib and own<commit_after>/**
 * Exercise 5 : Read in a gph-file, computes the longest (with respect to the edge weights) shortest path from any vertex to the vertex with index 1.
 *
 * @author FirstSanny
 */

#include <iostream>
#include <fstream>
#include <utility>
#include <vector>
#include <climits>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/timer/timer.hpp>
#include "Dijkstra.h"

// Constants
namespace {

const char* FILEEND = ".gph";
const char* LIBALGO = "-m1";
const char* OWNALGO = "-m2";

}

// declaring print
using std::cout;
using std::endl;
using std::cerr;
using std::string;

// declaring types
using Graph = boost::adjacency_list<boost::listS, boost::vecS,
  boost::undirectedS, boost::no_property,
  boost::property<boost::edge_weight_t, int>> ;
using VertexDescriptor = boost::graph_traits < Graph >::vertex_descriptor;
using Directions = std::vector<VertexDescriptor >;
using Edge = std::pair<int, int>;
using Edges = std::vector<Edge >;
using Weights = std::vector<int >;

/** check which method should be used for computing the shortest path */
char checkPreferredAlgo(char* argv[], int argn) {
	if(argn == 2){
		return 0;
	}
	string command = argv[1];
	const string::size_type indexCommandOwnAlgo = command.find(OWNALGO);
	if(indexCommandOwnAlgo != string::npos){
		return 1;
	}
	const string::size_type indexCommandLibAlgo = command.find(LIBALGO);
	if(indexCommandLibAlgo != string::npos){
		return 0;
	}
	return 0;
}

/** add's fileending and opens the via ifstream */
std::ifstream openFile(char* argv[], int argn) {
	string filename;
	if(argn == 2){
		filename = argv[1];
	} else {
		filename = argv[2];
	}
	filename += FILEEND;
	cout << "Going to parse the file " << filename << endl;
	std::ifstream fileStream;
	fileStream.open(filename.c_str(), std::ios::in);
	return fileStream;
}

/** Reading in a Graphfile, computes the longest shortest path */
int main(int argn, char *argv[]) {
	boost::timer::auto_cpu_timer t;
	if (argn <= 1) {
		cerr << "ERROR : There was no filename" << endl;
		return 1;
	}

	char useOwnAlgo = checkPreferredAlgo(argv, argn);
	if(useOwnAlgo){
		cout << "Using own algorithm..." << endl;
	} else {
		cout << "Using algorithm from boost-libary..." << endl;
	}

	std::ifstream fileStream = openFile(argv, argn);

	if ( (fileStream.rdstate()) != 0 ){
		std::perror("ERROR : Encoutered Problem opening file");
		return 1;
	}

	string line;

	unsigned int edgeCount;
	unsigned int vertexCount;

	if(std::getline(fileStream, line)){
		sscanf(line.c_str(), "%d %d", &vertexCount, &edgeCount);
		cout << "Vertexcount: " << vertexCount << endl;
		cout << "Edgecount: " << edgeCount << endl;
		line.clear();
		vertexCount++;
	} else {
		cerr << "ERROR : File was empty" << endl;
		return 1;
	}

	Edges* edges = new Edges(edgeCount);
	Weights* weights = new Weights(edgeCount);

	cout << "Reading edges..." << endl;
	while (getline(fileStream, line)) {
		int start;
		int end;
		int weight;
		int count = sscanf(line.c_str(), "%d %d %d", &start, &end, &weight);
		if (count != 3) {
			line.clear();
			continue;
		}
		edges->push_back(std::make_pair(start, end));
		weights->push_back(weight);
		line.clear();
	}

	cout << "Creating graph..." << endl;
	Graph g{edges->begin(), edges->end(), weights->begin(), vertexCount};

	Directions* directions = new std::vector<VertexDescriptor>(vertexCount);
	Weights weightsForShortestpath;

	if(useOwnAlgo){
		cout << "Compute shortest paths via Dijkstra(own)..." << endl;
		Dijkstra* d = new Dijkstra();
		weightsForShortestpath = d->dijkstra(vertexCount, *edges, *weights, 1);
	} else {
		cout << "Compute shortest paths via Dijkstra(boost)..." << endl;
		std::vector<int>* weightMapPointer = new std::vector<int>(vertexCount);
		boost::dijkstra_shortest_paths(g, 1,
			boost::predecessor_map(//
					boost::make_iterator_property_map(directions->begin(), boost::get(boost::vertex_index, g))) //
				.distance_map(//
					boost::make_iterator_property_map(weightMapPointer->begin(), boost::get(boost::vertex_index, g))));
		weightsForShortestpath = *weightMapPointer;
		delete weightMapPointer;
	}

	cout << "Search longest shortest path..." << endl;
	int vertex = 1;
	int distance = 0;

	for(unsigned int i=2; i<vertexCount; i++){
		if(weightsForShortestpath[i]>distance){
			distance = weightsForShortestpath[i];
			vertex = i;
		}
	}

	cout << "RESULT VERTEX " << vertex << endl;
	cout << "RESULT DIST " << distance << endl;

	delete edges;
	delete weights;
	delete directions;

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <errno.h>

int main(int argc, char** argv)
{
	char login[64];
	int chk = getlogin_r(login, sizeof(login)-1);
	std::string name = login;
	chk = gethostname(login, sizeof(login)-1);
	std::string host = login;
	name += "@";
	std::string user = name + host;
	std::string cmd_line;
	while(1)
	{
		std::cout << user  << "$ ";
		std::cin >> cmd_line;
		char* cmd = const_cast<char*>(cmd_line.c_str());
		if(cmd_line == "exit")
		{
			return 0;
		}
		int pid = fork();
		if(pid == 0)
		{
			execvp(cmd, argv);
		}
		else
		{
			if(pid == -1)
			{
				perror("fork");
				exit(1);
			}
			wait(0);
		}
	}
}

<commit_msg>Fixed input with getline(). Tokenized command line and identified where flags are located<commit_after>#include <iostream>
#include <stdlib.h>
#include <unistd.h>				// Sys calls
#include <stdio.h>
#include <sys/wait.h>			// Wait
#include <errno.h>				// perror()
#include <string.h>				// strtok
#include <cstring>				// strcpy()
#include <sstream>
#include <vector>

int main(int argc, char* argv[])
{
	char login[64];
	getlogin_r(login, sizeof(login)-1);
	std::string name = login;
	gethostname(login, sizeof(login)-1);
	std::string host = login;
	name += "@";
	std::string user = name + host;

	std::string cmd_line;
	std::vector<char*> commands;
	std::vector<int> flag;
	while(1)
	{
		std::cout << user << "$ ";			// Prompt and input
		getline(std::cin, cmd_line);

		char*  cmd_str = new char [cmd_line.length()+1];	// Tokenizing
		std::strcpy(cmd_str, cmd_line.c_str());

		char* cmd = std::strtok(cmd_str, " ");
		while(cmd != NULL)
		{
			commands.push_back(cmd);
			cmd = std::strtok(NULL, " ");
		}

		int flagcnt = 0;							// Locating cmd flags
		for(int i = 0; i < commands.size(); ++i)
		{
			if(commands.at(i)[0] == '-')
			{
				flag.push_back(i);
				flagcnt++;
			}
		}
		//for(int j = 0; j < commands.size() - flagcnt; ++j)
		int pid = fork();
		if(pid == 0)
		{
			execvp(commands.at(0), argv);		// Works for std cmds only
		}
		else
		{
			if(pid == -1)
			{
				perror("fork");
				exit(1);
			}
			wait(0);
		}

		while(commands.size() != 0)
			commands.pop_back();
	}
}

<|endoftext|>


<commit_before>/*
   Copyright (c) 2011, The Mineserver Project
   All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "../mineserver.h"
#include "../map.h"
#include "../logger.h"

#include "ice.h"

bool BlockIce::onBroken(User* user, int8_t status, int32_t x, int8_t y, int32_t z, int map, int8_t direction)
{
  Mineserver::get()->map(map)->setBlock(x, y, z, BLOCK_WATER, direction);
  Mineserver::get()->map(map)->sendBlockChange(x, y, z, BLOCK_WATER, direction);
  applyPhysics(user, x, y, z, map);
  return true;
}

bool BlockIce::onPlace(User* user, int16_t newblock, int32_t x, int8_t y, int32_t z, int map, int8_t direction)
{
  uint8_t oldblock;
  uint8_t oldmeta;

  if (newblock > 255)
  {
    return true;
  }

  if (!Mineserver::get()->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* Check block below allows blocks placed on top */
  if (!this->isBlockStackable(oldblock))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->translateDirection(&x, &y, &z, map, direction))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (this->isUserOnBlock(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->isBlockEmpty(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  //direction = user->relativeToBlock(x, y, z);

  Mineserver::get()->map(map)->setBlock(x, y, z, (char)newblock, 0);
  Mineserver::get()->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);
  return false;
}

<commit_msg>Removing applyPhysics(); there's already physics being done for water and applyPhysics() is for falling blocks.<commit_after>/*
   Copyright (c) 2011, The Mineserver Project
   All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "../mineserver.h"
#include "../map.h"
#include "../logger.h"

#include "ice.h"

bool BlockIce::onBroken(User* user, int8_t status, int32_t x, int8_t y, int32_t z, int map, int8_t direction)
{
  Mineserver::get()->map(map)->setBlock(x, y, z, BLOCK_WATER, direction);
  Mineserver::get()->map(map)->sendBlockChange(x, y, z, BLOCK_WATER, direction);
  return true;
}

bool BlockIce::onPlace(User* user, int16_t newblock, int32_t x, int8_t y, int32_t z, int map, int8_t direction)
{
  uint8_t oldblock;
  uint8_t oldmeta;

  if (newblock > 255)
  {
    return true;
  }

  if (!Mineserver::get()->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* Check block below allows blocks placed on top */
  if (!this->isBlockStackable(oldblock))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->translateDirection(&x, &y, &z, map, direction))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (this->isUserOnBlock(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->isBlockEmpty(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  //direction = user->relativeToBlock(x, y, z);

  Mineserver::get()->map(map)->setBlock(x, y, z, (char)newblock, 0);
  Mineserver::get()->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);
  return false;
}

<|endoftext|>