41d3f8ab37
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;
|
|
}
|