<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.1.4.1  2000/05/08 15:13:59  cblume
Introduce boundary checking

Revision 1.1  2000/02/28 18:59:19  cblume
Add new TRD classes

*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  Base class of a general container for data of a TRD detector segment.    //
//  Adapted from AliDigits (origin: M.Ivanov).                               //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "TClass.h"
#include "TError.h"
#include "AliTRDsegmentID.h"
#include "AliTRDarrayI.h"
#include "AliTRDdataArray.h"

ClassImp(AliTRDdataArray)

//_____________________________________________________________________________
AliTRDdataArray::AliTRDdataArray()
{
  //
  // Default constructor
  //

  fIndex   =  0;

  fNdim1   = -1;
  fNdim2   = -1;
  fNelems  = -1;

  fBufType = -1;

  fNrow    =  0;
  fNcol    =  0;
  fNtime   =  0;

}

//_____________________________________________________________________________
AliTRDdataArray::AliTRDdataArray(Int_t nrow, Int_t ncol, Int_t ntime)
{
  //
  // Creates a AliTRDdataArray with the dimensions <nrow>, <ncol>, and <ntime>.
  // The row- and column dimensions are compressible.
  //

  Allocate(nrow,ncol,ntime);

}

//_____________________________________________________________________________
AliTRDdataArray::~AliTRDdataArray()
{
  //
  // Destructor
  //

  if (fIndex) fIndex->Delete();

}

//_____________________________________________________________________________
void AliTRDdataArray::Allocate(Int_t nrow, Int_t ncol,Int_t ntime)
{
  //
  // Allocates memory for a AliTRDdataArray with the dimensions
  // <nrow>, <ncol>, and <ntime>.
  // The row- and column dimensions are compressible.
  //

  if (nrow  <= 0) {
    Error("AliTRDdataArray::Allocate","The number of rows has to be positive");
    exit(1);
  }
  if (ncol  <= 0) {
    Error("AliTRDdataArray::Allocate","The number of columns has to be positive");
    exit(1);
  }
  if (ntime <= 0) {
    Error("AliTRDdataArray::Allocate","The number of timebins has to be positive");
    exit(1);
  }

  // The two-dimensional array row/column gets mapped into the first
  // dimension of the array. The second array dimension, which is not compressible,
  // corresponds to the time direction
  fNdim1  = nrow * ncol;
  fNdim2  = ntime;
  fNelems = fNdim1 * fNdim2;

  fNrow   = nrow;
  fNcol   = ncol;
  fNtime  = ntime;

  if (fIndex) delete fIndex;
  fIndex = new AliTRDarrayI;
  fIndex->Set(fNdim2);
  for (Int_t i = 0, k = 0; i < fNdim2; i++, k += fNdim1) {
    (*fIndex)[i] = k;
  }

  fBufType = 0;

}

//_____________________________________________________________________________
void AliTRDdataArray::Reset()
{
  //
  // Reset the array (old content gets deleted)
  //

  if (fIndex) delete fIndex;
  fIndex = new AliTRDarrayI;
  fIndex->Set(0);

  fNdim1   = -1;
  fNdim2   = -1;
  fNelems  = -1;

  fBufType = -1;

  fNrow    =  0;
  fNcol    =  0;
  fNtime   =  0;

}

<commit_msg>Added #include <stdlib.h><commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.2  2000/05/08 16:17:27  cblume
Merge TRD-develop

Revision 1.1.4.1  2000/05/08 15:13:59  cblume
Introduce boundary checking

Revision 1.1  2000/02/28 18:59:19  cblume
Add new TRD classes

*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  Base class of a general container for data of a TRD detector segment.    //
//  Adapted from AliDigits (origin: M.Ivanov).                               //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "TClass.h"
#include "TError.h"
#include "AliTRDsegmentID.h"
#include "AliTRDarrayI.h"
#include "AliTRDdataArray.h"

ClassImp(AliTRDdataArray)

//_____________________________________________________________________________
AliTRDdataArray::AliTRDdataArray()
{
  //
  // Default constructor
  //

  fIndex   =  0;

  fNdim1   = -1;
  fNdim2   = -1;
  fNelems  = -1;

  fBufType = -1;

  fNrow    =  0;
  fNcol    =  0;
  fNtime   =  0;

}

//_____________________________________________________________________________
AliTRDdataArray::AliTRDdataArray(Int_t nrow, Int_t ncol, Int_t ntime)
{
  //
  // Creates a AliTRDdataArray with the dimensions <nrow>, <ncol>, and <ntime>.
  // The row- and column dimensions are compressible.
  //

  Allocate(nrow,ncol,ntime);

}

//_____________________________________________________________________________
AliTRDdataArray::~AliTRDdataArray()
{
  //
  // Destructor
  //

  if (fIndex) fIndex->Delete();

}

//_____________________________________________________________________________
void AliTRDdataArray::Allocate(Int_t nrow, Int_t ncol,Int_t ntime)
{
  //
  // Allocates memory for a AliTRDdataArray with the dimensions
  // <nrow>, <ncol>, and <ntime>.
  // The row- and column dimensions are compressible.
  //

  if (nrow  <= 0) {
    Error("AliTRDdataArray::Allocate","The number of rows has to be positive");
    exit(1);
  }
  if (ncol  <= 0) {
    Error("AliTRDdataArray::Allocate","The number of columns has to be positive");
    exit(1);
  }
  if (ntime <= 0) {
    Error("AliTRDdataArray::Allocate","The number of timebins has to be positive");
    exit(1);
  }

  // The two-dimensional array row/column gets mapped into the first
  // dimension of the array. The second array dimension, which is not compressible,
  // corresponds to the time direction
  fNdim1  = nrow * ncol;
  fNdim2  = ntime;
  fNelems = fNdim1 * fNdim2;

  fNrow   = nrow;
  fNcol   = ncol;
  fNtime  = ntime;

  if (fIndex) delete fIndex;
  fIndex = new AliTRDarrayI;
  fIndex->Set(fNdim2);
  for (Int_t i = 0, k = 0; i < fNdim2; i++, k += fNdim1) {
    (*fIndex)[i] = k;
  }

  fBufType = 0;

}

//_____________________________________________________________________________
void AliTRDdataArray::Reset()
{
  //
  // Reset the array (old content gets deleted)
  //

  if (fIndex) delete fIndex;
  fIndex = new AliTRDarrayI;
  fIndex->Set(0);

  fNdim1   = -1;
  fNdim2   = -1;
  fNelems  = -1;

  fBufType = -1;

  fNrow    =  0;
  fNcol    =  0;
  fNtime   =  0;

}

<|endoftext|>


<commit_before>#include "StdAfx.h"
#include <windows.h>
#include <iostream>
#include <osg/MatrixTransform>
#include <osgFX/Scribe>
#include "jrOSGHighlightVisitor.h"

jrOSGHighlightVisitor::jrOSGHighlightVisitor(void) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {
}

jrOSGHighlightVisitor::~jrOSGHighlightVisitor(void) {
}

void jrOSGHighlightVisitor::apply(osg::Node &node) {
	if (node.getName().find("ForeArm.Flat") != std::string::npos) {
		//std::cout << "highlighting: " << node.getName() << std::endl;
		//osgFX::Scribe* scribe = new osgFX::Scribe();
		//osg::Group* parent = node.getParent(0);
		//
		//scribe->setName("highlighted");
		//scribe->setWireframeColor(osg::Vec4(0,1,0,0.5));
		//scribe->addChild(&node);
		//
		//parent->replaceChild(&node, scribe);

		osg::Group* parent = node.getParent(0);

		osg::MatrixTransform* transform = new osg::MatrixTransform;

		const double angle = 0.1;
		const osg::Vec3d axis(0, 0, 1);
		transform->setMatrix(osg::Matrix::rotate(angle, axis));
		transform->setName("trans");
		transform->addChild(&node);
		parent->replaceChild(&node, transform);

	}
	else if (node.getName().find("highlighted") != std::string::npos) {
		std::cout << "removing highlight on: " << node.getName() << std::endl;
		osg::Group* parent = node.getParent(0);
		osgFX::Scribe* scribe = dynamic_cast<osgFX::Scribe*>(&node);
		parent->replaceChild(&node, scribe->getChild(0));
		return;
	}

	traverse(node);
}
<commit_msg>More work on the highlight visitor.<commit_after>#include "StdAfx.h"
#include <windows.h>
#include <iostream>
#include <osg/MatrixTransform>
#include <osgFX/Scribe>
#include "jrOSGHighlightVisitor.h"

jrOSGHighlightVisitor::jrOSGHighlightVisitor(void) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {
}

jrOSGHighlightVisitor::~jrOSGHighlightVisitor(void) {
}

void jrOSGHighlightVisitor::apply(osg::Node &node) {
	if (node.getName().find("ForeArm.Flat") != std::string::npos) {
		std::cout << "highlighting: " << node.getName() << std::endl;
		osgFX::Scribe* scribe = new osgFX::Scribe();
		osg::Group* parent = node.getParent(0);

		scribe->setName("highlighted");
		scribe->setWireframeColor(osg::Vec4(0,1,0,0.5));
		scribe->addChild(&node);

		parent->replaceChild(&node, scribe);

		parent = node.getParent(0);

		osg::MatrixTransform* transform = new osg::MatrixTransform;

		const double angle = 0.1;
		const osg::Vec3d axis(0, 0, 1);
		transform->setMatrix(osg::Matrix::rotate(angle, axis));
		transform->setName("trans");
		transform->addChild(&node);
		parent->replaceChild(&node, transform);

	}
	else if (node.getName().find("highlighted") != std::string::npos) {
		std::cout << "removing highlight on: " << node.getName() << std::endl;
		osg::Group* parent = node.getParent(0);
		osgFX::Scribe* scribe = dynamic_cast<osgFX::Scribe*>(&node);
		parent->replaceChild(&node, scribe->getChild(0));
		return;
	}

	traverse(node);
}
<|endoftext|>


<commit_before>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @GFile    g_file.cpp
* @version
* @brief
* @author   duye
* @date	    2013-06-20
* @note
*
*  1. 2013-06-20 duye Created this GFile
*
*/
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <g_file.h>

namespace gsys {

// default create GFile permissions
static const GUint32 G_FILE_MASK = 0x775;

GResult FileUtil::createFile(const GInt8* filePath)
{
    return createFile(filePath, 0);
}

GResult FileUtil::createFile(const GInt8* filePath, const GUint64& initSize)
{
    GInt32 fd = ::creat(filePath, G_FILE_MASK);
    if (fd == -1)
    {
    	return G_NO;
    }

    if (ftruncate(fd, initSize) == -1)
    {
    	::close(fd);
    	return G_NO;
    }

    ::close(fd);

    return G_YES;
}

bool FileUtil::isExist(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return false;
    }

    if (access(filePath, 0) < 0)
    {
    	return false;
    }

    return true;
}

GResult FileUtil::removeFile(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return G_NO;
    }

    GInt8 cmd[128] = {0};
    sprintf(cmd, "rm %s -f", filePath);
    return System::shell(cmd);
}

File::File() : m_fd(-1), m_flags(0), m_pathLen(0)
{
    m_error[0] = 0;
    m_path[0] = 0;
}

