<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_plant.h"

TPlant::TPlant() :
  TExpandableContainer()
{
  setType(0);
  setAge(0);
  setYield(0);
  setCarryWeightLimit(100.0);
  setCarryVolumeLimit(10000);
}

TPlant::TPlant(const TPlant &a) :
  TExpandableContainer(a)
{
}

void TPlant::assignFourValues(int x1, int x2, int x3, int)
{
  setType(x1);
  setAge(x2);
  setYield(x3);
}

void TPlant::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getType();
  *x2 = getAge();
  *x3 = getYield();
  *x4 = 0;
}

TPlant & TPlant::operator=(const TPlant &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  return *this;
}

TPlant::~TPlant()
{
  vlogf(LOG_MISC, fmt("%s is dying: lifetime yield of %i.") % this->getName() % this->getYield());
}

int TPlant::putSomethingInto(TBeing *ch, TThing *)
{
  // technically, would be OK since is a container, but prevent them anyhow
  act("Unfortunately, you can't put things into $p.",
             FALSE, ch, this, 0, TO_CHAR);
  return 2;
}

sstring TPlant::statObjInfo() const
{
  char buf[256];
  sprintf(buf, "Type: %i Age: %i Total Yield: %i", getType(), getAge(), getYield());
  sstring a(buf);
  return a;
}

// the case numbers are the vnum of the seed tool object
// the return value is the plant type index
int seed_to_plant(int vnum)
{
  switch(vnum){
    case 13880:
      return 0;
    case 13881:
      return 1;
    case 13882:
      return 2;
    case 13883:
      return 3;
    case 13884:
      return 4;
    case 13885:
      return 5;
    case 13886:
      return 6;
    case 34213:
      return 7;
    case 33526:
      return 8;
    case 35485:
      return 9;
    case 35499:
      return 10;
    case 33600:
      return 11;
    case 34738:
      return 12;
    case 29410:  // candy heart seed
      return 13; // candy heart tree
    case 34216:  // grape seeds
      return 14; // gray grapes
  }

  return 0;
}

void TPlant::updateDesc()
{
  int plantindex=min(3, (getAge()/10));
  char buf[256];

  const char *plantkeywords [] =
  {
    "mound dirt",
    "sprout tiny",
    "plant small %s",
    "plant %s",
    "plant withered %s"
  };

  const char *plantname [] =
  {
    "a small mound of <o>dirt<1>",
    "a tiny sprout",
    "a small %s",
    "a %s",
    "an old, withered %s"
  };

  const char *plantdesc [] =
  {
    "A small mound of <o>dirt<1> is here.",
    "A tiny sprout is growing here.",
    "A small %s is here.",
    "A %s is here.",
    "An old, withered %s is here."
  };

  const char *planttypes [] =
  {
    "<r>tomato<1> <g>plant<1>",
    "<r>red<1> rose bush",
    "<r>apple<1> tree",
    "<W>white<1> rose bush",
    "<Y>yellow<1> rose bush",
    "<o>orange<1> tree",
    "<g>money<1> tree",
    "<w>pipe<g>weed<1><o> bush<1>",
    "<o>pumpkin<1> vine",
    "<g>turnip<1> plant",
    "<G>lettuce<1> plant",
    "<g>marijuana<1> plant",
    "
catnip<1> <g>plant<1>",
    "
candy heart<1> tree",
    "vine of <k>gray grapes<1>"
  };
  const char *planttypeskeywords [] =
  {
    "tomato",
    "red rose bush",
    "apple tree",
    "white rose bush",
    "yellow rose bush",
    "orange tree",
    "money tree",
    "pipeweed bush",
    "pumpkin vine",
    "turnip plant",
    "lettuce plant",
    "marijuana plant",
    "catnip plant",
    "candy heart tree",
    "gray grape vine"
  };
  int plantfruits [] =
  {
    14348,
    28917,
    8936,
    28918,
    28919,
    432,
    13,
    34212,
    33507,
    33508,
    33525,
    33601,
    34737,
    29405,
    34215
  };

  // considering a plant ages an average of 2 'age' points each mud hour,
  // a plant will age to 17520 in a mud year
  int plantlifeexpectancy [] =
  {
    175200, // 10 years
    262800, // 15 years
    219000,  // 12.5 years
    262800,  // 15 years
    262800,  // 15 years
    219000,  // 12.5 years
    35040,  // 2 years
    17520,  // 1 year
    8760, // 1/2 year
    8760, // 1/2 year
    8760, // bah
    17520, // 1 year
    17520, // 1 year
    3456, // 3 real days
    262800 // 15 years
  };

  // really old plants should wither and die
  if(getAge() > plantlifeexpectancy[getType()]){
    plantindex=4;
    if(obj_flags.decay_time <= -1)
      obj_flags.decay_time=300;
  }

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    name = mud_str_dup(obj_index[getItemIndex()].name);
    ex_description = NULL;
    action_description = NULL;
  }

  if(plantindex>=2){
    sprintf(buf, plantkeywords[plantindex], planttypeskeywords[getType()]);
    delete [] name;
    name = mud_str_dup(buf);

    sprintf(buf, plantname[plantindex], planttypes[getType()]);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, plantdesc[plantindex], planttypes[getType()]);
    setDescr(mud_str_dup(buf));
  } else {
    sprintf(buf, plantkeywords[plantindex]);
    delete [] name;
    name = mud_str_dup(buf);

    sprintf(buf, plantname[plantindex]);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, plantdesc[plantindex]);
    setDescr(mud_str_dup(buf));
  }

  if(plantindex == 3 && !::number(0,3)){
    TThing *t;
    int count=0;

    for(t=getStuff();t;t=t->nextThing){
      ++count;
    }

    if(count<=4){
      t=read_object(plantfruits[getType()], VIRTUAL);
      *this += *t;
      setYield(getYield() + 1);
    }
  }

  if(plantindex == 4 && !::number(0,11)){
    TThing *t;
    int count=0;

    for(t=getStuff();t;t=t->nextThing){
      ++count;
    }

    if(count<=2){
      t=read_object(plantfruits[getType()], VIRTUAL);
      *this += *t;
      setYield(getYield() + 1);
    }
  }
}

void TPlant::updateAge(){
  setAge(getAge()+::number(1,3));
  updateDesc();
  if(roomp)
    roomp->saveItems("");
}

<commit_msg>Reduced lifespan of candy heart trees<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_plant.h"

TPlant::TPlant() :
  TExpandableContainer()
{
  setType(0);
  setAge(0);
  setYield(0);
  setCarryWeightLimit(100.0);
  setCarryVolumeLimit(10000);
}

TPlant::TPlant(const TPlant &a) :
  TExpandableContainer(a)
{
}

void TPlant::assignFourValues(int x1, int x2, int x3, int)
{
  setType(x1);
  setAge(x2);
  setYield(x3);
}

void TPlant::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getType();
  *x2 = getAge();
  *x3 = getYield();
  *x4 = 0;
}

TPlant & TPlant::operator=(const TPlant &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  return *this;
}

TPlant::~TPlant()
{
  vlogf(LOG_MISC, fmt("%s is dying: lifetime yield of %i.") % this->getName() % this->getYield());
}

int TPlant::putSomethingInto(TBeing *ch, TThing *)
{
  // technically, would be OK since is a container, but prevent them anyhow
  act("Unfortunately, you can't put things into $p.",
             FALSE, ch, this, 0, TO_CHAR);
  return 2;
}

sstring TPlant::statObjInfo() const
{
  char buf[256];
  sprintf(buf, "Type: %i Age: %i Total Yield: %i", getType(), getAge(), getYield());
  sstring a(buf);
  return a;
}

// the case numbers are the vnum of the seed tool object
// the return value is the plant type index
int seed_to_plant(int vnum)
{
  switch(vnum){
    case 13880:
      return 0;
    case 13881:
      return 1;
    case 13882:
      return 2;
    case 13883:
      return 3;
    case 13884:
      return 4;
    case 13885:
      return 5;
    case 13886:
      return 6;
    case 34213:
      return 7;
    case 33526:
      return 8;
    case 35485:
      return 9;
    case 35499:
      return 10;
    case 33600:
      return 11;
    case 34738:
      return 12;
    case 29410:  // candy heart seed
      return 13; // candy heart tree
    case 34216:  // grape seeds
      return 14; // gray grapes
  }

  return 0;
}

void TPlant::updateDesc()
{
  int plantindex=min(3, (getAge()/10));
  char buf[256];

  const char *plantkeywords [] =
  {
    "mound dirt",
    "sprout tiny",
    "plant small %s",
    "plant %s",
    "plant withered %s"
  };

  const char *plantname [] =
  {
    "a small mound of <o>dirt<1>",
    "a tiny sprout",
    "a small %s",
    "a %s",
    "an old, withered %s"
  };

  const char *plantdesc [] =
  {
    "A small mound of <o>dirt<1> is here.",
    "A tiny sprout is growing here.",
    "A small %s is here.",
    "A %s is here.",
    "An old, withered %s is here."
  };

  const char *planttypes [] =
  {
    "<r>tomato<1> <g>plant<1>",
    "<r>red<1> rose bush",
    "<r>apple<1> tree",
    "<W>white<1> rose bush",
    "<Y>yellow<1> rose bush",
    "<o>orange<1> tree",
    "<g>money<1> tree",
    "<w>pipe<g>weed<1><o> bush<1>",
    "<o>pumpkin<1> vine",
    "<g>turnip<1> plant",
    "<G>lettuce<1> plant",
    "<g>marijuana<1> plant",
    "
catnip<1> <g>plant<1>",
    "
candy heart<1> tree",
    "vine of <k>gray grapes<1>"
  };
  const char *planttypeskeywords [] =
  {
    "tomato",
    "red rose bush",
    "apple tree",
    "white rose bush",
    "yellow rose bush",
    "orange tree",
    "money tree",
    "pipeweed bush",
    "pumpkin vine",
    "turnip plant",
    "lettuce plant",
    "marijuana plant",
    "catnip plant",
    "candy heart tree",
    "gray grape vine"
  };
  int plantfruits [] =
  {
    14348,
    28917,
    8936,
    28918,
    28919,
    432,
    13,
    34212,
    33507,
    33508,
    33525,
    33601,
    34737,
    29405,
    34215
  };

  // considering a plant ages an average of 2 'age' points each mud hour,
  // a plant will age to 17520 in a mud year
  int plantlifeexpectancy [] =
  {
    175200, // 10 years
    262800, // 15 years
    219000,  // 12.5 years
    262800,  // 15 years
    262800,  // 15 years
    219000,  // 12.5 years
    35040,  // 2 years
    17520,  // 1 year
    8760, // 1/2 year
    8760, // 1/2 year
    8760, // bah
    17520, // 1 year
    17520, // 1 year
    2074, // 2ish real days, not sure
    262800 // 15 years
  };

  // really old plants should wither and die
  if(getAge() > plantlifeexpectancy[getType()]){
    plantindex=4;
    if(obj_flags.decay_time <= -1)
      obj_flags.decay_time=300;
  }

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    name = mud_str_dup(obj_index[getItemIndex()].name);
    ex_description = NULL;
    action_description = NULL;
  }

  if(plantindex>=2){
    sprintf(buf, plantkeywords[plantindex], planttypeskeywords[getType()]);
    delete [] name;
    name = mud_str_dup(buf);

    sprintf(buf, plantname[plantindex], planttypes[getType()]);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, plantdesc[plantindex], planttypes[getType()]);
    setDescr(mud_str_dup(buf));
  } else {
    sprintf(buf, plantkeywords[plantindex]);
    delete [] name;
    name = mud_str_dup(buf);

    sprintf(buf, plantname[plantindex]);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, plantdesc[plantindex]);
    setDescr(mud_str_dup(buf));
  }

  if(plantindex == 3 && !::number(0,3)){
    TThing *t;
    int count=0;

    for(t=getStuff();t;t=t->nextThing){
      ++count;
    }

    if(count<=4){
      t=read_object(plantfruits[getType()], VIRTUAL);
      *this += *t;
      setYield(getYield() + 1);
    }
  }

  if(plantindex == 4 && !::number(0,11)){
    TThing *t;
    int count=0;

    for(t=getStuff();t;t=t->nextThing){
      ++count;
    }

    if(count<=2){
      t=read_object(plantfruits[getType()], VIRTUAL);
      *this += *t;
      setYield(getYield() + 1);
    }
  }
}

