<commit_before>#include <QFileDialog>
#include <memory>
#include "lib/CRC/CRC32.h"
#include "lib/File/File.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

namespace
{
    QString filters("All files (*.*)");
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
}

void MainWindow::on_inputPathPushButton_clicked()
{
    QString inputPath = QFileDialog::getOpenFileName(
        0, "Load file", QDir::currentPath(), filters);

    if (inputPath == nullptr)
        return;

    ui->inputPathLineEdit->setText(inputPath);

    if (ui->outputPathLineEdit->text() == "")
    {
        auto inputFileInfo = QFileInfo(inputPath);
        auto outputPath = inputFileInfo.baseName() + "-patched";
        if (inputFileInfo.completeSuffix() != "")
            outputPath += "." + inputFileInfo.completeSuffix();
        ui->outputPathLineEdit->setText(outputPath);
    }
}

void MainWindow::on_outputPathPushButton_clicked()
{
    QString outputPath = QFileDialog::getSaveFileName(
        0, "Save file", QDir::currentPath(), filters);

    if (outputPath == nullptr)
        return;

    ui->outputPathLineEdit->setText(outputPath);
}

void MainWindow::on_patchPushButton_clicked()
{
    try
    {
        uint32_t desiredChecksum = ui->crcLineEdit->text().toULong(nullptr, 16);
        std::string inputPath = ui->inputPathLineEdit->text().toStdString();
        std::string outputPath = ui->outputPathLineEdit->text().toStdString();

        std::unique_ptr<CRC> crc(new CRC32);

        std::unique_ptr<File> inputFile(File::fromFileName(
            inputPath.c_str(), File::FOPEN_READ | File::FOPEN_BINARY));

        std::unique_ptr<File> outputFile(File::fromFileName(
            outputPath.c_str(), File::FOPEN_WRITE | File::FOPEN_BINARY));

        File::OffsetType desiredPosition = inputFile->getFileSize();

        crc->applyPatch(
            desiredChecksum,
            desiredPosition,
            *inputFile,
            *outputFile,
            false);

        puts("Done!"); //TODO
    }
    catch (...)
    {
        puts("Error..."); //TODO
    }
}

#ifdef WAF
    #include "gui/mainwindow.moc"
    #include "gui/mainwindow.cc.moc"
#endif
<commit_msg>Added parent widgets to save and open dialogs<commit_after>#include <QFileDialog>
#include <memory>
#include "lib/CRC/CRC32.h"
#include "lib/File/File.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

namespace
{
    QString filters("All files (*.*)");
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
}

void MainWindow::on_inputPathPushButton_clicked()
{
    QString inputPath = QFileDialog::getOpenFileName(
        ui->centralWidget, "Load file", QDir::currentPath(), filters);

    if (inputPath == nullptr)
        return;

    ui->inputPathLineEdit->setText(inputPath);

    if (ui->outputPathLineEdit->text() == "")
    {
        auto inputFileInfo = QFileInfo(inputPath);
        auto outputPath = inputFileInfo.baseName() + "-patched";
        if (inputFileInfo.completeSuffix() != "")
            outputPath += "." + inputFileInfo.completeSuffix();
        ui->outputPathLineEdit->setText(outputPath);
    }
}

void MainWindow::on_outputPathPushButton_clicked()
{
    QString outputPath = QFileDialog::getSaveFileName(
        ui->centralWidget, "Save file", QDir::currentPath(), filters);

    if (outputPath == nullptr)
        return;

    ui->outputPathLineEdit->setText(outputPath);
}

void MainWindow::on_patchPushButton_clicked()
{
    try
    {
        uint32_t desiredChecksum = ui->crcLineEdit->text().toULong(nullptr, 16);
        std::string inputPath = ui->inputPathLineEdit->text().toStdString();
        std::string outputPath = ui->outputPathLineEdit->text().toStdString();

        std::unique_ptr<CRC> crc(new CRC32);

        std::unique_ptr<File> inputFile(File::fromFileName(
            inputPath.c_str(), File::FOPEN_READ | File::FOPEN_BINARY));

        std::unique_ptr<File> outputFile(File::fromFileName(
            outputPath.c_str(), File::FOPEN_WRITE | File::FOPEN_BINARY));

        File::OffsetType desiredPosition = inputFile->getFileSize();

        crc->applyPatch(
            desiredChecksum,
            desiredPosition,
            *inputFile,
            *outputFile,
            false);

        puts("Done!"); //TODO
    }
    catch (...)
    {
        puts("Error..."); //TODO
    }
}

#ifdef WAF
    #include "gui/mainwindow.moc"
    #include "gui/mainwindow.cc.moc"
#endif
<|endoftext|>


<commit_before>
// =============================================================================
// Type Interfaces -- Title Page
// =============================================================================

/** \page pageTypeInterfaces Type Interfaces
 *
 * These pages document type interfaces: i.e. types which may appear as template
 * parameters, and which must conform to some standard in order to complete their tasks.
 *
 * Documented Type Interfaces in the %Tomographer framwork are:
 *
 *  - \subpage pageInterfaceMatrQ
 *  - \subpage pageInterfaceTomoProblem
 *  - \subpage pageInterfaceRandomWalk
 *  - \subpage pageInterfaceMHWalker
 *  - \subpage pageInterfaceMHRWStatsCollector
 *  - \subpage pageInterfaceTomoValueCalculator
 *  - \subpage pageTaskManagerDispatcher
 *
 */

// =============================================================================
// MatrQ
// =============================================================================

/** \page pageInterfaceMatrQ Interface
 *
 * Declares types for dealing with quantum states and POVMs of a fixed dimension which
 * we'll call here \a dim. See also \ref Tomographer::MatrQ.
 *
 * \par typedef ... RealScalar
 * The real scalar type we're working with.
 *
 * \par typedef ... ComplexScalar
 * The complex scalar type we're working with.
 *
 * \par typedef ... IntFreqType
 * The integral type to use for measurement counts. Usually \c int is enough, except if in
 * your experiment you take >1e9 measurements
 *
 * \par typedef ... MatrixType
 * The type needed to represent a density matrix. This is usually expected to be a Eigen
 * type.
 *
 * \par MatrixType initMatrixType() const
 * Returns an expression which can be assigned to a \a MatrixType such that the matrix is
 * initialized to a square \a dim x \a dim zero matrix.
 *
 * \par typedef ... VectorParamType
 * The type needed to represent a X-parameterization of a density matrix. This is usually
 * expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamType() const
 * Returns an expression which can be assigned to a \a VectorParamType such that the
 * vector is initialized to a zero column vector with dim*dim entries.
 *
 * \par typedef ... VectorParamNdofType
 * The type needed to represent some parameterization of a density matrix with
 * dim*dim-1 parameters. This is usually expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamNdofType() const
 * Returns an expression which can be assigned to a \a VectorParamNdofType such that the
 * vector is initialized to a zero column vector with dim*dim-1 entries.
 *
 * \par typedef ... VectorParamListType
 * The type needed to represent a list of X-parameterizations of e.g. POVM effects, each
 * with dim*dim parameters. This is usually expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamListType(std::size_t length) const
 * Returns an expression which can be assigned to a \a VectorParamListType such that the
 * list is initialized to a list with \a length copies of a zero column vector with
 * dim*dim entries.
 *
 * \par typedef ... FreqListType
 * The type needed to represent frequency counts of measurements. This is typically an
 * \ref Eigen::Array integral type.
 *
 * \par MatrixType initFreqListType(std::size_t len) const
 * Returns an expression which can be assigned to a \a FreqListType such that the vector
 * is initialized to \a len items with zero counts each.
 *
 *
 */

// =============================================================================
// TomoProblem
// =============================================================================

/** \page pageInterfaceTomoProblem Interface
 *
 * Stores the data relevant for a tomography problem. Includes:
 *
 * - a \ref pageInterfaceMatrQ object, which stores the dimension and is able to construct
 *   requested types;
 *
 * - cached values of \a dim, dim2=dim*dim, and Ndof=dim*dim-1
 *
 * - a factor by which to artificially amplify/reduce the number of frequency counts
 *
 * - the list of POVM effects and their frequency counts (measurement data)
 *
 * - the maximum likelihood estimate, along with cached values of various of its
 *   parameterizations
 *
 * - a method which can calculate the loglikelihood function.
 *
 * See also: \ref Tomographer::IndepMeasTomoProblem<MatrQ_,LLHValueType_,UseCLoopInstead>
 *
 *
 * \par const MatrQ matrq;
 * A \ref pageInterfaceMatrQ object which we may use to create matrices etc.
 *
 * \par const IntegralType dim;
 * Cached dimension.
 *
 * \par const IntegralType dim2;
 * Cached value of dim*dim
 *
 * \par const IntegralType Ndof;
 * Cached value of dim*dim-1
 *
 * \par typedef .. LLHValueType;
 * The type to use to store the value of the loglikelihood function calculated by \a
 * calc_llh().
 *
 * \par LLHValueType NMeasAmplifyFactor;
 * Factor by which to multiply all measurement frequencies when calculating the
 * loglikelihood function
 *
 * \par typename MatrQ::VectorParamListType Exn;
 * The POVM Entries, parameterized with \ref pageParamsX
 *
 * \par typename MatrQ::FreqListType Nx;
 * The frequency list, i.e. number of times each POVM effect was observed
 *
 * \par typename MatrQ::MatrixType rho_MLE;
 * Maximum likelihood estimate as density matrix
 *
 * \par typename MatrQ::MatrixType T_MLE;
 * Maximum likelihood estimate as \ref pageParamsT of the density matrix
 *
 * \par typename MatrQ::VectorParamType x_MLE;
 * Maximum likelihood estimate as \ref pageParamsX
 *
 * \par LLHValueType calc_llh(const typename MatrQ::VectorParamType & x) const;
 * Calculate the loglikelihood function, defined as
 * \f[
 *   \lambda\left(\rho\right) = -2\,\ln\,\tr\left[B^n\,\rho^{\otimes n}\right]\ .
 * \f]
 * The argument \a x is the \ref pageParamsX of the density matrix at which the
 * loglikelihood function should be evaluated.
 *
 */

// =============================================================================
// MHRWStatsCollector
// =============================================================================