File::File(const GInt8* filePath) : m_fd(-1), m_flags(0), m_pathLen(0)
{
    GUint32 len = strlen(filePath);
    if (len < G_PATH_MAX)
    {
    	memcpy(m_path, filePath, len);
    	m_path[len] = 0;
    	m_pathLen = len;
    }

    m_error[0] = 0;
}

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

GResult File::open(const FileOpenFlags fileOpenFlags)
{
    return open(fileOpenFlags, G_FILE_MASK);
}

GResult File::open(const FileOpenFlags fileOpenFlags, const GInt32 mode)
{
    GInt32 openFlags = 0;
    if (fileOpenFlags | G_OPEN_READ)
    {
    	openFlags = O_RDONLY;
    }
    else if (fileOpenFlags | G_OPEN_WRITE)
    {
        openFlags = O_WRONLY | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_RDWR)
    {
    	openFlags = O_RDWR | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_APPEND)
    {
    	if (openFlags == 0)
    	{
            return G_NO;
    	}
        openFlags |= O_APPEND;
    }

    if (openFlags == 0)
    {
    	setError("input open mode error");
    	return G_NO;
    }

    return orgOpen(openFlags, mode);
}

GResult File::close()
{
    if (m_fd < 0)
    {
        setError("file don't open");
        return G_NO;
    }

    GResult ret = (::close(m_fd) != -1 ? G_YES : G_NO);

    m_fd = -1;
    m_path[0] = 0;
    m_flags = 0;

    return ret;
}

GInt64 File::getSize()
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    struct stat	fileStat;
    fstat(m_fd, &fileStat);

    return (GInt64)(fileStat.st_size);
}

GInt64 File::seek(const GInt64 offset, const FileSeekFlags& flags)
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    GInt32 sysFlags = -1;

    switch(flags)
    {
	case G_SEEK_BEG:
            sysFlags = SEEK_SET;
            break;
	case G_SEEK_CUR:
            sysFlags = SEEK_CUR;
            break;
	case G_SEEK_END:
            sysFlags = SEEK_END;
            break;
	default:
	    return G_NO;
	    break;
    }

    return ::lseek(m_fd, offset, sysFlags);
}

GInt64 File::tell()
{
    return seek(0, G_SEEK_CUR);
}

GInt64 File::read(GInt8* buffer, const GUint64 size)
{
    if (buffer == NULL || size <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    return ::read(m_fd, buffer, size);
}

GInt64 File::write(const GInt8* data, const GUint64 length)
{
    if (data == NULL || length <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
        setError("file don't open");
        return G_NO;
    }

    return ::write(m_fd, data, length);
}

GInt8* File::getError()
{
    return m_error;
}

GResult File::orgOpen(const GInt32 flags, const GUint32 mode)
{
    if (m_fd > 0)
    {
    	setError("file had opened");
    	return G_NO;
    }

    if (m_pathLen == 0)
    {
    	setError("hasn't set file path");
    	return G_NO;
    }

    m_fd = ::open(m_path, flags, mode);
    if (m_fd > 0)
    {
    	m_flags = flags;
    }
    else
    {
    	setError("open file failed, check whether exist this file path");
    }

    return (m_fd != -1 ? true : false);
}

void File::setError(const GInt8* args, ...)
{
    System::pformat(m_error, G_ERROR_BUF_SIZE, args);
}
<commit_msg>Update g_file.cpp<commit_after>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @GFile    g_file.cpp
* @version
* @brief
* @author   duye
* @date	    2013-06-20
* @note
*
*  1. 2013-06-20 duye Created this GFile
*
*/
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <g_file.h>

namespace gsys {

// default create GFile permissions
static const GUint32 G_FILE_MASK = 0x775;

GResult FileUtil::createFile(const GInt8* filePath)
{
    return createFile(filePath, 0);
}

GResult FileUtil::createFile(const GInt8* filePath, const GUint64& initSize)
{
    GInt32 fd = ::creat(filePath, G_FILE_MASK);
    if (fd == -1)
    {
    	return G_NO;
    }

    if (ftruncate(fd, initSize) == -1)
    {
    	::close(fd);
    	return G_NO;
    }

    ::close(fd);

    return G_YES;
}

bool FileUtil::isExist(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return false;
    }

    if (access(filePath, 0) < 0)
    {
    	return false;
    }

    return true;
}

GResult FileUtil::removeFile(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return G_NO;
    }

    GInt8 cmd[128] = {0};
    sprintf(cmd, "rm %s -f", filePath);
    return System::shell(cmd);
}

File::File() : m_fd(-1), m_flags(0), m_pathLen(0)
{
    m_error[0] = 0;
    m_path[0] = 0;
}

File::File(const GInt8* filePath) : m_fd(-1), m_flags(0), m_pathLen(0)
{
    GUint32 len = strlen(filePath);
    if (len < G_PATH_MAX)
    {
    	memcpy(m_path, filePath, len);
    	m_path[len] = 0;
    	m_pathLen = len;
    }

    m_error[0] = 0;
}

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

GResult File::open(const FileOpenFlags fileOpenFlags)
{
    return open(fileOpenFlags, G_FILE_MASK);
}

GResult File::open(const FileOpenFlags fileOpenFlags, const GInt32 mode)
{
    GInt32 openFlags = 0;
    if (fileOpenFlags | G_OPEN_READ)
    {
    	openFlags = O_RDONLY;
    }
    else if (fileOpenFlags | G_OPEN_WRITE)
    {
        openFlags = O_WRONLY | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_RDWR)
    {
    	openFlags = O_RDWR | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_APPEND)
    {
    	if (openFlags == 0)
    	{
            return G_NO;
    	}
        openFlags |= O_APPEND;
    }

    if (openFlags == 0)
    {
    	setError("input open mode error");
    	return G_NO;
    }

    return orgOpen(openFlags, mode);
}

GResult File::close()
{
    if (m_fd < 0)
    {
        setError("file don't open");
        return G_NO;
    }

    GResult ret = (::close(m_fd) != -1 ? G_YES : G_NO);

    m_fd = -1;
    m_path[0] = 0;
    m_flags = 0;

    return ret;
}

GInt64 File::getSize()
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    struct stat	fileStat;
    fstat(m_fd, &fileStat);

    return (GInt64)(fileStat.st_size);
}

GInt64 File::seek(const GInt64 offset, const FileSeekFlags& flags)
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    GInt32 sysFlags = -1;

    switch(flags)
    {
	case G_SEEK_BEG:
            sysFlags = SEEK_SET;
            break;
	case G_SEEK_CUR:
            sysFlags = SEEK_CUR;
            break;
	case G_SEEK_END:
            sysFlags = SEEK_END;
            break;
	default:
	    return G_NO;
	    break;
    }

    return ::lseek(m_fd, offset, sysFlags);
}

GInt64 File::tell()
{
    return seek(0, G_SEEK_CUR);
}

GInt64 File::read(GInt8* buffer, const GUint64 size)
{
    if (buffer == NULL || size <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    return ::read(m_fd, buffer, size);
}

GInt64 File::write(const GInt8* data, const GUint64 length)
{
    if (data == NULL || length <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
        setError("file don't open");
        return G_NO;
    }

    return ::write(m_fd, data, length);
}

GInt8* File::getError()
{
    return m_error;
}

GResult File::orgOpen(const GInt32 flags, const GUint32 mode)
{
    if (m_fd > 0)
    {
    	setError("file had opened");
    	return G_NO;
    }

    if (m_pathLen == 0)
    {
    	setError("hasn't set file path");
    	return G_NO;
    }

    m_fd = ::open(m_path, flags, mode);
    if (m_fd > 0)
    {
    	m_flags = flags;
    }
    else
    {
    	setError("open file failed, check whether exist this file path");
    }

    return (m_fd != -1 ? true : false);
}

void File::setError(const GInt8* args, ...)
{
    System::pformat(m_error, G_ERROR_BUF_SIZE, args);
}
}
<|endoftext|>


<commit_before>#if ! defined (__CINT__) || defined (__MAKECINT__)
#include "TError.h"
#include <TClass.h>
#include <TFileMerger.h>
#include <TCanvas.h>
#include <TH1.h>
#include <TGraph.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TPython.h>
#include <TString.h>
#include <TROOT.h>
#include <TSystem.h>
#include <TStyle.h>

#include "qaRec/AliTRDrecoTask.h"

#endif

#include "run.h"

Char_t *libs[] = {"libProofPlayer.so", "libANALYSIS.so", "libTRDqaRec.so", "libPyROOT"};

void makeResults(Char_t *tasks = "ALL", Char_t* dir=0x0)
{
	// Load Libraries in interactive mode
  Int_t nlibs = static_cast<Int_t>(sizeof(libs)/sizeof(Char_t *));
  for(Int_t ilib=0; ilib<nlibs; ilib++){
    if(gSystem->Load(libs[ilib]) >= 0) continue;
    printf("Failed to load %s.\n", libs[ilib]);
    return;
  }

  gStyle->SetOptStat(0);
  Bool_t mc      = kTRUE;
  Bool_t friends = kTRUE;

  // select tasks to process; we should move it to an
  // individual function and move the task identifiers
  // outside the const space
  TObjArray *tasksArray = TString(tasks).Tokenize(" ");
  Int_t fSteerTask = 0;
  for(Int_t isel = 0; isel < tasksArray->GetEntriesFast(); isel++){
    TString s = (dynamic_cast<TObjString *>(tasksArray->UncheckedAt(isel)))->String();
    if(s.CompareTo("ALL") == 0){
      for(Int_t itask = 1; itask < fknTasks; itask++) SETBIT(fSteerTask, itask);
      continue;
    } else if(s.CompareTo("NOFR") == 0){
      friends = kFALSE;
    } else if(s.CompareTo("NOMC") == 0){
      mc = kFALSE;
    } else {
      Bool_t foundOpt = kFALSE;
      for(Int_t itask = 1; itask < fknTasks; itask++){
        if(s.CompareTo(fTaskOpt[itask]) != 0) continue;
        SETBIT(fSteerTask, itask);
        foundOpt = kTRUE;
        break;
      }
      if(!foundOpt) Info("makeResults.C", Form("Task %s not implemented (yet).", s.Data()));
    }
  }

  // catch the list of files using the ROOT Python Interface
  TPython *pyshell = new TPython();
  pyshell->Exec("import commands");

  // file merger object
  TFileMerger *fFM = new TFileMerger();
  TClass *ctask = 0x0;
  TObject *o = 0x0;
  TObjArray *fContainer = 0x0;
  AliTRDrecoTask *task = 0x0;

  if(gSystem->AccessPathName(Form("%s/merge",  gSystem->ExpandPathName("$PWD")))) gSystem->Exec(Form("mkdir -v %s/merge",  gSystem->ExpandPathName("$PWD")));

  printf("\n\tPROCESSING DATA FOR TASKS [%b]:\n", fSteerTask);
  for(Int_t itask = 1; itask <fknTasks; itask++){
    if(!TESTBIT(fSteerTask, itask)) continue;

    ctask = new TClass(fTaskClass[itask]);
    task = (AliTRDrecoTask*)ctask->New();
    task->SetDebugLevel(0);
    task->SetMCdata(mc);
    task->SetFriends(friends);
    printf("\t%s [%s]\n", task->GetTitle(), task->GetName());

     // setup filelist
    TString pathname = gSystem->ExpandPathName( dir ? dir : "$PWD");
    TString filestring((const Char_t*) pyshell->Eval(Form("commands.getstatusoutput(\"find %s | grep TRD.Task%s.root\")[1]", pathname.Data(), task->GetName())));
    TObjArray *filenames = filestring.Tokenize("\n");
    Int_t nFiles = filenames->GetEntriesFast();
    if(!nFiles){
      printf("No Files found for Task %s\n", task->GetName());
      delete task;
      delete ctask;
      continue;
    }

    if(nFiles>1){
      fFM = new(fFM) TFileMerger(kTRUE);
      fFM->OutputFile(Form("%s/merge/TRD.Task%s.root",  gSystem->ExpandPathName("$PWD"), task->GetName()));
      for(Int_t ifile = 0; ifile < nFiles; ifile++){
        TString filename = (dynamic_cast<TObjString *>(filenames->UncheckedAt(ifile)))->String();
        if(filename.Contains("merge")) continue;
        //printf("\tProcessing %s ...\n", filename.Data());
        fFM->AddFile(filename.Data());
      }
      fFM->Merge();
      fFM->~TFileMerger();
      task->Load(Form("%s/merge/TRD.Task%s.root", gSystem->ExpandPathName("$PWD"), task->GetName()));
    } else task->Load((dynamic_cast<TObjString *>(filenames->UncheckedAt(0)))->String().Data());

    if(!(fContainer = task->Container())) {
      delete task;
      delete ctask;
      continue;
    }

    task->PostProcess();
    for(Int_t ipic=0; ipic<task->GetNRefFigures(); ipic++){
      TCanvas *c = new TCanvas("c", "", 500, 500);
      Int_t ifirst, ilast; Option_t *opt;
      TH1 *h = 0x0; TGraph *g = 0x0;
      task->GetRefFigure(ipic, ifirst, ilast, opt);
      if(!(o = fContainer->At(ifirst))) continue;

      if(o->InheritsFrom("TH1")){
        h = dynamic_cast<TH1*>(o);
        h->Draw(opt);
      } else if(o->InheritsFrom("TGraph")){
        g = dynamic_cast<TGraph*>(o);
        g->Draw(opt);
      } else{
        printf("No idea how to plot object of type %s.\n", o->IsA()->GetName());
        printf("Please teach me.\n");
        continue;
      }

      for(Int_t ig=ifirst+1; ig<ilast; ig++){
        if(!(o = fContainer->At(ig))) continue;
        if(o->InheritsFrom("TH1")){
          h = dynamic_cast<TH1*>(o);
          h->Draw(Form("%ssame", opt));
        } else if(o->InheritsFrom("TGraph")){
          g = dynamic_cast<TGraph*>(o);
          g->Draw(opt);
        }
      }
      c->SaveAs(Form("%s_fig%d.gif", task->GetName(), ipic));
      delete c;
    }
    delete task;
    delete ctask;
  }
  delete pyshell;
}