void TPlant::updateAge(){
  setAge(getAge()+::number(1,3));
  updateDesc();
  if(roomp)
    roomp->saveItems("");
}

<|endoftext|>


<commit_before><commit_msg>Revert "[debugserver] Remove dead function call. NFCI."<commit_after><|endoftext|>


<commit_before><commit_msg>mPlayerInfo에 Angle을 추가하지 않은 점 수정<commit_after><|endoftext|>


<commit_before>/*
 * DefaultPatternMatchCB.cc
 *
 * Copyright (C) 2008,2009,2014,2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  February 2008
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/execution/EvaluationLink.h>
#include <opencog/atomutils/FindUtils.h>
#include <opencog/atoms/bind/BetaRedex.h>

#include "DefaultPatternMatchCB.h"
#include "Instantiator.h"
#include "PatternMatchEngine.h"

using namespace opencog;

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

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

DefaultPatternMatchCB::DefaultPatternMatchCB(AtomSpace* as) :
	_classserver(classserver()),
	_temp_aspace(as),
	_instor(&_temp_aspace),
	_as(as)
{
	_connectives.insert(AND_LINK);
	_connectives.insert(OR_LINK);
	_connectives.insert(NOT_LINK);
}

void DefaultPatternMatchCB::set_pattern(const Variables& vars,
                                        const Pattern& pat)
{
	_type_restrictions = &vars.typemap;
	_dynamic = &pat.evaluatable_terms;
	_have_evaluatables = (0 < _dynamic->size());
}

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

/**
 * Called when a node in the template pattern needs to
 * be compared to a possibly matching node in the atomspace.
 * The first argument is a node from the pattern, and the
 * second is a possible solution (grounding) node from the
 * atomspace.
 *
 * Return true if the nodes match, else return false.
 * By default, the nodes must be identical.
 */
bool DefaultPatternMatchCB::node_match(const Handle& npat_h,
                                       const Handle& nsoln_h)
{
	// If equality, then a match.
	return npat_h == nsoln_h;
}

/**
 * Called when a variable in the template pattern
 * needs to be compared to a possible grounding
 * node in the atomspace. The first argument
 * is a variable from the pattern, and the second
 * is a possible grounding node from the atomspace.
 * Return true if the nodes match, else return false.
 */
bool DefaultPatternMatchCB::variable_match(const Handle& npat_h,
                                           const Handle& nsoln_h)
{
	Type pattype = npat_h->getType();

	// If the ungrounded term is not of type VariableNode, then just
	// accept the match. This allows any kind of node types to be
	// explicitly bound as variables.  However, the type VariableNode
	// gets special handling, below.
	if (pattype != VARIABLE_NODE) return true;

	// If the ungrounded term is a variable, then see if there
	// are any restrictions on the variable type.
	// If no restrictions, we are good to go.
	if (_type_restrictions->empty()) return true;

	// If we are here, there's a restriction on the grounding type.
	// Validate the node type, if needed.
	VariableTypeMap::const_iterator it = _type_restrictions->find(npat_h);
	if (it == _type_restrictions->end()) return true;

	// Is the ground-atom type in our list of allowed types?
	Type soltype = nsoln_h->getType();
	const std::set<Type> &tset = it->second;
	std::set<Type>::const_iterator allow = tset.find(soltype);
	return allow != tset.end();
}

/**
 * Called when a link in the template pattern
 * needs to be compared to a possibly matching
 * link in the atomspace. The first argument
 * is a link from the pattern, and the second
 * is a possible solution link from the atomspace.
 * Return true if the links should be compared,
 * else return false.
 *
 * By default, the search continues if the link
 * arity and the link types match.
 */
bool DefaultPatternMatchCB::link_match(const LinkPtr& lpat,
                                       const LinkPtr& lsoln)
{
	// If the pattern is exactly the same link as the proposed
	// grounding, then its a perfect match.
	if (lpat == lsoln) return true;

	// Accept all ChoiceLink's by default! We will get another shot
	// at it when the contents of the ChoiceLink are examined.
	Type pattype = lpat->getType();
	if (CHOICE_LINK == pattype) return true;

	if (lpat->getArity() != lsoln->getArity()) return false;
	Type soltype = lsoln->getType();

	// If types differ, no match
	return pattype == soltype;
}

bool DefaultPatternMatchCB::post_link_match(const LinkPtr& lpat,
                                            const LinkPtr& lgnd)
{
	if (not _have_evaluatables) return true;
	Handle hp(lpat);
	if (_dynamic->find(hp) == _dynamic->end()) return true;

	// We will find ourselves here whenever the link contain
	// a GroundedPredicateNode. In this case, execute the
	// node, and declare a match, or no match, depending
	// one how the evaluation turned out.  Its "crisp logic"
	// because we use a greater-than-half for the TV.
	// This is the same behavior as used in evaluate_term().
	TruthValuePtr tv(EvaluationLink::do_evaluate(_as, lgnd->getHandle()));
	return tv->getMean() >= 0.5;
}

/**
 * Called to accept of reject a top-level clause.
 *
 * This is straight-forward, except when the pattern is a VariableNode,
 * and the proposed grounding is evaluatable.  In this case, we want to
 * treat the grounding term as if it was a regular evaluatable clause,
 * and evaluate it, and use that to determine if the match is accepted.
 *
 * This allows a clause to implement a (pre-)condition on the match.
 * If we didn't implement this here, the user could still work around
 * this by saying (NotLink (NotLink (VariableNode $x))), thus forcing
 * the "normal" path to evaluate_sentence(). So may as well do it here.
 */
bool DefaultPatternMatchCB::clause_match(const Handle& ptrn,
                                         const Handle& grnd)
{
	if (ptrn == grnd) return false;
	if (ptrn->getType() == VARIABLE_NODE and
	    grnd->getType() == EVALUATION_LINK)
	{
		dbgprt("Evaluate the grounding clause=\n%s\n",
		        grnd->toShortString().c_str());
		// We make two awkard asumptions here: the ground term itself
		// does not contain any variables, and so does not need any
		// further grounding. This actuall seems reasonable. The second
		// assumption is that the EvaluationLink is actually evaluatable,
		// which seems reasonable, except that everything else in the
		// default callback ignores the TV on EvaluationLinks. So this
		// is kind-of schizophrenic here.  Not sure what else to do.
		TruthValuePtr tvp(EvaluationLink::do_evaluate(&_temp_aspace, grnd));

		dbgprt("clause_match evaluation yeilded tv=%s\n", tvp->toString().c_str());

		// XXX FIXME: we are making a crsip-logic go/no-go decision
		// based on the TV strength. Perhaps something more subtle might be
		// wanted, here.
		bool relation_holds = tvp->getMean() > 0.5;
		return relation_holds;
	}
	return true;
}

/**
 * The default semantics here is to reject a match if the option
 * clauses are detected.  This is in keeping with the semantics
 * AbsentLink: a match is possible only if the indicated clauses
 * are absent!
 */
bool DefaultPatternMatchCB::optional_clause_match(const Handle& ptrn,
                                                  const Handle& grnd)
{
	if (Handle::UNDEFINED == grnd) return true;
	_optionals_present = true;
	return false;
}

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

bool DefaultPatternMatchCB::eval_term(const Handle& virt,
                                      const std::map<Handle, Handle>& gnds)
{
	// Evaluation of the link requires working with an atomspace
	// of some sort, so that the atoms can be communicated to scheme or
	// python for the actual evaluation. We don't want to put the
	// proposed grounding into the "real" atomspace, because the
	// grounding might be insane.  So we put it here. This is probably
	// not very efficient, but will do for now...

	Handle gvirt(_instor.instantiate(virt, gnds));

	dbgprt("Enter eval_term CB with virt=\n%s\n",
	        virt->toShortString().c_str());
	dbgprt("grounded by gvirt=\n%s\n",
	        gvirt->toShortString().c_str());

	// At this time, we expect all virutal links to be in one of two
	// forms: either EvaluationLink's or GreaterThanLink's.  The
	// EvaluationLinks should have the structure
	//
	//   EvaluationLink
	//       GroundedPredicateNode "scm:blah"
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// The GreaterThanLink's should have the "obvious" structure
	//
	//   GreaterThanLink
	//       Arg1Atom
	//       Arg2Atom
	//
	// XXX TODO as discussed on the mailing list, we should perhaps first
	// see if the following can be found in the atomspace:
	//
	//   EvaluationLink
	//       PredicateNode "blah"  ; not Grounded any more, and scm: stripped
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// If it does, we should declare a match.  If not, only then run the
	// do_evaluate callback.  Alternately, perhaps the
	// EvaluationLink::do_evaluate() method should do this ??? Its a toss-up.

	TruthValuePtr tvp(EvaluationLink::do_evaluate(&_temp_aspace, gvirt));

	dbgprt("eval_term evaluation yeilded tv=%s\n", tvp->toString().c_str());

	// XXX FIXME: we are making a crsip-logic go/no-go decision
	// based on the TV strength. Perhaps something more subtle might be
	// wanted, here.
	bool relation_holds = tvp->getMean() > 0.5;
	return relation_holds;
}

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

/**
 * This implements the evaluation of a classical boolean-logic
 * "sentence": a well-formed formula with no free variables,
 * having a crisp true/false truth value.  Here, "top" holds
 * the sentence (with variables), 'gnds' holds the bindings of
 * variables to values.
 */
bool DefaultPatternMatchCB::eval_sentence(const Handle& top,
                              const std::map<Handle, Handle>& gnds)
{
	dbgprt("Enter eval_sentence CB with top=\n%s\n",
	        top->toShortString().c_str());

	LinkPtr ltop(LinkCast(top));
	if (NULL == ltop)
		throw InvalidParamException(TRACE_INFO,
	            "Not expecting a Node, here %s\n",
	            top->toShortString().c_str());

	const HandleSeq& oset = ltop->getOutgoingSet();
	if (0 == oset.size())
		throw InvalidParamException(TRACE_INFO,
		   "Expecting logical connective to have at least one child!");

	Type term_type = top->getType();
	if (OR_LINK == term_type)
	{
		for (const Handle& h : oset)
			if (eval_sentence(h, gnds)) return true;

		return false;
	}
	else if (AND_LINK == term_type)
	{
		for (const Handle& h : oset)
			if (not eval_sentence(h, gnds)) return false;

		return true;
	}
	else if (NOT_LINK == term_type)
	{
		if (1 != oset.size())
			throw InvalidParamException(TRACE_INFO,
			            "NotLink can have only one child!");

		return not eval_sentence(oset[0], gnds);
	}
	else if (EVALUATION_LINK == term_type or
	         _classserver.isA(term_type, VIRTUAL_LINK))
	{
		return eval_term(top, gnds);
	}
	throw InvalidParamException(TRACE_INFO,
	            "Unknown logical connective %s\n",
	            top->toShortString().c_str());
}