/** \page pageInterfaceMHRWStatsCollector MHRWStatsCollector Interface
 *
 * A type implementing a \a MHRWStatsCollector interface is responsible for collecting
 * statistics from samples during a Metropolis-Hastings random walk (see \ref
 * Tomographer::MHRandomWalk).
 *
 * This type must provide the following members. The members, or the class itself, must be
 * templates with type parameters \c CountIntType, \c PointType, \c FnValueType, and \c
 * MHRandomWalk. (It is usually most convenient to template the methods themselves, so
 * that you don't have to specify the parameters when instantiating the object.)
 *
 * \par void init()
 * is called before starting the random walk
 *
 * \par void thermalizing_done()
 * is called after the thermalizing runs, before starting the "live" runs.
 *
 * \par void done()
 * is called after the random walk is finished.
 *
 * \par void process_sample(CountIntType, const PointType & pt, FnValueType fnval, MHRandomWalk & rw)
 *     is called at the end of each sweep, after the thermalization sweeps have finished.
 *     This function is meant to actually take live samples.
 *
 * \par void raw_move(CountIntType k, bool is_thermalizing, bool is_live_iter, bool accepted, double a, const PointType & newpt, FnValueType newptval, const PointType & curpt, FnValueType curptval, MHRandomWalk & rw)
 *     is called after each move during the random walk. Note that if you want to take
 *     real samples, use \c process_sample() instead.
 *
 * \par
 *     \c k is the iteration number, \c is_thermalizing is \c true during the first part
 *     of the random walk during the thermalizing runs, \c is_live_iter is set to \c true
 *     only if a sample is taken at this point, i.e. if not thermalizing and after a full
 *     sweep. \c accepted indicates whether this Metropolis-Hastings move was accepted or
 *     not and \c a gives the ratio of the function which was tested for the move. (Note
 *     that \c a might not be calculated and left to 1 if known to be greater than 1.) \c
 *     newpt and \c newptval are the new proposal jump point and the function value at
 *     that new point. The function value is either the actual value of the function, or
 *     its logarithm, or a dummy value, depending on \c MHWalker::UseFnSyntaxType.
 *     Similarly \c curpt and \c curptval are the current point and function value. The
 *     object \c rw is a reference to the random walk object instance.
 *
 *
 */

// =============================================================================
// MHWalker
// =============================================================================

/** \page pageInterfaceMHWalker MHWalker Interface
 *
 * A \a MHWalker compliant type describes a particular Metropolis-Hastings walk on some
 * state space. It takes care for example of providing candidate new points (jump
 * function), and calculating the probability ratio for the jump.
 *
 * \a MHWalker types are used in particular by:
 *  - \refitem Tomographer::MHRandomWalk.
 *
 * A type implementing the \a MHWalker interface must provide the following types:
 *
 * \par typedef ... PointType
 *     The type needed to represent a point in state space in which we are performing a
 *     random walk. An object of such type is never default-constructed, but always
 *     copy-constructed from another \a PointType. One should also be able to assign a \a
 *     PointType to another \c PointType (e.g. curpt = other_point).
 *
 * \par typedef ... RealScalar
 *     The type needed to represent a step size. This will most likely be a \c double
 *     or some floating-point type.
 *
 * \par typedef ... FnValueType — required only if UseFnSyntaxType != MHUseFnRelativeValue
 *     The return value type of the function evaluated at each point during the
 *     Metropolis-Hastings random walk. Usually this is \c double or some floating-point
 *     type. You do not need to provide this typedef if \c UseFnSyntaxType is set to \c
 *     MHUseFnRelativeValue.
 *
 * A \a MHWalker must provide the following constant enumeration values:
 *
 * \par enum { UseFnSyntaxType = ... }
 *     Specifies how we calculate the function probability ratio of two points in the
 *     random walk. \c UseFnSyntaxType should be set to one of either \ref
 *     Tomographer::MHUseFnValue, \ref Tomographer::MHUseFnLogValue, or \ref
 *     Tomographer::MHUseFnRelativeValue. See \ref
 *     labelMHWalkerUseFnSyntaxType "Role of UseFnSyntaxType".
 *
 *
 * And must provide the following members:
 *
 * \par void init()
 *
 * \par void thermalizing_done()
 *
 * \par void done()
 *
 * \par PointType jump_fn(const PointType & curpt, RealScalar step_size)
 *
 * \par FnValueType fnval(const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnValue
 *
 * \par FnValueType fnlogval(const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnLogValue
 *
 * \par double fnrelval(const PointType & newpt, const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnRelativeValue
 *
 *

 *
 * \anchor labelMHWalkerUseFnSyntaxType
 * \par Role of \c UseFnSyntaxType:
 *
 *  - MHUseFnValue --> use MHWalker::fnval(newpt)
 *  - MHUseFnLogValue --> use MHWalker::fnlogval(newpt)
 *  - MHUseFnRelativeValue --> use MHWalker::fnrelval(newpt, curpt)
 *
 *
 * .........................
 *
 */

// =============================================================================
// RandomWalk
// =============================================================================

/** \page pageInterfaceRandomWalk RandomWalk Interface
 *
 * The \a RandomWalk type is responsible for actually implementing the random walk. It
 * should keep the current state of the random walk in memory and update it when the \c
 * move() function is called.
 *
 * \a RandomWalk types are used in particular by:
 *  - \refitem Tomographer::RandomWalkBase.
 *
 * The \a RandomWalk type should provide the following typedef member:
 *
 * \par typedef ... CountIntType
 *          This (usually an unsigned int or unsigned long)
 *          should specify which type to use to count the iterations. This is also the
 *          return type of \c n_sweep() etc.
 *
 * \a RandomWalk needs to provide the following members, which are called at the
 * appropriate times:
 *
 * \par CountIntType RandomWalk::n_sweep()
 *          Number of iterations that compose a "sweep".
 *
 * \par CountIntType RandomWalk::n_therm()
 *          Number of thermalizing sweeps to perform.
 *
 * \par CountIntType RandomWalk::n_run()
 *          Number of live sweeps to perform.
 *
 * \par void RandomWalk::move(CountIntType k, bool is_thermalizing, bool is_live_iter)
 *          Is called to perform a new random walk iteration. The random walk object is
 *          responsible for keeping the current state of the random walk in memory,
 *          and for processing a jump function. This method should update the internal
 *          state of the random walk. This function does not return anything. \c k is the
 *          raw iteration count, starting at zero (and which is reset to zero after the
 *          thermalizing sweeps). \c is_thermalizing is \c true during the thermalizing
 *          runs, \c false otherwise. \c is_live_iter is \c true when a live sample is
 *          taken, only once every sweep after the thermalization runs.
 *
 * \par void RandomWalk::process_sample(CountIntType k)
 *          Is called for each "live" point for which a sample should be taken. The point
 *          in question is the current state of the random walk. This only happens after
 *          thermalization, and at the last iteration of a sweep.
 *
 * \par void RandomWalk::init()
 *          Is called before starting the random walk. The RandomWalk may perform custom
 *          last-minute initializations if required.
 *
 * \par void RandomWalk::thermalizing_done()
 *          Is called after the thermalizing runs and before starting the live runs.
 *
 * \par void RandomWalk::done()
 *          Is called after the random walk is finished. This happens after the given
 *          number of iterations were reached.
 *
 */

/** \page pageInterfaceTomoValueCalculator TomoValueCalculator Interface
 *
 * \todo ............ doc. ..................
 *
 * NOTE: must be copy-constructible, and different threads must be able to operate safely
 * on different copies.
 */
<commit_msg>fixed minor stuff<commit_after>
// =============================================================================
// Type Interfaces -- Title Page
// =============================================================================

/** \page pageTypeInterfaces Type Interfaces
 *
 * These pages document type interfaces: i.e. types which may appear as template
 * parameters, and which must conform to some standard in order to complete their tasks.
 *
 * Documented Type Interfaces in the %Tomographer framwork are:
 *
 *  - \subpage pageInterfaceMatrQ
 *  - \subpage pageInterfaceTomoProblem
 *  - \subpage pageInterfaceRandomWalk
 *  - \subpage pageInterfaceMHWalker
 *  - \subpage pageInterfaceMHRWStatsCollector
 *  - \subpage pageInterfaceTomoValueCalculator
 *  - \subpage pageTaskManagerDispatcher
 *
 */

// =============================================================================
// MatrQ
// =============================================================================

/** \page pageInterfaceMatrQ MatrQ Interface
 *
 * Declares types for dealing with quantum states and POVMs of a fixed dimension which
 * we'll call here \a dim. See also \ref Tomographer::MatrQ.
 *
 * \par typedef ... RealScalar
 * The real scalar type we're working with.
 *
 * \par typedef ... ComplexScalar
 * The complex scalar type we're working with.
 *
 * \par typedef ... IntFreqType
 * The integral type to use for measurement counts. Usually \c int is enough, except if in
 * your experiment you take >1e9 measurements
 *
 * \par typedef ... MatrixType
 * The type needed to represent a density matrix. This is usually expected to be a Eigen
 * type.
 *
 * \par MatrixType initMatrixType() const
 * Returns an expression which can be assigned to a \a MatrixType such that the matrix is
 * initialized to a square \a dim x \a dim zero matrix.
 *
 * \par typedef ... VectorParamType
 * The type needed to represent a X-parameterization of a density matrix. This is usually
 * expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamType() const
 * Returns an expression which can be assigned to a \a VectorParamType such that the
 * vector is initialized to a zero column vector with dim*dim entries.
 *
 * \par typedef ... VectorParamNdofType
 * The type needed to represent some parameterization of a density matrix with
 * dim*dim-1 parameters. This is usually expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamNdofType() const
 * Returns an expression which can be assigned to a \a VectorParamNdofType such that the
 * vector is initialized to a zero column vector with dim*dim-1 entries.
 *
 * \par typedef ... VectorParamListType
 * The type needed to represent a list of X-parameterizations of e.g. POVM effects, each
 * with dim*dim parameters. This is usually expected to be a Eigen type.
 *
 * \par MatrixType initVectorParamListType(std::size_t length) const
 * Returns an expression which can be assigned to a \a VectorParamListType such that the
 * list is initialized to a list with \a length copies of a zero column vector with
 * dim*dim entries.
 *
 * \par typedef ... FreqListType
 * The type needed to represent frequency counts of measurements. This is typically an
 * \ref Eigen::Array integral type.
 *
 * \par MatrixType initFreqListType(std::size_t len) const
 * Returns an expression which can be assigned to a \a FreqListType such that the vector
 * is initialized to \a len items with zero counts each.
 *
 *
 */

// =============================================================================
// TomoProblem
// =============================================================================

/** \page pageInterfaceTomoProblem TomoProblem Interface
 *
 * Stores the data relevant for a tomography problem. Includes:
 *
 * - a \ref pageInterfaceMatrQ object, which stores the dimension and is able to construct
 *   requested types;
 *
 * - cached values of \a dim, dim2=dim*dim, and Ndof=dim*dim-1
 *
 * - a factor by which to artificially amplify/reduce the number of frequency counts
 *
 * - the list of POVM effects and their frequency counts (measurement data)
 *
 * - the maximum likelihood estimate, along with cached values of various of its
 *   parameterizations
 *
 * - a method which can calculate the loglikelihood function.
 *
 * See also: \ref Tomographer::IndepMeasTomoProblem<MatrQ_,LLHValueType_,UseCLoopInstead>
 *
 *
 * \par const MatrQ matrq;
 * A \ref pageInterfaceMatrQ object which we may use to create matrices etc.
 *
 * \par const IntegralType dim;
 * Cached dimension.
 *
 * \par const IntegralType dim2;
 * Cached value of dim*dim
 *
 * \par const IntegralType Ndof;
 * Cached value of dim*dim-1
 *
 * \par typedef .. LLHValueType;
 * The type to use to store the value of the loglikelihood function calculated by \a
 * calc_llh().
 *
 * \par LLHValueType NMeasAmplifyFactor;
 * Factor by which to multiply all measurement frequencies when calculating the
 * loglikelihood function
 *
 * \par typename MatrQ::VectorParamListType Exn;
 * The POVM Entries, parameterized with \ref pageParamsX
 *
 * \par typename MatrQ::FreqListType Nx;
 * The frequency list, i.e. number of times each POVM effect was observed
 *
 * \par typename MatrQ::MatrixType rho_MLE;
 * Maximum likelihood estimate as density matrix
 *
 * \par typename MatrQ::MatrixType T_MLE;
 * Maximum likelihood estimate as \ref pageParamsT of the density matrix
 *
 * \par typename MatrQ::VectorParamType x_MLE;
 * Maximum likelihood estimate as \ref pageParamsX
 *
 * \par LLHValueType calc_llh(const typename MatrQ::VectorParamType & x) const;
 * Calculate the loglikelihood function, defined as
 * \f[
 *   \lambda\left(\rho\right) = -2\,\ln\,\mathrm{tr}\left[B^n\,\rho^{\otimes n}\right]\ .
 * \f]
 * The argument \a x is the \ref pageParamsX of the density matrix at which the
 * loglikelihood function should be evaluated.
 *
 */

