/**
 * @file jeuneEtVieux.c
 * @author l'équipe pédagogique 
 * @version version 1 03/12/05
 * @brief corrige du TD2 - Exercice 3
 * Structures de données et algorithmes - DUT1 Paris 5
 */

#include <assert.h>
#include <stdio.h>

/**
 * @brief Type date
 * invariant : la date doit être valide
*/
typedef struct Date {
	unsigned short jour, mois, annee;
} Date;

 /**
 * @brief Saisie d'une date valide
 * @return la date saisie
 */
Date saisirDate() {
	Date d;
	printf("jour, mois, année : "); fflush(stdout);
	scanf("%d %d %d", &d.jour, &d.mois, &d.annee); 
	return d;
}
  
/**
 * @brief Affiche une date
 * @param[in] d : la date à afficher
 */
void afficher(const Date* d) {
	printf("%d/%d/%d", d->jour, d->mois, d->annee);
}

 /**
 * @brief Compare deux dates sur l'axe des temps
 * @param[in] d1 : 1er argument
 * @param[in] d2 : 2ème argument
 * @return un entier négatif si d1<d2, positif si d1>d2 et nul si d1==d2
 */
int comparer(const Date* d1, const Date* d2) {
  if (d1->annee != d2->annee)
    return d1->annee - d2->annee;
  if (d1->mois != d2->mois)
    return d1->mois - d2->mois;
  if (d1->jour != d2->jour)
    return d1->jour - d2->jour;
  else return 0;
}

typedef Date Item;

/**
 * @brief Type des tableaux statiques d'items de capacité 30
 * Les fonctions "compare" et "afficher" doivent être définies
 * invariant : nbItems <= CAPACITE
*/
#define CAPACITE 5   	// Capacité du tableau

typedef struct ConteneurTS {
  Item tab[CAPACITE]; 	// Tableau des items
  unsigned int nbItems; // Nombre d'items stockés
} ConteneurTS;

 /**
 * @brief Initialise un tableau d'items vide
 * @param[out] t : le tableau d'items
 */
void initialiserT(ConteneurTS* t) {
	t->nbItems=0;
}

 /**
 * @brief Lecture d'un item d'un tableau d'items
 * @param[in] t : le tableau d'items
 * @param[in] i : l'indice de l'item dans le tableau
 * @return l'item au poste i
 * @pre i < t.nbItems   
 */
Item lireT(const ConteneurTS* t, unsigned int i) {
	assert (i < t->nbItems);
	return t->tab[i];
}

 /**
 * @brief Ecrire un item dans un tableau d'items
 * @param[in,out] t : le tableau d'items
 * @param[in] i : l'indice où ecrire l'item
 * @param[in] item : l'item à ecrire
 * @pre modification en i tel que i<t.nbItems ou ajout en i=t->nbItems tel que i<CAPACITE    
 */
void ecrireT(ConteneurTS* t, unsigned int i, const Item* item) {
	assert ((i < t->nbItems) || ((i == t->nbItems) && (t->nbItems < CAPACITE));
	t->tab[i] = *item;
	if(i == t->nbItems)
		t->nbItems++;
}

 /**
 * @brief Affichage des elements d'un tableau d'items
 * @param[in] t : le tableau d'items
 */
void afficherT(const ConteneurTS* t) {
	unsigned int i;
	for (i=0; i < t->nbItems; ++i) { // invariant : les elements de 0 à i-1 ont été affichés
		afficher(&t->tab[i]); printf("%s", "  ");
    }
	printf("%s\n");
}

 /**
 * @brief Calcul des indices des valeurs extrema d'un tableau d'items
 * @param[in] t : le tableau d'items
 * @param[out] min : l'indice d'un plus petit element
 * @param[out] max : l'indice d'un plus grand element
 * @pre t ne doit pas etre vide
 */
void extremaT(const ConteneurTS* t, unsigned int* min, unsigned int* max) {
	assert(t->nbItems > 0);
	unsigned int i;
	for (i=1, *min=0, *max=0; i < t->nbItems; ++i)
		if (comparer(&t->tab[i], &t->tab[*min]) <0)
			*min=i;
    	else if(comparer (&t->tab[i], &t->tab[*max])>0)
     			 *max=i;
}

int main() {
	ConteneurTS datesNaissanceTD;
	initialiserT(&datesNaissanceTD);
	Date d;
	int nbEtudiants, i;

	do {
		printf("En C Nombre d'étudiants du TD (max : %d) : ", CAPACITE);
		fflush(stdout);
		scanf("%d", &nbEtudiants);
	} while ((nbEtudiants <= 0) ||(nbEtudiants > CAPACITE));
	
	for (i=0; i < nbEtudiants ; ++i) {  // invariant : i dates saisies
		d = saisirDate();            
		ecrireT(&datesNaissanceTD, i, &d);
	}
	printf("\nLes dates de naissance des étudiants du TD : \n");
	afficherT(&datesNaissanceTD);
	
   	unsigned int min, max;
	extremaT(&datesNaissanceTD, &min, &max);
	printf("\nLe(s) plus jeune(s) du TD est(sont) né(s) le : ");
	Date dateMax = lireT(&datesNaissanceTD, max);
 	afficher(&dateMax); 
 	printf("\nLe(s) plus vieux du TD est(sont) né(s) le : ");
 	Date dateMin = lireT(&datesNaissanceTD, min);
 	afficher(&dateMin);
	
	return 0;
}