/* ===================== END OF FILE ===================== */
<commit_msg>Minor include file fix<commit_after>/*
 * DefaultPatternMatchCB.cc
 *
 * Copyright (C) 2008,2009,2014,2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  February 2008
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/execution/EvaluationLink.h>
#include <opencog/atomutils/FindUtils.h>
#include <opencog/atoms/bind/BetaRedex.h>

#include "DefaultPatternMatchCB.h"
#include "Instantiator.h"

using namespace opencog;

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

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

DefaultPatternMatchCB::DefaultPatternMatchCB(AtomSpace* as) :
	_classserver(classserver()),
	_temp_aspace(as),
	_instor(&_temp_aspace),
	_as(as)
{
	_connectives.insert(AND_LINK);
	_connectives.insert(OR_LINK);
	_connectives.insert(NOT_LINK);
}

void DefaultPatternMatchCB::set_pattern(const Variables& vars,
                                        const Pattern& pat)
{
	_type_restrictions = &vars.typemap;
	_dynamic = &pat.evaluatable_terms;
	_have_evaluatables = (0 < _dynamic->size());
}

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

/**
 * Called when a node in the template pattern needs to
 * be compared to a possibly matching node in the atomspace.
 * The first argument is a node from the pattern, and the
 * second is a possible solution (grounding) node from the
 * atomspace.
 *
 * Return true if the nodes match, else return false.
 * By default, the nodes must be identical.
 */
bool DefaultPatternMatchCB::node_match(const Handle& npat_h,
                                       const Handle& nsoln_h)
{
	// If equality, then a match.
	return npat_h == nsoln_h;
}

/**
 * Called when a variable in the template pattern
 * needs to be compared to a possible grounding
 * node in the atomspace. The first argument
 * is a variable from the pattern, and the second
 * is a possible grounding node from the atomspace.
 * Return true if the nodes match, else return false.
 */
bool DefaultPatternMatchCB::variable_match(const Handle& npat_h,
                                           const Handle& nsoln_h)
{
	Type pattype = npat_h->getType();

	// If the ungrounded term is not of type VariableNode, then just
	// accept the match. This allows any kind of node types to be
	// explicitly bound as variables.  However, the type VariableNode
	// gets special handling, below.
	if (pattype != VARIABLE_NODE) return true;

	// If the ungrounded term is a variable, then see if there
	// are any restrictions on the variable type.
	// If no restrictions, we are good to go.
	if (_type_restrictions->empty()) return true;

	// If we are here, there's a restriction on the grounding type.
	// Validate the node type, if needed.
	VariableTypeMap::const_iterator it = _type_restrictions->find(npat_h);
	if (it == _type_restrictions->end()) return true;

	// Is the ground-atom type in our list of allowed types?
	Type soltype = nsoln_h->getType();
	const std::set<Type> &tset = it->second;
	std::set<Type>::const_iterator allow = tset.find(soltype);
	return allow != tset.end();
}

/**
 * Called when a link in the template pattern
 * needs to be compared to a possibly matching
 * link in the atomspace. The first argument
 * is a link from the pattern, and the second
 * is a possible solution link from the atomspace.
 * Return true if the links should be compared,
 * else return false.
 *
 * By default, the search continues if the link
 * arity and the link types match.
 */
bool DefaultPatternMatchCB::link_match(const LinkPtr& lpat,
                                       const LinkPtr& lsoln)
{
	// If the pattern is exactly the same link as the proposed
	// grounding, then its a perfect match.
	if (lpat == lsoln) return true;

	// Accept all ChoiceLink's by default! We will get another shot
	// at it when the contents of the ChoiceLink are examined.
	Type pattype = lpat->getType();
	if (CHOICE_LINK == pattype) return true;

	if (lpat->getArity() != lsoln->getArity()) return false;
	Type soltype = lsoln->getType();

	// If types differ, no match
	return pattype == soltype;
}

bool DefaultPatternMatchCB::post_link_match(const LinkPtr& lpat,
                                            const LinkPtr& lgnd)
{
	if (not _have_evaluatables) return true;
	Handle hp(lpat);
	if (_dynamic->find(hp) == _dynamic->end()) return true;

	// We will find ourselves here whenever the link contain
	// a GroundedPredicateNode. In this case, execute the
	// node, and declare a match, or no match, depending
	// one how the evaluation turned out.  Its "crisp logic"
	// because we use a greater-than-half for the TV.
	// This is the same behavior as used in evaluate_term().
	TruthValuePtr tv(EvaluationLink::do_evaluate(_as, lgnd->getHandle()));
	return tv->getMean() >= 0.5;
}

/**
 * Called to accept of reject a top-level clause.
 *
 * This is straight-forward, except when the pattern is a VariableNode,
 * and the proposed grounding is evaluatable.  In this case, we want to
 * treat the grounding term as if it was a regular evaluatable clause,
 * and evaluate it, and use that to determine if the match is accepted.
 *
 * This allows a clause to implement a (pre-)condition on the match.
 * If we didn't implement this here, the user could still work around
 * this by saying (NotLink (NotLink (VariableNode $x))), thus forcing
 * the "normal" path to evaluate_sentence(). So may as well do it here.
 */
bool DefaultPatternMatchCB::clause_match(const Handle& ptrn,
                                         const Handle& grnd)
{
	if (ptrn == grnd) return false;
	if (ptrn->getType() == VARIABLE_NODE and
	    grnd->getType() == EVALUATION_LINK)
	{
		dbgprt("Evaluate the grounding clause=\n%s\n",
		        grnd->toShortString().c_str());
		// We make two awkard asumptions here: the ground term itself
		// does not contain any variables, and so does not need any
		// further grounding. This actuall seems reasonable. The second
		// assumption is that the EvaluationLink is actually evaluatable,
		// which seems reasonable, except that everything else in the
		// default callback ignores the TV on EvaluationLinks. So this
		// is kind-of schizophrenic here.  Not sure what else to do.
		TruthValuePtr tvp(EvaluationLink::do_evaluate(&_temp_aspace, grnd));

		dbgprt("clause_match evaluation yeilded tv=%s\n", tvp->toString().c_str());

		// XXX FIXME: we are making a crsip-logic go/no-go decision
		// based on the TV strength. Perhaps something more subtle might be
		// wanted, here.
		bool relation_holds = tvp->getMean() > 0.5;
		return relation_holds;
	}
	return true;
}

/**
 * The default semantics here is to reject a match if the option
 * clauses are detected.  This is in keeping with the semantics
 * AbsentLink: a match is possible only if the indicated clauses
 * are absent!
 */
bool DefaultPatternMatchCB::optional_clause_match(const Handle& ptrn,
                                                  const Handle& grnd)
{
	if (Handle::UNDEFINED == grnd) return true;
	_optionals_present = true;
	return false;
}

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

bool DefaultPatternMatchCB::eval_term(const Handle& virt,
                                      const std::map<Handle, Handle>& gnds)
{
	// Evaluation of the link requires working with an atomspace
	// of some sort, so that the atoms can be communicated to scheme or
	// python for the actual evaluation. We don't want to put the
	// proposed grounding into the "real" atomspace, because the
	// grounding might be insane.  So we put it here. This is probably
	// not very efficient, but will do for now...

	Handle gvirt(_instor.instantiate(virt, gnds));

	dbgprt("Enter eval_term CB with virt=\n%s\n",
	        virt->toShortString().c_str());
	dbgprt("grounded by gvirt=\n%s\n",
	        gvirt->toShortString().c_str());

	// At this time, we expect all virutal links to be in one of two
	// forms: either EvaluationLink's or GreaterThanLink's.  The
	// EvaluationLinks should have the structure
	//
	//   EvaluationLink
	//       GroundedPredicateNode "scm:blah"
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// The GreaterThanLink's should have the "obvious" structure
	//
	//   GreaterThanLink
	//       Arg1Atom
	//       Arg2Atom
	//
	// XXX TODO as discussed on the mailing list, we should perhaps first
	// see if the following can be found in the atomspace:
	//
	//   EvaluationLink
	//       PredicateNode "blah"  ; not Grounded any more, and scm: stripped
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// If it does, we should declare a match.  If not, only then run the
	// do_evaluate callback.  Alternately, perhaps the
	// EvaluationLink::do_evaluate() method should do this ??? Its a toss-up.

	TruthValuePtr tvp(EvaluationLink::do_evaluate(&_temp_aspace, gvirt));

	dbgprt("eval_term evaluation yeilded tv=%s\n", tvp->toString().c_str());

	// XXX FIXME: we are making a crsip-logic go/no-go decision
	// based on the TV strength. Perhaps something more subtle might be
	// wanted, here.
	bool relation_holds = tvp->getMean() > 0.5;
	return relation_holds;
}

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

/**
 * This implements the evaluation of a classical boolean-logic
 * "sentence": a well-formed formula with no free variables,
 * having a crisp true/false truth value.  Here, "top" holds
 * the sentence (with variables), 'gnds' holds the bindings of
 * variables to values.
 */
