<commit_before>// Composes two transform sets.
// Output transform is the result of applying the first input transform, followed by the second.

#include <assert.h>

#include "itkTransformFileReader.h"
#include "itkTransformFileWriter.h"
#include "itkTransformFactory.h"
#include "itkMatrixOffsetTransformBase.h"

#include "IOHelpers.hpp"
#include "Dirs.hpp"

void checkUsage(int argc, char const *argv[]) {
  if( argc < 3 )
  {
    cerr << "\nUsage: " << endl;
    cerr << argv[0] << " firstInputDir secondInputDir outputDir\n\n";
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char const *argv[]) {
	// Verify the number of parameters in the command line
	checkUsage(argc, argv);

	// Generate file lists
  vector< string > firstInputFileNames  = constructPaths(argv[1], Dirs::ImageList(), ".meta");
  vector< string > secondInputFileNames = constructPaths(argv[2], Dirs::ImageList(), ".meta");
  vector< string > outputFileNames      = constructPaths(argv[3], Dirs::ImageList(), ".meta");

	// Some transforms might not be registered
  // with the factory so we add them manually
  itk::TransformFactoryBase::RegisterDefaultTransforms();
  // itk::TransformFactory< itk::TranslationTransform< double, 2 > >::RegisterTransform();

	// Generate new transforms
	typedef itk::TransformFileReader ReaderType;
	typedef itk::TransformFileWriter WriterType;
	// TranslationTransform also has a Compose() interface, but only with other TranslationTransforms
  typedef itk::MatrixOffsetTransformBase< double, 2, 2 > ComposableTransformType;

  for(unsigned int i=0; i < firstInputFileNames.size(); ++i)
  {
    // Load input transforms
    ReaderType::Pointer firstReader = ReaderType::New();
    ReaderType::Pointer secondReader = ReaderType::New();
    firstReader->SetFileName(  firstInputFileNames[i].c_str()  );
    secondReader->SetFileName( secondInputFileNames[i].c_str() );
    firstReader->Update();
    secondReader->Update();

    // check that transforms are of the right dynamic type
    ComposableTransformType *pFirstTransform  = dynamic_cast<ComposableTransformType*>( firstReader->GetTransformList()->begin()->GetPointer() );
    ComposableTransformType *pSecondTransform = dynamic_cast<ComposableTransformType*>( secondReader->GetTransformList()->begin()->GetPointer() );
    assert( pFirstTransform != 0 && pSecondTransform != 0 );

    // compose transforms
    // If the argument pre is true, then other is precomposed with self; that is, the resulting transformation consists of first applying
    // other to the source, followed by self. If pre is false or omitted, then other is post-composed with self; that is the resulting
    // transformation consists of first applying self to the source, followed by other. This updates the Translation based on current center.
    pFirstTransform->Compose(pSecondTransform);

    // save output transform
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName( outputFileNames[i].c_str() );
    writer->AddTransform( pFirstTransform );
    writer->Update();

  }

  return EXIT_SUCCESS;
}
<commit_msg>Compose diffusion transforms from originals and adjustments<commit_after>// Composes two transform sets.
// Output transform is the result of applying the first input transform, followed by the second.

#include <assert.h>

#include "itkTransformFileReader.h"
#include "itkTransformFileWriter.h"
#include "itkTransformFactory.h"
#include "itkAffineTransform.h"

#include "IOHelpers.hpp"
#include "Dirs.hpp"

void checkUsage(int argc, char const *argv[]) {
  if( argc < 3 )
  {
    cerr << "\nUsage: " << endl;
    cerr << argv[0] << " originalDir adjustmentDir outputDir\n\n";
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char const *argv[]) {
	// Verify the number of parameters in the command line
	checkUsage(argc, argv);

	// Generate file lists
  vector< string > basenames = directoryContents(argv[1]);
  vector< string > originalPaths   = constructPaths(argv[1], basenames);
  vector< string > adjustmentPaths = constructPaths(argv[2], basenames);
  vector< string > outputPaths     = constructPaths(argv[3], basenames);

	// clear results directory
  remove_all(argv[3]);
  create_directory(argv[3]);

	// Some transforms might not be registered
  // with the factory so we add them manually
  itk::TransformFactoryBase::RegisterDefaultTransforms();
  // itk::TransformFactory< itk::TranslationTransform< double, 2 > >::RegisterTransform();

	// Generate new transforms
	typedef itk::TransformFileReader ReaderType;
	typedef itk::TransformFileWriter WriterType;
	// TranslationTransform also has a Compose() interface, but only with other TranslationTransforms
  typedef itk::MatrixOffsetTransformBase< double, 2, 2 > ComposableTransformType;
  typedef itk::AffineTransform< double, 2 > AffineTransformType;

  // the first and last slices should not have adjustments
  // apply adjustments for every other slice
  for(unsigned int i=1; i < originalPaths.size() - 1; ++i)
  {
    // Load input transforms
    ReaderType::Pointer originalReader = ReaderType::New();
    ReaderType::Pointer adjustmentReader = ReaderType::New();
    originalReader->SetFileName(  originalPaths[i].c_str()  );
    adjustmentReader->SetFileName( adjustmentPaths[i].c_str() );
    originalReader->Update();
    adjustmentReader->Update();

    // check that transforms are of the right dynamic type
    ComposableTransformType *pOriginalTransform  = dynamic_cast<ComposableTransformType*>( originalReader->GetTransformList()->begin()->GetPointer() );
    ComposableTransformType *pAdjustmentTransform = dynamic_cast<ComposableTransformType*>( adjustmentReader->GetTransformList()->begin()->GetPointer() );
    assert( pOriginalTransform != 0 && pAdjustmentTransform != 0 );

    // compose transforms
    // If the argument pre is true (default false), then other is precomposed with self; that is, the resulting transformation consists of first
    // applying other to the source, followed by self. If pre is false or omitted, then other is post-composed with self; that is the resulting
    // transformation consists of first applying self to the source, followed by other. This updates the Translation based on current center.
    AffineTransformType::Pointer outputTransform = AffineTransformType::New();
    outputTransform->SetIdentity();
    outputTransform->Compose(pOriginalTransform);
    outputTransform->Compose(pAdjustmentTransform);

    // save output transform
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName( outputPaths[i].c_str() );
    writer->AddTransform( outputTransform );
    writer->Update();

  }

  // write out the unaltered first and last transforms
  copy_file( *(originalPaths.begin()), *(outputPaths.begin()) );
  copy_file( *(--originalPaths.end()), *(--outputPaths.end()) );

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
  This file is part of KOrganizer.

  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

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

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "alarmdockwindow.h"
#include "koalarmclient.h"

#include <kactioncollection.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kiconeffect.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kurl.h>
#include <kstandarddirs.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <kaction.h>
#include <kstandardaction.h>
#include <ktoolinvocation.h>
#include <kglobal.h>

#include <QFile>
#include <QMouseEvent>

#include <stdlib.h>

AlarmDockWindow::AlarmDockWindow()
  : KSystemTrayIcon( 0 )
{
  // Read the autostart status from the config file
  KConfigGroup config( KGlobal::config(), "General" );
  bool autostart = config.readEntry( "Autostart", true );
  bool alarmsEnabled = config.readEntry( "Enabled", true );

  mName = i18nc( "@title:window", "KOrganizer Reminder Daemon" );
  setToolTip( mName );

  // Set up icons
  KIconLoader::global()->addAppDir( "korgac" );
  KIconLoader::global()->addAppDir( "kdepim" );
  mIconEnabled  = loadIcon( "korgac" );
  if ( mIconEnabled.isNull() ) {
    KMessageBox::sorry( parentWidget(),
                        i18nc( "@info", "Cannot load system tray icon." ) );
  } else {
    KIconLoader loader;
    QImage iconDisabled =
      mIconEnabled.pixmap( loader.currentSize( KIconLoader::Panel ) ).toImage();
    KIconEffect::toGray( iconDisabled, 1.0 );
    mIconDisabled = QIcon( QPixmap::fromImage( iconDisabled ) );
  }

  setIcon( alarmsEnabled ? mIconEnabled : mIconDisabled );

  // Set up the context menu
  mSuspendAll =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Suspend All" ), this,
                              SLOT(slotSuspendAll()) );
  mDismissAll =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Dismiss All" ), this,
                              SLOT(slotDismissAll()) );
  mSuspendAll->setEnabled( false );
  mDismissAll->setEnabled( false );

  contextMenu()->addSeparator();
  mAlarmsEnabled =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Enable Reminders" ) );
  connect( mAlarmsEnabled, SIGNAL(toggled(bool)), SLOT(toggleAlarmsEnabled(bool)) );
  mAlarmsEnabled->setCheckable( true );

  mAutostart =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Start Reminder Daemon at Login" ) );
  connect( mAutostart, SIGNAL(toggled(bool )), SLOT(toggleAutostart(bool)) );
  mAutostart->setCheckable( true );

  mAlarmsEnabled->setChecked( alarmsEnabled );
  mAutostart->setChecked( autostart );

  // Disable standard quit behaviour. We have to intercept the quit even, if the
  // main window is hidden.
  KActionCollection *ac = actionCollection();
  const char *quitName = KStandardAction::name( KStandardAction::Quit );
  QAction *quit = ac->action( quitName );
  if ( !quit ) {
    kDebug() << "No Quit standard action.";
  } else {
    quit->disconnect( SIGNAL(triggered(bool)), this, SLOT(maybeQuit()) );
    connect( quit, SIGNAL(activated()), SLOT(slotQuit()) );
  }

  connect( this, SIGNAL(activated( QSystemTrayIcon::ActivationReason )),
           SLOT(slotActivated( QSystemTrayIcon::ActivationReason )) );

  setToolTip( mName );
}

AlarmDockWindow::~AlarmDockWindow()
{
}

void AlarmDockWindow::slotUpdate( int reminders )
{
  mSuspendAll->setEnabled( reminders > 0 );
  mDismissAll->setEnabled( reminders > 0 );
  if ( reminders > 0 ) {
    setToolTip( i18ncp( "@info:tooltip",
                        "There is 1 active reminder.",
                        "There are %1 active reminders.", reminders ) );
  } else {
    setToolTip( mName );
  }
}

void AlarmDockWindow::toggleAlarmsEnabled( bool checked )
{
  kDebug();

  setIcon( checked ? mIconEnabled : mIconDisabled );

  KConfigGroup config( KGlobal::config(), "General" );
  config.writeEntry( "Enabled", checked );
  config.sync();
}

void AlarmDockWindow::toggleAutostart( bool checked )
{
  kDebug();
  enableAutostart( checked );
}

void AlarmDockWindow::slotSuspendAll()
{
  emit suspendAllSignal();
}

void AlarmDockWindow::slotDismissAll()
{
  emit dismissAllSignal();
}

void AlarmDockWindow::enableAutostart( bool enable )
{
  KConfigGroup config( KGlobal::config(), "General" );
  config.writeEntry( "Autostart", enable );
  config.sync();
}

void AlarmDockWindow::slotActivated( QSystemTrayIcon::ActivationReason reason )
{
  if ( reason == QSystemTrayIcon::Trigger ) {
    KToolInvocation::startServiceByDesktopName( "korganizer", QString() );
  }
}

void AlarmDockWindow::slotQuit()
{
  int result = KMessageBox::questionYesNoCancel(
    parentWidget(),
    i18nc( "@info", "Do you want to start the KOrganizer reminder daemon at login "
          "(note that you will not get reminders whilst the daemon is not running)?" ),
    i18nc( "@title:window", "Close KOrganizer Reminder Daemon" ),
    KGuiItem( i18nc( "@action:button start the reminder daemon", "Start" ) ),
    KGuiItem( i18nc( "@action:button do not start the reminder daemon", "Do Not Start" ) ),
    KStandardGuiItem::cancel(),
    QString::fromLatin1( "AskForStartAtLogin" ) );

  bool autostart = true;
  if ( result == KMessageBox::No ) {
    autostart = false;
  }
  enableAutostart( autostart );

  if ( result != KMessageBox::Cancel ) {
    emit quitSignal();
  }
}

#include "alarmdockwindow.moc"
<commit_msg>more explicit menu items strings<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

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

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "alarmdockwindow.h"
#include "koalarmclient.h"

#include <kactioncollection.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kiconeffect.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kurl.h>
#include <kstandarddirs.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <kaction.h>
#include <kstandardaction.h>
#include <ktoolinvocation.h>
#include <kglobal.h>

#include <QFile>
#include <QMouseEvent>

#include <stdlib.h>

AlarmDockWindow::AlarmDockWindow()
  : KSystemTrayIcon( 0 )
{
  // Read the autostart status from the config file
  KConfigGroup config( KGlobal::config(), "General" );
  bool autostart = config.readEntry( "Autostart", true );
  bool alarmsEnabled = config.readEntry( "Enabled", true );

  mName = i18nc( "@title:window", "KOrganizer Reminder Daemon" );
  setToolTip( mName );

  // Set up icons
  KIconLoader::global()->addAppDir( "korgac" );
  KIconLoader::global()->addAppDir( "kdepim" );
  mIconEnabled  = loadIcon( "korgac" );
  if ( mIconEnabled.isNull() ) {
    KMessageBox::sorry( parentWidget(),
                        i18nc( "@info", "Cannot load system tray icon." ) );
  } else {
    KIconLoader loader;
    QImage iconDisabled =
      mIconEnabled.pixmap( loader.currentSize( KIconLoader::Panel ) ).toImage();
    KIconEffect::toGray( iconDisabled, 1.0 );
    mIconDisabled = QIcon( QPixmap::fromImage( iconDisabled ) );
  }

  setIcon( alarmsEnabled ? mIconEnabled : mIconDisabled );

  // Set up the context menu
  mSuspendAll =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Suspend All Reminders" ), this,
                              SLOT(slotSuspendAll()) );
  mDismissAll =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Dismiss All Reminders" ), this,
                              SLOT(slotDismissAll()) );
  mSuspendAll->setEnabled( false );
  mDismissAll->setEnabled( false );

  contextMenu()->addSeparator();
  mAlarmsEnabled =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Enable Reminders" ) );
  connect( mAlarmsEnabled, SIGNAL(toggled(bool)), SLOT(toggleAlarmsEnabled(bool)) );
  mAlarmsEnabled->setCheckable( true );

  mAutostart =
    contextMenu()->addAction( i18nc( "@action:inmenu", "Start Reminder Daemon at Login" ) );
  connect( mAutostart, SIGNAL(toggled(bool )), SLOT(toggleAutostart(bool)) );
  mAutostart->setCheckable( true );

  mAlarmsEnabled->setChecked( alarmsEnabled );
  mAutostart->setChecked( autostart );

  // Disable standard quit behaviour. We have to intercept the quit even, if the
  // main window is hidden.
  KActionCollection *ac = actionCollection();
  const char *quitName = KStandardAction::name( KStandardAction::Quit );
  QAction *quit = ac->action( quitName );
  if ( !quit ) {
    kDebug() << "No Quit standard action.";
  } else {
    quit->disconnect( SIGNAL(triggered(bool)), this, SLOT(maybeQuit()) );
    connect( quit, SIGNAL(activated()), SLOT(slotQuit()) );
  }

  connect( this, SIGNAL(activated( QSystemTrayIcon::ActivationReason )),
           SLOT(slotActivated( QSystemTrayIcon::ActivationReason )) );

  setToolTip( mName );
}

