/* *************************************************************

        Final Project                                 MMU 1996

        ######################################################
        #                                                    #
        #               A Modular Neural Network             #   
        #                                                    #
        #              A Fast File Access Class              #   
        #                                                    #
        ######################################################

        Albrecht Schmidt                              17.09.96

        FILE: CData.C                              Version 1.0

   ************************************************************* */

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

#include "CSupport.h"
#include "CData.h"

// #define DP(X) cout << X;
#define DP(X) ;


// Constructor 
CData::CData()
{
    DP("\nCData::CData()");
    count = 0; // no tuples yet
    // allocate the pointers
    data = new pair[MAX_PAIR];
}

// Destructor
CData::~CData()
{
  DP("\nCData::~CData()");
  // give the memory free
  int j;
  for(j=0;j<count;j++)
  {
     // deallocate the input part of the pair
     delete[] data[j].inputV;
     // if necessary deallocate the traget part as well
     if (out_len > 0) delete[] data[j].targetV;
  }
}

// read an input vector
vector CData::GetInV(vector vect, int no)
{

  DP("\nCData::GetInV("<< vect << ", " << no << ")");
  int i;
  for(i=0;i<inp_len;i++)
  {
    vect[i] = data[no].inputV[i];
  }

  return vect;
}


// write an input vector
void CData::PutInV(vector vect, int no)
{

  DP("\nCData::PutInV("<< vect << ", " << no << ")");
  int i;
  for(i=0;i<inp_len;i++)
  {
    data[no].inputV[i] = vect[i];
  }

}


// read an target vector
vector CData::GetOutV(vector vect, int no)
{

  DP("\nCData::GetOutV("<< vect << ", " << no << ")");

  if (out_len >0 )
  {
	int i;
	 for(i=0;i<out_len;i++)
	    vect[i] = data[no].targetV[i];
  }
  else
  {
	cout << WARN_MSG << " GetOutV called - Output size is 0!!!";
	cout << "\n The return value is grab!!!\n";
  }
  return vect;
}


// read the file into memory
int CData::Read(char * filename, int i_l, int o_l)
{
	DP("\nCData::Read("<< filename << ", " << i_l << ", " << o_l << ")" );
	// the file descriptors
	FILE *fd;       // the input file
	char sep1[20], sep2[20];  // the separators in the data file

	int  endLoop = FALSE, ret_in=0, ret_out=0;

	inp_len = i_l;
	out_len = o_l;

	// open the input file
	fd = fopen(filename, "rt");
	if (fd == NULL)
	{
	   cout << ERR_MSG << "can not open file :" << filename << " !!!";
	   return -1;
	}

	// read the traingsdata and allocate memory for it
	while ( !feof(fd)  && (endLoop == FALSE) && (count < MAX_TRAIN))
	{
	   // allocate
	   data[count].inputV = new double[inp_len];
	   // read the input vector
	   ret_in = ReadVecCheck(data[count].inputV, inp_len, fd);
	   if (ret_in == -1 && !feof(fd))
	   {
	       cout << WARN_MSG << " Problems with Input Vector: ";
	       cout << count+1 << " >>> Check the Data File !!!\n";
	   }
	   // read the separartor ":" or ";"
	   sep1[0] = ';';
	   fscanf(fd, "%1s", sep1);

	   if (out_len > 0)
	   {
	     data[count].targetV = new double[out_len];

	     // read the desired vector
	     ret_out = ReadVecCheck(data[count].targetV,out_len, fd);
	     if (ret_out == -1 && !feof(fd) )
	     {
	       cout << WARN_MSG << " Problems with Output Vector: ";
	       cout << count+1 << " >>> Check the Data File !!!\n";
	     }

	     // read the separartor ";" or "."
	     sep2[0] = '.';
	     fscanf(fd, "%1s", sep2);

	     #ifdef PRINT
		PrintV(data[count].inputV, inp_len, "inV");
		PrintV(data[count].targetV, out_len, "outV");
		cout << "\n sep1: " << sep1 << "   sep2: " << sep2 << "\n";
	     #endif



	     //check if the file is in the last line
	     // if yes => stop reading
	     if (sep1[0] == ':' &&  sep2[0] == '.' )
	     {
		endLoop = TRUE;
	     }

	     // check if the file is ok
	     if (sep1[0] != ':' ||
	       ( sep2[0] != ';'  &&  sep2[0] != '.'))
	     {
	       cout << ERR_MSG << " Problems with the File Format!";
	       cout << "\n >>> Check line " << count+1
			  << " in the Data File !!!\n";
	       FileWarning(filename);
	       char dummy[MAX_STR_LEN];
	       cout << "\n\nCan't do the job! Press >RETURN< for the menu!\n";
	       gets(dummy);
	       return -1;
	     }

	   }
	   else
	   {
	     //check if the file is in the last line
	     // if yes => stop reading
	     if (sep1[0] == '.' )
	     {
		endLoop = TRUE;
	     }
	     // check if the file is ok
	     if (sep1[0] != ';' && sep1[0] != '.')
	     {
	       cout << ERR_MSG << " Problems with the File Format!";
	       cout << "\n >>> Check line " << count+1
			  << " in the Data File !!!\n";
	       FileWarning(filename);
	       return -1;
	     }
	   }
	   // increase the number of records
	   count ++;
	}

	// close the input file
	fclose(fd);

	// if the last seperator was a ";" one tupel to much
	// was read delete it !
	if( ret_in ==-1 || ret_out == -1 ) return count -1;
	else return count;
}