bool DefaultPatternMatchCB::eval_sentence(const Handle& top,
                              const std::map<Handle, Handle>& gnds)
{
	dbgprt("Enter eval_sentence CB with top=\n%s\n",
	        top->toShortString().c_str());

	LinkPtr ltop(LinkCast(top));
	if (NULL == ltop)
		throw InvalidParamException(TRACE_INFO,
	            "Not expecting a Node, here %s\n",
	            top->toShortString().c_str());

	const HandleSeq& oset = ltop->getOutgoingSet();
	if (0 == oset.size())
		throw InvalidParamException(TRACE_INFO,
		   "Expecting logical connective to have at least one child!");

	Type term_type = top->getType();
	if (OR_LINK == term_type)
	{
		for (const Handle& h : oset)
			if (eval_sentence(h, gnds)) return true;

		return false;
	}
	else if (AND_LINK == term_type)
	{
		for (const Handle& h : oset)
			if (not eval_sentence(h, gnds)) return false;

		return true;
	}
	else if (NOT_LINK == term_type)
	{
		if (1 != oset.size())
			throw InvalidParamException(TRACE_INFO,
			            "NotLink can have only one child!");

		return not eval_sentence(oset[0], gnds);
	}
	else if (EVALUATION_LINK == term_type or
	         _classserver.isA(term_type, VIRTUAL_LINK))
	{
		return eval_term(top, gnds);
	}
	throw InvalidParamException(TRACE_INFO,
	            "Unknown logical connective %s\n",
	            top->toShortString().c_str());
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"
#include "lowtools.h"
#include <unistd.h>

int main(int argc, char **argv)
{
  TDatabase db(DB_SNEEZYBETA);
  vector<int>vnums;
  map<sstring,sstring>val;
  char file[]="/tmp/sqledshopXXXXXX";
  FILE *tmpfile;
  sstring buf, sbuf;
  int answer;

  if(argc<=1){
    printf("Usage: sqledshop <shop_nr list>\n");
    printf("Example: sqledshop 100\n");
    exit(0);
  }

  if(!parse_num_args(argc-1, argv+1, vnums))
    exit(0);

  for(unsigned int i=0;i<vnums.size();++i){
    printf("Fetching data for shop %i\n", vnums[i]);

    db.query("select * from shop where shop_nr=%i", vnums[i]);
    if(db.fetchRow()){
      buf = fmt("- shop\n"); sbuf+=buf;
      buf = fmt("shop_nr:       %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("profit_buy:    %s\n") % db["profit_buy"];  sbuf+=buf;
      buf = fmt("profit_sell:   %s\n") % db["profit_sell"];  sbuf+=buf;
      buf = fmt("no_such_item1: %s\n") % db["no_such_item1"];  sbuf+=buf;
      buf = fmt("no_such_item2: %s\n") % db["no_such_item2"];  sbuf+=buf;
      buf = fmt("do_not_buy:    %s\n") % db["do_not_buy"];  sbuf+=buf;
      buf = fmt("missing_cash1: %s\n") % db["missing_cash1"];  sbuf+=buf;
      buf = fmt("missing_cash2: %s\n") % db["missing_cash2"];  sbuf+=buf;
      buf = fmt("message_buy:   %s\n") % db["message_buy"];  sbuf+=buf;
      buf = fmt("message_sell:  %s\n") % db["message_sell"];  sbuf+=buf;
      buf = fmt("temper1:       %s\n") % db["temper1"];  sbuf+=buf;
      buf = fmt("temper2:       %s\n") % db["temper2"];  sbuf+=buf;
      buf = fmt("keeper:        %s\n") % db["keeper"];  sbuf+=buf;
      buf = fmt("flags:         %s\n") % db["flags"];  sbuf+=buf;
      buf = fmt("in_room:       %s\n") % db["in_room"];  sbuf+=buf;
      buf = fmt("open1:         %s\n") % db["open1"];  sbuf+=buf;
      buf = fmt("close1:        %s\n") % db["close1"];  sbuf+=buf;
      buf = fmt("open2:         %s\n") % db["open2"];  sbuf+=buf;
      buf = fmt("close2:        %s\n") % db["close2"];  sbuf+=buf;
      buf = fmt("gold:          %s\n") % db["gold"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shoptype where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shoptype\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("type:    %s\n") % db["type"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shopproducing where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shopproducing\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("producing:    %s\n") % db["producing"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shopmaterial where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shopmaterial\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("mat_type:    %s\n") % db["mat_type"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

  }

  mkstemp(file);
  tmpfile=fopen(file, "w");
  fprintf(tmpfile, "%s", sbuf.c_str());
  fclose(tmpfile);

  printf("Opening editor.\n");
  buf = fmt("$EDITOR %s") % file;
  system(buf.c_str());

  printf("Insert shop%s? [y/n] ", vnums.size()>1?"s":"");
  while(1){
    answer=getc(stdin);
    if(answer=='n'){
      printf("Shop%s not inserted.\n", vnums.size()>1?"s":"");
      unlink(file);
      exit(0);
    } else if(answer=='y'){
      break;
    } else {
      printf("Insert shop%s? [y/n] ", vnums.size()>1?"s":"");
    }
  }

  buf = fmt("/bin/cp -f %s %s.backup") % file % file;
  system(buf.c_str());

  int i=0;

  while(++i){
    val=parse_data_file(file, i);
    if(val["shop_nr"]=="EOM")
      break;

    if(val["DATATYPE"]=="shop"){
      printf("replacing shop %s\n", val["shop_nr"].c_str());
      db.query("delete from shop where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shopmaterial where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shoptype where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shopproducing where shop_nr=%s",
	       val["shop_nr"].c_str());

      db.query("insert into shop (shop_nr,profit_buy,profit_sell,no_such_item1,no_such_item2,do_not_buy,missing_cash1,missing_cash2,message_buy,message_sell,temper1,temper2,keeper,flags,in_room,open1,close1,open2,close2,gold) values (%s,%s,%s,'%s','%s','%s','%s','%s','%s','%s',%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",
	       val["shop_nr"].c_str(),val["profit_buy"].c_str(),val["profit_sell"].c_str(),val["no_such_item1"].c_str(),val["no_such_item2"].c_str(),val["do_not_buy"].c_str(),val["missing_cash1"].c_str(),val["missing_cash2"].c_str(),val["message_buy"].c_str(),val["message_sell"].c_str(),val["temper1"].c_str(),val["temper2"].c_str(),val["keeper"].c_str(),val["flags"].c_str(),val["in_room"].c_str(),val["open1"].c_str(),val["close1"].c_str(),val["open2"].c_str(),val["close2"].c_str(),val["gold"].c_str());
    } else if(val["DATATYPE"]=="shoptype"){
      printf("replacing shoptype %s\n", val["shop_nr"].c_str());

      db.query("insert into shoptype (shop_nr, type) values (%s,%s)", val["shop_nr"].c_str(), val["type"].c_str());

    } else if(val["DATATYPE"]=="shopproducing"){
      printf("replacing shopproducing %s\n", val["shop_nr"].c_str());

      db.query("insert into shopproducing (shop_nr, producing) values (%s,%s)", val["shop_nr"].c_str(), val["producing"].c_str());

    } else if(val["DATATYPE"]=="shopmaterial"){
      printf("replacing shopmaterial %s\n", val["shop_nr"].c_str());

      db.query("insert into shopmaterial (shop_nr, mat_type) values (%s,%s)", val["shop_nr"].c_str(), val["mat_type"].c_str());

    }

    printf("\n");

  }

  unlink(file);

  printf("Done.\n\r");
  printf("Your backup file is %s.backup\n", file);
}
<commit_msg>added toggle load<commit_after>#include "stdsneezy.h"
#include "database.h"
#include "lowtools.h"
#include <unistd.h>

int main(int argc, char **argv)
{
  TDatabase db(DB_SNEEZYBETA);
  vector<int>vnums;
  map<sstring,sstring>val;
  char file[]="/tmp/sqledshopXXXXXX";
  FILE *tmpfile;
  sstring buf, sbuf;
  int answer;

  if(argc<=1){
    printf("Usage: sqledshop <shop_nr list>\n");
    printf("Example: sqledshop 100\n");
    exit(0);
  }

  toggleInfo.loadToggles();

  if(!parse_num_args(argc-1, argv+1, vnums))
    exit(0);

  for(unsigned int i=0;i<vnums.size();++i){
    printf("Fetching data for shop %i\n", vnums[i]);

    db.query("select * from shop where shop_nr=%i", vnums[i]);
    if(db.fetchRow()){
      buf = fmt("- shop\n"); sbuf+=buf;
      buf = fmt("shop_nr:       %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("profit_buy:    %s\n") % db["profit_buy"];  sbuf+=buf;
      buf = fmt("profit_sell:   %s\n") % db["profit_sell"];  sbuf+=buf;
      buf = fmt("no_such_item1: %s\n") % db["no_such_item1"];  sbuf+=buf;
      buf = fmt("no_such_item2: %s\n") % db["no_such_item2"];  sbuf+=buf;
      buf = fmt("do_not_buy:    %s\n") % db["do_not_buy"];  sbuf+=buf;
      buf = fmt("missing_cash1: %s\n") % db["missing_cash1"];  sbuf+=buf;
      buf = fmt("missing_cash2: %s\n") % db["missing_cash2"];  sbuf+=buf;
      buf = fmt("message_buy:   %s\n") % db["message_buy"];  sbuf+=buf;
      buf = fmt("message_sell:  %s\n") % db["message_sell"];  sbuf+=buf;
      buf = fmt("temper1:       %s\n") % db["temper1"];  sbuf+=buf;
      buf = fmt("temper2:       %s\n") % db["temper2"];  sbuf+=buf;
      buf = fmt("keeper:        %s\n") % db["keeper"];  sbuf+=buf;
      buf = fmt("flags:         %s\n") % db["flags"];  sbuf+=buf;
      buf = fmt("in_room:       %s\n") % db["in_room"];  sbuf+=buf;
      buf = fmt("open1:         %s\n") % db["open1"];  sbuf+=buf;
      buf = fmt("close1:        %s\n") % db["close1"];  sbuf+=buf;
      buf = fmt("open2:         %s\n") % db["open2"];  sbuf+=buf;
      buf = fmt("close2:        %s\n") % db["close2"];  sbuf+=buf;
      buf = fmt("gold:          %s\n") % db["gold"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shoptype where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shoptype\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("type:    %s\n") % db["type"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shopproducing where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shopproducing\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("producing:    %s\n") % db["producing"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from shopmaterial where shop_nr=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- shopmaterial\n"); sbuf+=buf;
      buf = fmt("shop_nr: %s\n") % db["shop_nr"];  sbuf+=buf;
      buf = fmt("mat_type:    %s\n") % db["mat_type"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

  }

  mkstemp(file);
  tmpfile=fopen(file, "w");
  fprintf(tmpfile, "%s", sbuf.c_str());
  fclose(tmpfile);

  printf("Opening editor.\n");
  buf = fmt("$EDITOR %s") % file;
  system(buf.c_str());

  printf("Insert shop%s? [y/n] ", vnums.size()>1?"s":"");
  while(1){
    answer=getc(stdin);
    if(answer=='n'){
      printf("Shop%s not inserted.\n", vnums.size()>1?"s":"");
      unlink(file);
      exit(0);
    } else if(answer=='y'){
      break;
    } else {
      printf("Insert shop%s? [y/n] ", vnums.size()>1?"s":"");
    }
  }

  buf = fmt("/bin/cp -f %s %s.backup") % file % file;
  system(buf.c_str());

  int i=0;

  while(++i){
    val=parse_data_file(file, i);
    if(val["shop_nr"]=="EOM")
      break;

    if(val["DATATYPE"]=="shop"){
      printf("replacing shop %s\n", val["shop_nr"].c_str());
      db.query("delete from shop where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shopmaterial where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shoptype where shop_nr=%s",
	       val["shop_nr"].c_str());
      db.query("delete from shopproducing where shop_nr=%s",
	       val["shop_nr"].c_str());

      db.query("insert into shop (shop_nr,profit_buy,profit_sell,no_such_item1,no_such_item2,do_not_buy,missing_cash1,missing_cash2,message_buy,message_sell,temper1,temper2,keeper,flags,in_room,open1,close1,open2,close2,gold) values (%s,%s,%s,'%s','%s','%s','%s','%s','%s','%s',%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",
	       val["shop_nr"].c_str(),val["profit_buy"].c_str(),val["profit_sell"].c_str(),val["no_such_item1"].c_str(),val["no_such_item2"].c_str(),val["do_not_buy"].c_str(),val["missing_cash1"].c_str(),val["missing_cash2"].c_str(),val["message_buy"].c_str(),val["message_sell"].c_str(),val["temper1"].c_str(),val["temper2"].c_str(),val["keeper"].c_str(),val["flags"].c_str(),val["in_room"].c_str(),val["open1"].c_str(),val["close1"].c_str(),val["open2"].c_str(),val["close2"].c_str(),val["gold"].c_str());
    } else if(val["DATATYPE"]=="shoptype"){
      printf("replacing shoptype %s\n", val["shop_nr"].c_str());

      db.query("insert into shoptype (shop_nr, type) values (%s,%s)", val["shop_nr"].c_str(), val["type"].c_str());

    } else if(val["DATATYPE"]=="shopproducing"){
      printf("replacing shopproducing %s\n", val["shop_nr"].c_str());

      db.query("insert into shopproducing (shop_nr, producing) values (%s,%s)", val["shop_nr"].c_str(), val["producing"].c_str());

    } else if(val["DATATYPE"]=="shopmaterial"){
      printf("replacing shopmaterial %s\n", val["shop_nr"].c_str());

      db.query("insert into shopmaterial (shop_nr, mat_type) values (%s,%s)", val["shop_nr"].c_str(), val["mat_type"].c_str());

    }

    printf("\n");

  }

  unlink(file);

  printf("Done.\n\r");
  printf("Your backup file is %s.backup\n", file);
}
<|endoftext|>


<commit_before><commit_msg>Rando.cpp<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include <stdlib.h>

#include <TROOT.h>
#include <TTree.h>
#include <TFile.h>
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TSQLRow.h>

#include "DataStruct.h"

using namespace std;

int main(int argc, char* argv[])
{
    // define the output file structure
    Spill* p_spill = new Spill; Spill& spill = *p_spill;

    TFile* saveFile = new TFile(argv[2], "recreate");
    TTree* saveTree = new TTree("save", "save");

    saveTree->Branch("spill", &p_spill, 256000, 99);

    //Connect to server
    TSQLServer* server = TSQLServer::Connect(Form("mysql://%s", argv[3]), "", "");
    server->Exec(Form("USE %s", argv[1]));
    cout << "Reading schema " << argv[1] << " and save to " << argv[2] << endl;

    char query[2000];
    sprintf(query, "SELECT spillID FROM Spill WHERE runID in (SELECT run FROM production WHERE ktracked=1) ORDER BY spillID");

    TSQLResult* res = server->Query(query);
    int nSpillsRow = res->GetRowCount();

    int nGoodSpill = 0;
    int nBadSpill_record = 0;
    int nBadSpill_quality = 0;
    for(int i = 0; i < nSpillsRow; ++i)
    {
        if(i % 100 == 0)
        {
            cout << "Converting spill " << i << "/" << nSpillsRow << endl;
        }

        //basic spillID info
        TSQLRow* row = res->Next();
        spill.spillID = atoi(row->GetField(0));
        delete row;

        //target position
        sprintf(query, "SELECT a.targetPos,b.value FROM Spill AS a,Target AS b WHERE a.spillID"
            "=%d AND b.spillID=%d AND b.name='TARGPOS_CONTROL'", spill.spillID, spill.spillID);
        TSQLResult* res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 1)
        {
            ++nBadSpill_record;
            spill.log("lacks target position info");

            delete res_spill;
            continue;
        }

        TSQLRow* row_spill = res_spill->Next();
        spill.targetPos       = atoi(row_spill->GetField(0));
        spill.TARGPOS_CONTROL = atoi(row_spill->GetField(1));
        delete row_spill;
        delete res_spill;

        //Beam/BeamDAQ
        sprintf(query, "SELECT a.value,b.NM3ION,b.QIESum,b.inhibit_block_sum,b.trigger_sum_no_inhibit,"
            "b.dutyFactor53MHz FROM Beam AS a,BeamDAQ AS b WHERE a.spillID=%d AND b.spillID=%d AND "
            "a.name='S:G2SEM'", spill.spillID, spill.spillID);
        res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 1)
        {
            ++nBadSpill_record;
            spill.log("lacks Beam/BeamDAQ info");

            delete res_spill;
            continue;
        }

        row_spill = res_spill->Next();
        spill.G2SEM      = atof(row_spill->GetField(0));
        spill.NM3ION     = atof(row_spill->GetField(1));
        spill.QIESum     = atof(row_spill->GetField(2));
        spill.inhibitSum = atof(row_spill->GetField(3));
        spill.busySum    = atof(row_spill->GetField(4));
        spill.dutyFactor = atof(row_spill->GetField(5));

        spill.liveG2SEM  = spill.G2SEM*(spill.QIESum - spill.inhibitSum - spill.busySum)/spill.QIESum;
        spill.QIEUnit    = spill.G2SEM/spill.QIESum;

        delete row_spill;
        delete res_spill;

        //Scalar table
        sprintf(query, "SELECT value FROM Scaler WHERE spillType='EOS' AND spillID=%d AND scalerName "
            "in ('TSGo','AcceptedMatrix1','AfterInhMatrix1') ORDER BY scalerName", spill.spillID);
        res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 3)
        {
            ++nBadSpill_record;
            spill.log("lacks scaler info");

            delete res_spill;
            continue;
        }

        row_spill = res_spill->Next(); spill.acceptedMatrix1 = atof(row_spill->GetField(0)); delete row_spill;
        row_spill = res_spill->Next(); spill.afterInhMatrix1 = atof(row_spill->GetField(0)); delete row_spill;
        row_spill = res_spill->Next(); spill.TSGo            = atof(row_spill->GetField(0)); delete row_spill;
        delete res_spill;

        if(spill.goodSpill())
        {
            saveTree->Fill();
            ++nGoodSpill;

            if(nGoodSpill % 100 == 0) saveTree->AutoSave("self");
        }
        else
        {
            ++nBadSpill_quality;
            spill.log("spill bad");
            spill.print();
        }
    }
    delete res_spill;

    cout << "sqlReader finished successfully." << endl;
    cout << nGoodSpill << " good spills, " << nBadSpill_record << " spills have insufficient info in database, " << nBadSpill_quality << " rejected because of bad quality." << endl;

    saveFile->cd();
    saveTree->Write();
    saveFile->Close();

    return EXIT_SUCCESS;
}
<commit_msg>Minor bug fix in sqlSpillReader.cxx<commit_after>#include <iostream>
#include <cmath>
#include <stdlib.h>

#include <TROOT.h>
#include <TTree.h>
#include <TFile.h>
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TSQLRow.h>

#include "DataStruct.h"

using namespace std;

int main(int argc, char* argv[])
{
    // define the output file structure
    Spill* p_spill = new Spill; Spill& spill = *p_spill;

    TFile* saveFile = new TFile(argv[2], "recreate");
    TTree* saveTree = new TTree("save", "save");

    saveTree->Branch("spill", &p_spill, 256000, 99);

    //Connect to server
    TSQLServer* server = TSQLServer::Connect(Form("mysql://%s", argv[3]), "", "");
    server->Exec(Form("USE %s", argv[1]));
    cout << "Reading schema " << argv[1] << " and save to " << argv[2] << endl;

    char query[2000];
    sprintf(query, "SELECT spillID FROM Spill WHERE runID in (SELECT run FROM production WHERE ktracked=1) ORDER BY spillID");

    TSQLResult* res = server->Query(query);
    int nSpillsRow = res->GetRowCount();

    int nGoodSpill = 0;
    int nBadSpill_record = 0;
    int nBadSpill_quality = 0;
    for(int i = 0; i < nSpillsRow; ++i)
    {
        if(i % 100 == 0)
        {
            cout << "Converting spill " << i << "/" << nSpillsRow << endl;
        }

        //basic spillID info
        TSQLRow* row = res->Next();
        spill.spillID = atoi(row->GetField(0));
        delete row;

        //target position
        sprintf(query, "SELECT a.targetPos,b.value FROM Spill AS a,Target AS b WHERE a.spillID"
            "=%d AND b.spillID=%d AND b.name='TARGPOS_CONTROL'", spill.spillID, spill.spillID);
        TSQLResult* res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 1)
        {
            ++nBadSpill_record;
            spill.log("lacks target position info");

            delete res_spill;
            continue;
        }

        TSQLRow* row_spill = res_spill->Next();
        spill.targetPos       = atoi(row_spill->GetField(0));
        spill.TARGPOS_CONTROL = atoi(row_spill->GetField(1));
        delete row_spill;
        delete res_spill;

        //Beam/BeamDAQ
        sprintf(query, "SELECT a.value,b.NM3ION,b.QIESum,b.inhibit_block_sum,b.trigger_sum_no_inhibit,"
            "b.dutyFactor53MHz FROM Beam AS a,BeamDAQ AS b WHERE a.spillID=%d AND b.spillID=%d AND "
            "a.name='S:G2SEM'", spill.spillID, spill.spillID);
        res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 1)
        {
            ++nBadSpill_record;
            spill.log("lacks Beam/BeamDAQ info");

            delete res_spill;
            continue;
        }

        row_spill = res_spill->Next();
        spill.G2SEM      = atof(row_spill->GetField(0));
        spill.NM3ION     = atof(row_spill->GetField(1));
        spill.QIESum     = atof(row_spill->GetField(2));
        spill.inhibitSum = atof(row_spill->GetField(3));
        spill.busySum    = atof(row_spill->GetField(4));
        spill.dutyFactor = atof(row_spill->GetField(5));

        spill.liveG2SEM  = spill.G2SEM*(spill.QIESum - spill.inhibitSum - spill.busySum)/spill.QIESum;
        spill.QIEUnit    = spill.G2SEM/spill.QIESum;

        delete row_spill;
        delete res_spill;

        //Scalar table
        sprintf(query, "SELECT value FROM Scaler WHERE spillType='EOS' AND spillID=%d AND scalerName "
            "in ('TSGo','AcceptedMatrix1','AfterInhMatrix1') ORDER BY scalerName", spill.spillID);
        res_spill = server->Query(query);
        if(res_spill->GetRowCount() != 3)
        {
            ++nBadSpill_record;
            spill.log("lacks scaler info");

            delete res_spill;
            continue;
        }

        row_spill = res_spill->Next(); spill.acceptedMatrix1 = atof(row_spill->GetField(0)); delete row_spill;
        row_spill = res_spill->Next(); spill.afterInhMatrix1 = atof(row_spill->GetField(0)); delete row_spill;
        row_spill = res_spill->Next(); spill.TSGo            = atof(row_spill->GetField(0)); delete row_spill;
        delete res_spill;

        if(spill.goodSpill())
        {
            saveTree->Fill();
            ++nGoodSpill;

            if(nGoodSpill % 100 == 0) saveTree->AutoSave("self");
        }
        else
        {
            ++nBadSpill_quality;
            spill.log("spill bad");
            spill.print();
        }
    }
    delete res;

    cout << "sqlReader finished successfully." << endl;
    cout << nGoodSpill << " good spills, " << nBadSpill_record << " spills have insufficient info in database, " << nBadSpill_quality << " rejected because of bad quality." << endl;

    saveFile->cd();
    saveTree->Write();
    saveFile->Close();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include <rapidcheck/gtest.h>

#include <algorithm>
#include <climits>
#include <numeric>
#include <tuple>
#include <vector>

#include SPECIFIC_HEADER

// Running tests

TEST(TEST_NAME, InputItSelf)
{
  auto expected = std::make_tuple(-2, 1, 1);
  auto&& out = sum3({{ 1, -2, 1 }});
  ASSERT_EQ(1, out.size());
  ASSERT_TRUE(expected == out[0]);
}

TEST(TEST_NAME, OverflowReachingZeroIsInvalid)
{
  int b = -1097024319;
  int a = -b -b;
  ASSERT_TRUE(a < 0);
  auto&& out = sum3({{ b, b, a }});
  ASSERT_TRUE(out.size() == 0);
}

TEST(TEST_NAME, MultipleTriplets)
{
  std::vector<std::tuple<int,int,int>> expected = { std::tuple<int,int,int>{-1, 0, 1}, std::tuple<int,int,int>{-1, -1, 2} };
  auto&& out = sum3({{ -1, 0, 1, 2, -1, -4 }});
  ASSERT_EQ(2, out.size());
  ASSERT_TRUE(out[0] != out[1]);
  ASSERT_TRUE(expected[0] == out[0] || expected[0] == out[1]);
  ASSERT_TRUE(expected[1] == out[0] || expected[1] == out[1]);
}

RC_GTEST_PROP(TEST_NAME, SumToZero, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= 3);
  auto&& out = sum3(in);
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [](auto t) { return std::get<0>(t) + std::get<1>(t) + std::get<2>(t) == 0;
  }) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, Ordered, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [](auto t) { return std::get<0>(t) <= std::get<1>(t) && std::get<1>(t) <= std::get<2>(t);
  }) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, Unicity, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  std::sort(std::begin(out), std::end(out));
  RC_ASSERT(std::unique(std::begin(out), std::end(out)) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, ComeFromInput, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  auto sin = in;
  std::sort(std::begin(sin), std::end(sin));
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [&sin](auto t) {
          auto it = std::find(std::begin(sin), std::end(sin), std::get<0>(t));
          it = std::find(it, std::end(sin), std::get<1>(t));
          return std::find(std::begin(sin), std::end(sin), std::get<2>(t)) != std::end(sin);
  }) == std::end(out));
}

bool same_sign(int a, int b)
{
  return (a < 0 && b < 0) || (a > 0 && b > 0);
}

RC_GTEST_PROP(TEST_NAME, FindAnswerWhenItExist, (std::vector<int> in, int a, int b))
{
  int c = -a -b;
  RC_PRE((a == 0 && b == 0 && c == 0) || !same_sign(a,b) || !same_sign(b,c) || !same_sign(c,a));

  int tab[] = {a, b ,c};
  std::sort(tab, tab+3);
  auto possible_answer = std::make_tuple(tab[0], tab[1], tab[2]);

  std::size_t pa = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pa), a);
  std::size_t pb = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pb), b);
  std::size_t pc = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pc), c);

  auto&& out = sum3(in);
  RC_ASSERT(out.size());
  RC_ASSERT(std::find(std::begin(out), std::end(out), possible_answer) != std::end(out));
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int ret { RUN_ALL_TESTS() };
  return ret;
}
<commit_msg>[triplet-suming-to-zero][vs] Fix compile issue unsigned to bool<commit_after>#include "gtest/gtest.h"
#include <rapidcheck/gtest.h>

