/* File: assicura.c */
/* Time-stamp: "2001-05-25 15:45:06 calvanes" */
/* Scopo: soluzione esercizio 1 compito esame di Fondamenti di Informatica del
          14/10/2000 */

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


/* ******* SOLUZIONE PUNTO 1 ******* */

typedef int bool;
#define TRUE 1
#define FALSE 0

#define lung_targa 7
#define merito_max 20
#define lung_nome  20

typedef char TipoTarga[lung_targa + 1];
typedef char TipoNome[lung_nome + 1];

typedef char TipoData[9];          /* formato: GGMMAAAA */
typedef char TipoResponsabilita;   /* valori ammessi: 'S' o 'N' */


struct nodoLista {
  TipoTarga targa;
  int num_incidenti;
  struct nodoLista *next;
};
typedef struct nodoLista NodoLista;
typedef NodoLista *TipoLista;


/* ******* SOLUZIONE PUNTO 2 ******* */


TipoLista CercaTarga(char *t, TipoLista lis)
  /* Cerca il veicolo con targa t in lis e restituisce il puntatore
     all'elemento trovato, se questo esiste, NULL altrimenti.
     Usata al punto 2 per verificare se una targa e` gia` presente nella lista,
        ed al punto 3 per trovare il numero di incidenti. */
{
  TipoLista ris = NULL;
  bool trovato = FALSE;

  while (lis != NULL && !trovato)
    if (strcmp(lis->targa, t) == 0) {
      trovato = TRUE;
      ris = lis;
    }
    else
      lis = lis->next;

  return ris;
}  /* CercaTarga */


TipoLista ContaIncidenti(char *nomefile)
  /* In base alle informazioni contenute nel file di nome nomefile,
     costruisce una lista di coppie <t,n>, dove t e` la targa di un autoveicolo
     nel file, ed n e` il numero di incidenti di cui l'autoveicolo e` stato
     responsabile. */
{
  FILE *finc;
  TipoTarga targa;
  TipoData data;
  TipoResponsabilita resp;
  TipoLista lis_incidenti = NULL, punt;

  if ((finc = fopen(nomefile, "r")) == NULL) {
    printf("Errore in apertura in lettura di %s\n", nomefile);
    return NULL;
  }

  /* lettura degli incidenti e aggiornamento della lista */

  fscanf(finc, "%7s %8s %c", targa, data, &resp);
  while (!feof(finc)) {
    if (resp == 'S') {
      punt = CercaTarga(targa, lis_incidenti);
      if (punt == NULL) {   /* inserisci un nuovo record in testa alla lista */
        punt = malloc(sizeof(NodoLista));
        strcpy(punt->targa, targa);
        punt->num_incidenti = 1;
        punt->next = lis_incidenti;
        lis_incidenti = punt;
      } else         /* aggiorna il numero di incidenti associato alla targa */
        punt->num_incidenti++;
    }
    fscanf(finc, "%7s %8s %c", targa, data, &resp);
  }

  fclose(finc);
  return lis_incidenti;
}  /* ContaIncidenti */


/* ******* SOLUZIONE PUNTO 3 ******* */

void AggiornaClasse(int *classe, int ninc)
  /* Aggiorna la classe di merito in base al numero di incidenti. */
{
  if (ninc == 0) {
    if (*classe > 0)
      (*classe)--;
  } else
    if (*classe + ninc * 2 > merito_max)
      *classe = merito_max;
    else
      *classe += ninc * 2;
}  /* AggiornaClasse */


void AggiornaPolizze(char *nomefile, TipoLista lis_incidenti)
{
  FILE *fpolizze, *fappoggio;
  TipoTarga targa;
  int classe;
  TipoNome nome;
  TipoLista punt;
  int ninc;

  /* apertura del file di polizze e di un file di appoggio su cui scrivere le
     polizze aggiornate */

  if ((fpolizze = fopen(nomefile, "r")) == NULL) {
    printf("Errore in apertura in lettura di %s\n", nomefile);
    return;
  }

  if ((fappoggio = fopen("appoggio.txt", "w")) == NULL) {
    printf("Errore in apertura in scritture di %s\n", nomefile);
    return;
  }

  /* lettura delle polizze, aggiornamento e scrittura sul file di appoggio */
  fscanf(fpolizze, "%7s %d %20s", targa, &classe, nome);
  fgetc(fpolizze);
  while (!feof(fpolizze)) {
    punt = CercaTarga(targa, lis_incidenti);
    if (punt == NULL)
      ninc = 0;
    else
      ninc = punt->num_incidenti;
    AggiornaClasse(&classe, ninc);
    fprintf(fappoggio, "%s %2d %s\n", targa, classe, nome);
    fscanf(fpolizze, "%7s %d %20s", targa, &classe, nome);
  }

  fclose(fpolizze);
  fclose(fappoggio);

  /* rinomina il file di polizze in modo da non perderlo;
     non richiesto nella specifica */
  rename(nomefile, "polizze-orig.txt");

  /* rinomina il file di appoggio */
  rename("appoggio.txt", nomefile);
}  /* AggiornaPolizze */


/* ******* PARTE NON RICHIESTA DAL TESTO ******* */

void CancellaLista(TipoLista *lis)
  /* Pone lis uguale alla lista vuota e rende disponibile la memoria occupata.
     Versione iterativa. */
{
  TipoLista paux;

  while (*lis != NULL) {
    paux = *lis;
    *lis = (*lis)->next;
    free(paux);
  }
}  /* CancellaLista */


int main(void)
{
  char nome_file_incidenti[256], nome_file_polizze[256];
  TipoLista lis;

  printf("Immetti il nome di un file di incidenti: ");
  scanf("%256s", nome_file_incidenti);
  printf("Immetti il nome di un file di polizze: ");
  scanf("%256s", nome_file_polizze);
  lis = ContaIncidenti(nome_file_incidenti);
  AggiornaPolizze(nome_file_polizze, lis);
  CancellaLista(&lis);

  return 0;
}  /* Assicurazione */