static void takeABus (unsigned int k, unsigned int id)
{

	/* enter critical region */
	if (semDown (semgid, sh->access) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */
	int i,counter=0;

	//she queues
	queueIn(&sh->fSt.busQueue,id);

	for(i=0;i<T;i++)
	{
		//if the number of queueing passengers
		if(queuePeek(&sh->fSt.busQueue,i) != EMPTYPOS)
		{
			counter++;
		}
	}
	//equals the number os seats in the bus
	if(counter==T)
	{
		//she informs the bus driver it is time start boarding
		if (semUp (semgid, sh->waitingDrive) == -1)
		{
			perror ("error on the up operation for semaphore access (PA)");
			exit (EXIT_FAILURE);
		}
	}
	// Change State
	sh->fSt.st.passStat[k][id].stat = AT_THE_ARRIVAL_TRANSFER_TERMINAL;
	saveState (nFic,k,&(sh->fSt));

	if (semUp (semgid, sh->access) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */
	//she waits her turn
	if (semDown (semgid, sh->pass[id]) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}

}
static void leaveTheBus (unsigned int k, unsigned int id)
{
	/* enter critical region */
	if (semDown (semgid, sh->access) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */
	int i;

	//if the bus is already empty
	if(sh->fSt.bus.nOccup==0)
	{
		//she issues an error message
		perror ("error, the bus is already empty");
		exit (EXIT_FAILURE);
	}
	//she leaves the bust
	for(i=0;i<T;i++)
	{
		if(sh->fSt.bus.seat[i] == id)
		{
			sh->fSt.bus.seat[i] = EMPTYST;
			sh->fSt.bus.nOccup--;
			break;
		}
	}
	sh->nPassD++;

	//if she is the last one to exit
	if(sh->fSt.bus.nOccup==0){
		if (semUp (semgid, sh->waitingPass) == -1)
		{
			perror ("error on the up operation for semaphore access (PA)");
			exit (EXIT_FAILURE);
		}
	}
	//change state
	sh->fSt.st.passStat[k][id].stat = AT_THE_DEPARTURE_TRANSFER_TERMINAL;
	saveState (nFic,k,&(sh->fSt));

	/* exit critical region */
	if (semUp (semgid, sh->access) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}

}
static bool collectMaterials(unsigned int craftId) {
    if (semDown(semgid, sh->access) == -1) { /* enter critical region */
        perror("error on executing the down operation for semaphore access");
        exit(EXIT_FAILURE);
    }

    bool materialsRequired; // return control variable if materials are needed

    while (!sh->fSt.workShop.nPMatIn) {
        sh->nCraftsmenBlk++;

        if (semUp(semgid, sh->access) == -1) { /* exit critical region */
            perror("error on executing the up operation for semaphore access");
            exit(EXIT_FAILURE);
        }

        /* insert your code here */
        if (semDown(semgid, sh->waitForMaterials) == -1) {
            perror("collectMaterials() error during semDown waitformaterials");
            exit(EXIT_FAILURE);
        }

        if (semDown(semgid, sh->access) == -1) { /* enter critical region */
            perror("error on executing the down operation for semaphore access");
            exit(EXIT_FAILURE);
        }
    }

    /* insert your code here */
    sh->fSt.workShop.nPMatIn -= PP; // collect the number of materials needed to produce an piece
    saveState(nFic, &(sh->fSt));

    materialsRequired = (sh->fSt.workShop.nPMatIn < PMIN); // check if the number of materials available are too low

    if (semUp(semgid, sh->access) == -1) { /* exit critical region */
        perror("error on executing the up operation for semaphore access");
        exit(EXIT_FAILURE);
    }

    return materialsRequired;
}
static bool endOperCraftsman (unsigned int craftId)
{
    bool stat;                                                                                     /* craftsman status */
    unsigned int nOpCraft,                                                      /* number of craftsmen still operative */
             i;                                                                               /* counting variable */

    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    stat = (sh->fSt.workShop.NSPMat == NP);               /* all the delivers of prime materials have been carried out */
    if (stat)
    {   nOpCraft = 0;                                              /* find out how many customers are still operative */
        for (i = 0; i < M; i++)
            if (sh->fSt.st.craftStat[i].readyToWork) nOpCraft += 1;
        stat = (sh->fSt.workShop.nPMatIn < nOpCraft*PP);             /* the amount of prime materials still remaining
                                               is less than the number of craftsmen still operative times the amount
                                                                     of prime materials necessary to produce a piece */
        if (stat)
            sh->fSt.st.craftStat[craftId].readyToWork = false;  /* the craftsman is signaled non operative from now on */
        if (stat && (nOpCraft == 1))                                   /* check if the last craftsman is about to die */
        {   sh->fSt.shop.prodTransfer = true;                    /* signal a batch of products is ready for transfer */
            if (semUp (semgid, sh->proceed) == -1)                                     /* and alert the entrepreneur */
            {   perror ("error on executing the up operation for semaphore proceed");
                exit (EXIT_FAILURE);
            }
            saveState (nFic, &(sh->fSt));                                      /* save present state in the log file */
        }
    }

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    //stat = true;                               /*         <---            remove this instruction for normal operation */
    return stat;
}
static void batchReadyForTransfer (unsigned int craftId)
{
    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    sh->fSt.st.craftStat[craftId].stat = CONTACTING_THE_ENTREPRENEUR; // state change
    sh->fSt.shop.prodTransfer = true; // ready for transfer

    if(semUp(semgid,sh->proceed) == -1) {
        perror("batchReadyForTransfer() error while semUp sh->proceed");
        exit(EXIT_FAILURE);
    }

    saveState(nFic,&(sh->fSt));

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }
}
static void primeMaterialsNeeded (unsigned int craftId)
{
    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    /* insert your code here */
    sh->fSt.st.craftStat[craftId].stat = CONTACTING_THE_ENTREPRENEUR; // state change
    sh->fSt.shop.primeMatReq = true; // materials are needed

    if(semUp(semgid,sh->proceed) == -1) {
        perror("primeMaterialsNeeded() error during semUp() for proceed");
        exit (EXIT_FAILURE);
    }

    saveState(nFic,&(sh->fSt));

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }
}
static void prepareToProduce (unsigned int craftId)
{
    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    /* insert your code here */
    sh->fSt.st.craftStat[craftId].stat = PRODUCING_A_NEW_PIECE; // state change
    saveState(nFic,&(sh->fSt));

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }
}
static void backToWork (unsigned int craftId)
{
    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    /* insert your code here */
    sh->fSt.st.craftStat[craftId].stat = FETCHING_PRIME_MATERIALS; // change state
    saveState(nFic,&(sh->fSt));

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }
}
static void reportMissingBags (unsigned int k, unsigned int id)
{
	/* Enter Critical Region */
	if (semDown (semgid, sh->access) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */

	// Change State
	sh->fSt.st.passStat[k][id].stat = AT_THE_BAGGAGE_RECLAIM_OFFICE;
	saveState (nFic,k,&(sh->fSt));

	/* Exit Critical Region */
	if (semUp (semgid, sh->access) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
}
static unsigned int goToStore (unsigned int craftId)
{
    if (semDown (semgid, sh->access) == -1)                                                   /* enter critical region */
    {   perror ("error on executing the down operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    /* insert your code here */
    int nProdIn; // variable return the correct value of materials
    sh->fSt.st.craftStat[craftId].stat = STORING_IT_FOR_TRANSFER; // state change
    sh->fSt.st.craftStat[craftId].prodPieces++; // one more unit produced by this craftsman
    sh->fSt.workShop.nProdIn++; // one more unit ready to sell
    sh->fSt.workShop.NTProd++; // one more unite produced globally
    saveState(nFic,&(sh->fSt));

    nProdIn = sh->fSt.workShop.nProdIn; // update return variable

    if (semUp (semgid, sh->access) == -1)                                                      /* exit critical region */
    {   perror ("error on executing the up operation for semaphore access");
        exit (EXIT_FAILURE);
    }

    return nProdIn;
}
static unsigned int goCollectABag (unsigned int k, unsigned int id)
{
	unsigned int retorno;
	/* Enter Critical Region */
	if (semDown (semgid, sh->access) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	if (sh->fSt.st.passStat[k][id].stat == AT_THE_DISEMBARKING_ZONE)
	{
		sh->fSt.st.passStat[k][id].stat = AT_THE_LUGGAGE_COLLECTION_POINT;
		saveState (nFic,k,&(sh->fSt));
	}

	/* Exit Critical Region */
	if (semUp (semgid, sh->access) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */

	// The passenger waits until she receives a call from the porter.
	if (semDown (semgid, sh->pass[id]) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}

	/* Enter Critical Region */
	if (semDown (semgid, sh->access) == -1)
	{
		perror ("error on the down operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	/* insert your code here */
	//If the belt is empty
	if(camEmpty(&sh->fSt.convBelt))
	{
		//and the passenger doesnt have all her bags
		if(sh->fSt.st.passStat[k][id].nBagsAct < sh->fSt.st.passStat[k][id].nBagsReal)
			//she has missing bags
			retorno = MB;
		else
			//otherwise she has no more bags to collect
			retorno = YES;
	}
	else
	{
		//goCollectBag
		//if there is a bag in the belt
		if(camSearch(&sh->fSt.convBelt,id))
		{
			//she collects it
			camOut(&sh->fSt.convBelt,id);
			sh->fSt.st.passStat[k][id].nBagsAct++;

			if(sh->fSt.st.passStat[k][id].nBagsAct < sh->fSt.st.passStat[k][id].nBagsReal)
				//she has more bags to collect
				retorno = NO;
			else
				//otherwise there are no more bags to collect
				retorno = YES;
		}
		//if there isn't
		else
		{
			//and she doesnt have all her bags
			if(sh->fSt.st.passStat[k][id].nBagsAct < sh->fSt.st.passStat[k][id].nBagsReal)
				//she has missing bags
				retorno = MB;
			else
				//otherwise there are no more bags to collect
				retorno = YES;
		}
	}
	sh->nCalls[id]--;
	saveState (nFic,k,&(sh->fSt));

	/* Exit Critical Region */
	if (semUp(semgid, sh->access) == -1)
	{
		perror ("error on the up operation for semaphore access (PA)");
		exit (EXIT_FAILURE);
	}
	return retorno;
}