<commit_before>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

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

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

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

#include <config-gpgme++.h>

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cerrno>
#include <cstring>

using namespace GpgME;

static const char * status_to_string( unsigned int status );
static Error status_to_error( unsigned int status );

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, size_t count ) {
        size_t toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err = status_to_error( status );

        if ( !err ) {

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
                              oldState, status_to_string(status), args ? args : "<null>", ei->state );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result ) {
                        errno = 0;
                        if ( writeAll( fd, result, std::strlen( result ) ) != std::strlen( result ) ) {
                            err = Error( gpg_error_from_syserror() );
                            if ( ei->debug )
                                std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                            goto error;
                        }
                    }
                    errno = 0;
                    if ( writeAll( fd, "\n", 1 ) != 1 ) {
                        err = Error( gpg_error_from_syserror() );
                        if ( ei->debug )
                            std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                        goto error;
                    }
                } else {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: no action result\n" );
                }
            } else {
                if ( ei->debug )
                    std::fprintf( ei->debug, "EditInteractor: no action executed\n" );
            }
        }

    error:
        if ( err ) {
            ei->error = err;
            ei->state = EditInteractor::ErrorState;
        }

        if ( ei->debug )
            std::fprintf( ei->debug, "EditInteractor: error now %u (%s)\n",
                          ei->error.encodedError(), gpg_strerror( ei->error.encodedError() ) );

        return ei->error.encodedError();
    }
};

static gpgme_error_t edit_interactor_callback( void * opaque, gpgme_status_code_t status, const char * args, int fd )
{
    return CallbackHelper::edit_interactor_callback_impl( opaque, status, args, fd );
}

gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;

EditInteractor::Private::Private( EditInteractor * qq )
    : q( qq ),
      state( StartState ),
      error(),
      debug(0)
{

}

EditInteractor::Private::~Private() {}

EditInteractor::EditInteractor()
    : d( new Private( this ) )
{

}

EditInteractor::~EditInteractor() {
    delete d; d = 0;
}

unsigned int EditInteractor::state() const {
    return d->state;
}

Error EditInteractor::lastError() const {
    return d->error;
}

bool EditInteractor::needsNoResponse( unsigned int status ) const {
    switch ( status ) {
    case GPGME_STATUS_EOF:
    case GPGME_STATUS_GOT_IT:
    case GPGME_STATUS_NEED_PASSPHRASE:
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
    case GPGME_STATUS_GOOD_PASSPHRASE:
    case GPGME_STATUS_BAD_PASSPHRASE:
    case GPGME_STATUS_USERID_HINT:
    case GPGME_STATUS_SIGEXPIRED:
    case GPGME_STATUS_KEYEXPIRED:
        return true;
    default:
        return false;
    }
}

// static
Error status_to_error( unsigned int status ) {
    switch ( status ) {
    case GPGME_STATUS_MISSING_PASSPHRASE:
        return Error( gpg_error( GPG_ERR_NO_PASSPHRASE ) );
    case GPGME_STATUS_ALREADY_SIGNED:
        return Error( gpg_error( GPG_ERR_ALREADY_SIGNED ) );
    }
    return Error();
}

void EditInteractor::setDebugChannel( std::FILE * debug ) {
    d->debug = debug;
}

static const char * status_strings[] = {
    "EOF",
    /* mkstatus processing starts here */
    "ENTER",
    "LEAVE",
    "ABORT",

    "GOODSIG",
    "BADSIG",
    "ERRSIG",

    "BADARMOR",

    "RSA_OR_IDEA",
    "KEYEXPIRED",
    "KEYREVOKED",

    "TRUST_UNDEFINED",
    "TRUST_NEVER",
    "TRUST_MARGINAL",
    "TRUST_FULLY",
    "TRUST_ULTIMATE",

    "SHM_INFO",
    "SHM_GET",
    "SHM_GET_BOOL",
    "SHM_GET_HIDDEN",

    "NEED_PASSPHRASE",
    "VALIDSIG",
    "SIG_ID",
    "ENC_TO",
    "NODATA",
    "BAD_PASSPHRASE",
    "NO_PUBKEY",
    "NO_SECKEY",
    "NEED_PASSPHRASE_SYM",
    "DECRYPTION_FAILED",
    "DECRYPTION_OKAY",
    "MISSING_PASSPHRASE",
    "GOOD_PASSPHRASE",
    "GOODMDC",
    "BADMDC",
    "ERRMDC",
    "IMPORTED",
    "IMPORT_OK",
    "IMPORT_PROBLEM",
    "IMPORT_RES",
    "FILE_START",
    "FILE_DONE",
    "FILE_ERROR",

    "BEGIN_DECRYPTION",
    "END_DECRYPTION",
    "BEGIN_ENCRYPTION",
    "END_ENCRYPTION",

    "DELETE_PROBLEM",
    "GET_BOOL",
    "GET_LINE",
    "GET_HIDDEN",
    "GOT_IT",
    "PROGRESS",
    "SIG_CREATED",
    "SESSION_KEY",
    "NOTATION_NAME",
    "NOTATION_DATA",
    "POLICY_URL",
    "BEGIN_STREAM",
    "END_STREAM",
    "KEY_CREATED",
    "USERID_HINT",
    "UNEXPECTED",
    "INV_RECP",
    "NO_RECP",
    "ALREADY_SIGNED",
    "SIGEXPIRED",
    "EXPSIG",
    "EXPKEYSIG",
    "TRUNCATED",
    "ERROR",
    "NEWSIG",
    "REVKEYSIG",
    "SIG_SUBPACKET",
    "NEED_PASSPHRASE_PIN",
    "SC_OP_FAILURE",
    "SC_OP_SUCCESS",
    "CARDCTRL",
    "BACKUP_KEY_CREATED",
    "PKA_TRUST_BAD",
    "PKA_TRUST_GOOD",

    "PLAINTEXT",
};
static const unsigned int num_status_strings = sizeof status_strings / sizeof *status_strings ;

const char * status_to_string( unsigned int idx ) {
    if ( idx < num_status_strings )
        return status_strings[idx];
    else
        return "(unknown)";
}
<commit_msg>Backport r883814 by tmcguire from trunk to the 4.1 branch:<commit_after>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

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

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

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

#include <config-gpgme++.h>

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cerrno>
#include <cstring>

using namespace GpgME;

static const char * status_to_string( unsigned int status );
static Error status_to_error( unsigned int status );

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, size_t count ) {
        size_t toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err = status_to_error( status );

        if ( !err ) {

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
                              oldState, status_to_string(status), args ? args : "<null>", ei->state );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result ) {
                        errno = 0;
                        if ( writeAll( fd, result, std::strlen( result ) ) != std::strlen( result ) ) {
                            err = Error( gpg_error_from_syserror() );
                            if ( ei->debug )
                                std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                            goto error;
                        }
                    }
                    errno = 0;
                    if ( writeAll( fd, "\n", 1 ) != 1 ) {
                        err = Error( gpg_error_from_syserror() );
                        if ( ei->debug )
                            std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                        goto error;
                    }
                } else {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: no action result\n" );
                }
            } else {
                if ( ei->debug )
                    std::fprintf( ei->debug, "EditInteractor: no action executed\n" );
            }
        }

    error:
        if ( err ) {
            ei->error = err;
            ei->state = EditInteractor::ErrorState;
        }

        if ( ei->debug )
            std::fprintf( ei->debug, "EditInteractor: error now %u (%s)\n",
                          ei->error.encodedError(), gpg_strerror( ei->error.encodedError() ) );

        return ei->error.encodedError();
    }
};

static gpgme_error_t edit_interactor_callback( void * opaque, gpgme_status_code_t status, const char * args, int fd )
{
    return CallbackHelper::edit_interactor_callback_impl( opaque, status, args, fd );
}

gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;

EditInteractor::Private::Private( EditInteractor * qq )
    : q( qq ),
      state( StartState ),
      error(),
      debug(0)
{

}

EditInteractor::Private::~Private() {}

EditInteractor::EditInteractor()
    : d( new Private( this ) )
{

}

EditInteractor::~EditInteractor() {
    delete d; d = 0;
}

unsigned int EditInteractor::state() const {
    return d->state;
}

Error EditInteractor::lastError() const {
    return d->error;
}

bool EditInteractor::needsNoResponse( unsigned int status ) const {
    switch ( status ) {
    case GPGME_STATUS_EOF:
    case GPGME_STATUS_GOT_IT:
    case GPGME_STATUS_NEED_PASSPHRASE:
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
    case GPGME_STATUS_GOOD_PASSPHRASE:
    case GPGME_STATUS_BAD_PASSPHRASE:
    case GPGME_STATUS_USERID_HINT:
    case GPGME_STATUS_SIGEXPIRED:
    case GPGME_STATUS_KEYEXPIRED:
        return true;
    default:
        return false;
    }
}

// static
Error status_to_error( unsigned int status ) {
    switch ( status ) {
    case GPGME_STATUS_MISSING_PASSPHRASE:
        return Error( gpg_error( GPG_ERR_NO_PASSPHRASE ) );
    case GPGME_STATUS_ALREADY_SIGNED:
        return Error( gpg_error( GPG_ERR_ALREADY_SIGNED ) );
    case GPGME_STATUS_KEYEXPIRED:
        return Error( gpg_error( GPG_ERR_CERT_EXPIRED ) );
    case GPGME_STATUS_SIGEXPIRED:
        return Error( gpg_error( GPG_ERR_SIG_EXPIRED ) );
    }
    return Error();
}

void EditInteractor::setDebugChannel( std::FILE * debug ) {
    d->debug = debug;
}

