<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//      "obj_egg.cc" - Procedures for eggs.  Derived from obj_food.cc
//
//////////////////////////////////////////////////////////////////////////

#include <cmath>

#include "stdsneezy.h"
#include "obj_food.h"
#include "obj_egg.h"

TEgg::TEgg() :
  TFood(),
  touched(0),
  incubationTimer(0),
  mobVNum(0)
{
}

TEgg::TEgg(const TEgg &a) :
  TFood(a),
  touched(a.touched),
  incubationTimer(a.incubationTimer),
  mobVNum(a.mobVNum)
{
}

TEgg & TEgg::operator=(const TEgg &a)
{
  if (this == &a) return *this;
  TFood::operator=(a);
  touched = a.touched;
  incubationTimer = a.incubationTimer;
  mobVNum = a.mobVNum;
  return *this;
}

TEgg::~TEgg()
{
}

void eggPoisoned(TEgg *egg, TBeing *ch, int dur)
{
  affectedData af;

  if (egg->isFoodFlag(FOOD_POISON) &&
      !ch->isAffected(AFF_POISON)) {
    if (ch->isImmune(IMMUNE_POISON, (dur * 10 + 20))) {
      act("That tasted rather strange, but you don't think it had any ill-effect!!", FALSE, ch, 0, 0, TO_CHAR);
    } else {
      act("That tasted rather strange !!", FALSE, ch, 0, 0, TO_CHAR);
      act("$n coughs and utters some strange sounds.", FALSE, ch, 0, 0, TO_ROOM);
      af.type = SPELL_POISON;
      af.duration = dur * UPDATES_PER_MUDHOUR;
      af.modifier = 0;
      af.location = APPLY_NONE;
      af.bitvector = AFF_POISON;
      ch->affectJoin(NULL, &af, AVG_DUR_NO, AVG_EFF_NO);
    }
  }
}

void eggSpoiled(TEgg *egg, TBeing *ch, int dur)
{
  affectedData af;

  if (egg->isFoodFlag(FOOD_SPOILED)) {
    if (ch->isImmune(IMMUNE_POISON, (dur * 10 + 5))) {
      ch->sendTo("BLAH!  That was a very rotten egg.  Hopefully you won't have any ill-effect.\n\r");
    } else {
      af.type = AFFECT_DISEASE;
      af.level = 0;
     // Added /4 because of player complaints of food poisoning - Russ 04/28/96
      af.duration = dur * UPDATES_PER_MUDHOUR;
      af.modifier = DISEASE_FOODPOISON;
      af.location = APPLY_NONE;
      af.bitvector = 0;
      ch->affectTo(&af);
      disease_start(ch, &af);
    }
  }
}

void TEgg::eatMe(TBeing *ch)
{
  if ((ch->getCond(FULL) > 20) && !ch->isImmortal()) {
    ch->sendTo("You try to stuff another egg food into your mouth, but alas, you are full!\n\r");
    return;
  }
  if (isFoodFlag(FOOD_SPOILED) && ch->isPerceptive()) {
    act("You gag at the smell of $p and discard it instead.", TRUE, ch, this, 0, TO_CHAR);
    act("$n gags at the smell of $p and throws it out.", TRUE, ch, this, 0, TO_ROOM);

    ch->playsound(SOUND_FOODPOISON, SOUND_TYPE_NOISE);

    delete this;
    return;
  }

  act("$n eats $p.", TRUE, ch, this, 0, TO_ROOM);
  act("You eat the $o.", FALSE, ch, this, 0, TO_CHAR);

  if(ch->isVampire()){
    ch->sendTo("You eat the mortal food, but it has no affect on you.\n\r");
  } else {
    if (ch->getCond(FULL) > -1)
      ch->gainCondition(FULL, TFood::getFoodFill());
  }

  if (ch->getCond(FULL) > 20)
    act("You are full.", FALSE, ch, 0, 0, TO_CHAR);

  if (!ch->isImmortal()) {
    eggPoisoned(this, ch, getFoodFill());
    eggSpoiled(this, ch, getFoodFill());
  }
  delete this;
}

void TEgg::tasteMe(TBeing *ch)
{
  if (ch->hasDisease(DISEASE_FOODPOISON)) {
    ch->sendTo("Uggh, your stomach feels just horrible and the thought of eggs nauseates you.\n\r");
    ch->sendTo("You decide to skip this meal until you feel better.\n\r");
    return;
  }
  act("$n tastes the $o.", FALSE, ch, this, 0, TO_ROOM);
  act("You taste the $o.", FALSE, ch, this, 0, TO_CHAR);

  if(ch->isVampire()){
    ch->sendTo("You eat the mortal food, but it has no affect on you.\n\r");
  } else {
    ch->gainCondition(FULL, 1);
  }

  if (ch->getCond(FULL) > 20)
    act("You are full.", FALSE, ch, 0, 0, TO_CHAR);

  if (!ch->isImmortal()) {
    eggPoisoned(this, ch, 1);
  }
  if (isFoodFlag(FOOD_SPOILED)) {
    ch->sendTo("Blah, that egg is spoiled!\n\r");
    ch->sendTo("No point in keeping it around now...\n\r");
    delete this;
    return;
  }

  // we filled them "1 unit"
  // let's actually remove "1+ unit" so that we insure that taste isn't
  // better at filling than outright eating
  setFoodFill(getFoodFill() - 2);

  if (getFoodFill() <= 0) {    /* Nothing left */
    act("There is nothing left now.", FALSE, ch, 0, 0, TO_CHAR);
    delete this;
    return;
  }
  return;
}

bool TEgg::getEggTouched() const
{
  return touched;
}

void TEgg::setEggTouched(bool r)
{
  touched = r;
}

int TEgg::getEggTimer() const
{
  return incubationTimer;
}

void TEgg::setEggTimer(int r)
{
  incubationTimer = r;
}

int TEgg::getEggMobVNum() const
{
  return mobVNum;
}

void TEgg::setEggMobVNum(int r)
{
  mobVNum = r;
}

void TEgg::lowCheck()
{
  TFood::lowCheck();
}

sstring TEgg::statObjInfo() const
{
  char buf[256];

  sprintf(buf, "Makes full : %d\n\rPoisoned : %d\n\rIncubation timer : %d\n\rMob vnum : %d\n\rTouched : %d",
    getFoodFill(), getFoodFlags(), getEggTimer(), getEggMobVNum(),
    getEggTouched());

  sstring a(buf);
  return a;
}

void TEgg::assignFourValues(int x1, int x2, int x3, int x4)
{
  TFood::assignFourValues(x1, x2, x3, x4);

  setEggTouched(GET_BITS(x1, 31, 1));
  setEggTimer(x2);
  setEggMobVNum(x3);
}

void TEgg::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  TFood::getFourValues(x1, x2, x3, x4);

  int r = *x1;
  SET_BITS(r, 31, 1, getEggTouched());
  *x1 = r;

  *x2 = getEggTimer();
  *x3 = getEggMobVNum();
}

sstring TEgg::displayFourValues()
{
  char tString[256];
  int x1, x2, x3, x4;

  getFourValues(&x1, &x2, &x3, &x4);
  sprintf(tString, "Current values : %d %d %d %d\n\r", x1, x2, x3, x4);

  sprintf(tString + strlen(tString),
          "Current values : Touched[%d] Food Fill[%d]\n\r\
Incubation Timer[%d] Mob VNum[%d] Food Flags[%d]",
          getEggTouched(), getFoodFill(), getEggTimer(), getEggMobVNum(),
          getFoodFlags());

  return tString;
}

void TEgg::changeObjValue1(TBeing *ch)
{
  ch->specials.edit = CHANGE_EGG_VALUE1;
  change_egg_value1(ch, this, "", ENTER_CHECK);
  return;
}

int TEgg::chiMe(TBeing *tLunatic)
{
  int tMana  = ::number(10, 30),
      bKnown = tLunatic->getSkillLevel(SKILL_CHI);

  if (tLunatic->getMana() < tMana) {
    tLunatic->sendTo("You lack the chi to do this.\n\r");
    return RET_STOP_PARSING;
  } else
    tLunatic->reconcileMana(TYPE_UNDEFINED, 0, tMana);

  if (!bSuccess(tLunatic, bKnown, SKILL_CHI) || isFoodFlag(FOOD_SPOILED)) {
    act("You fail to affect $p in any way.",
        FALSE, tLunatic, this, NULL, TO_CHAR);
    return true;
  }

  act("You focus your chi, causing $p to get warmer!",
      FALSE, tLunatic, this, NULL, TO_CHAR);
  act("$n stares at $p, causing it to get warmer!",
      TRUE, tLunatic, this, NULL, TO_ROOM);
  act("$p begins to wiggle a bit.",
      TRUE, tLunatic, this, NULL, TO_CHAR);
  act("$p begins to wiggle a bit.",
      TRUE, tLunatic, this, NULL, TO_ROOM);

  obj_flags.decay_time += ::number(1, 3);
  incubationTimer = 1;

  return true;
}

int TEgg::getMe(TBeing *ch, TThing *sub)
{
  // do baseclass stuff
  int rc = TObj::getMe(ch, sub);
  if (rc)
    return rc;

  touched=TRUE;

  return TRUE;
}

void TEgg::hatch(TRoom *rp)
{
  TMonster *mob;
  TBeing *ch;
  affectedData aff;

  if (!(mob = read_mobile(mobVNum, VIRTUAL))) {
    vlogf(LOG_BUG, "Problem loading monster in TEgg::hatch");
    return;
  }

  *rp += *mob;
  mob->oldRoom = inRoom();
  act("Suddenly, $p begins to move violently from within!",
    TRUE, mob, this, NULL, TO_ROOM);
  act("With a final push, $n emerges from $p!",
    TRUE, mob, this, NULL, TO_ROOM);

  if(!mob->isAffected(AFF_AGGRESSOR) && parent &&
     (ch=dynamic_cast<TBeing *>(parent)) && ch->isPc() &&
     mob->GetMaxLevel() < ch->GetMaxLevel() &&
     !ch->tooManyFollowers(mob, FOL_PET)){
    // this code was cut and pasted from the pet buying code, sorry :(
    mob->doAction(ch->name, CMD_STARE);

    SET_BIT(mob->specials.affectedBy, AFF_CHARM);
    ch->addFollower(mob);
    mob->balanceMakeNPCLikePC();

    aff.type = AFFECT_PET;
    aff.level = 0;
    aff.duration  = PERMANENT_DURATION;
    aff.location = APPLY_NONE;
    aff.modifier = 0;   // to be used for elemental skill level
    aff.bitvector = 0;

    char * tmp = mud_str_dup(ch->name);
    aff.be = (TThing *) tmp;

    mob->affectTo(&aff, -1);
  }
}

