#include <applicat.h>
#include <mask.h>
#include <printer.h>
#include <progind.h>
#include <relation.h>
#include <urldefid.h>
#include <utility.h>

#include "at3.h"

// nomi campi maschera
#include "at3600a.h"
          
// nomi dei campi
#include "soggetti.h"
#include "donaz.h"
#include "atstatd.h"
#include "sezioni.h"

// classe per la definizione di una riga di statistica
class TRigaGruppo : public TObject
{                             
	TString16			_gruppo, _rh;
	TArray				_valori;

protected:
	const TRigaGruppo& copy(const TRigaGruppo& riga);
public:
	const TString16 gruppo() const { return _gruppo; }
	const TString16 rh() const { return _rh; } 
	TObject* dup() const { return new TRigaGruppo(*this); }
	const TRigaGruppo& operator = (const TRigaGruppo& riga);
	const real& operator [] (int colonna) const;
	void aggiorna_valore(int colonna, const real& numero) ;
	void azzera_valori();
	// costruttore
	TRigaGruppo(TString16 gruppo, TString16 rh) {_gruppo = gruppo; _rh = rh;}
	// costruttore di copia
	TRigaGruppo(const TRigaGruppo& riga)  { copy(riga); }
	virtual ~TRigaGruppo() {};
};

const TRigaGruppo& TRigaGruppo::copy(const TRigaGruppo& riga)
{
	_gruppo = riga._gruppo;
	_rh = riga._rh;
	_valori = riga._valori;
	return (*this);
}

const TRigaGruppo& TRigaGruppo::operator = (const TRigaGruppo& riga)
{
	copy(riga);
	return (*this);
}

const real& TRigaGruppo::operator [] (int colonna) const
{
	real* valore = (real*)_valori.objptr(colonna);
	if (valore == NULL)
		return ZERO;
	else
		return *valore;		
}

void TRigaGruppo::aggiorna_valore(int colonna, const real& numero)
{
	real* valore = (real*)_valori.objptr(colonna);
	if (valore == NULL)
		_valori.add(new real(numero), colonna);
	else
		*valore += numero;
}
  
void TRigaGruppo::azzera_valori()
{
	_valori.destroy();
}

class TStatDonGrRh : public TApplication
{
	TMask*					_msk;
	TRelation*   		_rel;
	TCursor*				_cur;
	TLocalisamfile* _sezioni;
	TLocalisamfile* _soggetti;
	TLocalisamfile* _donaz;
	TLocalisamfile* _atstatd;
	TDate						_dataini, _datafin;
	TString16 			_tipodon1, _tipodon2, _tipodon3, _tipodon4, _tipodon5;
	TAssoc_array*		_colonne;
	TArray					_righe;	// array per riepilogo donazioni
	TString16				_sezini, _sotini, _sezfin, _sotfin;
	TAssoc_array*		_asoggetti;
	bool						_solotot, _pergruppo;
	int							_sezionistampate;

protected:
	virtual bool create();
	virtual bool destroy();
  virtual bool menu(MENU_TAG m);
	virtual TMask& get_mask() { return *_msk; }
	virtual TRelation* get_relation() const { return _rel; }
	int data2row(const TString16 gruppo, const TString16 rh);
	bool riepilogo();
	bool stampa();
	bool crea_colonne();
	bool crea_righe();
	void azzera_righe();
	void stampa_sezione(TString16 codsez, TString16 codsot);
	void crea_intestazione();
public:
	TStatDonGrRh() {}
	
};

HIDDEN inline TStatDonGrRh& app() { return (TStatDonGrRh&) main_app(); }

int TStatDonGrRh::data2row(const TString16 gruppo, const TString16 rh)
{              
	int igruppo = 0;
	int irh = 0;
	if (gruppo == "0")
		igruppo = 1;
	if (gruppo == "A")
		igruppo = 2;
	if (gruppo == "A1")
		igruppo = 3;
	if (gruppo == "A2")
		igruppo = 4;
	if (gruppo == "A1B")
		igruppo = 5;
	if (gruppo == "A2B")
		igruppo = 6;
	if (gruppo == "AB")
		igruppo = 7;
	if (gruppo == "B")
		igruppo = 8;
	if (rh == "POS")
		irh = 1;
	if (rh == "NEG")
		irh = 2;
	return igruppo*10 + irh;
}