static const char * status_strings[] = {
    "EOF",
    /* mkstatus processing starts here */
    "ENTER",
    "LEAVE",
    "ABORT",

    "GOODSIG",
    "BADSIG",
    "ERRSIG",

    "BADARMOR",

    "RSA_OR_IDEA",
    "KEYEXPIRED",
    "KEYREVOKED",

    "TRUST_UNDEFINED",
    "TRUST_NEVER",
    "TRUST_MARGINAL",
    "TRUST_FULLY",
    "TRUST_ULTIMATE",

    "SHM_INFO",
    "SHM_GET",
    "SHM_GET_BOOL",
    "SHM_GET_HIDDEN",

    "NEED_PASSPHRASE",
    "VALIDSIG",
    "SIG_ID",
    "ENC_TO",
    "NODATA",
    "BAD_PASSPHRASE",
    "NO_PUBKEY",
    "NO_SECKEY",
    "NEED_PASSPHRASE_SYM",
    "DECRYPTION_FAILED",
    "DECRYPTION_OKAY",
    "MISSING_PASSPHRASE",
    "GOOD_PASSPHRASE",
    "GOODMDC",
    "BADMDC",
    "ERRMDC",
    "IMPORTED",
    "IMPORT_OK",
    "IMPORT_PROBLEM",
    "IMPORT_RES",
    "FILE_START",
    "FILE_DONE",
    "FILE_ERROR",

    "BEGIN_DECRYPTION",
    "END_DECRYPTION",
    "BEGIN_ENCRYPTION",
    "END_ENCRYPTION",

    "DELETE_PROBLEM",
    "GET_BOOL",
    "GET_LINE",
    "GET_HIDDEN",
    "GOT_IT",
    "PROGRESS",
    "SIG_CREATED",
    "SESSION_KEY",
    "NOTATION_NAME",
    "NOTATION_DATA",
    "POLICY_URL",
    "BEGIN_STREAM",
    "END_STREAM",
    "KEY_CREATED",
    "USERID_HINT",
    "UNEXPECTED",
    "INV_RECP",
    "NO_RECP",
    "ALREADY_SIGNED",
    "SIGEXPIRED",
    "EXPSIG",
    "EXPKEYSIG",
    "TRUNCATED",
    "ERROR",
    "NEWSIG",
    "REVKEYSIG",
    "SIG_SUBPACKET",
    "NEED_PASSPHRASE_PIN",
    "SC_OP_FAILURE",
    "SC_OP_SUCCESS",
    "CARDCTRL",
    "BACKUP_KEY_CREATED",
    "PKA_TRUST_BAD",
    "PKA_TRUST_GOOD",

    "PLAINTEXT",
};
static const unsigned int num_status_strings = sizeof status_strings / sizeof *status_strings ;

const char * status_to_string( unsigned int idx ) {
    if ( idx < num_status_strings )
        return status_strings[idx];
    else
        return "(unknown)";
}
<|endoftext|>


<commit_before>#include <fstream>
#include <cstdio>
#include <ctype.h>

#include <metaObject.h>

int main(int argc, char **argv)
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  float orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 1);
  tObj.ElementSpacing(2, 1);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  if(tObj.Position(0) != 4)
    {
    std::cout << "Position: FAIL" << std::endl;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing(0) != 2)
    {
    std::cout << "ElementSpacing: FAIL" << std::endl;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  return 1;
  }
<commit_msg>BUG: Resolved ambiguous argument of 0 versus NULL<commit_after>#include <fstream>
#include <cstdio>
#include <ctype.h>

#include <metaObject.h>

int main(int argc, char **argv)
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  float orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 1);
  tObj.ElementSpacing(2, 1);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  if(tObj.Position((int)0) != 4)
    {
    std::cout << "Position: FAIL" << std::endl;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing((int)0) != 2)
    {
    std::cout << "ElementSpacing: FAIL" << std::endl;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  return 1;
  }
<|endoftext|>


<commit_before>#include <vector>
#include <gtest/gtest.h>
#include "../../main/gradient_computers/GradientComputer.h"
#include "../../main/objectives/ObjectiveMSE.h"
#include "../../main/objectives/ObjectiveBPR.h"
#include <typeinfo>

namespace {

  class DummyModel : public Model {
    public:
      DummyModel(){
        for(int i=1; i<=5; i++){predictions.push_back(0.1*i);}
        predictVal = predictions.begin();
      }
      void update() {
        predictVal++;
        if(predictVal==predictions.end()) predictVal=predictions.begin();
      }
      void add(RecDat* rec_dat) override {
        add_calls.push_back(make_pair(prediction_calls.size(),rec_dat));
      }
      double prediction(RecDat* rec_dat) override {
        prediction_calls.push_back(rec_dat);
        return (*predictVal)*(rec_dat->item);
      }
      vector<double> predictions;
      vector<double>::iterator predictVal;
      vector<RecDat*> prediction_calls;
      vector<pair<int,RecDat*>> add_calls;
  };

  class DummyModelGradientUpdater : public ModelGradientUpdater {
    public:
      void update(RecDat* recDat, double gradient) override {
        model->update();
        gradientData.push_back(make_pair(recDat,gradient));
      }
      void message(UpdaterMessage message) override {
        message_calls.push_back(message);
      }
      vector<pair<RecDat*,double>> gradientData;
      vector<UpdaterMessage> message_calls;
      void set_model(DummyModel* model_){model = model_;}
      DummyModel* model;
  };

  class DummyObjective : public ObjectivePointWise {
    double get_gradient(RecPred *rec_pred) override { return rec_pred->score+rec_pred->prediction; }
  };

  class TestGradientComputer : public ::testing::Test  {
    public:
      DummyModel model;
      DummyModelGradientUpdater updater;
      GradientComputerPointWise gradient_computer;
      DummyObjective objective;

      vector<RecDat*> recDats;
      TestGradientComputer() {
      }
      virtual ~TestGradientComputer() {
        // You can do clean-up work that doesn't throw exceptions here.
      }
      void SetUp() override {
        updater.set_model(&model);
        gradient_computer.add_gradient_updater(&updater);
        gradient_computer.set_objective(&objective);
        gradient_computer.set_model(&model);
        gradient_computer.set_objective(&objective);
      }
      void TearDown() override {
        for (vector<RecDat*>::iterator it = recDats.begin();it!=recDats.end();it++){
          delete *it;
        }
      }
      RecDat* create_rec_dat(int user, int item, double time, double score){
        RecDat* recDat = new RecDat;
        recDat -> user = user;
        recDat -> item = item;
        recDat -> time = time;
        recDat -> score = score;
        recDats.push_back(recDat);
        return recDat;
      }
  };
}

TEST_F(TestGradientComputer, message) {
  EXPECT_TRUE(gradient_computer.self_test());
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  ASSERT_EQ(6,updater.message_calls.size());
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[0]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[1]);
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[2]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[3]);
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[4]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[5]);
}
TEST_F(TestGradientComputer, update) {
  RecDat* rec_dat = create_rec_dat(1,5,11,1.0); //user=1,item=5,time=11,score=1.0
  gradient_computer.update(rec_dat);
  ASSERT_EQ(1,model.add_calls.size());
  EXPECT_EQ(0,model.add_calls[0].first); //the add call should happen before the prediction call
  ASSERT_EQ(1,model.prediction_calls.size());
  EXPECT_EQ(rec_dat,model.prediction_calls[0]);
  ASSERT_EQ(1,updater.gradientData.size());
  EXPECT_DOUBLE_EQ(5*0.1+1.0,updater.gradientData[0].second);
  rec_dat = create_rec_dat(3,2,12,1.0); //user=3,item=2,time=12,score=1.0
  gradient_computer.update(rec_dat);
  ASSERT_EQ(2,model.add_calls.size());
  EXPECT_EQ(1,model.add_calls[1].first); //the add call should happen before the prediction call
  ASSERT_EQ(2,model.prediction_calls.size());
  EXPECT_EQ(rec_dat,model.prediction_calls[1]);
  ASSERT_EQ(2,updater.gradientData.size());
  EXPECT_DOUBLE_EQ(2*0.2+1.0,updater.gradientData[1].second);
}

// TEST_F(TestGradientComputer, pairwise) {
//   gradient_computer = new GradientComputerImplicitPairWise(&objectiveBPR);
//   gradient_computer->set_model(&model);
//   learner.set_gradient_computer(gradient_computer);

//   learner.learn(create_rec_dat(1,5,1.1,1.0));
//   EXPECT_EQ(1,model.counter);
//   EXPECT_EQ(4,updater.counter);
//   ASSERT_EQ(4,model.gradientData.size());
//   double pred1 = 5*0.1/1;
//   double pred2 = 2*0.1/1;
//   double gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(5,model.gradientData[0].first->item);
//   EXPECT_EQ(1,model.gradientData[0].first->score);
//   EXPECT_EQ(1,model.gradientData[0].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[0].second);
//   EXPECT_EQ(2,model.gradientData[1].first->item);
//   EXPECT_EQ(0,model.gradientData[1].first->score);
//   EXPECT_EQ(1,model.gradientData[1].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[1].second);
//   pred1 = 5*0.1/3;
//   pred2 = 4*0.1/3;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(5,model.gradientData[2].first->item);
//   EXPECT_EQ(1,model.gradientData[2].first->score);
//   EXPECT_EQ(1,model.gradientData[2].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[2].second);
//   EXPECT_EQ(4,model.gradientData[3].first->item);
//   EXPECT_EQ(0,model.gradientData[3].first->score);
//   EXPECT_EQ(1,model.gradientData[3].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[3].second);
//   EXPECT_DOUBLE_EQ(1*0.1/5,model.prediction(create_rec_dat(1,1,1.1,1.0)));
//   learner.learn(create_rec_dat(2,1,1.1,1.0));
//   EXPECT_EQ(2,model.counter);
//   EXPECT_EQ(8,updater.counter);
//   ASSERT_EQ(8,model.gradientData.size());
//   pred1 = 1*0.1/5;
//   pred2 = 2*0.1/5;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(1,model.gradientData[4].first->item);
//   EXPECT_EQ(1,model.gradientData[4].first->score);
//   EXPECT_EQ(2,model.gradientData[4].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[4].second);
//   EXPECT_EQ(2,model.gradientData[5].first->item);
//   EXPECT_EQ(0,model.gradientData[5].first->score);
//   EXPECT_EQ(2,model.gradientData[5].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[5].second);
//   pred1 = 1*0.1/2;
//   pred2 = 4*0.1/2;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(1,model.gradientData[6].first->item);
//   EXPECT_EQ(1,model.gradientData[6].first->score);
//   EXPECT_EQ(2,model.gradientData[6].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[6].second);
//   EXPECT_EQ(4,model.gradientData[7].first->item);
//   EXPECT_EQ(0,model.gradientData[7].first->score);
//   EXPECT_EQ(2,model.gradientData[7].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[7].second);
//   EXPECT_DOUBLE_EQ(3*0.1/4,model.prediction(create_rec_dat(1,3,1.1,1.0)));
// }

// TEST_F(TestGradientComputer, listwise) {
//   gradient_computer = new GradientComputerListWise(&objectiveDummyListWise);
//   gradient_computer->set_model(&model);
//   learner.set_gradient_computer(gradient_computer);