<commit_msg>small fix for drawing superimposed graphs<commit_after>#if ! defined (__CINT__) || defined (__MAKECINT__)
#include "TError.h"
#include <TClass.h>
#include <TFileMerger.h>
#include <TCanvas.h>
#include <TH1.h>
#include <TGraph.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TPython.h>
#include <TString.h>
#include <TROOT.h>
#include <TSystem.h>
#include <TStyle.h>

#include "qaRec/AliTRDrecoTask.h"

#endif

#include "run.h"

Char_t *libs[] = {"libProofPlayer.so", "libANALYSIS.so", "libTRDqaRec.so", "libPyROOT"};

void makeResults(Char_t *tasks = "ALL", Char_t* dir=0x0)
{
	// Load Libraries in interactive mode
  Int_t nlibs = static_cast<Int_t>(sizeof(libs)/sizeof(Char_t *));
  for(Int_t ilib=0; ilib<nlibs; ilib++){
    if(gSystem->Load(libs[ilib]) >= 0) continue;
    printf("Failed to load %s.\n", libs[ilib]);
    return;
  }

  gStyle->SetOptStat(0);
  Bool_t mc      = kTRUE;
  Bool_t friends = kTRUE;

  // select tasks to process; we should move it to an
  // individual function and move the task identifiers
  // outside the const space
  TObjArray *tasksArray = TString(tasks).Tokenize(" ");
  Int_t fSteerTask = 0;
  for(Int_t isel = 0; isel < tasksArray->GetEntriesFast(); isel++){
    TString s = (dynamic_cast<TObjString *>(tasksArray->UncheckedAt(isel)))->String();
    if(s.CompareTo("ALL") == 0){
      for(Int_t itask = 1; itask < fknTasks; itask++) SETBIT(fSteerTask, itask);
      continue;
    } else if(s.CompareTo("NOFR") == 0){
      friends = kFALSE;
    } else if(s.CompareTo("NOMC") == 0){
      mc = kFALSE;
    } else {
      Bool_t foundOpt = kFALSE;
      for(Int_t itask = 1; itask < fknTasks; itask++){
        if(s.CompareTo(fTaskOpt[itask]) != 0) continue;
        SETBIT(fSteerTask, itask);
        foundOpt = kTRUE;
        break;
      }
      if(!foundOpt) Info("makeResults.C", Form("Task %s not implemented (yet).", s.Data()));
    }
  }

  // catch the list of files using the ROOT Python Interface
  TPython *pyshell = new TPython();
  pyshell->Exec("import commands");

  // file merger object
  TFileMerger *fFM = new TFileMerger();
  TClass *ctask = 0x0;
  TObject *o = 0x0;
  TObjArray *fContainer = 0x0;
  AliTRDrecoTask *task = 0x0;

  if(gSystem->AccessPathName(Form("%s/merge",  gSystem->ExpandPathName("$PWD")))) gSystem->Exec(Form("mkdir -v %s/merge",  gSystem->ExpandPathName("$PWD")));

  printf("\n\tPROCESSING DATA FOR TASKS [%b]:\n", fSteerTask);
  for(Int_t itask = 1; itask <fknTasks; itask++){
    if(!TESTBIT(fSteerTask, itask)) continue;

    ctask = new TClass(fTaskClass[itask]);
    task = (AliTRDrecoTask*)ctask->New();
    task->SetDebugLevel(0);
    task->SetMCdata(mc);
    task->SetFriends(friends);
    printf("\t%s [%s]\n", task->GetTitle(), task->GetName());

     // setup filelist
    TString pathname = gSystem->ExpandPathName( dir ? dir : "$PWD");
    TString filestring((const Char_t*) pyshell->Eval(Form("commands.getstatusoutput(\"find %s | grep TRD.Task%s.root\")[1]", pathname.Data(), task->GetName())));
    TObjArray *filenames = filestring.Tokenize("\n");
    Int_t nFiles = filenames->GetEntriesFast();
    if(!nFiles){
      printf("No Files found for Task %s\n", task->GetName());
      delete task;
      delete ctask;
      continue;
    }

    if(nFiles>1){
      fFM = new(fFM) TFileMerger(kTRUE);
      fFM->OutputFile(Form("%s/merge/TRD.Task%s.root",  gSystem->ExpandPathName("$PWD"), task->GetName()));
      for(Int_t ifile = 0; ifile < nFiles; ifile++){
        TString filename = (dynamic_cast<TObjString *>(filenames->UncheckedAt(ifile)))->String();
        if(filename.Contains("merge")) continue;
        //printf("\tProcessing %s ...\n", filename.Data());
        fFM->AddFile(filename.Data());
      }
      fFM->Merge();
      fFM->~TFileMerger();
      task->Load(Form("%s/merge/TRD.Task%s.root", gSystem->ExpandPathName("$PWD"), task->GetName()));
    } else task->Load((dynamic_cast<TObjString *>(filenames->UncheckedAt(0)))->String().Data());

    if(!(fContainer = task->Container())) {
      delete task;
      delete ctask;
      continue;
    }

    task->PostProcess();
    for(Int_t ipic=0; ipic<task->GetNRefFigures(); ipic++){
      TCanvas *c = new TCanvas("c", "", 500, 500);
      Int_t ifirst, ilast; Option_t *opt;
      TH1 *h = 0x0; TGraph *g = 0x0;
      task->GetRefFigure(ipic, ifirst, ilast, opt);
      if(!(o = fContainer->At(ifirst))) continue;

      if(o->InheritsFrom("TH1")){
        h = dynamic_cast<TH1*>(o);
        h->Draw(opt);
      } else if(o->InheritsFrom("TGraph")){
        g = dynamic_cast<TGraph*>(o);
        g->Draw(Form("a%s", opt));
      } else{
        printf("No idea how to plot object of type %s.\n", o->IsA()->GetName());
        printf("Please teach me.\n");
        continue;
      }

      for(Int_t ig=ifirst+1; ig<ilast; ig++){
        if(!(o = fContainer->At(ig))) continue;
        if(o->InheritsFrom("TH1")){
          h = dynamic_cast<TH1*>(o);
          h->Draw(Form("%ssame", opt));
        } else if(o->InheritsFrom("TGraph")){
          g = dynamic_cast<TGraph*>(o);
          g->Draw(opt);
        }
      }
      c->SaveAs(Form("%s_fig%d.gif", task->GetName(), ipic));
      delete c;
    }
    delete task;
    delete ctask;
  }
  delete pyshell;
}

<|endoftext|>


<commit_before>/**
 * Copyright © 2012, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is 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.
 */

/**
 * @file tgHillyGround.cpp
 * @brief Contains the implementation of class tgHillyGround
 * @author Steven Lessard
 * $Id$
 */

//This Module
#include "tgHillyGround.h"

//Bullet Physics
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btDefaultMotionState.h"
#include "LinearMath/btTransform.h"

// The C++ Standard Library
#include <cassert>
#include <iostream> //For debugging

tgHillyGround::Config::Config(btVector3 eulerAngles,
        btScalar friction,
        btScalar restitution,
        btVector3 size,
        btVector3 origin,
        size_t nx,
        size_t ny,
        double margin,
        double triangleSize,
        double waveHeight,
        double offset) :
    m_eulerAngles(eulerAngles),
    m_friction(friction),
    m_restitution(restitution),
    m_size(size),
    m_origin(origin),
    m_nx(nx),
    m_ny(ny),
    m_margin(margin),
    m_triangleSize(triangleSize),
    m_waveHeight(waveHeight),
    m_offset(offset)
{
    assert((m_friction >= 0.0) && (m_friction <= 1.0));
    assert((m_restitution >= 0.0) && (m_restitution <= 1.0));
    assert((m_size[0] >= 0.0) && (m_size[1] >= 0.0) && (m_size[2] >= 0.0));
    assert(m_nx > 0);
    assert(m_ny > 0);
    assert(m_margin >= 0.0);
    assert(m_triangleSize >= 0.0);
    assert(m_waveHeight >= 0.0);
    assert(m_offset >= 0.0);
}

tgHillyGround::tgHillyGround() :
    m_config(Config())
{
    // @todo make constructor aux to avoid repeated code
    pGroundShape = hillyCollisionShape();
}

tgHillyGround::tgHillyGround(const tgHillyGround::Config& config) :
    m_config(config)
{
    pGroundShape = hillyCollisionShape();
}

