/*******************************************************************************************
09P.cpp
    read data into an array of objects, display them and do some calculations on them
*******************************************************************************************/
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class soldier_t {
    public:
        string first;
        string last;
        string rank;
};

class result_t {
    public:
        string rank;
        int count;
        float percent;
};

//prototypes
void readData(string file, soldier_t[], const int size, int& count);
void readCriteria(string file, result_t list[], const int size, int& count);
void calcKnowns(soldier_t[], const int, result_t[], const int);
int countOfRank(string rank, soldier_t[], const int size);
void addUnknown(const int init, result_t results[], int& count);
void displayResults(result_t results[], const int numResults);

void main() {
    //setup storage "material"
    const int MaxSoldiers = 100;
    soldier_t soldiers[MaxSoldiers];
    int numSoldiers = 0;

    const int MaxResults = 30+1;
    result_t results[MaxResults];
    int numResults = 0;

    //get user input
    string filename;
    cout << "Enter the DATA FILE name: ";
    cin >> filename;
    readData(filename, soldiers, MaxSoldiers, numSoldiers);
    cout << "Enter the RANK FILE name: ";
    cin >> filename;
    readCriteria(filename, results, MaxResults, numResults);
    cout << endl;

    calcKnowns(soldiers, numSoldiers, results, numResults);
    addUnknown(numSoldiers, results, numResults);

    displayResults(results, numResults);
}

// ------- Load the specified data file into the list -------
void readData(string file, soldier_t list[], const int size, int& count) {
    ifstream fin(file.c_str());

    for (int i = 0; i < size; i++) {
        if(fin >> list[i].rank >> list[i].first >> list[i].last)
            count++;
        else
            break;
    }
}

// ------- Loat the specified criteria file into the list --------
void readCriteria(string file, result_t list[], const int size, int& count) {
    ifstream fin(file.c_str());

    for (int i = 0; i < size; i++) {
        if(fin >> list[i].rank)
            count++;
        else
            break;
    }
}

// ------- Cross-reference and calculate between lists -------
void calcKnowns(soldier_t data[], const int numData, result_t results[], const int numResult) {
    for (int i = 0; i < numResult; i++) {
        results[i].count = countOfRank(results[i].rank, data, numData);
        results[i].percent = (float)results[i].count / numData;
    }
}

// ------- return the count of a given rank -------
int countOfRank(string rank, soldier_t list[], const int size) {
    int sum = 0;
    for (int i = 0; i < size; i++)
        if (list[i].rank == rank)
            sum++;
    return sum;
}

// ------- Tweak the result array to include a final "other" category count -------
void addUnknown(const int init, result_t results[], int& count) {
    results[count].rank = "Other";
    results[count].count = init;
    results[count].percent = 1.0;
    for (int i = 0; i < count; i++) {
        results[count].count -= results[i].count;
        results[count].percent -= results[i].percent;
    }
    count++; //include the unknown data
}

// ------- Display the results in the prescribed format -------
void displayResults(result_t results[], const int numResults) {
^Icout.precision(0);
    cout.setf(ios::fixed);
    int total = 0;
    for (int i = 0; i < numResults; i++) {
        cout << results[i].rank << "s: " << results[i].count
             << " (" << results[i].percent*100 << "%)" << endl;
        total += results[i].count;
    }
    cout << "------------------------------------" << endl
         << "Total: " << total << endl;
}