//   learner.learn(create_rec_dat(1,5,1.1,1.0));
//   EXPECT_EQ(1,model.counter);
//   EXPECT_EQ(3,updater.counter);
//   ASSERT_EQ(3,model.gradientData.size());
//   EXPECT_EQ(5,model.gradientData[0].first->item);
//   EXPECT_EQ(1,model.gradientData[0].first->score);
//   EXPECT_EQ(1,model.gradientData[0].first->user);
//   EXPECT_DOUBLE_EQ((5*0.1/1-1.0)*1,model.gradientData[0].second);
//   EXPECT_EQ(2,model.gradientData[1].first->item);
//   EXPECT_EQ(0,model.gradientData[1].first->score);
//   EXPECT_EQ(1,model.gradientData[1].first->user);
//   EXPECT_DOUBLE_EQ((2*0.1/1-0.0)*2,model.gradientData[1].second);
//   EXPECT_EQ(4,model.gradientData[2].first->item);
//   EXPECT_EQ(0,model.gradientData[2].first->score);
//   EXPECT_EQ(1,model.gradientData[2].first->user);
//   EXPECT_DOUBLE_EQ((4*0.1/1-0.0)*3,model.gradientData[2].second);
//   EXPECT_DOUBLE_EQ(1*0.1/4,model.prediction(create_rec_dat(1,1,1.1,1.0)));
//   learner.learn(create_rec_dat(2,1,1.1,1.0));
//   EXPECT_EQ(2,model.counter);
//   EXPECT_EQ(6,updater.counter);
//   ASSERT_EQ(6,model.gradientData.size());
//   EXPECT_EQ(1,model.gradientData[3].first->item);
//   EXPECT_EQ(1,model.gradientData[3].first->score);
//   EXPECT_EQ(2,model.gradientData[3].first->user);
//   EXPECT_DOUBLE_EQ((1*0.1/4-1.0)*1,model.gradientData[3].second);
//   EXPECT_EQ(2,model.gradientData[4].first->item);
//   EXPECT_EQ(0,model.gradientData[4].first->score);
//   EXPECT_EQ(2,model.gradientData[4].first->user);
//   EXPECT_DOUBLE_EQ((2*0.1/4-0.0)*2,model.gradientData[4].second);
//   EXPECT_EQ(4,model.gradientData[5].first->item);
//   EXPECT_EQ(0,model.gradientData[5].first->score);
//   EXPECT_EQ(2,model.gradientData[5].first->user);
//   EXPECT_DOUBLE_EQ((4*0.1/4-0.0)*3,model.gradientData[5].second);
//   EXPECT_DOUBLE_EQ(3*0.1/2,model.prediction(create_rec_dat(1,3,1.1,1.0)));
// }
// TEST_F(TestOfflineGradientComputerPointWise, pointwise) {
//   //EXPECT_FALSE(gradient_computer_.selfTest());
//   gradient_computer_.set_model(&model_);
//   gradient_computer_.set_objective(&objective_);
//   //EXPECT_TRUE(gradient_computer_.selfTest());
//   double gradient = gradient_computer_.get_gradient(create_rec_dat(1,2,3.0,5.0));
//   EXPECT_DOUBLE_EQ(1+2+5.0, gradient);
//   EXPECT_EQ(0,model_.counter_);
// }

int main (int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<commit_msg>add destructor test coverage<commit_after>#include <vector>
#include <gtest/gtest.h>
#include "../../main/gradient_computers/GradientComputer.h"
#include "../../main/objectives/ObjectiveMSE.h"
#include "../../main/objectives/ObjectiveBPR.h"
#include <typeinfo>

namespace {

  class DummyModel : public Model {
    public:
      DummyModel(){
        for(int i=1; i<=5; i++){predictions.push_back(0.1*i);}
        predictVal = predictions.begin();
      }
      void update() {
        predictVal++;
        if(predictVal==predictions.end()) predictVal=predictions.begin();
      }
      void add(RecDat* rec_dat) override {
        add_calls.push_back(make_pair(prediction_calls.size(),rec_dat));
      }
      double prediction(RecDat* rec_dat) override {
        prediction_calls.push_back(rec_dat);
        return (*predictVal)*(rec_dat->item);
      }
      vector<double> predictions;
      vector<double>::iterator predictVal;
      vector<RecDat*> prediction_calls;
      vector<pair<int,RecDat*>> add_calls;
  };

  class DummyModelGradientUpdater : public ModelGradientUpdater {
    public:
      void update(RecDat* recDat, double gradient) override {
        model->update();
        gradientData.push_back(make_pair(recDat,gradient));
      }
      void message(UpdaterMessage message) override {
        message_calls.push_back(message);
      }
      vector<pair<RecDat*,double>> gradientData;
      vector<UpdaterMessage> message_calls;
      void set_model(DummyModel* model_){model = model_;}
      DummyModel* model;
  };

  class DummyObjective : public ObjectivePointWise {
    double get_gradient(RecPred *rec_pred) override { return rec_pred->score+rec_pred->prediction; }
  };

  class TestGradientComputer : public ::testing::Test  {
    public:
      DummyModel model;
      DummyModelGradientUpdater updater;
      GradientComputerPointWise gradient_computer;
      DummyObjective objective;

      vector<RecDat*> recDats;
      TestGradientComputer() {
      }
      virtual ~TestGradientComputer() {
        // You can do clean-up work that doesn't throw exceptions here.
      }
      void SetUp() override {
        updater.set_model(&model);
        gradient_computer.add_gradient_updater(&updater);
        gradient_computer.set_objective(&objective);
        gradient_computer.set_model(&model);
        gradient_computer.set_objective(&objective);
      }
      void TearDown() override {
        for (vector<RecDat*>::iterator it = recDats.begin();it!=recDats.end();it++){
          delete *it;
        }
      }
      RecDat* create_rec_dat(int user, int item, double time, double score){
        RecDat* recDat = new RecDat;
        recDat -> user = user;
        recDat -> item = item;
        recDat -> time = time;
        recDat -> score = score;
        recDats.push_back(recDat);
        return recDat;
      }
  };
}

TEST_F(TestGradientComputer, message) {
  EXPECT_TRUE(gradient_computer.self_test());
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::start_of_implicit_update_cycle);
  gradient_computer.message(UpdaterMessage::end_of_implicit_update_cycle);
  ASSERT_EQ(6,updater.message_calls.size());
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[0]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[1]);
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[2]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[3]);
  EXPECT_EQ(UpdaterMessage::start_of_implicit_update_cycle,updater.message_calls[4]);
  EXPECT_EQ(UpdaterMessage::end_of_implicit_update_cycle,updater.message_calls[5]);
}
TEST_F(TestGradientComputer, update) {
  RecDat* rec_dat = create_rec_dat(1,5,11,1.0); //user=1,item=5,time=11,score=1.0
  gradient_computer.update(rec_dat);
  ASSERT_EQ(1,model.add_calls.size());
  EXPECT_EQ(0,model.add_calls[0].first); //the add call should happen before the prediction call
  ASSERT_EQ(1,model.prediction_calls.size());
  EXPECT_EQ(rec_dat,model.prediction_calls[0]);
  ASSERT_EQ(1,updater.gradientData.size());
  EXPECT_DOUBLE_EQ(5*0.1+1.0,updater.gradientData[0].second);
  rec_dat = create_rec_dat(3,2,12,1.0); //user=3,item=2,time=12,score=1.0
  gradient_computer.update(rec_dat);
  ASSERT_EQ(2,model.add_calls.size());
  EXPECT_EQ(1,model.add_calls[1].first); //the add call should happen before the prediction call
  ASSERT_EQ(2,model.prediction_calls.size());
  EXPECT_EQ(rec_dat,model.prediction_calls[1]);
  ASSERT_EQ(2,updater.gradientData.size());
  EXPECT_DOUBLE_EQ(2*0.2+1.0,updater.gradientData[1].second);
}
TEST_F(TestGradientComputer, destructor) {
  GradientComputerPointWise* gradient_computer =
      new GradientComputerPointWise;
  delete gradient_computer;
}

// TEST_F(TestGradientComputer, pairwise) {
//   gradient_computer = new GradientComputerImplicitPairWise(&objectiveBPR);
//   gradient_computer->set_model(&model);
//   learner.set_gradient_computer(gradient_computer);

//   learner.learn(create_rec_dat(1,5,1.1,1.0));
//   EXPECT_EQ(1,model.counter);
//   EXPECT_EQ(4,updater.counter);
//   ASSERT_EQ(4,model.gradientData.size());
//   double pred1 = 5*0.1/1;
//   double pred2 = 2*0.1/1;
//   double gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(5,model.gradientData[0].first->item);
//   EXPECT_EQ(1,model.gradientData[0].first->score);
//   EXPECT_EQ(1,model.gradientData[0].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[0].second);
//   EXPECT_EQ(2,model.gradientData[1].first->item);
//   EXPECT_EQ(0,model.gradientData[1].first->score);
//   EXPECT_EQ(1,model.gradientData[1].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[1].second);
//   pred1 = 5*0.1/3;
//   pred2 = 4*0.1/3;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(5,model.gradientData[2].first->item);
//   EXPECT_EQ(1,model.gradientData[2].first->score);
//   EXPECT_EQ(1,model.gradientData[2].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[2].second);
//   EXPECT_EQ(4,model.gradientData[3].first->item);
//   EXPECT_EQ(0,model.gradientData[3].first->score);
//   EXPECT_EQ(1,model.gradientData[3].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[3].second);
//   EXPECT_DOUBLE_EQ(1*0.1/5,model.prediction(create_rec_dat(1,1,1.1,1.0)));
//   learner.learn(create_rec_dat(2,1,1.1,1.0));
//   EXPECT_EQ(2,model.counter);
//   EXPECT_EQ(8,updater.counter);
//   ASSERT_EQ(8,model.gradientData.size());
//   pred1 = 1*0.1/5;
//   pred2 = 2*0.1/5;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(1,model.gradientData[4].first->item);
//   EXPECT_EQ(1,model.gradientData[4].first->score);
//   EXPECT_EQ(2,model.gradientData[4].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[4].second);
//   EXPECT_EQ(2,model.gradientData[5].first->item);
//   EXPECT_EQ(0,model.gradientData[5].first->score);
//   EXPECT_EQ(2,model.gradientData[5].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[5].second);
//   pred1 = 1*0.1/2;
//   pred2 = 4*0.1/2;
//   gradient = -1.0/(1.0+exp(pred1-pred2));
//   EXPECT_EQ(1,model.gradientData[6].first->item);
//   EXPECT_EQ(1,model.gradientData[6].first->score);
//   EXPECT_EQ(2,model.gradientData[6].first->user);
//   EXPECT_DOUBLE_EQ(gradient,model.gradientData[6].second);
//   EXPECT_EQ(4,model.gradientData[7].first->item);
//   EXPECT_EQ(0,model.gradientData[7].first->score);
//   EXPECT_EQ(2,model.gradientData[7].first->user);
//   EXPECT_DOUBLE_EQ(-gradient,model.gradientData[7].second);
//   EXPECT_DOUBLE_EQ(3*0.1/4,model.prediction(create_rec_dat(1,3,1.1,1.0)));
// }