btRigidBody* tgHillyGround::getGroundRigidBody() const
{
    const btScalar mass = 0.0;

    btTransform groundTransform;
    groundTransform.setIdentity();
    groundTransform.setOrigin(m_config.m_origin);

    btQuaternion orientation;
    orientation.setEuler(m_config.m_eulerAngles[0], // Yaw
                         m_config.m_eulerAngles[1], // Pitch
                         m_config.m_eulerAngles[2]); // Roll
    groundTransform.setRotation(orientation);

    // Using motionstate is recommended
    // It provides interpolation capabilities, and only synchronizes 'active' objects
    btDefaultMotionState* const pMotionState =
        new btDefaultMotionState(groundTransform);

    const btVector3 localInertia(0, 0, 0);

    btRigidBody::btRigidBodyConstructionInfo const rbInfo(mass, pMotionState, pGroundShape, localInertia);

    btRigidBody* const pGroundBody = new btRigidBody(rbInfo);

    assert(pGroundBody);
    return pGroundBody;
}

btCollisionShape* tgHillyGround::hillyCollisionShape() {
    btCollisionShape * pShape = 0;
    // The number of vertices in the mesh
    // Hill Paramenters: Subject to Change
    const size_t vertexCount = m_config.m_nx * m_config.m_ny;
    std::cout << "vertexCount: " << vertexCount << std::endl;

    std::cout << "In hillyCollisionShape()" << std::endl;
    if (vertexCount > 0) {
        // The number of triangles in the mesh
        const size_t triangleCount = 2 * (m_config.m_nx - 1) * (m_config.m_ny - 1);
        std::cout << "triangleCount: " << triangleCount << std::endl;

        // A flattened array of all vertices in the mesh
        btVector3 * const vertices = new btVector3[vertexCount];

        // Supplied by the derived class
        setVertices(vertices);
        // A flattened array of indices for each corner of each triangle
        int *indices = new int[triangleCount * 3];

        // Supplied by the derived class
        setIndices(indices);

        // Create the mesh object
        btTriangleIndexVertexArray* const pMesh =
            createMesh(triangleCount, indices, vertexCount, vertices);

        // Create the shape object
        pShape = createShape(pMesh);

        // Set the margin
        pShape->setMargin(m_config.m_margin);
        // DO NOT deallocate vertices, indices or pMesh! The shape owns them.
    }

    assert(pShape);
    return pShape;
}

btTriangleIndexVertexArray *tgHillyGround::createMesh(size_t triangleCount, int indices[], size_t vertexCount, btVector3 vertices[]) {
    const int vertexStride = sizeof(btVector3);
    const int indexStride = 3 * sizeof(int);

    btTriangleIndexVertexArray* const pMesh =
        new btTriangleIndexVertexArray(triangleCount,
                indices,
                indexStride,
                vertexCount,
                (btScalar*) &vertices[0].x(),
                vertexStride);
    return pMesh;
}

btCollisionShape *tgHillyGround::createShape(btTriangleIndexVertexArray *pMesh) {
    const bool useQuantizedAabbCompression = true;
    btCollisionShape *const pShape =
        new btBvhTriangleMeshShape(pMesh, useQuantizedAabbCompression);
    return pShape;
}

void tgHillyGround::setVertices(btVector3 vertices[]) {
    for (size_t i = 0; i < m_config.m_nx; i++)
    {
        for (size_t j = 0; j < m_config.m_ny; j++)
        {
            const btScalar x = (i - (m_config.m_nx * 0.5)) * m_config.m_triangleSize;
            const btScalar y = (m_config.m_waveHeight * sinf((float)i) * cosf((float)j) +
                    m_config.m_offset);
            const btScalar z = (j - (m_config.m_ny * 0.5)) * m_config.m_triangleSize;
            vertices[i + (j * m_config.m_nx)].setValue(x, y, z);
        }
    }
}

void tgHillyGround::setIndices(int indices[]) {
    int index = 0;
    for (int i = 0; i < m_config.m_nx - 1; i++)
    {
        for (int j = 0; j < m_config.m_ny - 1; j++)
        {
            indices[index++] = (j       * m_config.m_nx) + i;
            indices[index++] = (j       * m_config.m_nx) + i + 1;
            indices[index++] = ((j + 1) * m_config.m_nx) + i + 1;

            indices[index++] = (j       * m_config.m_nx) + i;
            indices[index++] = ((j + 1) * m_config.m_nx) + i + 1;
            indices[index++] = ((j + 1) * m_config.m_nx) + i;
        }
    }
}

<commit_msg>Removed debugging print statements<commit_after>/**
 * Copyright © 2012, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is 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.
 */

/**
 * @file tgHillyGround.cpp
 * @brief Contains the implementation of class tgHillyGround
 * @author Steven Lessard
 * $Id$
 */

//This Module
#include "tgHillyGround.h"

//Bullet Physics
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btDefaultMotionState.h"
#include "LinearMath/btTransform.h"

// The C++ Standard Library
#include <cassert>

tgHillyGround::Config::Config(btVector3 eulerAngles,
        btScalar friction,
        btScalar restitution,
        btVector3 size,
        btVector3 origin,
        size_t nx,
        size_t ny,
        double margin,
        double triangleSize,
        double waveHeight,
        double offset) :
    m_eulerAngles(eulerAngles),
    m_friction(friction),
    m_restitution(restitution),
    m_size(size),
    m_origin(origin),
    m_nx(nx),
    m_ny(ny),
    m_margin(margin),
    m_triangleSize(triangleSize),
    m_waveHeight(waveHeight),
    m_offset(offset)
{
    assert((m_friction >= 0.0) && (m_friction <= 1.0));
    assert((m_restitution >= 0.0) && (m_restitution <= 1.0));
    assert((m_size[0] >= 0.0) && (m_size[1] >= 0.0) && (m_size[2] >= 0.0));
    assert(m_nx > 0);
    assert(m_ny > 0);
    assert(m_margin >= 0.0);
    assert(m_triangleSize >= 0.0);
    assert(m_waveHeight >= 0.0);
    assert(m_offset >= 0.0);
}

tgHillyGround::tgHillyGround() :
    m_config(Config())
{
    // @todo make constructor aux to avoid repeated code
    pGroundShape = hillyCollisionShape();
}

tgHillyGround::tgHillyGround(const tgHillyGround::Config& config) :
    m_config(config)
{
    pGroundShape = hillyCollisionShape();
}

btRigidBody* tgHillyGround::getGroundRigidBody() const
{
    const btScalar mass = 0.0;

    btTransform groundTransform;
    groundTransform.setIdentity();
    groundTransform.setOrigin(m_config.m_origin);

    btQuaternion orientation;
    orientation.setEuler(m_config.m_eulerAngles[0], // Yaw
                         m_config.m_eulerAngles[1], // Pitch
                         m_config.m_eulerAngles[2]); // Roll
    groundTransform.setRotation(orientation);

    // Using motionstate is recommended
    // It provides interpolation capabilities, and only synchronizes 'active' objects
    btDefaultMotionState* const pMotionState =
        new btDefaultMotionState(groundTransform);

    const btVector3 localInertia(0, 0, 0);

    btRigidBody::btRigidBodyConstructionInfo const rbInfo(mass, pMotionState, pGroundShape, localInertia);

    btRigidBody* const pGroundBody = new btRigidBody(rbInfo);

    assert(pGroundBody);
    return pGroundBody;
}

btCollisionShape* tgHillyGround::hillyCollisionShape() {
    btCollisionShape * pShape = 0;
    // The number of vertices in the mesh
    // Hill Paramenters: Subject to Change
    const size_t vertexCount = m_config.m_nx * m_config.m_ny;

    if (vertexCount > 0) {
        // The number of triangles in the mesh
        const size_t triangleCount = 2 * (m_config.m_nx - 1) * (m_config.m_ny - 1);

        // A flattened array of all vertices in the mesh
        btVector3 * const vertices = new btVector3[vertexCount];

        // Supplied by the derived class
        setVertices(vertices);
        // A flattened array of indices for each corner of each triangle
        int *indices = new int[triangleCount * 3];

        // Supplied by the derived class
        setIndices(indices);

        // Create the mesh object
        btTriangleIndexVertexArray* const pMesh =
            createMesh(triangleCount, indices, vertexCount, vertices);

        // Create the shape object
        pShape = createShape(pMesh);

        // Set the margin
        pShape->setMargin(m_config.m_margin);
        // DO NOT deallocate vertices, indices or pMesh! The shape owns them.
    }

    assert(pShape);
    return pShape;
}

btTriangleIndexVertexArray *tgHillyGround::createMesh(size_t triangleCount, int indices[], size_t vertexCount, btVector3 vertices[]) {
    const int vertexStride = sizeof(btVector3);
    const int indexStride = 3 * sizeof(int);

    btTriangleIndexVertexArray* const pMesh =
        new btTriangleIndexVertexArray(triangleCount,
                indices,
                indexStride,
                vertexCount,
                (btScalar*) &vertices[0].x(),
                vertexStride);
    return pMesh;
}

btCollisionShape *tgHillyGround::createShape(btTriangleIndexVertexArray *pMesh) {
    const bool useQuantizedAabbCompression = true;
    btCollisionShape *const pShape =
        new btBvhTriangleMeshShape(pMesh, useQuantizedAabbCompression);
    return pShape;
}

void tgHillyGround::setVertices(btVector3 vertices[]) {
    for (size_t i = 0; i < m_config.m_nx; i++)
    {
        for (size_t j = 0; j < m_config.m_ny; j++)
        {
            const btScalar x = (i - (m_config.m_nx * 0.5)) * m_config.m_triangleSize;
            const btScalar y = (m_config.m_waveHeight * sinf((float)i) * cosf((float)j) +
                    m_config.m_offset);
            const btScalar z = (j - (m_config.m_ny * 0.5)) * m_config.m_triangleSize;
            vertices[i + (j * m_config.m_nx)].setValue(x, y, z);
        }
    }
}