#include <algorithm>
#include <climits>
#include <numeric>
#include <tuple>
#include <vector>

#include SPECIFIC_HEADER

// Running tests

TEST(TEST_NAME, InputItSelf)
{
  auto expected = std::make_tuple(-2, 1, 1);
  auto&& out = sum3({{ 1, -2, 1 }});
  ASSERT_EQ(1, out.size());
  ASSERT_TRUE(expected == out[0]);
}

TEST(TEST_NAME, OverflowReachingZeroIsInvalid)
{
  int b = -1097024319;
  int a = -b -b;
  ASSERT_TRUE(a < 0);
  auto&& out = sum3({{ b, b, a }});
  ASSERT_TRUE(out.size() == 0);
}

TEST(TEST_NAME, MultipleTriplets)
{
  std::vector<std::tuple<int,int,int>> expected = { std::tuple<int,int,int>{-1, 0, 1}, std::tuple<int,int,int>{-1, -1, 2} };
  auto&& out = sum3({{ -1, 0, 1, 2, -1, -4 }});
  ASSERT_EQ(2, out.size());
  ASSERT_TRUE(out[0] != out[1]);
  ASSERT_TRUE(expected[0] == out[0] || expected[0] == out[1]);
  ASSERT_TRUE(expected[1] == out[0] || expected[1] == out[1]);
}