// TEST_F(TestGradientComputer, listwise) {
//   gradient_computer = new GradientComputerListWise(&objectiveDummyListWise);
//   gradient_computer->set_model(&model);
//   learner.set_gradient_computer(gradient_computer);

//   learner.learn(create_rec_dat(1,5,1.1,1.0));
//   EXPECT_EQ(1,model.counter);
//   EXPECT_EQ(3,updater.counter);
//   ASSERT_EQ(3,model.gradientData.size());
//   EXPECT_EQ(5,model.gradientData[0].first->item);
//   EXPECT_EQ(1,model.gradientData[0].first->score);
//   EXPECT_EQ(1,model.gradientData[0].first->user);
//   EXPECT_DOUBLE_EQ((5*0.1/1-1.0)*1,model.gradientData[0].second);
//   EXPECT_EQ(2,model.gradientData[1].first->item);
//   EXPECT_EQ(0,model.gradientData[1].first->score);
//   EXPECT_EQ(1,model.gradientData[1].first->user);
//   EXPECT_DOUBLE_EQ((2*0.1/1-0.0)*2,model.gradientData[1].second);
//   EXPECT_EQ(4,model.gradientData[2].first->item);
//   EXPECT_EQ(0,model.gradientData[2].first->score);
//   EXPECT_EQ(1,model.gradientData[2].first->user);
//   EXPECT_DOUBLE_EQ((4*0.1/1-0.0)*3,model.gradientData[2].second);
//   EXPECT_DOUBLE_EQ(1*0.1/4,model.prediction(create_rec_dat(1,1,1.1,1.0)));
//   learner.learn(create_rec_dat(2,1,1.1,1.0));
//   EXPECT_EQ(2,model.counter);
//   EXPECT_EQ(6,updater.counter);
//   ASSERT_EQ(6,model.gradientData.size());
//   EXPECT_EQ(1,model.gradientData[3].first->item);
//   EXPECT_EQ(1,model.gradientData[3].first->score);
//   EXPECT_EQ(2,model.gradientData[3].first->user);
//   EXPECT_DOUBLE_EQ((1*0.1/4-1.0)*1,model.gradientData[3].second);
//   EXPECT_EQ(2,model.gradientData[4].first->item);
//   EXPECT_EQ(0,model.gradientData[4].first->score);
//   EXPECT_EQ(2,model.gradientData[4].first->user);
//   EXPECT_DOUBLE_EQ((2*0.1/4-0.0)*2,model.gradientData[4].second);
//   EXPECT_EQ(4,model.gradientData[5].first->item);
//   EXPECT_EQ(0,model.gradientData[5].first->score);
//   EXPECT_EQ(2,model.gradientData[5].first->user);
//   EXPECT_DOUBLE_EQ((4*0.1/4-0.0)*3,model.gradientData[5].second);
//   EXPECT_DOUBLE_EQ(3*0.1/2,model.prediction(create_rec_dat(1,3,1.1,1.0)));
// }
// TEST_F(TestOfflineGradientComputerPointWise, pointwise) {
//   //EXPECT_FALSE(gradient_computer_.selfTest());
//   gradient_computer_.set_model(&model_);
//   gradient_computer_.set_objective(&objective_);
//   //EXPECT_TRUE(gradient_computer_.selfTest());
//   double gradient = gradient_computer_.get_gradient(create_rec_dat(1,2,3.0,5.0));
//   EXPECT_DOUBLE_EQ(1+2+5.0, gradient);
//   EXPECT_EQ(0,model_.counter_);
// }

int main (int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<|endoftext|>


<commit_before>/*
 * Recognizer experiment
 */

#ifndef _OPENCOG_RECOGNIZER_H
#define _OPENCOG_RECOGNIZER_H

#include <opencog/query/DefaultPatternMatchCB.h>
#include <opencog/atoms/bind/PatternLink.h>

#include "BindLinkAPI.h"

namespace opencog {

class Recognizer :
   public virtual DefaultPatternMatchCB
{
	protected:
		const Pattern* _pattern;

		Handle _root;
		Handle _starter_term;
		bool do_search(PatternMatchEngine*, const Handle&);

	public:
		Recognizer(AtomSpace* as) :
			DefaultPatternMatchCB(as) {}

		virtual bool initiate_search(PatternMatchEngine*);
		virtual void set_pattern(const Variables& vars,
										 const Pattern& pat)
		{
			_pattern = &pat;
			DefaultPatternMatchCB::set_pattern(vars, pat);
		}

		virtual bool grounding(const std::map<Handle, Handle> &var_soln,
		                       const std::map<Handle, Handle> &term_soln);
};

} // namespace opencog

#endif // _OPENCOG_RECOGNIZER_H

using namespace opencog;

// Uncomment below to enable debug print
// #define DEBUG
#ifdef DEBUG
#define dbgprt(f, varargs...) printf(f, ##varargs)
#else
#define dbgprt(f, varargs...)
#endif

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

bool Recognizer::do_search(PatternMatchEngine* pme, const Handle& top)
{
	LinkPtr ltop(LinkCast(top));
	if (ltop)
	{
		for (const Handle& h : ltop->getOutgoingSet())
		{
			_starter_term = top;
			bool found = do_search(pme, h);
			if (found) return true;
		}
	}
	IncomingSet iset = get_incoming_set(top);
	size_t sz = iset.size();
	for (size_t i = 0; i < sz; i++)
	{
		Handle h(iset[i]);
		dbgprt("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n");
		dbgprt("Loop candidate (%lu/%lu):\n%s\n", i+1, sz,
		       h->toShortString().c_str());
		bool found = pme->explore_neighborhood(_root, _starter_term, h);

		// Terminate search if satisfied.
		if (found) return true;
   }

	return false;
}

bool Recognizer::initiate_search(PatternMatchEngine* pme)
{
	const HandleSeq& clauses = _pattern->cnf_clauses;

	for (const Handle& h: clauses)
	{
		_root = h;
		bool found = do_search(pme, h);
		if (found) return true;
	}
	return false;
}

bool Recognizer::grounding(const std::map<Handle, Handle> &var_soln,
                           const std::map<Handle, Handle> &term_soln)
{
printf("duuuude ola!!\n");

	// Look for more groundings.
	return false;
}

Handle opencog::recognize(AtomSpace* as, const Handle& hlink)
{
	PatternLinkPtr bl(PatternLinkCast(hlink));
	if (NULL == bl)
		bl = createPatternLink(hlink);

	Recognizer reco(as);
	bl->satisfy(reco);

	return Handle(createLink(LIST_LINK, HandleSeq()));
}
<commit_msg>Minor fixes<commit_after>/*
 * Recognizer experiment
 */

#ifndef _OPENCOG_RECOGNIZER_H
#define _OPENCOG_RECOGNIZER_H

#include <opencog/query/DefaultPatternMatchCB.h>
#include <opencog/atoms/bind/PatternLink.h>

#include "BindLinkAPI.h"

namespace opencog {

class Recognizer :
   public virtual DefaultPatternMatchCB
{
	protected:
		const Pattern* _pattern;

		Handle _root;
		Handle _starter_term;
		size_t _cnt;
		bool do_search(PatternMatchEngine*, const Handle&);

	public:
		Recognizer(AtomSpace* as) :
			DefaultPatternMatchCB(as) {}

		virtual bool initiate_search(PatternMatchEngine*);
		virtual void set_pattern(const Variables& vars,
										 const Pattern& pat)
		{
			_pattern = &pat;
			DefaultPatternMatchCB::set_pattern(vars, pat);
		}

		virtual bool grounding(const std::map<Handle, Handle> &var_soln,
		                       const std::map<Handle, Handle> &term_soln);
};

} // namespace opencog

#endif // _OPENCOG_RECOGNIZER_H

using namespace opencog;

// Uncomment below to enable debug print
// #define DEBUG
#ifdef DEBUG
#define dbgprt(f, varargs...) printf(f, ##varargs)
#else
#define dbgprt(f, varargs...)
#endif

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

bool Recognizer::do_search(PatternMatchEngine* pme, const Handle& top)
{
	LinkPtr ltop(LinkCast(top));
	if (ltop)
	{
		for (const Handle& h : ltop->getOutgoingSet())
		{
			_starter_term = top;
			bool found = do_search(pme, h);
			if (found) return true;
		}
		return false;
	}

	IncomingSet iset = get_incoming_set(top);
	size_t sz = iset.size();
	for (size_t i = 0; i < sz; i++)
	{
		Handle h(iset[i]);
		dbgprt("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n");
		dbgprt("Loop candidate (%lu - %s):\n%s\n", _cnt++,
		       top->toShortString().c_str(),
		       h->toShortString().c_str());
		bool found = pme->explore_neighborhood(_root, _starter_term, h);

		// Terminate search if satisfied.
		if (found) return true;
   }

	return false;
}

bool Recognizer::initiate_search(PatternMatchEngine* pme)
{
	const HandleSeq& clauses = _pattern->cnf_clauses;

	_cnt = 0;
	for (const Handle& h: clauses)
	{
		_root = h;
		bool found = do_search(pme, h);
		if (found) return true;
	}
	return false;
}

bool Recognizer::grounding(const std::map<Handle, Handle> &var_soln,
                           const std::map<Handle, Handle> &term_soln)
{
printf("duuuude ola!!\n");

	// Look for more groundings.
	return false;
}

Handle opencog::recognize(AtomSpace* as, const Handle& hlink)
{
	PatternLinkPtr bl(PatternLinkCast(hlink));
	if (NULL == bl)
		bl = createPatternLink(hlink);

	Recognizer reco(as);
	bl->satisfy(reco);

	return Handle(createLink(LIST_LINK, HandleSeq()));
}
<|endoftext|>


<commit_before>/*
 * load-file.cc
 *
 * Utility helper function -- load scheme code from a file
 * Copyright (c) 2008 Linas Vepstas <linasvepstas@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include "SchemeEval.h"

namespace opencog {

/**
 * Load scheme code from a file.
 * The code will be loaded into a running instance of the evaluator.
 * Parsing errors will be printed to stderr.
 *
 * Return errno if file cannot be opened.
 */
int load_scm_file (const char * filename)
{
#define BUFSZ 400
	char buff[BUFSZ];

	FILE * fh = fopen (filename, "r");
	if (NULL == fh)
	{
		int norr = errno;
		fprintf(stderr, "Error: %d %s: %s\n",
			norr, strerror(norr), filename);
		return norr;
	}

	SchemeEval evaluator;
	int lineno = 0;

	while(1)
	{
		char * rc = fgets(buff, BUFSZ, fh);
		if (NULL == rc) break;
		std::string rv = evaluator.eval(buff);

		if (evaluator.eval_error())
		{
			fprintf(stderr, "File: %s line: %d\n", filename, lineno);
			fprintf(stderr, "%s\n", rv.c_str());
		}
		lineno ++;
	}

	fclose (fh);
	return 0;
}

}
#endif /* HAVE_GUILE */
<commit_msg>fix include file path <commit_after>/*
 * load-file.cc
 *
 * Utility helper function -- load scheme code from a file
 * Copyright (c) 2008 Linas Vepstas <linasvepstas@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <opencog/guile/SchemeEval.h>

namespace opencog {

/**
 * Load scheme code from a file.
 * The code will be loaded into a running instance of the evaluator.
 * Parsing errors will be printed to stderr.
 *
 * Return errno if file cannot be opened.
 */