bool TStatDonGrRh::crea_colonne()
{                   
	_colonne->destroy();
	real contatore(ZERO);
	real* oggettodm = new real(contatore);                                
	const char* indicedm = "DM"; // donazioni maschi
	_colonne->add(indicedm,(TObject*)oggettodm);
	const char* indicedf = "DF"; // donazioni femmine
	contatore = contatore+1;
	real* oggettodf = new real(contatore);                                	
	_colonne->add(indicedf,(TObject*)oggettodf);
	const char* indicesm = "SM"; // soggetti maschi
	contatore = contatore+1;
	real* oggettosm = new real(contatore);                                	
	_colonne->add(indicesm,(TObject*)oggettosm);
	const char* indicesf = "SF"; // soggetti femmine
	contatore = contatore+1;
	real* oggettosf = new real(contatore);                                	
	_colonne->add(indicesf,(TObject*)oggettosf);
	return TRUE;
}

bool TStatDonGrRh::crea_righe()
{                     
	TString16 gruppo, rh;
	for (int igruppo=0;igruppo<=8;igruppo++)
	{		
		switch (igruppo)
		{  
			case 0 : gruppo = "";   break;
			case 1 : gruppo = "0";   break;
			case 2 : gruppo = "A";   break;
			case 3 : gruppo = "A1";  break;		
			case 4 : gruppo = "A2"; break;
			case 5 : gruppo = "A1B";  break;
			case 6 : gruppo = "A2B"; break;						
			case 7 : gruppo = "AB";  break;		
			case 8 : gruppo = "B";   break;		
		}            
		for (int irh=0;irh <=2;irh++)
		{
			switch (irh)
			{  
				case 1  : rh = "POS"; break;
				case 2  : rh = "NEG"; break;
				default : rh = "   "; break;		
			}            
			_righe.add(new TRigaGruppo(gruppo, rh), data2row(gruppo, rh));
		}
	}		
	return _righe.items()>0;	
}

bool TStatDonGrRh::create()
{
	TApplication::create();
	_msk = new TMask("at3600a");
	_rel = new TRelation(LF_DONAZ);
  _rel->add(LF_SOGGETTI, "CODICE==CODICE");
  _soggetti = new TLocalisamfile(LF_SOGGETTI);
	_donaz = new TLocalisamfile(LF_DONAZ);
	_atstatd = new TLocalisamfile(LF_ATSTATD);
	_sezioni = new TLocalisamfile(LF_SEZIONI);
	_colonne = new TAssoc_array();
	_asoggetti = new TAssoc_array();
  dispatch_e_menu(BAR_ITEM_ID(1));
	return TRUE;
}	

bool TStatDonGrRh::destroy()	
{
	delete _asoggetti;
	delete _colonne;
	delete _sezioni;
	delete _atstatd;
	delete _donaz;   
	delete _soggetti;
	delete _rel;
	delete _msk;
	return TApplication::destroy();
}

bool TStatDonGrRh::menu(MENU_TAG m)
{ 
	TMask& msk = get_mask();
	KEY tasto;
 	tasto = msk.run();
 	if (tasto == K_ENTER)
 	{
		_dataini = msk.get(F_DATAINI); 		
		_datafin = msk.get(F_DATAFIN);
		_tipodon1 = msk.get(F_TIPODON1); 		
		_tipodon2 = msk.get(F_TIPODON2); 		
		_tipodon3 = msk.get(F_TIPODON3); 		
		_tipodon4 = msk.get(F_TIPODON4); 		
		_tipodon5 = msk.get(F_TIPODON5); 		
		_pergruppo = msk.get_bool(F_PERGRUPPO); 		
		_solotot = msk.get_bool(F_SOLOTOT); 		
 		_sezini =  msk.get(F_SEZINI);
 		_sotini =  msk.get(F_SOTINI);
 		_sezfin =  msk.get(F_SEZFIN);
 		_sotfin =  msk.get(F_SOTFIN);
		if (riepilogo())
			stampa();
 	}
 	return FALSE;
}  

