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

#define N 22

struct elem {
	char farmaco[13];
	char data[7];
	struct elem *next;
};

typedef struct elem Elem;

struct componente {
	unsigned long matricola;
	Elem *terapia;
};

typedef struct componente Componente;


/* prototipi */
FILE *ApriFile(char *, char *);
void CopianeDue(char *, char *);
void Rovescia(char *, char *);
int ConfrontaDate(char *, char *);
void EliminaElemento(Elem **, Elem *);
void ControllaArchivio(Componente *, char *, char *);
void EliminaProibiti(Componente *, char *);
Elem *CreaElemento(char *, char *);
void InserisciInCoda(Elem **, Elem *, Elem *);
Elem *CreaListaAmmessi(char *);
void StampaLista(Elem *);
void StampaArchivioAtleti(Componente *);
void CostruisciArchivioAtletiDaFile(Componente *, char *);
void CostruisciArchivioAtletiDaTastiera(Componente *);
int main(void);
/* fine prototipi */



FILE *ApriFile(char *nome, char *modo)
{
	FILE *f;
	f=fopen(nome,modo);
	if(f==NULL) {
		fprintf(stderr,"Errore apertura file %s in modalita` %s. Programma terminato.\n",nome,modo);
		exit(2);
	}
	return f;
}



void CopianeDue(char *sorg, char *dest)
{
	dest[0]=sorg[0];
	dest[1]=sorg[1];
	return;
}



void Rovescia(char *sorg, char *dest)
{
	int i;
	for(i=0; i<=4; i=i+2)
		CopianeDue(sorg+4-i, dest+i);
	dest[6]='\0';
	return;
}



/*
equivalentemente si puo` far uso della seguente funzione Rovescia

void Rovescia(char *sorg, char *dest)
{
	dest[0]=sorg[4];
	dest[1]=sorg[5];
	dest[2]=sorg[2];
	dest[3]=sorg[3];
	dest[4]=sorg[0];
	dest[5]=sorg[1];
	dest[6]='\0';
	return;
}
*/



int ConfrontaDate(char *d1, char *d2)
/* restituisce:
	 1 se d1 dopo d2
	 0 se d1 e` eguale a d2
	-1 se d1 prima di d2
*/
{
	char d1rovesciata[7],  d2rovesciata[7];
	
	Rovescia(d1,d1rovesciata);
	Rovescia(d2,d2rovesciata);
	return strcmp(d1rovesciata,d2rovesciata);
}



void EliminaElemento(Elem **testa, Elem *prec)
{
	Elem *morituro;
	
	if(prec==NULL) {
		morituro=*testa;
		*testa=(*testa)->next;
	} else {
		morituro=prec->next;
		prec->next=morituro->next;
	}
	free(morituro);
		
	return;
}



void ControllaArchivio(Componente *atleti, char *farmacovietato, char *datadivieto)
{
	int i;
	Elem *precedente, *corrente, *prossimo;
	
	for(i=0; i<N; i=i+1) {
		precedente=NULL;
		corrente=atleti[i].terapia;
		while(corrente!=NULL) {
			prossimo=corrente->next;
			if((strcmp(corrente->farmaco,farmacovietato)==0) &&
			   (ConfrontaDate(corrente->data,datadivieto) > -1))
				EliminaElemento(&(atleti[i].terapia),precedente);
			else
				precedente=corrente;
			corrente=prossimo;
		}
	}
	
	return;
}



void EliminaProibiti(Componente *atleti, char *nomefile)
{
	FILE *f;
	char farmaco[13], data[7], newline;
	int ammesso,letti;
	
	f=ApriFile(nomefile,"r");
	while((letti=fscanf(f,"%s %d %s%c",farmaco,&ammesso,data,&newline))==4)
		if(ammesso==0)
			ControllaArchivio(atleti, farmaco, data);
	if((letti!=EOF)||(!feof(f))) {
		fprintf(stderr,"Formato errato nel file %s. Programma terminato.\n",nomefile);
		exit(1); /* exit() chiude automaticamente i file aperti */
	}
	fclose(f);
	return;
}



Elem *CreaElemento(char *farmaco, char *data)
{
	Elem *nuovo;
	nuovo=malloc(sizeof(Elem));
	if(nuovo==NULL) {
		fprintf(stderr,"Memoria esaurita. Programma terminato.\n");
		exit(3); 
	}
	strcpy(nuovo->farmaco,farmaco);
	strcpy(nuovo->data, data);
	nuovo->next=NULL;
	return nuovo;
}



void InserisciInCoda(Elem **testa, Elem *coda, Elem *nuovo)
{
	if(coda==NULL)
		*testa=nuovo;
	else
		coda->next=nuovo;
	return;
}