void tgHillyGround::setIndices(int indices[]) {
    int index = 0;
    for (int i = 0; i < m_config.m_nx - 1; i++)
    {
        for (int j = 0; j < m_config.m_ny - 1; j++)
        {
            indices[index++] = (j       * m_config.m_nx) + i;
            indices[index++] = (j       * m_config.m_nx) + i + 1;
            indices[index++] = ((j + 1) * m_config.m_nx) + i + 1;

            indices[index++] = (j       * m_config.m_nx) + i;
            indices[index++] = ((j + 1) * m_config.m_nx) + i + 1;
            indices[index++] = ((j + 1) * m_config.m_nx) + i;
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>these 9 scripts are in icu >= 4.8, but not in 4.6.1<commit_after><|endoftext|>


<commit_before>//
//  Electron.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/01/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Electron.hpp"

#include <algorithm>

using namespace Electron;

Machine::Machine()
{
	setup6502();
}

Machine::~Machine()
{
}

unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
	printf("%04x\n", address);

	if(address < 32768)
	{
		if(isReadOperation(operation))
		{
			*value = ram[address];
		}
		else
		{
			ram[address] = *value;
		}
	}
	else
	{
		if(address > 49152)
		{
			if(isReadOperation(operation)) *value = os[address - 49152];
		}
		else
		{
			if(isReadOperation(operation)) *value = basic[address - 32768];
		}
	}

	return 1;
}

void Machine::set_rom(ROMSlot slot, size_t length, const uint8_t *data)
{
	uint8_t *target = nullptr;
	switch(slot)
	{
		case ROMTypeBASIC:	target = basic;	break;
		case ROMTypeOS:		target = os;	break;
	}

	memcpy(target, data, std::min((size_t)16384, length));
}
<commit_msg>This is the bare minimum to prove that the ROM is trying properly to boot.<commit_after>//
//  Electron.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/01/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Electron.hpp"

#include <algorithm>

using namespace Electron;

Machine::Machine()
{
	setup6502();
}

Machine::~Machine()
{
}

unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
	if(address < 32768)
	{
		if(isReadOperation(operation))
		{
			*value = ram[address];
		}
		else
		{
			ram[address] = *value;
		}
	}
	else
	{
		if(address > 49152)
		{
			if((address & 0xff00) == 0xfe00)
			{
				printf("%c: %02x: ", isReadOperation(operation) ? 'r' : 'w', *value);

				switch(address&0xf)
				{
					case 0x0:
						printf("Interrupt status or control\n");
					break;
					case 0x1:
					break;
					case 0x2:
					case 0x3:
						printf("Screen start address\n");
					break;
					case 0x4:
						printf("Cassette\n");
					break;
					case 0x5:
						printf("Interrupt clear and paging\n");
					break;
					case 0x6:
						printf("Counter\n");
					break;
					case 0x7:
						printf("Misc. control\n");
					break;
					default:
						printf("Palette\n");
					break;
				}
			}
			else
			{
				if(isReadOperation(operation))
					*value = os[address - 49152];
			}
		}
		else
		{
			if(isReadOperation(operation)) *value = basic[address - 32768];
		}
	}

	return 1;
}

void Machine::set_rom(ROMSlot slot, size_t length, const uint8_t *data)
{
	uint8_t *target = nullptr;
	switch(slot)
	{
		case ROMTypeBASIC:	target = basic;	break;
		case ROMTypeOS:		target = os;	break;
	}

	memcpy(target, data, std::min((size_t)16384, length));
}
<|endoftext|>


<commit_before>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * 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 Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * << detailed description >>
 *
 * @file ParticleTypeRegistry.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 29.03.17
 * @copyright GNU Lesser General Public License v3.0
 */

#include <readdy/model/ParticleTypeRegistry.h>
#include <readdy/model/Utils.h>

namespace readdy {
namespace model {

ParticleTypeInfo::ParticleTypeInfo(const std::string &name, const scalar diffusionConstant,
                                   const particle_flavor flavor, const Particle::type_type typeId)
        : name(name), diffusionConstant(diffusionConstant), flavor(flavor), typeId(typeId) {}

void ParticleTypeRegistry::add(const std::string &name, const scalar diffusionConst, const particle_flavor flavor) {
    util::validateTypeName(name);
    {
        if(diffusionConst < 0) {
            throw std::invalid_argument("The diffusion constant must not be negative");
        }
        // check if name already exists
        for(const auto &e : particle_info_) {
            if(e.second.name == name) {
                throw std::invalid_argument(fmt::format("A particle type with name {} already exists.", name));
            }
        }
    }
    particle_type_type t_id = type_counter_++;
    type_mapping_.emplace(name, t_id);
    particle_info_.emplace(std::make_pair(t_id, ParticleTypeInfo{name, diffusionConst, flavor, t_id}));
    n_types_++;
}

std::string ParticleTypeRegistry::describe() const {
    namespace rus = readdy::util::str;
    std::string description;
    description += fmt::format(" - particle types:{}", rus::newline);
    auto flavorName = [](auto flavor) -> std::string {
        switch (flavor) {
            case particleflavor::NORMAL: {
                return "";
            }
            case particleflavor::TOPOLOGY: {
                return "Topology";
            }
            case particleflavor::MEMBRANE: {
                return "Membrane";
            }
            default: {
                throw std::logic_error("encountered a particle flavor that was neither of NORMAL, TOPOLOGY, MEMBRANE.");
            }
        }
    };
    for (const auto &entry : particle_info_) {
        description += fmt::format("     * {} particle type \"{}\" with D={}{}", entry.second.name,
                                   flavorName(entry.second.flavor), entry.second.diffusionConstant, rus::newline);
    }
    return description;
}

}
}
<commit_msg>prettified particle type registry output<commit_after>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * 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 Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * << detailed description >>
 *
 * @file ParticleTypeRegistry.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 29.03.17
 * @copyright GNU Lesser General Public License v3.0
 */

#include <readdy/model/ParticleTypeRegistry.h>
#include <readdy/model/Utils.h>

namespace readdy {
namespace model {

ParticleTypeInfo::ParticleTypeInfo(const std::string &name, const scalar diffusionConstant,
                                   const particle_flavor flavor, const Particle::type_type typeId)
        : name(name), diffusionConstant(diffusionConstant), flavor(flavor), typeId(typeId) {}

void ParticleTypeRegistry::add(const std::string &name, const scalar diffusionConst, const particle_flavor flavor) {
    util::validateTypeName(name);
    {
        if(diffusionConst < 0) {
            throw std::invalid_argument("The diffusion constant must not be negative");
        }
        // check if name already exists
        for(const auto &e : particle_info_) {
            if(e.second.name == name) {
                throw std::invalid_argument(fmt::format("A particle type with name {} already exists.", name));
            }
        }
    }
    particle_type_type t_id = type_counter_++;
    type_mapping_.emplace(name, t_id);
    particle_info_.emplace(std::make_pair(t_id, ParticleTypeInfo{name, diffusionConst, flavor, t_id}));
    n_types_++;
}

std::string ParticleTypeRegistry::describe() const {
    namespace rus = readdy::util::str;
    std::string description;
    description += fmt::format(" - particle types:{}", rus::newline);
    auto flavorName = [](auto flavor) -> std::string {
        switch (flavor) {
            case particleflavor::NORMAL: {
                return "";
            }
            case particleflavor::TOPOLOGY: {
                return "Topology";
            }
            case particleflavor::MEMBRANE: {
                return "Membrane";
            }
            default: {
                throw std::logic_error("encountered a particle flavor that was neither of NORMAL, TOPOLOGY, MEMBRANE.");
            }
        }
    };
    for (const auto &entry : particle_info_) {
        description += fmt::format("     * {} particle type \"{}\" with D={}{}", flavorName(entry.second.flavor),
                                   entry.second.name, entry.second.diffusionConstant, rus::newline);
    }
    return description;
}

}
}
<|endoftext|>


<commit_before>#include <Cosa/Alarm.hh>
#include <Cosa/IOBuffer.hh>
#include <Cosa/RTT.hh>
#include <Cosa/Trace.hh>
#include <Cosa/UART.hh>
#include <Cosa/Soft/UART.hh>
#include <Cosa/Watchdog.hh>
#include <stdint-gcc.h>
#include "initializer_list"

static const uint16_t WATCHDOG_PERIOD = 16;

static const uint32_t SEND_PERIOD_SECS = 60;
static const uint32_t CAM_REPLY_TIMEOUT_SECS = 2;

static const size_t CAM_RX_BUFFER_MAX = 64;
static const size_t CAM_TX_BUFFER_MAX = 16;

static const size_t CAM_RECV_BUFFER_SIZE = 16;
static const size_t CAM_PICT_BUFFER_SIZE = 32;

static const Board::DigitalPin CAM_TX_PIN = Board::D2;
static const Board::InterruptPin CAM_RX_PIN = Board::PCI3;

static uint8_t HI(uint16_t in)
{
	return (in >> 8);
}

static uint8_t LO(uint16_t in)
{
	return (in & 0xFF);
}

static uint16_t SWAP(uint16_t in)
{
	return (LO(in) << 8) | HI(in);
}

class Camera
{
public:
	enum class Resolution
	{
		RES_640x480,
		RES_320x240,
		RES_160x120,
	};

	enum class BaudRate
	{
		BAUD_9600,
		BAUD_19200,
		BAUD_38400,
		BAUD_57600,
		BAUD_115200
	};

	Camera(IOStream& cam, uint32_t timeout)
		:_timeout(timeout * 1000), _cam(cam)
	{
		delay(3000);
		_trace(true);
	}

	void reset()
	{
//		trace << "reset" << endl;
		_send({0x56, 0x00, 0x26, 0x00});
		_receive({0x76, 0x00, 0x26, 0x00, 0x00});
		//FIXME reset generates the power on init string: we should wait until it is received then!
		delay(3000);
//		_trace(true);
	}

	//TODO method to take picture and notify callback for content
	template<typename CB>
	void take_picture(CB& callback)
	{
		take_picture();
		int32_t size = picture_size();
		uint16_t address = 0;
		while (size > 0)
		{
			//TODO buffer should be an argument to the function (more customizable)
			uint8_t buffer[CAM_PICT_BUFFER_SIZE];
			picture_content(address, CAM_PICT_BUFFER_SIZE, buffer);
			address += CAM_PICT_BUFFER_SIZE;
			size -= CAM_PICT_BUFFER_SIZE;
			callback(buffer, CAM_PICT_BUFFER_SIZE, (size > 0));
		}
		stop_picture();
	}

	void take_picture()
	{
//		trace << "take_picture" << endl;
		_send({0x56, 0x00, 0x36, 0x01, 0x00});
		_receive({0x76, 0x00, 0x36, 0x00, 0x00});
	}

	void stop_picture()
	{
//		trace << "stop_picture" << endl;
		_send({0x56, 0x00, 0x36, 0x01, 0x03});
		_receive({0x76, 0x00, 0x36, 0x00, 0x00});
	}

	uint16_t picture_size()
	{
//		trace << "get picture_size" << endl;
		_send({0x56, 0x00, 0x34, 0x01, 0x00});
		uint16_t size;
		if (	_receive({0x76, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00})
			&&	_receive((uint8_t*)(&size), sizeof(size)))
			return SWAP(size);
		return 0;
	}

	void picture_content(uint16_t address, uint16_t size, uint8_t* buffer)
	{
		_send({
			0x56, 0x00, 0x32, 0x0C, 0x00, 0x0A,
			0x00, 0x00, HI(address), LO(address),
			0x00, 0x00, HI(size), LO(size),
			0x00, 0x0A});
		_receive({0x76, 0x00, 0x32, 0x00, 0x00}) &&
		_receive(buffer, size) &&
		_receive({0x76, 0x00, 0x32, 0x00, 0x00});
	}

	void compression(uint8_t ratio)
	{
		_send({0x56, 0x00, 0x31, 0x05, 0x01, 0x01, 0x12, 0x04, ratio});
		_receive({0x76, 0x00, 0x31, 0x00, 0x00});
	}

	void picture_resolution(Resolution resolution)
	{
		uint8_t code;
		switch (resolution)
		{
			case Resolution::RES_160x120: code = 0x22; break;
			case Resolution::RES_320x240: code = 0x11; break;
			case Resolution::RES_640x480: code = 0x00; break;
		}
		_send({0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, code});
		_receive({0x76, 0x00, 0x31, 0x00, 0x00});
	}

	void enter_power_save()
	{
//		trace << "enter_power_save" << endl;
		_send({0x56, 0x00, 0x3E, 0x03, 0x00, 0x01, 0x01});
		_receive({0x76, 0x00, 0x3E, 0x00, 0x00});
	}

	void exit_power_save()
	{
//		trace << "exit_power_save" << endl;
		_send({0x56, 0x00, 0x3E, 0x03, 0x00, 0x01, 0x00});
		_receive({0x76, 0x00, 0x3E, 0x00, 0x00});
	}

	void baud_rate(BaudRate baud)
	{
		uint16_t code;
		switch (baud)
		{
			case BaudRate::BAUD_9600: code = 0xAEC8; break;
			case BaudRate::BAUD_19200: code = 0x56E4; break;
			case BaudRate::BAUD_38400: code = 0x2AF2; break;
			case BaudRate::BAUD_57600: code = 0x1C4C; break;
			case BaudRate::BAUD_115200: code = 0x0DA6; break;
		}
		_send({
			0x56, 0x00, 0x24, 0x03, 0x01,
			HI(code), LO(code)});
		_receive({0x76, 0x00, 0x24, 0x00, 0x00});
	}

private:
	void _send(std::initializer_list<uint8_t> content)
	{
		for (auto i : content)
			_cam.device()->putchar(i);
		_cam.device()->flush();
	}

	bool _receive(std::initializer_list<uint8_t> expected)
	{
		uint8_t content[CAM_RECV_BUFFER_SIZE];
		if (_receive(content, expected.size()))
		{
			uint8_t* compare = content;
			for (auto i : expected)
			{
				if (*compare != i)
				{
					trace << "expected " << hex << i << ", actual " << *compare << endl;
					return false;
				}
				++compare;
			}
			return true;
		}
		return false;
	}

	bool _receive(uint8_t* content, uint8_t size)
	{
		// Wait until timeout or expected received
		uint32_t now = RTT::millis();
		uint8_t count = 0;
		do
		{
			while (_cam.device()->available())
			{
				*content++ = _cam.device()->getchar();
				if (++count == size)
					return true;
			}
			delay(1);
		}
		while (RTT::since(now) < _timeout);
		trace << "receive timeout. Expected size " << size << ", actual " << count << endl;
		return false;
	}

	void _trace(bool ascii_response = false)
	{
		trace << "<< ";
		while (_cam.device()->available())
		{
			int c = _cam.device()->getchar();
			if (ascii_response)
				trace << (char) c;
			else
				trace << hex << c << ' ';
		}
		trace << endl;
	}

	const uint32_t _timeout;
	IOStream& _cam;
};

class CamHandler: public Alarm
{
public:
	CamHandler(Camera& cam, ::Clock* clock, uint32_t period)
		:Alarm(clock, period), _cam(cam), _led(Board::LED, 0)
	{
		cam.reset();
		cam.compression(0x36);
		cam.picture_resolution(Camera::Resolution::RES_640x480);
		cam.reset();
	}

	virtual void run()
	{
		_led.toggle();
		_cam.exit_power_save();
		_cam.take_picture();
		int32_t size = _cam.picture_size();
		trace << "picture size = " << size << endl;
		uint16_t address = 0;
		while (size > 0)
		{
			uint8_t buffer[CAM_PICT_BUFFER_SIZE];
			_cam.picture_content(address, CAM_PICT_BUFFER_SIZE, buffer);
			address += CAM_PICT_BUFFER_SIZE;
			size -= CAM_PICT_BUFFER_SIZE;
		}
		_cam.stop_picture();
		_cam.enter_power_save();
		// This delay seems necessary to avoid garbage sent to trace... (1ms is not long enough)
		delay(5);
	}

private:
	Camera& _cam;
	OutputPin _led;
};

int main()
{
	// Disable analog comparator
	ACSR = _BV(ACD);
	// Disable all modules but ADC (required for bandgap reading)
	Power::all_disable();
	Power::adc_enable();
	// Allow interrupts from here
	sei();

	// Start watchdog and alarms
	Watchdog::begin(WATCHDOG_PERIOD);
//	Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA

	// Start using RTT
	RTT::begin();

	uart.begin(115200);
	trace.begin(&uart, PSTR("CamCheck: started"));

	IOBuffer<CAM_RX_BUFFER_MAX> ibuf;

	Soft::UART uartCam{CAM_TX_PIN, CAM_RX_PIN, &ibuf};
	uartCam.begin(38400);
	IOStream streamCam{&uartCam};
	Camera camera{streamCam, CAM_REPLY_TIMEOUT_SECS};

	//TODO improve baud rate here
//	camera.baud_rate(Camera::BaudRate::BAUD_115200);
//	uartCam.end();
//	uartCam.begin(115200);

	// Needed for Alarms to work properly
	Watchdog::Clock clock;
	CamHandler handler(camera, &clock, SEND_PERIOD_SECS);

	// Stop using RTT and restore Watchdog
	RTT::end();
	::delay = Watchdog::delay;

	handler.start();

	while (true)
	{
		Watchdog::await();

		// If there is at least one event to be dispatched, then change sleep mode, start RTT and NRF
		if (Event::queue.available())
		{
			// Only this mode works when using serial output and full-time RTC
			Power::set(SLEEP_MODE_IDLE);			// 15mA
			// Start using RTT
			RTT::begin();

			Event event;
			while (Event::queue.dequeue(&event))
				event.dispatch();

			// Stop using RTT and restore Watchdog
			RTT::end();
			::delay = Watchdog::delay;
			// Lowest consumption mode
			Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA
		}
	}
}
<commit_msg>Improve project prototype for LinkSprite Camera.<commit_after>#include <Cosa/Alarm.hh>
#include <Cosa/IOBuffer.hh>
#include <Cosa/RTT.hh>
#include <Cosa/Trace.hh>
#include <Cosa/UART.hh>
#include <Cosa/Soft/UART.hh>
#include <Cosa/Watchdog.hh>
#include <stdint-gcc.h>
#include "initializer_list"

static const uint16_t WATCHDOG_PERIOD = 16;

static const uint32_t SEND_PERIOD_SECS = 60;
static const uint32_t CAM_REPLY_TIMEOUT_SECS = 2;

static const size_t CAM_RX_BUFFER_MAX = 64;
static const size_t CAM_TX_BUFFER_MAX = 16;

static const size_t CAM_RECV_BUFFER_SIZE = 16;
static const size_t CAM_PICT_BUFFER_SIZE = 64;
//static const size_t CAM_PICT_BUFFER_SIZE = 32;

static const Board::DigitalPin CAM_TX_PIN = Board::D2;
static const Board::InterruptPin CAM_RX_PIN = Board::PCI3;

static uint8_t HI(uint16_t in)
{
	return (in >> 8);
}

static uint8_t LO(uint16_t in)
{
	return (in & 0xFF);
}

static uint16_t SWAP(uint16_t in)
{
	return (LO(in) << 8) | HI(in);
}

class Camera
{
public:
	enum class Resolution
	{
		RES_640x480,
		RES_320x240,
		RES_160x120
	};

	enum class BaudRate
	{
		BAUD_9600,
		BAUD_19200,
		BAUD_38400,
		BAUD_57600,
		BAUD_115200
	};

	Camera(IOStream& cam, uint32_t timeout)
		:_timeout(timeout * 1000), _cam(cam)
	{
		reset();
	}

	void reset()
	{
		trace << "reset" << endl;
		_send({0x56, 0x00, 0x26, 0x00});
		_receive({0x76, 0x00, 0x26, 0x00, 0x00});
		// Reset generates the power on init string: wait until it is received
//		_wait_init();
		delay(3000);
		_cam.device()->empty();
//		_trace(true);
	}

	//TODO method to take picture and notify callback for content
	template<typename CB>
	void take_picture(CB& callback)
	{
		take_picture();
		int32_t size = picture_size();
		uint16_t address = 0;
		while (size > 0)
		{
			//TODO buffer should be an argument to the function (more customizable)
			uint8_t buffer[CAM_PICT_BUFFER_SIZE];
			picture_content(address, CAM_PICT_BUFFER_SIZE, buffer);
			address += CAM_PICT_BUFFER_SIZE;
			size -= CAM_PICT_BUFFER_SIZE;
			callback(buffer, CAM_PICT_BUFFER_SIZE, (size > 0));
		}
		stop_picture();
	}

	void take_picture()
	{
//		trace << "take_picture" << endl;
		_send({0x56, 0x00, 0x36, 0x01, 0x00});
		_receive({0x76, 0x00, 0x36, 0x00, 0x00});
	}

	void stop_picture()
	{
//		trace << "stop_picture" << endl;
		_send({0x56, 0x00, 0x36, 0x01, 0x03});
		_receive({0x76, 0x00, 0x36, 0x00, 0x00});
	}

	uint16_t picture_size()
	{
//		trace << "get picture_size" << endl;
		_send({0x56, 0x00, 0x34, 0x01, 0x00});
		uint16_t size;
		if (	_receive({0x76, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00})
			&&	_receive((uint8_t*)(&size), sizeof(size)))
			return SWAP(size);
		return 0;
	}

	void picture_content(uint16_t address, uint16_t size, uint8_t* buffer)
	{
		_send({
			0x56, 0x00, 0x32, 0x0C, 0x00, 0x0A,
			0x00, 0x00, HI(address), LO(address),
			0x00, 0x00, HI(size), LO(size),
			0x00, 0x0A});
		_receive({0x76, 0x00, 0x32, 0x00, 0x00}) &&
		_receive(buffer, size) &&
		_receive({0x76, 0x00, 0x32, 0x00, 0x00});
	}

	void compression(uint8_t ratio)
	{
//		trace << "compression" << endl;
		_send({0x56, 0x00, 0x31, 0x05, 0x01, 0x01, 0x12, 0x04, ratio});
		_receive({0x76, 0x00, 0x31, 0x00, 0x00});
	}

	void picture_resolution(Resolution resolution)
	{
//		trace << "picture_resolution" << endl;
		uint8_t code;
		switch (resolution)
		{
			case Resolution::RES_160x120: code = 0x22; break;
			case Resolution::RES_320x240: code = 0x11; break;
			case Resolution::RES_640x480: code = 0x00; break;
		}
		_send({0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, code});
		_receive({0x76, 0x00, 0x31, 0x00, 0x00});
	}

	void enter_power_save()
	{
//		trace << "enter_power_save" << endl;
		_send({0x56, 0x00, 0x3E, 0x03, 0x00, 0x01, 0x01});
		_receive({0x76, 0x00, 0x3E, 0x00, 0x00});
	}

	void exit_power_save()
	{
//		trace << "exit_power_save" << endl;
		_send({0x56, 0x00, 0x3E, 0x03, 0x00, 0x01, 0x00});
		_receive({0x76, 0x00, 0x3E, 0x00, 0x00});
	}

	void baud_rate(BaudRate baud)
	{
//		trace << "baud_rate" << endl;
		uint16_t code;
		switch (baud)
		{
			case BaudRate::BAUD_9600: code = 0xAEC8; break;
			case BaudRate::BAUD_19200: code = 0x56E4; break;
			case BaudRate::BAUD_38400: code = 0x2AF2; break;
			case BaudRate::BAUD_57600: code = 0x1C4C; break;
			case BaudRate::BAUD_115200: code = 0x0DA6; break;
		}
		_send({
			0x56, 0x00, 0x24, 0x03, 0x01,
			HI(code), LO(code)});
		_receive({0x76, 0x00, 0x24, 0x00, 0x00});
	}

private:
	bool _wait_init()
	{
		// Wait until timeout or expected received
		uint32_t now = RTT::millis();
		do
		{
			char buffer[80];
			if (	_cam.readline(buffer, sizeof(buffer), false)
				&&	strstr(buffer, "Init end"))
			{
				_cam.device()->empty();
				return true;
			}
			delay(1);
		}
		while (RTT::since(now) < 3000);
		trace << "wait init timeout." << endl;
		_cam.device()->empty();
		return false;
	}

	void _send(std::initializer_list<uint8_t> content)
	{
		for (auto i : content)
			_cam.device()->putchar(i);
		_cam.device()->flush();
	}

	bool _receive(std::initializer_list<uint8_t> expected)
	{
		uint8_t content[CAM_RECV_BUFFER_SIZE];
		if (_receive(content, expected.size()))
		{
			uint8_t* compare = content;
			for (auto i : expected)
			{
				if (*compare != i)
				{
					trace << "expected " << hex << i << ", actual " << hex << *compare << endl;
					return false;
				}
				++compare;
			}
			return true;
		}
		return false;
	}

	bool _receive(uint8_t* content, uint8_t size)
	{
		// Wait until timeout or expected received
		uint32_t now = RTT::millis();
		uint8_t count = 0;
		do
		{
			while (_cam.device()->available())
			{
				*content++ = _cam.device()->getchar();
				if (++count == size)
					return true;
			}
			delay(1);
		}
		while (RTT::since(now) < _timeout);
		trace << "receive timeout. Expected size " << size << ", actual " << count << endl;
		return false;
	}

	void _trace(bool ascii_response = false)
	{
		trace << "<< ";
		while (_cam.device()->available())
		{
			int c = _cam.device()->getchar();
			if (ascii_response)
				trace << (char) c;
			else
				trace << hex << c << ' ';
		}
		trace << endl;
	}

	const uint32_t _timeout;
	IOStream& _cam;
};

class CamHandler: public Alarm
{
public:
	CamHandler(Camera& cam, ::Clock* clock, uint32_t period)
		:Alarm(clock, period), _cam(cam), _led(Board::LED, 0)
	{
		cam.compression(0x36);
		cam.picture_resolution(Camera::Resolution::RES_640x480);
		cam.reset();
	}

	virtual void run()
	{
		_led.toggle();
		_cam.exit_power_save();
		_cam.take_picture();
		int32_t size = _cam.picture_size();
//		trace << "picture size = " << size << endl;
		uint16_t address = 0;
		while (size > 0)
		{
			uint8_t buffer[CAM_PICT_BUFFER_SIZE];
			_cam.picture_content(address, CAM_PICT_BUFFER_SIZE, buffer);
			address += CAM_PICT_BUFFER_SIZE;
			size -= CAM_PICT_BUFFER_SIZE;
			trace.device()->write(buffer, CAM_PICT_BUFFER_SIZE);
		}
		_cam.stop_picture();
		_cam.enter_power_save();
		// This delay seems necessary to avoid garbage sent to trace... (1ms is not long enough)
		delay(5);
	}

private:
	Camera& _cam;
	OutputPin _led;
};

int main()
{
	// Disable analog comparator
	ACSR = _BV(ACD);
	// Disable all modules but ADC (required for bandgap reading)
	Power::all_disable();
	Power::adc_enable();
	// Allow interrupts from here
	sei();

	// Start watchdog and alarms
	Watchdog::begin(WATCHDOG_PERIOD);
//	Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA

	// Start using RTT
	RTT::begin();

	uart.begin(115200);
	trace.begin(&uart, PSTR("CamCheck: started"));

	IOBuffer<CAM_RX_BUFFER_MAX> ibuf;

	Soft::UART uartCam{CAM_TX_PIN, CAM_RX_PIN, &ibuf};
	uartCam.begin(38400);
	IOStream streamCam{&uartCam};
	Camera camera{streamCam, CAM_REPLY_TIMEOUT_SECS};

	//TODO improve baud rate here
//	camera.baud_rate(Camera::BaudRate::BAUD_115200);
//	uartCam.end();
//	uartCam.begin(115200);

	// Needed for Alarms to work properly
	Watchdog::Clock clock;
	CamHandler handler(camera, &clock, SEND_PERIOD_SECS);

	// Stop using RTT and restore Watchdog
	RTT::end();
	::delay = Watchdog::delay;

	handler.start();

	while (true)
	{
		Watchdog::await();

		// If there is at least one event to be dispatched, then change sleep mode, start RTT and NRF
		if (Event::queue.available())
		{
			// Only this mode works when using serial output and full-time RTC
			Power::set(SLEEP_MODE_IDLE);			// 15mA
			// Start using RTT
			RTT::begin();

			Event event;
			while (Event::queue.dequeue(&event))
				event.dispatch();

			// Stop using RTT and restore Watchdog
			RTT::end();
			::delay = Watchdog::delay;
			// Lowest consumption mode
			Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA
		}
	}
}
<|endoftext|>


<commit_before>/*
 * The main source of the Beng proxy server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "direct.hxx"
#include "lb_instance.hxx"
#include "lb_check.hxx"
#include "lb_setup.hxx"
#include "lb_connection.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "stock/MapStock.hxx"
#include "failure.hxx"
#include "bulldog.hxx"
#include "balancer.hxx"
#include "pipe_stock.hxx"
#include "log_glue.hxx"
#include "lb_config.hxx"
#include "ssl/ssl_init.hxx"
#include "pool.hxx"
#include "thread_pool.hxx"
#include "fb_pool.hxx"
#include "capabilities.hxx"
#include "system/Isolate.hxx"
#include "system/SetupProcess.hxx"
#include "util/PrintException.hxx"
#include "util/Macros.hxx"

#include <daemon/log.h>

#include <systemd/sd-daemon.h>
#include <postgresql/libpq-fe.h>

#include <assert.h>
#include <unistd.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>

#ifdef __linux
#include <sys/prctl.h>

#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
#endif
#endif

static constexpr cap_value_t cap_keep_list[1] = {
    /* keep the NET_RAW capability to be able to to use the socket
       option IP_TRANSPARENT */
    CAP_NET_RAW,
};