// =============================================================================
// MHRWStatsCollector
// =============================================================================

/** \page pageInterfaceMHRWStatsCollector MHRWStatsCollector Interface
 *
 * A type implementing a \a MHRWStatsCollector interface is responsible for collecting
 * statistics from samples during a Metropolis-Hastings random walk (see \ref
 * Tomographer::MHRandomWalk).
 *
 * This type must provide the following members. The members, or the class itself, must be
 * templates with type parameters \c CountIntType, \c PointType, \c FnValueType, and \c
 * MHRandomWalk. (It is usually most convenient to template the methods themselves, so
 * that you don't have to specify the parameters when instantiating the object.)
 *
 * \par void init()
 * is called before starting the random walk
 *
 * \par void thermalizing_done()
 * is called after the thermalizing runs, before starting the "live" runs.
 *
 * \par void done()
 * is called after the random walk is finished.
 *
 * \par void process_sample(CountIntType, const PointType & pt, FnValueType fnval, MHRandomWalk & rw)
 *     is called at the end of each sweep, after the thermalization sweeps have finished.
 *     This function is meant to actually take live samples.
 *
 * \par void raw_move(CountIntType k, bool is_thermalizing, bool is_live_iter, bool accepted, double a, const PointType & newpt, FnValueType newptval, const PointType & curpt, FnValueType curptval, MHRandomWalk & rw)
 *     is called after each move during the random walk. Note that if you want to take
 *     real samples, use \c process_sample() instead.
 *
 * \par
 *     \c k is the iteration number, \c is_thermalizing is \c true during the first part
 *     of the random walk during the thermalizing runs, \c is_live_iter is set to \c true
 *     only if a sample is taken at this point, i.e. if not thermalizing and after a full
 *     sweep. \c accepted indicates whether this Metropolis-Hastings move was accepted or
 *     not and \c a gives the ratio of the function which was tested for the move. (Note
 *     that \c a might not be calculated and left to 1 if known to be greater than 1.) \c
 *     newpt and \c newptval are the new proposal jump point and the function value at
 *     that new point. The function value is either the actual value of the function, or
 *     its logarithm, or a dummy value, depending on \c MHWalker::UseFnSyntaxType.
 *     Similarly \c curpt and \c curptval are the current point and function value. The
 *     object \c rw is a reference to the random walk object instance.
 *
 *
 */

// =============================================================================
// MHWalker
// =============================================================================

/** \page pageInterfaceMHWalker MHWalker Interface
 *
 * A \a MHWalker compliant type describes a particular Metropolis-Hastings walk on some
 * state space. It takes care for example of providing candidate new points (jump
 * function), and calculating the probability ratio for the jump.
 *
 * \a MHWalker types are used in particular by:
 *  - \refitem Tomographer::MHRandomWalk.
 *
 * A type implementing the \a MHWalker interface must provide the following types:
 *
 * \par typedef ... PointType
 *     The type needed to represent a point in state space in which we are performing a
 *     random walk. An object of such type is never default-constructed, but always
 *     copy-constructed from another \a PointType. One should also be able to assign a \a
 *     PointType to another \c PointType (e.g. curpt = other_point).
 *
 * \par typedef ... RealScalar
 *     The type needed to represent a step size. This will most likely be a \c double
 *     or some floating-point type.
 *
 * \par typedef ... FnValueType — required only if UseFnSyntaxType != MHUseFnRelativeValue
 *     The return value type of the function evaluated at each point during the
 *     Metropolis-Hastings random walk. Usually this is \c double or some floating-point
 *     type. You do not need to provide this typedef if \c UseFnSyntaxType is set to \c
 *     MHUseFnRelativeValue.
 *
 * A \a MHWalker must provide the following constant enumeration values:
 *
 * \par enum { UseFnSyntaxType = ... }
 *     Specifies how we calculate the function probability ratio of two points in the
 *     random walk. \c UseFnSyntaxType should be set to one of either \ref
 *     Tomographer::MHUseFnValue, \ref Tomographer::MHUseFnLogValue, or \ref
 *     Tomographer::MHUseFnRelativeValue. See \ref
 *     labelMHWalkerUseFnSyntaxType "Role of UseFnSyntaxType".
 *
 *
 * And must provide the following members:
 *
 * \par void init()
 *
 * \par void thermalizing_done()
 *
 * \par void done()
 *
 * \par PointType jump_fn(const PointType & curpt, RealScalar step_size)
 *
 * \par FnValueType fnval(const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnValue
 *
 * \par FnValueType fnlogval(const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnLogValue
 *
 * \par double fnrelval(const PointType & newpt, const PointType & curpt) — required only if UseFnSyntaxType == MHUseFnRelativeValue
 *
 *

 *
 * \anchor labelMHWalkerUseFnSyntaxType
 * \par Role of \c UseFnSyntaxType:
 *
 *  - MHUseFnValue --> use MHWalker::fnval(newpt)
 *  - MHUseFnLogValue --> use MHWalker::fnlogval(newpt)
 *  - MHUseFnRelativeValue --> use MHWalker::fnrelval(newpt, curpt)
 *
 *
 * .........................
 *
 */

// =============================================================================
// RandomWalk
// =============================================================================

/** \page pageInterfaceRandomWalk RandomWalk Interface
 *
 * The \a RandomWalk type is responsible for actually implementing the random walk. It
 * should keep the current state of the random walk in memory and update it when the \c
 * move() function is called.
 *
 * \a RandomWalk types are used in particular by:
 *  - \refitem Tomographer::RandomWalkBase.
 *
 * The \a RandomWalk type should provide the following typedef member:
 *
 * \par typedef ... CountIntType
 *          This (usually an unsigned int or unsigned long)
 *          should specify which type to use to count the iterations. This is also the
 *          return type of \c n_sweep() etc.
 *
 * \a RandomWalk needs to provide the following members, which are called at the
 * appropriate times:
 *
 * \par CountIntType RandomWalk::n_sweep()
 *          Number of iterations that compose a "sweep".
 *
 * \par CountIntType RandomWalk::n_therm()
 *          Number of thermalizing sweeps to perform.
 *
 * \par CountIntType RandomWalk::n_run()
 *          Number of live sweeps to perform.
 *
 * \par void RandomWalk::move(CountIntType k, bool is_thermalizing, bool is_live_iter)
 *          Is called to perform a new random walk iteration. The random walk object is
 *          responsible for keeping the current state of the random walk in memory,
 *          and for processing a jump function. This method should update the internal
 *          state of the random walk. This function does not return anything. \c k is the
 *          raw iteration count, starting at zero (and which is reset to zero after the
 *          thermalizing sweeps). \c is_thermalizing is \c true during the thermalizing
 *          runs, \c false otherwise. \c is_live_iter is \c true when a live sample is
 *          taken, only once every sweep after the thermalization runs.
 *
 * \par void RandomWalk::process_sample(CountIntType k)
 *          Is called for each "live" point for which a sample should be taken. The point
 *          in question is the current state of the random walk. This only happens after
 *          thermalization, and at the last iteration of a sweep.
 *
 * \par void RandomWalk::init()
 *          Is called before starting the random walk. The RandomWalk may perform custom
 *          last-minute initializations if required.
 *
 * \par void RandomWalk::thermalizing_done()
 *          Is called after the thermalizing runs and before starting the live runs.
 *
 * \par void RandomWalk::done()
 *          Is called after the random walk is finished. This happens after the given
 *          number of iterations were reached.
 *
 */

/** \page pageInterfaceTomoValueCalculator TomoValueCalculator Interface
 *
 * \todo ............ doc. ..................
 *
 * NOTE: must be copy-constructible, and different threads must be able to operate safely
 * on different copies.
 */
<|endoftext|>


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

#include "Tape.hpp"

using namespace Electron;

Tape::Tape() :
		TapePlayer(2000000),
		is_running_(false),
		data_register_(0),
		delegate_(nullptr),
		output_({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}),
		last_posted_interrupt_status_(0),
		interrupt_status_(0) {}

void Tape::push_tape_bit(uint16_t bit) {
	data_register_ = (uint16_t)((data_register_ >> 1) | (bit << 10));

	if(input_.minimum_bits_until_full) input_.minimum_bits_until_full--;
	if(input_.minimum_bits_until_full == 8) interrupt_status_ &= ~Interrupt::ReceiveDataFull;
	if(!input_.minimum_bits_until_full) {
		if((data_register_&0x3) == 0x1) {
			interrupt_status_ |= Interrupt::ReceiveDataFull;
			if(is_in_input_mode_) input_.minimum_bits_until_full = 9;
		}
	}

	if(output_.bits_remaining_until_empty)	output_.bits_remaining_until_empty--;
	if(!output_.bits_remaining_until_empty)	interrupt_status_ |= Interrupt::TransmitDataEmpty;

	if(data_register_ == 0x3ff)	interrupt_status_ |= Interrupt::HighToneDetect;
	else						interrupt_status_ &= ~Interrupt::HighToneDetect;

	evaluate_interrupts();
}

void Tape::evaluate_interrupts() {
	if(last_posted_interrupt_status_ != interrupt_status_) {
		last_posted_interrupt_status_ = interrupt_status_;
		if(delegate_) delegate_->tape_did_change_interrupt_status(this);
	}
}

void Tape::clear_interrupts(uint8_t interrupts) {
	interrupt_status_ &= ~interrupts;
	evaluate_interrupts();
}

void Tape::set_is_in_input_mode(bool is_in_input_mode) {
	is_in_input_mode_ = is_in_input_mode;
}

void Tape::set_counter(uint8_t value) {
	output_.cycles_into_pulse = 0;
	output_.bits_remaining_until_empty = 0;
}

void Tape::set_data_register(uint8_t value) {
	data_register_ = (uint16_t)((value << 2) | 1);
	output_.bits_remaining_until_empty = 9;
}

uint8_t Tape::get_data_register() {
	return (uint8_t)(data_register_ >> 2);
}

