// Melita Mihaljevic 0036411392
// Djed Mraz spava u svojoj kuci na Sjevernom polu i može biti probuden ako mu se vrati svih 10 sobova sa njihovog odmora (preciznije posljednji budi Djeda Mraza). 
//On ih tada nahrani i ponovo odlazi spavati, a sobovi ostaju pred kucom. Djedovo budenje mogu izazvati i patuljci koji imaju poteškoca prilikom izrade igracaka. Ako samo 
//jedan patuljak ima problem, to nije toliko ozbiljno da bi probudio Djeda Mraza, pa zato patuljci posjecuju Djeda Mraza u grupama po 3. Patuljci kod Djeda Mraza provedu 
//odredeno vrijeme te se nakon toga vrate pravljenju igracaka, a Djed Mraz spavanju. Samo jedna grupa patuljaka može u isto vrijeme ici Djeda Mrazu, dok ostale moraju cekati 
//da se ta grupa ne vrati. Ako se Djed Mraz probudi i ispred vrata vidi grupu patuljaka (može i manje od tri) i sve sobove, on ce smatrati da je došlo vrijeme za razvoženje poklona
// te da patuljci mogu cekati dok ne obavi zadatak. Nakon razvoženja poklona dat ce svojim sobovima godišnji odmor.
//Napišite program koji simulira gornje radnje pazeci na specificnosti svakog od likova. Ispis programa mora biti detaljan. Za svakog "aktera" predviditi po jednu dretvu/proces.

// djed mraz sa semaforima
// implementirana su i djeca koja cekaju darove

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<sys/msg.h>
#include<values.h>
#include<pthread.h>
#include<signal.h>
#include<semaphore.h>
#include<time.h>
#include<malloc.h>

int redni_broj_soba =0; // globalne varijable
int broj_patuljaka =0;
int red_patuljaka[100];

// semafori , ima ih 5 od tog su djed_mraz, K i djeca_cekaju binarni, a sobovi i konzultacije su opci semafori (broje dolazak sobova i patuljaka)
sem_t *DJED_MRAZ;
sem_t *K;
sem_t *SOBOVI;
sem_t *KONZULTACIJE;
sem_t *djeca_cekaju;

// ako se dogodi prekid ubij semafore
void prekidna_rutina(int sig) {
	sem_destroy(DJED_MRAZ);
	sem_destroy(K);
	sem_destroy(SOBOVI);
	sem_destroy(KONZULTACIJE);
	sem_destroy(djeca_cekaju);
	exit(0);
}

//dretva sob
void *Sob (void *arg){
	sem_wait(K);  // udlji u kriticni odsjecak jer moras promijenti varijablu koja broji koliko ima sobova
	redni_broj_soba ++;
	printf("%d.sobova je pred vratima i %d -i patuljak je pred vratima\n",redni_broj_soba,broj_patuljaka);
	
	if (redni_broj_soba==10) { // ako su svi sobovi dosli budi djeda mraza
		printf ("stigli su Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen,Robbie, Rudolph. Rudolph je svojim nosicem probudio Djedicu\n");
		sem_post(DJED_MRAZ); // probudi djeda mraza
	}
	sem_post(K);// postavi semafor K (izadji iz KO)
	sem_wait(SOBOVI); // postavi semafor SOBOVI

}

//dretva Patuljak
void *Patuljak (void *arg){
	sem_wait(K); // udlji u KO
	broj_patuljaka ++; // povecaj broj patuljaka koji su stigli
	printf("%d sobova je pred vratima i %d-i patuljak je dosao pred vrata\n",redni_broj_soba, broj_patuljaka);
	if (broj_patuljaka == 3) { // ako je broj patuljaka 3 onda budi djedicu
		sem_post(DJED_MRAZ);
	}
	if (!(broj_patuljaka%3)) { // ako je broj patuljaka djeljiv s 3 onda isto probudi djedicu  (bas i nije vjerojatno)
		sem_post(DJED_MRAZ);
	}
	sem_post(K); // izadji iz KO
	sem_wait(KONZULTACIJE);// cekaj patuljke opet
}

