#include <string.h>
#include <ctype.h>
#include <iostream.h> 
#include <fstream.h> 
#include <iomanip.h> 
#include <time.h> 
#include <stdlib.h>  
#include <string.h> 
#include <math.h>

void adjust();
void clip(char *path, char *path2);
int max(int a, int b);
int lookUp(char *word, char *path);
void orderCats(char *func, int numCats);
void major(int *vote, char paths[4][120], char *fileName);
int id(char k, char *arr);
int pick(int *vote, int numberOfWinners, int wi);
void majorityVote();
void removeE(char *word);
void stringFrom();
void stringTo();
char idByNumber(int ID);
void makeAFile();
int detectTies(int *vote, int winner);
int chooseRandomly(int *vote, int winner, double prob, double randN);



//remove everything from data/*
//keep file.names category.names
//make result.paths (names of files that can vote


void main(){
  //  ofstream te("new.results");
  //int s = 173 * 5 * 35 * sizeof(char) + 1;
  //for(int j = 0; j < s; j++)
  // te<<' ';
  //  stringTo();
  // stringFrom();
  ofstream fe("majority.vote");
  fe.close();
  majorityVote();

  makeAFile();
}


void makeAFile(){
  int numberOfAlgorithms = 5;
  char fileName[120], vote, filePath[120];;
  char name[120], path[120], loss[120], extension, E;
  int numberOfClasses, s, y, Vote[5];
  numberOfClasses = 4;
  char catList[4][120];
  for(int t = 0; t < 5; t++)
    Vote[t] = 0;

  ifstream cats("category.names");
  if(!cats) cerr<<"Unable to open category.names"<<endl;
  for(int j = 0; j < numberOfClasses; j++)
    cats>>catList[j];

  char func[numberOfClasses];
  orderCats(func, numberOfClasses);

  ifstream fileNames("file.names");
  if(!fileNames) cerr<<"Unable to open file.names"<<endl;
  
  while(!fileNames.eof()){
    fileNames>>path;
    if(strlen(path) < 1) continue;
    memcpy(filePath, "data/", 6);
    strcat(filePath, path);
    ifstream file(filePath);
    if(!file) cerr<<"Unable to open "<<filePath<<endl;
    for(int a = 0; a < numberOfAlgorithms; a++){
      file>>vote;
      Vote[id(vote, func)]++;
    }
    //for(int u = 0; u < 5; u++)
    // cout<<Vote[u]<<' ';
    major(Vote, catList, path);
    for(int u = 0; u < 5; u++)
      Vote[u] = 0;
    // cout<<endl;
  }
}

void removeE(char *word){
  int s = strlen(word), pt = 0;
  for(int t = 0; t < s; t++){
    if(word[t] == '.')
      pt++;
    if(pt > 4){
      word[t] = '\0';
      break;
    }
  }
}

void stringTo(){
  char path[120];
  int ct = 1, oCT = 0;
  ifstream re("result.paths");
  //ofstream te("new.results");
  while(!re.eof()){
    re>>path;
    if(strlen(path) < 1) continue;
    ifstream obi(path);
    ct = 0;
    while(!obi.eof()){
      obi>>path;
      if(strlen(path) < 1) continue;
      //te.seekp(sizeof(char) * 35 * (ct * 5 + oCT));
      //te.write(path, 35*sizeof(char));
      //ct++;
    }
    oCT++;
  }
}

void stringFrom(){
  char path[120];
  char word[120];
  ifstream te("new.results");
  //ofstream re("newer.results");
  for(int a = 1; a < ((173 * 5) + 2); a++){
    //    for(int b = 1; b < 174; b++){
      te.seekg(a * 35 * sizeof(char));
      te.read(word, sizeof(char) * 35);
      //  re<<word<<' ';
    }

}


//makes the files under data that are entitled by the file they are voting for

void majorityVote(){
  char name[120], path[120], loss[120], extension, E;
  int numberOfAlgorithms = 5;
  int numberOfClasses, y, vote[5];
  numberOfClasses = 4;
  char catList[4][120];
  for(int t = 0; t < numberOfAlgorithms; t++)
    vote[t] = 0;

  ifstream cats("category.names");
  for(int j = 0; j < numberOfClasses; j++)
    cats>>catList[j];

  char func[numberOfClasses];
  orderCats(func, numberOfClasses);

  ifstream resultP("result.paths");
  while(!resultP.eof()){
    resultP>>path;
    if(strlen(path) < 1) continue;
    
    ifstream results(path);
    while(!results.eof()){
      results>>loss;
      if(strlen(loss) < 1) continue;
      clip(loss, name);
      for(y = 0; y < strlen(loss); y++){
	if(loss[y] == '.'){
	  extension = loss[y + 1];
	  break;
	}
      }
      int flag = 0;
      for(y += 2; y < strlen(loss); y++){
	if(loss[y] == '.')
	  flag++;
	if((flag) && (loss[y] != '.')){
	  E = loss[y]; 
	  break;}
      }
      char pth[60];
      memcpy(pth, "data/", 6);
      strcat(pth, name);
      ofstream horn(pth, ios::app);
      horn<<E<<' ';
      horn.close();
    }
  }
}