RC_GTEST_PROP(TEST_NAME, SumToZero, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= 3);
  auto&& out = sum3(in);
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [](auto t) { return std::get<0>(t) + std::get<1>(t) + std::get<2>(t) == 0;
  }) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, Ordered, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [](auto t) { return std::get<0>(t) <= std::get<1>(t) && std::get<1>(t) <= std::get<2>(t);
  }) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, Unicity, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  std::sort(std::begin(out), std::end(out));
  RC_ASSERT(std::unique(std::begin(out), std::end(out)) == std::end(out));
}

RC_GTEST_PROP(TEST_NAME, ComeFromInput, (std::vector<int> const& in))
{
  RC_PRE(in.size() >= unsigned(3));
  auto&& out = sum3(in);
  auto sin = in;
  std::sort(std::begin(sin), std::end(sin));
  RC_ASSERT(std::find_if_not(std::begin(out), std::end(out)
      , [&sin](auto t) {
          auto it = std::find(std::begin(sin), std::end(sin), std::get<0>(t));
          it = std::find(it, std::end(sin), std::get<1>(t));
          return std::find(std::begin(sin), std::end(sin), std::get<2>(t)) != std::end(sin);
  }) == std::end(out));
}

bool same_sign(int a, int b)
{
  return (a < 0 && b < 0) || (a > 0 && b > 0);
}

RC_GTEST_PROP(TEST_NAME, FindAnswerWhenItExist, (std::vector<int> in, int a, int b))
{
  int c = -a -b;
  RC_PRE((a == 0 && b == 0 && c == 0) || !same_sign(a,b) || !same_sign(b,c) || !same_sign(c,a));

  int tab[] = {a, b ,c};
  std::sort(tab, tab+3);
  auto possible_answer = std::make_tuple(tab[0], tab[1], tab[2]);

  std::size_t pa = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pa), a);
  std::size_t pb = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pb), b);
  std::size_t pc = *rc::gen::inRange(std::size_t(), in.size());
  in.insert(std::next(std::begin(in), pc), c);

  auto&& out = sum3(in);
  RC_ASSERT(!!out.size());
  RC_ASSERT(std::find(std::begin(out), std::end(out), possible_answer) != std::end(out));
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int ret { RUN_ALL_TESTS() };
  return ret;
}
<|endoftext|>


<commit_before><commit_msg>hotfix - DynamixelSDK cpp ver. windows port number over than 10 ignored in play bug fixed<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS changefileheader (1.3.216); FILE MERGED 2008/04/01 10:52:43 thb 1.3.216.2: #i85898# Stripping all external header guards 2008/03/28 15:23:19 rt 1.3.216.1: #i87441# Change license header to LPGL v3.<commit_after><|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) Jrgen Riegel          (juergen.riegel@web.de)          *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <Base/Writer.h>

#include "Document.h"
#include "DocumentObject.h"
#include "DocumentObjectPy.h"
#include "DocumentObjectGroup.h"
#include "PropertyLinks.h"
#include "PropertyExpressionEngine.h"
#include <boost/signals/connection.hpp>
#include <boost/bind.hpp>

using namespace App;

PROPERTY_SOURCE(App::DocumentObject, App::PropertyContainer)

DocumentObjectExecReturn *DocumentObject::StdReturn = 0;

//===========================================================================
// DocumentObject
//===========================================================================

DocumentObject::DocumentObject(void)
    : ExpressionEngine(),_pDoc(0),pcNameInDocument(0)
{
    // define Label of type 'Output' to avoid being marked as touched after relabeling
    ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)");
    ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions");
}

DocumentObject::~DocumentObject(void)
{
    if (!PythonObject.is(Py::_None())){
        // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed
        // Python object or not. In the constructor we forced the wrapper to own the object so we need
        // not to dec'ref the Python object any more.
        // But we must still invalidate the Python object because it need not to be
        // destructed right now because the interpreter can own several references to it.
        Base::PyObjectBase* obj = (Base::PyObjectBase*)PythonObject.ptr();
        // Call before decrementing the reference counter, otherwise a heap error can occur
        obj->setInvalid();
    }
}

namespace App {
class ObjectExecution
{
public:
    ObjectExecution(DocumentObject* o) : obj(o)
    { obj->StatusBits.set(3); }
    ~ObjectExecution()
    { obj->StatusBits.reset(3); }
private:
    DocumentObject* obj;
};
}

App::DocumentObjectExecReturn *DocumentObject::recompute(void)
{
    // set/unset the execution bit
    ObjectExecution exe(this);
    return this->execute();
}

DocumentObjectExecReturn *DocumentObject::execute(void)
{
    return StdReturn;
}

short DocumentObject::mustExecute(void) const
{
    return (isTouched() ? 1 : 0);
}

const char* DocumentObject::getStatusString(void) const
{
    if (isError()) {
        const char* text = getDocument()->getErrorDescription(this);
        return text ? text : "Error";
    }
    else if (isTouched())
        return "Touched";
    else
        return "Valid";
}

const char *DocumentObject::getNameInDocument(void) const
{
    // Note: It can happen that we query the internal name of an object even if it is not
    // part of a document (anymore). This is the case e.g. if we have a reference in Python
    // to an object that has been removed from the document. In this case we should rather
    // return 0.
    //assert(pcNameInDocument);
    if (!pcNameInDocument) return 0;
    return pcNameInDocument->c_str();
}

std::vector<DocumentObject*> DocumentObject::getOutList(void) const
{
    std::vector<Property*> List;
    std::vector<DocumentObject*> ret;
    getPropertyList(List);
    for (std::vector<Property*>::const_iterator It = List.begin();It != List.end(); ++It) {
        if ((*It)->isDerivedFrom(PropertyLinkList::getClassTypeId())) {
            const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkList*>(*It)->getValues();
            for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
                if (*It2)
                    ret.push_back(*It2);
            }
        }
        else if ((*It)->isDerivedFrom(PropertyLinkSubList::getClassTypeId())) {
            const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkSubList*>(*It)->getValues();
            for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
                if (*It2)
                    ret.push_back(*It2);
            }
        }
        else if ((*It)->isDerivedFrom(PropertyLink::getClassTypeId())) {
            if (static_cast<PropertyLink*>(*It)->getValue())
                ret.push_back(static_cast<PropertyLink*>(*It)->getValue());
        }
        else if ((*It)->isDerivedFrom(PropertyLinkSub::getClassTypeId())) {
            if (static_cast<PropertyLinkSub*>(*It)->getValue())
                ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
        }
    }

    // Get document objects that this document object relies on
    ExpressionEngine.getDocumentObjectDeps(ret);

    return ret;
}

std::vector<App::DocumentObject*> DocumentObject::getInList(void) const
{
    if (_pDoc)
        return _pDoc->getInList(this);
    else
        return std::vector<App::DocumentObject*>();
}

DocumentObjectGroup* DocumentObject::getGroup() const
{
    return DocumentObjectGroup::getGroupOfObject(this);
}

void DocumentObject::onLostLinkToObject(DocumentObject*)
{

}

App::Document *DocumentObject::getDocument(void) const
{
    return _pDoc;
}

void DocumentObject::setDocument(App::Document* doc)
{
    _pDoc=doc;
    onSettingDocument();
}

void DocumentObject::onBeforeChange(const Property* prop)
{

    // Store current name in oldLabel, to be able to easily retrieve old name of document object later
    // when renaming expressions.
    if (prop == &Label)
        oldLabel = static_cast<PropertyString*>(&Label)->getStrValue();

    if (_pDoc)
        _pDoc->onBeforeChangeProperty(this,prop);
}

/// get called by the container when a Property was changed
void DocumentObject::onChanged(const Property* prop)
{
    if (_pDoc)
        _pDoc->onChangedProperty(this,prop);

    if (prop == &Label && _pDoc)
        _pDoc->signalRenamedObject(*this);

    if (prop->getType() & Prop_Output)
        return;
    // set object touched
    StatusBits.set(0);
}

PyObject *DocumentObject::getPyObject(void)
{
    if (PythonObject.is(Py::_None())) {
        // ref counter is set to 1
        PythonObject = Py::Object(new DocumentObjectPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}

std::vector<PyObject *> DocumentObject::getPySubObjects(const std::vector<std::string>&) const
{
    // default implementation returns nothing
    return std::vector<PyObject *>();
}

void DocumentObject::touch(void)
{
    StatusBits.set(0);
}

/**
 * @brief Check whether the document object is touched or not.
 * @return true if document object is touched, false if not.
 */

bool DocumentObject::isTouched() const
{
    return ExpressionEngine.isTouched() || StatusBits.test(0);
}

void DocumentObject::Save (Base::Writer &writer) const
{
    writer.ObjectName = this->getNameInDocument();
    App::PropertyContainer::Save(writer);
}

/**
 * @brief Associate the expression \expr with the object identifier \a path in this document object.
 * @param path Target object identifier for the result of the expression
 * @param expr Expression tree
 * @param comment Optional comment describing the expression
 */

void DocumentObject::setExpression(const ObjectIdentifier &path, boost::shared_ptr<Expression> expr, const char * comment)
{
    ExpressionEngine.setValue(path, expr, comment);
    connectRelabelSignals();
}

/**
 * @brief Get expression information associated with \a path.
 * @param path Object identifier
 * @return Expression info, containing expression and optional comment.
 */

const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const
{
    boost::any value = ExpressionEngine.getValue(path);

    if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo))
        return boost::any_cast<PropertyExpressionEngine::ExpressionInfo>(value);
    else
        return PropertyExpressionEngine::ExpressionInfo();
}