AlarmDockWindow::~AlarmDockWindow()
{
}

void AlarmDockWindow::slotUpdate( int reminders )
{
  mSuspendAll->setEnabled( reminders > 0 );
  mDismissAll->setEnabled( reminders > 0 );
  if ( reminders > 0 ) {
    setToolTip( i18ncp( "@info:tooltip",
                        "There is 1 active reminder.",
                        "There are %1 active reminders.", reminders ) );
  } else {
    setToolTip( i18nc( "@info:tooltip", "No active reminders." ) );
  }
}

void AlarmDockWindow::toggleAlarmsEnabled( bool checked )
{
  kDebug();

  setIcon( checked ? mIconEnabled : mIconDisabled );

  KConfigGroup config( KGlobal::config(), "General" );
  config.writeEntry( "Enabled", checked );
  config.sync();
}

void AlarmDockWindow::toggleAutostart( bool checked )
{
  kDebug();
  enableAutostart( checked );
}

void AlarmDockWindow::slotSuspendAll()
{
  emit suspendAllSignal();
}

void AlarmDockWindow::slotDismissAll()
{
  emit dismissAllSignal();
}

void AlarmDockWindow::enableAutostart( bool enable )
{
  KConfigGroup config( KGlobal::config(), "General" );
  config.writeEntry( "Autostart", enable );
  config.sync();
}

void AlarmDockWindow::slotActivated( QSystemTrayIcon::ActivationReason reason )
{
  if ( reason == QSystemTrayIcon::Trigger ) {
    KToolInvocation::startServiceByDesktopName( "korganizer", QString() );
  }
}

void AlarmDockWindow::slotQuit()
{
  int result = KMessageBox::questionYesNoCancel(
    parentWidget(),
    i18nc( "@info", "Do you want to start the KOrganizer reminder daemon at login "
          "(note that you will not get reminders whilst the daemon is not running)?" ),
    i18nc( "@title:window", "Close KOrganizer Reminder Daemon" ),
    KGuiItem( i18nc( "@action:button start the reminder daemon", "Start" ) ),
    KGuiItem( i18nc( "@action:button do not start the reminder daemon", "Do Not Start" ) ),
    KStandardGuiItem::cancel(),
    QString::fromLatin1( "AskForStartAtLogin" ) );

  bool autostart = true;
  if ( result == KMessageBox::No ) {
    autostart = false;
  }
  enableAutostart( autostart );

  if ( result != KMessageBox::Cancel ) {
    emit quitSignal();
  }
}

#include "alarmdockwindow.moc"
<|endoftext|>


<commit_before>/*
    This file is part of kdepim.

    Copyright (c) 2008 Kevin Ottens <ervin@kde.org>

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

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "folderselectdialog.h"

#include <qlayout.h>
#include <qlabel.h>
#include <qevent.h>

using namespace KPIM;

FolderSelectDialog::FolderSelectDialog( const QString& caption, const QString& label,
                                        const QStringList& list )
  : KDialog()
{
  setModal(true);
  setCaption(caption);
  setButtons(Ok);
  setDefaultButton(Ok);
  showButtonSeparator(true);

  QWidget* frame = mainWidget();
  QVBoxLayout* layout = new QVBoxLayout( frame, 0, spacingHint() );

  QLabel* labelWidget = new QLabel( label, frame );
  layout->addWidget( labelWidget );

  mListBox = new K3ListBox( frame );
  mListBox->insertStringList( list );
  mListBox->setSelected( 0, true );
  mListBox->ensureCurrentVisible();
  layout->addWidget( mListBox, 10 );

  connect( mListBox, SIGNAL( doubleClicked( QListBoxItem * ) ),
           SLOT( okClicked() ) );
  connect( mListBox, SIGNAL( returnPressed( QListBoxItem * ) ),
           SLOT( okClicked() ) );

  mListBox->setFocus();

  layout->addStretch();

  setMinimumWidth( 320 );
}

QString FolderSelectDialog::getItem( const QString &caption, const QString &label,
                                     const QStringList& list )
{
  FolderSelectDialog dlg( caption, label, list );

  QString result;
  if ( dlg.exec() == Accepted )
    result = dlg.mListBox->currentText();

  return result;
}

void FolderSelectDialog::closeEvent(QCloseEvent *event)
{
  event->ignore();
}

void FolderSelectDialog::reject()
{
}

<commit_msg>Fix signal/slot connection.<commit_after>/*
    This file is part of kdepim.

    Copyright (c) 2008 Kevin Ottens <ervin@kde.org>

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

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "folderselectdialog.h"

#include <qlayout.h>
#include <qlabel.h>
#include <qevent.h>

using namespace KPIM;

FolderSelectDialog::FolderSelectDialog( const QString& caption, const QString& label,
                                        const QStringList& list )
  : KDialog()
{
  setModal(true);
  setCaption(caption);
  setButtons(Ok);
  setDefaultButton(Ok);
  showButtonSeparator(true);

  QWidget* frame = mainWidget();
  QVBoxLayout* layout = new QVBoxLayout( frame, 0, spacingHint() );

  QLabel* labelWidget = new QLabel( label, frame );
  layout->addWidget( labelWidget );

  mListBox = new K3ListBox( frame );
  mListBox->insertStringList( list );
  mListBox->setSelected( 0, true );
  mListBox->ensureCurrentVisible();
  layout->addWidget( mListBox, 10 );

  connect( mListBox, SIGNAL( doubleClicked( Q3ListBoxItem * ) ),
           SLOT( accept() ) );
  connect( mListBox, SIGNAL( returnPressed( Q3ListBoxItem * ) ),
           SLOT( accept() ) );

  mListBox->setFocus();

  layout->addStretch();

  setMinimumWidth( 320 );
}

QString FolderSelectDialog::getItem( const QString &caption, const QString &label,
                                     const QStringList& list )
{
  FolderSelectDialog dlg( caption, label, list );

  QString result;
  if ( dlg.exec() == Accepted )
    result = dlg.mListBox->currentText();

  return result;
}

void FolderSelectDialog::closeEvent(QCloseEvent *event)
{
  event->ignore();
}

void FolderSelectDialog::reject()
{
}

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016      Los Alamos National Security, LLC
 *                         All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * LA-CC 10-123
 */