int TEgg::eggIncubate()
{
  return --incubationTimer;
}
<commit_msg>fixed typo<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//      "obj_egg.cc" - Procedures for eggs.  Derived from obj_food.cc
//
//////////////////////////////////////////////////////////////////////////

#include <cmath>

#include "stdsneezy.h"
#include "obj_food.h"
#include "obj_egg.h"

TEgg::TEgg() :
  TFood(),
  touched(0),
  incubationTimer(0),
  mobVNum(0)
{
}

TEgg::TEgg(const TEgg &a) :
  TFood(a),
  touched(a.touched),
  incubationTimer(a.incubationTimer),
  mobVNum(a.mobVNum)
{
}

TEgg & TEgg::operator=(const TEgg &a)
{
  if (this == &a) return *this;
  TFood::operator=(a);
  touched = a.touched;
  incubationTimer = a.incubationTimer;
  mobVNum = a.mobVNum;
  return *this;
}

TEgg::~TEgg()
{
}

void eggPoisoned(TEgg *egg, TBeing *ch, int dur)
{
  affectedData af;

  if (egg->isFoodFlag(FOOD_POISON) &&
      !ch->isAffected(AFF_POISON)) {
    if (ch->isImmune(IMMUNE_POISON, (dur * 10 + 20))) {
      act("That tasted rather strange, but you don't think it had any ill-effect!!", FALSE, ch, 0, 0, TO_CHAR);
    } else {
      act("That tasted rather strange !!", FALSE, ch, 0, 0, TO_CHAR);
      act("$n coughs and utters some strange sounds.", FALSE, ch, 0, 0, TO_ROOM);
      af.type = SPELL_POISON;
      af.duration = dur * UPDATES_PER_MUDHOUR;
      af.modifier = 0;
      af.location = APPLY_NONE;
      af.bitvector = AFF_POISON;
      ch->affectJoin(NULL, &af, AVG_DUR_NO, AVG_EFF_NO);
    }
  }
}

void eggSpoiled(TEgg *egg, TBeing *ch, int dur)
{
  affectedData af;

  if (egg->isFoodFlag(FOOD_SPOILED)) {
    if (ch->isImmune(IMMUNE_POISON, (dur * 10 + 5))) {
      ch->sendTo("BLAH!  That was a very rotten egg.  Hopefully you won't have any ill-effect.\n\r");
    } else {
      af.type = AFFECT_DISEASE;
      af.level = 0;
     // Added /4 because of player complaints of food poisoning - Russ 04/28/96
      af.duration = dur * UPDATES_PER_MUDHOUR;
      af.modifier = DISEASE_FOODPOISON;
      af.location = APPLY_NONE;
      af.bitvector = 0;
      ch->affectTo(&af);
      disease_start(ch, &af);
    }
  }
}

void TEgg::eatMe(TBeing *ch)
{
  if ((ch->getCond(FULL) > 20) && !ch->isImmortal()) {
    ch->sendTo("You try to stuff another egg food into your mouth, but alas, you are full!\n\r");
    return;
  }
  if (isFoodFlag(FOOD_SPOILED) && ch->isPerceptive()) {
    act("You gag at the smell of $p and discard it instead.", TRUE, ch, this, 0, TO_CHAR);
    act("$n gags at the smell of $p and throws it out.", TRUE, ch, this, 0, TO_ROOM);

    ch->playsound(SOUND_FOODPOISON, SOUND_TYPE_NOISE);

    delete this;
    return;
  }

  act("$n eats $p.", TRUE, ch, this, 0, TO_ROOM);
  act("You eat the $o.", FALSE, ch, this, 0, TO_CHAR);

  if(ch->isVampire()){
    ch->sendTo("You eat the mortal food, but it has no affect on you.\n\r");
  } else {
    if (ch->getCond(FULL) > -1)
      ch->gainCondition(FULL, TFood::getFoodFill());
  }

  if (ch->getCond(FULL) > 20)
    act("You are full.", FALSE, ch, 0, 0, TO_CHAR);

  if (!ch->isImmortal()) {
    eggPoisoned(this, ch, getFoodFill());
    eggSpoiled(this, ch, getFoodFill());
  }
  delete this;
}

void TEgg::tasteMe(TBeing *ch)
{
  if (ch->hasDisease(DISEASE_FOODPOISON)) {
    ch->sendTo("Uggh, your stomach feels just horrible and the thought of eggs nauseates you.\n\r");
    ch->sendTo("You decide to skip this meal until you feel better.\n\r");
    return;
  }
  act("$n tastes the $o.", FALSE, ch, this, 0, TO_ROOM);
  act("You taste the $o.", FALSE, ch, this, 0, TO_CHAR);

  if(ch->isVampire()){
    ch->sendTo("You eat the mortal food, but it has no affect on you.\n\r");
  } else {
    ch->gainCondition(FULL, 1);
  }

  if (ch->getCond(FULL) > 20)
    act("You are full.", FALSE, ch, 0, 0, TO_CHAR);

  if (!ch->isImmortal()) {
    eggPoisoned(this, ch, 1);
  }
  if (isFoodFlag(FOOD_SPOILED)) {
    ch->sendTo("Blah, that egg is spoiled!\n\r");
    ch->sendTo("No point in keeping it around now...\n\r");
    delete this;
    return;
  }

  // we filled them "1 unit"
  // let's actually remove "1+ unit" so that we insure that taste isn't
  // better at filling than outright eating
  setFoodFill(getFoodFill() - 2);

  if (getFoodFill() <= 0) {    /* Nothing left */
    act("There is nothing left now.", FALSE, ch, 0, 0, TO_CHAR);
    delete this;
    return;
  }
  return;
}

bool TEgg::getEggTouched() const
{
  return touched;
}

void TEgg::setEggTouched(bool r)
{
  touched = r;
}

int TEgg::getEggTimer() const
{
  return incubationTimer;
}

void TEgg::setEggTimer(int r)
{
  incubationTimer = r;
}

int TEgg::getEggMobVNum() const
{
  return mobVNum;
}

void TEgg::setEggMobVNum(int r)
{
  mobVNum = r;
}

void TEgg::lowCheck()
{
  TFood::lowCheck();
}

sstring TEgg::statObjInfo() const
{
  char buf[256];

  sprintf(buf, "Makes full : %d\n\rPoisoned : %d\n\rIncubation timer : %d\n\rMob vnum : %d\n\rTouched : %d",
    getFoodFill(), getFoodFlags(), getEggTimer(), getEggMobVNum(),
    getEggTouched());

  sstring a(buf);
  return a;
}

void TEgg::assignFourValues(int x1, int x2, int x3, int x4)
{
  TFood::assignFourValues(x1, x2, x3, x4);

  setEggTouched(GET_BITS(x1, 31, 1));
  setEggTimer(x2);
  setEggMobVNum(x3);
}

void TEgg::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  TFood::getFourValues(x1, x2, x3, x4);

  int r = *x1;
  SET_BITS(r, 31, 1, getEggTouched());
  *x1 = r;

  *x2 = getEggTimer();
  *x3 = getEggMobVNum();
}

sstring TEgg::displayFourValues()
{
  char tString[256];
  int x1, x2, x3, x4;

  getFourValues(&x1, &x2, &x3, &x4);
  sprintf(tString, "Current values : %d %d %d %d\n\r", x1, x2, x3, x4);

  sprintf(tString + strlen(tString),
          "Current values : Touched[%d] Food Fill[%d]\n\r\
Incubation Timer[%d] Mob VNum[%d] Food Flags[%d]",
          getEggTouched(), getFoodFill(), getEggTimer(), getEggMobVNum(),
          getFoodFlags());

  return tString;
}

void TEgg::changeObjValue1(TBeing *ch)
{
  ch->specials.edit = CHANGE_EGG_VALUE1;
  change_egg_value1(ch, this, "", ENTER_CHECK);
  return;
}

int TEgg::chiMe(TBeing *tLunatic)
{
  int tMana  = ::number(10, 30),
      bKnown = tLunatic->getSkillLevel(SKILL_CHI);

  if (tLunatic->getMana() < tMana) {
    tLunatic->sendTo("You lack the chi to do this.\n\r");
    return RET_STOP_PARSING;
  } else
    tLunatic->reconcileMana(TYPE_UNDEFINED, 0, tMana);

  if (!bSuccess(tLunatic, bKnown, SKILL_CHI) || isFoodFlag(FOOD_SPOILED)) {
    act("You fail to affect $p in any way.",
        FALSE, tLunatic, this, NULL, TO_CHAR);
    return true;
  }

  act("You focus your chi, causing $p to get warmer!",
      FALSE, tLunatic, this, NULL, TO_CHAR);
  act("$n stares at $p, causing it to get warmer!",
      TRUE, tLunatic, this, NULL, TO_ROOM);
  act("$p begins to wiggle a bit.",
      TRUE, tLunatic, this, NULL, TO_CHAR);
  act("$p begins to wiggle a bit.",
      TRUE, tLunatic, this, NULL, TO_ROOM);

  obj_flags.decay_time += ::number(1, 3);
  incubationTimer = 1;

  return true;
}

int TEgg::getMe(TBeing *ch, TThing *sub)
{
  // do baseclass stuff
  int rc = TObj::getMe(ch, sub);
  if (rc)
    return rc;

  touched=TRUE;

  return TRUE;
}

void TEgg::hatch(TRoom *rp)
{
  TMonster *mob;
  TBeing *ch;
  affectedData aff;

  if (!(mob = read_mobile(mobVNum, VIRTUAL))) {
    vlogf(LOG_BUG, "Problem loading monster in TEgg::hatch");
    return;
  }

  *rp += *mob;
  mob->oldRoom = inRoom();
  act("Suddenly, $p begins to move violently from within!",
    TRUE, mob, this, NULL, TO_ROOM);
  act("With a final push, $n emerges from $p!",
    TRUE, mob, this, NULL, TO_ROOM);

  if(!mob->isAffected(AFF_AGGRESSIVE) && parent &&
     (ch=dynamic_cast<TBeing *>(parent)) && ch->isPc() &&
     mob->GetMaxLevel() < ch->GetMaxLevel() &&
     !ch->tooManyFollowers(mob, FOL_PET)){
    // this code was cut and pasted from the pet buying code, sorry :(
    mob->doAction(ch->name, CMD_STARE);

    SET_BIT(mob->specials.affectedBy, AFF_CHARM);
    ch->addFollower(mob);
    mob->balanceMakeNPCLikePC();

    aff.type = AFFECT_PET;
    aff.level = 0;
    aff.duration  = PERMANENT_DURATION;
    aff.location = APPLY_NONE;
    aff.modifier = 0;   // to be used for elemental skill level
    aff.bitvector = 0;

    char * tmp = mud_str_dup(ch->name);
    aff.be = (TThing *) tmp;

    mob->affectTo(&aff, -1);
  }
}