void TStatDonGrRh::crea_intestazione()
{ 
	TPrintrow row;
	TString256 sep;
	sep = "STATISTICA DONAZIONI/DONATORI PER SESSO, GRUPPO E RH";
	sep.center_just(80);
	row.put(sep);
	printer().setheaderline(2, row);		
	sep = "";
	if (_tipodon1.not_empty())
	{
		sep << "Tipo ";
		sep << _tipodon1;
	}	
	if (_tipodon2.not_empty())
		sep << ' ' << _tipodon2;
	if (_tipodon3.not_empty())
		sep << ' ' << _tipodon3;
	if (_tipodon4.not_empty())
		sep << ' ' << _tipodon4;
	if (_tipodon5.not_empty())
		sep << ' ' << _tipodon5;
	
	if (_dataini.ok())
	{
		sep << " dal ";
		sep << _dataini.string();
	}
	if (_datafin.ok())
	{
		sep << " al ";
		sep << _datafin.string();
	}
	sep.center_just(80);
	row.reset();
	row.put(sep);
  row.put("@>", 1);
  row.put("Pag. @#", 70);
  printer().setheaderline(3, row);
  row.reset();
  printer().setheaderline(4, row);	  
  sep = "";
  sep << "Gruppo/Rh             Donazioni                 Donatori             Donazioni/Donatori";
	row.put(sep);
	printer().setheaderline(5, row);  
  sep = "";
  sep << "               Maschi  Femmine Totali    Maschi  Femmine Totali    Maschi  Femmine Totali";
	row.reset();
	row.put(sep);
	printer().setheaderline(6, row);  
	sep = "";
	sep.fill('-',80);
	row.reset();
	row.put(sep);
	printer().setheaderline(7, row);
}

bool TStatDonGrRh::stampa()
{ 
	if (printer().open())
	{
		_sezionistampate = 0;
		crea_intestazione();
		TRelation* relstat = new TRelation(LF_ATSTATD);
		TCursor* curstat = new TCursor(relstat, "", 3);
		TString16 oldsez = "**";
		TString16 oldsot = "**";
		double numero,numsog,numero2,numsog2;
		TString16 actsez, actsot;
		TString16 gruppo, rh;
		long last = curstat->items();
	  for ( *curstat=0; curstat->pos() < last; ++(*curstat) )
	  {
			actsez = curstat->curr().get(ATS_CODSEZ);																						  	
			actsot = curstat->curr().get(ATS_CODSOT);		
			gruppo = curstat->curr().get(ATS_GRUPPO);		
			rh = curstat->curr().get(ATS_RH);		
			numero = (double)curstat->curr().get_int(ATS_NUMERO);		
			numsog = (double)curstat->curr().get_int(ATS_NUMPRIME);		
			numero2 = (double)curstat->curr().get_int(ATS_NUMERO2);		
			numsog2 = (double)curstat->curr().get_int(ATS_NUMPRIME2);		
			
			if (actsez != oldsez || actsot != oldsot)
			{                 
				if (oldsez != "**" && oldsot != "**")
				{
					stampa_sezione(oldsez,oldsot);
					azzera_righe();
				}
				oldsez = actsez;
				oldsot = actsot;
			}				
			TRigaGruppo& riga = (TRigaGruppo&)_righe[data2row(gruppo,rh)];
			const char* indicedm = "DM";
			real& colonnadm = (real&)_colonne->find(indicedm);
			real n = numero;
			riga.aggiorna_valore((int) colonnadm.integer(),n);
			const char* indicedf = "DF";
			real& colonnadf = (real&)_colonne->find(indicedf);
			n = numero2;
			riga.aggiorna_valore((int) colonnadf.integer(),n);
			const char* indicesm = "SM";
			real& colonnasm = (real&)_colonne->find(indicesm);
			n = numsog;
			riga.aggiorna_valore((int) colonnasm.integer(),n);
			const char* indicesf = "SF";
			real& colonnasf = (real&)_colonne->find(indicesf);
			n = numsog2;
			riga.aggiorna_valore((int) colonnasf.integer(),n);
		}                             
		if (oldsez != "**" && oldsot != "**")
			stampa_sezione(oldsez,oldsot);
		delete curstat;
		delete relstat;
		printer().close();
		return TRUE;
	}
	else
		return FALSE;		
}