void
LbInstance::ShutdownCallback()
{
    if (should_exit)
        return;

    should_exit = true;
    deinit_signals(this);
    thread_pool_stop();

    avahi_client.Close();

    compress_event.Cancel();

    deinit_all_controls(this);

    DisconnectCertCaches();

    while (!connections.empty())
        lb_connection_close(&connections.front());
    assert(n_tcp_connections == 0);

    deinit_all_listeners(this);

    thread_pool_join();

    monitors.Clear();

    pool_commit();

    if (tcp_balancer != nullptr)
        tcp_balancer_free(tcp_balancer);

    delete tcp_stock;

    if (balancer != nullptr)
        balancer_free(balancer);

    if (pipe_stock != nullptr)
        pipe_stock_free(pipe_stock);

    pool_commit();
}

void
LbInstance::ReloadEventCallback(int)
{
    unsigned n_ssl_sessions = FlushSSLSessionCache(LONG_MAX);
    daemon_log(3, "flushed %u SSL sessions\n", n_ssl_sessions);

    Compress();
}

void
init_signals(LbInstance *instance)
{
    instance->shutdown_listener.Enable();
    instance->sighup_event.Enable();
}

void
deinit_signals(LbInstance *instance)
{
    instance->shutdown_listener.Disable();
    instance->sighup_event.Disable();
}

