/*
 * Animal.java
 * @author  Michael Anderson
 *
 *  Defines the agents in the LotkaVolterra model.
 *
 * Created on July 21, 2004, 4:23 PM
 * Last Updated on August 26, 2004
 */

package LotkaVolterra;

public class Animal {
    
    // ** data members
    public double r;           // growth rate
    private double x;           // population
    public int[] connection;    // array of connections
    public double[] conStrength;// array of connection strengths
    // **
    
    
    // Return the population of this animal
    public double getX() {
        return x;
    }
    
    
    // Set the Population of this animal
    // but keep it within bounds
    public void setX(double newX) {
        if (newX >= 1) {
            this.x = 0.99999999;
        } else if (newX < Math.pow(10,-10)) {
            this.x = 0;
        } else {
            this.x = newX;
        }
    }
    
    
    // Creates a new instance of Animal
    public Animal(double r, double x, int[] c, double[] s) {
        this.r = r;
        this.x = x;
        this.connection = c;
        this.conStrength = s;
    }
    
    public Animal(int[] c, double[] s) {
        this.r = -Math.log(Math.random());
        this.x = Math.random();
        this.connection = c;
        this.conStrength = s;
    }
    
    
    // Takes in an array of doubles and will turn that into
    // a connection array and a conStrength array
    public Animal(double[] alphaArray) {
        
        this.r = -Math.log(Math.random());
        this.x = Math.random();
        
        // Count the number of non-zero connections
        int counter = 0;
        for (int i = 0; i < alphaArray.length; i++) {
            if (alphaArray[i] != 0)
                counter++;
        }
        
        this.connection = new int[counter];
        this.conStrength = new double[counter];
        
        int j = 0;
        for (int i = 0; i < alphaArray.length; i++) {
            if (alphaArray[i] != 0) {
                this.connection[j] = i;
                this.conStrength[j] = alphaArray[i];
                j++;
            }
        }
        
        
    }
    
    
    // Takes in an array of doubles and will turn that into
    // a connection array and a conStrength array
    public Animal(double growthRate, double population, double[] alphaArray) {
        
        this.r = growthRate;
        this.x = population;
        
        // Count the number of non-zero connections
        int counter = 0;
        for (int i = 0; i < alphaArray.length; i++) {
            if (alphaArray[i] != 0.0)
                counter++;
        }
        
        this.connection = new int[counter];
        this.conStrength = new double[counter];
        
        int j = 0;
        for (int i = 0; i < alphaArray.length; i++) {
            if (alphaArray[i] != 0) {
                this.connection[j] = i;
                this.conStrength[j] = alphaArray[i];
                j++;
            }
        }    
    }
    
    
    // Another constructor that creates a new instance of Animal
    public Animal(int numberOfSpecies, int numberOfConnections) {
        
        // Pick a growth rate and initial
        // populationi for ourselves
        this.r = -Math.log(Math.random());
        this.x = Math.random();
        this.connection = new int[numberOfConnections];
        this.conStrength = new double[numberOfConnections];
        
        // Pick out which animals we will
        // be connected to and how strongly
        for(int i = 0; i < numberOfConnections; i++) {
            connection[i] = (int)(numberOfSpecies * Math.random());
            conStrength[i] = -Math.log(Math.random());
        }
    }
    
    
    // Remove a connection to animal k
    public void removeConnection(int k) {
        
        int newLength = this.connection.length - 1;
        int[] newConnection = new int[newLength];
        double[] newConStrength = new double[newLength];
        int j = 0;
        
        for (int i = 0; i < this.connection.length; i++) {
            
            // Don't copy the kth animal
            if (this.connection[i] != k) {
                newConnection[j] = this.connection[i];
                newConStrength[j] = this.conStrength[i];
                j++;
            }
        
        }  // end of i loop
        
        this.connection = newConnection;
        this.conStrength = newConStrength;
    }
    
    
    // Return whether or not this animal is connected to a specified species j
    public boolean connected(int j) {
        
        boolean connected = false;
        
        for (int i = 0; i < this.conStrength.length; i++) {
            if (this.connection[i] == j) {
                connected = true;
            }
        }
        
        return connected;
    }
    
    // Step by a small dt into the future 
    // pop is an array of all the animals' populations 
    public void stepOnce(double[] pop, double dt) {
        
        double sum = 0;
        for (int i = 0; i < this.connection.length; i++) {
            sum = sum + conStrength[i] * pop[connection[i]];
        }
        
        double dXdT = r * x * (1 - sum);
        setX(x + dXdT * dt);
      
    }
    
    
    // Return this animal's current dxdt
    // (change in population over change in time)
    public double getdxdt(double[] pop) {
        
        double sum = 0;
        for (int i = 0; i < this.connection.length; i++) {
            sum = sum + conStrength[i] * pop[connection[i]];
        }
        
        return r * x * (1 - sum);
    }  // End of the getdxdt method
    
    
    // The only important information is this
    // species population
    public String toString() {
        return "" + this.getX();
    }
    
    
} // End of the Animal Class