// dretva djedica
void *Djed_Mraz(void *arg){
	while(1){
		sem_wait(DJED_MRAZ); // cekaj semafor djed mraz tu ga postavlja
		sem_wait(K); // udlji u KO
		if(redni_broj_soba == 10 && broj_patuljaka >0) { // ako su dosli svi sobovi i ima bar 1 patuljak
			sem_post(K);// izadjnji iz KO
			sem_post(djeca_cekaju); //postavi djecu koja ckejau
			redni_broj_soba = 0;// vrati globalne varijable na 0
			broj_patuljaka =0;
			usleep(1500000);
			sem_wait(K);//  udlji u KO
			sem_init(SOBOVI,0,10); // inicializiraj sobove da cekas 10
		}
		if (redni_broj_soba == 10 && broj_patuljaka == 0) { // ako su samo sobovi  a nema patuljaka
			sem_post(K); // nahrani sobove i to je  u KO
			printf("Sobovi papaju i pripremaju se na put\n");
			usleep(15000000);
			sem_wait(K);
		}
		if(broj_patuljaka>=3){ // ako ima vise od 3 patuljka uzmi 3 , pomozi im i odi pavati
			sem_post(K);
			printf("Djed mraz zijeva,prima patuljke,pomaze im, pije mlijeko i nastavlja spavati \n");
			broj_patuljaka -=3;
			usleep(1500000);
			sem_wait(K);
			sem_init(KONZULTACIJE,0,3); //postavi semafor na ckanje
		}
		sem_post(K);// vrati se iz KO
	}
}
// dretva djeca
void *Djeca(void *arg) {
	sem_post(K); // KO
	printf("Djeca cekaju darove i jako su tuzna jer bozic kasni\n");
	sem_wait(K);
	sem_wait(djeca_cekaju);
	printf("Djed mraz svoj djeci donosi darove jer nezna koja su bila dobra a koja losa\n");
	printf(" Djeca su dobila darove i jako si sretna\n");
	usleep(1500000);
}

// glavni program
int main(void) {
	int i ;	
	sigset(SIGKILL,signal); // sta  ako se ubije 
	
	pthread_t pSob[100]; 		
	pthread_t pPatuljak[100];
	pthread_t pDjed_Mraz;
	pthread_t pDjeca;
	
	DJED_MRAZ =(sem_t*)malloc(sizeof(sem_t)); // mem prostor semafora
	K=(sem_t*) malloc(sizeof(sem_t));
	SOBOVI =(sem_t*)malloc(sizeof(sem_t));
	KONZULTACIJE= (sem_t*) malloc(sizeof(sem_t));
	djeca_cekaju= (sem_t*)malloc(sizeof(sem_t));
	
	if (Djed_Mraz == NULL || K == NULL) {
		printf ("Nema memorije za semafore!\n");
		exit(-1);
	}
// inicializacija semafora

	sem_init(DJED_MRAZ,0,0);
	sem_init(K,0,1);
	sem_init(SOBOVI,0,10);
	sem_init(KONZULTACIJE,0,3);
	sem_init(djeca_cekaju,0,0);
//Pokretanje dretvi	
	pthread_create(&pDjed_Mraz,NULL,Djed_Mraz,NULL);
	pthread_create(&pDjeca,NULL,Djeca,NULL);
// random pokretanje dretvi soba i patljaka
	for (i =0; i<100; i++) {
		sleep(rand()%3 +1);
		if (rand()%2  ==0 ) {
			if(redni_broj_soba <10) {
				pthread_create(&pSob[i],NULL,Sob,NULL);
			}
		}
		if (rand()%2==0) {
			pthread_create(&pPatuljak[i],NULL,Patuljak,NULL);
		}
	}
	for (i =0; i<100; i++) {
		pthread_join(pSob[i],NULL);
		pthread_join(pPatuljak[i],NULL); // ubijanje dretvi

	}
	pthread_join(pDjed_Mraz,NULL);
	pthread_join(pDjeca,NULL);

	return 0;
}





