/****************************************************************/
/* skier.c                                                      */
/* Justin Hartman                                               */
/* EECS 338 - Spring 2003                                       */
/* Assignment 5                                                 */
/****************************************************************/

/****************************************************************/
/* Written in Microsoft Visual C++ .NET                         */
/* Compiled and executed on CWRU's EECS department              */
/* lab's (Olin 404.5) SUN boxes using SSH and                   */
/* secure FTP                                                   */
/****************************************************************/

#include "sem.h"
#include "queue.h"

int main(int argc, char *argv[]) {
	int shmid, semid_lines, mutex_q, mutex_count;
	int i;
	int ppid = (int)getppid();
	
	int lscount;
	int ltcount;
	int rtcount;
	int rscount;

	int *skicount;
	queue *q[4];

	int ridecount=0;

	/* Initialize the shared queues */
	for (i=0; i<4; i++) {
		if ((shmid=shmget(ppid + i, 0, 0)) == -1) {
			perror("Skier: op shmget of queues failed");
			exit(1);
		}
		if ((q[i]=(queue *)shmat(shmid,0,0)) == (queue *)-1) {
			perror("Skier: op shmat attach of queues failed");
			exit(1);
		}
	}

	/* Initialize the shared skier count */
	if ((shmid=shmget(ppid + 4, 0, 0)) == -1) {
		perror("Skier: op shmget of skier count failed");
		exit(3);
	}
	if ((skicount=(int *)shmat(shmid,0,0)) == (int *)-1) {
		perror("Skier: op shmat attach of skier count failed");
		exit(4);
	}

	/* Set up the four line semaphores */
	if ((semid_lines=semget(ppid + 5, 4, 0)) == -1) {
		perror("op semget of line semaphore failed");
		exit(5);
	}

	/* Set up the queue mutex semaphore */
	if ((mutex_q=semget(ppid + 6, 1, 0)) == -1) {
		perror("op semget of queue mutex semaphore failed");
		exit(6);
	}

	/* Set up the skier count mutex semaphore */
	if ((mutex_count=semget(ppid + 7, 1, 0)) == -1) {
		perror("op semget of skier count mutex semaphore failed");
		exit(7);
	}

	/* Create 16 processes - 15 plus this one */
	for (i=0; i<SKIERCOUNT-1; i++) {
		if (fork()==0) break; /* If you're a forked skier, break out */
	}

	/* Increment the number of skiers */
	P(mutex_count, 0);
	(*skicount)++;
	V(mutex_count, 0);

	/* As long as we haven't ridden the max times, keep getting in line */
	while (ridecount < RIDESMAX) {
		P(mutex_q, 0);

		lscount = count(q[0]);
		ltcount = count(q[1]);
		rtcount = count(q[2]);
		rscount = count(q[3]);

		if ((lscount < (int)(2 * ceil(ltcount / 3.0))) && (lscount < (int)(2 * ceil(rtcount / 3.0))) && (lscount < rscount)) {
			//Load in the left single line
			printf("\nSkier: Process %d loading in the left single line.", (int)getpid());
			insertq ((int)getpid(), q[0]);
			V(mutex_q, 0);
			P(semid_lines, 0);
		} else if ((rscount < (int)(2 * ceil(ltcount / 3.0))) && (rscount < (int)(2 * ceil(rtcount / 3.0)))	&& (rscount <= lscount)) {
			//Load in the right single line
			printf("\nSkier: Process %d loading in the right single line.", (int)getpid());
			insertq ((int)getpid(), q[3]);
			V(mutex_q, 0);
			P(semid_lines, 3);
		} else if (ltcount < rtcount) {
			//Load in the left triple line
			printf("\nSkier: Process %d loading in the left triple line.", (int)getpid());
			insertq ((int)getpid(), q[1]);
			V(mutex_q, 0);
			P(semid_lines, 1);
		} else {
			//Load in the right triple line
			printf("\nSkier: Process %d loading in the right triple line.", (int)getpid());
			insertq ((int)getpid(), q[2]);
			V(mutex_q, 0);
			P(semid_lines, 2);
		}

		sleep(rand0to5 ()); /* Skiing */

		ridecount++;
	}

	/* One less skier */
	P(mutex_count, 0);
	(*skicount)--;
	V(mutex_count, 0);

	printf("\nSkier: Process %d is done for the day.", (int)getpid());

	return(0);
}