//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

/*!
 @file SetupHalo_ref.cpp

 HPCG routine
 */

#pragma once

#include "LegionMatrices.hpp"

#include "hpcg.hpp"
#include "mytimer.hpp"

#include <map>
#include <set>
#include <cassert>

/*!
    Reference version of SetupHalo that prepares system matrix data structure
    and creates data necessary for communication of boundary values of this
    process.

    @param[inout] A    The known system matrix

    @see ExchangeHalo
*/
inline void
SetupHalo(
    SparseMatrix &A,
    LegionRuntime::HighLevel::Context ctx,
    LegionRuntime::HighLevel::Runtime *runtime
) {
    using namespace std;
    // Extract Matrix pieces
    local_int_t localNumberOfRows = A.localNumberOfRows;
    char *nonzerosInRow = A.nonzerosInRow;
    // These have already been allocated, so just interpret at 2D array
    Array2D<global_int_t> mtxIndG(
        localNumberOfRows, A.maxNonzerosPerRow , A.mtxIndG
    );
    Array2D<local_int_t> mtxIndL(
        localNumberOfRows, A.maxNonzerosPerRow , A.mtxIndL
    );

    // Scan global IDs of the nonzeros in the matrix.  Determine if the column
    // ID matches a row ID.  If not: 1) We call the ComputeRankOfMatrixRow
    // function, which tells us the rank of the processor owning the row ID.  We
    // need to receive this value of the x vector during the halo exchange.  2)
    // We record our row ID since we know that the other processor will need
    // this value from us, due to symmetry.

    std::map< int, std::set< global_int_t> > sendList, receiveList;
    typedef std::map< int, std::set< global_int_t> >::iterator map_iter;
    typedef std::set<global_int_t>::iterator set_iter;
    std::map< local_int_t, local_int_t > externalToLocalMap;

    for (local_int_t i = 0; i < localNumberOfRows; i++) {
        global_int_t currentGlobalRow = A.localToGlobalMap[i];
        for (int j = 0; j<nonzerosInRow[i]; j++) {
            global_int_t curIndex = mtxIndG(i, j);
            int rankIdOfColumnEntry = ComputeRankOfMatrixRow(
                                          *(A.geom), curIndex
                                      );
            // If column index is not a row index, then it comes from another
            // processor
            if (A.geom->rank != rankIdOfColumnEntry) {
                receiveList[rankIdOfColumnEntry].insert(curIndex);
                // Matrix symmetry means we know the neighbor process wants my
                // value
                sendList[rankIdOfColumnEntry].insert(currentGlobalRow);
            }
        }
    }

    // Count number of matrix entries to send and receive
    local_int_t totalToBeSent = 0;
    for (map_iter curNeighbor = sendList.begin();
         curNeighbor != sendList.end(); ++curNeighbor) {
        totalToBeSent += (curNeighbor->second).size();
    }
    local_int_t totalToBeReceived = 0;
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor) {
        totalToBeReceived += (curNeighbor->second).size();
    }

#ifdef HPCG_DETAILED_DEBUG
    // These are all attributes that should be true, due to symmetry
    HPCG_fout << "totalToBeSent = " << totalToBeSent
              << " totalToBeReceived = " << totalToBeReceived << endl;
    // Number of sent entry should equal number of received
    assert(totalToBeSent == totalToBeReceived);
    // Number of send-to neighbors should equal number of receive-from
    assert(sendList.size() == receiveList.size());
    // Each receive-from neighbor should be a send-to neighbor, and send the
    // same number of entries
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor) {
        assert(sendList.find(curNeighbor->first)!=sendList.end());
        assert(sendList[curNeighbor->first].size() ==
               receiveList[curNeighbor->first].size());
    }
#endif

    // Build the arrays and lists needed by the ExchangeHalo function.
    //double * sendBuffer = new double[totalToBeSent];
    //
    ArrayAllocator<local_int_t> *aaElementsToSend = nullptr;
    local_int_t *elementsToSend = nullptr;
    if (totalToBeSent != 0) {
        aaElementsToSend = new ArrayAllocator<local_int_t>(
            totalToBeSent, WO_E, ctx, runtime
        );
        elementsToSend = aaElementsToSend->data();
        assert(elementsToSend);
    }
    //
    ArrayAllocator<int> *aaNeighbors = nullptr;
    int *neighbors = nullptr;
    if (sendList.size() != 0) {
        aaNeighbors = new ArrayAllocator<int>(
            sendList.size(), WO_E, ctx, runtime
        );
        neighbors = aaNeighbors->data();
        assert(neighbors);
    }
    //
    ArrayAllocator<local_int_t> *aaReceiveLength = nullptr;
    local_int_t *receiveLength = nullptr;
    if (receiveList.size() != 0) {
        aaReceiveLength = new ArrayAllocator<local_int_t>(
            receiveList.size(), WO_E, ctx, runtime
        );
        receiveLength = aaReceiveLength->data();
        assert(receiveLength);
    }
    //
    ArrayAllocator<local_int_t> *aaSendLength = nullptr;
    local_int_t *sendLength = nullptr;
    if (sendList.size() != 0) {
        aaSendLength = new ArrayAllocator<local_int_t>(
            sendList.size(), WO_E, ctx, runtime
        );
        sendLength = aaSendLength->data();
        assert(sendLength);
    }
    int neighborCount = 0;
    local_int_t receiveEntryCount = 0;
    local_int_t sendEntryCount = 0;
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor, ++neighborCount) {
        // rank of current neighbor we are processing
        int neighborId = curNeighbor->first;
        // store rank ID of current neighbor
        neighbors[neighborCount] = neighborId;
        receiveLength[neighborCount] = receiveList[neighborId].size();
        // Get count if sends/receives
        sendLength[neighborCount] = sendList[neighborId].size();
        for (set_iter i = receiveList[neighborId].begin();
             i != receiveList[neighborId].end(); ++i, ++receiveEntryCount) {
            // The remote columns are indexed at end of internals
            externalToLocalMap[*i] = localNumberOfRows + receiveEntryCount;
        }
        for (set_iter i = sendList[neighborId].begin();
             i != sendList[neighborId].end(); ++i, ++sendEntryCount) {
            // store local ids of entry to send
            elementsToSend[sendEntryCount] = A.globalToLocalMap[*i];
        }
    }
    // Convert matrix indices to local IDs
    for (local_int_t i = 0; i< localNumberOfRows; i++) {
        for (int j = 0; j < nonzerosInRow[i]; j++) {
            global_int_t curIndex = mtxIndG(i, j);
            int rankIdOfColumnEntry = ComputeRankOfMatrixRow(*(A.geom), curIndex);
            // My column index, so convert to local index
            if (A.geom->rank==rankIdOfColumnEntry) {
                mtxIndL(i, j) = A.globalToLocalMap[curIndex];
            }
            // If column index is not a row index, then it comes from another
            // processor
            else {
                mtxIndL(i, j) = externalToLocalMap[curIndex];
            }
        }
    }
    // Store contents in our matrix struct
    // Convenience pointer to A.localData
    auto *AlD = A.localData;
    //
    AlD->numberOfExternalValues = externalToLocalMap.size();
    AlD->localNumberOfColumns   = AlD->localNumberOfRows
                                + AlD->numberOfExternalValues;
    AlD->numberOfSendNeighbors  = sendList.size();
    AlD->numberOfRecvNeighbors  = receiveList.size();
    AlD->totalToBeSent          = totalToBeSent;
    //
    if (aaElementsToSend) {
        aaElementsToSend->bindToLogicalRegion(*(A.pic.elementsToSend.data()));
        delete aaElementsToSend;
    }
    if (aaNeighbors) {
        aaNeighbors->bindToLogicalRegion(*(A.pic.neighbors.data()));
        delete aaNeighbors;
    }
    if (aaReceiveLength) {
         aaReceiveLength->bindToLogicalRegion(*(A.pic.receiveLength.data()));
         delete aaReceiveLength;
    }
    if (aaSendLength) {
        aaSendLength->bindToLogicalRegion(*(A.pic.sendLength.data()));
        delete aaSendLength;
    }

#if 0
    cout << " For rank " << A.geom->rank
            << " of " << A.geom->size
            << ", number of neighbors = " << AlD->numberOfSendNeighbors << endl;
    for (int i = 0; i < AlD->numberOfSendNeighbors; i++) {
        cout << "     rank " << A.geom->rank
             << " neighbor " << neighbors[i]
             << " send/recv length = " << sendLength[i]
             << "/" << receiveLength[i] << endl;
        for (local_int_t j = 0; j<sendLength[i]; ++j)
            cout << "       rank " << A.geom->rank
                 << " elementsToSend[" << j << "] = "
                 << elementsToSend[j] << endl;
    }
#endif
}

/**
 *
 */