int TEgg::eggIncubate()
{
  return --incubationTimer;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>
#include <wallet/wallet.h>
#include <wallet/coinselection.h>

#include <set>

static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<OutputGroup>& groups)
{
    int nInput = 0;

    static int nextLockTime = 0;
    CMutableTransaction tx;
    tx.nLockTime = nextLockTime++; // so all transactions get different hashes
    tx.vout.resize(nInput + 1);
    tx.vout[nInput].nValue = nValue;
    CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));

    int nAge = 6 * 24;
    COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
    groups.emplace_back(output.GetInputCoin(), 0, false, 0, 0);
}

// Simple benchmark for wallet coin selection. Note that it maybe be necessary
// to build up more complicated scenarios in order to get meaningful
// measurements of performance. From laanwj, "Wallet coin selection is probably
// the hardest, as you need a wider selection of scenarios, just testing the
// same one over and over isn't too useful. Generating random isn't useful
// either for measurements."
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CoinSelection(benchmark::State& state)
{
    const CWallet wallet("dummy", WalletDatabase::CreateDummy());
    LOCK(wallet.cs_wallet);

    // Add coins.
    std::vector<OutputGroup> groups;
    for (int i = 0; i < 1000; ++i) {
        addCoin(1000 * COIN, wallet, groups);
    }
    addCoin(3 * COIN, wallet, groups);

    const CoinEligibilityFilter filter_standard(1, 6, 0);
    const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0);
    while (state.KeepRunning()) {
        std::set<CInputCoin> setCoinsRet;
        CAmount nValueRet;
        bool bnb_used;
        bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used);
        assert(success);
        assert(nValueRet == 1003 * COIN);
        assert(setCoinsRet.size() == 2);
    }
}

typedef std::set<CInputCoin> CoinSet;
static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn;

// Copied from src/wallet/test/coinselector_tests.cpp
static void add_coin(const CAmount& nValue, int nInput, std::vector<OutputGroup>& set)
{
    CMutableTransaction tx;
    tx.vout.resize(nInput + 1);
    tx.vout[nInput].nValue = nValue;
    std::unique_ptr<CWalletTx> wtx(new CWalletTx(&testWallet, MakeTransactionRef(std::move(tx))));
    set.emplace_back(COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true, 0, 0);
    wtxn.emplace_back(std::move(wtx));
}
// Copied from src/wallet/test/coinselector_tests.cpp
static CAmount make_hard_case(int utxos, std::vector<OutputGroup>& utxo_pool)
{
    utxo_pool.clear();
    CAmount target = 0;
    for (int i = 0; i < utxos; ++i) {
        target += (CAmount)1 << (utxos+i);
        add_coin((CAmount)1 << (utxos+i), 2*i, utxo_pool);
        add_coin(((CAmount)1 << (utxos+i)) + ((CAmount)1 << (utxos-1-i)), 2*i + 1, utxo_pool);
    }
    return target;
}

static void BnBExhaustion(benchmark::State& state)
{
    // Setup
    std::vector<OutputGroup> utxo_pool;
    CoinSet selection;
    CAmount value_ret = 0;
    CAmount not_input_fees = 0;

    while (state.KeepRunning()) {
        // Benchmark
        CAmount target = make_hard_case(17, utxo_pool);
        SelectCoinsBnB(utxo_pool, target, 0, selection, value_ret, not_input_fees); // Should exhaust

        // Cleanup
        utxo_pool.clear();
        selection.clear();
    }
}

BENCHMARK(CoinSelection, 650);
BENCHMARK(BnBExhaustion, 650);
<commit_msg>bench: Make CoinSelection output groups pass eligibility filter<commit_after>// Copyright (c) 2012-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>
#include <wallet/wallet.h>
#include <wallet/coinselection.h>

#include <set>

static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<OutputGroup>& groups)
{
    int nInput = 0;

    static int nextLockTime = 0;
    CMutableTransaction tx;
    tx.nLockTime = nextLockTime++; // so all transactions get different hashes
    tx.vout.resize(nInput + 1);
    tx.vout[nInput].nValue = nValue;
    CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));

    int nAge = 6 * 24;
    COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
    groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
}

// Simple benchmark for wallet coin selection. Note that it maybe be necessary
// to build up more complicated scenarios in order to get meaningful
// measurements of performance. From laanwj, "Wallet coin selection is probably
// the hardest, as you need a wider selection of scenarios, just testing the
// same one over and over isn't too useful. Generating random isn't useful
// either for measurements."
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CoinSelection(benchmark::State& state)
{
    const CWallet wallet("dummy", WalletDatabase::CreateDummy());
    LOCK(wallet.cs_wallet);

    // Add coins.
    std::vector<OutputGroup> groups;
    for (int i = 0; i < 1000; ++i) {
        addCoin(1000 * COIN, wallet, groups);
    }
    addCoin(3 * COIN, wallet, groups);

    const CoinEligibilityFilter filter_standard(1, 6, 0);
    const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0);
    while (state.KeepRunning()) {
        std::set<CInputCoin> setCoinsRet;
        CAmount nValueRet;
        bool bnb_used;
        bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used);
        assert(success);
        assert(nValueRet == 1003 * COIN);
        assert(setCoinsRet.size() == 2);
    }
}

typedef std::set<CInputCoin> CoinSet;
static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn;

// Copied from src/wallet/test/coinselector_tests.cpp
static void add_coin(const CAmount& nValue, int nInput, std::vector<OutputGroup>& set)
{
    CMutableTransaction tx;
    tx.vout.resize(nInput + 1);
    tx.vout[nInput].nValue = nValue;
    std::unique_ptr<CWalletTx> wtx(new CWalletTx(&testWallet, MakeTransactionRef(std::move(tx))));
    set.emplace_back(COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true, 0, 0);
    wtxn.emplace_back(std::move(wtx));
}
// Copied from src/wallet/test/coinselector_tests.cpp
static CAmount make_hard_case(int utxos, std::vector<OutputGroup>& utxo_pool)
{
    utxo_pool.clear();
    CAmount target = 0;
    for (int i = 0; i < utxos; ++i) {
        target += (CAmount)1 << (utxos+i);
        add_coin((CAmount)1 << (utxos+i), 2*i, utxo_pool);
        add_coin(((CAmount)1 << (utxos+i)) + ((CAmount)1 << (utxos-1-i)), 2*i + 1, utxo_pool);
    }
    return target;
}

static void BnBExhaustion(benchmark::State& state)
{
    // Setup
    std::vector<OutputGroup> utxo_pool;
    CoinSet selection;
    CAmount value_ret = 0;
    CAmount not_input_fees = 0;

    while (state.KeepRunning()) {
        // Benchmark
        CAmount target = make_hard_case(17, utxo_pool);
        SelectCoinsBnB(utxo_pool, target, 0, selection, value_ret, not_input_fees); // Should exhaust

        // Cleanup
        utxo_pool.clear();
        selection.clear();
    }
}

BENCHMARK(CoinSelection, 650);
BENCHMARK(BnBExhaustion, 650);
<|endoftext|>