void TStatDonGrRh::azzera_righe()
{
	TString16 gruppo, rh;
	for (int igruppo=0;igruppo<=8;igruppo++)
	{		
		switch (igruppo)
		{  
			case 0 : gruppo = "";   break;
			case 1 : gruppo = "0";   break;
			case 2 : gruppo = "A";   break;
			case 3 : gruppo = "A1";  break;		
			case 4 : gruppo = "A2"; break;
			case 5 : gruppo = "A1B";  break;
			case 6 : gruppo = "A2B"; break;						
			case 7 : gruppo = "AB";  break;		
			case 8 : gruppo = "B";   break;		
		}            
		for (int irh=0;irh <=2;irh++)
		{
			switch (irh)
			{  
				case 1  : rh = "POS"; break;
				case 2  : rh = "NEG"; break;
				default : rh = "   "; break;		
			}            
			TRigaGruppo& riga = (TRigaGruppo&)_righe[data2row(gruppo,rh)];
			riga.azzera_valori();
		}
	}		
}



void TStatDonGrRh::stampa_sezione(TString16 codsez, TString16 codsot)
{ 
	TPrintrow row;
	TString256 rigastampa;
	if (codsez == "ZZ" && codsot == "ZZ")
	{
		if (_sezionistampate != 1)
		{
			rigastampa = "";
			rigastampa << "RIEPILOGO TOTALE SEZIONI DA " << _sezini << '/' << _sotini << " A " << _sezfin << '/' << _sotfin;
			if (_pergruppo)
				rigastampa << " - SOLO GRUPPI AZIENDALI";
		}	
	}	
	else
	{
		_sezionistampate++;
		if (_pergruppo)
		{
			rigastampa = "Gruppo aziendale ";
			rigastampa << codsez;
			rigastampa << codsot;
		}
		else
		{		
			rigastampa = "Sezione: ";
			rigastampa << codsez;
			if (codsot.not_empty())
			{
				rigastampa << "/";
				rigastampa << codsot;
			}		
			rigastampa << " ";
			TLocalisamfile sezioni(LF_SEZIONI);
			sezioni.setkey(1);
			sezioni.zero();
			sezioni.put(SEZ_CODSEZ,codsez);
			sezioni.put(SEZ_CODSOT,codsot);	
			if (sezioni.read() == NOERR)
			{
				TString80 den = sezioni.get(SEZ_DENSEZ);
				rigastampa << den;
				den = sezioni.get(SEZ_DENSOT);
				if (den.not_empty())
				{
					rigastampa << "/";
					rigastampa << den;
				}
			}
		}	
	}		
	if ((codsez == "ZZ" && codsot == "ZZ" && _sezionistampate != 1) || (codsez != "ZZ"))
	{
		rigastampa.center_just(80);
		row.put(rigastampa);
	  printer().setheaderline(1, row);
	  
	  TRigaGruppo rigatotali("   ","   ");
		TString16 valore;
		TString16 gruppo, rh;
		real totsoggetti = ZERO;
		real totdonazioni = ZERO;
		for (int igruppo=0;igruppo<=8;igruppo++)
		{		
			switch (igruppo)
			{  
				case 0 : gruppo = "";   break;
				case 1 : gruppo = "0";   break;
				case 2 : gruppo = "A";   break;
				case 3 : gruppo = "A1";  break;		
				case 4 : gruppo = "A2"; break;
				case 5 : gruppo = "A1B";  break;
				case 6 : gruppo = "A2B"; break;						
				case 7 : gruppo = "AB";  break;		
				case 8 : gruppo = "B";   break;		
			}            
			for (int irh=0;irh <=2;irh++)
			{
				switch (irh)
				{  
					case 1  : rh = "POS"; break;
					case 2  : rh = "NEG"; break;
					default : rh = "   "; break;		
				}            
				totsoggetti = ZERO;
				totdonazioni = ZERO;
				TRigaGruppo& riga = (TRigaGruppo&)_righe[data2row(gruppo,rh)];
				row.reset();
				rigastampa = "";
				rigastampa << gruppo;
				rigastampa << " ";
				rigastampa << rh;
				int pos = 12;
				const char* indicedm = "DM";
				real& colonnadm = (real&)_colonne->find(indicedm);
				rigatotali.aggiorna_valore((int) colonnadm.integer(),riga[(int) colonnadm.integer()]);
				totdonazioni+=riga[(int) colonnadm.integer()];
				valore = "";
				//valore.format("%8d",riga[(int) colonnadm.integer()].integer());
				valore.format("%8s",riga[(int) colonnadm.integer()].string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+8;
				const char* indicedf = "DF";
				real& colonnadf = (real&)_colonne->find(indicedf);
				rigatotali.aggiorna_valore((int) colonnadf.integer(),riga[(int) colonnadf.integer()]);
				totdonazioni+=riga[(int) colonnadf.integer()];
				valore = "";
				//valore.format("%8d",riga[(int) colonnadf.integer()].integer());
				valore.format("%8s",riga[(int) colonnadf.integer()].string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+8;
				// stampo totale donazioni
				valore = "";
				//valore.format("%8d",totdonazioni.integer());
				valore.format("%8s",totdonazioni.string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+10;
				
				const char* indicesm = "SM";
				real& colonnasm = (real&)_colonne->find(indicesm);
				totsoggetti+=riga[(int) colonnasm.integer()];
				rigatotali.aggiorna_valore((int) colonnasm.integer(),riga[(int) colonnasm.integer()]);
				valore = "";
				//valore.format("%8d",riga[(int) colonnasm.integer()].integer());
				valore.format("%8s",riga[(int) colonnasm.integer()].string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+8;
				const char* indicesf = "SF";
				real& colonnasf = (real&)_colonne->find(indicesf);
				totsoggetti+=riga[(int) colonnasf.integer()];
				rigatotali.aggiorna_valore((int) colonnasf.integer(),riga[(int) colonnasf.integer()]);
				valore = "";
				//valore.format("%8d",riga[(int) colonnasf.integer()].integer());
				valore.format("%8s",riga[(int) colonnasf.integer()].string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+8;
				// stampo totale donatori
				valore = "";
				//valore.format("%8d",totsoggetti.integer());
				valore.format("%8s",totsoggetti.string());
				rigastampa.overwrite((const char*)valore, pos);
				pos = pos+14;
				
				// percentuale
				if (totsoggetti.integer()!=0)
				{
					// maschi
					//if (riga[(int) colonnasm.integer()].integer() != 0)
					if (riga[(int) colonnasm.integer()] != ZERO)
					{
						valore = "";
						real perc = riga[(int) colonnadm.integer()] / riga[(int) colonnasm.integer()];
						valore << perc.string(3,3);
						rigastampa.overwrite((const char*)valore, pos);
					}
					pos = pos+8;
					// femmine
					//if (riga[(int) colonnasf.integer()].integer() != 0)				
					if (riga[(int) colonnasf.integer()] != ZERO)				
					{
						valore = "";
						real perc = riga[(int) colonnadf.integer()] / riga[(int) colonnasf.integer()];
						valore << perc.string(3,3);
						rigastampa.overwrite((const char*)valore, pos);
					}					
					pos = pos+8;
					// totale
					valore = "";
					real perc = totdonazioni / totsoggetti;
					valore << perc.string(3,3);
					rigastampa.overwrite((const char*)valore, pos);
					pos = pos+10;
				}
				
				if (totdonazioni!=0)
				{
					row.put((const char*) rigastampa);
					printer().print(row);			
				}				
			}
		}		
		// stampa totali per sezione
		rigastampa = "";
		rigastampa.fill('-',80);
		row.reset();
		row.put(rigastampa);
		printer().print(row);
		row.reset();
		rigastampa = "";
		rigastampa = "Totale";
	
		totsoggetti = ZERO;	
		totdonazioni = ZERO;
		int pos = 12;
		const char* indicedm = "DM";
		real& colonnadm = (real&)_colonne->find(indicedm);
		totdonazioni+=rigatotali[(int) colonnadm.integer()];
		valore = "";
		//valore.format("%8d",rigatotali[(int) colonnadm.integer()].integer());
		valore.format("%8s",rigatotali[(int) colonnadm.integer()].string());
		rigastampa.overwrite((const char*)valore, pos);
		pos = pos+8;
		const char* indicedf = "DF";
		real& colonnadf = (real&)_colonne->find(indicedf);
		totdonazioni+=rigatotali[(int) colonnadf.integer()];
		valore = "";
		//valore.format("%8d",rigatotali[(int) colonnadf.integer()].integer());
		valore.format("%8s",rigatotali[(int) colonnadf.integer()].string());
		rigastampa.overwrite((const char*)valore, pos);
		pos = pos+8;
		// stampo totale donazioni
		valore = "";
		//valore.format("%8d",totdonazioni.integer());
		valore.format("%8s",totdonazioni.string());
		rigastampa.overwrite((const char*)valore, pos);
		pos = pos+10;
		const char* indicesm = "SM";
		real& colonnasm = (real&)_colonne->find(indicesm);
		totsoggetti+=rigatotali[(int) colonnasm.integer()];
		valore = "";
		//valore.format("%8d",rigatotali[(int) colonnasm.integer()].integer());
		valore.format("%8s",rigatotali[(int) colonnasm.integer()].string());
		rigastampa.overwrite((const char*)valore, pos);
		pos = pos+8;
		const char* indicesf = "SF";
		real& colonnasf = (real&)_colonne->find(indicesf);
		totsoggetti+=rigatotali[(int) colonnasf.integer()];
		valore = "";
		//valore.format("%8d",rigatotali[(int) colonnasf.integer()].integer());
		valore.format("%8s",rigatotali[(int) colonnasf.integer()].string());
		rigastampa.overwrite((const char*)valore, pos);
		pos = pos+8;
		// stampo totale donatori
		valore = "";
		//valore.format("%8d",totsoggetti.integer());
		valore.format("%8s",totsoggetti.string());
		rigastampa.overwrite((const char*)valore, pos);
	
		pos = pos+14;
		
		// percentuale
		//if (totsoggetti.integer()!=0)
		if (totsoggetti!=ZERO)
		{
			// maschi
			//if (rigatotali[(int) colonnasm.integer()].integer() != 0)
			if (rigatotali[(int) colonnasm.integer()] != ZERO)
			{
				valore = "";
				real perc = rigatotali[(int) colonnadm.integer()] / rigatotali[(int) colonnasm.integer()];
				valore << perc.string(3,3);
				rigastampa.overwrite((const char*)valore, pos);
			}
			pos = pos+8;
			// femmine
			//if (rigatotali[(int) colonnasf.integer()].integer() != 0)				
			if (rigatotali[(int) colonnasf.integer()] != ZERO)				
			{
				valore = "";
				real perc = rigatotali[(int) colonnadf.integer()] / rigatotali[(int) colonnasf.integer()];
				valore << perc.string(3,3);
				rigastampa.overwrite((const char*)valore, pos);
			}					
			pos = pos+8;
			// totale
			valore = "";
			real perc = totdonazioni / totsoggetti;
			valore << perc.string(3,3);
			rigastampa.overwrite((const char*)valore, pos);
			pos = pos+10;
		}
		row.put((const char*) rigastampa);
		printer().print(row);
		printer().formfeed();
	}		
}

bool TStatDonGrRh::riepilogo()
{            
	if (crea_colonne() && crea_righe())
	{     
		_asoggetti->destroy();
		// cancello i risultati della elaborazione precedente
		TLocalisamfile stat(LF_ATSTATD);
		for (stat.first(); !stat.eof(); stat.next())
			stat.remove();
		stat.setkey(3);			
		// filtro per data
		TRectype da(LF_DONAZ);
  	TRectype a (LF_DONAZ);
  	if (_dataini.ok())
			da.put(DON_DATADON, _dataini);
  	if (_datafin.ok())
			a.put(DON_DATADON, _datafin);
		_cur = new TCursor(_rel, "", 2, &da, &a);  
		TString256 filtro = "";
		// filtro per sezione/sottogruppo
	 	if (_sezini.not_empty())
	 	{
	 		if (_sotini.not_empty())
	 		{                    
	 			filtro << "(";
	 			filtro << format("(92->CODSEZ > \"%s\")",(const char*)_sezini);
	 			filtro << " || ";
	 			filtro << "(" << format("(92->CODSEZ == \"%s\")",(const char*)_sezini);
	 			filtro << " && ";
	 			filtro << format("(92->CODSOT >= \"%s\")",(const char*)_sotini);
	 			filtro << ")";
	 			filtro << ")";
	 		}
	 		else
		 			filtro << format("(92->CODSEZ >= \"%s\")",(const char*)_sezini);
	 	}
	 	if (_sezfin.not_empty())
	 	{
 			if (filtro.not_empty())
 				filtro << " && "; 
	 		if (_sotfin.not_empty())
	 		{          
	 			filtro << "(";
	 			filtro << format("(92->CODSEZ < \"%s\")",(const char*)_sezfin);
	 			filtro << " || ";
	 			filtro << "(" << format("(92->CODSEZ == \"%s\")",(const char*)_sezfin);
	 			filtro << " && ";
	 			filtro << format("(92->CODSOT <= \"%s\")",(const char*)_sotfin);
	 			filtro << ")";
	 			filtro << ")";
	 		}
	 		else
	 			filtro << format("(92->CODSEZ <= \"%s\")",(const char*)_sezfin);
		}
		// filtro per gruppi aziendali
		if (_pergruppo)
		{
 			if (filtro.not_empty())
 				filtro << " && "; 
	  	filtro << format("(90->GRUPPOAZIE != \"\")");
		}
		// filtro per tipo donazione
		TString256 filtrotd = "";
		if (_tipodon1.not_empty())
				filtrotd << format("(92->TIPODON==\"%s\")",(const char*)_tipodon1);
		if (_tipodon2.not_empty())
		{
			if (!filtrotd.empty())
				filtrotd << " || ";
			filtrotd << format("(92->TIPODON==\"%s\")",(const char*)_tipodon2);
    }
		if (_tipodon3.not_empty())
		{
			if (!filtrotd.empty())
				filtrotd << " || ";
			filtrotd << format("(92->TIPODON==\"%s\")",(const char*)_tipodon3);
    }
		if (_tipodon4.not_empty())
		{
			if (!filtrotd.empty())
				filtrotd << " || ";
			filtrotd << format("(92->TIPODON==\"%s\")",(const char*)_tipodon4);
    }
		if (_tipodon5.not_empty())
		{
			if (!filtrotd.empty())
				filtrotd << " || ";
			filtrotd << format("(92->TIPODON==\"%s\")",(const char*)_tipodon5);
    }                  
    if (!filtrotd.empty())
    {
 			if (!filtro.empty())
				filtro << " && ";
			filtro << '(' << filtrotd << ')';	
		}		
		_cur->setfilter((const char*) filtro, TRUE);
		TString16 codsez, codsot, tipodon, sesso, gruppoazie, gruppo, rh;
		TDate datadon;
		long numero;  
		bool esiste;
		TRectype& recdon = _cur->curr();
		TRectype& recsog = _cur->curr(LF_SOGGETTI);
  	long last = _cur->items();   
  	TProgind prg (last, "Elaborazione in corso... Prego attendere", FALSE, TRUE, 30);
  	for ( *_cur=0; _cur->pos() < last; ++(*_cur) )
  	{
    	prg.addstatus(1);   
    	const char* codice = recsog.get(SOG_CODICE);
			if (_asoggetti->is_key(codice))
				esiste = TRUE;
			else
			{				
	 			_asoggetti->add(codice);
	 			esiste = FALSE;
			}	 			
			if (_pergruppo)
			{
				gruppoazie = recsog.get(SOG_GRUPPOAZIE);
				codsez = gruppoazie.sub(0,2);
				codsot = gruppoazie.sub(2,4);
			}	
			else                                      
			{
				codsez = recdon.get(DON_CODSEZ);
				codsot = recdon.get(DON_CODSOT);
				if (codsez.empty())
				{
					codsez = recsog.get(SOG_CODSEZ);
					codsot = recsog.get(SOG_CODSOT);
				}                            
			}	
			sesso = recsog.get(SOG_SESSO);
			gruppo = recsog.get(SOG_GRUPPOAB0);
			if (gruppo == "A1" || gruppo == "A2")
				gruppo = "A";
			if (gruppo == "A1B" || gruppo == "A2B")
				gruppo = "AB";
			rh = recsog.get(SOG_RHANTID);
			if (!_solotot)
			{
				stat.zero();
				stat.put(ATS_CODSEZ, codsez);  	 
				stat.put(ATS_CODSOT, codsot);  	 
				stat.put(ATS_GRUPPO, gruppo);  	 
				stat.put(ATS_RH, rh);  	 
				if (stat.read() == NOERR)
				{
					if (sesso == "1")
						numero = stat.get_long(ATS_NUMERO);
					else
						numero = stat.get_long(ATS_NUMERO2);									
					numero++;
					if (sesso == "1")
						stat.put(ATS_NUMERO, numero);
					else					
						stat.put(ATS_NUMERO2, numero);
					if (!esiste)
					{
						if (sesso == "1")
							numero = stat.get_long(ATS_NUMPRIME);
						else					
							numero = stat.get_long(ATS_NUMPRIME2);
						numero++;
						if (sesso == "1")
							stat.put(ATS_NUMPRIME, numero);					
						else						
							stat.put(ATS_NUMPRIME2, numero);					
					}
					stat.rewrite();			
				}			
				else
				{
					stat.zero();
					stat.put(ATS_CODSEZ, codsez);  	 
					stat.put(ATS_CODSOT, codsot);  	 
					stat.put(ATS_GRUPPO, gruppo);  	 
					stat.put(ATS_RH, rh);  	 
					numero = 1;           
					if (sesso == "1")
					{
						stat.put(ATS_NUMERO, numero);
						stat.put(ATS_NUMPRIME, numero);
					}					
					else
					{
						stat.put(ATS_NUMERO2, numero);					
						stat.put(ATS_NUMPRIME2, numero);
					}					
					stat.write();
				}
			}	
			stat.zero();
			stat.put(ATS_CODSEZ, "ZZ");  	 
			stat.put(ATS_CODSOT, "ZZ");  	 
			stat.put(ATS_GRUPPO, gruppo);  	 
			stat.put(ATS_RH, rh);  	 
			if (stat.read() == NOERR)
			{                                    
				if (sesso == "1")
					numero = stat.get_long(ATS_NUMERO);
				else
					numero = stat.get_long(ATS_NUMERO2);									
				numero++;
				if (sesso == "1")
					stat.put(ATS_NUMERO, numero);
				else					
					stat.put(ATS_NUMERO2, numero);
				if (!esiste)
				{
					if (sesso == "1")
						numero = stat.get_long(ATS_NUMPRIME);
					else					
						numero = stat.get_long(ATS_NUMPRIME2);
					numero++;
					if (sesso == "1")
						stat.put(ATS_NUMPRIME, numero);					
					else						
						stat.put(ATS_NUMPRIME2, numero);					
				}
				int err = stat.rewrite();			
			}			
			else
			{
				stat.zero();
				stat.put(ATS_CODSEZ, "ZZ");  	 
				stat.put(ATS_CODSOT, "ZZ");  	 
				stat.put(ATS_GRUPPO, gruppo);  	 
				stat.put(ATS_RH, rh);  	 
				numero = 1;           
				if (sesso == "1")
				{
					stat.put(ATS_NUMERO, numero);
					stat.put(ATS_NUMPRIME, numero);
				}					
				else
				{
					stat.put(ATS_NUMERO2, numero);					
					stat.put(ATS_NUMPRIME2, numero);
				}					
				int err = stat.write();
			}
		}	
		return (stat.eod() > 0);
	}		
	else
		return FALSE;	
}         

int at3600(int argc, char* argv[])
{
	TStatDonGrRh a;
	a.run(argc, argv, "Statistica donazioni/donatori");
	return 0;
}