1853 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1853 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <ctype.h>
 | ||
| #include <stdlib.h>
 | ||
| 
 | ||
| #include <urldefid.h>
 | ||
| #include <currency.h>
 | ||
| #include <utility.h>
 | ||
| #include "tabutil.h"
 | ||
| 
 | ||
| #include "dblib.h"
 | ||
| 
 | ||
| #include "../mg/anamag.h"
 | ||
| #include "../mg/umart.h" 
 | ||
| #include "../mg/rmovmag.h" 
 | ||
| #include "../include/rdoc.h"
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TQuantita' 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| const fraction& TQuantita::get_factor(const TCodice_um& um) const
 | ||
| {
 | ||
|   static TAssoc_array factors;
 | ||
|     
 | ||
|   TString80 code;
 | ||
|   code << _articolo << '|' << (um.empty() ? _um : um);
 | ||
|   
 | ||
|   fraction* conv = (fraction*)factors.objptr(code);
 | ||
|   if (conv == NULL)
 | ||
|   {
 | ||
|     TLocalisamfile umart(LF_UMART);
 | ||
|     umart.setkey(2);
 | ||
|     umart.put(UMART_CODART, _articolo);
 | ||
|     umart.put(UMART_UM, um.empty() ? _um : um);
 | ||
|     if (umart.read() == NOERR)
 | ||
|       conv = new fraction(umart.get_real(UMART_FC), UNO);
 | ||
|     else
 | ||
|       conv = new fraction(1,1);
 | ||
|     factors.add(code, conv);
 | ||
|   }
 | ||
|   
 | ||
|   return *conv;
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::find_umbase(TCodice_um& um) const
 | ||
| {
 | ||
|   TString80 code;
 | ||
|   code << _articolo << "|1"; 
 | ||
|   const TString& new_um = cache().get(LF_UMART, code, UMART_UM);
 | ||
|   if (new_um.blank())
 | ||
|     um = cache().get("LAV", _articolo, "S6");
 | ||
|   else
 | ||
|     um = new_um;
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::find_umdist(TCodice_um& um) const
 | ||
| {
 | ||
|   um = cache().get(LF_DIST, _articolo, UMART_UM);
 | ||
|   if (um.blank()) 
 | ||
|     find_umbase(um);
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::set_articolo(const TString& art, const TString& um) 
 | ||
| {
 | ||
|   _articolo = art;
 | ||
| 
 | ||
|   if (isalnum(um[0]))
 | ||
|     _um = um;
 | ||
|   else
 | ||
|   {
 | ||
|     if (um.blank())
 | ||
|       find_umbase(_um);
 | ||
|     else
 | ||
|       find_umdist(_um);
 | ||
|   }
 | ||
| 
 | ||
|   if (!art.blank() && _um.blank())
 | ||
|     NFCHECK("Unita' di misura nulla per %s", (const char*)art);
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::copy(const TQuantita& q)
 | ||
| {
 | ||
|   _articolo = q._articolo;
 | ||
|   _um = q._um;
 | ||
|   _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 && !val.is_zero())
 | ||
|   {
 | ||
|     const fraction& mul = get_factor(from_um);
 | ||
|     const fraction& div = get_factor(to_um);
 | ||
|     val =  fraction(val, UNO) * mul / div;         
 | ||
|     TArticolo::round_um(val, to_um);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::convert2umdist()
 | ||
| {
 | ||
|   TCodice_um dummy;
 | ||
|   find_umdist(dummy);
 | ||
|   if (dummy != _um)
 | ||
|   {
 | ||
|     convert(_val, _um, dummy);
 | ||
|     _um = dummy;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TQuantita::convert2umbase()
 | ||
| {
 | ||
|   TCodice_um dummy;
 | ||
|   find_umbase(dummy);
 | ||
|   if (dummy != _um)
 | ||
|   {
 | ||
|     convert(_val, _um, dummy);
 | ||
|     _um = dummy;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TQuantita::currency2umbase(TCurrency& val) const
 | ||
| {
 | ||
|   TCodice_um ub;
 | ||
|   find_umbase(ub);
 | ||
|   if (_um != ub && !val.is_zero())
 | ||
|   {
 | ||
|     const fraction& mul = get_factor(_um);
 | ||
|     const fraction& div = get_factor(ub);
 | ||
|     const real v = fraction(val.get_num(), UNO) * mul / div;         
 | ||
|     val.set_num(v);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| real TQuantita::base_val() const
 | ||
| {
 | ||
|   TCodice_um dummy;
 | ||
|   find_umbase(dummy);
 | ||
|   if (dummy != _um)  // Se non sono gia' la base...
 | ||
|   {
 | ||
|     real v = _val;
 | ||
|     convert(v, _um, dummy);
 | ||
|     return v;
 | ||
|   }
 | ||
|   return _val;
 | ||
| }
 | ||
| 
 | ||
| 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 real& qta)
 | ||
| {
 | ||
|   _val += qta;
 | ||
|   return *this;
 | ||
| }
 | ||
| 
 | ||
| const TQuantita& TQuantita::operator -=(const real& qta)
 | ||
| {
 | ||
|   _val -= qta;
 | ||
|   return *this;
 | ||
| }
 | ||
| 
 | ||
| const TQuantita& TQuantita::operator +=(const TQuantita& q)
 | ||
| {
 | ||
|   if (!_um.blank())
 | ||
|   {
 | ||
|     real qta = q._val;
 | ||
|     if (_um != q._um)
 | ||
|       convert(qta, q._um, _um);
 | ||
|     _val += qta;
 | ||
|   }
 | ||
|   else
 | ||
|     copy(q);
 | ||
| 
 | ||
|   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() 
 | ||
| { }
 | ||
| 
 | ||
| TQuantita::TQuantita(const TString& art, const TString&  um, const real& val) 
 | ||
| { 
 | ||
|   set(art, um, val);
 | ||
| }
 | ||
| 
 | ||
| TQuantita::TQuantita(const TQuantita& q) 
 | ||
| { copy(q); }
 | ||
| 
 | ||
| TQuantita::~TQuantita() 
 | ||
| { 
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TLavorazione
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| 
 | ||
| // @cmember Legge il file <p f> con il tipo di record
 | ||
| int TLavorazione::read(TBaseisamfile& f, word op , word lockop)
 | ||
| {
 | ||
|   int err=TRectype::read(f, op, lockop );
 | ||
|   get_linee();
 | ||
|   return err;
 | ||
| }
 | ||
| // @cmember Legge il file <p f> con il tipo di record alla posizione desiderata
 | ||
| int TLavorazione::readat(TBaseisamfile& f, TRecnotype nrec, word lockop )
 | ||
| {
 | ||
|   int err=TRectype::readat(f, nrec, lockop );
 | ||
|   get_linee();
 | ||
|   return err;
 | ||
| }
 | ||
| // @cmember Aggiunge il record al file
 | ||
| int TLavorazione::write(TBaseisamfile& f) const
 | ||
| {
 | ||
|   ((TLavorazione *)this)->put_linee();
 | ||
|   return TRectype::write(f) ;
 | ||
| }
 | ||
| // @cmember Riscrive il record sul file
 | ||
| int TLavorazione::rewrite(TBaseisamfile& f) const
 | ||
| {
 | ||
|   ((TLavorazione *)this)->put_linee();
 | ||
|   return TRectype::rewrite(f) ;
 | ||
| }
 | ||
| 
 | ||
| const char* TLavorazione::cod_impianto(int l)
 | ||
| {
 | ||
|   return cache().get("LNP",cod_linea(l)).get("S6");
 | ||
| }
 | ||
| 
 | ||
| real TLavorazione::prezzo() const
 | ||
| {
 | ||
|   real p = get_real("R10");
 | ||
|   if (p.is_zero())  
 | ||
|   {
 | ||
|     if (is_euro_value(""))  // Se la ditta <20> in Euro
 | ||
|     {
 | ||
|       TPrice pr(get_real("R0") / 1936.27);
 | ||
|       p = pr.get_num();
 | ||
|     }
 | ||
|     else
 | ||
|       p = get_real("R0"); // Vecchio prezzo in lire
 | ||
|   }
 | ||
|   return p;
 | ||
| }
 | ||
| 
 | ||
| void TLavorazione::reset_linee()
 | ||
| {
 | ||
|   _linee.cut(0);
 | ||
| }
 | ||
| 
 | ||
| void TLavorazione::get_linee()
 | ||
| {
 | ||
|   char esse[3] ="S1";
 | ||
|   reset_linee();
 | ||
|   for (char s = '1'; s <= '5'; s++)
 | ||
|   {
 | ||
|     esse[1]=s;
 | ||
|     _linee << get(esse);
 | ||
|   }
 | ||
|   _linee.replace(SAFE_PIPE_CHR,'|');
 | ||
| }
 | ||
| 
 | ||
| void TLavorazione::put_linee()
 | ||
| {
 | ||
|   char esse[3]= "S1";
 | ||
|   int from=0, len=70;
 | ||
|   TString str;
 | ||
|   for (char s='1'; s<='5'; s++)
 | ||
|   {
 | ||
|     if (s > '3') len=20;
 | ||
|     esse[1]=s;
 | ||
|     str=_linee.mid(from,len);
 | ||
|     str.replace('|',SAFE_PIPE_CHR);
 | ||
|     put(esse, str);
 | ||
|     from+=len;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| int TLavorazione::linee() const
 | ||
| {
 | ||
|   return _linee.items()/3;
 | ||
| }
 | ||
| 
 | ||
| int TLavorazione::linee_standard() const 
 | ||
| {
 | ||
|   const int maxl = get_int("I1");
 | ||
|   const int lin = linee();
 | ||
|   return (maxl > 0 && maxl < lin) ? maxl : lin;
 | ||
| }
 | ||
| 
 | ||
| /*const TString& TLavorazione::linea(int l) const
 | ||
| {
 | ||
|   const int n = l / 14;
 | ||
|   CHECKD(n >= 0 && n <= 2, "Bad linea index ", l);
 | ||
|   char esse[3] = { 'S', char('1'+ n), '\0' };
 | ||
|   TString& str = _linee.cod_linea();
 | ||
|   const int pos = (l % 14) * 5;
 | ||
|   return str.mid(pos, 5);
 | ||
| }*/
 | ||
| 
 | ||
| const char * TLavorazione::cod_linea(int l)
 | ||
| {
 | ||
|   return _linee.get(l*3);
 | ||
| }
 | ||
| 
 | ||
| const int TLavorazione::raw_numpers_linea(int l)
 | ||
| {
 | ||
|   return atoi(_linee.get(l*3+1));
 | ||
| }
 | ||
| 
 | ||
| const int TLavorazione::numpers_linea(int l)
 | ||
| {
 | ||
|   real np(raw_numpers_linea(l));
 | ||
|   if (np.is_zero())
 | ||
|     np = get_real("R2");
 | ||
|   return (int)np.integer();
 | ||
| }
 | ||
| 
 | ||
| real TLavorazione::raw_produttiv_linea(int l)
 | ||
| {
 | ||
|   return real(_linee.get(l*3+2));
 | ||
| }
 | ||
| 
 | ||
| real TLavorazione::produttiv_linea(int l)
 | ||
| {
 | ||
|   real prod(raw_produttiv_linea(l));
 | ||
|   if (prod.is_zero())
 | ||
|     prod = get_real("R1");
 | ||
|   return prod;
 | ||
| }
 | ||
| 
 | ||
| const int TLavorazione::find_linea(const TString& linea)
 | ||
| {
 | ||
|   _linee.restart();
 | ||
| 
 | ||
|   if (linea.empty()) // Se la linea da cercare e' blank, ritorna la prima disponibile
 | ||
|     return 0;
 | ||
| 
 | ||
|   for (int l = 0; ;l++)
 | ||
|   {
 | ||
|     const char* c = _linee.get(l*3);
 | ||
|     if (!c || *c == '\0')
 | ||
|       break;
 | ||
|     if (linea == c)
 | ||
|       return l;
 | ||
|   }
 | ||
| 
 | ||
|   return -1;
 | ||
| }
 | ||
| 
 | ||
| bool TLavorazione::set_cod_linea(int l, const char *c)
 | ||
| {
 | ||
|   _linee.add(c, l*3);
 | ||
|   return _linee.len()<250;
 | ||
| }
 | ||
| 
 | ||
| bool TLavorazione::set_numpers_linea(int l, int pers)
 | ||
| {
 | ||
|   _linee.add(pers,l*3+1);
 | ||
|   return _linee.len()<250;
 | ||
| }
 | ||
| 
 | ||
| bool TLavorazione::set_produttiv_linea(int l, real & prod)
 | ||
| {
 | ||
|   _linee.add(prod.string(),l*3+2);
 | ||
|   return _linee.len()<250;
 | ||
| }
 | ||
| 
 | ||
| TLavorazione::TLavorazione(const char* cod)
 | ||
|             : TRectype(LF_TAB)
 | ||
| {
 | ||
|   if (cod && *cod)
 | ||
|     *this = cache().get("LAV", cod);
 | ||
|   else
 | ||
|     settab("LAV");
 | ||
| }
 | ||
| 
 | ||
| TRectype& TLavorazione::operator =(const TRectype& rec)
 | ||
| {
 | ||
|   TRectype::operator =(rec);
 | ||
|   get_linee();
 | ||
|   return *this;
 | ||
| }
 | ||
| 
 | ||
| TLavorazione::TLavorazione(const TRectype& rec) : TRectype(rec) 
 | ||
| { get_linee(); }
 | ||
| 
 | ||
| TLavorazione::TLavorazione(const TLavorazione& rec) : TRectype(rec) 
 | ||
| { _linee = rec._linee; }
 | ||
| 
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TDistinta_expr
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| bool TDistinta_expr::print_error(const char* msg) const
 | ||
| {
 | ||
|   return error_box(msg);
 | ||
| }
 | ||
| 
 | ||
| TDistinta_expr::TDistinta_expr()
 | ||
|               : TExpression(_numexpr, FALSE)
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TDistinta_tree
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| #define TREE_SEPARATOR  '~'
 | ||
| 
 | ||
| const TRectype* TDistinta_tree::_curr = NULL;
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| bool TDistinta_tree::isola_codice(TString& code) const
 | ||
| {
 | ||
|   int comma = code.find(TREE_SEPARATOR);
 | ||
|   if (comma > 0)
 | ||
|     code.cut(comma);
 | ||
|   return code.not_empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::father_code(TCodice_articolo& code) const
 | ||
| {
 | ||
|   const int it = _path.items();
 | ||
|   _path.get(it - 2, (TString &)_tmp);
 | ||
|   isola_codice((TString &)_tmp);
 | ||
|   code = _tmp;
 | ||
|   return code.not_empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::father_giaclev(TString& code, int levnum) const
 | ||
| {
 | ||
|   const int it = _path.items();
 | ||
|   _path.get(it - 2, (TString &) _tmp);
 | ||
|   _tmp.get(1, code);
 | ||
|   if (levnum>0)
 | ||
|     code = livgiac().unpack_grpcode(code, levnum).trim();
 | ||
|   return code.not_empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::path_code(TCodice_articolo& code, const TToken_string &path) const
 | ||
| {
 | ||
|   path.get(-2, (TString &)_tmp);
 | ||
|   isola_codice((TToken_string &)_tmp);
 | ||
|   code = _tmp;
 | ||
|   return code.not_empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::path_giaclev(TString& code, int levnum, const TToken_string &path) const
 | ||
| {
 | ||
| 	path.get(-2, (TString &)_tmp);
 | ||
|   _tmp.get(1, code);
 | ||
|   if (levnum>0)
 | ||
|     code = livgiac().unpack_grpcode(code, levnum).trim();
 | ||
|   return code.not_empty();
 | ||
| }
 | ||
| 
 | ||
| int TDistinta_tree::curr_comp(TString& code) const
 | ||
| {
 | ||
|   _path.get(-2, (TString &)_tmp);
 | ||
|   _tmp.get(2, code);
 | ||
|   return atoi(code);
 | ||
| }
 | ||
| 
 | ||
| long TDistinta_tree::curr_sort() const
 | ||
| {
 | ||
|   _path.get(-2, (TString &)_tmp);
 | ||
|   return ((TToken_string &)_tmp).get_long(3);
 | ||
| }
 | ||
| 
 | ||
| const char* TDistinta_tree::curr_um(TCodice_um& code) const
 | ||
| {
 | ||
|   _path.get(-2, (TString &)_tmp);
 | ||
|   _tmp.get(4, code);
 | ||
|   return code;
 | ||
| }
 | ||
| 
 | ||
| real TDistinta_tree::last_qta(bool vis_ghost) const
 | ||
| {
 | ||
|   const int last = _path.items()-1;
 | ||
|   int from = last - 1;
 | ||
|   TCodice_articolo art;
 | ||
|   TCodice_um um;
 | ||
|   real val;
 | ||
|   real tot = 1.0;
 | ||
|   TQuantita qta;
 | ||
|     
 | ||
|   if (!vis_ghost)
 | ||
|   {                    
 | ||
|     for (int i = from ; i >= 0; i--)
 | ||
|     {
 | ||
|       _path.get(i, (TString &)_tmp);
 | ||
|       if (((TToken_string &)_tmp).get_char(6) != 'G')
 | ||
|       {
 | ||
|         from = i + 1;
 | ||
|         break;
 | ||
|       }
 | ||
|     }
 | ||
|   }  
 | ||
|   if (from < 0)
 | ||
|     from = 0;
 | ||
|                           
 | ||
|   for (int i = 0; i <= last; i++)
 | ||
|   {
 | ||
|     _path.get(i, (TString &) _tmp);
 | ||
|     _tmp.get(5, val);
 | ||
|     _tmp.get(0, art);
 | ||
|     _tmp.get(4, um);
 | ||
|     if (i > 0)
 | ||
|     {
 | ||
|       qta.set_val(val);
 | ||
|       qta.convert2umdist();
 | ||
|       val = qta.val();              
 | ||
|     }                
 | ||
|     qta.set(art, um, ZERO);
 | ||
|     int tprec = tot.precision();
 | ||
|     int vprec = val.precision();
 | ||
|     if (tprec + vprec > 15)
 | ||
|     {
 | ||
|       while (tprec + vprec > 16)
 | ||
|       {
 | ||
|         if (tprec > vprec)
 | ||
|           --tprec;
 | ||
|         else
 | ||
|           --vprec;
 | ||
|       }
 | ||
|       tot.round(tprec);
 | ||
|       val.round(vprec);
 | ||
|     }                 
 | ||
| #ifdef DBG   
 | ||
|     TString s(tot.string());
 | ||
|     TString s1(val.string());
 | ||
| #endif             
 | ||
|     if (i >= from)
 | ||
|       tot *= val;
 | ||
| #ifdef DBG
 | ||
|     s = tot.string();
 | ||
| #endif
 | ||
|     if (tot.is_zero())
 | ||
|       break;
 | ||
|   }
 | ||
|   if (tot.precision() > 15)
 | ||
|     tot.round(15);
 | ||
|   return tot;
 | ||
| }
 | ||
| 
 | ||
| real TDistinta_tree::curr_qta() const
 | ||
| {
 | ||
|   real tot = 1.0;
 | ||
|   const int last = _path.items()-1;
 | ||
|   TCodice_articolo art;
 | ||
|   TCodice_um um;
 | ||
|   real val;
 | ||
|   TQuantita qta;
 | ||
|   for (int i = 0; i <= last; i++)
 | ||
|   {
 | ||
|     _path.get(i, (TString &) _tmp);
 | ||
|     _tmp.get(5, val);
 | ||
| //    if (i < last)
 | ||
|     _tmp.get(0, art);
 | ||
|     _tmp.get(4, um);
 | ||
|     if (i > 0)
 | ||
|     {
 | ||
|       qta.set_val(val);
 | ||
|       qta.convert2umdist();
 | ||
|       val = qta.val();              
 | ||
|     }                
 | ||
|     qta.set(art, um, ZERO);
 | ||
|     int tprec = tot.precision();
 | ||
|     int vprec = val.precision();
 | ||
|     if (tprec + vprec > 15)
 | ||
|     {
 | ||
|       while (tprec + vprec > 16)
 | ||
|       {
 | ||
|         if (tprec > vprec)
 | ||
|           --tprec;
 | ||
|         else
 | ||
|           --vprec;
 | ||
|       }
 | ||
|       tot.round(tprec);
 | ||
|       val.round(vprec);
 | ||
|     }                 
 | ||
| #ifdef DBG   
 | ||
|     TString s(tot.string());
 | ||
|     TString s1(val.string());
 | ||
| #endif
 | ||
|     tot *= val;
 | ||
| #ifdef DBG
 | ||
|     s = tot.string();
 | ||
| #endif
 | ||
|     if (tot.is_zero())
 | ||
|       break;
 | ||
|   }
 | ||
|   if (tot.precision() > 15)
 | ||
|     tot.round(15);
 | ||
|   return tot;
 | ||
| }
 | ||
| 
 | ||
| char TDistinta_tree::path_type(const TToken_string & path) const
 | ||
| {
 | ||
|   path.get(-2, (TString &)_tmp);
 | ||
|   char ap = ((TToken_string &) _tmp).get_char(6);
 | ||
|   return ap;
 | ||
| }
 | ||
| 
 | ||
| int TDistinta_tree::path_depth(const TToken_string & path) const 
 | ||
| { 
 | ||
|   int depth = path.items()-1; 
 | ||
|   if (_ignore_ghost)
 | ||
|   {
 | ||
|     for (int i = depth; i > 0; i--)
 | ||
|     {
 | ||
|       path.get(i, (TString &)_tmp);
 | ||
|       char ap = ((TToken_string &)_tmp).get_char(6);
 | ||
|       if (ap == 'G') depth--;
 | ||
|     }
 | ||
|   }
 | ||
|   return depth;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::goto_node(const TString &id)
 | ||
| {
 | ||
|   if (id != _path)
 | ||
|   {
 | ||
|     _stack.destroy();
 | ||
|     TToken_string str(id);
 | ||
|     _path = str.get(0);
 | ||
|     if (!push_vars())
 | ||
|       return FALSE;
 | ||
|     for (const char* t = str.get(); t; t = str.get())
 | ||
|     {
 | ||
|       _path.add(t);
 | ||
|       if (!push_vars())
 | ||
|         return FALSE;
 | ||
|     }
 | ||
|   }
 | ||
|   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;
 | ||
| }
 | ||
| 
 | ||
| const TString& TDistinta_tree::describe(const TCodice_articolo& codart) const 
 | ||
| {
 | ||
|   TString & descr = get_tmp_string();
 | ||
|   describe(codart, descr);
 | ||
|   return descr;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::describe(const TCodice_articolo& codart, TString& descr) const 
 | ||
| {
 | ||
|   descr = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR);
 | ||
|   if (descr.not_empty()) 
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   descr = cache().get("LAV", codart, "S0");
 | ||
|   if (descr.not_empty()) 
 | ||
|     return TRUE;
 | ||
|   
 | ||
|   const TRectype& rec = cache().get(LF_DIST, codart);
 | ||
|   descr = rec.get("DESCR");
 | ||
|   return !rec.empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::get_livgiac_on_descr(int l) const 
 | ||
| {
 | ||
|   if (livgiac().enabled(l))
 | ||
|     return _livgiac_on_descr[l-1];
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::set_livgiac_on_descr(int l, bool on)
 | ||
| {
 | ||
|   if (livgiac().enabled(l))
 | ||
|     return _livgiac_on_descr[l-1]=on;
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::get_description(TString& desc) const 
 | ||
| { 
 | ||
|   TCodice_articolo codart; curr_code(codart);
 | ||
|   if (!describe(codart, desc))
 | ||
|     desc = "???";
 | ||
|   else
 | ||
|   {
 | ||
|     for (int l = 1; l <= livgiac().last_level(); l++) if (get_livgiac_on_descr(l))
 | ||
|     {
 | ||
|       TString16 giaclev; curr_giaclev(giaclev,l);
 | ||
|       if (!giaclev.empty() )
 | ||
|         desc << ' ' << livgiac().name(l) << ' ' << giaclev;
 | ||
|     }
 | ||
|     if (get_qta_on_descr())
 | ||
|     {
 | ||
|       TCodice_um code; curr_um(code);
 | ||
|       desc << ' ' << get_descr_separator() << ' '
 | ||
|            << curr_qta().string() << ' ' << code;
 | ||
|     }
 | ||
|   }
 | ||
|   desc.insert(format(" %c ",get_descr_separator()), 0);
 | ||
|   desc.insert(codart, 0);
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| TImage* TDistinta_tree::image(bool selected) const
 | ||
| {
 | ||
|   TImage* img;
 | ||
|   if (is_cyclic())
 | ||
|     img = get_res_image(BMP_STOP);
 | ||
|   else
 | ||
|   {
 | ||
|     if (is_leaf())
 | ||
|     {
 | ||
|       TCodice_articolo art; curr_code(art);
 | ||
|       if (art == "???")
 | ||
|         img = get_res_image(BMP_STOP);
 | ||
|       else 
 | ||
|         img = get_res_image(BMP_FILE);
 | ||
|     }
 | ||
|     else
 | ||
|       img = TBidirectional_tree::image(selected);
 | ||
|   }
 | ||
|   return img;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::restart()
 | ||
| {
 | ||
|   return shrink_all();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::set_root(const TQuantita& qta, const char* livgiac)
 | ||
| {
 | ||
|   bool ok = find_child(qta.articolo(), 1) != NULL;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     _tmp = qta.articolo(); // codice 
 | ||
|     _tmp.add(livgiac);     // livgiac
 | ||
|     _tmp.add('0');
 | ||
|     _tmp.add('0');
 | ||
|     _tmp.add(qta.um());    // unita' di misura
 | ||
|     _tmp.add(qta.val().string()); // quantita
 | ||
|     _tmp.add(get_type(qta.articolo()));
 | ||
|     
 | ||
|     _root = _tmp;
 | ||
|     ok = restart();
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::set_root(const TCodice_articolo& art,
 | ||
|                               const char* um, real qta, 
 | ||
|                               const char* livgiac)
 | ||
| {
 | ||
|   bool ok = find_child(art, 1) != NULL;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     const TCodice_um umart = um;
 | ||
|     const TQuantita q(art, umart, qta);
 | ||
|     ok = set_root(q, livgiac);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::set_root(const TRectype & rec)
 | ||
| {                                  
 | ||
|   const int logicnum = rec.num();
 | ||
|   TCodice_articolo art;
 | ||
|   TCodice_um umart;
 | ||
|   TString16 livgiac;
 | ||
|   real qta;
 | ||
|   clear_globals();
 | ||
|   
 | ||
|   switch (logicnum)
 | ||
|   {
 | ||
|     case LF_RIGHEDOC:                                                      
 | ||
|       art = rec.get(RDOC_CODARTMAG);
 | ||
|       if (art.empty())
 | ||
|         art = rec.get(RDOC_CODART);
 | ||
|       umart = rec.get(RDOC_UMQTA);
 | ||
|       qta = rec.get_real(RDOC_QTA);
 | ||
|       livgiac = rec.get(RDOC_LIVELLO);
 | ||
|       set_global("_MAGDEP", rec.get(RDOC_CODMAG));
 | ||
|       set_global("_LINEA", rec.get(RDOC_LINEA));
 | ||
|       set_global("_IMPIANTO", rec.get(RDOC_IMPIANTO));
 | ||
|       break;
 | ||
|     case LF_RMOVMAG:
 | ||
|       art = rec.get(RMOVMAG_CODART);
 | ||
|       umart = rec.get(RMOVMAG_UM);
 | ||
|       qta = rec.get_real(RMOVMAG_QUANT);
 | ||
|       livgiac = rec.get(RMOVMAG_LIVGIAC);
 | ||
|       set_global("_MAGDEP", rec.get(RMOVMAG_CODMAG));
 | ||
|       set_global("_LINEA", rec.get(RMOVMAG_LINEA));
 | ||
|       set_global("_IMPIANTO", rec.get(RMOVMAG_IMPIANTO));
 | ||
|       break;
 | ||
|     default:
 | ||
|       NFCHECK("set root con un record (file n. %d) non previsto", logicnum);
 | ||
|       break;
 | ||
|   }
 | ||
|   return set_root(art, umart, qta, livgiac);
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::has_root() const
 | ||
| {
 | ||
|   return _root.not_empty();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::goto_root()
 | ||
| {
 | ||
|   bool ok = has_root();
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     _path = _root;
 | ||
|     _stack.destroy();
 | ||
|     ok = 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, (TString &)_tmp);
 | ||
|     TCodice_articolo mycod; _tmp.get(0, mycod); mycod.trim();
 | ||
|     for (int i = last-1; i >= 0; i--)
 | ||
|     {
 | ||
|       path.get(i, (TString &)_tmp);
 | ||
|       isola_codice((TToken_string &)_tmp);
 | ||
|       if (_tmp == mycod)
 | ||
|       {
 | ||
|         cyclic = TRUE;
 | ||
|         break;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return cyclic;
 | ||
| }
 | ||
| 
 | ||
| static int compare_rdist_key(const TObject** o1, const TObject** o2)
 | ||
| {
 | ||
|   TToken_string* s1 = (TToken_string*)(*o1);
 | ||
|   TToken_string* s2 = (TToken_string*)(*o2);
 | ||
| 
 | ||
|   long sk1 = s1->get_long(3);
 | ||
|   long sk2 = s2->get_long(3);
 | ||
|   if (sk1 == 0 && sk2 == 0)
 | ||
|   {
 | ||
|     sk1 = s1->get_long(2);
 | ||
|     sk2 = s2->get_long(2);
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     if (sk1 == 0) sk1 = 100000000L;
 | ||
|     if (sk2 == 0) sk2 = 100000000L;
 | ||
|   }
 | ||
|   return sk1 == sk2 ? 0 : (sk1 > sk2 ? +1 : -1);
 | ||
| }
 | ||
| 
 | ||
| const TRectype& TDistinta_tree::find_head(const TCodice_articolo& art) const
 | ||
| {
 | ||
|   const TRectype& rec = cache().get(LF_DIST, art);
 | ||
|   return rec;
 | ||
| }
 | ||
| 
 | ||
| const TRectype* TDistinta_tree::find_child(const TCodice_articolo& father, int child) const
 | ||
| {
 | ||
|   TString80 key = father;
 | ||
|   key << '|' << child;
 | ||
|   const TRectype& rec = cache().get(LF_RDIST,key);
 | ||
| 
 | ||
|   return rec.empty() ? NULL : &rec;
 | ||
| }
 | ||
| 
 | ||
| int TDistinta_tree::build_children_list(const TCodice_articolo& father, TArray& children) const
 | ||
| {
 | ||
|   TToken_string key(39, TREE_SEPARATOR);
 | ||
|   for (int nrig = 1; ; nrig++)
 | ||
|   {
 | ||
|     const TRectype* rec = find_child(father, nrig);
 | ||
|     if (rec == NULL)
 | ||
|       break;
 | ||
|     key.add(rec->get("CODCOMP"),0);
 | ||
|     key.add(rec->get("LIVELLO"),1);
 | ||
|     key.add(nrig,2);
 | ||
|     if (_sort > 0)
 | ||
|     {
 | ||
|       TString16 field; field.format("SORT%d", _sort);
 | ||
|       key.add(rec->get(field), 3);
 | ||
|     }
 | ||
|     children.add(key);
 | ||
|   }
 | ||
|   const int total = children.items();
 | ||
|   if (total > 1 && _sort != 0)
 | ||
|   {
 | ||
|     children.sort((COMPARE_FUNCTION)compare_rdist_key);
 | ||
|   }
 | ||
|   return total;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::has_son() const
 | ||
| {
 | ||
|   if (_max_depth > 0)
 | ||
|   {
 | ||
|     const int depth = curr_depth();
 | ||
|     if (depth >= _max_depth)
 | ||
|       return FALSE;
 | ||
|   }
 | ||
| 
 | ||
|   if (is_cyclic())
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   TCodice_articolo key; curr_code(key);
 | ||
| //  TString16 livgiac; curr_giaclev(livgiac);
 | ||
|   _curr = find_child(key, 1);
 | ||
|   // Se ci sono almeno due figli ed e' necessario ordinare
 | ||
|   if (_sort != 0 && find_child(key, 2) != NULL) 
 | ||
|   {
 | ||
|     TArray children;
 | ||
|     build_children_list(key, children);
 | ||
|     const int first = ((TToken_string*)children.objptr(0))->get_int(2);
 | ||
|     _curr = find_child(key, first);
 | ||
|   }
 | ||
|   return _curr != NULL;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::add_child()
 | ||
| {
 | ||
|   TCodice_articolo comp = _curr->get("CODCOMP");
 | ||
|   TString tmp,tmp2;
 | ||
|   if (_curr->get_char("TIPO") == 'V') // Espando la variabile
 | ||
|   {
 | ||
|     tmp = get_string(comp);
 | ||
|     if (tmp.blank() || tmp.len() > comp.size())
 | ||
|       tmp = "???";
 | ||
|     comp = tmp;
 | ||
|   }
 | ||
|   _path.add(comp);                      // 0 - Codice articolo
 | ||
| 
 | ||
|   _path << TREE_SEPARATOR;
 | ||
|   tmp = _curr->get("LIVELLO");
 | ||
|   if (livgiac().enabled())
 | ||
|   {
 | ||
|     TString fgiaclev;  father_giaclev(fgiaclev); 
 | ||
|     // ereditarieta'
 | ||
|     for (int l= 0 ; l < 4; l++) if (livgiac().enabled(l+1))
 | ||
|     {
 | ||
|       tmp2 = livgiac().unpack_grpcode(tmp, l+1);
 | ||
|       if (_curr->get("TIPO_LIV")[l]=='E')
 | ||
|       {
 | ||
|         tmp2 = livgiac().unpack_grpcode(fgiaclev, l+1);
 | ||
|         livgiac().pack_grpcode(tmp, tmp2 , l+1);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   _path << tmp;  // 1 Livello giacenza
 | ||
|   long num = _curr->get_long("NRIG");
 | ||
|   _path << TREE_SEPARATOR << num;                 // 2 Numero componente
 | ||
|   if (_sort > 0)
 | ||
|   {
 | ||
|     TString16 field; field << "SORT" << _sort;
 | ||
|     num = _curr->get_long(field);
 | ||
|   }
 | ||
|   _path << TREE_SEPARATOR << num;                 // 3 Numero ordinamento
 | ||
|   
 | ||
|   _path << TREE_SEPARATOR << _curr->get("UM");    // 4 Unita' di misura 
 | ||
| 
 | ||
|   const TString& expr = _curr->get("EXPR");
 | ||
|   const real qta = evaluate_numexpr(expr);
 | ||
|   _path << TREE_SEPARATOR << qta;                 // 5 Quantita' 
 | ||
|   _path << TREE_SEPARATOR << get_type(comp);      // 6 - Articolo, Lavorazione, Virtuale, Ghost
 | ||
| 
 | ||
|   push_vars();
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 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)
 | ||
|     return add_child();
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::has_rbrother() const
 | ||
| {
 | ||
|   const int last = _path.items()-1;
 | ||
|   if (last <= 0)
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   TString80 key; _path.get(last-1, key);
 | ||
|   isola_codice(key);
 | ||
|   const TCodice_articolo father(key);
 | ||
|   const int curr_nrig = curr_comp(key);
 | ||
| 
 | ||
|   if (_sort != 0)
 | ||
|   {
 | ||
|     TArray children;
 | ||
|     const int last = build_children_list(father, children)-1;
 | ||
|     if (last > 0)  // Ci sono almeno due fratelli
 | ||
|     {
 | ||
|     	int c;
 | ||
|     	
 | ||
|       for (c = last; c >= 0; c--)
 | ||
|       {                   
 | ||
|         const int nrig = ((TToken_string*)children.objptr(c))->get_int(2);
 | ||
|         if (nrig == curr_nrig)
 | ||
|           break;
 | ||
|       }
 | ||
|       if (c >= 0 && c < last)
 | ||
|       {
 | ||
|         const int brother = ((TToken_string*)children.objptr(c+1))->get_int(2);
 | ||
|         _curr = find_child(father, brother);
 | ||
|       }
 | ||
|       else
 | ||
|         _curr = NULL;
 | ||
|     }
 | ||
|     else
 | ||
|       _curr = NULL;
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     _curr = find_child(father, curr_nrig+1);
 | ||
|   }
 | ||
|   
 | ||
|   return _curr != NULL;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::goto_rbrother()
 | ||
| {
 | ||
|   const bool ok = has_rbrother();
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     kill_child();
 | ||
|     return add_child();
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::has_lbrother() const
 | ||
| {
 | ||
|   const int last = _path.items()-1;
 | ||
|   if (last <= 0)
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   TString80 key; _path.get(last-1, key);
 | ||
|   isola_codice(key);
 | ||
|   const TCodice_articolo father(key);
 | ||
|   const int curr_nrig = curr_comp(key);
 | ||
| 
 | ||
|   if (_sort != 0)
 | ||
|   {
 | ||
|     TArray children;
 | ||
|     const int last = build_children_list(father, children)-1;
 | ||
|     if (last > 0)  // Ci sono almeno due fratelli
 | ||
|     {
 | ||
|     	int c;
 | ||
|     	
 | ||
|       for (c = last; c > 0; c--)
 | ||
|       {                   
 | ||
|         const int nrig = ((TToken_string*)children.objptr(c))->get_int(2);
 | ||
|         if (nrig == curr_nrig)
 | ||
|           break;
 | ||
|       }
 | ||
|       if (c > 0)
 | ||
|       {
 | ||
|         const int brother = ((TToken_string*)children.objptr(c-1))->get_int(2);
 | ||
|         _curr = find_child(father, brother);
 | ||
|       }
 | ||
|       else
 | ||
|         _curr = NULL;
 | ||
|     }
 | ||
|     else
 | ||
|       _curr = NULL;
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     const int brother = curr_nrig - 1;
 | ||
|     if (brother > 0)
 | ||
|       _curr = find_child(father, brother);
 | ||
|     else
 | ||
|       _curr = NULL;
 | ||
|   }
 | ||
|   
 | ||
|   return _curr != NULL;
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::goto_lbrother()
 | ||
| {
 | ||
|   const bool ok = has_lbrother();
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     kill_child();
 | ||
|     return 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_child(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);
 | ||
|   const TString& desc = cache().get(LF_ANAMAG, code, ANAMAG_DESCR);
 | ||
|   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);
 | ||
|   const TString& desc = cache().get("LAV", code, "S0");
 | ||
|   return desc.not_empty();
 | ||
| }
 | ||
| 
 | ||
| char TDistinta_tree::get_type(const char* c) const
 | ||
| {
 | ||
|   char type = ' ';       // Tipo sconosciuto
 | ||
|   if (c && *c > ' ')
 | ||
|   {
 | ||
|     if (is_mag(c))
 | ||
|       type = 'A';        // Articolo di magazzino
 | ||
|     else
 | ||
|     {
 | ||
|       if (is_lav(c))
 | ||
|         type = 'L';      // Lavorazione
 | ||
|       else
 | ||
|       {
 | ||
|         if (find_child(c, 1))  // E' una distinta
 | ||
|         {
 | ||
|           const TString& artprod = find_head(c).get("ARTPROD");
 | ||
|           if (artprod.blank())
 | ||
|             type = 'G'; // Distinta fantasma
 | ||
|           else
 | ||
|             type = 'V'; // Distinta virtuale
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return type;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TDistinta_tree::set_sort_key(int k)
 | ||
| {
 | ||
|   CHECKD(k >= 0 && k <= 5, "Chiave distinta errata: ", k);
 | ||
|   _sort = k;
 | ||
| }
 | ||
| 
 | ||
| TTypeexp TDistinta_tree::get_var_type(const char* var)
 | ||
| {
 | ||
|   const TString& vt = cache().get("VAR", var, "B0");
 | ||
|   return vt.blank() ? _strexpr : _numexpr;
 | ||
| }
 | ||
| 
 | ||
| void TDistinta_tree::pop_vars()
 | ||
| {
 | ||
|   _stack.pop();
 | ||
| }
 | ||
| 
 | ||
| bool TDistinta_tree::is_global(const char* var)
 | ||
| {
 | ||
|   const char * gvars[] = {"_IMPIANTO","_LINEA",
 | ||
|               "_MAGDEP","_MAGAZZINO","_DEPOSITO",
 | ||
|                 "_DISTINTA", "_RADICE", 
 | ||
|                   "_LIVELLO","_LIV1","_LIV2","_LIV3", "_LIV4",
 | ||
|                     NULL};
 | ||
|   const char ** gvar=gvars;
 | ||
|   for (; *gvar; gvar++)
 | ||
|     if (strcmp(*gvar, var)==0)
 | ||
|       return TRUE;
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| 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);
 | ||
| }                        
 | ||
| 
 | ||
| TObject * TDistinta_tree::get_global(const char* name, word classname)
 | ||
| {
 | ||
|   // defaults
 | ||
|   TObject* val = _globals.objptr(name);
 | ||
|   if (val && val->class_id() != classname)
 | ||
|     return NULL;
 | ||
|   if (classname==CLASS_STRING )
 | ||
|   {
 | ||
|     if (!val || ((TString *)val)->blank())
 | ||
|       val = global_default_str(name);
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     if (!val || ((real *)val)->is_zero())
 | ||
|       val = global_default_real(name);
 | ||
|   }
 | ||
|   return val;                             
 | ||
| }
 | ||
| 
 | ||
| TObject * TDistinta_tree::global_default_str(const char* name)
 | ||
| {
 | ||
|   TConfig ini(CONFIG_DITTA,"db");
 | ||
|   TObject* val=NULL;
 | ||
|   int c=0;
 | ||
|   TToken_string var;
 | ||
|   while (!(var = ini.get("GLOBAL_STR",NULL,c++)).blank())
 | ||
|   {
 | ||
|     if (strcmp(var.get(0),name)==0 && *var.get(1)>' ')
 | ||
|     {
 | ||
|       val= new TString(var.get(1));
 | ||
|       break;
 | ||
|     }
 | ||
|   }
 | ||
|   if (!val)
 | ||
|   {
 | ||
|     // more defaults
 | ||
|     ini.set_paragraph("mr");
 | ||
|     if (strcmp("_IMPIANTO",name)==0)
 | ||
|       val= new TString(ini.get("DEFAULT_CODIMP"));
 | ||
|     else if (strcmp("_LINEA",name)==0)
 | ||
|       val= new TString(ini.get("DEFAULT_CODLIN"));
 | ||
|     else
 | ||
|     {
 | ||
|       ini.set_paragraph("mg");
 | ||
|       // 
 | ||
|       //if (strcmp("_MAGDEP",name))
 | ||
|       //  val= new TString(ini.get("DEFAULT_CODMAGDEP"));
 | ||
|     }
 | ||
|   }
 | ||
|   if (val)
 | ||
|     _globals.add(name, val ,TRUE);
 | ||
|   return val;
 | ||
| }
 | ||
| 
 | ||
| TObject * TDistinta_tree::global_default_real(const char* name)
 | ||
| {
 | ||
|   TConfig ini(CONFIG_DITTA,"db");
 | ||
|   TObject* val=NULL;
 | ||
|   int c=0;
 | ||
|   TToken_string var;
 | ||
|   while (!(var = ini.get("GLOBAL_REAL",NULL,c++)).blank())
 | ||
|   {
 | ||
|     if (strcmp(var.get(0),name)==0 && *var.get(1)>' ')
 | ||
|     {
 | ||
|       val= new real(var.get(1));
 | ||
|       break;
 | ||
|     }
 | ||
|   }
 | ||
|   if (val)
 | ||
|     _globals.add(name, val ,TRUE);
 | ||
|   return val;
 | ||
| }
 | ||
| 
 | ||
| const TString& TDistinta_tree::get_string(const char* var)
 | ||
| {
 | ||
|   // local vars
 | ||
|   for (int s = 0; s < _stack.count(); s++)
 | ||
|   {
 | ||
|     TAssoc_array& a = (TAssoc_array&)_stack.peek(s);
 | ||
|     const TObject* val = a.objptr(var);
 | ||
|     if (val)
 | ||
|     {
 | ||
|       if (val->class_id() == CLASS_STRING)
 | ||
|         return (const TString&)*val;
 | ||
|     }
 | ||
|   }
 | ||
|   // globals & special vars
 | ||
|   static TCodice_articolo _varvalue;
 | ||
|   if (strcmp(var, "_DISTINTA")==0)
 | ||
|   {
 | ||
|     curr_code(_varvalue);
 | ||
|     return _varvalue;
 | ||
|   }
 | ||
|   if (strcmp(var, "_RADICE")==0)
 | ||
|   {          
 | ||
|     TString & _codice = get_tmp_string();
 | ||
|     _codice = _root;
 | ||
|     isola_codice(_codice);
 | ||
|     return _codice;
 | ||
|   }
 | ||
|   if (strncmp(var, "_LIV",4)==0)
 | ||
|   {
 | ||
|     switch (var[4]) 
 | ||
|     { 
 | ||
|       case 'E': curr_giaclev(_varvalue); break;
 | ||
|       case '1': curr_giaclev(_varvalue,1);break;
 | ||
|       case '2': curr_giaclev(_varvalue,2);break;
 | ||
|       case '3': curr_giaclev(_varvalue,3);break;
 | ||
|       case '4': curr_giaclev(_varvalue,4);break;
 | ||
|     }
 | ||
|     return _varvalue;
 | ||
|   }
 | ||
|   if (strcmp(var, "_MAGAZZINO")==0 || strcmp(var, "_DEPOSITO")==0)
 | ||
|   {
 | ||
|     TString* val = (TString*)get_global("_MAGDEP", CLASS_STRING);
 | ||
|     if (val)
 | ||
|     {
 | ||
|       _varvalue =* val;
 | ||
|       switch (var[1]) 
 | ||
|       { 
 | ||
|         case 'M': _varvalue.cut(3); break; // cod magazzino
 | ||
|         case 'D': _varvalue = _varvalue.mid(3);break; // cod deposito
 | ||
|       }
 | ||
|       return _varvalue;
 | ||
|     }
 | ||
|   }
 | ||
|   TObject* val = get_global(var, CLASS_STRING);
 | ||
|   if (val)    
 | ||
|     return (const 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);
 | ||
|     const TObject* val = a.objptr(var);
 | ||
|     if (val)
 | ||
|     {
 | ||
|       if (val->class_id() != CLASS_STRING)
 | ||
|         return (const real&)*val;
 | ||
|       else
 | ||
|         break;
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       val = a.objptr("_GHOST"); 
 | ||
|       if (val == NULL) // Non sono ghost per cui non posso andar oltre
 | ||
|         break;
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   const TObject* val = _globals.objptr(var);
 | ||
|   if (val && val->class_id() != CLASS_STRING)
 | ||
|     return (const real&)*val;
 | ||
|   
 | ||
|   return ZERO;
 | ||
| }
 | ||
| 
 | ||
| void TDistinta_tree::evaluate(TDistinta_expr& e)
 | ||
| {
 | ||
|   for (int v = e.numvar()-1; v >= 0; v--)
 | ||
|   {
 | ||
|     TString name = e.varname(v);
 | ||
|     name.upper();
 | ||
|     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();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TDistinta_tree::push_vars()
 | ||
| {
 | ||
|   bool ok = TRUE;
 | ||
|   TAssoc_array* vars = new TAssoc_array;
 | ||
|   _stack.push(vars);
 | ||
| 
 | ||
|   const char tipo = curr_type();
 | ||
|   if (tipo == 'G')
 | ||
|     vars->add("_GHOST", real(1.0));
 | ||
| 
 | ||
|   TCodice_articolo art; curr_code(art);
 | ||
|   const TString& memo_field = find_head(art).get("PARAMETRI");
 | ||
|   if (!memo_field.blank())
 | ||
|   {
 | ||
|     TString var, 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; var.trim();
 | ||
|         expr = equal + 1;
 | ||
|         const TTypeexp exprtype = get_var_type(var);
 | ||
|         if (e.set(expr, exprtype))
 | ||
|         {
 | ||
|           evaluate(e);
 | ||
|           if (exprtype == _numexpr)
 | ||
|             vars->add(var, e.as_real());
 | ||
|           else
 | ||
|             vars->add(var, e.as_string());
 | ||
|         } else {
 | ||
|           error_box("Errore nella distinta '%s'",(const char *)art);
 | ||
|           ok = FALSE;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| struct TExplosion_params
 | ||
| {
 | ||
|   int       _root_depth;
 | ||
|   TArray*   _array;
 | ||
|   TString16 _filter;
 | ||
|   int       _raggruppa;
 | ||
|   int       _max_depth;
 | ||
|   int       _sort_key;
 | ||
|   bool      _materiali_base;
 | ||
|   bool      _ignore_ghost;
 | ||
|   bool      _stop_prod;
 | ||
| };
 | ||
| 
 | ||
| static bool explode_callback(TTree& node, void* jolly, word when)
 | ||
| {
 | ||
|   if (when == SCAN_PRE_ORDER)
 | ||
|   {
 | ||
|     const TExplosion_params& ep = *(const TExplosion_params*)jolly;
 | ||
| 
 | ||
|     TDistinta_tree& tree = (TDistinta_tree&)node;
 | ||
|     
 | ||
|     if (tree.is_root())
 | ||
|       return FALSE;         // Don't explode root
 | ||
| 
 | ||
|     const bool is_leaf = tree.is_leaf();
 | ||
|     TCodice_articolo art; tree.curr_code(art);
 | ||
|     const char type = tree.curr_type();
 | ||
|     static long stop_depth = -1;
 | ||
|     const int curr_depth = tree.curr_depth();
 | ||
| 
 | ||
|     if (ep._materiali_base)
 | ||
|     {                                        
 | ||
|       bool is_prod = FALSE;
 | ||
|       if (ep._stop_prod)
 | ||
|       {
 | ||
|         if (stop_depth > 0)
 | ||
|         {
 | ||
|           if (curr_depth > stop_depth)
 | ||
|             return FALSE;
 | ||
|           else
 | ||
|             stop_depth = -1;
 | ||
|         }
 | ||
|         if (stop_depth < 0)
 | ||
|         {
 | ||
|           is_prod = (type == 'A') && cache().get(LF_ANAMAG, art).get_bool(ANAMAG_ARTPROD);
 | ||
|           if (is_prod)
 | ||
|             stop_depth = curr_depth ;
 | ||
|         }
 | ||
|       }
 | ||
|                 
 | ||
|       if (!is_leaf && !is_prod)
 | ||
|       {      
 | ||
|         if (ep._max_depth <= 0 || curr_depth < ep._max_depth)
 | ||
|           return FALSE;         // Please, leaves only
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     if (is_leaf)
 | ||
|     {
 | ||
|       if (art == "???")
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     if (ep._sort_key > 0)  // Se sort_key <= 0 accetta tutto comunque
 | ||
|     {
 | ||
|       const long sk = tree.curr_sort();
 | ||
|       if (sk <= 0)
 | ||
|         return FALSE;      // Non fa parte dell'ordinamento
 | ||
|     }
 | ||
| 
 | ||
|     if (ep._filter.find(type) < 0)
 | ||
|       return FALSE;
 | ||
|     
 | ||
|     TRiga_esplosione* er = new TRiga_esplosione(tree, ep._filter.find('G') >= 0);
 | ||
|     er->set_mat_base(is_leaf);
 | ||
|     ep._array->add(er);
 | ||
|   }
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| int TDistinta_tree::raggruppa(TArray& boom, TExplosion_grouping mode) const
 | ||
| {
 | ||
|   for (int i = 0; i < boom.items(); i++)
 | ||
|   {
 | ||
|     TRiga_esplosione& qta1 = (TRiga_esplosione&)boom[i];
 | ||
|   
 | ||
|     if (mode == RAGGR_EXP_UMBASE || mode == RAGGR_EXP_BASE)
 | ||
|       qta1.convert2umbase(); else
 | ||
|     if (mode == RAGGR_EXP_UMDIST || mode == RAGGR_EXP_DIST)
 | ||
|       qta1.convert2umdist();
 | ||
| 
 | ||
|     if (mode == RAGGR_EXP_UMBASE || 
 | ||
|         mode == RAGGR_EXP_UMDIST || 
 | ||
|         mode == RAGGR_EXP_EACHUM)
 | ||
|     {
 | ||
|       for (int j = boom.items()-1; j > i; j--)
 | ||
|       {
 | ||
|         TRiga_esplosione& qta2 = (TRiga_esplosione&)boom[j];
 | ||
|         if (qta1.articolo() != qta2.articolo())
 | ||
|           continue;
 | ||
|      
 | ||
|         if (mode == RAGGR_EXP_EACHUM && qta1.um() != qta2.um())
 | ||
|           continue;
 | ||
| 
 | ||
|         qta1 += qta2;  
 | ||
|         boom.destroy(j, TRUE);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return boom.items();
 | ||
| }
 | ||
| 
 | ||
| int TDistinta_tree::explode(TArray& boom, 
 | ||
|                             bool mb, TExplosion_grouping gr, int md, 
 | ||
|                             const char* filter, int sk, bool sp)
 | ||
| {
 | ||
|   const int  old_sk = get_sort_key();
 | ||
|   const int  old_md = get_max_depth();
 | ||
|   const bool old_iv = get_ignore_ghost();
 | ||
|   const bool old_sp = get_stop_prod();
 | ||
| 
 | ||
|   TExplosion_params ep;
 | ||
|   ep._root_depth = curr_depth();
 | ||
|   ep._array = &boom;
 | ||
|   ep._materiali_base = mb;
 | ||
|   ep._raggruppa = gr;
 | ||
|   ep._max_depth = md;
 | ||
|   ep._sort_key = sk;
 | ||
|   ep._filter = filter; 
 | ||
|   if (ep._filter.empty())
 | ||
|     ep._filter = "ALV";
 | ||
|   ep._ignore_ghost = ep._filter.find('G') < 0; 
 | ||
|   ep._stop_prod = sp; 
 | ||
| 
 | ||
|   set_sort_key (abs(ep._sort_key));    // Sort key puo' essere negativa per includere anche quelli senza!
 | ||
|   set_max_depth(ep._max_depth);
 | ||
|   set_ignore_ghost(ep._ignore_ghost);
 | ||
|   set_stop_prod(ep._stop_prod);
 | ||
| 
 | ||
|   boom.destroy();   // Non si sa mai!
 | ||
|   scan_depth_first(explode_callback, &ep);
 | ||
| 
 | ||
|   set_sort_key(old_sk);
 | ||
|   set_max_depth(old_md);
 | ||
|   set_ignore_ghost(old_iv);
 | ||
|   set_stop_prod(old_sp);
 | ||
| 
 | ||
|   if (gr != RAGGR_EXP_NONE)
 | ||
|     raggruppa(boom, gr);
 | ||
| 
 | ||
|   return boom.items();
 | ||
| }
 | ||
| 
 | ||
| TCodgiac_livelli &TDistinta_tree::livgiac()  const
 | ||
| {
 | ||
|   if (_livgiac==NULL)
 | ||
|     ((TDistinta_tree *)this)->_livgiac = new TCodgiac_livelli();
 | ||
|   return *_livgiac;
 | ||
| }
 | ||
| TDistinta_tree::TDistinta_tree() 
 | ||
|               : _sort(0), _max_depth(0), _ignore_ghost(FALSE),
 | ||
|                 _livgiac(NULL),_qta_on_descr(FALSE),_descr_sep('-'),
 | ||
| 								_tmp(80, TREE_SEPARATOR)
 | ||
| {
 | ||
|   memset(_livgiac_on_descr, 0, sizeof(_livgiac_on_descr));
 | ||
| }
 | ||
| 
 | ||
| TDistinta_tree::~TDistinta_tree()
 | ||
| {
 | ||
|   if (_livgiac)
 | ||
|     delete _livgiac;
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione *TDistinta_tree::first_critical_labor(TArray & labors, TExplosion_grouping raggum)
 | ||
| {
 | ||
|   TRiga_esplosione *l=first_labor(labors, raggum);
 | ||
|   while (l)
 | ||
|   {
 | ||
|     TLavorazione labor(l->articolo());
 | ||
|     for (int lnp=0 ; lnp < labor.linee();lnp++)
 | ||
|     { 
 | ||
|       if (!cache().get("LNP",labor.cod_linea(lnp)).get_bool("B9"))
 | ||
|         // escluso dal CRP
 | ||
|         return l;
 | ||
|     }
 | ||
|     l=(TRiga_esplosione *)labors.succ_item();
 | ||
|   }
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione *TDistinta_tree::next_critical_labor(TArray & labors)
 | ||
| {
 | ||
|   return next_labor(labors);
 | ||
| }
 | ||
|   
 | ||
| 
 | ||
| TRiga_esplosione *TDistinta_tree::first_labor(TArray & labors, TExplosion_grouping raggum)
 | ||
| {
 | ||
|   explode(labors,FALSE,raggum, 1,"L");
 | ||
|   TRiga_esplosione *l=(TRiga_esplosione *)labors.first_item();
 | ||
|   return l;
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione *TDistinta_tree::next_labor(TArray & labors)
 | ||
| {
 | ||
|   if (labors.items()==0)
 | ||
|     return NULL;
 | ||
|   TRiga_esplosione *l=(TRiga_esplosione *)labors.succ_item();
 | ||
|   return l;
 | ||
| }
 | ||
| 
 | ||
| TLavorazione *TDistinta_tree::find_labor(TRiga_esplosione *l)
 | ||
| {
 | ||
|   static TLavorazione *curr_labor=NULL;
 | ||
|   if (l)
 | ||
|   {
 | ||
|     if (curr_labor==NULL) curr_labor=new TLavorazione();
 | ||
|     curr_labor->put("CODTAB",l->articolo());
 | ||
|     TTable tablav("LAV");
 | ||
|     curr_labor->read(tablav);
 | ||
|     return curr_labor;
 | ||
|   }
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TRiga_esplosione
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| void TRiga_esplosione::init(const TDistinta_tree& tree, bool vis_ghost)
 | ||
| {
 | ||
|   TCodice_articolo art; tree.curr_code(art); art.trim();
 | ||
|   TCodice_um um; tree.curr_um(um);
 | ||
|   real val = tree.curr_qta();
 | ||
|   set(art, um, val);
 | ||
|   _last_qta = tree.last_qta(vis_ghost); // Puo' sempre servire anche questa
 | ||
|   tree.curr_giaclev(_giac);
 | ||
|   _tipo = tree.curr_type();
 | ||
|   _sort = tree.curr_sort();
 | ||
|   _mat_base = FALSE;
 | ||
|   // set path and code
 | ||
|   tree.curr_id(_path);  // path
 | ||
| }
 | ||
| 
 | ||
| const char * TRiga_esplosione::father(const char * types)
 | ||
| {
 | ||
|   TString & _tmp_path = get_tmp_string();
 | ||
| 
 | ||
|   _tmp_path = _path;
 | ||
|   while (TRUE)
 | ||
|   {
 | ||
|     const int index = _tmp_path.rfind('|');
 | ||
|     if (index == -1)
 | ||
|       return "";
 | ||
|     else
 | ||
|     {
 | ||
|       _tmp_path.cut(index);
 | ||
|       char type =  _tmp_path[index-1];
 | ||
|       if (types == NULL || strchr(types, type))
 | ||
|         break;
 | ||
|     }
 | ||
|   }
 | ||
|   return _tmp_path;
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione::TRiga_esplosione(const TDistinta_tree& tree, bool vis_ghost)
 | ||
| {
 | ||
|   init(tree, vis_ghost);
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione::TRiga_esplosione(const TRiga_esplosione& re)
 | ||
|                 : TQuantita(re)
 | ||
| {
 | ||
|   _giac = re._giac;
 | ||
|   _tipo = re._tipo;
 | ||
|   _path = re._path;
 | ||
|   _sort = re._sort;
 | ||
|   _mat_base = re._mat_base;
 | ||
|   _last_qta = re._last_qta;
 | ||
| }
 | ||
| 
 | ||
| TRiga_esplosione::TRiga_esplosione()
 | ||
|                 : TQuantita()
 | ||
| {
 | ||
|   _tipo = '\0';
 | ||
|   _sort = 0L;
 | ||
|   _mat_base = FALSE;
 | ||
| }
 | ||
| 
 | ||
| TUm_tempo::TUm_tempo(char c)
 | ||
| {
 | ||
|   switch (c)
 | ||
|   {
 | ||
|     case 'M': // minutes
 | ||
|       _ore=1.0/60.0;
 | ||
|       break;
 | ||
|     case 'S': // seconds
 | ||
|       _ore=1.0/3600.0;
 | ||
|       break;
 | ||
|     case 'H': // hours
 | ||
|     default:
 | ||
|       _ore=1.0;
 | ||
|       break;
 | ||
|   }
 | ||
| }
 | ||
| 
 |