/**
 * @brief Invoke ExpressionEngine's renameObjectIdentifier, to possibly rewrite expressions using
 * the \a paths map with current and new identifiers.
 *
 * @param paths
 */

void DocumentObject::renameObjectIdentifiers(const std::map<ObjectIdentifier, ObjectIdentifier> &paths)
{
    ExpressionEngine.renameObjectIdentifiers(paths);
}

/**
 * @brief Helper function that sets up a signal to track document object renames.
 */

void DocumentObject::connectRelabelSignals()
{
    // Only keep signal if the ExpressionEngine has at least one expression
    if (ExpressionEngine.numExpressions() > 0) {

        // Not already connected?
        if (!onRelabledObjectConnection.connected())
            onRelabledObjectConnection = getDocument()->signalRenamedObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectRenamed, &ExpressionEngine, _1));

        try {
            // Crude method to resolve all expression dependencies
            ExpressionEngine.execute();
        }
        catch (...) {
            // Ignore any error
        }
    }
    else {
        // Disconnect signals; nothing to track now
        onRelabledObjectConnection.disconnect();
        onRelabledDocumentConnection.disconnect();
    }
}
<commit_msg>+ get Label directly<commit_after>/***************************************************************************
 *   Copyright (c) Jrgen Riegel          (juergen.riegel@web.de)          *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <Base/Writer.h>

#include "Document.h"
#include "DocumentObject.h"
#include "DocumentObjectPy.h"
#include "DocumentObjectGroup.h"
#include "PropertyLinks.h"
#include "PropertyExpressionEngine.h"
#include <boost/signals/connection.hpp>
#include <boost/bind.hpp>

using namespace App;

PROPERTY_SOURCE(App::DocumentObject, App::PropertyContainer)

DocumentObjectExecReturn *DocumentObject::StdReturn = 0;

//===========================================================================
// DocumentObject
//===========================================================================

DocumentObject::DocumentObject(void)
    : ExpressionEngine(),_pDoc(0),pcNameInDocument(0)
{
    // define Label of type 'Output' to avoid being marked as touched after relabeling
    ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)");
    ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions");
}

DocumentObject::~DocumentObject(void)
{
    if (!PythonObject.is(Py::_None())){
        // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed
        // Python object or not. In the constructor we forced the wrapper to own the object so we need
        // not to dec'ref the Python object any more.
        // But we must still invalidate the Python object because it need not to be
        // destructed right now because the interpreter can own several references to it.
        Base::PyObjectBase* obj = (Base::PyObjectBase*)PythonObject.ptr();
        // Call before decrementing the reference counter, otherwise a heap error can occur
        obj->setInvalid();
    }
}

namespace App {
class ObjectExecution
{
public:
    ObjectExecution(DocumentObject* o) : obj(o)
    { obj->StatusBits.set(3); }
    ~ObjectExecution()
    { obj->StatusBits.reset(3); }
private:
    DocumentObject* obj;
};
}

App::DocumentObjectExecReturn *DocumentObject::recompute(void)
{
    // set/unset the execution bit
    ObjectExecution exe(this);
    return this->execute();
}

DocumentObjectExecReturn *DocumentObject::execute(void)
{
    return StdReturn;
}

short DocumentObject::mustExecute(void) const
{
    return (isTouched() ? 1 : 0);
}

const char* DocumentObject::getStatusString(void) const
{
    if (isError()) {
        const char* text = getDocument()->getErrorDescription(this);
        return text ? text : "Error";
    }
    else if (isTouched())
        return "Touched";
    else
        return "Valid";
}

const char *DocumentObject::getNameInDocument(void) const
{
    // Note: It can happen that we query the internal name of an object even if it is not
    // part of a document (anymore). This is the case e.g. if we have a reference in Python
    // to an object that has been removed from the document. In this case we should rather
    // return 0.
    //assert(pcNameInDocument);
    if (!pcNameInDocument) return 0;
    return pcNameInDocument->c_str();
}

std::vector<DocumentObject*> DocumentObject::getOutList(void) const
{
    std::vector<Property*> List;
    std::vector<DocumentObject*> ret;
    getPropertyList(List);
    for (std::vector<Property*>::const_iterator It = List.begin();It != List.end(); ++It) {
        if ((*It)->isDerivedFrom(PropertyLinkList::getClassTypeId())) {
            const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkList*>(*It)->getValues();
            for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
                if (*It2)
                    ret.push_back(*It2);
            }
        }
        else if ((*It)->isDerivedFrom(PropertyLinkSubList::getClassTypeId())) {
            const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkSubList*>(*It)->getValues();
            for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
                if (*It2)
                    ret.push_back(*It2);
            }
        }
        else if ((*It)->isDerivedFrom(PropertyLink::getClassTypeId())) {
            if (static_cast<PropertyLink*>(*It)->getValue())
                ret.push_back(static_cast<PropertyLink*>(*It)->getValue());
        }
        else if ((*It)->isDerivedFrom(PropertyLinkSub::getClassTypeId())) {
            if (static_cast<PropertyLinkSub*>(*It)->getValue())
                ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
        }
    }

    // Get document objects that this document object relies on
    ExpressionEngine.getDocumentObjectDeps(ret);

    return ret;
}

std::vector<App::DocumentObject*> DocumentObject::getInList(void) const
{
    if (_pDoc)
        return _pDoc->getInList(this);
    else
        return std::vector<App::DocumentObject*>();
}

DocumentObjectGroup* DocumentObject::getGroup() const
{
    return DocumentObjectGroup::getGroupOfObject(this);
}

void DocumentObject::onLostLinkToObject(DocumentObject*)
{

}

App::Document *DocumentObject::getDocument(void) const
{
    return _pDoc;
}

void DocumentObject::setDocument(App::Document* doc)
{
    _pDoc=doc;
    onSettingDocument();
}

void DocumentObject::onBeforeChange(const Property* prop)
{

    // Store current name in oldLabel, to be able to easily retrieve old name of document object later
    // when renaming expressions.
    if (prop == &Label)
        oldLabel = Label.getStrValue();

    if (_pDoc)
        _pDoc->onBeforeChangeProperty(this,prop);
}

/// get called by the container when a Property was changed
void DocumentObject::onChanged(const Property* prop)
{
    if (_pDoc)
        _pDoc->onChangedProperty(this,prop);

    if (prop == &Label && _pDoc)
        _pDoc->signalRenamedObject(*this);

    if (prop->getType() & Prop_Output)
        return;
    // set object touched
    StatusBits.set(0);
}

PyObject *DocumentObject::getPyObject(void)
{
    if (PythonObject.is(Py::_None())) {
        // ref counter is set to 1
        PythonObject = Py::Object(new DocumentObjectPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}

std::vector<PyObject *> DocumentObject::getPySubObjects(const std::vector<std::string>&) const
{
    // default implementation returns nothing
    return std::vector<PyObject *>();
}

void DocumentObject::touch(void)
{
    StatusBits.set(0);
}

/**
 * @brief Check whether the document object is touched or not.
 * @return true if document object is touched, false if not.
 */

bool DocumentObject::isTouched() const
{
    return ExpressionEngine.isTouched() || StatusBits.test(0);
}

void DocumentObject::Save (Base::Writer &writer) const
{
    writer.ObjectName = this->getNameInDocument();
    App::PropertyContainer::Save(writer);
}

/**
 * @brief Associate the expression \expr with the object identifier \a path in this document object.
 * @param path Target object identifier for the result of the expression
 * @param expr Expression tree
 * @param comment Optional comment describing the expression
 */

void DocumentObject::setExpression(const ObjectIdentifier &path, boost::shared_ptr<Expression> expr, const char * comment)
{
    ExpressionEngine.setValue(path, expr, comment);
    connectRelabelSignals();
}

/**
 * @brief Get expression information associated with \a path.
 * @param path Object identifier
 * @return Expression info, containing expression and optional comment.
 */

const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const
{
    boost::any value = ExpressionEngine.getValue(path);

    if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo))
        return boost::any_cast<PropertyExpressionEngine::ExpressionInfo>(value);
    else
        return PropertyExpressionEngine::ExpressionInfo();
}

/**
 * @brief Invoke ExpressionEngine's renameObjectIdentifier, to possibly rewrite expressions using
 * the \a paths map with current and new identifiers.
 *
 * @param paths
 */

void DocumentObject::renameObjectIdentifiers(const std::map<ObjectIdentifier, ObjectIdentifier> &paths)
{
    ExpressionEngine.renameObjectIdentifiers(paths);
}

/**
 * @brief Helper function that sets up a signal to track document object renames.
 */

void DocumentObject::connectRelabelSignals()
{
    // Only keep signal if the ExpressionEngine has at least one expression
    if (ExpressionEngine.numExpressions() > 0) {

        // Not already connected?
        if (!onRelabledObjectConnection.connected())
            onRelabledObjectConnection = getDocument()->signalRenamedObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectRenamed, &ExpressionEngine, _1));

        try {
            // Crude method to resolve all expression dependencies
            ExpressionEngine.execute();
        }
        catch (...) {
            // Ignore any error
        }
    }
    else {
        // Disconnect signals; nothing to track now
        onRelabledObjectConnection.disconnect();
        onRelabledDocumentConnection.disconnect();
    }
}
<|endoftext|>


<commit_before>// $Id$

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdio>
#include <cassert>
#include "Util.h"
#include "StaticData.h"
#include "ScoreIndexManager.h"
#include "ScoreProducer.h"
#include "ScoreComponentCollection.h" // debugging