inline void
SetupHaloTopLevel(
    LogicalSparseMatrix &A,
    const Geometry &geom,
    LegionRuntime::HighLevel::Context ctx,
    LegionRuntime::HighLevel::Runtime *lrt
) {
    using namespace std;
    //
    cout << "*** Setting Up Structures for SPMD Exchanges..." << endl;
    const double startTime = mytimer();
    const int nShards = geom.size;
    // Extract required info from logical structures.
    //
    cout << "--> Memory for SparseMatrixScalars="
         << (sizeof(SparseMatrixScalars) * nShards) / 1024.0
         << "kB" << endl;
    Array<SparseMatrixScalars> aSparseMatrixScalars(
        A.localData.mapRegion(RO_E, ctx, lrt), ctx, lrt
    );
    SparseMatrixScalars *smScalars = aSparseMatrixScalars.data();
    assert(smScalars);
    // Calculate the entire extent (including ghost cells) for a given halo'd
    // vector. This is simply the sum of all localNumberOfColumns.
    size_t totVecLen = 0;
    std::vector<size_t> vecPartLens;
    for (int s = 0; s < nShards; ++s) {
        const auto locLen = smScalars[s].localNumberOfColumns;
        totVecLen += locLen;
        vecPartLens.push_back(locLen);
    }
    cout << "--> Halo'd Vector Total Length=" << totVecLen << endl;
    //
    Array<LogicalRegion> alrNeighborss(
        A.lrNeighborss.mapRegion(RO_E, ctx, lrt), ctx, lrt
    );
    LogicalRegion *lrpNeighbors = alrNeighborss.data();
    assert(lrpNeighbors);
    // Determine total number of PhaseBarriers required for synchronization
    size_t totpb = 0;
    // Record number of PhaseBarriers required for each task and tally total
    // number of PhaseBarriers required for this calculation.
    std::vector<size_t> numPhaseBarriers;
    for (int shard = 0; shard < nShards; ++shard) {
        const size_t nrn = smScalars[shard].numberOfSendNeighbors;
        numPhaseBarriers.push_back(nrn);
        totpb += nrn;
    }
    // 2x for ready/done pairs
    cout << "--> Total Number of PhaseBarriers Created="
         << 2 * totpb << endl;
    // Create and partition logical regions that will store PhaseBarriers
    LogicalArray<PhaseBarrier> lrReadyPhaseBarriers;
    LogicalArray<PhaseBarrier> lrDonePhaseBarriers;
    //
    lrReadyPhaseBarriers.allocate(totpb, ctx, lrt);
    lrDonePhaseBarriers.allocate(totpb, ctx, lrt);
    //
    lrReadyPhaseBarriers.partition(numPhaseBarriers, ctx, lrt);
    lrDonePhaseBarriers.partition(numPhaseBarriers, ctx, lrt);
    // Iterate over all shards
    for (int shard = 0; shard < nShards; ++shard) {
        LogicalItem<LogicalRegion> lrNeighbors(lrpNeighbors[shard], ctx, lrt);
        Array<int> aNeighbors(lrNeighbors.mapRegion(RO_E, ctx, lrt), ctx, lrt);
        int *neighbors = aNeighbors.data(); assert(neighbors);
        const int nNeighbors = smScalars[shard].numberOfSendNeighbors;
        cout << "Rank " << shard << " Has "
             << nNeighbors << " Send Neighbors " << endl;
        for (int i = 0; i < nNeighbors;  ++i) {
            cout << neighbors[i] << " ";
        }
        cout << endl;
        lrNeighbors.unmapRegion(ctx, lrt);
    }
    // Unmap inline mapped structures.
    A.localData.unmapRegion(ctx, lrt);
    A.lrNeighborss.unmapRegion(ctx, lrt);
    //
    lrReadyPhaseBarriers.deallocate(ctx, lrt);
    lrDonePhaseBarriers.deallocate(ctx, lrt);
    //
    const double endTime = mytimer();
    double time = endTime - startTime;
    cout << "--> Time=" << time << "s" << endl;
}
<commit_msg>Fix build and cleanup.<commit_after>/**
 * Copyright (c) 2016      Los Alamos National Security, LLC
 *                         All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * LA-CC 10-123
 */

//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

/*!
 @file SetupHalo_ref.cpp

 HPCG routine
 */

#pragma once

#include "LegionMatrices.hpp"

#include "hpcg.hpp"
#include "mytimer.hpp"

#include <map>
#include <set>
#include <cassert>

/*!
    Reference version of SetupHalo that prepares system matrix data structure
    and creates data necessary for communication of boundary values of this
    process.

    @param[inout] A    The known system matrix

    @see ExchangeHalo
*/
inline void
SetupHalo(
    SparseMatrix &A,
    LegionRuntime::HighLevel::Context ctx,
    LegionRuntime::HighLevel::Runtime *runtime
) {
    using namespace std;
    // Extract Matrix pieces
    local_int_t localNumberOfRows = A.localNumberOfRows;
    char *nonzerosInRow = A.nonzerosInRow;
    // These have already been allocated, so just interpret at 2D array
    Array2D<global_int_t> mtxIndG(
        localNumberOfRows, A.maxNonzerosPerRow , A.mtxIndG
    );
    Array2D<local_int_t> mtxIndL(
        localNumberOfRows, A.maxNonzerosPerRow , A.mtxIndL
    );

    // Scan global IDs of the nonzeros in the matrix.  Determine if the column
    // ID matches a row ID.  If not: 1) We call the ComputeRankOfMatrixRow
    // function, which tells us the rank of the processor owning the row ID.  We
    // need to receive this value of the x vector during the halo exchange.  2)
    // We record our row ID since we know that the other processor will need
    // this value from us, due to symmetry.

    std::map< int, std::set< global_int_t> > sendList, receiveList;
    typedef std::map< int, std::set< global_int_t> >::iterator map_iter;
    typedef std::set<global_int_t>::iterator set_iter;
    std::map< local_int_t, local_int_t > externalToLocalMap;

    for (local_int_t i = 0; i < localNumberOfRows; i++) {
        global_int_t currentGlobalRow = A.localToGlobalMap[i];
        for (int j = 0; j<nonzerosInRow[i]; j++) {
            global_int_t curIndex = mtxIndG(i, j);
            int rankIdOfColumnEntry = ComputeRankOfMatrixRow(
                                          *(A.geom), curIndex
                                      );
            // If column index is not a row index, then it comes from another
            // processor
            if (A.geom->rank != rankIdOfColumnEntry) {
                receiveList[rankIdOfColumnEntry].insert(curIndex);
                // Matrix symmetry means we know the neighbor process wants my
                // value
                sendList[rankIdOfColumnEntry].insert(currentGlobalRow);
            }
        }
    }

    // Count number of matrix entries to send and receive
    local_int_t totalToBeSent = 0;
    for (map_iter curNeighbor = sendList.begin();
         curNeighbor != sendList.end(); ++curNeighbor) {
        totalToBeSent += (curNeighbor->second).size();
    }
    local_int_t totalToBeReceived = 0;
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor) {
        totalToBeReceived += (curNeighbor->second).size();
    }

#ifdef HPCG_DETAILED_DEBUG
    // These are all attributes that should be true, due to symmetry
    HPCG_fout << "totalToBeSent = " << totalToBeSent
              << " totalToBeReceived = " << totalToBeReceived << endl;
    // Number of sent entry should equal number of received
    assert(totalToBeSent == totalToBeReceived);
    // Number of send-to neighbors should equal number of receive-from
    assert(sendList.size() == receiveList.size());
    // Each receive-from neighbor should be a send-to neighbor, and send the
    // same number of entries
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor) {
        assert(sendList.find(curNeighbor->first)!=sendList.end());
        assert(sendList[curNeighbor->first].size() ==
               receiveList[curNeighbor->first].size());
    }
#endif

    // Build the arrays and lists needed by the ExchangeHalo function.
    //double * sendBuffer = new double[totalToBeSent];
    //
    ArrayAllocator<local_int_t> *aaElementsToSend = nullptr;
    local_int_t *elementsToSend = nullptr;
    if (totalToBeSent != 0) {
        aaElementsToSend = new ArrayAllocator<local_int_t>(
            totalToBeSent, WO_E, ctx, runtime
        );
        elementsToSend = aaElementsToSend->data();
        assert(elementsToSend);
    }
    //
    ArrayAllocator<int> *aaNeighbors = nullptr;
    int *neighbors = nullptr;
    if (sendList.size() != 0) {
        aaNeighbors = new ArrayAllocator<int>(
            sendList.size(), WO_E, ctx, runtime
        );
        neighbors = aaNeighbors->data();
        assert(neighbors);
    }
    //
    ArrayAllocator<local_int_t> *aaReceiveLength = nullptr;
    local_int_t *receiveLength = nullptr;
    if (receiveList.size() != 0) {
        aaReceiveLength = new ArrayAllocator<local_int_t>(
            receiveList.size(), WO_E, ctx, runtime
        );
        receiveLength = aaReceiveLength->data();
        assert(receiveLength);
    }
    //
    ArrayAllocator<local_int_t> *aaSendLength = nullptr;
    local_int_t *sendLength = nullptr;
    if (sendList.size() != 0) {
        aaSendLength = new ArrayAllocator<local_int_t>(
            sendList.size(), WO_E, ctx, runtime
        );
        sendLength = aaSendLength->data();
        assert(sendLength);
    }
    int neighborCount = 0;
    local_int_t receiveEntryCount = 0;
    local_int_t sendEntryCount = 0;
    for (map_iter curNeighbor = receiveList.begin();
         curNeighbor != receiveList.end(); ++curNeighbor, ++neighborCount) {
        // rank of current neighbor we are processing
        int neighborId = curNeighbor->first;
        // store rank ID of current neighbor
        neighbors[neighborCount] = neighborId;
        receiveLength[neighborCount] = receiveList[neighborId].size();
        // Get count if sends/receives
        sendLength[neighborCount] = sendList[neighborId].size();
        for (set_iter i = receiveList[neighborId].begin();
             i != receiveList[neighborId].end(); ++i, ++receiveEntryCount) {
            // The remote columns are indexed at end of internals
            externalToLocalMap[*i] = localNumberOfRows + receiveEntryCount;
        }
        for (set_iter i = sendList[neighborId].begin();
             i != sendList[neighborId].end(); ++i, ++sendEntryCount) {
            // store local ids of entry to send
            elementsToSend[sendEntryCount] = A.globalToLocalMap[*i];
        }
    }
    // Convert matrix indices to local IDs
    for (local_int_t i = 0; i< localNumberOfRows; i++) {
        for (int j = 0; j < nonzerosInRow[i]; j++) {
            global_int_t curIndex = mtxIndG(i, j);
            int rankIdOfColumnEntry = ComputeRankOfMatrixRow(*(A.geom), curIndex);
            // My column index, so convert to local index
            if (A.geom->rank==rankIdOfColumnEntry) {
                mtxIndL(i, j) = A.globalToLocalMap[curIndex];
            }
            // If column index is not a row index, then it comes from another
            // processor
            else {
                mtxIndL(i, j) = externalToLocalMap[curIndex];
            }
        }
    }
    // Store contents in our matrix struct
    // Convenience pointer to A.localData
    auto *AlD = A.localData;
    //
    AlD->numberOfExternalValues = externalToLocalMap.size();
    AlD->localNumberOfColumns   = AlD->localNumberOfRows
                                + AlD->numberOfExternalValues;
    AlD->numberOfSendNeighbors  = sendList.size();
    AlD->numberOfRecvNeighbors  = receiveList.size();
    AlD->totalToBeSent          = totalToBeSent;
    //
    if (aaElementsToSend) {
        aaElementsToSend->bindToLogicalRegion(*(A.pic.elementsToSend.data()));
        delete aaElementsToSend;
    }
    if (aaNeighbors) {
        aaNeighbors->bindToLogicalRegion(*(A.pic.neighbors.data()));
        delete aaNeighbors;
    }
    if (aaReceiveLength) {
         aaReceiveLength->bindToLogicalRegion(*(A.pic.receiveLength.data()));
         delete aaReceiveLength;
    }
    if (aaSendLength) {
        aaSendLength->bindToLogicalRegion(*(A.pic.sendLength.data()));
        delete aaSendLength;
    }

