Files correlati : db0.exe Ricompilazione Demo : [ ] Commento : Gestione interattiva distinta base git-svn-id: svn://10.65.10.50/trunk@6849 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			958 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			958 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <urldefid.h>
 | 
						|
 | 
						|
#include "dblib.h"
 | 
						|
 | 
						|
#include "../mg/anamag.h"
 | 
						|
#include "../mg/umart.h"
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TQuantita' 
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TDecoder* TQuantita::_umart1 = NULL;
 | 
						|
TDecoder* TQuantita::_umart2 = NULL;
 | 
						|
 | 
						|
real TQuantita::get_factor(const TCodice_um& um) const
 | 
						|
{
 | 
						|
  real fc = 1.0;
 | 
						|
  if (_articolo.blank())
 | 
						|
  {
 | 
						|
    NFCHECK("Unita' di misura generica non supportata");
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (_umart2 == NULL)
 | 
						|
      _umart2 = new TDecoder(LF_UMART, UMART_FC, 2);
 | 
						|
 | 
						|
    TString80 code;
 | 
						|
    code << _articolo << '|' << (um.empty() ? _um : um);
 | 
						|
    const TString& val = _umart2->decode(code);
 | 
						|
    if (val.not_empty())
 | 
						|
      fc = real(val);
 | 
						|
  }
 | 
						|
 | 
						|
  return fc;
 | 
						|
}
 | 
						|
 | 
						|
void TQuantita::set_articolo(const TCodice_articolo& art, 
 | 
						|
                             const TCodice_um& um) 
 | 
						|
{
 | 
						|
  _articolo = art;
 | 
						|
 | 
						|
  if (um.blank())
 | 
						|
  {
 | 
						|
    if (_umart1 == NULL)
 | 
						|
      _umart1 = new TDecoder(LF_UMART, UMART_UM, 1);
 | 
						|
 | 
						|
    TString80 code;
 | 
						|
    code << _articolo << "|1"; 
 | 
						|
    const TString& new_um = _umart1->decode(code);
 | 
						|
    if (!new_um.blank())
 | 
						|
      _um = new_um;
 | 
						|
    _conv = 1.0;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    _um = um;
 | 
						|
    _conv = get_factor(_um);
 | 
						|
  }
 | 
						|
 | 
						|
  CHECK(!_um.blank(), "Unita' di misura nulla");
 | 
						|
  CHECK(_conv > ZERO, "Invalid conversion factor");
 | 
						|
}
 | 
						|
 | 
						|