int main(int argc, char **argv)
{
    const ScopeFbPoolInit fb_pool_init;
    LbInstance instance;

    /* configuration */

    LbConfig config;
    ParseCommandLine(instance.cmdline, config, argc, argv);

    try {
        LoadConfigFile(config,
                       instance.cmdline.config_path);
    } catch (const std::exception &e) {
        PrintException(e);
        return EXIT_FAILURE;
    }

    instance.config = &config;

    if (instance.cmdline.check) {
        int status = EXIT_SUCCESS;

        const ScopeSslGlobalInit ssl_init;

        try {
            lb_check(instance.event_loop, *instance.config);
        } catch (const std::exception &e) {
            PrintException(e);
            status = EXIT_FAILURE;
        }

        return status;
    }

    /* initialize */

    SetupProcess();

    const ScopeSslGlobalInit ssl_init;

    /* prevent libpq from initializing libssl & libcrypto again */
    PQinitOpenSSL(0, 0);

    direct_global_init();

    init_signals(&instance);

    try {
        init_all_controls(&instance);
        init_all_listeners(instance);
    } catch (const std::exception &e) {
        fprintf(stderr, "%s\n", e.what());
        return EXIT_FAILURE;
    }

    instance.balancer = balancer_new(instance.event_loop);
    instance.tcp_stock = tcp_stock_new(instance.event_loop,
                                       instance.cmdline.tcp_stock_limit);
    instance.tcp_balancer = tcp_balancer_new(*instance.tcp_stock,
                                             *instance.balancer);

    instance.pipe_stock = pipe_stock_new(instance.event_loop);

    failure_init();
    bulldog_init(instance.cmdline.bulldog_path);

    /* launch the access logger */

    log_global_init(config.access_logger.c_str(),
                    &instance.cmdline.logger_user);

    /* daemonize II */

    if (!instance.cmdline.user.IsEmpty())
        capabilities_pre_setuid();

    instance.cmdline.user.Apply();

    for (const auto &path : config.lua_files)
        instance.RunLuaFile(path.c_str());

    /* can't change to new (empty) rootfs if we may need to reconnect
       to PostgreSQL eventually */
    // TODO: bind-mount the PostgreSQL socket into the new rootfs
    if (!instance.config->HasCertDatabase())
        isolate_from_filesystem(instance.config->HasZeroConf());

    if (!instance.cmdline.user.IsEmpty())
        capabilities_post_setuid(cap_keep_list, ARRAY_SIZE(cap_keep_list));

#ifdef __linux
    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
#endif

    /* main loop */

    instance.InitWorker();

    /* tell systemd we're ready */
    sd_notify(0, "READY=1");

    instance.event_loop.Dispatch();

    /* cleanup */

    log_global_deinit();

    bulldog_deinit();
    failure_deinit();

    deinit_all_listeners(&instance);
    deinit_all_controls(&instance);

    thread_pool_deinit();
}
<commit_msg>lb_main: global exception handler<commit_after>/*
 * The main source of the Beng proxy server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "direct.hxx"
#include "lb_instance.hxx"
#include "lb_check.hxx"
#include "lb_setup.hxx"
#include "lb_connection.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "stock/MapStock.hxx"
#include "failure.hxx"
#include "bulldog.hxx"
#include "balancer.hxx"
#include "pipe_stock.hxx"
#include "log_glue.hxx"
#include "lb_config.hxx"
#include "ssl/ssl_init.hxx"
#include "pool.hxx"
#include "thread_pool.hxx"
#include "fb_pool.hxx"
#include "capabilities.hxx"
#include "system/Isolate.hxx"
#include "system/SetupProcess.hxx"
#include "util/PrintException.hxx"
#include "util/Macros.hxx"

#include <daemon/log.h>

#include <systemd/sd-daemon.h>
#include <postgresql/libpq-fe.h>

#include <assert.h>
#include <unistd.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>

#ifdef __linux
#include <sys/prctl.h>

#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
#endif
#endif

static constexpr cap_value_t cap_keep_list[1] = {
    /* keep the NET_RAW capability to be able to to use the socket
       option IP_TRANSPARENT */
    CAP_NET_RAW,
};