#if 0
    cout << " For rank " << A.geom->rank
            << " of " << A.geom->size
            << ", number of neighbors = " << AlD->numberOfSendNeighbors << endl;
    for (int i = 0; i < AlD->numberOfSendNeighbors; i++) {
        cout << "     rank " << A.geom->rank
             << " neighbor " << neighbors[i]
             << " send/recv length = " << sendLength[i]
             << "/" << receiveLength[i] << endl;
        for (local_int_t j = 0; j<sendLength[i]; ++j)
            cout << "       rank " << A.geom->rank
                 << " elementsToSend[" << j << "] = "
                 << elementsToSend[j] << endl;
    }
#endif
}

/**
 *
 */
inline void
SetupHaloTopLevel(
    LogicalSparseMatrix &A,
    const Geometry &geom,
    LegionRuntime::HighLevel::Context ctx,
    LegionRuntime::HighLevel::Runtime *lrt
) {
    using namespace std;
    //
    cout << "*** Setting Up Structures for SPMD Exchanges..." << endl;
    const double startTime = mytimer();
    const int nShards = geom.size;
    // Extract required info from logical structures.
    //
    cout << "--> Memory for SparseMatrixScalars="
         << (sizeof(SparseMatrixScalars) * nShards) / 1024.0
         << "kB" << endl;
    Array<SparseMatrixScalars> aSparseMatrixScalars(
        A.localData.mapRegion(RO_E, ctx, lrt), ctx, lrt
    );
    SparseMatrixScalars *smScalars = aSparseMatrixScalars.data();
    assert(smScalars);
    // Calculate the entire extent (including ghost cells) for a given halo'd
    // vector. This is simply the sum of all localNumberOfColumns.
    size_t totVecLen = 0;
    std::vector<size_t> vecPartLens;
    for (int s = 0; s < nShards; ++s) {
        const auto locLen = smScalars[s].localNumberOfColumns;
        totVecLen += locLen;
        vecPartLens.push_back(locLen);
    }
    cout << "--> Halo'd Vector Total Length=" << totVecLen << endl;
    //
    Array<LogicalRegion> alrNeighborss(
        A.lrNeighbors.mapRegion(RO_E, ctx, lrt), ctx, lrt
    );
    LogicalRegion *lrpNeighbors = alrNeighborss.data();
    assert(lrpNeighbors);
    // Determine total number of PhaseBarriers required for synchronization.
    // Each shard will create two PhaseBarriers that it owns. A ready
    // PhaseBarrier to notify its consumers and a done PhaseBarrier to receive
    // notifications from its consumers.
    // 2x for ready/done pairs
    size_t totpb = 2 * nShards;
    cout << "--> Total Number of PhaseBarriers Created="
         << totpb << endl;
    // Iterate over all shards
    for (int shard = 0; shard < nShards; ++shard) {
        LogicalItem<LogicalRegion> lrNeighbors(lrpNeighbors[shard], ctx, lrt);
        Array<int> aNeighbors(lrNeighbors.mapRegion(RO_E, ctx, lrt), ctx, lrt);
        int *neighbors = aNeighbors.data(); assert(neighbors);
        const int nNeighbors = smScalars[shard].numberOfSendNeighbors;
        cout << "Rank " << shard << " Has "
             << nNeighbors << " Send Neighbors " << endl;
        for (int i = 0; i < nNeighbors;  ++i) {
            cout << neighbors[i] << " ";
        }
        cout << endl;
        lrNeighbors.unmapRegion(ctx, lrt);
    }
    // Unmap inline mapped structures.
    A.localData.unmapRegion(ctx, lrt);
    A.lrNeighbors.unmapRegion(ctx, lrt);
    //
    const double endTime = mytimer();
    double time = endTime - startTime;
    cout << "--> Time=" << time << "s" << endl;
}
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    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 <lib/support/CodeUtils.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/NetworkCommissioning.h>
#include <platform/OpenThread/GenericNetworkCommissioningThreadDriver.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
#include <platform/ThreadStackManager.h>

#include <limits>

using namespace chip;
using namespace chip::Thread;
using namespace chip::DeviceLayer::PersistedStorage;

namespace chip {
namespace DeviceLayer {
namespace NetworkCommissioning {

// NOTE: For GenericThreadDriver, we assume that the network configuration is persisted by
// the OpenThread stack after ConnectNetwork command is called, and before that, all the changes
// are made to a local copy of the dataset stored in mStagingNetwork.
// Also, in order to support the fail-safe mechanism, the configuration is backed up in a temporary
// KVS slot upon any changes and restored when the fail-safe timeout is triggered or the device
// reboots without completing all the changes.

// Not all KVS implementations support zero-length values, so use this special value, that is not a valid
// dataset, to represent an empty dataset. We need that to be able to revert the network configuration
// in the case of an unsuccessful commissioning.
constexpr uint8_t kEmptyDataset[1] = {};

CHIP_ERROR GenericThreadDriver::Init(Internal::BaseDriver::NetworkStatusChangeCallback * statusChangeCallback)
{
    ThreadStackMgrImpl().SetNetworkStatusChangeCallback(statusChangeCallback);

    VerifyOrReturnError(ThreadStackMgrImpl().IsThreadAttached(), CHIP_NO_ERROR);
    VerifyOrReturnError(ThreadStackMgrImpl().GetThreadProvision(mStagingNetwork) == CHIP_NO_ERROR, CHIP_NO_ERROR);

    return CHIP_NO_ERROR;
}

void GenericThreadDriver::Shutdown()
{
    ThreadStackMgrImpl().SetNetworkStatusChangeCallback(nullptr);
}

CHIP_ERROR GenericThreadDriver::CommitConfiguration()
{
    // OpenThread persists the network configuration on AttachToThreadNetwork, so simply remove
    // the backup, so that it cannot be restored. If no backup could be found, it means that the
    // configuration has not been modified since the fail-safe was armed, so return with no error.

    DefaultStorageKeyAllocator key;
    CHIP_ERROR error = KeyValueStoreMgr().Delete(key.FailSafeNetworkConfig());

    return error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND ? CHIP_NO_ERROR : error;
}

CHIP_ERROR GenericThreadDriver::RevertConfiguration()
{
    DefaultStorageKeyAllocator key;
    uint8_t datasetBytes[Thread::kSizeOperationalDataset];
    size_t datasetLength;

    CHIP_ERROR error = KeyValueStoreMgr().Get(key.FailSafeNetworkConfig(), datasetBytes, sizeof(datasetBytes), &datasetLength);

    // If no backup could be found, it means that the network configuration has not been modified
    // since the fail-safe was armed, so return with no error.
    ReturnErrorCodeIf(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR);
    ReturnErrorOnFailure(error);

    ChipLogError(NetworkProvisioning, "Found Thread configuration backup: reverting configuration");

    // Not all KVS implementations support zero-length values, so handle a special value representing an empty dataset.
    ByteSpan dataset(datasetBytes, datasetLength);

    if (dataset.data_equal(ByteSpan(kEmptyDataset)))
    {
        dataset = {};
    }

    ReturnErrorOnFailure(mStagingNetwork.Init(dataset));
    ReturnErrorOnFailure(DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingNetwork, /* callback */ nullptr));

    // TODO: What happens on errors above? Why do we not remove the failsafe?
    return KeyValueStoreMgr().Delete(key.FailSafeNetworkConfig());
}

Status GenericThreadDriver::AddOrUpdateNetwork(ByteSpan operationalDataset, MutableCharSpan & outDebugText,
                                               uint8_t & outNetworkIndex)
{
    ByteSpan newExtpanid;
    Thread::OperationalDataset newDataset;

    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    VerifyOrReturnError(newDataset.Init(operationalDataset) == CHIP_NO_ERROR && newDataset.IsCommissioned(), Status::kOutOfRange);
    newDataset.GetExtendedPanIdAsByteSpan(newExtpanid);

    // We only support one active operational dataset. Add/Update based on either:
    // Staging network not commissioned yet (active) or we are updating the dataset with same Extended Pan ID.
    VerifyOrReturnError(!mStagingNetwork.IsCommissioned() || MatchesNetworkId(mStagingNetwork, newExtpanid) == Status::kSuccess,
                        Status::kBoundsExceeded);
    VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

    mStagingNetwork = newDataset;
    return Status::kSuccess;
}

Status GenericThreadDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex)
{
    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    VerifyOrReturnError(status == Status::kSuccess, status);
    VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

    mStagingNetwork.Clear();

    return Status::kSuccess;
}

Status GenericThreadDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText)
{
    outDebugText.reduce_size(0);

    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    VerifyOrReturnError(status == Status::kSuccess, status);
    VerifyOrReturnError(index == 0, Status::kOutOfRange);

    return Status::kSuccess;
}

void GenericThreadDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
{
    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    if (status == Status::kSuccess && BackupConfiguration() != CHIP_NO_ERROR)
    {
        status = Status::kUnknownError;
    }

    if (status == Status::kSuccess &&
        DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingNetwork, callback) != CHIP_NO_ERROR)
    {
        status = Status::kUnknownError;
    }

    if (status != Status::kSuccess)
    {
        callback->OnResult(status, CharSpan(), 0);
    }
}

void GenericThreadDriver::ScanNetworks(ThreadDriver::ScanCallback * callback)
{
    if (DeviceLayer::ThreadStackMgrImpl().StartThreadScan(callback) != CHIP_NO_ERROR)
    {
        callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
    }
}

Status GenericThreadDriver::MatchesNetworkId(const Thread::OperationalDataset & dataset, const ByteSpan & networkId) const
{
    ByteSpan extpanid;

    if (!dataset.IsCommissioned())
    {
        return Status::kNetworkIDNotFound;
    }

    if (dataset.GetExtendedPanIdAsByteSpan(extpanid) != CHIP_NO_ERROR)
    {
        return Status::kUnknownError;
    }

    return networkId.data_equal(extpanid) ? Status::kSuccess : Status::kNetworkIDNotFound;
}

CHIP_ERROR GenericThreadDriver::BackupConfiguration()
{
    DefaultStorageKeyAllocator key;
    uint8_t dummy;

    // If configuration is already backed up, return with no error
    if (KeyValueStoreMgr().Get(key.FailSafeNetworkConfig(), &dummy, 0) == CHIP_ERROR_BUFFER_TOO_SMALL)
    {
        return CHIP_NO_ERROR;
    }

    // Not all KVS implementations support zero-length values, so use a special value in such a case.
    ByteSpan dataset = mStagingNetwork.IsEmpty() ? ByteSpan(kEmptyDataset) : mStagingNetwork.AsByteSpan();

    return KeyValueStoreMgr().Put(key.FailSafeNetworkConfig(), dataset.data(), dataset.size());
}