void Tape::process_input_pulse(Storage::Tape::Tape::Pulse pulse) {
	crossings_[0] = crossings_[1];
	crossings_[1] = crossings_[2];
	crossings_[2] = crossings_[3];

	crossings_[3] = Tape::Unrecognised;
	if(pulse.type != Storage::Tape::Tape::Pulse::Zero) {
		float pulse_length = (float)pulse.length.length / (float)pulse.length.clock_rate;
		if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) crossings_[3] = Tape::Short;
		if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) crossings_[3] = Tape::Long;
	}

	if(crossings_[0] == Tape::Long && crossings_[1] == Tape::Long) {
		push_tape_bit(0);
		crossings_[0] = crossings_[1] = Tape::Recognised;
	} else {
		if(crossings_[0] == Tape::Short && crossings_[1] == Tape::Short && crossings_[2] == Tape::Short && crossings_[3] == Tape::Short) {
			push_tape_bit(1);
			crossings_[0] = crossings_[1] =
			crossings_[2] = crossings_[3] = Tape::Recognised;
		}
	}
}

void Tape::run_for_cycles(unsigned int number_of_cycles) {
	if(is_enabled_) {
		if(is_in_input_mode_) {
			if(is_running_) {
				TapePlayer::run_for_cycles((int)number_of_cycles);
			}
		} else {
			output_.cycles_into_pulse += number_of_cycles;
			while(output_.cycles_into_pulse > 1664) {	// 1664 = the closest you can get to 1200 baud if you're looking for something
				output_.cycles_into_pulse -= 1664;		// that divides the 125,000Hz clock that the sound divider runs off.
				push_tape_bit(1);
			}
		}
	}
}
<commit_msg>Oh yuck, it looks like I've repeated this same test in two different places. Must figure out where to factor it out to. But in the meantime, the emulated Electron has just loaded its first CSW.<commit_after>//
//  Tape.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/12/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Tape.hpp"

using namespace Electron;

Tape::Tape() :
		TapePlayer(2000000),
		is_running_(false),
		data_register_(0),
		delegate_(nullptr),
		output_({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}),
		last_posted_interrupt_status_(0),
		interrupt_status_(0) {}

void Tape::push_tape_bit(uint16_t bit) {
	data_register_ = (uint16_t)((data_register_ >> 1) | (bit << 10));

	if(input_.minimum_bits_until_full) input_.minimum_bits_until_full--;
	if(input_.minimum_bits_until_full == 8) interrupt_status_ &= ~Interrupt::ReceiveDataFull;
	if(!input_.minimum_bits_until_full) {
		if((data_register_&0x3) == 0x1) {
			interrupt_status_ |= Interrupt::ReceiveDataFull;
			if(is_in_input_mode_) input_.minimum_bits_until_full = 9;
		}
	}

	if(output_.bits_remaining_until_empty)	output_.bits_remaining_until_empty--;
	if(!output_.bits_remaining_until_empty)	interrupt_status_ |= Interrupt::TransmitDataEmpty;

	if(data_register_ == 0x3ff)	interrupt_status_ |= Interrupt::HighToneDetect;
	else						interrupt_status_ &= ~Interrupt::HighToneDetect;

	evaluate_interrupts();
}

void Tape::evaluate_interrupts() {
	if(last_posted_interrupt_status_ != interrupt_status_) {
		last_posted_interrupt_status_ = interrupt_status_;
		if(delegate_) delegate_->tape_did_change_interrupt_status(this);
	}
}

void Tape::clear_interrupts(uint8_t interrupts) {
	interrupt_status_ &= ~interrupts;
	evaluate_interrupts();
}

void Tape::set_is_in_input_mode(bool is_in_input_mode) {
	is_in_input_mode_ = is_in_input_mode;
}

void Tape::set_counter(uint8_t value) {
	output_.cycles_into_pulse = 0;
	output_.bits_remaining_until_empty = 0;
}

void Tape::set_data_register(uint8_t value) {
	data_register_ = (uint16_t)((value << 2) | 1);
	output_.bits_remaining_until_empty = 9;
}

uint8_t Tape::get_data_register() {
	return (uint8_t)(data_register_ >> 2);
}

void Tape::process_input_pulse(Storage::Tape::Tape::Pulse pulse) {
	crossings_[0] = crossings_[1];
	crossings_[1] = crossings_[2];
	crossings_[2] = crossings_[3];

	crossings_[3] = Tape::Unrecognised;
	if(pulse.type != Storage::Tape::Tape::Pulse::Zero) {
		float pulse_length = (float)pulse.length.length / (float)pulse.length.clock_rate;
		if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 1200.0) {
			crossings_[3] = pulse_length > 1.0 / 3000.0 ? Tape::Long : Tape::Short;
		}
//		if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) crossings_[3] = Tape::Short;
//		if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) crossings_[3] = Tape::Long;
	}

	if(crossings_[0] == Tape::Long && crossings_[1] == Tape::Long) {
		push_tape_bit(0);
		crossings_[0] = crossings_[1] = Tape::Recognised;
	} else {
		if(crossings_[0] == Tape::Short && crossings_[1] == Tape::Short && crossings_[2] == Tape::Short && crossings_[3] == Tape::Short) {
			push_tape_bit(1);
			crossings_[0] = crossings_[1] =
			crossings_[2] = crossings_[3] = Tape::Recognised;
		}
	}
}

void Tape::run_for_cycles(unsigned int number_of_cycles) {
	if(is_enabled_) {
		if(is_in_input_mode_) {
			if(is_running_) {
				TapePlayer::run_for_cycles((int)number_of_cycles);
			}
		} else {
			output_.cycles_into_pulse += number_of_cycles;
			while(output_.cycles_into_pulse > 1664) {	// 1664 = the closest you can get to 1200 baud if you're looking for something
				output_.cycles_into_pulse -= 1664;		// that divides the 125,000Hz clock that the sound divider runs off.
				push_tape_bit(1);
			}
		}
	}
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkFileWriterSelector.h"

#include <mitkFileWriterRegistry.h>
#include <mitkCoreServices.h>
#include <mitkIMimeTypeProvider.h>
#include <mitkBaseData.h>

#include <usServiceReference.h>
#include <usServiceProperties.h>
#include <usAny.h>

#include <itksys/SystemTools.hxx>

#include <set>
#include <limits>
#include <iterator>

namespace mitk {

struct FileWriterSelector::Item::Impl : us::SharedData
{
  Impl()
    : m_FileWriter(NULL)
    , m_ConfidenceLevel(IFileWriter::Unsupported)
    , m_BaseDataIndex(0)
    , m_Id(-1)
  {}

  us::ServiceReference<IFileWriter> m_FileWriterRef;
  IFileWriter* m_FileWriter;
  IFileWriter::ConfidenceLevel m_ConfidenceLevel;
  std::size_t m_BaseDataIndex;
  MimeType m_MimeType;
  long m_Id;
};

struct FileWriterSelector::Impl : us::SharedData
{
  Impl()
    : m_BestId(-1)
    , m_SelectedId(m_BestId)
  {}

  Impl(const Impl& other)
    : us::SharedData(other)
    , m_BestId(-1)
    , m_SelectedId(m_BestId)
  {}

  FileWriterRegistry m_WriterRegistry;
  std::map<long, FileWriterSelector::Item> m_Items;
  std::set<MimeType> m_MimeTypes;
  long m_BestId;
  long m_SelectedId;
};

FileWriterSelector::FileWriterSelector(const FileWriterSelector& other)
  : m_Data(other.m_Data)
{
}

FileWriterSelector::FileWriterSelector(const BaseData* baseData, const std::string& mimeType,
                                       const std::string& path)
  : m_Data(new Impl)
{
  mitk::CoreServicePointer<mitk::IMimeTypeProvider> mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider());

  std::vector<FileWriterRegistry::WriterReference> refs;

  std::string destMimeType = mimeType;
  if (destMimeType.empty() && !path.empty())
  {
    // try to derive a mime-type from the file
    std::vector<MimeType> mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path);
    if (!mimeTypes.empty())
    {
      for( unsigned int index = 0; index < mimeTypes.size(); index++)
      {
        std::vector<FileWriterRegistry::WriterReference> tempRefs = m_Data->m_WriterRegistry.GetReferences(baseData, mimeTypes.at(index).GetName());
        for( unsigned int innerIndex = 0; innerIndex < tempRefs.size(); innerIndex++)
        {
          refs.push_back( tempRefs.at(innerIndex) );
        }
      }
    }
    else if (!itksys::SystemTools::GetFilenameExtension(path).empty())
    {
      // If there are no suitable mime-type for the file AND an extension
      // was supplied, we stop here.
      return;
    }
  }
  else
  {
    refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType);
  }

  std::vector<std::string> classHierarchy = baseData->GetClassHierarchy();

  // Get all writers and their mime types for the given base data type
  Item bestItem;
  for (std::vector<FileWriterRegistry::WriterReference>::const_iterator iter = refs.begin(),
       iterEnd = refs.end(); iter != iterEnd; ++iter)
  {
    std::string mimeTypeName = iter->GetProperty(IFileWriter::PROP_MIMETYPE()).ToString();
    if (!mimeTypeName.empty())
    {
      MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName);
      if (mimeType.IsValid())
      {
        // There is a registered mime-type for this writer. Now get the confidence level
        // of this writer for writing the given base data object.

        IFileWriter* writer = m_Data->m_WriterRegistry.GetWriter(*iter);
        if (writer == NULL) continue;
        try
        {
          writer->SetInput(baseData);
          IFileWriter::ConfidenceLevel confidenceLevel = writer->GetConfidenceLevel();
          if (confidenceLevel == IFileWriter::Unsupported)
          {
            continue;
          }

          std::string baseDataType = iter->GetProperty(IFileWriter::PROP_BASEDATA_TYPE()).ToString();
          std::vector<std::string>::iterator idxIter =
              std::find(classHierarchy.begin(), classHierarchy.end(), baseDataType);
          std::size_t baseDataIndex = std::numeric_limits<std::size_t>::max();
          if (idxIter != classHierarchy.end())
          {
            baseDataIndex = std::distance(classHierarchy.begin(), idxIter);
          }

          Item item;
          item.d->m_FileWriterRef = *iter;
          item.d->m_FileWriter = writer;
          item.d->m_ConfidenceLevel = confidenceLevel;
          item.d->m_BaseDataIndex = baseDataIndex;
          item.d->m_MimeType = mimeType;
          item.d->m_Id = us::any_cast<long>(iter->GetProperty(us::ServiceConstants::SERVICE_ID()));
          m_Data->m_Items.insert(std::make_pair(item.d->m_Id, item));
          m_Data->m_MimeTypes.insert(mimeType);
          if (!bestItem.GetReference() || bestItem < item)
          {
            bestItem = item;
          }
        }
        catch (const us::BadAnyCastException& e)
        {
          MITK_WARN << "Unexpected: " << e.what();
        }
        catch (const std::exception& e)
        {
          // Log the error but continue
          MITK_WARN << "IFileWriter::GetConfidenceLevel exception: " << e.what();
        }
      }
    }
  }

  if (bestItem.GetReference())
  {
    m_Data->m_BestId = bestItem.GetServiceId();
    m_Data->m_SelectedId = m_Data->m_BestId;
  }
}

FileWriterSelector::~FileWriterSelector()
{
}

FileWriterSelector& FileWriterSelector::operator=(const FileWriterSelector& other)
{
  m_Data = other.m_Data;
  return *this;
}

bool FileWriterSelector::IsEmpty() const
{
  return m_Data->m_Items.empty();
}