namespace Moses
{
using namespace std;

void ScoreIndexManager::AddScoreProducer(const ScoreProducer* sp)
{
	// Producers must be inserted in the order they are created
	const_cast<ScoreProducer*>(sp)->CreateScoreBookkeepingID();
	assert(m_begins.size() == (sp->GetScoreBookkeepingID()));

	m_producers.push_back(sp);

	m_begins.push_back(m_last);
	size_t numScoreCompsProduced = sp->GetNumScoreComponents();
	assert(numScoreCompsProduced > 0);
	m_last += numScoreCompsProduced;
	m_ends.push_back(m_last);
	InitFeatureNames();
	/*VERBOSE(1,"Added ScoreProducer(" << sp->GetScoreBookkeepingID()
						<< " " << sp->GetScoreProducerDescription()
						<< ") index=" << m_begins.back() << "-" << m_ends.back()-1 << std::endl);
	*/
}

void ScoreIndexManager::PrintLabeledScores(std::ostream& os, const ScoreComponentCollection& scores) const
{
	std::vector<float> weights(scores.m_scores.size(), 1.0f);
	PrintLabeledWeightedScores(os, scores, weights);
}

void ScoreIndexManager::PrintLabeledWeightedScores(std::ostream& os, const ScoreComponentCollection& scores, const std::vector<float>& weights) const
{
  assert(m_featureShortNames.size() == weights.size());
	string lastName = "";
  for (size_t i = 0; i < m_featureShortNames.size(); ++i)
	{
		if (i>0)
		{
			os << " ";
		}
		if (lastName != m_featureShortNames[i])
		{
			os << m_featureShortNames[i] << ": ";
			lastName = m_featureShortNames[i];
		}
    os << weights[i] * scores[i];
	}
}

void ScoreIndexManager::InitFeatureNames() {
	m_featureNames.clear();
	m_featureIndexes.clear();
	m_featureShortNames.clear();
	size_t cur_i = 0;
	size_t cur_scoreType = 0;
	while (cur_i < m_last) {
		size_t nis_idx = 0;
		bool add_idx = (m_producers[cur_scoreType]->GetNumInputScores() > 1);
		while (nis_idx < m_producers[cur_scoreType]->GetNumInputScores()){
			ostringstream os;
			//os << m_producers[cur_scoreType]->GetScoreProducerDescription();
			//if (add_idx)
				//os << '_' << (nis_idx+1);
			os << cur_i;
			const string &featureName = os.str();
			m_featureNames.push_back(featureName);
			m_featureIndexes[featureName] = m_featureNames.size() - 1;
			nis_idx++;
			cur_i++;
		}

		int ind = 1;
		add_idx = (m_ends[cur_scoreType] - cur_i > 1);
		while (cur_i < m_ends[cur_scoreType]) {
			ostringstream os;
			//os << m_producers[cur_scoreType]->GetScoreProducerDescription();
			//if (add_idx)
				//os << '_' << ind;
			os << cur_i;
			const string &featureName = os.str();
			m_featureNames.push_back(featureName);
			m_featureIndexes[featureName] = m_featureNames.size() - 1;
			m_featureShortNames.push_back( m_producers[cur_scoreType]->GetScoreProducerWeightShortName() );
			++cur_i;
			++ind;
		}
		cur_scoreType++;
	}
}

void ScoreIndexManager::InitFeatureNamesAles() {
	m_featureNames.clear();
	m_featureIndexes.clear();
	m_featureShortNames.clear();
	size_t globalIndex = 0;
	vector<const ScoreProducer *>::const_iterator it;

	for (it = m_producers.begin(); it != m_producers.end(); ++it) {
		size_t scoreCount = (*it)->GetNumInputScores();
		for (size_t i = 0; i < scoreCount; ++i) {
			ostringstream oStream;
			oStream << (*it)->GetScoreProducerDescription() << "_" << globalIndex;
			m_featureNames.push_back(oStream.str());
			m_featureIndexes[oStream.str()] = globalIndex;
			++globalIndex;
		}
	}
}

#ifdef HAVE_PROTOBUF
void ScoreIndexManager::SerializeFeatureNamesToPB(hgmert::Hypergraph* hg) const {
	for (size_t i = 0; i < m_featureNames.size(); ++i) {
		hg->add_feature_names(m_featureNames[i]);
	}
}
#endif

void ScoreIndexManager::InitWeightVectorFromFile(const std::string& fnam, vector<float>* m_allWeights) const {
	assert(m_allWeights->size() == m_featureNames.size());
	ifstream in(fnam.c_str());
	assert(in.good());
	char buf[2000];
	map<string, double> name2val;
	while (!in.eof()) {
		in.getline(buf, 2000);
		if (strlen(buf) == 0) continue;
		if (buf[0] == '#') continue;
		istringstream is(buf);
		string fname;
		double val;
		is >> fname >> val;
		map<string, double>::iterator i = name2val.find(fname);
		assert(i == name2val.end()); // duplicate weight name
		name2val[fname] = val;
	}
	assert(m_allWeights->size() == m_featureNames.size());
	for (size_t i = 0; i < m_featureNames.size(); ++i) {
		map<string, double>::iterator iter = name2val.find(m_featureNames[i]);
		if (iter == name2val.end()) {
			cerr << "No weight found found for feature: " << m_featureNames[i] << endl;
			abort();
		}
		(*m_allWeights)[i] = iter->second;
	}
}

std::ostream& operator<<(std::ostream& os, const ScoreIndexManager& sim)
{
	for (size_t i = 0; i < sim.m_featureNames.size(); ++i) {
		os << sim.m_featureNames[i] << endl;
	}
	os  << endl;
	return os;
}

const std::string &ScoreIndexManager::GetFeatureName(size_t fIndex) const
{
#ifndef NDEBUG
  if (m_featureNames.size() <= fIndex) {
      printf("%s: %i ScoreIndexManager::GetFeatureName(m_producers.size() = %zd, m_featureNames.size() = %zd, fIndex = %zd)\n", __FILE__, __LINE__, m_producers.size(), m_featureNames.size(), fIndex);
  }
#endif
	assert(m_featureNames.size() > fIndex);
	return m_featureNames[fIndex];
}
//! get the index of a feature by name
size_t ScoreIndexManager::GetFeatureIndex(const std::string& fName) const
{
	return m_featureIndexes.find(fName)->second;
}

}
<commit_msg>mira<commit_after>// $Id$

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdio>
#include <cassert>
#include "Util.h"
#include "StaticData.h"
#include "ScoreIndexManager.h"
#include "ScoreProducer.h"
#include "ScoreComponentCollection.h" // debugging

namespace Moses
{
using namespace std;

void ScoreIndexManager::AddScoreProducer(const ScoreProducer* sp)
{
	// Producers must be inserted in the order they are created
	const_cast<ScoreProducer*>(sp)->CreateScoreBookkeepingID();
	assert(m_begins.size() == (sp->GetScoreBookkeepingID()));

	m_producers.push_back(sp);

	m_begins.push_back(m_last);
	size_t numScoreCompsProduced = sp->GetNumScoreComponents();
	assert(numScoreCompsProduced > 0);
	m_last += numScoreCompsProduced;
	m_ends.push_back(m_last);
	InitFeatureNames();
	/*VERBOSE(1,"Added ScoreProducer(" << sp->GetScoreBookkeepingID()
						<< " " << sp->GetScoreProducerDescription()
						<< ") index=" << m_begins.back() << "-" << m_ends.back()-1 << std::endl);
	*/
}

void ScoreIndexManager::PrintLabeledScores(std::ostream& os, const ScoreComponentCollection& scores) const
{
	std::vector<float> weights(scores.m_scores.size(), 1.0f);
	PrintLabeledWeightedScores(os, scores, weights);
}

void ScoreIndexManager::PrintLabeledWeightedScores(std::ostream& os, const ScoreComponentCollection& scores, const std::vector<float>& weights) const
{
  assert(m_featureShortNames.size() == weights.size());
	string lastName = "";
  for (size_t i = 0; i < m_featureShortNames.size(); ++i)
	{
		if (i>0)
		{
			os << " ";
		}
		if (lastName != m_featureShortNames[i])
		{
			os << m_featureShortNames[i] << ": ";
			lastName = m_featureShortNames[i];
		}
    os << weights[i] * scores[i];
	}
}

void ScoreIndexManager::InitFeatureNames() {
	m_featureNames.clear();
	m_featureIndexes.clear();
	m_featureShortNames.clear();
	size_t cur_i = 0;
	size_t cur_scoreType = 0;
	while (cur_i < m_last) {
		size_t nis_idx = 0;
		bool add_idx = (m_producers[cur_scoreType]->GetNumInputScores() > 1);
		while (nis_idx < m_producers[cur_scoreType]->GetNumInputScores()){
			ostringstream os;
			//os << m_producers[cur_scoreType]->GetScoreProducerDescription();
			//if (add_idx)
				//os << '_' << (nis_idx+1);
			os << cur_i;
			const string &featureName = os.str();
			m_featureNames.push_back(featureName);
			m_featureIndexes[featureName] = m_featureNames.size() - 1;
			nis_idx++;
			cur_i++;
		}

		int ind = 1;
		add_idx = (m_ends[cur_scoreType] - cur_i > 1);
		while (cur_i < m_ends[cur_scoreType]) {
			ostringstream os;
			//os << m_producers[cur_scoreType]->GetScoreProducerDescription();
			//if (add_idx)
				//os << '_' << ind;
			os << cur_i;
			const string &featureName = os.str();
			m_featureNames.push_back(featureName);
			m_featureIndexes[featureName] = m_featureNames.size() - 1;
			m_featureShortNames.push_back( m_producers[cur_scoreType]->GetScoreProducerWeightShortName() );
			++cur_i;
			++ind;
		}
		cur_scoreType++;
	}
}

#if 0
void ScoreIndexManager::InitFeatureNamesAles() {
	m_featureNames.clear();
	m_featureIndexes.clear();
	m_featureShortNames.clear();
	size_t globalIndex = 0;
	vector<const ScoreProducer *>::const_iterator it;

	for (it = m_producers.begin(); it != m_producers.end(); ++it) {
		size_t scoreCount = (*it)->GetNumInputScores();
		for (size_t i = 0; i < scoreCount; ++i) {
			ostringstream oStream;
			oStream << (*it)->GetScoreProducerDescription() << "_" << globalIndex;
			m_featureNames.push_back(oStream.str());
			m_featureIndexes[oStream.str()] = globalIndex;
			++globalIndex;
		}
	}
}
#endif

#ifdef HAVE_PROTOBUF
void ScoreIndexManager::SerializeFeatureNamesToPB(hgmert::Hypergraph* hg) const {
	for (size_t i = 0; i < m_featureNames.size(); ++i) {
		hg->add_feature_names(m_featureNames[i]);
	}
}
#endif

void ScoreIndexManager::InitWeightVectorFromFile(const std::string& fnam, vector<float>* m_allWeights) const {
	assert(m_allWeights->size() == m_featureNames.size());
	ifstream in(fnam.c_str());
	assert(in.good());
	char buf[2000];
	map<string, double> name2val;
	while (!in.eof()) {
		in.getline(buf, 2000);
		if (strlen(buf) == 0) continue;
		if (buf[0] == '#') continue;
		istringstream is(buf);
		string fname;
		double val;
		is >> fname >> val;
		map<string, double>::iterator i = name2val.find(fname);
		assert(i == name2val.end()); // duplicate weight name
		name2val[fname] = val;
	}
	assert(m_allWeights->size() == m_featureNames.size());
	for (size_t i = 0; i < m_featureNames.size(); ++i) {
		map<string, double>::iterator iter = name2val.find(m_featureNames[i]);
		if (iter == name2val.end()) {
			cerr << "No weight found found for feature: " << m_featureNames[i] << endl;
			abort();
		}
		(*m_allWeights)[i] = iter->second;
	}
}

std::ostream& operator<<(std::ostream& os, const ScoreIndexManager& sim)
{
	for (size_t i = 0; i < sim.m_featureNames.size(); ++i) {
		os << sim.m_featureNames[i] << endl;
	}
	os  << endl;
	return os;
}

const std::string &ScoreIndexManager::GetFeatureName(size_t fIndex) const
{
#ifndef NDEBUG
  if (m_featureNames.size() <= fIndex) {
      printf("%s: %i ScoreIndexManager::GetFeatureName(m_producers.size() = %zd, m_featureNames.size() = %zd, fIndex = %zd)\n", __FILE__, __LINE__, m_producers.size(), m_featureNames.size(), fIndex);
  }
#endif
	assert(m_featureNames.size() > fIndex);
	return m_featureNames[fIndex];
}
//! get the index of a feature by name
size_t ScoreIndexManager::GetFeatureIndex(const std::string& fName) const
{
	return m_featureIndexes.find(fName)->second;
}

}
<|endoftext|>