// write the memory (as integer) back in a file
void CData::Write(char * filename)
{
	DP("\nCData::Write("<< filename << ")" );

	FILE *outfd;

	TVector inV, outV;
	// allocate memory for the calcualtion
	inV = new double[inp_len];
	outV = new double[out_len];

	// open output file
	outfd= fopen(filename, "wt");
	if (outfd == NULL)
	{
	   cout << ERR_MSG << "can not open file :" << filename << " !!!";
	   return;
	}

	int i;
	// for all input vector in the infile do
	for(i=0;i<count;i++)
	{
	   // write the result in the output file
	   inV = GetInV( inV, i);
	   WriteIntVector(inV, inp_len, outfd);
	   fprintf(outfd, " : ");
	   outV = GetOutV( outV, i);
	   WriteIntVector(outV, out_len, outfd);
	   if (i == (count-1))
		 fprintf(outfd, ".\n");
	   else
		 fprintf(outfd, ";\n");

	}

	// close the file
	fclose(outfd);

	// give memory free
	delete[] inV;
	delete[] outV;
}


// write the memory (as floats) back in a file
void CData::WriteReal(char * filename)
{
	DP("\nCData::WriteReal("<< filename << ")" );

	FILE *outfd;

	TVector inV, outV;
	// allocate memory for the calcualtion
	inV = new double[inp_len];
	outV = new double[out_len];

	// open output file
	outfd= fopen(filename, "wt");
	if (outfd == NULL)
	{
	   cout << ERR_MSG << "can not open file :" << filename << " !!!";
	   return;
	}

	int i;
	// for all input vector in the infile do
	for(i=0;i<count;i++)
	{
	   // write the result in the output file
	   inV = GetInV( inV, i);
	   WriteVector(inV, inp_len, outfd);
	   fprintf(outfd, " : ");
	   outV = GetOutV( outV, i);
	   WriteVector(outV, out_len, outfd);
	   if (i == (count-1))
		 fprintf(outfd, ".\n");
	   else
		 fprintf(outfd, ";\n");

	}

	// close the file
	fclose(outfd);

	// give memory free
	delete[] inV;
	delete[] outV;
}


// write the class instead of the target vector
void CData::WriteClass(char * filename)
{
	DP("\nCData::WriteClass("<< filename << ")" );

	FILE *outfd;

	TVector inV, outV;
	// allocate memory for the calcualtion
	inV = new double[inp_len];
	outV = new double[out_len];

	// open output file
	outfd= fopen(filename, "wt");
	if (outfd == NULL)
	{
	   cout << ERR_MSG << "can not open file :" << filename << " !!!";
	   return;
	}

	int i;
	// for all input vector in the infile do
	for(i=0;i<count;i++)
	{
	   // write the result in the output file
	   inV = GetInV( inV, i);
	   WriteIntVector(inV, inp_len, outfd);
	   fprintf(outfd, " : ");

	   outV = GetOutV( outV, i);
	   fprintf(outfd, "%i ", WinnerNo(outV, out_len));

           if (i == (count-1))
                 fprintf(outfd, ".\n");
           else
                 fprintf(outfd, ";\n");
 
        }
 
        // close the file
        fclose(outfd);
 
        // give memory free
        delete[] inV;
        delete[] outV;
}


// make the data set noisey - set to 0 or 1
// level is the percentage of noise
void CData::InpNoise(double level)
{
	DP("\nCData::InpNoise("<< level << ")" );

        double rnd_res;

        if (level < 0 || level >1)
        {
           cout << ERR_MSG << "Noise level between 0..1!!! !!!";
           return ;
        }

	int i,j;
        for(i=0;i<count;i++)
	{
	   for(j=0;j<inp_len;j++)
	   {
		rnd_res = frand();
		if (rnd_res < level)
		{
			data[i].inputV[j] = (int) (frand() + 0.5);
			// cout << "\n : " << rnd_res;
		}
	   }
	}
}

// make the data set noisey - set to random value between 0 and 1
// level is the percentage of noise
void CData::InpNoiseReal(double level)
{
	DP("\nCData::InpNoiseReal("<< level << ")" );

	double rnd_res;
 
        if (level < 0 || level >1)
        {
           cout << ERR_MSG << "Noise level between 0..1!!! !!!";
           return ;
        }
 
        int i,j; 
	for(i=0;i<count;i++)
        {
           for(j=0;j<inp_len;j++)
           {    
                rnd_res = frand();
                if (rnd_res < level)
                {
                        // cout << "\n data[" << i << "].inputV[" << j ;
			// cout << "] was: " << data[i].inputV[j]; 

                        data[i].inputV[j] += frand();
			if (data[i].inputV[j] > 1)
				data[i].inputV[j] -= 1;

			// cout << " is now: " << data[i].inputV[j]; 
                }
           }    
        }
}
 