void
LbInstance::ShutdownCallback()
{
    if (should_exit)
        return;

    should_exit = true;
    deinit_signals(this);
    thread_pool_stop();

    avahi_client.Close();

    compress_event.Cancel();

    deinit_all_controls(this);

    DisconnectCertCaches();

    while (!connections.empty())
        lb_connection_close(&connections.front());
    assert(n_tcp_connections == 0);

    deinit_all_listeners(this);

    thread_pool_join();

    monitors.Clear();

    pool_commit();

    if (tcp_balancer != nullptr)
        tcp_balancer_free(tcp_balancer);

    delete tcp_stock;

    if (balancer != nullptr)
        balancer_free(balancer);

    if (pipe_stock != nullptr)
        pipe_stock_free(pipe_stock);

    pool_commit();
}

void
LbInstance::ReloadEventCallback(int)
{
    unsigned n_ssl_sessions = FlushSSLSessionCache(LONG_MAX);
    daemon_log(3, "flushed %u SSL sessions\n", n_ssl_sessions);

    Compress();
}

void
init_signals(LbInstance *instance)
{
    instance->shutdown_listener.Enable();
    instance->sighup_event.Enable();
}

void
deinit_signals(LbInstance *instance)
{
    instance->shutdown_listener.Disable();
    instance->sighup_event.Disable();
}

int main(int argc, char **argv)
try {
    const ScopeFbPoolInit fb_pool_init;
    LbInstance instance;

    /* configuration */

    LbConfig config;
    ParseCommandLine(instance.cmdline, config, argc, argv);

    LoadConfigFile(config, instance.cmdline.config_path);

    instance.config = &config;

    if (instance.cmdline.check) {
        const ScopeSslGlobalInit ssl_init;
        lb_check(instance.event_loop, *instance.config);
        return EXIT_SUCCESS;
    }

    /* initialize */

    SetupProcess();

    const ScopeSslGlobalInit ssl_init;

    /* prevent libpq from initializing libssl & libcrypto again */
    PQinitOpenSSL(0, 0);

    direct_global_init();

    init_signals(&instance);

    init_all_controls(&instance);
    init_all_listeners(instance);

    instance.balancer = balancer_new(instance.event_loop);
    instance.tcp_stock = tcp_stock_new(instance.event_loop,
                                       instance.cmdline.tcp_stock_limit);
    instance.tcp_balancer = tcp_balancer_new(*instance.tcp_stock,
                                             *instance.balancer);

    instance.pipe_stock = pipe_stock_new(instance.event_loop);

    failure_init();
    bulldog_init(instance.cmdline.bulldog_path);

    /* launch the access logger */

    log_global_init(config.access_logger.c_str(),
                    &instance.cmdline.logger_user);

    /* daemonize II */

    if (!instance.cmdline.user.IsEmpty())
        capabilities_pre_setuid();

    instance.cmdline.user.Apply();

    for (const auto &path : config.lua_files)
        instance.RunLuaFile(path.c_str());

    /* can't change to new (empty) rootfs if we may need to reconnect
       to PostgreSQL eventually */
    // TODO: bind-mount the PostgreSQL socket into the new rootfs
    if (!instance.config->HasCertDatabase())
        isolate_from_filesystem(instance.config->HasZeroConf());

    if (!instance.cmdline.user.IsEmpty())
        capabilities_post_setuid(cap_keep_list, ARRAY_SIZE(cap_keep_list));

#ifdef __linux
    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
#endif

    /* main loop */

    instance.InitWorker();

    /* tell systemd we're ready */
    sd_notify(0, "READY=1");

    instance.event_loop.Dispatch();

    /* cleanup */

    log_global_deinit();

    bulldog_deinit();
    failure_deinit();

    deinit_all_listeners(&instance);
    deinit_all_controls(&instance);

    thread_pool_deinit();
} catch (const std::exception &e) {
    PrintException(e);
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include "modinclude.h"
#include "bot_admin.h"

class DieCommand : public AdminHook {
	public:
		int botAPIversion();
		bool onLoadComplete();
		void onRehash();
		std::string getDesc();
		std::vector<std::string> supports();
		std::vector<std::vector<std::string> > adminCommands();
		void onAdminCommand(std::string server, std::string nick, std::string command, std::string message, dccSender* dccMod, bool master);
};

int DieCommand::botAPIversion() {
	return 1002;
}

bool DieCommand::onLoadComplete() {
	std::multimap<std::string, std::string> modAbilities = getModAbilities();
	std::multimap<std::string, std::string>::iterator botAdminAbility = modAbilities.find("BOT_ADMIN");
	if (botAdminAbility == modAbilities.end()) { // BOT_ADMIN not provided but required for this module
		std::cout << "A module providing BOT_ADMIN is required for " << moduleName << ".  Unloading." << std::endl;
		unloadModule(moduleName);
		return false;
	}
	if (config["masteronly"] != "") {
		if (config["masteronly"][0] == 'n')
			config["masteronly"] = "no";
		else
			config["masteronly"] = "yes";
	} else
		config["masteronly"] = "yes";
	return true;
}

void DieCommand::onRehash() {
	std::multimap<std::string, std::string> modAbilities = getModAbilities();
	std::multimap<std::string, std::string>::iterator botAdminAbility = modAbilities.find("BOT_ADMIN");
	if (botAdminAbility == modAbilities.end()) { // BOT_ADMIN not provided but required for this module
		std::cout << "A module providing BOT_ADMIN is required for " << moduleName << ".  Unloading." << std::endl;
		unloadModule(moduleName);
	}
	if (config["masteronly"] != "") {
		if (config["masteronly"][0] == 'n')
			config["masteronly"] = "no";
		else
			config["masteronly"] = "yes";
	} else
		config["masteronly"] = "yes";
}

std::string DieCommand::getDesc() {
	return "Allows the bot master to shut the bot down from IRC.";
}

std::vector<std::string> DieCommand::supports() {
	std::vector<std::string> supporting;
	supporting.push_back("BOT_ADMIN");
	return supporting;
}

std::vector<std::vector<std::string> > DieCommand::adminCommands() {
	std::vector<std::vector<std::string> > theCommands;
	std::vector<std::string> dieCommand;
	dieCommand.push_back("die");
	dieCommand.push_back("Makes the bot shut down.");
	dieCommand.push_back("Syntax: die [reason]");
	dieCommand.push_back("This command causes the bot to shut down.  If a reason is given, it will be used as the quit reason on all servers.");
	if (config["masteronly"] == "yes")
		dieCommand.push_back("This command is available only to bot admins.");
	theCommands.push_back(dieCommand);
	return theCommands;
}

void DieCommand::onAdminCommand(std::string server, std::string nick, std::string command, std::string message, dccSender* dccMod, bool master) {
	if (config["masteronly"] == "yes" && !master) {
		if (dccMod == NULL)
			sendPrivMsg(server, nick, "The die command is available only to bot masters.");
		else
			dccMod->dccSend(server + "/" + nick, "The die command is available only to bot masters.");
		return;
	}
	std::list<std::string> connectedServers = getServers();
	for (std::list<std::string>::iterator servIter = connectedServers.begin(); servIter != connectedServers.end(); ++servIter)
		quitServer(*servIter, message);
	if (dccMod != NULL) {
		std::vector<std::string> connectedDCC = dccMod->getConnections();
		for (unsigned int i = 0; i < connectedDCC.size(); i++)
			dccMod->closeDCCConnection(connectedDCC[i]);
	}
	std::cout << "Shutting down by admin command: die" << std::endl;
	std::exit(0);
}

extern "C" Module* spawn() {
	return new DieCommand;
}<commit_msg>Add some sleep to m_admin_die so the bot doesn't exist before the send queues can flush.<commit_after>#include "modinclude.h"
#include "bot_admin.h"

class DieCommand : public AdminHook {
	public:
		int botAPIversion();
		bool onLoadComplete();
		void onRehash();
		std::string getDesc();
		std::vector<std::string> supports();
		std::vector<std::vector<std::string> > adminCommands();
		void onAdminCommand(std::string server, std::string nick, std::string command, std::string message, dccSender* dccMod, bool master);
};

int DieCommand::botAPIversion() {
	return 1002;
}

bool DieCommand::onLoadComplete() {
	std::multimap<std::string, std::string> modAbilities = getModAbilities();
	std::multimap<std::string, std::string>::iterator botAdminAbility = modAbilities.find("BOT_ADMIN");
	if (botAdminAbility == modAbilities.end()) { // BOT_ADMIN not provided but required for this module
		std::cout << "A module providing BOT_ADMIN is required for " << moduleName << ".  Unloading." << std::endl;
		unloadModule(moduleName);
		return false;
	}
	if (config["masteronly"] != "") {
		if (config["masteronly"][0] == 'n')
			config["masteronly"] = "no";
		else
			config["masteronly"] = "yes";
	} else
		config["masteronly"] = "yes";
	return true;
}

void DieCommand::onRehash() {
	std::multimap<std::string, std::string> modAbilities = getModAbilities();
	std::multimap<std::string, std::string>::iterator botAdminAbility = modAbilities.find("BOT_ADMIN");
	if (botAdminAbility == modAbilities.end()) { // BOT_ADMIN not provided but required for this module
		std::cout << "A module providing BOT_ADMIN is required for " << moduleName << ".  Unloading." << std::endl;
		unloadModule(moduleName);
	}
	if (config["masteronly"] != "") {
		if (config["masteronly"][0] == 'n')
			config["masteronly"] = "no";
		else
			config["masteronly"] = "yes";
	} else
		config["masteronly"] = "yes";
}

std::string DieCommand::getDesc() {
	return "Allows the bot master to shut the bot down from IRC.";
}

std::vector<std::string> DieCommand::supports() {
	std::vector<std::string> supporting;
	supporting.push_back("BOT_ADMIN");
	return supporting;
}

std::vector<std::vector<std::string> > DieCommand::adminCommands() {
	std::vector<std::vector<std::string> > theCommands;
	std::vector<std::string> dieCommand;
	dieCommand.push_back("die");
	dieCommand.push_back("Makes the bot shut down.");
	dieCommand.push_back("Syntax: die [reason]");
	dieCommand.push_back("This command causes the bot to shut down.  If a reason is given, it will be used as the quit reason on all servers.");
	if (config["masteronly"] == "yes")
		dieCommand.push_back("This command is available only to bot admins.");
	theCommands.push_back(dieCommand);
	return theCommands;
}

void DieCommand::onAdminCommand(std::string server, std::string nick, std::string command, std::string message, dccSender* dccMod, bool master) {
	if (config["masteronly"] == "yes" && !master) {
		if (dccMod == NULL)
			sendPrivMsg(server, nick, "The die command is available only to bot masters.");
		else
			dccMod->dccSend(server + "/" + nick, "The die command is available only to bot masters.");
		return;
	}
	std::list<std::string> connectedServers = getServers();
	for (std::list<std::string>::iterator servIter = connectedServers.begin(); servIter != connectedServers.end(); ++servIter)
		quitServer(*servIter, message);
	if (dccMod != NULL) {
		std::vector<std::string> connectedDCC = dccMod->getConnections();
		for (unsigned int i = 0; i < connectedDCC.size(); i++)
			dccMod->closeDCCConnection(connectedDCC[i]);
	}
	std::cout << "Shutting down by admin command: die" << std::endl;
	sleep(1);
	std::exit(0);
}

extern "C" Module* spawn() {
	return new DieCommand;
}<|endoftext|>