//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Sep 10 18:41:07 PDT 2006
// Last Modified: Sun Sep 10 18:41:10 PDT 2006
// Filename:      ...sig/examples/all/perf2score.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/perf2score.cpp
// Syntax:        C++; museinfo
//
// Description:   Combine performance data with a performance score.
//

#include "humdrum.h"

#include <string.h>
#include <stdio.h>
#include <math.h>

#ifndef OLDCPP
   using namespace std;
   #include <iostream>
#else
   #include <iostream.h>
#endif

// function declarations:
void      checkOptions(Options& opts, int argc, char** argv);
void      example(void);
void      usage(const char* command);
void      printData(HumdrumFile& pdata, HumdrumFile& sdata,
                                 Array<double>& abeat, Array<int>& pindex,
                                 Array<Array<int> >& keys);

// User interface variables:
Options   options;
HumdrumFile firstinput;

//////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv) {
   // process the command-line options
   checkOptions(options, argc, argv);
   HumdrumFile pdata;
   HumdrumFile sdata;

   pdata.read(options.getArg(1));
   sdata.read(options.getArg(2));

   Array<double>         abeat;
   Array<Array<int> >    keys;
   Array<int>            pindex;

   abeat.setSize(pdata.getNumLines());
   abeat.setSize(0);
   keys.setSize(pdata.getNumLines());
   keys.setSize(0);
   pindex.setSize(pdata.getNumLines());
   pindex.setSize(0);

   int i, j;

   char *nump;
   char tmpstr[1024] = {0};

   double number;
   int    inumber;

   int abeatindex  = 0;
   int keyindex    = 1;
   int peventindex = 2;
   int ieventindex = 3;
   int idynindex   = 4;

   for (i=0; i<pdata.getNumLines(); i++) {
      if (strncmp(pdata[i][0], "**", 2) == 0) {
         for (j=0; j<pdata[i].getFieldCount(); j++) {
            if (strcmp(pdata[i][j], "**abeat") == 0) {
               abeatindex = j;
            }
            if (strcmp(pdata[i][j], "**keynums") == 0) {
               keyindex = j;
            }
            if (strcmp(pdata[i][j], "**pevent") == 0) {
               peventindex = j;
            }
            if (strcmp(pdata[i][j], "**ievent") == 0) {
               ieventindex = j;
            }
            if (strcmp(pdata[i][j], "**idyn") == 0) {
               idynindex = j;
            }
         }
      }
	     
      if (pdata[i].getType() != E_humrec_data) {
         continue;
      }

      if (sscanf(pdata[i][abeatindex], "%lf", &number) == 1) {
         abeat.append(number);
         pindex.append(i);
      } else {
         cerr << "Error on line: " << pdata[i] << endl;
         exit(1);
      }

      strcpy(tmpstr, pdata[i][keyindex]);

      nump = strtok(tmpstr, " \n\t:,");
      keys.setSize(keys.getSize()+1);
      keys[keys.getSize()-1].setSize(100);
      keys[keys.getSize()-1].setSize(0);
      while (nump != NULL) {
         if (sscanf(nump, "%d", &inumber) == 1) {
            keys[keys.getSize()-1].append(inumber);
         }
         nump = strtok(NULL, " \n\t:,");
      }
		         

   }

   printData(pdata, sdata, abeat, pindex, keys);
   

   return 0;
}

//////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// printData -- print performance data + score data
//

void printData(HumdrumFile& pdata, HumdrumFile& sdata,
      Array<double>& abeat, Array<int>& pindex, Array<Array<int> >& keys) {

   sdata.analyzeRhythm("4");

   int i, j;
   j = 0;

   for (i=0; i<sdata.getNumLines(); i++) {
      switch (sdata[i].getType()) {
         case E_humrec_data_comment:
            cout << "!\t" << sdata[i] << "\t!\t!\n";
            break;
         case E_humrec_data_kern_measure:
            cout << sdata[i][0] << "\t" << sdata[i] << "\t" 
                 << sdata[i][0] << "\t" << sdata[i][0] << "\n";
            break;
         case E_humrec_interpretation:
            if (strncmp(sdata[i][0], "**", 2) == 0) {
               cout << "**time\t" << sdata[i] << "\t**itime\t**idyn\n";
            } else if (sdata[i].equalFieldsQ()) {
               // could be buggy to do it this way in the general case...
               cout << sdata[i][0] << "\t" << sdata[i] << "\t" 
                    << sdata[i][0] << "\t" << sdata[i][0] << "\n";
            } else {
               cout << "*\t" << sdata[i] << "\t*\t*\n";
            }
            break;
         case E_humrec_data:
	    if (j > abeat.getSize()-1) {
               cout << ".\t" << sdata[i] << "\t.\t.\n";
            } else if (fabs(abeat[j] - sdata[i].getAbsBeat()) < 0.001) {
               cout << pdata[pindex[j]][2]
                    << "\t" << sdata[i] 
                    << "\t" << pdata[pindex[j]][3]
                    << "\t" << pdata[pindex[j]][4]
                    << "\n";
	       j++;
            } else {
               cout << ".\t" << sdata[i] << "\t.\t.\n";
            }
            break;
         case E_humrec_none:
         case E_humrec_empty:
         case E_humrec_global_comment:
         case E_humrec_bibliography:
         default:
            cout << sdata[i] << "\n";
      }

   }

}




//////////////////////////////
//
// checkOptions -- 
//

void checkOptions(Options& opts, int argc, char* argv[]) {

   opts.define("author=b",  "author of program"); 
   opts.define("version=b", "compilation info");
   opts.define("example=b", "example usages");   
   opts.define("help=b",  "short description");
   opts.process(argc, argv);
   
   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, Sep 2006" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 11 Sep 2006" << endl;
      cout << "compiled: " << __DATE__ << endl;
      cout << MUSEINFO_VERSION << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }
   
}



//////////////////////////////
//
// example --
//

void example(void) {


}



//////////////////////////////
//
// usage --
//

void usage(const char* command) {

}



// md5sum: d88a28f14519e0fa014fb978f217a00a perf2score.cpp [20080518]