std::vector<FileWriterSelector::Item> FileWriterSelector::Get(const std::string& mimeType) const
{
  std::vector<Item> result;
  for (std::map<long, Item>::const_iterator iter = m_Data->m_Items.begin(),
       iterEnd = m_Data->m_Items.end(); iter != iterEnd; ++iter)
  {
    if (mimeType.empty() || iter->second.GetMimeType().GetName() == mimeType)
    {
      result.push_back(iter->second);
    }
  }
  std::sort(result.begin(), result.end());
  return result;
}

std::vector<FileWriterSelector::Item> FileWriterSelector::Get() const
{
  return Get(this->GetSelected().d->m_MimeType.GetName());
}

FileWriterSelector::Item FileWriterSelector::Get(long id) const
{
  std::map<long, Item>::const_iterator iter = m_Data->m_Items.find(id);
  if (iter != m_Data->m_Items.end())
  {
    return iter->second;
  }
  return Item();
}

FileWriterSelector::Item FileWriterSelector::GetDefault() const
{
  return Get(m_Data->m_BestId);
}

long FileWriterSelector::GetDefaultId() const
{
  return m_Data->m_BestId;
}

FileWriterSelector::Item FileWriterSelector::GetSelected() const
{
  return Get(m_Data->m_SelectedId);
}

long FileWriterSelector::GetSelectedId() const
{
  return m_Data->m_SelectedId;
}

bool FileWriterSelector::Select(const std::string& mimeType)
{
  std::vector<Item> items = Get(mimeType);
  if (items.empty()) return false;
  return Select(items.back());
}

bool FileWriterSelector::Select(const FileWriterSelector::Item& item)
{
  return Select(item.d->m_Id);
}

bool FileWriterSelector::Select(long id)
{
  if (id > -1)
  {
    if (m_Data->m_Items.find(id) == m_Data->m_Items.end())
    {
      return false;
    }
    m_Data->m_SelectedId = id;
    return true;
  }
  return false;
}

std::vector<MimeType> FileWriterSelector::GetMimeTypes() const
{
  std::vector<MimeType> result;
  result.reserve(m_Data->m_MimeTypes.size());
  result.assign(m_Data->m_MimeTypes.begin(), m_Data->m_MimeTypes.end());
  return result;
}

void FileWriterSelector::Swap(FileWriterSelector& fws)
{
  m_Data.Swap(fws.m_Data);
}

FileWriterSelector::Item::Item(const FileWriterSelector::Item& other)
  : d(other.d)
{
}

FileWriterSelector::Item::~Item()
{
}

FileWriterSelector::Item& FileWriterSelector::Item::operator=(const FileWriterSelector::Item& other)
{
  d = other.d;
  return *this;
}

IFileWriter* FileWriterSelector::Item::GetWriter() const
{
  return d->m_FileWriter;
}

std::string FileWriterSelector::Item::GetDescription() const
{
  us::Any descr = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_DESCRIPTION());
  if (descr.Empty()) return std::string();
  return descr.ToString();
}

IFileWriter::ConfidenceLevel FileWriterSelector::Item::GetConfidenceLevel() const
{
  return d->m_ConfidenceLevel;
}

MimeType FileWriterSelector::Item::GetMimeType() const
{
  return d->m_MimeType;
}

std::string FileWriterSelector::Item::GetBaseDataType() const
{
  us::Any any = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_BASEDATA_TYPE());
  if (any.Empty()) return std::string();
  return any.ToString();
}

us::ServiceReference<IFileWriter> FileWriterSelector::Item::GetReference() const
{
  return d->m_FileWriterRef;
}

long FileWriterSelector::Item::GetServiceId() const
{
  return d->m_Id;
}

bool FileWriterSelector::Item::operator<(const FileWriterSelector::Item& other) const
{
  // sort by confidence level first (ascending)
  if (d->m_ConfidenceLevel == other.d->m_ConfidenceLevel)
  {
    // sort by class hierarchy index (writers for more derived
    // based data types are considered a better match)
    if (d->m_BaseDataIndex == other.d->m_BaseDataIndex)
    {
      // sort by file writer service ranking
      return d->m_FileWriterRef < other.d->m_FileWriterRef;
    }
    return other.d->m_BaseDataIndex < d->m_BaseDataIndex;
  }
  return d->m_ConfidenceLevel < other.d->m_ConfidenceLevel;
}

FileWriterSelector::Item::Item()
  : d(new Impl())
{}

void swap(FileWriterSelector& fws1, FileWriterSelector& fws2)
{
  fws1.Swap(fws2);
}

}
<commit_msg>COMP: Also get references for empy destMimeType<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkFileWriterSelector.h"

#include <mitkFileWriterRegistry.h>
#include <mitkCoreServices.h>
#include <mitkIMimeTypeProvider.h>
#include <mitkBaseData.h>

#include <usServiceReference.h>
#include <usServiceProperties.h>
#include <usAny.h>

#include <itksys/SystemTools.hxx>

#include <set>
#include <limits>
#include <iterator>

namespace mitk {

struct FileWriterSelector::Item::Impl : us::SharedData
{
  Impl()
    : m_FileWriter(NULL)
    , m_ConfidenceLevel(IFileWriter::Unsupported)
    , m_BaseDataIndex(0)
    , m_Id(-1)
  {}

  us::ServiceReference<IFileWriter> m_FileWriterRef;
  IFileWriter* m_FileWriter;
  IFileWriter::ConfidenceLevel m_ConfidenceLevel;
  std::size_t m_BaseDataIndex;
  MimeType m_MimeType;
  long m_Id;
};

struct FileWriterSelector::Impl : us::SharedData
{
  Impl()
    : m_BestId(-1)
    , m_SelectedId(m_BestId)
  {}

  Impl(const Impl& other)
    : us::SharedData(other)
    , m_BestId(-1)
    , m_SelectedId(m_BestId)
  {}

  FileWriterRegistry m_WriterRegistry;
  std::map<long, FileWriterSelector::Item> m_Items;
  std::set<MimeType> m_MimeTypes;
  long m_BestId;
  long m_SelectedId;
};

FileWriterSelector::FileWriterSelector(const FileWriterSelector& other)
  : m_Data(other.m_Data)
{
}

FileWriterSelector::FileWriterSelector(const BaseData* baseData, const std::string& mimeType,
                                       const std::string& path)
  : m_Data(new Impl)
{
  mitk::CoreServicePointer<mitk::IMimeTypeProvider> mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider());

  std::vector<FileWriterRegistry::WriterReference> refs;

  std::string destMimeType = mimeType;
  if (destMimeType.empty() && !path.empty())
  {
    // try to derive a mime-type from the file
    std::vector<MimeType> mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path);
    if (!mimeTypes.empty())
    {
      for( unsigned int index = 0; index < mimeTypes.size(); index++)
      {
        std::vector<FileWriterRegistry::WriterReference> tempRefs = m_Data->m_WriterRegistry.GetReferences(baseData, mimeTypes.at(index).GetName());
        for( unsigned int innerIndex = 0; innerIndex < tempRefs.size(); innerIndex++)
        {
          refs.push_back( tempRefs.at(innerIndex) );
        }
      }
    }
    else if (!itksys::SystemTools::GetFilenameExtension(path).empty())
    {
      // If there are no suitable mime-type for the file AND an extension
      // was supplied, we stop here.
      return;
    }
    else
    {
      refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType);
    }
  }
  else
  {
    refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType);
  }

  std::vector<std::string> classHierarchy = baseData->GetClassHierarchy();

  // Get all writers and their mime types for the given base data type
  Item bestItem;
  for (std::vector<FileWriterRegistry::WriterReference>::const_iterator iter = refs.begin(),
       iterEnd = refs.end(); iter != iterEnd; ++iter)
  {
    std::string mimeTypeName = iter->GetProperty(IFileWriter::PROP_MIMETYPE()).ToString();
    if (!mimeTypeName.empty())
    {
      MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName);
      if (mimeType.IsValid())
      {
        // There is a registered mime-type for this writer. Now get the confidence level
        // of this writer for writing the given base data object.

        IFileWriter* writer = m_Data->m_WriterRegistry.GetWriter(*iter);
        if (writer == NULL) continue;
        try
        {
          writer->SetInput(baseData);
          IFileWriter::ConfidenceLevel confidenceLevel = writer->GetConfidenceLevel();
          if (confidenceLevel == IFileWriter::Unsupported)
          {
            continue;
          }

          std::string baseDataType = iter->GetProperty(IFileWriter::PROP_BASEDATA_TYPE()).ToString();
          std::vector<std::string>::iterator idxIter =
              std::find(classHierarchy.begin(), classHierarchy.end(), baseDataType);
          std::size_t baseDataIndex = std::numeric_limits<std::size_t>::max();
          if (idxIter != classHierarchy.end())
          {
            baseDataIndex = std::distance(classHierarchy.begin(), idxIter);
          }

          Item item;
          item.d->m_FileWriterRef = *iter;
          item.d->m_FileWriter = writer;
          item.d->m_ConfidenceLevel = confidenceLevel;
          item.d->m_BaseDataIndex = baseDataIndex;
          item.d->m_MimeType = mimeType;
          item.d->m_Id = us::any_cast<long>(iter->GetProperty(us::ServiceConstants::SERVICE_ID()));
          m_Data->m_Items.insert(std::make_pair(item.d->m_Id, item));
          m_Data->m_MimeTypes.insert(mimeType);
          if (!bestItem.GetReference() || bestItem < item)
          {
            bestItem = item;
          }
        }
        catch (const us::BadAnyCastException& e)
        {
          MITK_WARN << "Unexpected: " << e.what();
        }
        catch (const std::exception& e)
        {
          // Log the error but continue
          MITK_WARN << "IFileWriter::GetConfidenceLevel exception: " << e.what();
        }
      }
    }
  }

  if (bestItem.GetReference())
  {
    m_Data->m_BestId = bestItem.GetServiceId();
    m_Data->m_SelectedId = m_Data->m_BestId;
  }
}

FileWriterSelector::~FileWriterSelector()
{
}

FileWriterSelector& FileWriterSelector::operator=(const FileWriterSelector& other)
{
  m_Data = other.m_Data;
  return *this;
}

bool FileWriterSelector::IsEmpty() const
{
  return m_Data->m_Items.empty();
}

std::vector<FileWriterSelector::Item> FileWriterSelector::Get(const std::string& mimeType) const
{
  std::vector<Item> result;
  for (std::map<long, Item>::const_iterator iter = m_Data->m_Items.begin(),
       iterEnd = m_Data->m_Items.end(); iter != iterEnd; ++iter)
  {
    if (mimeType.empty() || iter->second.GetMimeType().GetName() == mimeType)
    {
      result.push_back(iter->second);
    }
  }
  std::sort(result.begin(), result.end());
  return result;
}

std::vector<FileWriterSelector::Item> FileWriterSelector::Get() const
{
  return Get(this->GetSelected().d->m_MimeType.GetName());
}

FileWriterSelector::Item FileWriterSelector::Get(long id) const
{
  std::map<long, Item>::const_iterator iter = m_Data->m_Items.find(id);
  if (iter != m_Data->m_Items.end())
  {
    return iter->second;
  }
  return Item();
}

FileWriterSelector::Item FileWriterSelector::GetDefault() const
{
  return Get(m_Data->m_BestId);
}

long FileWriterSelector::GetDefaultId() const
{
  return m_Data->m_BestId;
}

