/*
 \|/
--0--
 /|\

Martin Robinson
Soleil
calcul les mois d'ensoleillements
et dresse un statistique
10 Mai 2012
---------------------------------
préprocesseur
*/

#include <iostream>
#include <iomanip>

#include "../lib/saisieMR.hpp"
#include "../lib/algoMR.hpp"

using namespace std;

/*
constante
*/

const int NBJOURS [] = {31,29,31,30,31,30,31,31,30,31,30,31};
const char NOMMOIS [][11] = {"Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Decembre"}; 

/*
structures
*/

struct meilleurJour{
    int jour,
        duMois;
};

/*
prototype de fonction
*/

template <size_t m, size_t n>
void lireFichier(lecture &fichier, int (&moisHeure)[m][n]);
template <size_t m, size_t n>
void calculerTotalHeurChcMois(int (&totalChcMois)[m],  int (&moisHeure)[m][n]);
template <size_t m>
void calculeMoyenneHeurChcMois(int (&totalChcMois)[m], float (&moyenne)[m]);
template <size_t m>
void afficherResultatParMois(int (&totalChcMois)[m], float (&moyenne)[m]);
template <size_t m, size_t n>
meilleurJour trouverMeilleureJournee(int (&moisHeure)[m][n]);
template <size_t m>
int trouverMeilleureMois(int (&totalChcMois)[m]);
template <size_t m, size_t n>
void afficherStatistiqueEnsoleillement(meilleurJour jours, int mois, int (&moisHeure)[m][n], int (&totalChcMois)[m]);
template <size_t m>
void trierMoisHeureDecroissant(int (&totalChcMois)[m],int (&index)[m]);
template <size_t m>
void afficher6MeilleurMois(int (&index)[m]);

/*
programme principal
*/

int main()
{
    //initialisation
    int moisHeure[12][31],				//tous les mois avec le nombre d'heures d'ensoleillement par jours
        totalChcMois[12],				//somme du nombre d'heures d'ensoleillement par mois de tout les jours
        indexMoisOrdreDec[] = {0,1,2,3,4,5,6,7,8,9,10,11};	//index pour trier les mois
    float moyenne[12];					//la moyenne de chaque mois
    
	saisie <void>pause("appuyer sur une touche pour continuer\n");
	lecture soleilFichier("soleil.txt");
    if (!soleilFichier)
        return 0;

    //execution
    lireFichier<12,31>(soleilFichier,moisHeure);
   
	calculerTotalHeurChcMois<12,31>(totalChcMois,  moisHeure);
    calculeMoyenneHeurChcMois<12>(totalChcMois, moyenne);
	afficherResultatParMois<12>(totalChcMois, moyenne);
   
	meilleurJour jour = trouverMeilleureJournee<12,31>(moisHeure);
    int mois = trouverMeilleureMois<12>(totalChcMois);
    afficherStatistiqueEnsoleillement<12,31>(jour, mois,moisHeure, totalChcMois);
    
	trierMoisHeureDecroissant<12>(totalChcMois, indexMoisOrdreDec);
    afficher6MeilleurMois<12>(indexMoisOrdreDec);
    
	pause();
    return 0;
}

/*
fonction
*/

//Lire le fichier
template <size_t m, size_t n>
void lireFichier(lecture &fichier, int (&moisHeures)[m][n])
{
    for (int i=0;i<m;i++)
        for (int j=0;j<n;j++)
            if (fichier)
                fichier >> moisHeures[i][j];
}

//Calculer le total d’heure pour chaque mois
template <size_t m, size_t n>
void calculerTotalHeurChcMois(int (&totalChcMois)[m],  int (&moisHeures)[m][n])
{
    for (int i=0;i<m;i++)
    {
        totalChcMois[i] = 0;
        for (int j=0;j<n;j++)
            totalChcMois[i] += moisHeures[i][j];
    }
}

//Calculer la moyenne d’heure pour chaque mois
template <size_t m>
void calculeMoyenneHeurChcMois(int (&totalChcMois)[m], float (&moyenne)[m])
{
    for (int i=0;i<m;i++)
        moyenne[i] = (float)totalChcMois[i] / NBJOURS[i];
}

//Afficher les résultats par mois (nom du mois, son total et sa moyenne d’heure)
template <size_t m>
void afficherResultatParMois(int (&totalChcMois)[m], float (&moyenne)[m])
{
    cout << setw(60) << "Liste des statistiques sur l'ensoleillement\n"
         << setw(60) << "*******************************************\n"
         << "\nHeures d'ensoleillement par mois\n\n"
         << setw(21) << "Total" 
         << setw(11) << "Moyenne\n";
    for (int i=0;i<m;i++)
        cout << left << setw(17) << NOMMOIS[i]
             << setw(9) << totalChcMois[i]
             << setprecision(3) << moyenne[i]
             << endl;
}

//Trouver la meilleure journée dans l’année
//et l'afficher
template <size_t m, size_t n>
meilleurJour trouverMeilleureJournee(int (&moisHeure)[m][n])
{
    meilleurJour meilleur;
    meilleur.jour = 0;
    meilleur.duMois = 0;
    for (int i=0;i<m;i++)
        for (int j=0;j<n;j++)
            if (moisHeure[meilleur.duMois][meilleur.jour] < moisHeure[i][j])
            {
                meilleur.jour = j;
                meilleur.duMois = i;
            }
    return meilleur;
}

//Trouver le meilleur mois dans l’année
template <size_t m>
int trouverMeilleureMois(int (&totalChcMois)[m])
{
    int bestMonth = 0;
    for (int i = 0; i < m; i++)
        if (totalChcMois[bestMonth]<totalChcMois[i])
            bestMonth = i;
    return bestMonth;
}

//Afficher statistiques d’ensoleillement (Meilleur journée, meilleur mois)
template <size_t m, size_t n>
void afficherStatistiqueEnsoleillement(meilleurJour jour, int mois, int (&moisHeure)[m][n], int (&totalChcMois)[m])
{
    cout << "\nLa meilleure journee de l'annee est le "
         << jour.jour+1 << " " << NOMMOIS[jour.duMois] << endl
         << "et il y eu " << moisHeure[jour.duMois][jour.jour]
         << " heures d'ensoleillement\n\n";
         
    cout << "Le mois de " 
         << NOMMOIS[mois]
         << " fut le plus ensoleille avec "
         << totalChcMois[mois]
         << " heures\n\n";
}

//Trier les mois et les heures en ordre décroissant
//http://en.wikipedia.org/wiki/Gnome_sort
template <size_t m>
void trierMoisHeureDecroissant(int (&totalChcMois)[m],int (&index)[m])
{
    int tmp,
        j;
    for (int i=0; i<m;i++)
    {
        j = i;
        while(j>0 && totalChcMois[index[j-1]]<totalChcMois[index[j]])
        {
            tmp = index[j];
            index[j] = index[j-1];
            index[j-1] = tmp;
            j--;
        }
    }
}

//Afficher 6 meilleurs mois 
template <size_t m>
void afficher6MeilleurMois(int (&index)[m])
{
    cout << "Les 6 meilleurs mois d’ensoleillement\n";
    for (int i=0;i<6;i++)
    {
        cout << right << setw(6) << i << ". "
             << NOMMOIS[index[i]]
             << endl;
    }
}

