/*
 * Neuron.java
 *
 * Created on 4 of August 2004, 21:54
 */

/**
 *
 * @author Paulo Roque Silva
 */
import java.util.*;
import java.io.*;

public class Neuron implements Serializable {
    public static final long serialVersionUID = 2023L;
    // Vers�o dos dados
    private static final int Nperceptions = 10;
    // perceptions atribuidas por defeito
    static boolean			end;
    // Se verdadeiro o programa do neur�nio � para acabar
    int			        	pointer, // atual passo
    						step; // total de passos dados
    int			 			who, // Identifica��o pr�pria
    						quality, // Bom ou mau
    						finalQuality, // quality total
    						threshold;
    // Nivel de rea��o (em percentagem 0-100)
    boolean					fire, // Neur�nio disparou
    						standby,
    // Para a aprendizagem por subreviv�ncia no Act
    						standby2;
    // Para a aprendizagem Out-Wait-In do Sleep
    ArrayList<Signal>		perception;
    // Sinais a que o neur�nio ouve ou age
    ArrayList<Signal>		learn; // Sinais para o Sleep

    /** Creates a new instance of Neuron */
    public Neuron(int neuronId, int th) {

		pointer = 0;
        step = 0;
        end = false;
        who = neuronId;
        threshold = th;
        quality = 0;
        finalQuality = 0;
        fire = false;
        standby = false; // Espera por disparo do aleat�rio
        standby2 = false; // Espera disparo do Mind
        perception = new ArrayList<Signal>(Nperceptions);
        learn = new ArrayList<Signal>(Nperceptions);
    }

    public void addStep() {
        
        step += 1;
    }

    public void addPointer() {
        
        pointer += 1;
    }

    public void setPointer(int i) {
        
        pointer = i;
    }
    
    public void addFinalQuality(int q) {
        
    	finalQuality += q;
    }
    
    public void setFinalQuality(int q) {
        
    	finalQuality = q;
    }
    
    public void addQuality(int q) {
        
    	quality += q;
    }
    
    public Signal getPerception(int n) {

    	if (n < perception.size())
        	return (Signal)perception.get(n);
    	else
    		if (n == 0)
    			return new Signal(0, 0, 0);
		return new Signal(0, 0, 0);
    }

    // As perce��es s�o de emissores diferentes
    private boolean newPerception(int e) {

        boolean isNew;
        int		i;
        
        isNew =true;
        for (i=0; i<perception.size(); i++)
            if (getPerception(i).emitter == e)
                isNew = false;
        return isNew;
    }
    
    // adiciona o signal com emissor <e>, a amplitude <pw>
    // e prazer <plsr>
    public void addPerception(int e, float pw, int plsr) {

        if (newPerception(e))
        	perception.add(new Signal(e, pw, plsr));
    }
    
    public void clearSignals() {
    	int i;

    	for (i=0; i<perception.size(); i++)
    		getPerception(i).setActive(false);
    }

    public void clearPerceptions() {
    	
        perception.clear();
        perception = new ArrayList<Signal>(Nperceptions);
    }
    
    public Signal getLearn(int n) {

    	return (Signal)learn.get(n);
    }

    public boolean newLearn(int e) {

        boolean isNew;
        int		i;
        
        isNew =true;
        for (i=0; i<learn.size(); i++)
            if (Math.abs(getLearn(i).emitter) == e)
                isNew = false;
        return isNew;
    }
    
    // Adiciona sinal com emissor <e>, a amplitude <pw>
    // e prazer <plsr>
    public void addLearn(int e, float pw, int plsr) {

        if (newLearn(e))
            learn.add(new Signal(e, pw, plsr));
    }
    
    public void clearLearn() {
    	
        learn.clear();
        learn = new ArrayList<Signal>(Nperceptions);
    }

    public void removeLearn(int e) {
    	
        learn.remove(e);
    }
    