int load_scm_file (const char * filename)
{
#define BUFSZ 400
	char buff[BUFSZ];

	FILE * fh = fopen (filename, "r");
	if (NULL == fh)
	{
		int norr = errno;
		fprintf(stderr, "Error: %d %s: %s\n",
			norr, strerror(norr), filename);
		return norr;
	}

	SchemeEval evaluator;
	int lineno = 0;

	while(1)
	{
		char * rc = fgets(buff, BUFSZ, fh);
		if (NULL == rc) break;
		std::string rv = evaluator.eval(buff);

		if (evaluator.eval_error())
		{
			fprintf(stderr, "File: %s line: %d\n", filename, lineno);
			fprintf(stderr, "%s\n", rv.c_str());
		}
		lineno ++;
	}

	fclose (fh);
	return 0;
}

}
#endif /* HAVE_GUILE */
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE openssl_authentication
#include "caf/test/unit_test.hpp"

#include <unistd.h>

#include <vector>
#include <sstream>
#include <utility>
#include <algorithm>

#include <limits.h>
#include <stdlib.h>

#include "caf/all.hpp"
#include "caf/io/all.hpp"
#include "caf/openssl/all.hpp"

using namespace caf;

namespace {

constexpr char local_host[] = "127.0.0.1";

class config : public actor_system_config {
public:
  config() {
    load<io::middleman>();
    load<openssl::manager>();
    add_message_type<std::vector<int>>("std::vector<int>");
    actor_system_config::parse(test::engine::argc(), test::engine::argv());
    middleman_detach_multiplexer = false;
    middleman_detach_utility_actors = false;
    scheduler_policy = atom("testing");
  }

  static std::string data_dir() {
     std::string path{::caf::test::engine::path()};
     path = path.substr(0, path.find_last_of("/"));
     // TODO: https://github.com/actor-framework/actor-framework/issues/555
     path += "/../../libcaf_openssl/test";
     char rpath[PATH_MAX];
     auto rp = realpath(path.c_str(), rpath);
     std::string result;
     if (rp)
       result = rp;
     return result;
  }
};

behavior make_pong_behavior() {
  return {
    [](int val) -> int {
      ++val;
      CAF_MESSAGE("pong " << val);
      return val;
    }
  };
}

behavior make_ping_behavior(event_based_actor* self, const actor& pong) {
  CAF_MESSAGE("ping " << 0);
  self->send(pong, 0);
  return {
    [=](int val) -> int {
      CAF_MESSAGE("ping " << val);
      if (val >= 3) {
        CAF_MESSAGE("terminate ping");
        self->quit();
      }
      return val;
    }
  };
}

struct fixture {
  using sched_t = scheduler::test_coordinator;

  config server_side_config;
  config client_side_config;
  bool initialized;
  union { actor_system server_side; };
  union { actor_system client_side; };
  sched_t* ssched;
  sched_t* csched;

  fixture() : initialized(false) {
    // nop
  }

  ~fixture() {
    if (initialized) {
      server_side.~actor_system();
      client_side.~actor_system();
    }
  }

  bool init(bool skip_client_side_ca) {
    auto cd = config::data_dir();
    cd += '/';
    server_side_config.openssl_passphrase = "12345";
    // check whether all files exist before setting config parameters
    std::string dummy;
    std::pair<const char*, std::string*> cfg[] {
      {"ca.pem", &server_side_config.openssl_cafile},
      {"cert.1.pem", &server_side_config.openssl_certificate},
      {"key.1.enc.pem", &server_side_config.openssl_key},
      {"ca.pem", skip_client_side_ca ? &dummy
                                     : &client_side_config.openssl_cafile},
      {"cert.2.pem", &client_side_config.openssl_certificate},
      {"key.2.pem", &client_side_config.openssl_key}
    };
    // return if any file is unreadable or non-existend
    for (auto& x : cfg) {
      auto path = cd + x.first;
      if (access(path.c_str(), F_OK) == -1) {
        CAF_MESSAGE("pem files missing, skip test");
        return false;
      }
      *x.second = std::move(path);
    }
    CAF_MESSAGE("initialize server side");
    new (&server_side) actor_system(server_side_config);
    CAF_MESSAGE("initialize client side");
    new (&client_side) actor_system(client_side_config);
    ssched = &dynamic_cast<sched_t&>(server_side.scheduler());
    csched = &dynamic_cast<sched_t&>(client_side.scheduler());
    initialized = true;
    return true;
  }

  sched_t& sched_by_sys(actor_system& sys) {
    return &sys == &server_side ? *ssched : *csched;
  }
  bool exec_one(actor_system& sys) {
    CAF_ASSERT(initialized);
    CAF_PUSH_AID(0);
    CAF_SET_LOGGER_SYS(&sys);
    return sched_by_sys(sys).try_run_once()
           || sys.middleman().backend().try_run_once();
  }

  void exec_loop(actor_system& sys) {
    while (exec_one(sys))
      ; // nop
  }

  void exec_loop() {
    while (exec_one(client_side) | exec_one(server_side))
      ; // nop
  }

  void loop_after_next_enqueue(actor_system& sys) {
    auto s = &sys == &server_side ? ssched : csched;
    s->after_next_enqueue([=] { exec_loop(); });
  }
};

} // namespace <anonymous>

CAF_TEST_FIXTURE_SCOPE(authentication, fixture)

using openssl::remote_actor;
using openssl::publish;

CAF_TEST(authentication_succes) {
  if (!init(false))
    return;
  // server side
  CAF_MESSAGE("spawn pong on server");
  auto spong = server_side.spawn(make_pong_behavior);
  exec_loop();
  loop_after_next_enqueue(server_side);
  CAF_MESSAGE("publish pong");
  CAF_EXP_THROW(port, publish(spong, 0, local_host));
  exec_loop();
  // client side
  CAF_MESSAGE("connect to pong via port " << port);
  loop_after_next_enqueue(client_side);
  CAF_EXP_THROW(pong, remote_actor(client_side, local_host, port));
  CAF_MESSAGE("spawn ping and exchange messages");
  client_side.spawn(make_ping_behavior, pong);
  exec_loop();
  CAF_MESSAGE("terminate pong");
  anon_send_exit(spong, exit_reason::user_shutdown);
  exec_loop();
}

CAF_TEST(authentication_failure) {
  if (!init(true))
    return;
  // server side
  CAF_MESSAGE("spawn pong on server");
  auto spong = server_side.spawn(make_pong_behavior);
  exec_loop();
  loop_after_next_enqueue(server_side);
  CAF_MESSAGE("publish pong");
  CAF_EXP_THROW(port, publish(spong, 0, local_host));
  exec_loop();
  // client side
  CAF_MESSAGE("connect to pong via port " << port);
  loop_after_next_enqueue(client_side);
  auto remote_pong = remote_actor(client_side, local_host, port);
  CAF_CHECK(!remote_pong);
  CAF_MESSAGE("terminate pong");
  anon_send_exit(spong, exit_reason::user_shutdown);
  exec_loop();
}

CAF_TEST_FIXTURE_SCOPE_END()
<commit_msg>Fix termination issue in OpenSSL test<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE openssl_authentication
#include "caf/test/unit_test.hpp"

#include <unistd.h>

#include <vector>
#include <sstream>
#include <utility>
#include <algorithm>

#include <limits.h>
#include <stdlib.h>

#include "caf/all.hpp"
#include "caf/io/all.hpp"
#include "caf/openssl/all.hpp"

using namespace caf;

namespace {

constexpr char local_host[] = "127.0.0.1";

class config : public actor_system_config {
public:
  config() {
    load<io::middleman>();
    load<openssl::manager>();
    add_message_type<std::vector<int>>("std::vector<int>");
    actor_system_config::parse(test::engine::argc(), test::engine::argv());
    middleman_detach_multiplexer = false;
    middleman_detach_utility_actors = false;
    scheduler_policy = atom("testing");
  }

  static std::string data_dir() {
     std::string path{::caf::test::engine::path()};
     path = path.substr(0, path.find_last_of("/"));
     // TODO: https://github.com/actor-framework/actor-framework/issues/555
     path += "/../../libcaf_openssl/test";
     char rpath[PATH_MAX];
     auto rp = realpath(path.c_str(), rpath);
     std::string result;
     if (rp)
       result = rp;
     return result;
  }
};

behavior make_pong_behavior() {
  return {
    [](int val) -> int {
      ++val;
      CAF_MESSAGE("pong " << val);
      return val;
    }
  };
}

behavior make_ping_behavior(event_based_actor* self, const actor& pong) {
  CAF_MESSAGE("ping " << 0);
  self->send(pong, 0);
  return {
    [=](int val) -> int {
      CAF_MESSAGE("ping " << val);
      if (val >= 3) {
        CAF_MESSAGE("terminate ping");
        self->quit();
      }
      return val;
    }
  };
}

struct fixture {
  using sched_t = scheduler::test_coordinator;

  config server_side_config;
  config client_side_config;
  bool initialized;
  union { actor_system server_side; };
  union { actor_system client_side; };
  sched_t* ssched;
  sched_t* csched;

  fixture() : initialized(false) {
    // nop
  }

  ~fixture() {
    if (initialized) {
      server_side.~actor_system();
      client_side.~actor_system();
    }
  }