void TQuantita::copy(const TQuantita& q)
 | 
						|
{
 | 
						|
  _articolo = q._articolo;
 | 
						|
  _um = q._um;
 | 
						|
  _conv = q._conv;
 | 
						|
  _val = q._val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TQuantita::convert(real& val, const TCodice_um& from_um, 
 | 
						|
                                   const TCodice_um& to_um) const
 | 
						|
{
 | 
						|
  CHECK(!from_um.blank() && !to_um.blank(), "Unita' di misura nulla");
 | 
						|
  if (from_um != to_um)
 | 
						|
  {
 | 
						|
    if (!_val.is_zero())
 | 
						|
    {
 | 
						|
      const real mul = get_factor(from_um);
 | 
						|
      const real div = get_factor(to_um);
 | 
						|
      val *= mul;
 | 
						|
      val /= div;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TQuantita::convert_to_base()
 | 
						|
{
 | 
						|
  CHECK(_conv > ZERO, "Invalid conversion factor");
 | 
						|
  _val *= _conv;
 | 
						|
  TCodice_um dummy;
 | 
						|
  set_articolo(_articolo, dummy);
 | 
						|
}
 | 
						|
 | 
						|
int TQuantita::compare(const TSortable& s) const
 | 
						|
{
 | 
						|
  const TQuantita& q = (const TQuantita&)s;
 | 
						|
  real qta = q._val;
 | 
						|
  if (_um != q._um)
 | 
						|
    convert(qta, q._um, _um);
 | 
						|
  qta -= _val;
 | 
						|
  return -qta.sign();
 | 
						|
}
 | 
						|
 | 
						|
const TQuantita& TQuantita::operator +=(const TQuantita& q)
 | 
						|
{
 | 
						|
  real qta = q._val;
 | 
						|
  if (_um != q._um)
 | 
						|
    convert(qta, q._um, _um);
 | 
						|
  _val += qta;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
const TQuantita& TQuantita::operator -=(const TQuantita& q)
 | 
						|
{
 | 
						|
  real qta = q._val;
 | 
						|
  if (_um != q._um)
 | 
						|
    convert(qta, q._um, _um);
 | 
						|
  _val -= qta;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
const TQuantita& TQuantita::operator =(const real& q)
 | 
						|
{
 | 
						|
  CHECK(!_um.blank(), "Unita' di misura nulla");
 | 
						|
  _val = q;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
const TQuantita& TQuantita::operator *=(const real& q)
 | 
						|
{
 | 
						|
  CHECK(!_um.blank(), "Unita' di misura nulla");
 | 
						|
  _val *= q;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
const TQuantita& TQuantita::operator /=(const real& q)
 | 
						|
{
 | 
						|
  CHECK(!_um.blank(), "Unita' di misura nulla");
 | 
						|
  _val /= q;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
TQuantita::TQuantita() 
 | 
						|
         : _conv(1.0) 
 | 
						|
{ }
 | 
						|
 | 
						|
TQuantita::TQuantita(const TCodice_articolo& art) 
 | 
						|
{ 
 | 
						|
  TCodice_um dummy;
 | 
						|
  set(art, dummy, ZERO);
 | 
						|
}
 | 
						|
 | 
						|
TQuantita::TQuantita(const TCodice_articolo& art, const TCodice_um& um, const real& val) 
 | 
						|
{ 
 | 
						|
  set(art, um, val);
 | 
						|
}
 | 
						|
 | 
						|
TQuantita::TQuantita(const TQuantita& q) 
 | 
						|
{ copy(q); }
 | 
						|
 | 
						|
TQuantita::~TQuantita() 
 | 
						|
{ 
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TDistinta_expr
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TDistinta_expr::print_error(const char* msg) const
 | 
						|
{
 | 
						|
  return error_box(msg);
 | 
						|
}
 | 
						|
 | 
						|
TDistinta_expr::TDistinta_expr()
 | 
						|
              : TExpression(_numexpr, FALSE)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TDistinta_tree
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
const TRectype* TDistinta_tree::_curr = NULL;
 | 
						|
TToken_string TDistinta_tree::_tmp(80, ',');
 | 
						|
 | 
						|
bool TDistinta_tree::isola_codice(TString& code) const
 | 
						|
{
 | 
						|
  int comma = code.find(',');
 | 
						|
  if (comma > 0)
 | 
						|
    code.cut(comma);
 | 
						|
  return code.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::curr_code(TCodice_articolo& code) const
 | 
						|
{
 | 
						|
  _path.get(-2, _tmp);
 | 
						|
  isola_codice(_tmp);
 | 
						|
  code = _tmp;
 | 
						|
  return code.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::curr_giac(TString& code) const
 | 
						|
{
 | 
						|
  _path.get(-2, _tmp);
 | 
						|
  _tmp.get(1, code);
 | 
						|
  return code.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
int TDistinta_tree::curr_comp(TString& code) const
 | 
						|
{
 | 
						|
  _path.get(-2, _tmp);
 | 
						|
  _tmp.get(2, code);
 | 
						|
  return atoi(code);
 | 
						|
}
 | 
						|
 | 
						|
long TDistinta_tree::curr_sort() const
 | 
						|
{
 | 
						|
  _path.get(-2, _tmp);
 | 
						|
  return _tmp.get_long(3);
 | 
						|
}
 | 
						|
 | 
						|
const char* TDistinta_tree::curr_um(TCodice_um& code) const
 | 
						|
{
 | 
						|
  _path.get(-2, _tmp);
 | 
						|
  _tmp.get(4, code);
 | 
						|
  return code;
 | 
						|
}
 | 
						|
 | 
						|
real TDistinta_tree::curr_qta(bool last_only) const
 | 
						|
{
 | 
						|
  real qta = 1.0;
 | 
						|
  const int last = _path.items()-1;
 | 
						|
  if (last > 0)
 | 
						|
  {
 | 
						|
    for (int i = last; i > 0; i--)
 | 
						|
    {
 | 
						|
      _path.get(i, _tmp);
 | 
						|
      real val; _tmp.get(5, val);
 | 
						|
      qta *= val;
 | 
						|
      if (last_only || qta.is_zero())
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return qta;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_node(const TString &id)
 | 
						|
{
 | 
						|
  if (id != _path)
 | 
						|
  {
 | 
						|
    _stack.destroy();
 | 
						|
    TToken_string str = id;
 | 
						|
    _path = str.get(0);
 | 
						|
    push_vars();
 | 
						|
    for (const char* t = str.get(); t; t = str.get())
 | 
						|
    {
 | 
						|
      _path.add(t);
 | 
						|
      push_vars();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
struct TFind_node_data
 | 
						|
{
 | 
						|
  TCodice_articolo _id;
 | 
						|
  long _count;
 | 
						|
};
 | 
						|
 | 
						|
HIDDEN bool find_node_callback(TTree& tree, void* jolly, word flags)
 | 
						|
{
 | 
						|
  if (flags == SCAN_PRE_ORDER)
 | 
						|
  {
 | 
						|
    TFind_node_data& data = *(TFind_node_data*)jolly;
 | 
						|
    data._count++;
 | 
						|
    TDistinta_tree& dt = (TDistinta_tree&)tree;
 | 
						|
    TCodice_articolo id; dt.curr_code(id);
 | 
						|
    if (data._id == id)
 | 
						|
      return TRUE;
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
long TDistinta_tree::find_node(const TCodice_articolo& str, word flags)
 | 
						|
{
 | 
						|
  if (goto_root())
 | 
						|
  {
 | 
						|
    TFind_node_data fnd;
 | 
						|
    fnd._id = str;
 | 
						|
    fnd._count = 0;
 | 
						|
    if (scan_breadth_first(find_node_callback, &fnd, flags))
 | 
						|
      return fnd._count;
 | 
						|
  }
 | 
						|
  return 0L;
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::node2id(const TObject* node, TString& id) const
 | 
						|
{
 | 
						|
  id = *(TToken_string*)node;
 | 
						|
}
 | 
						|
 | 
						|
TObject* TDistinta_tree::curr_node() const
 | 
						|
{
 | 
						|
  return (TObject*)&_path;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::get_description(TString& desc) const 
 | 
						|
{ 
 | 
						|
  _path.get(-2, desc);
 | 
						|
  isola_codice(desc);
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
TImage* TDistinta_tree::image(bool selected) const
 | 
						|
{
 | 
						|
  TImage* img;
 | 
						|
  if (is_cyclic())
 | 
						|
    img = get_res_image(BMP_STOP);
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (is_leaf())
 | 
						|
      img = get_res_image(BMP_FILE);
 | 
						|
    else
 | 
						|
      img = TBidirectional_tree::image(selected);
 | 
						|
  }
 | 
						|
  return img;
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::restart()
 | 
						|
{
 | 
						|
  _dist.destroy();
 | 
						|
  _rdist.destroy();   
 | 
						|
  _vars.destroy();
 | 
						|
  _mag.destroy();
 | 
						|
  _lav.destroy();
 | 
						|
  shrink_all();
 | 
						|
  goto_root();
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::set_root(const TCodice_articolo& str)
 | 
						|
{
 | 
						|
  const bool ok = find(str, 1) != NULL;
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    _root = str;
 | 
						|
    restart();
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::has_root() const
 | 
						|
{
 | 
						|
  return _root.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_root()
 | 
						|
{
 | 
						|
  const bool ok = has_root();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    _path = _root;
 | 
						|
    _stack.destroy();
 | 
						|
    push_vars();
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::is_cyclic(const TToken_string& path) const
 | 
						|
{
 | 
						|
  bool cyclic = FALSE;
 | 
						|
  const int last = path.items()-1;
 | 
						|
  if (last > 0)
 | 
						|
  {
 | 
						|
    path.get(-2, _tmp);
 | 
						|
    TCodice_articolo mycod; _tmp.get(0, mycod);
 | 
						|
    for (int i = last-1; i >= 0; i--)
 | 
						|
    {
 | 
						|
      path.get(i, _tmp);
 | 
						|
      isola_codice(_tmp);
 | 
						|
      if (_tmp == mycod)
 | 
						|
      {
 | 
						|
        cyclic = TRUE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return cyclic;
 | 
						|
}
 | 
						|
 | 
						|
static int _sort_key;
 | 
						|
static int compare_rdist(const TObject** o1, const TObject** o2)
 | 
						|
{
 | 
						|
  const TRectype* r1 = (const TRectype*)(*o1);
 | 
						|
  const TRectype* r2 = (const TRectype*)(*o2);
 | 
						|
  TString16 field;
 | 
						|
  field << "SORT" << _sort_key;
 | 
						|
  long k1 = r1->get_long(field);
 | 
						|
  long k2 = r2->get_long(field);
 | 
						|
  if (k1 == 0 && k2 == 0)
 | 
						|
  {
 | 
						|
    k1 = r1->get_long("NRIG");
 | 
						|
    k2 = r2->get_long("NRIG");
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (k1 == 0) k1 = 100000000L;
 | 
						|
    if (k2 == 0) k2 = 100000000L;
 | 
						|
  }
 | 
						|
  return k1 == k2 ? 0 : (k1 > k2 ? +1 : -1);
 | 
						|
}
 | 
						|
 | 
						|
const TRectype* TDistinta_tree::find(const TCodice_articolo& father, int child) const
 | 
						|
{
 | 
						|
  TString80 key = father;
 | 
						|
  key << '|' << child;
 | 
						|
  const TRectype& rec = ((TDistinta_tree*)this)->_rdist.get(key);
 | 
						|
  return rec.empty() ? NULL : &rec;
 | 
						|
}
 | 
						|
 | 
						|
int TDistinta_tree::build_children_list(const TCodice_articolo& father, TPointer_array& children) const
 | 
						|
{
 | 
						|
  for (int nrig = 1; ; nrig++)
 | 
						|
  {
 | 
						|
    const TRectype* rec = find(father, nrig);
 | 
						|
    if (rec == NULL)
 | 
						|
      break;
 | 
						|
    children.add((TRectype*)rec);
 | 
						|
  }
 | 
						|
  const int total = children.items();
 | 
						|
  if (total > 1)
 | 
						|
  {
 | 
						|
    _sort_key = _sort;
 | 
						|
    children.sort(compare_rdist);
 | 
						|
  }
 | 
						|
  return total;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::has_son() const
 | 
						|
{
 | 
						|
  if (_max_depth > 0)
 | 
						|
  {
 | 
						|
    const int depth = _path.items()-1;
 | 
						|
    if (depth >= _max_depth)
 | 
						|
      return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (is_cyclic())
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  TCodice_articolo key; curr_code(key);
 | 
						|
  _curr = find(key, 1);
 | 
						|
  // Se c'e' almeno un figlio ed e' necessario ordinare
 | 
						|
  if (_curr != NULL && _sort > 0) 
 | 
						|
  {
 | 
						|
    TPointer_array children;
 | 
						|
    const int total = build_children_list(key, children);
 | 
						|
    if (total > 1)
 | 
						|
      _curr = (TRectype*)children.objptr(0);
 | 
						|
  }
 | 
						|
  return _curr != NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TDistinta_tree::add_child()
 | 
						|
{
 | 
						|
  const char tipo = _curr->get_char("TIPO");
 | 
						|
  const TString& comp = _curr->get("CODCOMP");
 | 
						|
 | 
						|
  if (tipo == 'V')
 | 
						|
    _path.add(get_string(comp));
 | 
						|
  else
 | 
						|
    _path.add(comp);                   // Codice articolo
 | 
						|
 | 
						|
  _path << ',' << _curr->get("LIVELLO");// Livello giacenza
 | 
						|
 | 
						|
  long num = _curr->get_long("NRIG");
 | 
						|
  _path << ',' << num;                 // Numero componente
 | 
						|
  if (_sort > 0)
 | 
						|
  {
 | 
						|
    TString16 field; field << "SORT" << _sort;
 | 
						|
    num = _curr->get_long(field);
 | 
						|
  }
 | 
						|
  _path << ',' << num;                 // Numero ordinamento
 | 
						|
  
 | 
						|
  _path << ',' << _curr->get("UM");    // Unita' di misura 
 | 
						|
 | 
						|
  const TString& expr = _curr->get("EXPR");
 | 
						|
  const real qta = evaluate_numexpr(expr);
 | 
						|
  _path << ',' << qta;                 // Quantita' 
 | 
						|
 | 
						|
  push_vars();
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::kill_child()
 | 
						|
{
 | 
						|
  // Distrugge l'ultimo stack delle variabili
 | 
						|
  pop_vars();
 | 
						|
 | 
						|
  // Toglie l'ultimo elemento dal path
 | 
						|
  const int pipe = _path.rfind('|');
 | 
						|
  _path.cut(pipe);
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_firstson()
 | 
						|
{
 | 
						|
  const bool ok = has_son();
 | 
						|
  if (ok)
 | 
						|
    add_child();
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::has_rbrother() const
 | 
						|
{
 | 
						|
  const int last = _path.items()-1;
 | 
						|
  if (last < 1)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  TString80 key; _path.get(last-1, key);
 | 
						|
  isola_codice(key);
 | 
						|
  const TCodice_articolo father(key);
 | 
						|
  curr_comp(key);
 | 
						|
 | 
						|
  if (_sort > 0)
 | 
						|
  {
 | 
						|
    TPointer_array children;
 | 
						|
    const int last = build_children_list(father, children)-1;
 | 
						|
    if (last > 0)
 | 
						|
    {
 | 
						|
      for (int c = last; c >= 0; c--)
 | 
						|
      {
 | 
						|
        const TRectype& rec = (const TRectype&)children[c];
 | 
						|
        if (rec.get("NRIG") == key)
 | 
						|
          break;
 | 
						|
      }
 | 
						|
      if (c >= 0 && c < last)
 | 
						|
        _curr = &(TRectype&)children[c+1];
 | 
						|
      else
 | 
						|
        _curr = NULL;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      _curr = NULL;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    const int brother = atoi(key) + 1;
 | 
						|
    _curr = find(father, brother);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return _curr != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_rbrother()
 | 
						|
{
 | 
						|
  const bool ok = has_rbrother();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    kill_child();
 | 
						|
    add_child();
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::has_lbrother() const
 | 
						|
{
 | 
						|
  const int last = _path.items()-1;
 | 
						|
  if (last < 1)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  TString80 key; _path.get(last-1, key);
 | 
						|
  isola_codice(key);
 | 
						|
  const TCodice_articolo father(key);
 | 
						|
  curr_comp(key);
 | 
						|
 | 
						|
  if (_sort > 0)
 | 
						|
  {
 | 
						|
    TPointer_array children;
 | 
						|
    const int last = build_children_list(father, children)-1;
 | 
						|
    if (last > 0)
 | 
						|
    {
 | 
						|
      for (int c = last; c > 0; c--)
 | 
						|
      {
 | 
						|
        const TRectype& rec = (const TRectype&)children[c];
 | 
						|
        if (rec.get("NRIG") == key)
 | 
						|
          break;
 | 
						|
      }
 | 
						|
      if (c > 0)
 | 
						|
        _curr = &(TRectype&)children[c-1];
 | 
						|
      else
 | 
						|
        _curr = NULL;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      _curr = NULL;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    const int brother = atoi(key) - 1;
 | 
						|
    if (brother > 0)
 | 
						|
      _curr = find(father, brother);
 | 
						|
    else
 | 
						|
      _curr = NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return _curr != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_lbrother()
 | 
						|
{
 | 
						|
  const bool ok = has_lbrother();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    kill_child();
 | 
						|
    add_child();
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::has_father() const
 | 
						|
{
 | 
						|
  const int items = _path.items();
 | 
						|
  return items > 1;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::goto_father()
 | 
						|
{
 | 
						|
  const bool ok = has_father();
 | 
						|
  if (ok)
 | 
						|
    kill_child();
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::is_root() const
 | 
						|
{
 | 
						|
  const int items = _path.items();
 | 
						|
  return items <= 1;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::is_leaf() const
 | 
						|
{
 | 
						|
  TCodice_articolo key; curr_code(key);
 | 
						|
  const TRectype* first_son = find(key, 1);
 | 
						|
  return first_son == NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::is_mag(const char* c) const
 | 
						|
{
 | 
						|
  TCodice_articolo code = c;
 | 
						|
  if (code.blank())
 | 
						|
    curr_code(code);
 | 
						|
  const TString& desc = ((TDistinta_tree*)this)->_mag.decode(code);
 | 
						|
  return desc.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
bool TDistinta_tree::is_lav(const char* c) const
 | 
						|
{
 | 
						|
  TCodice_articolo code = c;
 | 
						|
  if (code.blank())
 | 
						|
    curr_code(code);
 | 
						|
  const TString& desc = ((TDistinta_tree*)this)->_lav.decode(code);
 | 
						|
  return desc.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
char TDistinta_tree::get_type(const char* c) const
 | 
						|
{
 | 
						|
  char type = 'V';
 | 
						|
  if (is_mag(c))
 | 
						|
    type = 'A';
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (is_lav(c))
 | 
						|
      type = 'L';
 | 
						|
  }
 | 
						|
  return type;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TDistinta_tree::set_sort_key(int k)
 | 
						|
{
 | 
						|
  CHECK(k >= 0 && k <= 5, "Chiave distinta errata");
 | 
						|
  _sort = k;
 | 
						|
}
 | 
						|
 | 
						|
TTypeexp TDistinta_tree::get_var_type(const char* var)
 | 
						|
{
 | 
						|
  const TString& vt = _vars.decode(var);
 | 
						|
  return vt.blank() ? _strexpr : _numexpr;
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::pop_vars()
 | 
						|
{
 | 
						|
  _stack.pop();
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::clear_globals()
 | 
						|
{
 | 
						|
  _globals.destroy();
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::set_global(const char* name, const char* val)
 | 
						|
{
 | 
						|
  TString* str = new TString(val);
 | 
						|
  _globals.add(name, str, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::set_global(const char* name, const real& val)
 | 
						|
{
 | 
						|
  _globals.add(name, val, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
const TString& TDistinta_tree::get_string(const char* var)
 | 
						|
{
 | 
						|
  for (int s = 0; s < _stack.count(); s++)
 | 
						|
  {
 | 
						|
    TAssoc_array& a = (TAssoc_array&)_stack.peek(s);
 | 
						|
    TObject* val = a.objptr(var);
 | 
						|
    if (val)
 | 
						|
    {
 | 
						|
      if (val->class_id() == CLASS_STRING)
 | 
						|
        return (TString&)*val;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  TObject* val = _globals.objptr(var);
 | 
						|
  if (val && val->class_id() == CLASS_STRING)
 | 
						|
    return (TString&)*val;
 | 
						|
 | 
						|
  return EMPTY_STRING;
 | 
						|
}
 | 
						|
 | 
						|
const real& TDistinta_tree::get_real(const char* var)
 | 
						|
{
 | 
						|
  for (int s = 0; s < _stack.count(); s++)
 | 
						|
  {
 | 
						|
    TAssoc_array& a = (TAssoc_array&)_stack.peek(s);
 | 
						|
    TObject* val = a.objptr(var);
 | 
						|
    if (val)
 | 
						|
    {
 | 
						|
      if (val->class_id() != CLASS_STRING)
 | 
						|
        return (real&)*val;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  TObject* val = _globals.objptr(var);
 | 
						|
  if (val && val->class_id() != CLASS_STRING)
 | 
						|
    return (real&)*val;
 | 
						|
  
 | 
						|
  return ZERO;
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::evaluate(TDistinta_expr& e)
 | 
						|
{
 | 
						|
  for (int v = e.numvar()-1; v >= 0; v--)
 | 
						|
  {
 | 
						|
    const char* name = e.varname(v);
 | 
						|
    const TTypeexp vartype = get_var_type(name);
 | 
						|
    if (vartype == _numexpr)
 | 
						|
      e.setvar(v, get_real(name));
 | 
						|
    else
 | 
						|
      e.setvar(v, get_string(name));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
real TDistinta_tree::evaluate_numexpr(const char* str)
 | 
						|
{
 | 
						|
  TDistinta_expr e;
 | 
						|
  e.set(str, _numexpr);
 | 
						|
  evaluate(e);
 | 
						|
  return e.as_real();
 | 
						|
}
 | 
						|
 | 
						|
void TDistinta_tree::evaluate_strexpr(const char* str, TString& res)
 | 
						|
{
 | 
						|
  TDistinta_expr e;
 | 
						|
  e.set(str, _strexpr);
 | 
						|
  evaluate(e);
 | 
						|
  res = e.as_string();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TDistinta_tree::push_vars()
 | 
						|
{
 | 
						|
  TAssoc_array* vars = new TAssoc_array;
 | 
						|
  _stack.push(vars);
 | 
						|
 | 
						|
  TCodice_articolo var; curr_code(var);
 | 
						|
  const TString& memo_field = _dist.decode(var);
 | 
						|
  
 | 
						|
  if (!memo_field.blank())
 | 
						|
  {
 | 
						|
    TString80 expr;
 | 
						|
    TDistinta_expr e;
 | 
						|
 | 
						|
    TToken_string memo(memo_field, '\n');
 | 
						|
 | 
						|
    for (const char* str = memo.get(0); str; str = memo.get())
 | 
						|
    {
 | 
						|
      char* equal = strchr(str, '=');
 | 
						|
      if (equal)
 | 
						|
      {
 | 
						|
        *equal = '\0';
 | 
						|
        var = str;
 | 
						|
        expr = equal + 1;
 | 
						|
        const TTypeexp exprtype = get_var_type(var);
 | 
						|
        e.set(expr, exprtype);
 | 
						|
        evaluate(e);
 | 
						|
 | 
						|
        if (exprtype == _numexpr)
 | 
						|
          vars->add(var, e.as_real());
 | 
						|
        else
 | 
						|
          vars->add(var, e.as_string());
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
struct TExplosion_params
 | 
						|
{
 | 
						|
  TArray*   _array;
 | 
						|
  TString16 _filter;
 | 
						|
  int       _raggruppa;
 | 
						|
  int       _max_depth;
 | 
						|
  int       _sort_key;
 | 
						|
  bool      _materiali_base;
 | 
						|
  bool      _last_qta;
 | 
						|
};
 | 
						|
 | 
						|
static bool explode_callback(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  if (when == SCAN_PRE_ORDER)
 | 
						|
  {
 | 
						|
    TDistinta_tree& tree = (TDistinta_tree&)node;
 | 
						|
    if (tree.is_root())
 | 
						|
      return FALSE;         // Don't explode roots
 | 
						|
 | 
						|
    const TExplosion_params& ep = *(const TExplosion_params*)jolly;
 | 
						|
    if (ep._materiali_base && !tree.is_leaf())
 | 
						|
      return FALSE;         // Please, leaves only
 | 
						|
 | 
						|
    TRiga_esplosione er(tree, ep);
 | 
						|
    
 | 
						|
    const char type = er.tipo();
 | 
						|
    if (ep._filter.not_empty())
 | 
						|
    {
 | 
						|
      if (ep._filter.find(type) < 0)
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    if (ep._sort_key > 0)
 | 
						|
    {
 | 
						|
      if (er.ordinamento() <= 0)
 | 
						|
        return FALSE;      // Non fa parte dell'ordinamento
 | 
						|
    }
 | 
						|
 | 
						|
    ep._array->add(er);
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
int TDistinta_tree::raggruppa(TArray& boom, int mode) const
 | 
						|
{
 | 
						|
  for (int i = 0; i < boom.items(); i++)
 | 
						|
  {
 | 
						|
    TRiga_esplosione& qta1 = (TRiga_esplosione&)boom[i];
 | 
						|
  
 | 
						|
    if (mode == 2)
 | 
						|
      qta1.convert_to_base();
 | 
						|
 | 
						|
    for (int j = boom.items()-1; j > i; j--)
 | 
						|
    {
 | 
						|
      TRiga_esplosione& qta2 = (TRiga_esplosione&)boom[j];
 | 
						|
      if (qta1.articolo() != qta2.articolo())
 | 
						|
        continue;
 | 
						|
     
 | 
						|
      if (mode == 3 && qta1.um() != qta2.um())
 | 
						|
        continue;
 | 
						|
 | 
						|
      qta1 += qta2;  
 | 
						|
      boom.destroy(j, TRUE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return boom.items();
 | 
						|
}
 | 
						|
 | 
						|
int TDistinta_tree::explode(TArray& boom, 
 | 
						|
                            bool mb, int gr, int md, 
 | 
						|
                            const char* filter, int sk,
 | 
						|
                            bool lq)
 | 
						|
{
 | 
						|
  const int old_sk = get_sort_key();
 | 
						|
  const int old_md = get_max_depth();
 | 
						|
  if (mb) md = 0;
 | 
						|
 | 
						|
  set_sort_key(sk);
 | 
						|
  set_max_depth(md);
 | 
						|
 | 
						|
  TExplosion_params ep;
 | 
						|
  ep._array = &boom;
 | 
						|
  ep._materiali_base = mb;
 | 
						|
  ep._raggruppa = gr;
 | 
						|
  ep._max_depth = md;
 | 
						|
  ep._filter = filter;
 | 
						|
  ep._sort_key = sk;
 | 
						|
  ep._last_qta = lq;
 | 
						|
 | 
						|
  scan_depth_first(explode_callback, &ep);
 | 
						|
 | 
						|
  set_sort_key(old_sk);
 | 
						|
  set_max_depth(old_md);
 | 
						|
 | 
						|
  if (gr)
 | 
						|
    raggruppa(boom, gr);
 | 
						|
 | 
						|
  return boom.items();
 | 
						|
}
 | 
						|
 | 
						|
TDistinta_tree::TDistinta_tree() 
 | 
						|
              : _rdist(LF_RDIST), _sort(0), _max_depth(0),
 | 
						|
                _dist(LF_DIST, "PARAMETRI"), _vars("VAR", "B0"),
 | 
						|
                _mag(LF_ANAMAG, "DESCR"), _lav("LAV")
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
TDistinta_tree::~TDistinta_tree()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TRiga_esplosione
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void TRiga_esplosione::init(const TDistinta_tree& tree, 
 | 
						|
                            const TExplosion_params& ep)
 | 
						|
{
 | 
						|
  TCodice_articolo art; tree.curr_code(art);
 | 
						|
  TCodice_um um; tree.curr_um(um);
 | 
						|
  real val = tree.curr_qta(ep._last_qta);
 | 
						|
  set(art, um, val);
 | 
						|
  tree.curr_giac(_giac);
 | 
						|
  _tipo = tree.get_type(art);
 | 
						|
  _sort = tree.curr_sort();
 | 
						|
  _livello = tree.curr_depth();
 | 
						|
}
 | 
						|
 | 
						|
TRiga_esplosione::TRiga_esplosione(const TDistinta_tree& tree,
 | 
						|
                                   const TExplosion_params& ep)
 | 
						|
{
 | 
						|
  init(tree, ep);
 | 
						|
}
 | 
						|
 | 
						|
TRiga_esplosione::TRiga_esplosione(const TRiga_esplosione& re)
 | 
						|
                : TQuantita(re)
 | 
						|
{
 | 
						|
  _giac = re._giac;
 | 
						|
  _tipo = re._tipo;
 | 
						|
  _livello = re._livello;
 | 
						|
  _sort = re._sort;
 | 
						|
}
 |