    // Para os neur�nios no Emotions
    public int attentionOfFire(int sense) {
        float	activeCredit,
        		betterCredit; //Melhor surpresa
    	int		i, rtrn;
    	float   x; // Diferen�a absoluta entre amplitudes
        
    	activeCredit = 0;
    	betterCredit = 0;
    	rtrn = Cerebellum.ESCape;
        for (i=0; i<perception.size(); i++) {
            if (getPerception(i).active ||
            		getPerception(i).recPower >
            		Brain.MinSense) {
                x = Math.abs(getPerception(i).recPower -
                		getPerception(i).actPower);
                if (x > Brain.MaxInSense)
                	x = Brain.MaxInSense;
                activeCredit = (Brain.MaxInSense - x) *
                		100 / Brain.MaxInSense;
                if (activeCredit < threshold) {
                	if (sense == Brain.Vision &&
                			Liberu.Robot == 0)
                    	switch (i) {  // Muda a a��o
                    	case 1:
                    		if (activeCredit >
                    		betterCredit) {
                        		betterCredit =
                        				activeCredit;
                        		rtrn = Brain.WALK;
                    		}
                    		break;
                    	case 0:
                    		if (activeCredit >
                    		betterCredit) {
                        		betterCredit =
                        				activeCredit;
                        		rtrn = Brain.TURN_LEFT;
                    		}
                    		break;
                    	case 2: 
                    		if (activeCredit >
                    		betterCredit) {
                        		betterCredit =
                        				activeCredit;
                        		rtrn = Brain.TURN_RIGHT;
                    		}
                    		break;
                    	default: 
                        	System.out.print(
                        		"ERROR Act (actID)...");
                    		rtrn = Cerebellum.ESCape;
                    		break;
                    	}
                	if (sense == Brain.Vision &&
                			Liberu.Robot == 1)
                    	switch (i) {  // Muda a a��o
                    	case 0:
                    		if (activeCredit >
                    		betterCredit) {
                        		betterCredit =
                        				activeCredit;
                        		rtrn = Brain.TURN_RIGHT;
                    		}
                    		break;
                    	case 1: 
                    		if (activeCredit >
                    		betterCredit) {
                        		betterCredit =
                        				activeCredit;
                        		rtrn = Brain.TURN_LEFT;
                    		}
                    		break;
                    	default: 
                        	System.out.print(
                        		"ERROR Act (actID)...");
                    		rtrn = Cerebellum.ESCape;
                    		break;
                    	}
                	if (sense == Brain.Taste &&
                			Liberu.Robot == 0)
                    	switch (i) {  // Muda a a��o
                    	case (World.EARTH - 1):
                		break;
                    	case (World.WATER - 1):
                    		rtrn = Brain.DRINK;
                		break;
                    	case (World.FOOD - 1): 
                    		rtrn = Brain.EAT;
                		break;
                    	default: 
                        	System.out.print(
                        		"ERROR Act (actID)...");
                    		rtrn = Cerebellum.ESCape;
                    		break;
                    	}
                }
            }
        }
        return rtrn;  // = IdAct1
    }
    
    // Para os neur�nios no Remember
    public float powerOfFire(int sense) {
        float	activeCredit,
        		nActives, // N�mero de sinais ativos
        		rtrn ;
    	int		i; // index
    	float   x; // Diferen�a absoluta entre amplitudes
        
        nActives = 0;
    	activeCredit = 0;
    	rtrn = 0;
        for (i=0; i<perception.size(); i++)
            if (getPerception(i).active ||
            		getPerception(i).recPower >
            Brain.MinSense) {
            	// Calcula activeCredit
               	nActives += 1;
                x = Math.abs(getPerception(i).recPower -
                		getPerception(i).actPower);
                if (x > Brain.MaxInSense)
                	x = Brain.MaxInSense;
                activeCredit += (Brain.MaxInSense - x) *
                		100 / Brain.MaxInSense;
            }
    	fire = false;
    	if (nActives == 0) nActives = 1;
    	activeCredit = activeCredit / nActives;
        if (activeCredit >= threshold) {
        	fire = true;
        	rtrn = activeCredit;
        }
        return rtrn;
    }
    
 // Para os neur�nios do Act
    public void powerToAct() {
        int		activeCredit,
        		totalActivos, // Total das percep��es
        		credit, // Credito dado
    			i; // index
        
    	activeCredit = 0;
        totalActivos = 0;
        for (i=0; i<perception.size(); i++) {
            if (getPerception(i).active) {
                activeCredit += getPerception(i).recPower;
                totalActivos += 1;
            }
        }
    	fire = false;
    	if (totalActivos == 0) totalActivos = 1;
    	 // M�dia percentual dos ativos
    	credit = (int)(activeCredit / totalActivos);
    	System.out.println(credit); // RETIRAR
        if (credit >= threshold) {
        	fire = true;
        	standby = true;
        }
    }
}