Elem *CreaListaAmmessi(char *nomefile)
{
	FILE *f;
	int ammesso,letti;
	Elem *lista, *coda, *nuovo;
	char farmaco[13], data[7], newline;
	
	f=ApriFile(nomefile,"r");
	
	lista=NULL;
	coda=NULL;
	
	while((letti=fscanf(f,"%s %d %s%c",farmaco,&ammesso,data,&newline))==4)
		if(ammesso==1) {
			nuovo=CreaElemento(farmaco,data);
			InserisciInCoda(&lista,coda,nuovo);
			coda=nuovo;
		}
	
	if((letti!=EOF)||(!feof(f))) {
		fprintf(stderr,"Formato errato nel file %s. Programma terminato.\n",nomefile);
		exit(1); /* exit() chiude automaticamente i file aperti */
	}
	fclose(f);
	return lista;
}



void StampaLista(Elem *lista)
{
	for(; lista != NULL; lista=lista->next)
		printf("Farmaco %s, data %s\n",lista->farmaco, lista->data);
	return;
}



void StampaArchivioAtleti(Componente *atleti)
{
	int i;
	for(i=0;i<N;i=i+1) {
		printf("Atleta mat. %lu - Prescrizioni:\n",atleti[i].matricola);
		StampaLista(atleti[i].terapia);
		printf("--\n");
	}
	return;
}



void CostruisciArchivioAtletiDaFile(Componente *atleti, char *nomefile)
/* 
	Consente di leggere l'archivio atleti da file.
	In contrapposizione, la funzione CostruisciArchivioAtletiDaTastiera 
	(vedi) consente di leggere l'archivio da tastiera.
	
	Il file (di testo) ha il seguente formato: 
	matricola1
		farmaco11 data11
		farmaco12 data12
	matricola2
		farmaco21 data21
	matricola3
	matricola4
		
	ove si suppone che il primo atleta abbia due prescrizioni,
	il secondo una, il terzo e il quarto nessuna; ogni prescrizione occupa
	una linea cosi` composta: tabulatore, farmaco, spazio bianco,
	data, newline ('\n')
*/
{
	FILE *f;
	int i;
	char farmaco[13], data[7], linea[22];
	Elem *coda, *nuovo;

	f=ApriFile(nomefile,"r");
	fgets(linea,22,f);
	for(i=0; i<N; i=i+1) {
		/* atol converte una stringa in un long */
		atleti[i].matricola=(unsigned long)atol(linea);
		
		atleti[i].terapia=NULL;
		coda=NULL;
		if(fgets(linea,22,f)==NULL)
			break;
		while(linea[0] == '\t') {
			/* funzione di libreria per estrarre informazioni da una stringa */
			sscanf(linea,"\t%s %s",farmaco,data);
			
			nuovo=CreaElemento(farmaco,data);
			InserisciInCoda(&(atleti[i].terapia),coda,nuovo);
			coda=nuovo;
			if(fgets(linea,22,f)==NULL)
				break;
		}
	}
	return;
}



void CostruisciArchivioAtletiDaTastiera(Componente *atleti)
/* 
	consente di leggere l'archivio da tastiera
	in contrapposizione, la funzione CostruisciArchivioAtletiDaFile 
	(vedi) consente di leggere l'archivio da file
*/
{
	int i, contaprescrizioni;
	unsigned long mat;
	char farmaco[13], data[7];
	Elem *coda, *nuovo;

	
	for(i=0; i<N; i=i+1) {
		printf("Atleta n.ro %d:\n", i+1);
		printf("    matricola: ");
		scanf("%lu",&(atleti[i].matricola));
		getchar(); /* per consumare il newline */
		atleti[i].terapia=NULL;
		coda=NULL;
		contaprescrizioni=0;
		printf("    %d. inserisci farmaco prescritto (RETURN=fine): ",contaprescrizioni+1);
		gets(farmaco);
		while(farmaco[0] != '\0') {
			printf("    %d. inserisci data prescrizione (GGMMAA): ",contaprescrizioni+1);
			gets(data);
			nuovo=CreaElemento(farmaco,data);
			InserisciInCoda(&(atleti[i].terapia),coda,nuovo);
			coda=nuovo;
			contaprescrizioni=contaprescrizioni+1;
			printf("    %d. inserisci farmaco prescritto (RETURN=fine): ",contaprescrizioni+1);
			gets(farmaco);
		}
	}
	return;
}



main()
{
	Componente atleti[N];
	Elem *lista;
	
	/* necessario per utilizzare le funzioni d'esame*/
	CostruisciArchivioAtletiDaFile(atleti,"ARCHIVIO.TXT"); 
	StampaArchivioAtleti(atleti);
	
	EliminaProibiti(atleti,"NODOPING.TXT");
	
	StampaArchivioAtleti(atleti);
	
	lista=CreaListaAmmessi("NODOPING.TXT");
	
	StampaLista(lista);
	
	return 0;
}