<commit_before>/* Gobby - GTK-based collaborative text editor
 * Copyright (C) 2008, 2009 Armin Burgmeier <armin@arbur.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _GOBBY_WINDOW_HPP_
#define _GOBBY_WINDOW_HPP_

#include "features.hpp"

#include "commands/autosave-commands.hpp"
#include "commands/browser-commands.hpp"
#include "commands/browser-context-commands.hpp"
#include "commands/folder-commands.hpp"
#include "commands/file-commands.hpp"
#include "commands/edit-commands.hpp"
#include "commands/view-commands.hpp"
#include "commands/help-commands.hpp"
#include "operations/operations.hpp"

#include "dialogs/initial-dialog.hpp"

#include "core/iconmanager.hpp"
#include "core/header.hpp"
#include "core/folder.hpp"
#include "core/browser.hpp"
#include "core/statusbar.hpp"
#include "core/preferences.hpp"
#include "core/filechooser.hpp"
#include "core/titlebar.hpp"

#include "util/config.hpp"

#include <gtkmm/window.h>
#include <gtkmm/paned.h>
#include <gtkmm/messagedialog.h>

#ifdef WITH_UNIQUE
# include <unique/unique.h>
#endif

#include <memory>

namespace Gobby
{

class Window : public Gtk::Window
{
public:
	Window(unsigned int argc, const char* const argv[],
	       const IconManager& icon_mgr, Config& config
#ifdef WITH_UNIQUE
	       , UniqueApp* app
#endif
	       );
	~Window();

	const Folder& get_folder() const { return m_folder; }
	Folder& get_folder() { return m_folder; }

protected:
#ifdef WITH_UNIQUE
	static UniqueResponse
	on_message_received_static(UniqueApp* app,
	                           UniqueCommand command,
	                           UniqueMessageData* message,
	                           guint time,
	                           gpointer user_data)
	{
		return static_cast<Window*>(user_data)->on_message_received(
			command, message, time);
	}
#endif

	// Gtk::Window overrides
	virtual bool on_delete_event(GdkEventAny* event);
	virtual bool on_key_press_event(GdkEventKey* event);

	virtual void on_realize();
	virtual void on_show();

	void on_initial_dialog_hide();

#ifdef WITH_UNIQUE
	UniqueResponse on_message_received(UniqueCommand command,
	                                   UniqueMessageData* message,
	                                   guint time);
#endif

	// Command line arguments
	// TODO: We only require these in on_show to initially open files
	// passed on the command line. We can't do it in the constructor
	// already, because otherwise the main window is shown after the
	// document location dialog, and therefore ends up having focus,
	// which it shouldn't. Maybe we'll find a better solution which does
	// not require these member variables.
	const unsigned int m_argc;
	const char* const* m_argv;

	// Config
	Config& m_config;
	GtkSourceLanguageManager* m_lang_manager;
	Preferences m_preferences;
	const IconManager& m_icon_mgr;

#ifdef WITH_UNIQUE
	UniqueApp* m_app;
#endif

	// GUI
	Gtk::VBox m_mainbox;
	Gtk::HPaned m_paned;

	Header m_header;
	Browser m_browser;
	Folder m_folder;
	StatusBar m_statusbar;

	// Functionality
	DocumentInfoStorage m_info_storage;
	FileChooser m_file_chooser;
	Operations m_operations;

	AutosaveCommands m_commands_autosave;
	BrowserCommands m_commands_browser;
	BrowserContextCommands m_commands_browser_context;
	FolderCommands m_commands_folder;
	FileCommands m_commands_file;
	EditCommands m_commands_edit;
	ViewCommands m_commands_view;
	HelpCommands m_commands_help;

	TitleBar m_title_bar;

	// Dialogs
	std::auto_ptr<InitialDialog> m_initial_dlg;
};

}

#endif // _GOBBY_WINDOW_HPP_
<commit_msg>Gobby::Window: Added connect_to_host function forwarding to m_browser<commit_after>/* Gobby - GTK-based collaborative text editor
 * Copyright (C) 2008, 2009 Armin Burgmeier <armin@arbur.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _GOBBY_WINDOW_HPP_
#define _GOBBY_WINDOW_HPP_

#include "features.hpp"

#include "commands/autosave-commands.hpp"
#include "commands/browser-commands.hpp"
#include "commands/browser-context-commands.hpp"
#include "commands/folder-commands.hpp"
#include "commands/file-commands.hpp"
#include "commands/edit-commands.hpp"
#include "commands/view-commands.hpp"
#include "commands/help-commands.hpp"
#include "operations/operations.hpp"

#include "dialogs/initial-dialog.hpp"

#include "core/iconmanager.hpp"
#include "core/header.hpp"
#include "core/folder.hpp"
#include "core/browser.hpp"
#include "core/statusbar.hpp"
#include "core/preferences.hpp"
#include "core/filechooser.hpp"
#include "core/titlebar.hpp"

#include "util/config.hpp"

#include <gtkmm/window.h>
#include <gtkmm/paned.h>
#include <gtkmm/messagedialog.h>

#ifdef WITH_UNIQUE
# include <unique/unique.h>
#endif

#include <memory>

namespace Gobby
{

class Window : public Gtk::Window
{
public:
	Window(unsigned int argc, const char* const argv[],
	       const IconManager& icon_mgr, Config& config
#ifdef WITH_UNIQUE
	       , UniqueApp* app
#endif
	       );
	~Window();

	const Folder& get_folder() const { return m_folder; }
	Folder& get_folder() { return m_folder; }

	void connect_to_host(const Glib::ustring& hostname)
	{
		m_browser.connect_to_host(hostname);
	}

protected:
#ifdef WITH_UNIQUE
	static UniqueResponse
	on_message_received_static(UniqueApp* app,
	                           UniqueCommand command,
	                           UniqueMessageData* message,
	                           guint time,
	                           gpointer user_data)
	{
		return static_cast<Window*>(user_data)->on_message_received(
			command, message, time);
	}
#endif

	// Gtk::Window overrides
	virtual bool on_delete_event(GdkEventAny* event);
	virtual bool on_key_press_event(GdkEventKey* event);

	virtual void on_realize();
	virtual void on_show();

	void on_initial_dialog_hide();

#ifdef WITH_UNIQUE
	UniqueResponse on_message_received(UniqueCommand command,
	                                   UniqueMessageData* message,
	                                   guint time);
#endif

	// Command line arguments
	// TODO: We only require these in on_show to initially open files
	// passed on the command line. We can't do it in the constructor
	// already, because otherwise the main window is shown after the
	// document location dialog, and therefore ends up having focus,
	// which it shouldn't. Maybe we'll find a better solution which does
	// not require these member variables.
	const unsigned int m_argc;
	const char* const* m_argv;

	// Config
	Config& m_config;
	GtkSourceLanguageManager* m_lang_manager;
	Preferences m_preferences;
	const IconManager& m_icon_mgr;

#ifdef WITH_UNIQUE
	UniqueApp* m_app;
#endif

	// GUI
	Gtk::VBox m_mainbox;
	Gtk::HPaned m_paned;

	Header m_header;
	Browser m_browser;
	Folder m_folder;
	StatusBar m_statusbar;

	// Functionality
	DocumentInfoStorage m_info_storage;
	FileChooser m_file_chooser;
	Operations m_operations;

	AutosaveCommands m_commands_autosave;
	BrowserCommands m_commands_browser;
	BrowserContextCommands m_commands_browser_context;
	FolderCommands m_commands_folder;
	FileCommands m_commands_file;
	EditCommands m_commands_edit;
	ViewCommands m_commands_view;
	HelpCommands m_commands_help;

	TitleBar m_title_bar;

	// Dialogs
	std::auto_ptr<InitialDialog> m_initial_dlg;
};

}

#endif // _GOBBY_WINDOW_HPP_
<|endoftext|>


<commit_before>class ExitCounter{
    public:
        static int get();
        static int dec();
    private:
        // If fastforwarding is turned of the count
        // needs to be manually changed to 0 here.
        ExitCounter(){ count=0; };
        static ExitCounter * instance;
        int count;

};
<commit_msg>Assume fast forwarding is used by default.<commit_after>class ExitCounter{
    public:
        static int get();
        static int dec();
    private:
        // If fastforwarding is turned of the count
        // needs to be manually changed to 0 here.
        ExitCounter(){ count=1; };
        static ExitCounter * instance;
        int count;

};
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#include "query_optimizer/rules/PushDownLowCostDisjunctivePredicate.hpp"

#include <cstddef>
#include <vector>

#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp"
#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/expressions/LogicalAnd.hpp"
#include "query_optimizer/expressions/LogicalOr.hpp"
#include "query_optimizer/expressions/PatternMatcher.hpp"
#include "query_optimizer/expressions/Predicate.hpp"
#include "query_optimizer/physical/Aggregate.hpp"
#include "query_optimizer/physical/HashJoin.hpp"
#include "query_optimizer/physical/NestedLoopsJoin.hpp"
#include "query_optimizer/physical/PatternMatcher.hpp"
#include "query_optimizer/physical/Physical.hpp"
#include "query_optimizer/physical/PhysicalType.hpp"
#include "query_optimizer/physical/Selection.hpp"
#include "query_optimizer/physical/TableReference.hpp"
#include "query_optimizer/physical/TopLevelPlan.hpp"

#include "gflags/gflags.h"

#include "glog/logging.h"

namespace quickstep {
namespace optimizer {

DEFINE_uint64(push_down_disjunctive_predicate_cardinality_threshold, 100u,
              "The cardinality threshold for a stored relation for the "
              "PushDownLowCostDisjunctivePredicate optimization rule to push "
              "down a disjunctive predicate to pre-filter that relation.");

namespace E = ::quickstep::optimizer::expressions;
namespace P = ::quickstep::optimizer::physical;

P::PhysicalPtr PushDownLowCostDisjunctivePredicate::apply(const P::PhysicalPtr &input) {
  DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan);

  const P::TopLevelPlanPtr top_level_plan =
     std::static_pointer_cast<const P::TopLevelPlan>(input);
  cost_model_.reset(
      new cost::StarSchemaSimpleCostModel(
          top_level_plan->shared_subplans()));

  collectApplicablePredicates(input);

  if (!applicable_predicates_.empty()) {
    // Apply the selected predicates to stored relations.
    return attachPredicates(input);
  } else {
    return input;
  }
}

void PushDownLowCostDisjunctivePredicate::collectApplicablePredicates(
    const physical::PhysicalPtr &input) {
  P::TableReferencePtr table_reference;
  if (P::SomeTableReference::MatchesWithConditionalCast(input, &table_reference)) {
    // Consider only stored relations with small cardinality as targets.
    if (cost_model_->estimateCardinality(input) <=
            FLAGS_push_down_disjunctive_predicate_cardinality_threshold) {
      applicable_nodes_.emplace_back(input, &table_reference->attribute_list());
    }
    return;
  }

  for (const auto &child : input->children()) {
    collectApplicablePredicates(child);
  }

  E::PredicatePtr filter_predicate = nullptr;
  switch (input->getPhysicalType()) {
    case P::PhysicalType::kAggregate: {
      filter_predicate =
          std::static_pointer_cast<const P::Aggregate>(input)->filter_predicate();
      break;
    }
    case P::PhysicalType::kHashJoin: {
      const P::HashJoinPtr hash_join =
          std::static_pointer_cast<const P::HashJoin>(input);
      if (hash_join->join_type() == P::HashJoin::JoinType::kInnerJoin) {
        filter_predicate = hash_join->residual_predicate();
      }
      break;
    }
    case P::PhysicalType::kNestedLoopsJoin: {
      filter_predicate =
          std::static_pointer_cast<const P::NestedLoopsJoin>(input)->join_predicate();
      break;
    }
    case P::PhysicalType::kSelection: {
      filter_predicate =
          std::static_pointer_cast<const P::Selection>(input)->filter_predicate();
      break;
    }
    default:
      break;
  }

  E::LogicalOrPtr disjunctive_predicate;
  if (filter_predicate == nullptr ||
      !E::SomeLogicalOr::MatchesWithConditionalCast(filter_predicate, &disjunctive_predicate)) {
    return;
  }

  // Consider only disjunctive normal form, i.e. disjunction of conjunctions.
  // Divide the disjunctive components into groups.
  std::vector<std::vector<E::PredicatePtr>> candidate_predicates;
  std::vector<std::vector<std::vector<E::AttributeReferencePtr>>> candidate_attributes;
  for (const auto &conjunctive_predicate : disjunctive_predicate->operands()) {
    candidate_predicates.emplace_back();
    candidate_attributes.emplace_back();
    E::LogicalAndPtr logical_and;
    if (E::SomeLogicalAnd::MatchesWithConditionalCast(conjunctive_predicate, &logical_and)) {
      for (const auto &predicate : logical_and->operands()) {
        candidate_predicates.back().emplace_back(predicate);
        candidate_attributes.back().emplace_back(
            predicate->getReferencedAttributes());
      }
    } else {
      candidate_predicates.back().emplace_back(conjunctive_predicate);
      candidate_attributes.back().emplace_back(
          conjunctive_predicate->getReferencedAttributes());
    }
  }

  // Check whether the conditions are met for pushing down part of the predicates
  // to each small-cardinality stored relation.
  for (const auto &node_pair : applicable_nodes_) {
    const std::vector<E::AttributeReferencePtr> &target_attributes = *node_pair.second;
    std::vector<E::PredicatePtr> selected_disj_preds;
    for (std::size_t i = 0; i < candidate_predicates.size(); ++i) {
      const auto &cand_preds = candidate_predicates[i];
      const auto &cand_attrs = candidate_attributes[i];

      std::vector<E::PredicatePtr> selected_conj_preds;
      for (std::size_t j = 0; j < cand_preds.size(); ++j) {
        if (E::SubsetOfExpressions(cand_attrs[j], target_attributes)) {
          selected_conj_preds.emplace_back(cand_preds[j]);
        }
      }
      if (selected_conj_preds.empty()) {
        // Not every disjunctive component contains a predicate that can be applied
        // to the table reference node -- condition failed, exit.
        selected_disj_preds.clear();
        break;
      } else {
        selected_disj_preds.emplace_back(
            CreateConjunctive(selected_conj_preds));
      }
    }
    if (!selected_disj_preds.empty()) {
      applicable_predicates_[node_pair.first].add(
          CreateDisjunctive(selected_disj_preds));
    }
  }
}

P::PhysicalPtr PushDownLowCostDisjunctivePredicate::attachPredicates(
    const P::PhysicalPtr &input) const {
  std::vector<P::PhysicalPtr> new_children;
  for (const P::PhysicalPtr &child : input->children()) {
    const P::PhysicalPtr new_child = attachPredicates(child);
    new_children.push_back(new_child);
  }

  const P::PhysicalPtr output =
      new_children == input->children() ? input
                                        : input->copyWithNewChildren(new_children);

  const auto &node_it = applicable_predicates_.find(input);
  if (node_it != applicable_predicates_.end()) {
    const E::PredicatePtr filter_predicate =
        CreateConjunctive(node_it->second.predicates);
    return P::Selection::Create(output,
                                E::ToNamedExpressions(output->getOutputAttributes()),
                                filter_predicate);
  }

  return output;
}

E::PredicatePtr PushDownLowCostDisjunctivePredicate::CreateConjunctive(
    const std::vector<E::PredicatePtr> predicates) {
  DCHECK_GE(predicates.size(), 1u);
  if (predicates.size() == 1) {
    return predicates.front();
  } else {
    return E::LogicalAnd::Create(predicates);
  }
}

E::PredicatePtr PushDownLowCostDisjunctivePredicate::CreateDisjunctive(
    const std::vector<E::PredicatePtr> predicates) {
  DCHECK_GE(predicates.size(), 1u);
  if (predicates.size() == 1) {
    return predicates.front();
  } else {
    return E::LogicalOr::Create(predicates);
  }
}

}  // namespace optimizer
}  // namespace quickstep
<commit_msg>Improve disjunctive predicate pushdown to optimize more scenarios.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#include "query_optimizer/rules/PushDownLowCostDisjunctivePredicate.hpp"

#include <cstddef>
#include <vector>

#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp"
#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/expressions/LogicalAnd.hpp"
#include "query_optimizer/expressions/LogicalOr.hpp"
#include "query_optimizer/expressions/PatternMatcher.hpp"
#include "query_optimizer/expressions/Predicate.hpp"
#include "query_optimizer/physical/Aggregate.hpp"
#include "query_optimizer/physical/HashJoin.hpp"
#include "query_optimizer/physical/NestedLoopsJoin.hpp"
#include "query_optimizer/physical/PatternMatcher.hpp"
#include "query_optimizer/physical/Physical.hpp"
#include "query_optimizer/physical/PhysicalType.hpp"
#include "query_optimizer/physical/Selection.hpp"
#include "query_optimizer/physical/TableReference.hpp"
#include "query_optimizer/physical/TopLevelPlan.hpp"

#include "gflags/gflags.h"

#include "glog/logging.h"

namespace quickstep {
namespace optimizer {

DEFINE_uint64(push_down_disjunctive_predicate_cardinality_threshold, 100u,
              "The cardinality threshold for a stored relation for the "
              "PushDownLowCostDisjunctivePredicate optimization rule to push "
              "down a disjunctive predicate to pre-filter that relation.");

DEFINE_double(push_down_disjunctive_predicate_selectivity_threshold, 0.2,
              "The estimated selectivity threshold below which the "
              "PushDownLowCostDisjunctivePredicate optimization rule will push "
              "down a disjunctive predicate to pre-filter a stored relation.");

namespace E = ::quickstep::optimizer::expressions;
namespace P = ::quickstep::optimizer::physical;

P::PhysicalPtr PushDownLowCostDisjunctivePredicate::apply(const P::PhysicalPtr &input) {
  DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan);

  const P::TopLevelPlanPtr top_level_plan =
     std::static_pointer_cast<const P::TopLevelPlan>(input);
  cost_model_.reset(
      new cost::StarSchemaSimpleCostModel(
          top_level_plan->shared_subplans()));

  collectApplicablePredicates(input);

  if (!applicable_predicates_.empty()) {
    // Apply the selected predicates to stored relations.
    return attachPredicates(input);
  } else {
    return input;
  }
}

void PushDownLowCostDisjunctivePredicate::collectApplicablePredicates(
    const physical::PhysicalPtr &input) {
  P::TableReferencePtr table_reference;
  if (P::SomeTableReference::MatchesWithConditionalCast(input, &table_reference)) {
    applicable_nodes_.emplace_back(input, &table_reference->attribute_list());
    return;
  }

  for (const auto &child : input->children()) {
    collectApplicablePredicates(child);
  }

  E::PredicatePtr filter_predicate = nullptr;
  switch (input->getPhysicalType()) {
    case P::PhysicalType::kAggregate: {
      filter_predicate =
          std::static_pointer_cast<const P::Aggregate>(input)->filter_predicate();
      break;
    }
    case P::PhysicalType::kHashJoin: {
      const P::HashJoinPtr hash_join =
          std::static_pointer_cast<const P::HashJoin>(input);
      if (hash_join->join_type() == P::HashJoin::JoinType::kInnerJoin) {
        filter_predicate = hash_join->residual_predicate();
      }
      break;
    }
    case P::PhysicalType::kNestedLoopsJoin: {
      filter_predicate =
          std::static_pointer_cast<const P::NestedLoopsJoin>(input)->join_predicate();
      break;
    }
    case P::PhysicalType::kSelection: {
      filter_predicate =
          std::static_pointer_cast<const P::Selection>(input)->filter_predicate();
      break;
    }
    default:
      break;
  }

  E::LogicalOrPtr disjunctive_predicate;
  if (filter_predicate == nullptr ||
      !E::SomeLogicalOr::MatchesWithConditionalCast(filter_predicate, &disjunctive_predicate)) {
    return;
  }

  // Consider only disjunctive normal form, i.e. disjunction of conjunctions.
  // Divide the disjunctive components into groups.
  std::vector<std::vector<E::PredicatePtr>> candidate_predicates;
  std::vector<std::vector<std::vector<E::AttributeReferencePtr>>> candidate_attributes;
  for (const auto &conjunctive_predicate : disjunctive_predicate->operands()) {
    candidate_predicates.emplace_back();
    candidate_attributes.emplace_back();
    E::LogicalAndPtr logical_and;
    if (E::SomeLogicalAnd::MatchesWithConditionalCast(conjunctive_predicate, &logical_and)) {
      for (const auto &predicate : logical_and->operands()) {
        candidate_predicates.back().emplace_back(predicate);
        candidate_attributes.back().emplace_back(
            predicate->getReferencedAttributes());
      }
    } else {
      candidate_predicates.back().emplace_back(conjunctive_predicate);
      candidate_attributes.back().emplace_back(
          conjunctive_predicate->getReferencedAttributes());
    }
  }

  // Check whether the conditions are met for pushing down part of the predicates
  // to each small-cardinality stored relation.
  for (const auto &node_pair : applicable_nodes_) {
    const std::vector<E::AttributeReferencePtr> &target_attributes = *node_pair.second;
    std::vector<E::PredicatePtr> selected_disj_preds;
    for (std::size_t i = 0; i < candidate_predicates.size(); ++i) {
      const auto &cand_preds = candidate_predicates[i];
      const auto &cand_attrs = candidate_attributes[i];

      std::vector<E::PredicatePtr> selected_conj_preds;
      for (std::size_t j = 0; j < cand_preds.size(); ++j) {
        if (E::SubsetOfExpressions(cand_attrs[j], target_attributes)) {
          selected_conj_preds.emplace_back(cand_preds[j]);
        }
      }
      if (selected_conj_preds.empty()) {
        // Not every disjunctive component contains a predicate that can be applied
        // to the table reference node -- condition failed, exit.
        selected_disj_preds.clear();
        break;
      } else {
        selected_disj_preds.emplace_back(
            CreateConjunctive(selected_conj_preds));
      }
    }
    if (!selected_disj_preds.empty()) {
      applicable_predicates_[node_pair.first].add(
          CreateDisjunctive(selected_disj_preds));
    }
  }
}

P::PhysicalPtr PushDownLowCostDisjunctivePredicate::attachPredicates(
    const P::PhysicalPtr &input) const {
  std::vector<P::PhysicalPtr> new_children;
  for (const P::PhysicalPtr &child : input->children()) {
    const P::PhysicalPtr new_child = attachPredicates(child);
    new_children.push_back(new_child);
  }

  const P::PhysicalPtr output =
      new_children == input->children() ? input
                                        : input->copyWithNewChildren(new_children);

  const auto &node_it = applicable_predicates_.find(input);
  if (node_it != applicable_predicates_.end()) {
    const P::PhysicalPtr selection =
        P::Selection::Create(output,
                             E::ToNamedExpressions(output->getOutputAttributes()),
                             CreateConjunctive(node_it->second.predicates));

    // Applicable case 1: The stored relation has small cardinality.
    const bool is_small_cardinality_relation =
        cost_model_->estimateCardinality(input) <=
            FLAGS_push_down_disjunctive_predicate_cardinality_threshold;

    // Applicable case 2: The filter predicate has low selectivity.
    const bool is_selective_predicate =
        cost_model_->estimateSelectivityForFilterPredicate(selection) <=
            FLAGS_push_down_disjunctive_predicate_selectivity_threshold;

    if (is_small_cardinality_relation || is_selective_predicate) {
      return selection;
    }
  }

  return output;
}

E::PredicatePtr PushDownLowCostDisjunctivePredicate::CreateConjunctive(
    const std::vector<E::PredicatePtr> predicates) {
  DCHECK_GE(predicates.size(), 1u);
  if (predicates.size() == 1) {
    return predicates.front();
  } else {
    return E::LogicalAnd::Create(predicates);
  }
}

E::PredicatePtr PushDownLowCostDisjunctivePredicate::CreateDisjunctive(
    const std::vector<E::PredicatePtr> predicates) {
  DCHECK_GE(predicates.size(), 1u);
  if (predicates.size() == 1) {
    return predicates.front();
  } else {
    return E::LogicalOr::Create(predicates);
  }
}

}  // namespace optimizer
}  // namespace quickstep
<|endoftext|>


<commit_before>/* Copyright (c) 2011, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Karen Liu <karenliu@cc.gatech.edu>
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * This code incorporates portions of Open Dynamics Engine
 *     (Copyright (c) 2001-2004, Russell L. Smith. All rights
 *     reserved.) and portions of FCL (Copyright (c) 2011, Willow
 *     Garage, Inc. All rights reserved.), which were released under
 *     the same BSD license as below
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstdio>

#include "SimWindow.h"
#include "simulation/World.h"
#include "dynamics/Skeleton.h"
#include "constraint/ConstraintDynamics.h"
#include "collision/CollisionDetector.h"
#include "yui/GLFuncs.h"

namespace dart {
namespace simulation {

SimWindow::SimWindow()
    : Win3D()
{
    mBackground[0] = 1.0;
    mBackground[1] = 1.0;
    mBackground[2] = 1.0;
    mBackground[3] = 1.0;

    mPlay = false;
    mSimulating = false;
    mPlayFrame = 0;
    mShowMarkers = true;
    mPersp = 45.f;
    mTrans[1] = 300.f;
}

SimWindow::~SimWindow()
{
}

void SimWindow::drawSkels()
{
    for (int i = 0; i < mWorld->getNumSkeletons(); i++)
        mWorld->getSkeleton(i)->draw(mRI);
}

void SimWindow::displayTimer(int _val)
{
    int numIter = mDisplayTimeout / (mWorld->getTimeStep() * 1000);
    if (mPlay) {
        mPlayFrame += 16;
        if (mPlayFrame >= mBakedStates.size())
            mPlayFrame = 0;
    }else if (mSimulating) {
        for (int i = 0; i < numIter; i++) {
            timeStepping();
            bake();
        }
    }
    glutPostRedisplay();
    glutTimerFunc(mDisplayTimeout, refreshTimer, _val);
}

void SimWindow::draw()
{
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    if (!mSimulating) {
        if (mPlayFrame < mBakedStates.size()) {
            int nSkels = mWorld->getNumSkeletons();
            for (unsigned int i = 0; i < nSkels; i++) {
                int start = mWorld->getIndex(i);
                //int size = mWorld->getDofs(i).size();
                int size = mWorld->getSkeleton(i)->getDOF();
                mWorld->getSkeleton(i)->setPose(mBakedStates[mPlayFrame].segment(start, size), false, false);
            }
            if (mShowMarkers) {
                int sumDofs = mWorld->getIndex(nSkels);
                int nContact = (mBakedStates[mPlayFrame].size() - sumDofs) / 6;
                for (int i = 0; i < nContact; i++) {
                    Eigen::Vector3d v = mBakedStates[mPlayFrame].segment(sumDofs + i * 6, 3);
                    Eigen::Vector3d f = mBakedStates[mPlayFrame].segment(sumDofs + i * 6 + 3, 3) / 10.0;
                    glBegin(GL_LINES);
                    glVertex3f(v[0], v[1], v[2]);
                    glVertex3f(v[0] + f[0], v[1] + f[1], v[2] + f[2]);
                    glEnd();
                    mRI->setPenColor(Eigen::Vector3d(0.2, 0.2, 0.8));
                    mRI->pushMatrix();
                    glTranslated(v[0], v[1], v[2]);
                    mRI->drawEllipsoid(Eigen::Vector3d(0.02, 0.02, 0.02));
                    mRI->popMatrix();
                }
            }
        }
    }else{
        if (mShowMarkers) {
            for (int k = 0; k < mWorld->getCollisionHandle()->getCollisionChecker()->getNumContacts(); k++) {
                Eigen::Vector3d v = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(k).point;
                Eigen::Vector3d f = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(k).force / 10.0;
                glBegin(GL_LINES);
                glVertex3f(v[0], v[1], v[2]);
                glVertex3f(v[0] + f[0], v[1] + f[1], v[2] + f[2]);
                glEnd();
                mRI->setPenColor(Eigen::Vector3d(0.2, 0.2, 0.8));
                mRI->pushMatrix();
                glTranslated(v[0], v[1], v[2]);
                mRI->drawEllipsoid(Eigen::Vector3d(0.02, 0.02, 0.02));
                mRI->popMatrix();
            }
        }
    }
    drawSkels();

    // display the frame count in 2D text
    char buff[64];
    if (!mSimulating)
        sprintf(buff, "%d", mPlayFrame);
    else
        sprintf(buff, "%d", mWorld->getSimFrames());
    std::string frame(buff);
    glColor3f(0.0, 0.0, 0.0);
    yui::drawStringOnScreen(0.02f, 0.02f, frame);
    glEnable(GL_LIGHTING);
}

void SimWindow::keyboard(unsigned char key, int x, int y)
{
    switch(key){
        case ' ': // use space key to play or stop the motion
            mSimulating = !mSimulating;
            if(mSimulating) {
                mPlay = false;
                glutTimerFunc( mDisplayTimeout, refreshTimer, 0);
            }
            break;
        case 'p': // playBack
            mPlay = !mPlay;
            if (mPlay) {
                mSimulating = false;
                glutTimerFunc( mDisplayTimeout, refreshTimer, 0);
            }
            break;
        case '[': // step backward
            if (!mSimulating) {
                mPlayFrame--;
                if(mPlayFrame < 0)
                    mPlayFrame = 0;
                glutPostRedisplay();
            }
            break;
        case ']': // step forwardward
            if (!mSimulating) {
                mPlayFrame++;
                if(mPlayFrame >= mBakedStates.size())
                    mPlayFrame = 0;
                glutPostRedisplay();
            }
            break;
        case 'v': // show or hide markers
            mShowMarkers = !mShowMarkers;
            break;
        default:
            Win3D::keyboard(key,x,y);
    }
    glutPostRedisplay();
}

void SimWindow::bake()
{
    int nContact = mWorld->getCollisionHandle()->getCollisionChecker()->getNumContacts();
    Eigen::VectorXd state(mWorld->getIndex(mWorld->getNumSkeletons()) + 6 * nContact);
    for (unsigned int i = 0; i < mWorld->getNumSkeletons(); i++)
        state.segment(mWorld->getIndex(i), mWorld->getSkeleton(i)->getDOF()) = mWorld->getSkeleton(i)->getPose();
    for (int i = 0; i < nContact; i++) {
        int begin = mWorld->getIndex(mWorld->getNumSkeletons()) + i * 6;
        state.segment(begin, 3) = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(i).point;
        state.segment(begin + 3, 3) = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(i).force;
    }
    mBakedStates.push_back(state);
}

} // namespace simulation
} // namespace dart
<commit_msg>fixed the bug in SimWindow.cpp<commit_after>/* Copyright (c) 2011, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Karen Liu <karenliu@cc.gatech.edu>
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * This code incorporates portions of Open Dynamics Engine
 *     (Copyright (c) 2001-2004, Russell L. Smith. All rights
 *     reserved.) and portions of FCL (Copyright (c) 2011, Willow
 *     Garage, Inc. All rights reserved.), which were released under
 *     the same BSD license as below
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstdio>

#include "SimWindow.h"
#include "simulation/World.h"
#include "dynamics/Skeleton.h"
#include "constraint/ConstraintDynamics.h"
#include "collision/CollisionDetector.h"
#include "yui/GLFuncs.h"

namespace dart {
namespace simulation {

SimWindow::SimWindow()
    : Win3D()
{
    mBackground[0] = 1.0;
    mBackground[1] = 1.0;
    mBackground[2] = 1.0;
    mBackground[3] = 1.0;

    mPlay = false;
    mSimulating = false;
    mPlayFrame = 0;
    mShowMarkers = true;
    mPersp = 45.f;
    mTrans[1] = 300.f;
}

SimWindow::~SimWindow()
{
}

void SimWindow::drawSkels()
{
    for (int i = 0; i < mWorld->getNumSkeletons(); i++)
        mWorld->getSkeleton(i)->draw(mRI);
}

void SimWindow::displayTimer(int _val)
{
    int numIter = mDisplayTimeout / (mWorld->getTimeStep() * 1000);
    if (mPlay) {
        mPlayFrame += 16;
        if (mPlayFrame >= mBakedStates.size())
            mPlayFrame = 0;
    }else if (mSimulating) {
        for (int i = 0; i < numIter; i++) {
            timeStepping();
            bake();
        }
    }
    glutPostRedisplay();
    glutTimerFunc(mDisplayTimeout, refreshTimer, _val);
}

void SimWindow::draw()
{
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    if (!mSimulating) {
        if (mPlayFrame < mBakedStates.size()) {
            int nSkels = mWorld->getNumSkeletons();
            for (unsigned int i = 0; i < nSkels; i++) {
                int start = mWorld->getIndex(i);
                //int size = mWorld->getDofs(i).size();
                int size = mWorld->getSkeleton(i)->getDOF();
                mWorld->getSkeleton(i)->setPose(mBakedStates[mPlayFrame].segment(start, size), true, false);
            }
            if (mShowMarkers) {
                int sumDofs = mWorld->getIndex(nSkels);
                int nContact = (mBakedStates[mPlayFrame].size() - sumDofs) / 6;
                for (int i = 0; i < nContact; i++) {
                    Eigen::Vector3d v = mBakedStates[mPlayFrame].segment(sumDofs + i * 6, 3);
                    Eigen::Vector3d f = mBakedStates[mPlayFrame].segment(sumDofs + i * 6 + 3, 3) / 10.0;
                    glBegin(GL_LINES);
                    glVertex3f(v[0], v[1], v[2]);
                    glVertex3f(v[0] + f[0], v[1] + f[1], v[2] + f[2]);
                    glEnd();
                    mRI->setPenColor(Eigen::Vector3d(0.2, 0.2, 0.8));
                    mRI->pushMatrix();
                    glTranslated(v[0], v[1], v[2]);
                    mRI->drawEllipsoid(Eigen::Vector3d(0.02, 0.02, 0.02));
                    mRI->popMatrix();
                }
            }
        }
    }else{
        if (mShowMarkers) {
            for (int k = 0; k < mWorld->getCollisionHandle()->getCollisionChecker()->getNumContacts(); k++) {
                Eigen::Vector3d v = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(k).point;
                Eigen::Vector3d f = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(k).force / 10.0;
                glBegin(GL_LINES);
                glVertex3f(v[0], v[1], v[2]);
                glVertex3f(v[0] + f[0], v[1] + f[1], v[2] + f[2]);
                glEnd();
                mRI->setPenColor(Eigen::Vector3d(0.2, 0.2, 0.8));
                mRI->pushMatrix();
                glTranslated(v[0], v[1], v[2]);
                mRI->drawEllipsoid(Eigen::Vector3d(0.02, 0.02, 0.02));
                mRI->popMatrix();
            }
        }
    }
    drawSkels();

    // display the frame count in 2D text
    char buff[64];
    if (!mSimulating)
        sprintf(buff, "%d", mPlayFrame);
    else
        sprintf(buff, "%d", mWorld->getSimFrames());
    std::string frame(buff);
    glColor3f(0.0, 0.0, 0.0);
    yui::drawStringOnScreen(0.02f, 0.02f, frame);
    glEnable(GL_LIGHTING);
}

void SimWindow::keyboard(unsigned char key, int x, int y)
{
    switch(key){
        case ' ': // use space key to play or stop the motion
            mSimulating = !mSimulating;
            if(mSimulating) {
                mPlay = false;
                glutTimerFunc( mDisplayTimeout, refreshTimer, 0);
            }
            break;
        case 'p': // playBack
            mPlay = !mPlay;
            if (mPlay) {
                mSimulating = false;
                glutTimerFunc( mDisplayTimeout, refreshTimer, 0);
            }
            break;
        case '[': // step backward
            if (!mSimulating) {
                mPlayFrame--;
                if(mPlayFrame < 0)
                    mPlayFrame = 0;
                glutPostRedisplay();
            }
            break;
        case ']': // step forwardward
            if (!mSimulating) {
                mPlayFrame++;
                if(mPlayFrame >= mBakedStates.size())
                    mPlayFrame = 0;
                glutPostRedisplay();
            }
            break;
        case 'v': // show or hide markers
            mShowMarkers = !mShowMarkers;
            break;
        default:
            Win3D::keyboard(key,x,y);
    }
    glutPostRedisplay();
}

void SimWindow::bake()
{
    int nContact = mWorld->getCollisionHandle()->getCollisionChecker()->getNumContacts();
    Eigen::VectorXd state(mWorld->getIndex(mWorld->getNumSkeletons()) + 6 * nContact);
    for (unsigned int i = 0; i < mWorld->getNumSkeletons(); i++)
        state.segment(mWorld->getIndex(i), mWorld->getSkeleton(i)->getDOF()) = mWorld->getSkeleton(i)->getPose();
    for (int i = 0; i < nContact; i++) {
        int begin = mWorld->getIndex(mWorld->getNumSkeletons()) + i * 6;
        state.segment(begin, 3) = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(i).point;
        state.segment(begin + 3, 3) = mWorld->getCollisionHandle()->getCollisionChecker()->getContact(i).force;
    }
    mBakedStates.push_back(state);
}

} // namespace simulation
} // namespace dart
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     mnertclient.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     February, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of the Massachusetts General Hospital nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSACHUSETTS GENERAL HOSPITAL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the MneRtClient class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "mnertclient.h"
#include "mnertclientproducer.h"

#include "FormFiles/mnertclientsetupwidget.h"

#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QtPlugin>
#include <QtCore/QTextStream>
#include <QtCore/QFile>

#include <QList>
#include <QDebug>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MneRtClientPlugin;
using namespace UTILSLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

MneRtClient::MneRtClient()
: m_sMneRtClientClientAlias("mne-x")
, m_pRtCmdClient(NULL)
, m_pMneRtClientProducer(new MneRtClientProducer(this))
, m_sMneRtClientIP("127.0.0.1")//("172.21.16.88")//("127.0.0.1")
, m_bCmdClientIsConnected(false)
, m_iBufferSize(-1)
, m_pRawMatrixBuffer_In(0)
/*m_pRTMSA_MneRtClient(0)*/
{

}

