#include "splittingmethod.h"

/**
 * @brief The SplittingMethod constructor constructs class and set up parametrs
 * @param instances - number of instances in data set
 */
SplittingMethod::SplittingMethod(int instances)
{
     numberOfInstances = instances;
}

/**
 * @brief The SaveHeader function saves first row - names of atributes
 * @param Data - all data
 * @return vector - names of atributes
 */
 std::vector <std::string> SplittingMethod::SaveHeader(std::vector < std::vector<std::string> > Data){

    std::vector <std::string> header;

   for (size_t k = 0; k < Data[0].size(); ++k) {
       header.push_back(Data[0][k]);
   }
   return header;
}

 /**
  * @brief The useTrainingSet divide data into training and testing set
  * @param Data - all data
  * @return trainTestPair - pair of training and testing data
  */
trainTestPair SplittingMethod::useTrainingSet(std::vector <  std::vector<std::string> > Data) {

    std::vector < std::vector<std::string> > trainData;
    std::vector < std::vector<std::string> > testData;

    trainData = Data;
    Data.erase(Data.begin());
    testData = Data;

    return std::pair<std::vector < std::vector<std::string> >, std::vector < std::vector<std::string> > > (trainData, testData);
}

/**
 * @brief The percentageSplit divide data into training and testing set based on percentage
 * @param Data - all data
 * @param percentageSplit - number of percentage to split
 * @return trainTestPair - pair of training and testing data
 */
trainTestPair SplittingMethod::percentageSplit(std::vector <  std::vector<std::string> > Data, int percentageSplit) {

   std::vector <std::string> test;

   std::vector < std::vector<std::string> > trainData;
   std::vector < std::vector<std::string> > testData;

   int numberOfSets = numberOfInstances - percentageSplit * numberOfInstances/100;
   int random = 0;

   trainData = Data;

   // spliting data to train set and test set randomly
   for (int j = 0; j < numberOfSets-1; j++) {
           random = rand() % (numberOfInstances-j) + 1;
          for (size_t  k = 0; k < Data[j].size(); k++) {
                test.push_back(trainData[random][k]);
          }
             testData.push_back(test);
             test.clear();
             trainData.erase(std::find(trainData.begin(), trainData.end(), testData[j]));
   }
   return std::pair<std::vector < std::vector<std::string> >, std::vector < std::vector<std::string> > > (trainData, testData);
}

/**
 * @brief The crossValidation divide data into training and testing set based on folds
 * @param Data - all data
 * @param numberOfSets - how to divide the data
 * @return trainTestPair - pair of training and testing data
 */
trainTestPair SplittingMethod::crossValidation(std::vector <  std::vector<std::string> > Data, int numberOfSets) {

    std::vector <std::string> test;

    std::vector < std::vector<std::string> > trainData;
    std::vector < std::vector<std::string> > testData;

    int random = 0;

    trainData = Data;

       // spliting data to train set and test set randomly
       for (int j = 0; j < numberOfSets; j++) {
           random = rand() % (numberOfInstances-j) + 1;
          for (size_t k = 0; k < Data[j].size(); k++) {
                test.push_back(trainData[random][k]);
          }
             testData.push_back(test);
             test.clear();
             trainData.erase(std::find(trainData.begin(), trainData.end(), testData[j]));
           }
     return std::pair<std::vector < std::vector<std::string> >, std::vector < std::vector<std::string> > > (trainData, testData);
}
