/* File: magazzin.c */
/* Time-stamp: "2002-06-04 15:51:20 calvanes" */
/* Scopo: esercizio di esame del 20/09/2001 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* Dichiarazioni di costanti e tipi */

#define NUMCAT 6
/* #define NUMCAT 100 */
#define LUNGCAT  6
#define LUNGPROD 4
#define EUROINLIRE 1936.27

struct prodotto {
  char codice[LUNGPROD+1];
  int lire;
  float euro;
  struct prodotto *next;
};
typedef struct prodotto Prodotto;
typedef Prodotto *ListaProdotti;


struct prodCategoria {
  char cat[LUNGCAT+1];
  ListaProdotti prodotti;
};
typedef struct prodCategoria ProdCategoria;

typedef ProdCategoria Magazzino[NUMCAT];


struct prezzoCategoria {
  char cat[LUNGCAT+1];
  float prezzo;
  struct prezzoCategoria *next;
};
typedef struct prezzoCategoria PrezzoCategoria;
typedef PrezzoCategoria *ListaPrezzi;



/* Funzione che risolve il punto 2 */

/* ALGORITMO aggiorna i prezzi in Euro del magazzino
     FOR ogni categoria cat
     DO FOR ogni prodotto della categoria cat
        DO aggiorna il prezzo in Euro del prodotto
*/


void aggiornaPrezzi(Magazzino mag)
{
  int i;
  ListaProdotti prod;

  for (i = 0; i < NUMCAT; i++) {
    prod = mag[i].prodotti;
    while (prod != NULL) {
      prod->euro = prod->lire / EUROINLIRE;
      prod = prod->next;
    }
  }
}



/* Funzioni che risolvono il punto 3 */

/* ALGORITMO costruisci lista prezzi medi per categoria
     inizializza la lista dei prezzi alla lista vuota
     FOR ogni categoria cat
     DO IF la lista di prodotti di categoria cat non e` vuota
        THEN calcola il prezzo medio dei prodotti di categoria cat
             inserisci cat ed il prezzo medio ordinatamente nella lista
*/

float prezzoMedio(ListaProdotti prod)
{
  float prezzo = 0.0;
  int num = 0;

  while (prod != NULL) {
    prezzo += prod->euro;
    num++;
    prod = prod->next;
  }
  if (num != 0)
    prezzo /= num;

  return prezzo;
}


void inserisciInListaOrdinata(ListaPrezzi *plis, char categoria[LUNGCAT+1],
                              float prezzo)
{
  ListaPrezzi aux;

  if (*plis == NULL || (*plis)->prezzo > prezzo) {
    aux = malloc(sizeof(PrezzoCategoria));
    aux->prezzo = prezzo;
    strcpy(aux->cat, categoria);
    aux->next = *plis;
    *plis = aux;
  } else
    inserisciInListaOrdinata(&(*plis)->next, categoria, prezzo);
}


ListaPrezzi calcolaPrezziMedi(Magazzino mag)
{
  int i;
  ListaPrezzi lis = NULL;

  for (i = 0; i < NUMCAT; i++)
    if (mag[i].prodotti != NULL)
      inserisciInListaOrdinata(&lis, mag[i].cat, prezzoMedio(mag[i].prodotti));

  return lis;
}



/* funzioni ausiliarie per la verifica del programma */


void leggiMagazzino(char *nomefile, Magazzino mag)
  /* formato del file: NUMCAT righe, ciascuna con il seguente formato:
     codice-categoria n cod-prod-1 prezzo-1 ... cod-prod-n ... prezzo-n

     Esempio:

Form01 2 A001 12330 A002 15000
Form02 3 B001 1000  B002 2000  B003 3000
Scat01 0
Scat02 1 C001 1936
Surg01 2 D001 3450  D002 1230
Surg02 0

  */
{
  FILE *fp;
  int i, j, n;
  ListaProdotti aux;

  if ((fp = fopen(nomefile, "r")) == NULL) {
    printf("Errore in apertura in lettura del file %s\n", nomefile);
    exit(1);
  }

  for (i = 0; i < NUMCAT; i++) {
    fscanf(fp, "%6s%d", mag[i].cat, &n);
    mag[i].prodotti = NULL;
    for (j = 0; j < n; j++) {
      aux = malloc(sizeof(Prodotto));
      fscanf(fp, "%4s%d", aux->codice, &aux->lire);
      aux->euro = 0.0;
      aux->next = mag[i].prodotti;
      mag[i].prodotti = aux;
    }
  }
}


void stampaMagazzino(Magazzino mag)
{
  int i;
  ListaProdotti aux;

  for (i = 0; i < NUMCAT; i++) {
    printf("%6s", mag[i].cat);
    aux = mag[i].prodotti;
    while (aux != NULL) {
      printf(" - %4s %d %g", aux->codice, aux->lire, aux->euro);
      aux = aux->next;
    }
    printf("\n");
  }
}


void stampaLista(ListaPrezzi lis)
{
  while (lis != NULL) {
    printf("%6s %g\n", lis->cat, lis->prezzo);
    lis = lis->next;
  }
}


int main (void)
{
  char nomefile[256];
  Magazzino mag;
  ListaPrezzi lis;

  printf("Immetti il nome del file: ");
  scanf("%s", nomefile);
  leggiMagazzino(nomefile, mag);
  aggiornaPrezzi(mag);

  printf("Magazzino:\n");
  stampaMagazzino(mag);

  printf("\nLista prezzi:\n");
  lis = calcolaPrezziMedi(mag);
  stampaLista(lis);

  return 0;
}