/*
Nome: Mario
Cognome: Montanari

Si crei la struttura libro, in cui ogni libro ha
un codice numerico (numero intero) che lo caratterizza,
un titolo, un autore, un numero di pagine e un costo.
   - si memorizzino i dati di tre libri;
   - si calcoli il costo medio per pagina dei libri;
   - si stampino i dati dei tre libri in ordine crescente di costo per pagina;
   - si stampino i dati dei tre libri in ordine crescente di titolo.

*/

#include <iostream>
#include <ctime>
#include <iomanip>

#define SIZE 100+1

#define N_LIBRI 3

#define MIN_SILLABE 2
#define MAX_SILLABE 5

#define MIN_COD 10000
#define MAX_COD 99999

#define MIN_TITOLO 65
#define MAX_TITOLO 90

#define MIN_PAG 100
#define MAX_PAG 900

#define MIN_COSTO 1000
#define MAX_COSTO 9000

using namespace std;

typedef struct {
	int nCod;
	char titolo[SIZE];
	char autore[SIZE];
	int nPag;
	float costo;
	int costoPerPagina;
} libro;

int cmpCostoPerPagina(const void *x, const void *y);
int cmpTitolo(const void *x, const void *y);
void generaCaratteristiche(libro caratteristiche[]);
void stampaCaratteristiche(libro caratteristiche[]);

int main(void) {
	srand(time(NULL));
	libro caratteristiche[N_LIBRI];
	int nSillabe = 0;
	
	generaCaratteristiche(caratteristiche);
	
	cout << "--- Ordinazione crescente in base al costo medio per pagina --------------------------------------------" << endl << endl;
	qsort(caratteristiche, N_LIBRI, sizeof(libro), cmpCostoPerPagina);
	stampaCaratteristiche(caratteristiche);
	
	cout << endl << endl << endl << "--- Ordinazione crescente in base al titolo ------------------------------------" << endl << endl;	
	qsort(caratteristiche, N_LIBRI, sizeof(libro), cmpTitolo);
	stampaCaratteristiche(caratteristiche);
	
	return 0;
}

int cmpCostoPerPagina(const void *x, const void *y) {
	const libro *libroX = (const libro *)x;
	const libro *libroY = (const libro *)y;
	
	return libroY->costoPerPagina - libroX->costoPerPagina;
}

int cmpTitolo(const void *x, const void *y) {
	const libro *libroX = (const libro *)x;
	const libro *libroY = (const libro *)y;
	
	return strcmp(libroX->titolo, libroY->titolo);
}

void generaCaratteristiche(libro caratteristiche[]) {
	const char vocali[] = "AEIOU";
	const char consonanti[] = "BCDFGHJKLMNPQRSTVWXYZ";
	
	for (int i = 0; i < N_LIBRI; i++) {
		
		caratteristiche[i].nCod = rand() % (MAX_COD - MIN_COD + 1) + MIN_COD;
		// 'setfill('.')' riempie gli spazi vuoti con dei punti
		
		int nSillabe = rand() % (MAX_SILLABE - MIN_SILLABE + 1) + MIN_SILLABE;
		
		int r = 0;
		for (int j = 0; j < nSillabe; j++) {
			caratteristiche[i].titolo[r++] = consonanti[rand() % 21];
			caratteristiche[i].titolo[r++] = vocali[rand() % 5];
		}
		caratteristiche[i].titolo[r] = '\0';
		
		nSillabe = rand() % (MAX_SILLABE - MIN_SILLABE + 1) + MIN_SILLABE;
		
		int w = 0;
		for (int j = 0; j < nSillabe; j++) {
			caratteristiche[i].autore[w++] = consonanti[rand() % 16];
			caratteristiche[i].autore[w++] = vocali[rand() % 5];
		}
		
		caratteristiche[i].autore[w++] = ' ';
		
		nSillabe = rand() % (MAX_SILLABE - MIN_SILLABE + 1) + MIN_SILLABE;
		
		for (int j = 0; j < nSillabe; j++) {
			caratteristiche[i].autore[w++] = consonanti[rand() % 16];
			caratteristiche[i].autore[w++] = vocali[rand() % 5];
		}
		caratteristiche[i].autore[w] = '\0';
				
		caratteristiche[i].nPag = rand() % (MAX_PAG - MIN_PAG + 1) + MIN_PAG;
		
		caratteristiche[i].costo = rand() % (MAX_COSTO - MIN_COSTO + 1) + MIN_COSTO;
		
		caratteristiche[i].costoPerPagina = caratteristiche[i].costo / caratteristiche[i].nPag;
		// 'fixed' imposta il numero in virgola fissa
		// 'setprecision(2)' limita a 2 cifre decimali il numero
	}
}

void stampaCaratteristiche(libro caratteristiche[]) {
	for (int i = 0; i < N_LIBRI; i++) {
		cout << "Libro " << "'" << caratteristiche[i].titolo << "':" << endl;
		cout << "  Codice numerico: " << setfill('.') << setw(18) << " " << caratteristiche[i].nCod << endl;
		cout << "  Titolo: " << setw(27) << " " << caratteristiche[i].titolo << endl;
		cout << "  Autore: " << setw(27) << " " << caratteristiche[i].autore << endl;
		cout << "  Numero pagine: " << setw(20) << " " << caratteristiche[i].nPag << " pagine" << endl;
		cout << "  Costo: " << setw(28) << " " << caratteristiche[i].costo / 100 << " euro" << endl;
		cout << "  Costo medio per pagina: " << setw(11) << fixed << setprecision(2) << " " << caratteristiche[i].costoPerPagina << " centesimi" << endl << endl;
	}
}