  bool init(bool skip_client_side_ca) {
    auto cd = config::data_dir();
    cd += '/';
    server_side_config.openssl_passphrase = "12345";
    // check whether all files exist before setting config parameters
    std::string dummy;
    std::pair<const char*, std::string*> cfg[] {
      {"ca.pem", &server_side_config.openssl_cafile},
      {"cert.1.pem", &server_side_config.openssl_certificate},
      {"key.1.enc.pem", &server_side_config.openssl_key},
      {"ca.pem", skip_client_side_ca ? &dummy
                                     : &client_side_config.openssl_cafile},
      {"cert.2.pem", &client_side_config.openssl_certificate},
      {"key.2.pem", &client_side_config.openssl_key}
    };
    // return if any file is unreadable or non-existend
    for (auto& x : cfg) {
      auto path = cd + x.first;
      if (access(path.c_str(), F_OK) == -1) {
        CAF_MESSAGE("pem files missing, skip test");
        return false;
      }
      *x.second = std::move(path);
    }
    CAF_MESSAGE("initialize server side");
    new (&server_side) actor_system(server_side_config);
    CAF_MESSAGE("initialize client side");
    new (&client_side) actor_system(client_side_config);
    ssched = &dynamic_cast<sched_t&>(server_side.scheduler());
    csched = &dynamic_cast<sched_t&>(client_side.scheduler());
    initialized = true;
    return true;
  }

  sched_t& sched_by_sys(actor_system& sys) {
    return &sys == &server_side ? *ssched : *csched;
  }
  bool exec_one(actor_system& sys) {
    CAF_ASSERT(initialized);
    CAF_PUSH_AID(0);
    CAF_SET_LOGGER_SYS(&sys);
    return sched_by_sys(sys).try_run_once()
           || sys.middleman().backend().try_run_once();
  }

  void exec_loop(actor_system& sys) {
    while (exec_one(sys))
      ; // nop
  }

  void exec_loop() {
    while (exec_one(client_side) | exec_one(server_side))
      ; // nop
  }

  void loop_after_next_enqueue(actor_system& sys) {
    auto s = &sys == &server_side ? ssched : csched;
    s->after_next_enqueue([=] { exec_loop(); });
  }

  bool terminated(const actor& x) {
    return x ? x->getf(abstract_actor::is_terminated_flag) : false;
  }
};

} // namespace <anonymous>

CAF_TEST_FIXTURE_SCOPE(authentication, fixture)

using openssl::remote_actor;
using openssl::publish;

CAF_TEST(authentication_success) {
  if (!init(false))
    return;
  // server side
  CAF_MESSAGE("spawn pong on server");
  auto spong = server_side.spawn(make_pong_behavior);
  exec_loop();
  CAF_MESSAGE("publish pong");
  loop_after_next_enqueue(server_side);
  CAF_EXP_THROW(port, publish(spong, 0, local_host));
  exec_loop();
  // client side
  CAF_MESSAGE("connect to pong via port " << port);
  loop_after_next_enqueue(client_side);
  CAF_EXP_THROW(pong, remote_actor(client_side, local_host, port));
  CAF_MESSAGE("spawn ping and exchange messages");
  auto sping = client_side.spawn(make_ping_behavior, pong);
  while (!terminated(sping))
    exec_loop();
  CAF_MESSAGE("terminate pong");
  anon_send_exit(spong, exit_reason::user_shutdown);
  exec_loop();
}

CAF_TEST(authentication_failure) {
  if (!init(true))
    return;
  // server side
  CAF_MESSAGE("spawn pong on server");
  auto spong = server_side.spawn(make_pong_behavior);
  exec_loop();
  loop_after_next_enqueue(server_side);
  CAF_MESSAGE("publish pong");
  CAF_EXP_THROW(port, publish(spong, 0, local_host));
  exec_loop();
  // client side
  CAF_MESSAGE("connect to pong via port " << port);
  loop_after_next_enqueue(client_side);
  auto remote_pong = remote_actor(client_side, local_host, port);
  CAF_CHECK(!remote_pong);
  CAF_MESSAGE("terminate pong");
  anon_send_exit(spong, exit_reason::user_shutdown);
  exec_loop();
}