//*************************************************************************************************************

MneRtClient::~MneRtClient()
{
    if(this->isRunning())
        stop();
    if(m_pMneRtClientProducer->isRunning())
        m_pMneRtClientProducer->stop();
}

//*************************************************************************************************************

QSharedPointer<IPlugin> MneRtClient::clone() const
{
    QSharedPointer<MneRtClient> pMneRtClientClone(new MneRtClient());
    return pMneRtClientClone;
}

//*************************************************************************************************************

void MneRtClient::init()
{
    // Start MneRtClientProducer
    m_pMneRtClientProducer->start();

//    //Convinience CMD connection timer --> ToDo get rid of that -> it interrupts acquistion when not connected
//    connect(&m_cmdConnectionTimer, &QTimer::timeout, this, &MneRtClient::connectCmdClient);

    //init channels when fiff info is available
    connect(this, &MneRtClient::fiffInfoAvailable, this, &MneRtClient::initConnector);

//    //Start convinience timer
//    m_cmdConnectionTimer.start(5000);

    //Try to connect the cmd client on start up using localhost connection
    this->connectCmdClient();
}

//*************************************************************************************************************
//=============================================================================================================
// Create measurement instances and config them
//=============================================================================================================

void MneRtClient::initConnector()
{

    qDebug() << "MneRtClient::init()";

//    if(m_pFiffInfo)
//    {
////        m_pFiffInfo->sfreq /= 100;
//        m_pRTMSA_MneRtClient = addProviderRealTimeMultiSampleArray_New(MSR_ID::MEGMNERTCLIENT_OUTPUT);
//        m_pRTMSA_MneRtClient->initFromFiffInfo(m_pFiffInfo);
//        m_pRTMSA_MneRtClient->setMultiArraySize(10);
//    }

    if(m_pFiffInfo)
    {
        m_pRTMSA_MneRtClient = PluginOutputData<NewRealTimeMultiSampleArray>::create(this, "RtClient", "MNE Rt Client");

        m_pRTMSA_MneRtClient->data()->initFromFiffInfo(m_pFiffInfo);
        m_pRTMSA_MneRtClient->data()->setMultiArraySize(10);

        m_pRTMSA_MneRtClient->data()->setVisibility(true);

        m_outputConnectors.append(m_pRTMSA_MneRtClient);
    }

}