FileWriterSelector::Item FileWriterSelector::GetSelected() const
{
  return Get(m_Data->m_SelectedId);
}

long FileWriterSelector::GetSelectedId() const
{
  return m_Data->m_SelectedId;
}

bool FileWriterSelector::Select(const std::string& mimeType)
{
  std::vector<Item> items = Get(mimeType);
  if (items.empty()) return false;
  return Select(items.back());
}

bool FileWriterSelector::Select(const FileWriterSelector::Item& item)
{
  return Select(item.d->m_Id);
}

bool FileWriterSelector::Select(long id)
{
  if (id > -1)
  {
    if (m_Data->m_Items.find(id) == m_Data->m_Items.end())
    {
      return false;
    }
    m_Data->m_SelectedId = id;
    return true;
  }
  return false;
}

std::vector<MimeType> FileWriterSelector::GetMimeTypes() const
{
  std::vector<MimeType> result;
  result.reserve(m_Data->m_MimeTypes.size());
  result.assign(m_Data->m_MimeTypes.begin(), m_Data->m_MimeTypes.end());
  return result;
}

void FileWriterSelector::Swap(FileWriterSelector& fws)
{
  m_Data.Swap(fws.m_Data);
}

FileWriterSelector::Item::Item(const FileWriterSelector::Item& other)
  : d(other.d)
{
}

FileWriterSelector::Item::~Item()
{
}

FileWriterSelector::Item& FileWriterSelector::Item::operator=(const FileWriterSelector::Item& other)
{
  d = other.d;
  return *this;
}

IFileWriter* FileWriterSelector::Item::GetWriter() const
{
  return d->m_FileWriter;
}

std::string FileWriterSelector::Item::GetDescription() const
{
  us::Any descr = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_DESCRIPTION());
  if (descr.Empty()) return std::string();
  return descr.ToString();
}

IFileWriter::ConfidenceLevel FileWriterSelector::Item::GetConfidenceLevel() const
{
  return d->m_ConfidenceLevel;
}

MimeType FileWriterSelector::Item::GetMimeType() const
{
  return d->m_MimeType;
}

std::string FileWriterSelector::Item::GetBaseDataType() const
{
  us::Any any = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_BASEDATA_TYPE());
  if (any.Empty()) return std::string();
  return any.ToString();
}

us::ServiceReference<IFileWriter> FileWriterSelector::Item::GetReference() const
{
  return d->m_FileWriterRef;
}

long FileWriterSelector::Item::GetServiceId() const
{
  return d->m_Id;
}

bool FileWriterSelector::Item::operator<(const FileWriterSelector::Item& other) const
{
  // sort by confidence level first (ascending)
  if (d->m_ConfidenceLevel == other.d->m_ConfidenceLevel)
  {
    // sort by class hierarchy index (writers for more derived
    // based data types are considered a better match)
    if (d->m_BaseDataIndex == other.d->m_BaseDataIndex)
    {
      // sort by file writer service ranking
      return d->m_FileWriterRef < other.d->m_FileWriterRef;
    }
    return other.d->m_BaseDataIndex < d->m_BaseDataIndex;
  }
  return d->m_ConfidenceLevel < other.d->m_ConfidenceLevel;
}

FileWriterSelector::Item::Item()
  : d(new Impl())
{}

void swap(FileWriterSelector& fws1, FileWriterSelector& fws2)
{
  fws1.Swap(fws2);
}

}
<|endoftext|>


<commit_before>#include "SkyManager.h"
#include <iostream>

#define degreesToRadians(x) x*(3.141592f/180.0f)
float g_light;
float g_ticks;

//blend
float blend(float x, float y, float factor){
    return x + ((y-x) * factor);
}

SkyManager::SkyManager()
: sun("Sun"), moon("Moon")
{
    dayTime = 0; //Dawn
    m_prevTime = 0; //Time now

    std::vector<GLfloat> svertexCoords
    {
            -70,  70, 400,
             70,  70, 400,
             70, -70, 400,
            -70, -70, 400
        };

    std::vector<GLfloat> stextureCoords
        {
            0, 1,
            1, 1,
            1, 0,
            0, 0,
        };

    std::vector<GLuint> sindexCoords
    {
        0, 1, 2,
        2, 3, 0
    };

    m_SunModel.addData({svertexCoords, stextureCoords, sindexCoords});

    std::vector<GLfloat> mvertexCoords
    {
            -70,  70, -400,
             70,  70, -400,
             70, -70, -400,
            -70, -70, -400
        };

    std::vector<GLfloat> mtextureCoords
        {
            0, 1,
            1, 1,
            1, 0,
            0, 0,
        };

    std::vector<GLuint> mindexCoords
    {
        0, 1, 2,
        2, 3, 0
    };

    m_MoonModel.addData({mvertexCoords, mtextureCoords, mindexCoords});

}

void SkyManager::TickUpdate(unsigned int tickTime){
    //Day Time Management
    dayTime += tickTime - m_prevTime;
    m_prevTime = tickTime;

    if(dayTime > 23999){
        dayTime = 0;
    }

    //Ambient light
    //0 = 6am
    //12000 = 6pm
    if(dayTime < 1500){ //6am - 9am sun gets brighter
        g_light = blend(0.6f, 1.0f, (float)dayTime / 1500);
    }
    if(dayTime > 1500 && dayTime < 10500){ //9am - 3pm sun is brightest
        g_light = 1.0f;
    }
    if(dayTime > 10500 && dayTime < 12000){ //3pm - 6pm sun gets dimmer
        g_light = blend(1.0f, 0.6f,(float)((float)dayTime - 10500) / 1500);
    }
    if(dayTime > 12000 && dayTime < 13500){ //6pm - 9pm sun light fades
        g_light = blend(0.6f, 0.2f, (float)((float)dayTime - 12000)/ 1500);
    }
    if(dayTime > 13500 && dayTime < 22500){//9pm - 3am is night
        g_light = 0.2f;
    }
    if(dayTime > 22500 && dayTime < 24000){
        g_light = blend(0.2f, 0.6f, (float)((float)dayTime-22500) / 1500);
    }

    //Update Sun/Moon matrix
    transformMatrix = glm::translate(glm::mat4(1.0f), playerPos);

    g_ticks = dayTime;
}

void SkyManager::setTime(unsigned int tickTime){
    dayTime = tickTime;
}

unsigned int SkyManager::getTime(){
    return dayTime;
}

void SkyManager::Update(glm::vec3 position){
    playerPos = position;
}

void SkyManager::render(const Camera& camera){

    skyBox.Render(camera);
    glEnable(GL_BLEND);
    m_shader.useProgram();
    m_SunModel.bindVAO();
    sun.bindTexture();

    m_shader.loadModelMatrix(transformMatrix);
    m_shader.loadProjectionViewMatrix   (camera.getProjectionViewMatrix());
    m_shader.loadTime(degreesToRadians(((float)dayTime/24000) * 360));

    GL::drawElements(m_SunModel.getIndicesCount());

    m_shader.useProgram();
    m_MoonModel.bindVAO();
    moon.bindTexture();

    m_shader.loadModelMatrix(transformMatrix);
    m_shader.loadProjectionViewMatrix   (camera.getProjectionViewMatrix());
    m_shader.loadTime(degreesToRadians(((float)dayTime/24000) * 360));

    clouds.Render(camera, playerPos);

    GL::drawElements(m_MoonModel.getIndicesCount());
    glDisable(GL_BLEND);

}<commit_msg>Fixed drawing of the moon.<commit_after>#include "SkyManager.h"
#include <iostream>

#define degreesToRadians(x) x*(3.141592f/180.0f)
float g_light;
float g_ticks;

//blend
float blend(float x, float y, float factor){
    return x + ((y-x) * factor);
}

SkyManager::SkyManager()
: sun("Sun"), moon("Moon")
{
    dayTime = 0; //Dawn
    m_prevTime = 0; //Time now

    std::vector<GLfloat> svertexCoords
    {
            -70,  70, 400,
             70,  70, 400,
             70, -70, 400,
            -70, -70, 400
        };

    std::vector<GLfloat> stextureCoords
        {
            0, 1,
            1, 1,
            1, 0,
            0, 0,
        };

    std::vector<GLuint> sindexCoords
    {
        0, 1, 2,
        2, 3, 0
    };

    m_SunModel.addData({svertexCoords, stextureCoords, sindexCoords});

    std::vector<GLfloat> mvertexCoords
    {
            -70,  70, -400,
             70,  70, -400,
             70, -70, -400,
            -70, -70, -400
        };

    std::vector<GLfloat> mtextureCoords
        {
            0, 1,
            1, 1,
            1, 0,
            0, 0,
        };

    std::vector<GLuint> mindexCoords
    {
        0, 1, 2,
        2, 3, 0
    };

    m_MoonModel.addData({mvertexCoords, mtextureCoords, mindexCoords});

}

void SkyManager::TickUpdate(unsigned int tickTime){
    //Day Time Management
    dayTime += tickTime - m_prevTime;
    m_prevTime = tickTime;

    if(dayTime > 23999){
        dayTime = 0;
    }

    //Ambient light
    //0 = 6am
    //12000 = 6pm
    if(dayTime < 1500){ //6am - 9am sun gets brighter
        g_light = blend(0.6f, 1.0f, (float)dayTime / 1500);
    }
    if(dayTime > 1500 && dayTime < 10500){ //9am - 3pm sun is brightest
        g_light = 1.0f;
    }
    if(dayTime > 10500 && dayTime < 12000){ //3pm - 6pm sun gets dimmer
        g_light = blend(1.0f, 0.6f,(float)((float)dayTime - 10500) / 1500);
    }
    if(dayTime > 12000 && dayTime < 13500){ //6pm - 9pm sun light fades
        g_light = blend(0.6f, 0.2f, (float)((float)dayTime - 12000)/ 1500);
    }
    if(dayTime > 13500 && dayTime < 22500){//9pm - 3am is night
        g_light = 0.2f;
    }
    if(dayTime > 22500 && dayTime < 24000){
        g_light = blend(0.2f, 0.6f, (float)((float)dayTime-22500) / 1500);
    }

    //Update Sun/Moon matrix
    transformMatrix = glm::translate(glm::mat4(1.0f), playerPos);

    g_ticks = dayTime;
}

void SkyManager::setTime(unsigned int tickTime){
    dayTime = tickTime;
}

unsigned int SkyManager::getTime(){
    return dayTime;
}

void SkyManager::Update(glm::vec3 position){
    playerPos = position;
}

void SkyManager::render(const Camera& camera){

    skyBox.Render(camera);
    glEnable(GL_BLEND);
    m_shader.useProgram();
    m_SunModel.bindVAO();
    sun.bindTexture();

    m_shader.loadModelMatrix(transformMatrix);
    m_shader.loadProjectionViewMatrix   (camera.getProjectionViewMatrix());
    m_shader.loadTime(degreesToRadians(((float)dayTime/24000) * 360));

    GL::drawElements(m_SunModel.getIndicesCount());

    m_shader.useProgram();
    m_MoonModel.bindVAO();
    moon.bindTexture();

    m_shader.loadModelMatrix(transformMatrix);
    m_shader.loadProjectionViewMatrix   (camera.getProjectionViewMatrix());
    m_shader.loadTime(degreesToRadians(((float)dayTime/24000) * 360));
    GL::drawElements(m_MoonModel.getIndicesCount());

    clouds.Render(camera, playerPos);
    glDisable(GL_BLEND);

}<|endoftext|>