size_t GenericThreadDriver::ThreadNetworkIterator::Count()
{
    return driver->mStagingNetwork.IsCommissioned() ? 1 : 0;
}

bool GenericThreadDriver::ThreadNetworkIterator::Next(Network & item)
{
    if (exhausted || !driver->mStagingNetwork.IsCommissioned())
    {
        return false;
    }
    uint8_t extpanid[kSizeExtendedPanId];
    VerifyOrReturnError(driver->mStagingNetwork.GetExtendedPanId(extpanid) == CHIP_NO_ERROR, false);
    memcpy(item.networkID, extpanid, kSizeExtendedPanId);
    item.networkIDLen = kSizeExtendedPanId;
    item.connected    = false;
    exhausted         = true;

    Thread::OperationalDataset currentDataset;
    uint8_t enabledExtPanId[Thread::kSizeExtendedPanId];

    // The Thread network is not actually enabled.
    VerifyOrReturnError(ConnectivityMgrImpl().IsThreadAttached(), true);
    VerifyOrReturnError(ThreadStackMgrImpl().GetThreadProvision(currentDataset) == CHIP_NO_ERROR, true);
    // The Thread network is not enabled, but has a different extended pan id.
    VerifyOrReturnError(currentDataset.GetExtendedPanId(enabledExtPanId) == CHIP_NO_ERROR, true);
    VerifyOrReturnError(memcmp(extpanid, enabledExtPanId, kSizeExtendedPanId) == 0, true);
    // The Thread network is enabled and has the same extended pan id as the one in our record.
    item.connected = true;

    return true;
}

} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
<commit_msg>[OpenThread] Revert configuration on boot with fail-safe armed (#21597)<commit_after>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    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 <lib/support/CodeUtils.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/NetworkCommissioning.h>
#include <platform/OpenThread/GenericNetworkCommissioningThreadDriver.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
#include <platform/ThreadStackManager.h>

#include <limits>

using namespace chip;
using namespace chip::Thread;
using namespace chip::DeviceLayer::PersistedStorage;

namespace chip {
namespace DeviceLayer {
namespace NetworkCommissioning {

// NOTE: For GenericThreadDriver, we assume that the network configuration is persisted by
// the OpenThread stack after ConnectNetwork command is called, and before that, all the changes
// are made to a local copy of the dataset stored in mStagingNetwork.
// Also, in order to support the fail-safe mechanism, the configuration is backed up in a temporary
// KVS slot upon any changes and restored when the fail-safe timeout is triggered or the device
// reboots without completing all the changes.

CHIP_ERROR GenericThreadDriver::Init(Internal::BaseDriver::NetworkStatusChangeCallback * statusChangeCallback)
{
    ThreadStackMgrImpl().SetNetworkStatusChangeCallback(statusChangeCallback);
    ThreadStackMgrImpl().GetThreadProvision(mStagingNetwork);

    // If the network configuration backup exists, it means that the device has been rebooted with
    // the fail-safe armed. Since OpenThread persists all operational dataset changes, the backup
    // must be restored on the boot. If there's no backup, the below function is a no-op.
    RevertConfiguration();

    return CHIP_NO_ERROR;
}

void GenericThreadDriver::Shutdown()
{
    ThreadStackMgrImpl().SetNetworkStatusChangeCallback(nullptr);
}

CHIP_ERROR GenericThreadDriver::CommitConfiguration()
{
    // OpenThread persists the network configuration on AttachToThreadNetwork, so simply remove
    // the backup, so that it cannot be restored. If no backup could be found, it means that the
    // configuration has not been modified since the fail-safe was armed, so return with no error.

    DefaultStorageKeyAllocator key;
    CHIP_ERROR error = KeyValueStoreMgr().Delete(key.FailSafeNetworkConfig());

    return error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND ? CHIP_NO_ERROR : error;
}

CHIP_ERROR GenericThreadDriver::RevertConfiguration()
{
    DefaultStorageKeyAllocator key;
    uint8_t datasetBytes[Thread::kSizeOperationalDataset];
    size_t datasetLength;

    CHIP_ERROR error = KeyValueStoreMgr().Get(key.FailSafeNetworkConfig(), datasetBytes, sizeof(datasetBytes), &datasetLength);

    // If no backup could be found, it means that the network configuration has not been modified
    // since the fail-safe was armed, so return with no error.
    ReturnErrorCodeIf(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR);

    ChipLogProgress(NetworkProvisioning, "Reverting Thread operational dataset");

    if (error == CHIP_NO_ERROR)
    {
        error = mStagingNetwork.Init(ByteSpan(datasetBytes, datasetLength));
    }

    if (error == CHIP_NO_ERROR)
    {
        error = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingNetwork, /* callback */ nullptr);
    }

    // Always remove the backup, regardless if it can be successfully restored.
    KeyValueStoreMgr().Delete(key.FailSafeNetworkConfig());

    return error;
}

Status GenericThreadDriver::AddOrUpdateNetwork(ByteSpan operationalDataset, MutableCharSpan & outDebugText,
                                               uint8_t & outNetworkIndex)
{
    ByteSpan newExtpanid;
    Thread::OperationalDataset newDataset;

    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    VerifyOrReturnError(newDataset.Init(operationalDataset) == CHIP_NO_ERROR && newDataset.IsCommissioned(), Status::kOutOfRange);
    newDataset.GetExtendedPanIdAsByteSpan(newExtpanid);

    // We only support one active operational dataset. Add/Update based on either:
    // Staging network not commissioned yet (active) or we are updating the dataset with same Extended Pan ID.
    VerifyOrReturnError(!mStagingNetwork.IsCommissioned() || MatchesNetworkId(mStagingNetwork, newExtpanid) == Status::kSuccess,
                        Status::kBoundsExceeded);
    VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

    mStagingNetwork = newDataset;
    return Status::kSuccess;
}

Status GenericThreadDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex)
{
    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    VerifyOrReturnError(status == Status::kSuccess, status);
    VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

    mStagingNetwork.Clear();

    return Status::kSuccess;
}

Status GenericThreadDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText)
{
    outDebugText.reduce_size(0);

    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    VerifyOrReturnError(status == Status::kSuccess, status);
    VerifyOrReturnError(index == 0, Status::kOutOfRange);

    return Status::kSuccess;
}

void GenericThreadDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
{
    NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId);

    if (status == Status::kSuccess && BackupConfiguration() != CHIP_NO_ERROR)
    {
        status = Status::kUnknownError;
    }

    if (status == Status::kSuccess &&
        DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingNetwork, callback) != CHIP_NO_ERROR)
    {
        status = Status::kUnknownError;
    }

    if (status != Status::kSuccess)
    {
        callback->OnResult(status, CharSpan(), 0);
    }
}

void GenericThreadDriver::ScanNetworks(ThreadDriver::ScanCallback * callback)
{
    if (DeviceLayer::ThreadStackMgrImpl().StartThreadScan(callback) != CHIP_NO_ERROR)
    {
        callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
    }
}

Status GenericThreadDriver::MatchesNetworkId(const Thread::OperationalDataset & dataset, const ByteSpan & networkId) const
{
    ByteSpan extpanid;

    if (!dataset.IsCommissioned())
    {
        return Status::kNetworkIDNotFound;
    }

    if (dataset.GetExtendedPanIdAsByteSpan(extpanid) != CHIP_NO_ERROR)
    {
        return Status::kUnknownError;
    }

    return networkId.data_equal(extpanid) ? Status::kSuccess : Status::kNetworkIDNotFound;
}

CHIP_ERROR GenericThreadDriver::BackupConfiguration()
{
    DefaultStorageKeyAllocator key;

    // If configuration is already backed up, return with no error
    CHIP_ERROR err = KeyValueStoreMgr().Get(key.FailSafeNetworkConfig(), nullptr, 0);

    if (err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL)
    {
        return CHIP_NO_ERROR;
    }

    ByteSpan dataset = mStagingNetwork.AsByteSpan();

    return KeyValueStoreMgr().Put(key.FailSafeNetworkConfig(), dataset.data(), dataset.size());
}

size_t GenericThreadDriver::ThreadNetworkIterator::Count()
{
    return driver->mStagingNetwork.IsCommissioned() ? 1 : 0;
}

bool GenericThreadDriver::ThreadNetworkIterator::Next(Network & item)
{
    if (exhausted || !driver->mStagingNetwork.IsCommissioned())
    {
        return false;
    }
    uint8_t extpanid[kSizeExtendedPanId];
    VerifyOrReturnError(driver->mStagingNetwork.GetExtendedPanId(extpanid) == CHIP_NO_ERROR, false);
    memcpy(item.networkID, extpanid, kSizeExtendedPanId);
    item.networkIDLen = kSizeExtendedPanId;
    item.connected    = false;
    exhausted         = true;

    Thread::OperationalDataset currentDataset;
    uint8_t enabledExtPanId[Thread::kSizeExtendedPanId];

    // The Thread network is not actually enabled.
    VerifyOrReturnError(ConnectivityMgrImpl().IsThreadAttached(), true);
    VerifyOrReturnError(ThreadStackMgrImpl().GetThreadProvision(currentDataset) == CHIP_NO_ERROR, true);
    // The Thread network is not enabled, but has a different extended pan id.
    VerifyOrReturnError(currentDataset.GetExtendedPanId(enabledExtPanId) == CHIP_NO_ERROR, true);
    VerifyOrReturnError(memcmp(extpanid, enabledExtPanId, kSizeExtendedPanId) == 0, true);
    // The Thread network is enabled and has the same extended pan id as the one in our record.
    item.connected = true;

    return true;
}

} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
<|endoftext|>


<commit_before>#include <Common.h>
#include <Network/CommonNetwork.h>
#include <Network/GamePacketNew.h>
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/PacketContainer.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Util/Util.h>

#include "Zone/Zone.h"
#include "Zone/ZonePosition.h"
#include "Zone/HousingZone.h"
#include "Zone/HousingMgr.h"
#include "Zone/Land.h"

#include "Network/GameConnection.h"

#include "Network/PacketWrappers/ExaminePacket.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/PacketWrappers/ChatPacket.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket142.h"

#include "DebugCommand/DebugCommandHandler.h"

#include "Event/EventHelper.h"

#include "Action/Action.h"
#include "Action/ActionTeleport.h"

#include "Session.h"
#include "ServerZone.h"
#include "Forwards.h"
#include "Framework.h"
#include <Network/PacketDef/Lobby/ServerLobbyDef.h>