//*************************************************************************************************************

void MneRtClient::changeConnector(qint32 p_iNewConnectorId)
{
    if(p_iNewConnectorId != m_iActiveConnectorId)
    {
        // read meas info
        (*m_pRtCmdClient)["selcon"].pValues()[0].setValue(p_iNewConnectorId);
        (*m_pRtCmdClient)["selcon"].send();

        m_iActiveConnectorId = p_iNewConnectorId;

        // clear all and request everything new
        clear();

        //
        // request available commands
        //
        m_pRtCmdClient->requestCommands();

        //
        // Read Info
        //
        if(!m_pFiffInfo)
            requestInfo();

        //
        // Read Buffer Size
        //
        m_iBufferSize = m_pRtCmdClient->requestBufsize();

        emit cmdConnectionChanged(m_bCmdClientIsConnected);
    }
}

//*************************************************************************************************************

void MneRtClient::clear()
{
    m_pFiffInfo.reset();
    m_iBufferSize = -1;
}

//*************************************************************************************************************

void MneRtClient::connectCmdClient()
{
    if(m_pRtCmdClient.isNull())
        m_pRtCmdClient = QSharedPointer<RtCmdClient>(new RtCmdClient);
    else if(m_bCmdClientIsConnected)
        this->disconnectCmdClient();

    m_pRtCmdClient->connectToHost(m_sMneRtClientIP);
    m_pRtCmdClient->waitForConnected(1000);

    if(m_pRtCmdClient->state() == QTcpSocket::ConnectedState)
    {
        rtServerMutex.lock();

        //Stop convinience timer
//        m_cmdConnectionTimer.stop();

        if(!m_bCmdClientIsConnected)
        {
            //
            // request available commands
            //
            m_pRtCmdClient->requestCommands();

            //
            // set cmd client is connected
            //
            m_bCmdClientIsConnected = true;

            //
            // Read Info
            //
            if(!m_pFiffInfo)
                requestInfo();

            //
            // Read Connectors
            //
            if(m_qMapConnectors.size() == 0)
                m_iActiveConnectorId = m_pRtCmdClient->requestConnectors(m_qMapConnectors);

            //
            // Read Buffer Size
            //
            m_iBufferSize = m_pRtCmdClient->requestBufsize();

            emit cmdConnectionChanged(m_bCmdClientIsConnected);
        }
        rtServerMutex.unlock();
    }
}

