 
/*********************************************************************** 
 * This is the basic class for people in our simulation. Voters,  
 * Candidates, and Representatives are all subclasses of this Individual  
 * class.  These are the basic attributes that each person will have. 
 ***********************************************************************/ 
public class Individual { 
    public int[] ideology;       // Vector of positions on the Issues 
    public double[] strengths;   // Vector of Weights associated with ideology 
    public int[] votingRecord;   // Binary vector for votes on proposed issues 
    public int[] partyTag;       // Binary vector recording current party 
    public String name; 
    public District parent; 
 
    // Finds the similarity between the incoming tag and the  
    // partyTag of the Individual. Returns the deviation from the expected
    // similartiy of partyTag.length/2
    public double findSimilarity(int[] otherTag) { 
	 
	double tagSimilarity = 0; 
	for (int i=0; i<partyTag.length; i++) 
	    if (partyTag[i] == otherTag[i]) 
		tagSimilarity++; 
	tagSimilarity = tagSimilarity - (partyTag.length / 2); 
	tagSimilarity = tagSimilarity / (partyTag.length / 2); 
	return tagSimilarity; 
    } 
 
    // Find the separation between this individual and another
    // ideology vector using normalized euclidean distance.
    public double findSeparation(int[] otherIdeo) { 

        double separation = 0; 
        for (int i=0; i<ideology.length; i++) 
            separation += Math.pow((ideology[i] - otherIdeo[i]), 2); 
	separation = Math.sqrt(separation); 
	return separation; 
    } 
  
    // Displays the Individual's tag to the screen 
    public void showTag() { 
	for (int i=0; i<partyTag.length; i++) 
	    System.out.print(partyTag[i]); 
	System.out.println(""); 
    } 
 
    // Displays the Individual's votingRecord to the screen 
    public void showRecord() { 
	for (int i=0; i<votingRecord.length; i++) 
	    System.out.print(votingRecord[i]); 
	System.out.println(""); 
    } 
 
    // Displays the Individual's ideology to the screen 
    public void showIdeology() { 
	for (int i=0; i<ideology.length; i++) 
	    System.out.print(ideology[i]); 
	System.out.print("\t"); 
	// System.out.println(""); 
    } 

    // Outputs the number of 1's as well as the Pascal scaling
    // of the Individual's tag 
    public void CrunchTag() { 

	// Find number of ones
	int ones = 0; 
	for (int i=0; i<partyTag.length; i++) { 
	    if (partyTag[i] == 1) 
		ones++; 
	} 
	System.out.print(ones + "\t"); 
 
	// Give them a number depending on how many ones there are
	if (ones <= partyTag.length / 2) {
	    if (ones == 0) 
		System.out.print(.5); 
	    else { 
		long index = levelIndex(ones,partyTag.length-1); 
		long possible = Utilities.Pascal[partyTag.length][ones]; 
		System.out.print((double)index/(double)possible); 
	    } 
	}
	else {
	    if (ones == partyTag.length) 
		System.out.print(.5); 
	    else { 
		fliptag(); 
		long index = levelIndex(partyTag.length-ones, 
					partyTag.length-1); 
		long possible = Utilities.Pascal[partyTag.length]  
						[partyTag.length-ones]; 
		System.out.print((double)(possible-index)/(double)possible); 
		fliptag(); 
	    } 
	}
    }
	
    // Finds the Pascal index of the tag given the level
    public long levelIndex(int level, int n) { 
	if (level == 1) { 
	    for (int i=0; i<n+1; i++) { 
		if (partyTag[i] == 1) { 
		    return ((long)(i+1)); 
		} 
	    } 
	    System.out.println("Error!!"); 
	    return(0); 
	} 
	 
	long y = 0; 
	if (partyTag[n] == 1) { 
	    y = Utilities.Pascal[n+1][level] -  
		Utilities.Pascal[n][level-1] +  
		levelIndex(level-1, n-1); 
	    return (y); 
	} 
	else { 
	    y = levelIndex(level, n-1); 
	    return (y); 
	} 
    } 
 
    // Flips all the 1's and 0's of the tag. (used in Pascal scaling)
    public void fliptag() { 
	for (int i=0; i<partyTag.length; i++) 
	    partyTag[i] = (partyTag[i] + 1) % 2; 
    }  
} 