extern Core::Framework g_fw;

using namespace Core::Common;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
using namespace Core::Network::ActorControl;

void examineHandler( Core::Entity::Player& player, uint32_t targetId )
{
  using namespace Core;

  auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
  if( pSession )
  {
    auto pTarget = pSession->getPlayer();
    if( pTarget )
    {
      if( pTarget->isActingAsGm() || pTarget->getZoneId() != player.getZoneId() )
      {
        player.queuePacket( makeActorControl142( player.getId(), ActorControlType::ExamineError ) );
      }
      else
      {
        player.queuePacket( std::make_shared< ExaminePacket >( player, pTarget ) );
      }
    }
  }
}

void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
                                                          Entity::Player& player )
{
  auto pLog = g_fw.get< Logger >();

  const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket );

  const auto commandId = packet.data().commandId;
  const auto param1 = *reinterpret_cast< const uint64_t* >( &packet.data().param11 );
  const auto param11 = packet.data().param11;
  const auto param12 = packet.data().param12;
  const auto param2 = packet.data().param2;
  const auto param3 = packet.data().param3;

  pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " +
               Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) +
               "\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) +
               "\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) +
               "\nparam3: " + Util::intToHexString( static_cast< uint64_t >( param3 & 0xFFFFFFFFFFFFFFF ), 16 )
  );

  //g_log.Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString());

  switch( commandId )
  {
    case ClientTriggerType::ToggleSheathe:  // Toggle sheathe
    {
      if( param11 == 1 )
        player.setStance( Common::Stance::Active );
      else
      {
        player.setStance( Common::Stance::Passive );
        player.setAutoattack( false );
      }

      player.sendToInRangeSet( makeActorControl142( player.getId(), 0, param11, 1 ) );

      break;
    }
    case ClientTriggerType::ToggleAutoAttack:  // Toggle auto-attack
    {
      if( param11 == 1 )
      {
        player.setAutoattack( true );
        player.setStance( Common::Stance::Active );
      }
      else
        player.setAutoattack( false );

      player.sendToInRangeSet( makeActorControl142( player.getId(), 1, param11, 1 ) );

      break;
    }
    case ClientTriggerType::ChangeTarget: // Change target
    {

      uint64_t targetId = param1;
      player.changeTarget( targetId );
      break;
    }
    case ClientTriggerType::DismountReq:
    {
      player.dismount();
      break;
    }
    case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off)
    {
      // todo: check if status can be removed by client from exd
      player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
      break;
    }
    case ClientTriggerType::CastCancel: // Cancel cast
    {
      if( player.getCurrentAction() )
        player.getCurrentAction()->setInterrupted();
      break;
    }
    case ClientTriggerType::Examine:
    {
      uint32_t targetId = param11;
      examineHandler( player, targetId );
      break;
    }
    case ClientTriggerType::MarkPlayer: // Mark player
    {
      break;
    }
    case ClientTriggerType::SetTitleReq: // Set player title
    {
      player.setTitle( static_cast< uint16_t >( param1 ) );
      break;
    }
    case ClientTriggerType::TitleList: // Get title list
    {
      player.sendTitleList();
      break;
    }
    case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen
    {
      uint32_t howToId = param11;
      player.updateHowtosSeen( howToId );
      break;
    }
    case ClientTriggerType::CharaNameReq:
    {
      uint64_t targetContentId = param1;
      // todo: look up player by content id
      /*
        auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
        packet->data().contentId = targetContentId;

        // lookup the name

        strcpy( packet->data().name, name );

        player.queuePacket( packet );
      */
     break;
    }
    case ClientTriggerType::EmoteReq: // emote
    {
      uint64_t targetId = player.getTargetId();
      uint32_t emoteId = param11;
      bool isSilent = param2 == 1;

      auto pExdData = g_fw.get< Data::ExdDataGenerated >();
      auto emoteData = pExdData->get< Data::Emote >( emoteId );

      if( !emoteData )
        return;

      player.emote( emoteId, targetId, isSilent );

      bool isPersistent = emoteData->emoteMode != 0;

      if( isPersistent )
      {
        player.setStance( Common::Stance::Passive );
        player.setAutoattack( false );
        player.setPersistentEmote( emoteData->emoteMode );
        player.setStatus( Common::ActorStatus::EmoteMode );

        player.sendToInRangeSet( makeActorControl142( player.getId(), ActorControlType::SetStatus,
                                                      static_cast< uint8_t >( Common::ActorStatus::EmoteMode ),
                                                      emoteData->hasCancelEmote ? 1 : 0 ), true );
      }

      if( emoteData->drawsWeapon )
      {
        player.setStance( Common::Stance::Active );
      }

      break;
    }
    case ClientTriggerType::EmoteCancel: // emote
    {
      player.emoteInterrupt();
      break;
    }
    case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote
    {
      player.setPersistentEmote( 0 );
      player.emoteInterrupt();
      player.setStatus( Common::ActorStatus::Idle );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetStatus,
                                                   static_cast< uint8_t >( Common::ActorStatus::Idle ) );
      player.sendToInRangeSet( pSetStatusPacket );
      break;
    }
    case ClientTriggerType::PoseChange: // change pose
    case ClientTriggerType::PoseReapply: // reapply pose
    {
      player.setPose( param12 );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetPose, param11, param12 );
      player.sendToInRangeSet( pSetStatusPacket, true );
      break;
    }
    case ClientTriggerType::PoseCancel: // cancel pose
    {
      player.setPose( param12 );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetPose, param11, param12 );
      player.sendToInRangeSet( pSetStatusPacket, true );
      break;
    }
    case ClientTriggerType::Return: // return dead / accept raise
    {
      switch( static_cast < ResurrectType >( param1 ) )
      {
        case ResurrectType::RaiseSpell:
          // todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
          player.returnToHomepoint();
          break;
        case ResurrectType::Return:
          player.returnToHomepoint();
          break;
        default:
          break;
      }

    }
    case ClientTriggerType::FinishZoning: // Finish zoning
    {
      player.finishZoning();
      break;
    }

    case ClientTriggerType::Teleport: // Teleport
    {

      player.teleportQuery( param11 );
      break;
    }
    case ClientTriggerType::DyeItem: // Dye item
    {
      break;
    }
    case ClientTriggerType::DirectorInitFinish: // Director init finish
    {
      player.getCurrentZone()->onInitDirector( player );
      break;
    }
    case ClientTriggerType::DirectorSync: // Director init finish
    {
      player.getCurrentZone()->onDirectorSync( player );
      break;
    }
    case ClientTriggerType::EnterTerritoryEventFinished:// this may still be something else. I think i have seen it elsewhere
    {
      player.setOnEnterEventDone( true );
      break;
    }
    case ClientTriggerType::RequestInstanceLeave:
    {
      // todo: apply cf penalty if applicable, make sure player isnt in combat
      player.exitInstance();
      break;
    }
    case ClientTriggerType::AbandonQuest:
    {
      player.removeQuest( static_cast< uint16_t >( param1 ) );
      break;
    }
    case ClientTriggerType::RequestHousingSign:
    {

      auto plotPricePacket = makeZonePacket< Server::FFXIVIpcLandPriceUpdate >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      pLog->debug( " Ward: " + std::to_string( ward ) + " Plot: " + std::to_string( plot ) );

      player.setActiveLand( plot, ward );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      if( !hZone )
        return;

      auto land = hZone->getLand( plot );
      plotPricePacket->data().price = land->getCurrentPrice();
      plotPricePacket->data().timeLeft = land->getDevaluationTime();

      player.queuePacket( plotPricePacket );

      break;
    }
    case ClientTriggerType::RequestHousingInfoSign:
    {

      auto LandInfoSignPacket = makeZonePacket< Server::FFXIVIpcLandInfoSign >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      pLog->debug( " Ward: " + std::to_string( ward ) + " Plot: " + std::to_string( plot ) );

      player.setActiveLand( plot, ward );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      auto land = hZone->getLand( plot );
      if( !land )
      {
        auto pHousingMgr = g_fw.get< HousingMgr >();
        land = pHousingMgr->getLandByOwnerId( player.getId() );
      }

      memcpy( &LandInfoSignPacket->data().landMsg, "Hello World", 11 );
      //memcpy( &LandInfoSignPacket->data().landName, &land->getLandName(), 20 );
      memcpy( &LandInfoSignPacket->data().landName, "Hello World", 11 );
      LandInfoSignPacket->data().houseSize = land->getHouseSize();
      LandInfoSignPacket->data().houseState = land->getState();
      LandInfoSignPacket->data().landId = land->getLandId();
      LandInfoSignPacket->data().ownerId = land->getPlayerOwner();
      memcpy( &LandInfoSignPacket->data().ownerName, "Hello World", 11 );
      LandInfoSignPacket->data().wardNum = land->getWardNum();
      LandInfoSignPacket->data().worldId = 67;
      LandInfoSignPacket->data().zoneId = land->getZoneId();

      player.queuePacket( LandInfoSignPacket );

      break;
    }
    case ClientTriggerType::RequestHousingRename:
    {
      auto landRenamePacket = makeZonePacket< Server::FFXIVIpcRenameLand >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      auto land = hZone->getLand( plot );

      if( !land )
      {
        auto pHousingMgr = g_fw.get< HousingMgr >();
        land = pHousingMgr->getLandByOwnerId( player.getId() );
      }

      landRenamePacket->data().landId = land->getLandId();
      landRenamePacket->data().wardNum = land->getWardNum();
      landRenamePacket->data().worldId = 67;
      landRenamePacket->data().zoneId = land->getZoneId();
      memcpy( &landRenamePacket->data().landName, &land->getLandName(), 20 );

      player.queuePacket( landRenamePacket );

      break;
    }
    case ClientTriggerType::RequestHousingItemUI:
    {
      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      auto pShowHousingItemUIPacket = makeActorControl142( player.getId(), ShowHousingItemUI, 0, plot );

      player.queuePacket( pShowHousingItemUIPacket );

      //TODO: show item housing container

      break;
    }

    default:
    {
      pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
                   Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) );
      break;
    }
  }
}
<commit_msg>fixed errors<commit_after>#include <Common.h>
#include <Network/CommonNetwork.h>
#include <Network/GamePacketNew.h>
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/PacketContainer.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Util/Util.h>

#include "Zone/Zone.h"
#include "Zone/ZonePosition.h"
#include "Zone/HousingZone.h"
#include "Zone/HousingMgr.h"
#include "Zone/Land.h"

#include "Network/GameConnection.h"

#include "Network/PacketWrappers/ExaminePacket.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/PacketWrappers/ChatPacket.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket142.h"

