///////////////////////////////////////////////////////////////////////////
// ASVR: Active Support Vector Regression                                //
// Copyright 2002 David R. Musicant and Alexander Feinberg.              //
// This software is free for academic use only.                          //
// For commercial use, contact dmusican@carleton.edu.                    //
///////////////////////////////////////////////////////////////////////////
// AsvrTest.cpp: This file contains code relating to the standalone      //
// testing application.                                                  //
///////////////////////////////////////////////////////////////////////////

#include "DataSource.H"
#include "Utilities.H"
#include "StandAlone.H"
#include "Version.H"

// Functions corresponding to executable for testing ASVR output
char gTESTFILENAME[1000], gOUTPUTFILENAME[1000], gDATATYPE[10];
bool gHEADER;

// Parse the inputs off the command line.
void ParseInputs(int argc, char *argv[]) {
  int i;
  
  // Set default values 
  gDATATYPE[0]='d';
  strcpy(gTESTFILENAME,"__none__");
  
  // Parse the inputs
  for (i=1; i < argc && (argv[i][0]=='-'); i++) {
    
    if (!strcmp(argv[i],"-precision")) {
      i++;
      strcpy(gDATATYPE,argv[i]);
    } else if (!strcmp(argv[i],"-header"))
      gHEADER = TRUE;
    else
      ThrowIt("Invalid option.");
    
  } // end-for
  
  if (i != argc-2) {
    PRINT("Active Support Vector Regression Tester.\n");
    PRINT("Copyright (C) 2002 David R. Musicant and Alexander Feinberg.\n");
    PRINT(VERSION);
    PRINT("\n\n");
    PRINT("Syntax: asvr_test test_file solution_file\n");
    exit(2);
  }
  
  strcpy(gTESTFILENAME,argv[i]);
  strcpy(gOUTPUTFILENAME,argv[i+1]);
}

void getData(::ifstream &fileIn, DenseMatrixType<double>* &A,
	     DenseVector* &y)
{

  int rows, cols, dataCols;
  char comma;
	
  // Pull rows and columns from header if present, otherwise determine
  // dynamically
  if (gHEADER) {
    fileIn >> rows >> comma >>  dataCols;
  } else {

	  ::ifstream inFile(gTESTFILENAME,ios::in);
    char inBuf[MAXROWLENGTH];
    inFile.getline(inBuf,MAXROWLENGTH);
    // Determine number of cols by taking number of commas and adding 1
    cols = 1;
    for (unsigned int i=0; i < strlen(inBuf); i++)
      if (inBuf[i]==',') cols++;
    dataCols = cols - 1;
    rows = 1; // have read one row
    // Scan rows and count how many there are
    while (inFile.getline(inBuf,MAXROWLENGTH))
      rows++;
    inFile.close();

  }
	
  A = new DenseMatrixType<double>(rows, dataCols);
  y = new DenseVector(rows);
  double **data = A->dataMatrix, *dataRow, *yRow = y->dataMatrix;
	
  for (int i = 0; i < rows; i++)
    {
      dataRow = data[i];
      for (int j = 0; j < dataCols; j++)
	{	fileIn >> dataRow[j] >> comma;	}
		
      fileIn >> yRow[i];
    }

}

void loadData(DenseMatrixType<double>* &A, DenseVector* &y)
{
	::ifstream fileIn;
  fileIn.open(gTESTFILENAME);
  getData(fileIn, A, y);
  fileIn.close();
}

int main(int argc, char *argv[])
{
  try {
    ParseInputs(argc,argv);
    
    FILE *out = fopen(gOUTPUTFILENAME,"r");
    if (!out)
      ThrowIt("Unable to read from training output file.");
    int n;
    double gamma;
    fscanf(out,"%d\n%lf\n",&n,&gamma);
    DenseVector *w = new DenseVector(n);
    double *mean = new double[n];
    double *std = new double[n];
    int i;
    for (i=0; i < n; i++)
      fscanf(out,"%lf\n",&(w->dataMatrix[i]));
    for (i=0; i < n; i++)
      fscanf(out,"%lf\n",&(mean[i]));
    for (i=0; i < n; i++)
      fscanf(out,"%lf\n",&(std[i]));

    DenseMatrixType<double> *A;
    DenseVector *y;
    
    loadData(A, y);
    A->Normalize(mean,std);
    PRINT("Test error = %g\n",A->Accuracy(w,gamma,y));

    delete w;
    delete A;
    delete y;
    delete [] mean;
    delete [] std;

  }
  catch(const char* text) {
    PRINT("%s\n",text);
  }

  return 0;
}