char idByNumber(int ID){
  if(ID >= 0 && ID <= 463)
    return 'b';
  if(ID >= 1508 && ID <= 11712)
    return 'w';
  if(ID >= 1247 && ID <= 1451)
    return 'c';
  if(ID >= 464 && ID <= 1246)
    return 's';
  return 'E';
}

void major(int *vote, char paths[4][120], char *fileName){
  int nC = 5;
  double resolveTie;
  int winner = 0;
  int winningValue = 0;
  for(int a = 0; a < nC; a++)
    if(vote[a] > winningValue){
      winner = a;
      winningValue = vote[a];
    }
  int numberOfWinners = detectTies(vote, winningValue);
  //  resolveTie = 1/((double) detectTies(vote, winningValue));
  winningValue = vote[pick(vote, numberOfWinners, winningValue)];
  removeE(fileName);
  ofstream oFile("majority.vote", ios::app);
  char ID = idByNumber(atoi(fileName));
  oFile<<fileName<<'.'<<ID<<"..."<<paths[winner]<<endl;
}

int pick(int *vote, int numberOfWinners, int winner){
  double hash[numberOfWinners];
  int ordinal = numberOfWinners - 1;
  double hashMark = 1 / (double) numberOfWinners;
  for(int t = 0; t < numberOfWinners; t++)
    hash[t] = hashMark * (t + 1);
  
  double randNo = rand();
  double randN = ((double)randNo/100 - (floor((double) randNo / 100))) + 0.01;
  //cout<<randN<<' ';
  //  cout<<numberOfWinners<<'-'<<hashMark<<' ';
  for(int s = 0; s < numberOfWinners; s++)
    if(hash[s] >= randN){
      ordinal =  s;
      break;
    }
  for(int a = 0; a < 5; a++)
    if(vote[a] == winner)
      if(ordinal == 0)
	return a;
      else
	ordinal--;
  cerr<<"No random choice made."<<endl;
  return 0;
}


int chooseRandomly(int *vote, int winner, double prob, double randN){
  int ordinal = 0;
  double increment = prob;
  while(1){
    if(randN > prob){
      ordinal++;
      prob = prob + increment;
    }
    else
      break;
  }
  //  cout<<prob<<' ';
  for(int a = 0; a < 5; a++)
    if(vote[a] == winner)
      if(ordinal == 0)
	return a;
      else
	ordinal--;
  cerr<<"No random number chosen."<<' '<<ordinal<<' '<<winner<<endl;
  for(int y = 0; y < 5; y++)
    cout<<vote[y]<<' ';
  cout<<endl;
  return -1;
}


int detectTies(int *vote, int winner){
  int numbOfWinners = 0;
  for(int a = 0; a < 5; a++){
    if(vote[a] == winner)
      numbOfWinners++;
  }
  //  cout<<numbOfWinners<<' ';
  return numbOfWinners;
}


int id(char k, char *arr){
  int a = 0;
  while(1)
    if(k == arr[a])
      return a;
    else
      a++;


}

void adjust(){
  char path[120], path2[120], path3[120];;
  cout<<"Enter orginal file's name:";;
  cin>>path;
  cout<<"File to copare with:";
  cin>>path3;
  ifstream file(path);
  //ofstream oFile("bp.tan.10");
  while(!file.eof()){
    file>>path;
    //    if(strnlen(path
    clip(path, path2);
    //    cout<<path2<<':';
    int y = lookUp(path2, path3);
    if(y != 1)
      cout<<path2<<':'<<y<<' ';
  }
}

int lookUp(char *word, char *path){
  char title[120];
  char tit2[120];
  int count = 0;
  ifstream file(path);
  while(!file.eof()){
    file>>title;
    if(strlen(title) < 1) continue;
    clip(title, tit2);
    //    int h = strcmp("gorky9876", "gorky9876");
    //    cout<<' '<<tit2<<'='<<word<<'+'<<h<<' ';
    if(memcmp(tit2, word, max(strlen(word), strlen(tit2))) == 0)
      count++;
  }
  return count;
}

int max(int a, int b){
  if(a < b) return b;
  else return a;
}


void clip(char *path, char *path2){
  int i, st, fn;
  if(path[0] == 'd'){
    st = 17; fn = 23;}
  else{
    st = 12; fn = 17;
  }
  for(i = st; i < fn; i++){
    if(path[i] == '.')
      break;
    path2[i-st] = path[i];
  }
  path2[i-st] = '\0';
}





void orderCats(char *func, int numCats){
  char catName[80];
  //  func = new char[numCats];
  //  int t = 0;
  ifstream cats("category.names");
  for(int t = 0; t < numCats; t++){
    cats>>catName;
    func[t] = catName[0];
  }
}