#include "DebugCommand/DebugCommandHandler.h"

#include "Event/EventHelper.h"

#include "Action/Action.h"
#include "Action/ActionTeleport.h"

#include "Session.h"
#include "ServerZone.h"
#include "Forwards.h"
#include "Framework.h"
#include <Network/PacketDef/Lobby/ServerLobbyDef.h>

extern Core::Framework g_fw;

using namespace Core::Common;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
using namespace Core::Network::ActorControl;

void examineHandler( Core::Entity::Player& player, uint32_t targetId )
{
  using namespace Core;

  auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
  if( pSession )
  {
    auto pTarget = pSession->getPlayer();
    if( pTarget )
    {
      if( pTarget->isActingAsGm() || pTarget->getZoneId() != player.getZoneId() )
      {
        player.queuePacket( makeActorControl142( player.getId(), ActorControlType::ExamineError ) );
      }
      else
      {
        player.queuePacket( std::make_shared< ExaminePacket >( player, pTarget ) );
      }
    }
  }
}

void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
                                                          Entity::Player& player )
{
  auto pLog = g_fw.get< Logger >();

  const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket );

  const auto commandId = packet.data().commandId;
  const auto param1 = *reinterpret_cast< const uint64_t* >( &packet.data().param11 );
  const auto param11 = packet.data().param11;
  const auto param12 = packet.data().param12;
  const auto param2 = packet.data().param2;
  const auto param3 = packet.data().param3;

  pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " +
               Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) +
               "\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) +
               "\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) +
               "\nparam3: " + Util::intToHexString( static_cast< uint64_t >( param3 & 0xFFFFFFFFFFFFFFF ), 16 )
  );

  //g_log.Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString());

  switch( commandId )
  {
    case ClientTriggerType::ToggleSheathe:  // Toggle sheathe
    {
      if( param11 == 1 )
        player.setStance( Common::Stance::Active );
      else
      {
        player.setStance( Common::Stance::Passive );
        player.setAutoattack( false );
      }

      player.sendToInRangeSet( makeActorControl142( player.getId(), 0, param11, 1 ) );

      break;
    }
    case ClientTriggerType::ToggleAutoAttack:  // Toggle auto-attack
    {
      if( param11 == 1 )
      {
        player.setAutoattack( true );
        player.setStance( Common::Stance::Active );
      }
      else
        player.setAutoattack( false );

      player.sendToInRangeSet( makeActorControl142( player.getId(), 1, param11, 1 ) );

      break;
    }
    case ClientTriggerType::ChangeTarget: // Change target
    {

      uint64_t targetId = param1;
      player.changeTarget( targetId );
      break;
    }
    case ClientTriggerType::DismountReq:
    {
      player.dismount();
      break;
    }
    case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off)
    {
      // todo: check if status can be removed by client from exd
      player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
      break;
    }
    case ClientTriggerType::CastCancel: // Cancel cast
    {
      if( player.getCurrentAction() )
        player.getCurrentAction()->setInterrupted();
      break;
    }
    case ClientTriggerType::Examine:
    {
      uint32_t targetId = param11;
      examineHandler( player, targetId );
      break;
    }
    case ClientTriggerType::MarkPlayer: // Mark player
    {
      break;
    }
    case ClientTriggerType::SetTitleReq: // Set player title
    {
      player.setTitle( static_cast< uint16_t >( param1 ) );
      break;
    }
    case ClientTriggerType::TitleList: // Get title list
    {
      player.sendTitleList();
      break;
    }
    case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen
    {
      uint32_t howToId = param11;
      player.updateHowtosSeen( howToId );
      break;
    }
    case ClientTriggerType::CharaNameReq:
    {
      uint64_t targetContentId = param1;
      // todo: look up player by content id
      /*
        auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
        packet->data().contentId = targetContentId;

        // lookup the name

        strcpy( packet->data().name, name );

        player.queuePacket( packet );
      */
     break;
    }
    case ClientTriggerType::EmoteReq: // emote
    {
      uint64_t targetId = player.getTargetId();
      uint32_t emoteId = param11;
      bool isSilent = param2 == 1;

      auto pExdData = g_fw.get< Data::ExdDataGenerated >();
      auto emoteData = pExdData->get< Data::Emote >( emoteId );

      if( !emoteData )
        return;

      player.emote( emoteId, targetId, isSilent );

      bool isPersistent = emoteData->emoteMode != 0;

      if( isPersistent )
      {
        player.setStance( Common::Stance::Passive );
        player.setAutoattack( false );
        player.setPersistentEmote( emoteData->emoteMode );
        player.setStatus( Common::ActorStatus::EmoteMode );

        player.sendToInRangeSet( makeActorControl142( player.getId(), ActorControlType::SetStatus,
                                                      static_cast< uint8_t >( Common::ActorStatus::EmoteMode ),
                                                      emoteData->hasCancelEmote ? 1 : 0 ), true );
      }

      if( emoteData->drawsWeapon )
      {
        player.setStance( Common::Stance::Active );
      }

      break;
    }
    case ClientTriggerType::EmoteCancel: // emote
    {
      player.emoteInterrupt();
      break;
    }
    case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote
    {
      player.setPersistentEmote( 0 );
      player.emoteInterrupt();
      player.setStatus( Common::ActorStatus::Idle );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetStatus,
                                                   static_cast< uint8_t >( Common::ActorStatus::Idle ) );
      player.sendToInRangeSet( pSetStatusPacket );
      break;
    }
    case ClientTriggerType::PoseChange: // change pose
    case ClientTriggerType::PoseReapply: // reapply pose
    {
      player.setPose( param12 );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetPose, param11, param12 );
      player.sendToInRangeSet( pSetStatusPacket, true );
      break;
    }
    case ClientTriggerType::PoseCancel: // cancel pose
    {
      player.setPose( param12 );
      auto pSetStatusPacket = makeActorControl142( player.getId(), SetPose, param11, param12 );
      player.sendToInRangeSet( pSetStatusPacket, true );
      break;
    }
    case ClientTriggerType::Return: // return dead / accept raise
    {
      switch( static_cast < ResurrectType >( param1 ) )
      {
        case ResurrectType::RaiseSpell:
          // todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
          player.returnToHomepoint();
          break;
        case ResurrectType::Return:
          player.returnToHomepoint();
          break;
        default:
          break;
      }

    }
    case ClientTriggerType::FinishZoning: // Finish zoning
    {
      player.finishZoning();
      break;
    }

    case ClientTriggerType::Teleport: // Teleport
    {

      player.teleportQuery( param11 );
      break;
    }
    case ClientTriggerType::DyeItem: // Dye item
    {
      break;
    }
    case ClientTriggerType::DirectorInitFinish: // Director init finish
    {
      player.getCurrentZone()->onInitDirector( player );
      break;
    }
    case ClientTriggerType::DirectorSync: // Director init finish
    {
      player.getCurrentZone()->onDirectorSync( player );
      break;
    }
    case ClientTriggerType::EnterTerritoryEventFinished:// this may still be something else. I think i have seen it elsewhere
    {
      player.setOnEnterEventDone( true );
      break;
    }
    case ClientTriggerType::RequestInstanceLeave:
    {
      // todo: apply cf penalty if applicable, make sure player isnt in combat
      player.exitInstance();
      break;
    }
    case ClientTriggerType::AbandonQuest:
    {
      player.removeQuest( static_cast< uint16_t >( param1 ) );
      break;
    }
    case ClientTriggerType::RequestHousingSign:
    {

      auto plotPricePacket = makeZonePacket< Server::FFXIVIpcLandPriceUpdate >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      pLog->debug( " Ward: " + std::to_string( ward ) + " Plot: " + std::to_string( plot ) );

      player.setActiveLand( plot, ward );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      if( !hZone )
        return;

      auto land = hZone->getLand( plot );
      plotPricePacket->data().price = land->getCurrentPrice();
      plotPricePacket->data().timeLeft = land->getDevaluationTime();

      player.queuePacket( plotPricePacket );

      break;
    }
    case ClientTriggerType::RequestHousingInfoSign:
    {

      auto LandInfoSignPacket = makeZonePacket< Server::FFXIVIpcLandInfoSign >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      pLog->debug( " Ward: " + std::to_string( ward ) + " Plot: " + std::to_string( plot ) );

      player.setActiveLand( plot, ward );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      auto land = hZone->getLand( plot );
      if( !land )
      {
        auto pHousingMgr = g_fw.get< HousingMgr >();
        land = pHousingMgr->getLandByOwnerId( player.getId() );
      }

      memcpy( &LandInfoSignPacket->data().landMsg, "Hello World", 11 );
      memcpy( &LandInfoSignPacket->data().landName, land->getLandName().c_str(), 20 );
      LandInfoSignPacket->data().houseSize = land->getHouseSize();
      LandInfoSignPacket->data().houseState = land->getState();
      LandInfoSignPacket->data().landId = land->getLandId();
      LandInfoSignPacket->data().ownerId = land->getPlayerOwner();
      memcpy( &LandInfoSignPacket->data().ownerName, "Hello World", 11 );
      LandInfoSignPacket->data().wardNum = land->getWardNum();
      LandInfoSignPacket->data().worldId = 67;
      LandInfoSignPacket->data().zoneId = land->getZoneId();

      player.queuePacket( LandInfoSignPacket );

      break;
    }
    case ClientTriggerType::RequestHousingRename:
    {
      auto landRenamePacket = makeZonePacket< Server::FFXIVIpcRenameLand >( player.getId() );

      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );

      auto zone = player.getCurrentZone();

      auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );

      auto land = hZone->getLand( plot );

      if( !land )
      {
        auto pHousingMgr = g_fw.get< HousingMgr >();
        land = pHousingMgr->getLandByOwnerId( player.getId() );
      }

      landRenamePacket->data().landId = land->getLandId();
      landRenamePacket->data().wardNum = land->getWardNum();
      landRenamePacket->data().worldId = 67;
      landRenamePacket->data().zoneId = land->getZoneId();
      memcpy( &landRenamePacket->data().landName, land->getLandName().c_str(), 20 );

      player.queuePacket( landRenamePacket );

      break;
    }
    case ClientTriggerType::RequestHousingItemUI:
    {
      uint8_t ward = ( param12 & 0xFF00 ) >> 8;
      uint8_t plot = ( param12 & 0xFF );
      auto pShowHousingItemUIPacket = makeActorControl142( player.getId(), ShowHousingItemUI, 0, plot );

      player.queuePacket( pShowHousingItemUIPacket );

      //TODO: show item housing container

      break;
    }

    default:
    {
      pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
                   Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) );
      break;
    }
  }
}
<|endoftext|>