<commit_before>/** \brief Utility for converting between MARC formats.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <set>
#include <stdexcept>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include "MARC.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--quiet] [--limit max_no_of_records] marc_input marc_output [CTLN_1 CTLN_2 .. CTLN_N]\n"
              << "       Autoconverts the MARC format of \"marc_input\" to \"marc_output\".\n"
              << "       Supported extensions are \"xml\", \"mrc\", \"marc\" and \"raw\".\n"
              << "       All extensions except for \"xml\" are assumed to imply MARC-21.\n"
              << "       If a control number list has been specified only those records will\n"
              << "       be extracted or converted.\n\n";
    std::exit(EXIT_FAILURE);
}

void ProcessRecords(const bool quiet, const unsigned max_no_of_records, MARC::Reader * const marc_reader, MARC::Writer * const marc_writer,
                    const std::set<std::string> &control_numbers)
{
    unsigned record_count(0), extracted_count(0);

    while (MARC::Record record = marc_reader->read()) {
        ++record_count;

        if (not control_numbers.empty() and control_numbers.find(record.getControlNumber()) == control_numbers.end())
            continue;

        ++extracted_count;
        marc_writer->write(record);

        if (record_count == max_no_of_records)
            break;
    }

    if (not quiet) {
        logger->info("Processed " + std::to_string(record_count) + " MARC record(s).");
        logger->info("Extracted or converted " + std::to_string(extracted_count) + " record(s).");
    }
}

} // unnamed namespace

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 3)
        Usage();

    bool quiet(false);
    if (std::strcmp(argv[1], "--quiet") == 0) {
        quiet = true;
        --argc, ++argv;
    }

    if (argc < 3)
        Usage();

    unsigned max_no_of_records(UINT_MAX);
    if (std::strcmp(argv[1], "--limit") == 0) {
        if (not StringUtil::ToUnsigned(argv[2], &max_no_of_records) or max_no_of_records == 0)
            Usage();
        argc += 2;
        argv += 2;
    }

    if (argc != 3)
        Usage();

    const std::string input_filename(argv[1]);
    const std::string output_filename(argv[2]);

    try {
        std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(input_filename));
        std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(output_filename));

        std::set<std::string> control_numbers;
        for (int arg_no(3); arg_no < argc; ++arg_no)
            control_numbers.emplace(argv[arg_no]);

        ProcessRecords(quiet, max_no_of_records, marc_reader.get(), marc_writer.get(), control_numbers);
    } catch (const std::exception &e) {
        LOG_ERROR("Caught exception: " + std::string(e.what()));
    }
}
<commit_msg>Another argument-handling fix. a.k., three's the chram!<commit_after>/** \brief Utility for converting between MARC formats.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <set>
#include <stdexcept>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include "MARC.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--quiet] [--limit max_no_of_records] marc_input marc_output [CTLN_1 CTLN_2 .. CTLN_N]\n"
              << "       Autoconverts the MARC format of \"marc_input\" to \"marc_output\".\n"
              << "       Supported extensions are \"xml\", \"mrc\", \"marc\" and \"raw\".\n"
              << "       All extensions except for \"xml\" are assumed to imply MARC-21.\n"
              << "       If a control number list has been specified only those records will\n"
              << "       be extracted or converted.\n\n";
    std::exit(EXIT_FAILURE);
}

void ProcessRecords(const bool quiet, const unsigned max_no_of_records, MARC::Reader * const marc_reader, MARC::Writer * const marc_writer,
                    const std::set<std::string> &control_numbers)
{
    unsigned record_count(0), extracted_count(0);

    while (MARC::Record record = marc_reader->read()) {
        ++record_count;

        if (not control_numbers.empty() and control_numbers.find(record.getControlNumber()) == control_numbers.end())
            continue;

        ++extracted_count;
        marc_writer->write(record);

        if (record_count == max_no_of_records)
            break;
    }

    if (not quiet) {
        logger->info("Processed " + std::to_string(record_count) + " MARC record(s).");
        logger->info("Extracted or converted " + std::to_string(extracted_count) + " record(s).");
    }
}

} // unnamed namespace

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 3)
        Usage();

    bool quiet(false);
    if (std::strcmp(argv[1], "--quiet") == 0) {
        quiet = true;
        --argc, ++argv;
    }

    if (argc < 3)
        Usage();

    unsigned max_no_of_records(UINT_MAX);
    if (std::strcmp(argv[1], "--limit") == 0) {
        if (not StringUtil::ToUnsigned(argv[2], &max_no_of_records) or max_no_of_records == 0)
            Usage();
        argc -= 2;
        argv += 2;
    }

    if (argc < 3)
        Usage();

    const std::string input_filename(argv[1]);
    const std::string output_filename(argv[2]);

    try {
        std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(input_filename));
        std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(output_filename));

        std::set<std::string> control_numbers;
        for (int arg_no(3); arg_no < argc; ++arg_no)
            control_numbers.emplace(argv[arg_no]);

        ProcessRecords(quiet, max_no_of_records, marc_reader.get(), marc_writer.get(), control_numbers);
    } catch (const std::exception &e) {
        LOG_ERROR("Caught exception: " + std::string(e.what()));
    }
}
<|endoftext|>


<commit_before>/*
    open source routing machine
    Copyright (C) Dennis Luxen, 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
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 Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
or see http://www.gnu.org/licenses/agpl.txt.
 */

#define VERBOSE(x) x
#define VERBOSE2(x)

#ifdef NDEBUG
#undef VERBOSE
#undef VERBOSE2
#endif

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <luabind/luabind.hpp>

#include <boost/foreach.hpp>

#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>

#include "Algorithms/IteratorBasedCRC32.h"
#include "Util/OpenMPWrapper.h"
#include "typedefs.h"
#include "Contractor/Contractor.h"
#include "Contractor/EdgeBasedGraphFactory.h"
#include "DataStructures/BinaryHeap.h"
#include "DataStructures/DeallocatingVector.h"
#include "DataStructures/NNGrid.h"
#include "DataStructures/QueryEdge.h"
#include "Util/BaseConfiguration.h"
#include "Util/InputFileUtil.h"
#include "Util/GraphLoader.h"

using namespace std;

typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
typedef BaseConfiguration ContractorConfiguration;

std::vector<NodeInfo> internalToExternalNodeMapping;
std::vector<_Restriction> inputRestrictions;
std::vector<NodeID> bollardNodes;
std::vector<NodeID> trafficLightNodes;

int main (int argc, char *argv[]) {
    if(argc < 3) {
        ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
    }

    double startupTime = get_timestamp();
    unsigned numberOfThreads = omp_get_num_procs();
    std::string SRTM_ROOT;
    if(testDataFile("contractor.ini")) {
        ContractorConfiguration contractorConfig("contractor.ini");
        if(atoi(contractorConfig.GetParameter("Threads").c_str()) != 0 && (unsigned)atoi(contractorConfig.GetParameter("Threads").c_str()) <= numberOfThreads)
            numberOfThreads = (unsigned)atoi( contractorConfig.GetParameter("Threads").c_str() );
        if(0 < contractorConfig.GetParameter("SRTM").size() )
            SRTM_ROOT = contractorConfig.GetParameter("SRTM");
    }
    if(0 != SRTM_ROOT.size())
        INFO("Loading SRTM from/to " << SRTM_ROOT);
    omp_set_num_threads(numberOfThreads);

    INFO("Using restrictions from file: " << argv[2]);
    std::ifstream restrictionsInstream(argv[2], ios::binary);
    if(!restrictionsInstream.good()) {
        ERR("Could not access <osrm-restrictions> files");
    }
    _Restriction restriction;
    unsigned usableRestrictionsCounter(0);
    restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
    inputRestrictions.resize(usableRestrictionsCounter);
    restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
    restrictionsInstream.close();

    std::ifstream in;
    in.open (argv[1], std::ifstream::in | std::ifstream::binary);
    if (!in.is_open()) {
        ERR("Cannot open " << argv[1]);
    }

    char nodeOut[1024];         strcpy(nodeOut, argv[1]);           strcat(nodeOut, ".nodes");
    char edgeOut[1024];         strcpy(edgeOut, argv[1]);           strcat(edgeOut, ".edges");
    char graphOut[1024];    	strcpy(graphOut, argv[1]);      	strcat(graphOut, ".hsgr");
    char ramIndexOut[1024];    	strcpy(ramIndexOut, argv[1]);    	strcat(ramIndexOut, ".ramIndex");
    char fileIndexOut[1024];    strcpy(fileIndexOut, argv[1]);    	strcat(fileIndexOut, ".fileIndex");
    char levelInfoOut[1024];    strcpy(levelInfoOut, argv[1]);    	strcat(levelInfoOut, ".levels");

    std::vector<ImportEdge> edgeList;
    NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
    in.close();
    INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");

    if(!testDataFile("profile.lua")) {
        ERR("Need profile.lua to apply traffic signal penalty");
    }
    /*** Setup Scripting Environment ***/

    // Create a new lua state
    lua_State *myLuaState = luaL_newstate();

    // Connect LuaBind to this lua state
    luabind::open(myLuaState);

    // Now call our function in a lua script
    if(0 != luaL_dofile(myLuaState, "profile.lua")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }

    EdgeBasedGraphFactory::SpeedProfileProperties speedProfile;

    if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }
    speedProfile.trafficSignalPenalty = lua_tointeger(myLuaState, -1);

    if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }
    speedProfile.uTurnPenalty = lua_tointeger(myLuaState, -1);

    /***
     * Building an edge-expanded graph from node-based input an turn restrictions
     */

    INFO("Generating edge-expanded graph representation");
    EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
    std::vector<ImportEdge>().swap(edgeList);
    edgeBasedGraphFactory->Run(edgeOut);
    std::vector<_Restriction>().swap(inputRestrictions);
    std::vector<NodeID>().swap(bollardNodes);
    std::vector<NodeID>().swap(trafficLightNodes);
    NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
    DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
    edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
    if(0 == edgeBasedEdgeList.size())
        ERR("The input data is broken. It is impossible to do any turns in this graph");

    /***
     * Writing info on original (node-based) nodes
     */

    INFO("writing node map ...");
    std::ofstream mapOutFile(nodeOut, std::ios::binary);
    mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
    mapOutFile.close();
    std::vector<NodeInfo>().swap(internalToExternalNodeMapping);

    /***
     * Writing info on original (node-based) edges
     */
    INFO("writing info on original edges");
    std::vector<OriginalEdgeData> originalEdgeData;
    edgeBasedGraphFactory->GetOriginalEdgeData(originalEdgeData);