//*************************************************************************************************************

void MneRtClient::disconnectCmdClient()
{
    if(m_bCmdClientIsConnected)
    {
        m_pRtCmdClient->disconnectFromHost();
        m_pRtCmdClient->waitForDisconnected();
        rtServerMutex.lock();
        m_bCmdClientIsConnected = false;
        rtServerMutex.unlock();
        emit cmdConnectionChanged(m_bCmdClientIsConnected);
    }
}

//*************************************************************************************************************

void MneRtClient::requestInfo()
{
    if(m_pMneRtClientProducer->m_iDataClientId > -1 && m_bCmdClientIsConnected)
    {
        // read meas info
        (*m_pRtCmdClient)["measinfo"].pValues()[0].setValue(m_pMneRtClientProducer->m_iDataClientId);
        (*m_pRtCmdClient)["measinfo"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagInfoRequest = true;
        m_pMneRtClientProducer->producerMutex.unlock();
    }
    else
        qWarning() << "MneRtClientProducer is not connected!";
}

//*************************************************************************************************************

bool MneRtClient::start()
{
    if(m_bCmdClientIsConnected && m_pFiffInfo)
    {
        // Initialize real time measurements
        init();

        //Set buffer size
        (*m_pRtCmdClient)["bufsize"].pValues()[0].setValue(m_iBufferSize);
        (*m_pRtCmdClient)["bufsize"].send();

        // Buffer
        m_pRawMatrixBuffer_In = QSharedPointer<RawMatrixBuffer>(new RawMatrixBuffer(8,m_pFiffInfo->nchan,m_iBufferSize));

        // Start threads
        QThread::start();

        // Start Measurement at rt_Server
        // start measurement
        (*m_pRtCmdClient)["start"].pValues()[0].setValue(m_pMneRtClientProducer->m_iDataClientId);
        (*m_pRtCmdClient)["start"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagMeasuring = true;
        m_pMneRtClientProducer->producerMutex.unlock();
        m_pMneRtClientProducer->start();

        return true;
    }
    else
        return false;
}

//*************************************************************************************************************

bool MneRtClient::stop()
{
    if(m_bCmdClientIsConnected) //ToDo replace this with is running
    {
        // Stop Measurement at rt_Server
        (*m_pRtCmdClient)["stop-all"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagMeasuring = false;
        m_pMneRtClientProducer->producerMutex.unlock();
    }

    // Stop threads
    QThread::terminate();
    QThread::wait();

    //Clear Buffers

    return true;
}

//*************************************************************************************************************

IPlugin::PluginType MneRtClient::getType() const
{
    return _ISensor;
}

//*************************************************************************************************************

QString MneRtClient::getName() const
{
    return "RT Client";
}

//*************************************************************************************************************

QWidget* MneRtClient::setupWidget()
{
    MneRtClientSetupWidget* widget = new MneRtClientSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new

    //init dialog

    return widget;
}

//*************************************************************************************************************

void MneRtClient::run()
{

    MatrixXf matValue;
    while(true)
    {
        //pop matrix
        matValue = m_pRawMatrixBuffer_In->pop();
//        std::cout << "matValue " << matValue.block(0,0,1,10) << std::endl;

        //emit values
        for(qint32 i = 0; i < matValue.cols(); ++i)
            m_pRTMSA_MneRtClient->data()->setValue(matValue.col(i).cast<double>());
//        for(qint32 i = 0; i < matValue.cols(); i += 100)
//            m_pRTMSA_MneRtClient->setValue(matValue.col(i).cast<double>());
    }
}
<commit_msg>mne rt client fix<commit_after>//=============================================================================================================
/**
* @file     mnertclient.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     February, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of the Massachusetts General Hospital nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSACHUSETTS GENERAL HOSPITAL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the MneRtClient class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "mnertclient.h"
#include "mnertclientproducer.h"

#include "FormFiles/mnertclientsetupwidget.h"

#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QtPlugin>
#include <QtCore/QTextStream>
#include <QtCore/QFile>

#include <QList>
#include <QDebug>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MneRtClientPlugin;
using namespace UTILSLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

MneRtClient::MneRtClient()
: m_sMneRtClientClientAlias("mne-x")
, m_pRtCmdClient(NULL)
, m_pMneRtClientProducer(new MneRtClientProducer(this))
, m_sMneRtClientIP("127.0.0.1")//("172.21.16.88")//("127.0.0.1")
, m_bCmdClientIsConnected(false)
, m_iBufferSize(-1)
, m_pRawMatrixBuffer_In(0)
/*m_pRTMSA_MneRtClient(0)*/
{

}

//*************************************************************************************************************

MneRtClient::~MneRtClient()
{
    if(this->isRunning())
        stop();
    if(m_pMneRtClientProducer->isRunning())
        m_pMneRtClientProducer->stop();
}

//*************************************************************************************************************

QSharedPointer<IPlugin> MneRtClient::clone() const
{
    QSharedPointer<MneRtClient> pMneRtClientClone(new MneRtClient());
    return pMneRtClientClone;
}

//*************************************************************************************************************

void MneRtClient::init()
{
    // Start MneRtClientProducer
    m_pMneRtClientProducer->start();

//    //Convinience CMD connection timer --> ToDo get rid of that -> it interrupts acquistion when not connected
//    connect(&m_cmdConnectionTimer, &QTimer::timeout, this, &MneRtClient::connectCmdClient);

    //init channels when fiff info is available
    connect(this, &MneRtClient::fiffInfoAvailable, this, &MneRtClient::initConnector);

//    //Start convinience timer
//    m_cmdConnectionTimer.start(5000);

    //Try to connect the cmd client on start up using localhost connection
    this->connectCmdClient();
}

//*************************************************************************************************************
//=============================================================================================================
// Create measurement instances and config them
//=============================================================================================================

void MneRtClient::initConnector()
{

    qDebug() << "MneRtClient::init()";

//    if(m_pFiffInfo)
//    {
////        m_pFiffInfo->sfreq /= 100;
//        m_pRTMSA_MneRtClient = addProviderRealTimeMultiSampleArray_New(MSR_ID::MEGMNERTCLIENT_OUTPUT);
//        m_pRTMSA_MneRtClient->initFromFiffInfo(m_pFiffInfo);
//        m_pRTMSA_MneRtClient->setMultiArraySize(10);
//    }

    if(m_pFiffInfo)
    {
        m_pRTMSA_MneRtClient = PluginOutputData<NewRealTimeMultiSampleArray>::create(this, "RtClient", "MNE Rt Client");

        m_pRTMSA_MneRtClient->data()->initFromFiffInfo(m_pFiffInfo);
        m_pRTMSA_MneRtClient->data()->setMultiArraySize(10);

        m_pRTMSA_MneRtClient->data()->setVisibility(true);

        m_outputConnectors.append(m_pRTMSA_MneRtClient);
    }

}

//*************************************************************************************************************

void MneRtClient::changeConnector(qint32 p_iNewConnectorId)
{
    if(p_iNewConnectorId != m_iActiveConnectorId)
    {
        // read meas info
        (*m_pRtCmdClient)["selcon"].pValues()[0].setValue(p_iNewConnectorId);
        (*m_pRtCmdClient)["selcon"].send();

        m_iActiveConnectorId = p_iNewConnectorId;

        // clear all and request everything new
        clear();

        //
        // request available commands
        //
        m_pRtCmdClient->requestCommands();

        //
        // Read Info
        //
        if(!m_pFiffInfo)
            requestInfo();

        //
        // Read Buffer Size
        //
        m_iBufferSize = m_pRtCmdClient->requestBufsize();

        emit cmdConnectionChanged(m_bCmdClientIsConnected);
    }
}

//*************************************************************************************************************

void MneRtClient::clear()
{
    m_pFiffInfo.reset();
    m_iBufferSize = -1;
}

//*************************************************************************************************************

void MneRtClient::connectCmdClient()
{
    if(m_pRtCmdClient.isNull())
        m_pRtCmdClient = QSharedPointer<RtCmdClient>(new RtCmdClient);
    else if(m_bCmdClientIsConnected)
        this->disconnectCmdClient();

    m_pRtCmdClient->connectToHost(m_sMneRtClientIP);
    m_pRtCmdClient->waitForConnected(1000);

    if(m_pRtCmdClient->state() == QTcpSocket::ConnectedState)
    {
        rtServerMutex.lock();

        //Stop convinience timer
//        m_cmdConnectionTimer.stop();

        if(!m_bCmdClientIsConnected)
        {
            //
            // request available commands
            //
            m_pRtCmdClient->requestCommands();

            //
            // set cmd client is connected
            //
            m_bCmdClientIsConnected = true;

            //
            // Read Info
            //
            if(!m_pFiffInfo)
                requestInfo();

            //
            // Read Connectors
            //
            if(m_qMapConnectors.size() == 0)
                m_iActiveConnectorId = m_pRtCmdClient->requestConnectors(m_qMapConnectors);

            //
            // Read Buffer Size
            //
            m_iBufferSize = m_pRtCmdClient->requestBufsize();

            emit cmdConnectionChanged(m_bCmdClientIsConnected);
        }
        rtServerMutex.unlock();
    }
}

//*************************************************************************************************************

void MneRtClient::disconnectCmdClient()
{
    if(m_bCmdClientIsConnected)
    {
        m_pRtCmdClient->disconnectFromHost();
        m_pRtCmdClient->waitForDisconnected();
        rtServerMutex.lock();
        m_bCmdClientIsConnected = false;
        rtServerMutex.unlock();
        emit cmdConnectionChanged(m_bCmdClientIsConnected);
    }
}

//*************************************************************************************************************

void MneRtClient::requestInfo()
{
    if(m_pMneRtClientProducer->m_iDataClientId > -1 && m_bCmdClientIsConnected)
    {
        // read meas info
        (*m_pRtCmdClient)["measinfo"].pValues()[0].setValue(m_pMneRtClientProducer->m_iDataClientId);
        (*m_pRtCmdClient)["measinfo"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagInfoRequest = true;
        m_pMneRtClientProducer->producerMutex.unlock();
    }
    else
        qWarning() << "MneRtClientProducer is not connected!";
}

//*************************************************************************************************************

bool MneRtClient::start()
{
    if(m_bCmdClientIsConnected && m_pFiffInfo)
    {
        // Initialize real time measurements
        init();

        //Set buffer size
        (*m_pRtCmdClient)["bufsize"].pValues()[0].setValue(m_iBufferSize);
        (*m_pRtCmdClient)["bufsize"].send();

        // Buffer
        m_pRawMatrixBuffer_In = QSharedPointer<RawMatrixBuffer>(new RawMatrixBuffer(8,m_pFiffInfo->nchan,m_iBufferSize));

        // Start threads
        QThread::start();

        // Start Measurement at rt_Server
        // start measurement
        (*m_pRtCmdClient)["start"].pValues()[0].setValue(m_pMneRtClientProducer->m_iDataClientId);
        (*m_pRtCmdClient)["start"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagMeasuring = true;
        m_pMneRtClientProducer->producerMutex.unlock();
        m_pMneRtClientProducer->start();

        return true;
    }
    else
        return false;
}

//*************************************************************************************************************

bool MneRtClient::stop()
{
    if(m_bCmdClientIsConnected) //ToDo replace this with is running
    {
        // Stop Measurement at rt_Server
        (*m_pRtCmdClient)["stop-all"].send();

        m_pMneRtClientProducer->producerMutex.lock();
        m_pMneRtClientProducer->m_bFlagMeasuring = false;
        m_pMneRtClientProducer->producerMutex.unlock();
    }

    // Stop threads
    QThread::terminate();
    QThread::wait();

    //Clear Buffers
    m_pRawMatrixBuffer_In->clear();

    return true;
}

//*************************************************************************************************************

IPlugin::PluginType MneRtClient::getType() const
{
    return _ISensor;
}

//*************************************************************************************************************

QString MneRtClient::getName() const
{
    return "RT Client";
}

//*************************************************************************************************************

QWidget* MneRtClient::setupWidget()
{
    MneRtClientSetupWidget* widget = new MneRtClientSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new

    //init dialog

    return widget;
}

//*************************************************************************************************************

void MneRtClient::run()
{

    MatrixXf matValue;
    while(true)
    {
        //pop matrix
        matValue = m_pRawMatrixBuffer_In->pop();
//        std::cout << "matValue " << matValue.block(0,0,1,10) << std::endl;

        //emit values
        for(qint32 i = 0; i < matValue.cols(); ++i)
            m_pRTMSA_MneRtClient->data()->setValue(matValue.col(i).cast<double>());
//        for(qint32 i = 0; i < matValue.cols(); i += 100)
//            m_pRTMSA_MneRtClient->setValue(matValue.col(i).cast<double>());
    }
}
<|endoftext|>