CAF_TEST_FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before><commit_msg>Delete PWGCF/FEMTOSCOPY/macros/Train/pPbKKfemto/exp/confKpKp/2 directory<commit_after><|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
const int IP_HEADR_OFFSET = 14;
const int IP_HEADER_SIZE = 20;
const int UDP_HEADER_OFFSET = 34;
const int UDP_HEADER_SIZE = 8;
const int UDP_DATA_OFFSET = 42;

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == nullptr) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == NULL) {
    return -1;
  }

  while (true) {
    int RetVal;
    pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<commit_msg>Update prototype2/tools/ReaderPcap.cpp<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
const int IP_HEADR_OFFSET = 14;
const int IP_HEADER_SIZE = 20;
const int UDP_HEADER_OFFSET = 34;
const int UDP_HEADER_SIZE = 8;
const int UDP_DATA_OFFSET = 42;

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == nullptr) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == nullptr) {
    return -1;
  }

  while (true) {
    int RetVal;
    pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<|endoftext|>


<commit_before>/**
 *
 *  Graph
 *
 *  Undirected, weighted graph
 *  https://github.com/kdzlvaids/algorithm_and_practice-pknu-2016
 *
 */

/** Includes */
#include <cstddef> /** To define size_t */

/** STL containers */
#include <vector>
#include <forward_list>

namespace algorithm
{

template<
    class       ValueType,                            /**< vertex value type; operator== should be defined */
    class       WeightType            = unsigned int, /**< weight type */
    WeightType  WeightDefaultValue    = 0             /**< default value of weight */
>
class Graph
{
public:
    typedef size_t              SizeType;
    typedef unsigned int        KeyType;        /**< key type, used to access an array */

    /** \brief  Test if two keys are equal

        Test if two keys are equal.
        \return return true if two keys are equal; otherwise return false
        \param  key_first   first key to compare
        \param  key_second  second key to compare
    */
    bool
    IsKeyEqual(const KeyType & key_first, const KeyType & key_second)
    { return key_first == key_second; }

    /** \brief  Vertex class

        Vertex class.
        Each vertex has an array for its edges as a member.
    */
    struct VertexNode
    {
        const   KeyType             key;        /**< key of vertex; same with index in graph_ */
                ValueType           value;      /**< value of vertex */
                std::forward_list<
                    std::pair<const KeyType, WeightType>
                > edges;                        /**< edges of vertex
                                                    \param  const KeyType   key_dest
                                                    \param  WeightType      weight
                                                */
                SizeType            edges_size; /**< count of edges; forward_list not support size() function */

        /** Constructor */
        VertexNode(const KeyType & key, const ValueType & value)
        : key(key)
        , value(value)
        , edges_size(0)
        { }

        /** \brief  Test if two values are equal

            Test if two values are equal.
            \return return true if two values are equal; otherwise return false
            \param  value   value to compare
        */
        bool
        IsValueEqual(const ValueType & value)
        { return this.value == value; }
    };

private:
    std::vector<VertexNode> graph_; /**< graph */

public:
    /** \brief  Test whether there is an edge from the vertices src to dest

        Test whether there is an edge from the vertices depart to dest.
        \return return true if the edge exists; otherwise return false
        \param  key_src     key of source (src)
        \param  key_dest    key of destination (dest)
    */
    bool
    Adjacent(const KeyType & key_src, const KeyType & key_dest)
    {
        for(auto & edge : graph_.at(key_src)->edges)
        {
            if(IsKeyEqual(edge.first, key_dest) == true) /** Found */
                return true;
        }

        return false; /** Not found */
    }

    /** \brief  Add a vertex

        Add a vertex, if a graph not have the vertex with specified value already.
        \return return the key of vertex if added successfully; otherwise return -1
        \param  value_of_vertex     value of vertex
    */
    KeyType
    AddVertex(const ValueType & value_of_vertex)
    {
        KeyType key_of_vertex = GetVertexKey(value_of_vertex);

        if(key_of_vertex == GetVertexCount()) /** Not found */
            graph_.push_back(VertexNode(key_of_vertex, value_of_vertex));

        return key_of_vertex;
    }

    /** \brief  Add an edge

        Add an edge connects two vertices.
        \param  key_src     key of source (src)
        \param  key_dest    key of destination (dest)
        \param  weight      weight of the edge
    */
    void
    AddEdge(const KeyType & key_src, const KeyType & key_dest, const WeightType & weight = WeightDefaultValue)
    {
        graph_.at(key_src).edges.push_front(
            std::make_pair<const KeyType, WeightType> (key_dest, weight)
        );
        ++graph_.at(key_src).edges_size;
    }

    /** \brief  Get a key of the vertex with specified value

        Get a key of the vertex with specified value from a graph.
        If failed to add, return the size of graph which is an invalid key (maximum key + 1).
        \return return the key of vertex if added successfully; otherwise return the size of graph
        \param  value_of_vertex     value of vertex
    */
    KeyType
    GetVertexKey(const ValueType & value_of_vertex)
    {
        for(const VertexNode & vertex : graph_)
        {
            if(vertex.IsValueEqual(value_of_vertex) == true)
                return vertex.key;
        }

        return GetVertexCount();
    }

    /** \brief  Get a value of the vertex with specified key

        Get a value of the vertex with specified key from a graph.
        \return return the value
        \param  key_of_vertex   key of vertex
    */
    inline
    ValueType
    GetVertexValue(const KeyType & key_of_vertex)
    { return graph_.at(key_of_vertex).value; }

    /** \brief  Set a value of the vertex with specified key

        Set a value of the vertex with specified key from a graph.
        \param  key_of_vertex       key of vertex
        \param  value_of_vertex     value of vertex
    */
    inline
    void
    SetVertexValue(const KeyType & key_of_vertex, const ValueType & value_of_vertex)
    { graph_.at(key_of_vertex).value = value_of_vertex; }

    /** \brief  Get a count of vertices

        Get a count of vertices
        \return count of vertices
    */
    inline
    SizeType
    GetVertexCount(void)
    { return graph_.size(); }

    /** \brief  Get a count of edges

        Get a count of edges
        \return count of edges
        \param  key_of_vertex       key of vertex
    */
    inline
    SizeType
    GetVertexEdgeCount(const KeyType & key_of_vertex)
    { return graph_.at(key_of_vertex).edges_size; }
};

} /** ns: algorithm */
<commit_msg>Add comment for graph class<commit_after>/**
 *
 *  Graph
 *
 *  Undirected, weighted graph
 *  https://github.com/kdzlvaids/algorithm_and_practice-pknu-2016
 *
 */

/** Includes */
#include <cstddef> /** To define size_t */

/** STL containers */
#include <vector>
#include <forward_list>

namespace algorithm
{

/** \brief Graph class

    Undirected, weighted graph class.
    TODO: Vertex deletion is not implemented
    TODO: Edge deletion is not implemented
*/
template<
    class       ValueType,                            /**< vertex value type; operator== should be defined */
    class       WeightType            = unsigned int, /**< weight type */
    WeightType  WeightDefaultValue    = 0             /**< default value of weight */
>
class Graph
{
public:
    typedef size_t              SizeType;
    typedef unsigned int        KeyType;        /**< key type, used to access an array */

    /** \brief  Test if two keys are equal

        Test if two keys are equal.
        \return return true if two keys are equal; otherwise return false
        \param  key_first   first key to compare
        \param  key_second  second key to compare
    */
    bool
    IsKeyEqual(const KeyType & key_first, const KeyType & key_second)
    { return key_first == key_second; }

    /** \brief  Vertex class

        Vertex class.
        Each vertex has an array for its edges as a member.
    */
    struct VertexNode
    {
        const   KeyType             key;        /**< key of vertex; same with index in graph_ */
                ValueType           value;      /**< value of vertex */
                std::forward_list<
                    std::pair<const KeyType, WeightType>
                > edges;                        /**< edges of vertex
                                                    \param  const KeyType   key_dest
                                                    \param  WeightType      weight
                                                */
                SizeType            edges_size; /**< count of edges; forward_list not support size() function */

        /** Constructor */
        VertexNode(const KeyType & key, const ValueType & value)
        : key(key)
        , value(value)
        , edges_size(0)
        { }

        /** \brief  Test if two values are equal

            Test if two values are equal.
            \return return true if two values are equal; otherwise return false
            \param  value   value to compare
        */
        bool
        IsValueEqual(const ValueType & value)
        { return this.value == value; }
    };

private:
    std::vector<VertexNode> graph_; /**< graph */

public:
    /** \brief  Test whether there is an edge from the vertices src to dest

        Test whether there is an edge from the vertices depart to dest.
        \return return true if the edge exists; otherwise return false
        \param  key_src     key of source (src)
        \param  key_dest    key of destination (dest)
    */
    bool
    Adjacent(const KeyType & key_src, const KeyType & key_dest)
    {
        for(auto & edge : graph_.at(key_src)->edges)
        {
            if(IsKeyEqual(edge.first, key_dest) == true) /** Found */
                return true;
        }

        return false; /** Not found */
    }

    /** \brief  Add a vertex

        Add a vertex, if a graph not have the vertex with specified value already.
        \return return the key of vertex if added successfully; otherwise return -1
        \param  value_of_vertex     value of vertex
    */
    KeyType
    AddVertex(const ValueType & value_of_vertex)
    {
        KeyType key_of_vertex = GetVertexKey(value_of_vertex);

        if(key_of_vertex == GetVertexCount()) /** Not found */
            graph_.push_back(VertexNode(key_of_vertex, value_of_vertex));

        return key_of_vertex;
    }

    /** \brief  Add an edge

        Add an edge connects two vertices.
        \param  key_src     key of source (src)
        \param  key_dest    key of destination (dest)
        \param  weight      weight of the edge
    */
    void
    AddEdge(const KeyType & key_src, const KeyType & key_dest, const WeightType & weight = WeightDefaultValue)
    {
        graph_.at(key_src).edges.push_front(
            std::make_pair<const KeyType, WeightType> (key_dest, weight)
        );
        ++graph_.at(key_src).edges_size;
    }

    /** \brief  Get a key of the vertex with specified value

        Get a key of the vertex with specified value from a graph.
        If failed to add, return the size of graph which is an invalid key (maximum key + 1).
        \return return the key of vertex if added successfully; otherwise return the size of graph
        \param  value_of_vertex     value of vertex
    */
    KeyType
    GetVertexKey(const ValueType & value_of_vertex)
    {
        for(const VertexNode & vertex : graph_)
        {
            if(vertex.IsValueEqual(value_of_vertex) == true)
                return vertex.key;
        }

        return GetVertexCount();
    }

    /** \brief  Get a value of the vertex with specified key

        Get a value of the vertex with specified key from a graph.
        \return return the value
        \param  key_of_vertex   key of vertex
    */
    inline
    ValueType
    GetVertexValue(const KeyType & key_of_vertex)
    { return graph_.at(key_of_vertex).value; }

    /** \brief  Set a value of the vertex with specified key

        Set a value of the vertex with specified key from a graph.
        \param  key_of_vertex       key of vertex
        \param  value_of_vertex     value of vertex
    */
    inline
    void
    SetVertexValue(const KeyType & key_of_vertex, const ValueType & value_of_vertex)
    { graph_.at(key_of_vertex).value = value_of_vertex; }

    /** \brief  Get a count of vertices

        Get a count of vertices
        \return count of vertices
    */
    inline
    SizeType
    GetVertexCount(void)
    { return graph_.size(); }

    /** \brief  Get a count of edges

        Get a count of edges
        \return count of edges
        \param  key_of_vertex       key of vertex
    */
    inline
    SizeType
    GetVertexEdgeCount(const KeyType & key_of_vertex)
    { return graph_.at(key_of_vertex).edges_size; }
};

} /** ns: algorithm */
<|endoftext|>


<commit_before>#include <Arduino.h>
#include <RFM69_ATC.h>//get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include "DS3231.h"
#include "SdFat.h"

#define NODEID 0
#define FREQUENCY RF69_433MHZ
#define ATC_RSSI -70
#define ACK_WAIT_TIME 100 // # of ms to wait for an ack
#define ACK_RETRIES 10 // # of attempts before giving up
#define SERIAL_BAUD 9600
#define LED 9
#define SD_CS_PIN 4
#define CARD_DETECT 5

#define SERIAL_EN //Comment this out to remove Serial comms and save a few kb's of space
#ifdef SERIAL_EN
#define DEBUG(input)   {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#define DEBUGFlush() { Serial.flush(); }
#else
#define DEBUG(input);
#define DEBUGln(input);
#define DEBUGFlush();
#endif

// Functions
uint8_t setAddress();
void Blink(byte, int);
void checkSdCard();

/*==============|| RFM69 ||==============*/
RFM69_ATC radio; //Initialize Radio
uint8_t NETWORKID = 100; //base network address
byte lastRequesterNodeID = NODEID;

/*==============|| DS3231_RTC ||==============*/
DateTime now;
DS3231 rtc; //Initialize the Real Time Clock

/*==============|| SD ||==============*/
SdFat SD; //This is the sd Card
uint8_t CARD_PRESENT; //var for Card Detect sensor reading

struct TimeStamp {
	uint32_t timestamp;
};
TimeStamp theTimeStamp;

struct Payload {
	uint32_t timestamp;
	uint16_t count;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
	int16_t brd_tmp;
	int16_t bat_v;
};
Payload thePayload;

void setup() {
	bool sd_OK = false;
	pinMode(LED, OUTPUT);
	pinMode(CARD_DETECT, INPUT_PULLUP);
	NETWORKID += setAddress();
	rtc.begin();
	rtc.adjust(DateTime((__DATE__), (__TIME__))); //sets the RTC to the computer time.
	Serial.begin(SERIAL_BAUD);
	radio.initialize(FREQUENCY,NODEID,NETWORKID);
	radio.setHighPower(); //only for RFM69HW!
	radio.enableAutoPower(ATC_RSSI);
	radio.encrypt(null);
	DEBUG("Listening at 433mhz, "); DEBUG("Network Address: ");
	DEBUG(NETWORKID); DEBUG("."); DEBUGln(NODEID);
	digitalWrite(LED, HIGH);
	CARD_PRESENT = !digitalRead(CARD_DETECT); //read CD pin (invert it so logic stays logical)
	if(CARD_PRESENT) {
		DEBUGln("Card Present OK");
		if (SD.begin(SD_CS_PIN)) {
			DEBUGln("Sd.begin OK");
			File f;
			now = rtc.now();
			if(f.open("start.txt", FILE_WRITE)) {
				DEBUG("File Open OK at ");
				DEBUGln(now.unixtime());
				f.print("program started at: ");
				f.print(now.unixtime());
				f.println();
				f.close();
				sd_OK = true;
			}
		}
	}
	if(!sd_OK) {
		while(1) {
			Blink(LED, 100); //blink to show an error.
			Blink(LED, 200); //blink to show an error.
		}
	}
	digitalWrite(LED, LOW);
	DEBUGln("sd card initialized"); ///Victory
	DEBUGln("==========================");
}

void loop() {
	bool writeData = false;
	bool reportTime = false;

	if (radio.receiveDone()) {
		lastRequesterNodeID = radio.SENDERID;
		now = rtc.now();
		theTimeStamp.timestamp = now.unixtime();
		if(radio.DATALEN == 1 && radio.DATA[0] == 't') {
			DEBUG("rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] "); DEBUG("t  ->  ");
			reportTime = true;
		}
		if (radio.DATALEN == sizeof(thePayload)) {
			thePayload = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
			writeData = true;
			DEBUG("rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] ");
			DEBUG(thePayload.timestamp);
			DEBUG(" c: "); DEBUG(thePayload.count);
			DEBUG(" t1:"); DEBUG(thePayload.tc1/100.0);
			DEBUG(" t2: "); DEBUG(thePayload.tc2/100.0);
			DEBUG(" t3: "); DEBUG(thePayload.tc3/100.0);
			DEBUG(" tbrd: "); DEBUG(thePayload.brd_tmp/100.0);
			DEBUG(" v: "); DEBUG(thePayload.bat_v/100.0);
			DEBUGln();
		}
		if (radio.ACKRequested()) radio.sendACK();
		Blink(LED,5);
	}
	if(reportTime) {
		DEBUG("snd - "); DEBUG('['); DEBUG(lastRequesterNodeID); DEBUG("] ");
		if(radio.sendWithRetry(lastRequesterNodeID, (const void*)(&theTimeStamp), sizeof(theTimeStamp), ACK_RETRIES, ACK_WAIT_TIME)) {
			DEBUGln(theTimeStamp.timestamp);
		} else {
			DEBUGln("Failed . . . no ack");
		}
	}

	if(writeData) {
		File f;
		String address = String(String(NETWORKID) + "_" + String(lastRequesterNodeID));
		String fileName = String(address + ".csv");
		char _fileName[fileName.length() +1];
		fileName.toCharArray(_fileName, sizeof(_fileName));
		if (!f.open(_fileName, FILE_WRITE)) { DEBUG("sd - error opening "); DEBUG(_fileName); DEBUGln(); }
		// if the file opened okay, write to it:
		DEBUG("sd - writing to "); DEBUG(_fileName); DEBUGln();
		f.print(NETWORKID); f.print(".");
		f.print(radio.SENDERID); f.print(",");
		f.print(thePayload.timestamp); f.print(",");
		f.print(thePayload.tc1/100.0); f.print(",");
		f.print(thePayload.tc2/100.0); f.print(",");
		f.print(thePayload.tc3/100.0); f.print(",");
		f.print(thePayload.brd_tmp/100.0); f.print(",");
		f.print(thePayload.bat_v/100.0); f.print(",");
		f.print(thePayload.count); f.println();
		f.close();
	}
	checkSdCard(); //Checks for card insertion
}

void checkSdCard() {
	CARD_PRESENT = !digitalRead(CARD_DETECT); //invert for logic's sake
	if (!CARD_PRESENT) {
		DEBUGln("sd - card Not Present");
		while (1) {
			Blink(LED, 100);
			Blink(LED, 200); //blink to show an error.
		}
	}
}

void Blink(byte PIN, int DELAY_MS) {
	digitalWrite(PIN,HIGH);
	delay(DELAY_MS);
	digitalWrite(PIN,LOW);
	delay(DELAY_MS);
}

uint8_t setAddress() {
	//sets network address based on which solder jumpers are closed
	uint8_t addr01, addr02, addr03;
	pinMode(6, INPUT_PULLUP);
	pinMode(7, INPUT_PULLUP);
	pinMode(8, INPUT_PULLUP);
	addr01 = !digitalRead(8);
	addr02 = !digitalRead(6) * 2;
	addr03 = !digitalRead(7) * 4;
	pinMode(6, OUTPUT);
	pinMode(7, OUTPUT);
	pinMode(8, OUTPUT);
	digitalWrite(6, LOW);
	digitalWrite(7, LOW);
	digitalWrite(8, LOW);
	uint8_t addr = addr01 | addr02 | addr03;
	return addr;
}

// writeLocalTemp(now.unixtime());
// void writeLocalTemp(uint32_t n) {
//     float t;
//     File f;
//     rtc.convertTemperature();
//     t = rtc.getTemperature();
//     String address = String(String(NETWORKID) + "_0");
//     String fileName = String(address + ".csv");
//     char _fileName[fileName.length() +1];
//     fileName.toCharArray(_fileName, sizeof(_fileName));
//     if (!f.open(_fileName, FILE_WRITE)) {
//         DEBUG("error opening ");
//         DEBUG(_fileName);
//         DEBUGln(" for write");
//     }
//     f.print(NETWORKID);
//     f.print(".");
//     f.print("0");
//     f.print(",");
//     f.print(n);
//     f.print(",");
//     f.print(t);
//     f.println();
//     f.close(); // close the file:
// }
<commit_msg>changed payload uint16_t's to doubles to allow for Floats<commit_after>#include <Arduino.h>
#include <RFM69_ATC.h>//get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include "DS3231.h"
#include "SdFat.h"

#define NODEID 0
#define FREQUENCY RF69_433MHZ
#define ATC_RSSI -70
#define ACK_WAIT_TIME 100 // # of ms to wait for an ack
#define ACK_RETRIES 10 // # of attempts before giving up
#define SERIAL_BAUD 9600
#define LED 9
#define SD_CS_PIN 4
#define CARD_DETECT 5

#define SERIAL_EN //Comment this out to remove Serial comms and save a few kb's of space
#ifdef SERIAL_EN
#define DEBUG(input)   {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#define DEBUGFlush() { Serial.flush(); }
#else
#define DEBUG(input);
#define DEBUGln(input);
#define DEBUGFlush();
#endif

// Functions
uint8_t setAddress();
void Blink(byte, int);
void checkSdCard();

/*==============|| RFM69 ||==============*/
RFM69_ATC radio; //Initialize Radio
uint8_t NETWORKID = 100; //base network address
byte lastRequesterNodeID = NODEID;

/*==============|| DS3231_RTC ||==============*/
DateTime now;
DS3231 rtc; //Initialize the Real Time Clock

/*==============|| SD ||==============*/
SdFat SD; //This is the sd Card
uint8_t CARD_PRESENT; //var for Card Detect sensor reading

struct TimeStamp {
	uint32_t timestamp;
};
TimeStamp theTimeStamp;

struct Payload {
	uint32_t timestamp;
	uint16_t count;
	double tc1;
	double tc2;
	double tc3;
	double brd_tmp;
	double bat_v;
};
Payload thePayload;

void setup() {
	bool sd_OK = false;
	pinMode(LED, OUTPUT);
	pinMode(CARD_DETECT, INPUT_PULLUP);
	NETWORKID += setAddress();
	rtc.begin();
	// rtc.adjust(DateTime((__DATE__), (__TIME__))); //sets the RTC to the computer time.
	Serial.begin(SERIAL_BAUD);
	radio.initialize(FREQUENCY,NODEID,NETWORKID);
	radio.setHighPower(); //only for RFM69HW!
	radio.enableAutoPower(ATC_RSSI);
	radio.encrypt(null);
	DEBUG("Listening at 433mhz, "); DEBUG("Network Address: ");
	DEBUG(NETWORKID); DEBUG("."); DEBUGln(NODEID);
	digitalWrite(LED, HIGH);
	CARD_PRESENT = !digitalRead(CARD_DETECT); //read CD pin (invert it so logic stays logical)
	if(CARD_PRESENT) {
		DEBUGln("Card Present OK");
		if (SD.begin(SD_CS_PIN)) {
			DEBUGln("Sd.begin OK");
			File f;
			now = rtc.now();
			if(f.open("start.txt", FILE_WRITE)) {
				DEBUG("File Open OK at ");
				DEBUGln(now.unixtime());
				f.print("program started at: ");
				f.print(now.unixtime());
				f.println();
				f.close();
				sd_OK = true;
			}
		}
	}
	if(!sd_OK) {
		while(1) {
			Blink(LED, 100); //blink to show an error.
			Blink(LED, 200); //blink to show an error.
		}
	}
	digitalWrite(LED, LOW);
	DEBUGln("sd card initialized"); ///Victory
	DEBUGln("==========================");
}

void loop() {
	bool writeData = false;
	bool reportTime = false;

	if (radio.receiveDone()) {
		lastRequesterNodeID = radio.SENDERID;
		now = rtc.now();
		theTimeStamp.timestamp = now.unixtime();
		if(radio.DATALEN == 1 && radio.DATA[0] == 't') {
			DEBUG("rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] "); DEBUG("t  ->  ");
			reportTime = true;
		}
		if (radio.DATALEN == sizeof(thePayload)) {
			thePayload = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
			writeData = true;
			DEBUG("rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] ");
			DEBUG(thePayload.timestamp);
			DEBUG(" c: "); DEBUG(thePayload.count);
			DEBUG(" t1:"); DEBUG(thePayload.tc1/100.0);
			DEBUG(" t2: "); DEBUG(thePayload.tc2/100.0);
			DEBUG(" t3: "); DEBUG(thePayload.tc3/100.0);
			DEBUG(" tbrd: "); DEBUG(thePayload.brd_tmp/100.0);
			DEBUG(" v: "); DEBUG(thePayload.bat_v/100.0);
			DEBUGln();
		}
		if (radio.ACKRequested()) radio.sendACK();
		Blink(LED,5);
	}
	if(reportTime) {
		DEBUG("snd - "); DEBUG('['); DEBUG(lastRequesterNodeID); DEBUG("] ");
		if(radio.sendWithRetry(lastRequesterNodeID, (const void*)(&theTimeStamp), sizeof(theTimeStamp), ACK_RETRIES, ACK_WAIT_TIME)) {
			DEBUGln(theTimeStamp.timestamp);
		} else {
			DEBUGln("Failed . . . no ack");
		}
	}

	if(writeData) {
		File f;
		String address = String(String(NETWORKID) + "_" + String(lastRequesterNodeID));
		String fileName = String(address + ".csv");
		char _fileName[fileName.length() +1];
		fileName.toCharArray(_fileName, sizeof(_fileName));
		if (!f.open(_fileName, FILE_WRITE)) { DEBUG("sd - error opening "); DEBUG(_fileName); DEBUGln(); }
		// if the file opened okay, write to it:
		DEBUG("sd - writing to "); DEBUG(_fileName); DEBUGln();
		f.print(NETWORKID); f.print(".");
		f.print(radio.SENDERID); f.print(",");
		f.print(thePayload.timestamp); f.print(",");
		f.print(thePayload.tc1/100.0); f.print(",");
		f.print(thePayload.tc2/100.0); f.print(",");
		f.print(thePayload.tc3/100.0); f.print(",");
		f.print(thePayload.brd_tmp/100.0); f.print(",");
		f.print(thePayload.bat_v/100.0); f.print(",");
		f.print(thePayload.count); f.println();
		f.close();
	}
	checkSdCard(); //Checks for card insertion
}

void checkSdCard() {
	CARD_PRESENT = !digitalRead(CARD_DETECT); //invert for logic's sake
	if (!CARD_PRESENT) {
		DEBUGln("sd - card Not Present");
		while (1) {
			Blink(LED, 100);
			Blink(LED, 200); //blink to show an error.
		}
	}
}

void Blink(byte PIN, int DELAY_MS) {
	digitalWrite(PIN,HIGH);
	delay(DELAY_MS);
	digitalWrite(PIN,LOW);
	delay(DELAY_MS);
}

uint8_t setAddress() {
	//sets network address based on which solder jumpers are closed
	uint8_t addr01, addr02, addr03;
	pinMode(6, INPUT_PULLUP);
	pinMode(7, INPUT_PULLUP);
	pinMode(8, INPUT_PULLUP);
	addr01 = !digitalRead(8);
	addr02 = !digitalRead(6) * 2;
	addr03 = !digitalRead(7) * 4;
	pinMode(6, OUTPUT);
	pinMode(7, OUTPUT);
	pinMode(8, OUTPUT);
	digitalWrite(6, LOW);
	digitalWrite(7, LOW);
	digitalWrite(8, LOW);
	uint8_t addr = addr01 | addr02 | addr03;
	return addr;
}

// writeLocalTemp(now.unixtime());
// void writeLocalTemp(uint32_t n) {
//     float t;
//     File f;
//     rtc.convertTemperature();
//     t = rtc.getTemperature();
//     String address = String(String(NETWORKID) + "_0");
//     String fileName = String(address + ".csv");
//     char _fileName[fileName.length() +1];
//     fileName.toCharArray(_fileName, sizeof(_fileName));
//     if (!f.open(_fileName, FILE_WRITE)) {
//         DEBUG("error opening ");
//         DEBUG(_fileName);
//         DEBUGln(" for write");
//     }
//     f.print(NETWORKID);
//     f.print(".");
//     f.print("0");
//     f.print(",");
//     f.print(n);
//     f.print(",");
//     f.print(t);
//     f.println();
//     f.close(); // close the file:
// }
<|endoftext|>