//    std::ofstream oedOutFile(edgeOut, std::ios::binary);
//    unsigned numberOfOrigEdges = originalEdgeData.size();
//    oedOutFile.write((char*)&numberOfOrigEdges, sizeof(unsigned));
//    oedOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
//    oedOutFile.close();
//    std::vector<OriginalEdgeData>().swap(originalEdgeData);

    DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
    edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
    delete edgeBasedGraphFactory;
    double expansionHasFinishedTime = get_timestamp() - startupTime;

    /***
     * Building grid-like nearest-neighbor data structure
     */

    INFO("building grid ...");
    WritableGrid * writeableGrid = new WritableGrid();
    writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut, fileIndexOut);
    delete writeableGrid;
    IteratorbasedCRC32<DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
    unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
    nodeBasedEdgeList.clear();
    INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList);

    /***
     * Contracting the edge-expanded graph
     */

    INFO("initializing contractor");
    Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList );
    double contractionStartedTimestamp(get_timestamp());
    contractor->Run();
    INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");

    DeallocatingVector< QueryEdge > contractedEdgeList;
    contractor->GetEdges( contractedEdgeList );
    delete contractor;

    /***
     * Sorting contracted edges in a way that the static query graph can read some in in-place.
     */

    INFO("Building Node Array");
    sort(contractedEdgeList.begin(), contractedEdgeList.end());
    unsigned numberOfNodes = 0;
    unsigned numberOfEdges = contractedEdgeList.size();
    INFO("Serializing compacted graph");
    ofstream edgeOutFile(graphOut, ios::binary);

    BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) {
        if(edge.source > numberOfNodes) {
            numberOfNodes = edge.source;
        }
        if(edge.target > numberOfNodes) {
            numberOfNodes = edge.target;
        }
    }
    numberOfNodes+=1;

    std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
    _nodes.resize( numberOfNodes + 1 );

    StaticGraph<EdgeData>::EdgeIterator edge = 0;
    StaticGraph<EdgeData>::EdgeIterator position = 0;
    for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
        StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
        while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
            ++edge;
        _nodes[node].firstEdge = position; //=edge
        position += edge - lastEdge; //remove
    }
    ++numberOfNodes;
    //Serialize numberOfNodes, nodes
    edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
    edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
    edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
    //Serialize number of Edges
    edgeOutFile.write((char*) &position, sizeof(unsigned));
    --numberOfNodes;
    edge = 0;
    int usedEdgeCounter = 0;
    StaticGraph<EdgeData>::_StrEdge currentEdge;
    for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
        for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
            assert(node != contractedEdgeList[edge].target);
            currentEdge.target = contractedEdgeList[edge].target;
            currentEdge.data = contractedEdgeList[edge].data;
            if(currentEdge.data.distance <= 0) {
                INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
                ERR("Failed at edges of node " << node << " of " << numberOfNodes);
            }
            //Serialize edges
            edgeOutFile.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
            ++edge;
            ++usedEdgeCounter;
        }
    }
    double endTime = (get_timestamp() - startupTime);
    INFO("Expansion  : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
    INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");

    edgeOutFile.close();
    //cleanedEdgeList.clear();
    _nodes.clear();
    INFO("finished preprocessing");
    return 0;
}
<commit_msg>Use seconds for penalties<commit_after>/*
    open source routing machine
    Copyright (C) Dennis Luxen, 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
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 Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
or see http://www.gnu.org/licenses/agpl.txt.
 */

#define VERBOSE(x) x
#define VERBOSE2(x)

#ifdef NDEBUG
#undef VERBOSE
#undef VERBOSE2
#endif

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <luabind/luabind.hpp>

#include <boost/foreach.hpp>

#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>

#include "Algorithms/IteratorBasedCRC32.h"
#include "Util/OpenMPWrapper.h"
#include "typedefs.h"
#include "Contractor/Contractor.h"
#include "Contractor/EdgeBasedGraphFactory.h"
#include "DataStructures/BinaryHeap.h"
#include "DataStructures/DeallocatingVector.h"
#include "DataStructures/NNGrid.h"
#include "DataStructures/QueryEdge.h"
#include "Util/BaseConfiguration.h"
#include "Util/InputFileUtil.h"
#include "Util/GraphLoader.h"

using namespace std;

typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
typedef BaseConfiguration ContractorConfiguration;

std::vector<NodeInfo> internalToExternalNodeMapping;
std::vector<_Restriction> inputRestrictions;
std::vector<NodeID> bollardNodes;
std::vector<NodeID> trafficLightNodes;

int main (int argc, char *argv[]) {
    if(argc < 3) {
        ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
    }

    double startupTime = get_timestamp();
    unsigned numberOfThreads = omp_get_num_procs();
    std::string SRTM_ROOT;
    if(testDataFile("contractor.ini")) {
        ContractorConfiguration contractorConfig("contractor.ini");
        if(atoi(contractorConfig.GetParameter("Threads").c_str()) != 0 && (unsigned)atoi(contractorConfig.GetParameter("Threads").c_str()) <= numberOfThreads)
            numberOfThreads = (unsigned)atoi( contractorConfig.GetParameter("Threads").c_str() );
        if(0 < contractorConfig.GetParameter("SRTM").size() )
            SRTM_ROOT = contractorConfig.GetParameter("SRTM");
    }
    if(0 != SRTM_ROOT.size())
        INFO("Loading SRTM from/to " << SRTM_ROOT);
    omp_set_num_threads(numberOfThreads);

    INFO("Using restrictions from file: " << argv[2]);
    std::ifstream restrictionsInstream(argv[2], ios::binary);
    if(!restrictionsInstream.good()) {
        ERR("Could not access <osrm-restrictions> files");
    }
    _Restriction restriction;
    unsigned usableRestrictionsCounter(0);
    restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
    inputRestrictions.resize(usableRestrictionsCounter);
    restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
    restrictionsInstream.close();

    std::ifstream in;
    in.open (argv[1], std::ifstream::in | std::ifstream::binary);
    if (!in.is_open()) {
        ERR("Cannot open " << argv[1]);
    }

    char nodeOut[1024];         strcpy(nodeOut, argv[1]);           strcat(nodeOut, ".nodes");
    char edgeOut[1024];         strcpy(edgeOut, argv[1]);           strcat(edgeOut, ".edges");
    char graphOut[1024];    	strcpy(graphOut, argv[1]);      	strcat(graphOut, ".hsgr");
    char ramIndexOut[1024];    	strcpy(ramIndexOut, argv[1]);    	strcat(ramIndexOut, ".ramIndex");
    char fileIndexOut[1024];    strcpy(fileIndexOut, argv[1]);    	strcat(fileIndexOut, ".fileIndex");
    char levelInfoOut[1024];    strcpy(levelInfoOut, argv[1]);    	strcat(levelInfoOut, ".levels");

    std::vector<ImportEdge> edgeList;
    NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
    in.close();
    INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");

    if(!testDataFile("profile.lua")) {
        ERR("Need profile.lua to apply traffic signal penalty");
    }
    /*** Setup Scripting Environment ***/

    // Create a new lua state
    lua_State *myLuaState = luaL_newstate();

    // Connect LuaBind to this lua state
    luabind::open(myLuaState);

    // Now call our function in a lua script
    if(0 != luaL_dofile(myLuaState, "profile.lua")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }

    EdgeBasedGraphFactory::SpeedProfileProperties speedProfile;

    if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }
    speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1);

    if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
        ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
    }
    speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);

    /***
     * Building an edge-expanded graph from node-based input an turn restrictions
     */

    INFO("Generating edge-expanded graph representation");
    EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
    std::vector<ImportEdge>().swap(edgeList);
    edgeBasedGraphFactory->Run(edgeOut);
    std::vector<_Restriction>().swap(inputRestrictions);
    std::vector<NodeID>().swap(bollardNodes);
    std::vector<NodeID>().swap(trafficLightNodes);
    NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
    DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
    edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
    if(0 == edgeBasedEdgeList.size())
        ERR("The input data is broken. It is impossible to do any turns in this graph");

    /***
     * Writing info on original (node-based) nodes
     */

    INFO("writing node map ...");
    std::ofstream mapOutFile(nodeOut, std::ios::binary);
    mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
    mapOutFile.close();
    std::vector<NodeInfo>().swap(internalToExternalNodeMapping);

    /***
     * Writing info on original (node-based) edges
     */
    INFO("writing info on original edges");
    std::vector<OriginalEdgeData> originalEdgeData;
    edgeBasedGraphFactory->GetOriginalEdgeData(originalEdgeData);

//    std::ofstream oedOutFile(edgeOut, std::ios::binary);
//    unsigned numberOfOrigEdges = originalEdgeData.size();
//    oedOutFile.write((char*)&numberOfOrigEdges, sizeof(unsigned));
//    oedOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
//    oedOutFile.close();
//    std::vector<OriginalEdgeData>().swap(originalEdgeData);

    DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
    edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
    delete edgeBasedGraphFactory;
    double expansionHasFinishedTime = get_timestamp() - startupTime;

    /***
     * Building grid-like nearest-neighbor data structure
     */

    INFO("building grid ...");
    WritableGrid * writeableGrid = new WritableGrid();
    writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut, fileIndexOut);
    delete writeableGrid;
    IteratorbasedCRC32<DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
    unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
    nodeBasedEdgeList.clear();
    INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList);

    /***
     * Contracting the edge-expanded graph
     */

    INFO("initializing contractor");
    Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList );
    double contractionStartedTimestamp(get_timestamp());
    contractor->Run();
    INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");

    DeallocatingVector< QueryEdge > contractedEdgeList;
    contractor->GetEdges( contractedEdgeList );
    delete contractor;

    /***
     * Sorting contracted edges in a way that the static query graph can read some in in-place.
     */

    INFO("Building Node Array");
    sort(contractedEdgeList.begin(), contractedEdgeList.end());
    unsigned numberOfNodes = 0;
    unsigned numberOfEdges = contractedEdgeList.size();
    INFO("Serializing compacted graph");
    ofstream edgeOutFile(graphOut, ios::binary);

    BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) {
        if(edge.source > numberOfNodes) {
            numberOfNodes = edge.source;
        }
        if(edge.target > numberOfNodes) {
            numberOfNodes = edge.target;
        }
    }
    numberOfNodes+=1;

    std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
    _nodes.resize( numberOfNodes + 1 );

    StaticGraph<EdgeData>::EdgeIterator edge = 0;
    StaticGraph<EdgeData>::EdgeIterator position = 0;
    for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
        StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
        while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
            ++edge;
        _nodes[node].firstEdge = position; //=edge
        position += edge - lastEdge; //remove
    }
    ++numberOfNodes;
    //Serialize numberOfNodes, nodes
    edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
    edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
    edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
    //Serialize number of Edges
    edgeOutFile.write((char*) &position, sizeof(unsigned));
    --numberOfNodes;
    edge = 0;
    int usedEdgeCounter = 0;
    StaticGraph<EdgeData>::_StrEdge currentEdge;
    for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
        for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
            assert(node != contractedEdgeList[edge].target);
            currentEdge.target = contractedEdgeList[edge].target;
            currentEdge.data = contractedEdgeList[edge].data;
            if(currentEdge.data.distance <= 0) {
                INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
                ERR("Failed at edges of node " << node << " of " << numberOfNodes);
            }
            //Serialize edges
            edgeOutFile.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
            ++edge;
            ++usedEdgeCounter;
        }
    }
    double endTime = (get_timestamp() - startupTime);
    INFO("Expansion  : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
    INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");

    edgeOutFile.close();
    //cleanedEdgeList.clear();
    _nodes.clear();
    INFO("finished preprocessing");
    return 0;
}
<|endoftext|>