package com.scottlangley.elect98;
/* Copyright 1998 by Scott Langley.
All rights reserved.
*/
public class Congress {
  State[] states = State.getStates();
  short numberOfHouseRepublicans;
  short numberOfHouseDemocrats;
  short numberOfSenateRepublicans;
  short numberOfSenateDemocrats;
  public Congress(java.io.DataInputStream dataIn) throws java.io.IOException {
    State state;
    for(int i=0; i<50;i++){
      state = states[i];
      state.addRecords(dataIn);
    }
  }
//  public void elect(Parameters parameters){
  public void elect(short[] parameters){
    numberOfHouseDemocrats=numberOfHouseRepublicans=numberOfSenateDemocrats=numberOfSenateRepublicans=0;
    State state;
    for(int i=0; i<50;i++){
      state = states[i];
      state.elect(parameters);
      numberOfHouseDemocrats += state.numberOfHouseDemocrats;
      numberOfHouseRepublicans += state.numberOfHouseRepublicans;
      numberOfSenateDemocrats += state.numberOfSenateDemocrats;
      numberOfSenateRepublicans += state.numberOfSenateRepublicans;
    }
  }
  public void electDetailed(short[] parameters, java.awt.TextArea resultsText){
    resultsText.setText("KEY:\n");
    resultsText.appendText("State Abbreviation\n");
    resultsText.appendText("Party of Incumbent\n");
    resultsText.appendText("District\n");
    resultsText.appendText("Base Percent From Last Election\n");
    resultsText.appendText("Change in Advantage of Incumbency (+ = Boost Incumbents)\n");
    resultsText.appendText("Change in Party Support (+ = Boost Republican)\n");
    resultsText.appendText("Freshmen Incumbency Advantage (+ = Boost Freshmen)\n");
    resultsText.appendText("Gain/Loss for Open Seat( - = Loss to Vacating Party)\n");
    resultsText.appendText("Total\n");
    resultsText.appendText("Greater than Threshold Needed to Win?\n");
    resultsText.appendText("Party of Winner\n");
    resultsText.appendText("(* = seat changed parties)\n\n");
    State state;
    for(int i=0; i<50;i++){
      state = states[i];
      state.electDetailed(parameters, resultsText);
    }
  }

/*  public void displayElected(){
    System.out.println("Predicted Congress\n");
    System.out.println("House:  Democrats: "+numberOfHouseDemocrats +" Republicans: "+numberOfHouseRepublicans);
    System.out.println("Senate: Democrats: "+numberOfSenateDemocrats+" Republicans: "+numberOfSenateRepublicans);
    System.out.println("\n\n");
  }*/
  public short getHouseDemocrats(){
    return numberOfHouseDemocrats;
  }
  public short getHouseRepublicans(){
    return numberOfHouseRepublicans;
  }
  public short getSenateRepublicans(){
    return numberOfSenateRepublicans;
  }
  public short getSenateDemocrats(){
    return numberOfSenateDemocrats;
  }
}
class State {
  String stateName;
  byte numberOfHouseRepublicans;
  byte numberOfHouseDemocrats;
  byte numberOfSenateRepublicans;
  byte numberOfSenateDemocrats;
  DataRecord[] dataRecords;
  int numberOfDistricts;
  String stateAbbreviation;
  public State(String stateName, String stateAbbreviation, int numberOfDistricts) {
    this.stateName = stateName;
    this.stateAbbreviation = stateAbbreviation;
    this.numberOfDistricts = numberOfDistricts;
    dataRecords = new DataRecord[numberOfDistricts+2];
  }
  public void addRecords(java.io.DataInputStream dataIn) throws java.io.IOException {
    addSenateDataRecord(0,new DataRecord(dataIn));
    addSenateDataRecord(1,new DataRecord(dataIn));
    for(int i=2; i<numberOfDistricts+2; i++)
      addHouseDataRecord(i,new DataRecord(dataIn));
  }
  void addSenateDataRecord(int index,DataRecord dataRecord){
    this.dataRecords[index] = dataRecord;
  }
  void addHouseDataRecord(int index,DataRecord dataRecord){
    this.dataRecords[index] = dataRecord;
  }
  public String getStateName(){
    return stateName;
  }
  public void elect(short[] parameters){
//  public void elect(Parameters parameters){
    numberOfHouseDemocrats = numberOfHouseRepublicans = numberOfSenateDemocrats = numberOfSenateRepublicans=0;
    electSenator(dataRecords[0],parameters);
    electSenator(dataRecords[1],parameters);
    for(int i=2; i<numberOfDistricts+2; i++)
      electRepresentative(dataRecords[i],parameters);
  }
  public void electDetailed(short[] parameters, java.awt.TextArea resultsText){


    resultsText.appendText(stateAbbreviation+"   S"+ electDetailedSenator(dataRecords[0],parameters)+"\n");
    resultsText.appendText(stateAbbreviation+"   S"+ electDetailedSenator(dataRecords[1],parameters)+"\n");

    for(int i=2; i<numberOfDistricts+2; i++)   {
      String districtOut;
      if(i>10)
        districtOut = " "+(i-1);
      else
        districtOut = "   "+(i-1);
      resultsText.appendText(stateAbbreviation+districtOut+ electDetailedRepresentative(dataRecords[i],parameters)+"\n");
    }
  }

//  public void electSenator(DataRecord seat, Parameters parameters){
  public void electSenator(DataRecord seat, short[] parameters){
    if(seat.isSeatUpForElection()) {
        seat.elect(parameters);
//      seat.elect(parameters.getRepublicanAdvantage(),parameters.getIncumbentAdvantage(),parameters.openSeatDrop,parameters.freshmanIncumbentAdvantage);
      if(seat.isWinnerRepublican())
        numberOfSenateRepublicans++;
      else
        numberOfSenateDemocrats++;
    }
    else{
      if(seat.isIncumbentRepublican())
          numberOfSenateRepublicans++;
      else
          numberOfSenateDemocrats++;
    }
  }
  public String electDetailedSenator(DataRecord seat, short[] parameters){
    if(seat.isSeatUpForElection()) {
        return seat.electDetailed(parameters);
    }
    else{
        return seat.getIncumbentSenator();
    }
  }

  public void electRepresentative(DataRecord seat, short[] parameters){
      seat.elect(parameters);
      if(seat.isWinnerRepublican())
        numberOfHouseRepublicans++;
      else if(seat.isWinnerDemocrat())
        numberOfHouseDemocrats++;
  }
  public String electDetailedRepresentative(DataRecord seat, short[] parameters){
//  public void electRepresentative(DataRecord seat, Parameters parameters){
//      seat.elect(parameters.getRepublicanAdvantage(),parameters.getIncumbentAdvantage(),parameters.openSeatDrop,parameters.freshmanIncumbentAdvantage);
      return  seat.electDetailed(parameters);
  }

  public static final State[] getStates() {
    	State[] states = new State[50];
	    states[0] = new State("Alabama","AL",7);
    	states[1] = new State("Alaska","AK",1);
    	states[2] = new State("Arizona","AZ",6);
    	states[3] = new State("Arkansas","AR",4);
    	states[4] = new State("California","CA",52);
    	states[5] = new State("Colorado","CO",6);
    	states[6] = new State("Connecticut","CT",6);
    	states[7] = new State("Delaware","DE",1);
    	states[8] = new State("Florida","FL",23);
    	states[9] = new State("Georgia","GA",11);
    	states[10] = new State("Hawaii","HI",2);
    	states[11] = new State("Idaho","ID",2);
    	states[12] = new State("Illinois","IL",20);
    	states[13] = new State("Indiana","IN",10);
    	states[14] = new State("Iowa","IA",5);
    	states[15] = new State("Kansas","KS",4);
    	states[16] = new State("Kentucky","KY",6);
    	states[17] = new State("Louisiana","LA",7);
    	states[18] = new State("Maine","ME",2);
    	states[19] = new State("Maryland","MD",8);
    	states[20] = new State("Massachusetts","MA",10);
    	states[21] = new State("Michigan","MI",16);
    	states[22] = new State("Minnesota","MN",8);
    	states[23] = new State("Mississippi","MS",5);
    	states[24] = new State("Missouri","MO",9);
    	states[25] = new State("Montana","MT",1);
    	states[26] = new State("Nebraska","NE",3);
    	states[27] = new State("Nevada","NV",2);
    	states[28] = new State("New Hampshire","NH",2);
    	states[29] = new State("New Jersey","NJ",13);
    	states[30] = new State("New Mexico","NM",3);
    	states[31] = new State("New York","NY",31);
    	states[32] = new State("North Carolina","NC",12);
    	states[33] = new State("North Dakota","ND",1);
    	states[34] = new State("Ohio","OH",19);
    	states[35] = new State("Oklahoma","OK",6);
    	states[36] = new State("Oregon","OR",5);
    	states[37] = new State("Pennsylvania","PA",21);
    	states[38] = new State("Rhode Island","RI",2);
    	states[39] = new State("South Carolina","SC",6);
    	states[40] = new State("South Dakota","SD",1);
    	states[41] = new State("Tennessee","TN",9);
    	states[42] = new State("Texas","TX",30);
    	states[43] = new State("Utah","UT",3);
    	states[44] = new State("Vermont","VT",1);
    	states[45] = new State("Virginia","VA",11);
    	states[46] = new State("Washington","WA",9);
    	states[47] = new State("West Virginia","WV",3);
    	states[48] = new State("Wisconsin","WI",9);
    	states[49] = new State("Wyoming","WY",1);
      return states;
	}
}
class DataRecord {
  //Incoming Values
  public boolean uncontested;
  public boolean incumbentIsRunning;
  public boolean incumbentIsFreshman;
  public boolean incumbentIsDemocrat;
  public boolean incumbentIsRepublican;
  public boolean seatUpForElection;
  public short incumbentPercent;
//  public short republicanPercent;
//  public short democraticPercent;
  //Value to be Determined
  public boolean winnerIsRepublican;
  public boolean winnerIsDemocrat;
  public boolean incumbentDefeated;
  public boolean freshman;
  public DataRecord(java.io.DataInputStream dataIn) throws java.io.IOException {
    seatUpForElection = dataIn.readBoolean();
    incumbentIsRunning = dataIn.readBoolean();
    incumbentIsFreshman = dataIn.readBoolean();
    incumbentIsDemocrat = dataIn.readBoolean();
    incumbentIsRepublican = dataIn.readBoolean();
    uncontested = dataIn.readBoolean();
    incumbentPercent = dataIn.readShort();
//    democraticPercent = dataIn.readShort();
//    republicanPercent = dataIn.readShort();
  }
//  public void elect(short republicanAdvantage, short incumbentAdvantage,
//    short openSeatDrop, short freshmanIncumbentAdvantage){
  public void elect(short[] parameters){
  short republicanAdvantage = parameters[0];
  short incumbentAdvantage = parameters[1];
  short openSeatDrop = parameters[2];
  short freshmanIncumbentAdvantage = parameters[3];
    if(uncontested)
      electUncontested();
    else {
      short incumbentPercent = this.incumbentPercent;
//      short challengerPercent;
//      short openSeatDrop =42;
//      short freshmanIncumbentAdvantage = 20;
//      newDemocraticPercent = (short)(democraticPercent - republicanAdvantage);
//      newRepublicanPercent = (short)(republicanPercent + republicanAdvantage);
      if(incumbentIsRepublican){
        incumbentPercent += republicanAdvantage;

//        incumbentPercent = newRepublicanPercent;
//        challengerPercent = newDemocraticPercent;
      }
      else{
        incumbentPercent -=  republicanAdvantage;

//        incumbentPercent =  newDemocraticPercent;
//        challengerPercent = newRepublicanPercent;
      }
      if(incumbentIsRunning){
        incumbentPercent += incumbentAdvantage;
        //challengerPercent -= incumbentAdvantage;
        if(incumbentIsFreshman){
          incumbentPercent += freshmanIncumbentAdvantage;
          //challengerPercent -= freshmanIncumbentAdvantage;
        }
      }
      else{
        incumbentPercent -= openSeatDrop;
        //challengerPercent += openSeatDrop;
      }
      pickWinner(incumbentPercent);
      //pickWinner(incumbentPercent,challengerPercent);
    }
  }
  void electUncontested(){
      if(incumbentIsDemocrat){
        winnerIsDemocrat = true;
        winnerIsRepublican = false;
      }
      else if(incumbentIsRepublican){
        winnerIsDemocrat = false;
        winnerIsRepublican = true;
      }
      else{
        winnerIsDemocrat = false;
        winnerIsRepublican = false;
      }
      incumbentDefeated = false;
      freshman = false;
  }
  void pickWinner(short incumbentPercent){
    if(incumbentPercent >= 500){
      //Republican Incumbent Won
      if(incumbentIsRepublican){
        winnerIsDemocrat = false;
        winnerIsRepublican = true;
      }
      //Democratic Incumbent Won
      else{
        winnerIsDemocrat = true;
        winnerIsRepublican = false;
      }
      if(incumbentIsRunning)
        freshman = false;
      else
        freshman = true;
      incumbentDefeated = false;
      if(incumbentPercent >=1000)
        incumbentPercent=999;

    }
    else{
      //Democratic Challenger Won
      if(incumbentIsRepublican){
        winnerIsDemocrat = true;
        winnerIsRepublican = false;
      }
      //Republican Challenger Won
      else {
        winnerIsDemocrat = false;
        winnerIsRepublican = true;
      }
      //if(incumbentIsRunning)
        incumbentDefeated = true;
      //else
        //incumbentDefeated = false;
        freshman = true;
    }
  }
  public String electDetailed(short[] parameters){
  short republicanAdvantage = parameters[0];
  short incumbentAdvantage = parameters[1];
  short openSeatDrop = parameters[2];
  short freshmanIncumbentAdvantage = parameters[3];
  StringBuffer returnBuffer = new StringBuffer();
    if(incumbentIsDemocrat)
      returnBuffer.append(" INC=D ");
    else if(incumbentIsRepublican)
      returnBuffer.append(" INC=R ");
    else
      returnBuffer.append(" INC=I ");
    if(uncontested){
      electUncontested();
      returnBuffer.append(" Uncontested                                                              ");
    }
    else {
      short incumbentPercent = this.incumbentPercent;
      returnBuffer.append(percentize(incumbentPercent,false));
//      short challengerPercent;
//      short openSeatDrop =42;
//      short freshmanIncumbentAdvantage = 20;
//      newDemocraticPercent = (short)(democraticPercent - republicanAdvantage);
//      newRepublicanPercent = (short)(republicanPercent + republicanAdvantage);
      if(incumbentIsRepublican){
        incumbentPercent += republicanAdvantage;
        returnBuffer.append(percentize(republicanAdvantage));
//        incumbentPercent = newRepublicanPercent;
//        challengerPercent = newDemocraticPercent;
      }
      else{
        incumbentPercent -=  republicanAdvantage;
        returnBuffer.append(percentize((-1*republicanAdvantage)));

//        incumbentPercent =  newDemocraticPercent;
//        challengerPercent = newRepublicanPercent;
      }
      if(incumbentIsRunning){
        incumbentPercent += incumbentAdvantage;
        returnBuffer.append(percentize(incumbentAdvantage));
        //challengerPercent -= incumbentAdvantage;
        if(incumbentIsFreshman){
          incumbentPercent += freshmanIncumbentAdvantage;
          returnBuffer.append(percentize(freshmanIncumbentAdvantage));
        }
        else
          returnBuffer.append(percentize(0));
        returnBuffer.append(percentize(0));
      }
      else{
        returnBuffer.append(percentize(0));
        returnBuffer.append(percentize(0));
        returnBuffer.append(percentize(-openSeatDrop));
        incumbentPercent -= openSeatDrop;
        //challengerPercent += openSeatDrop;
      }
      pickWinner(incumbentPercent);
      returnBuffer.append(" = "+percentize(incumbentPercent,false)+" > 50.0 ? ");
      if(incumbentDefeated)
        returnBuffer.append("F ");
      else
        returnBuffer.append("T ");
      //pickWinner(incumbentPercent,challengerPercent);
    }
    returnBuffer.append(partyOfWinner());
    if(incumbentDefeated)
      returnBuffer.append(" *");
    return returnBuffer.toString();
  }
  public String percentize(int number){
    return percentize(number, true);
  }
  public String percentize(int number, boolean addPlus){
    StringBuffer sBuffer = new StringBuffer();
    //sBuffer.append(' ');
    String sign ="";
    if(number<0){
        sign=" -";
        number = Math.abs(number);
    }
    else if(addPlus){
      sign="+";
    }
    if(number<10) {
      sBuffer.append("  0.");
      sBuffer.append(number);
    }
    else{
      if(number<100)  {
        sBuffer.append("  ");
        sBuffer.append(number);
        sBuffer.insert(3,'.');
      }
      else{
        if(number>=1000)
          number = 999;
        sBuffer.append(number);
        sBuffer.insert(2,'.');
      }
    }
    return " "+sign+sBuffer.toString();
  }
  public String partyOfWinner(){
    if(winnerIsDemocrat)
      return "Outcome = D";
    else if(winnerIsRepublican)
      return "Outcome = R";
    else
      return " Outcome = I";
  }
  public boolean isSeatUpForElection(){
    return seatUpForElection;
  }
  public boolean isWinnerRepublican(){
    return winnerIsRepublican;
  }
  public boolean isWinnerDemocrat(){
    return winnerIsDemocrat;
  }
  public boolean isIncumbentDemocrat(){
    return incumbentIsDemocrat;
  }
  public boolean isIncumbentRepublican(){
    return incumbentIsRepublican;
  }
  public String getIncumbentSenator(){
    String beginString;
    if(incumbentIsDemocrat)
      beginString = "D";
    else
      beginString = "R";
    return " INC="+beginString+"  Not up for election                                                                         "+beginString;
  }
}

/*class Parameters {
  short republicanAdvantage;
  short incumbentAdvantage;
  short openSeatDrop;
  short freshmanIncumbentAdvantage;
  public Parameters(int republicanAdvantage, int incumbentAdvantage,
    int openSeatDrop, int freshmanIncumbentAdvantage) {
    this.republicanAdvantage = (short)republicanAdvantage;
    this.incumbentAdvantage = (short)incumbentAdvantage;
    this.openSeatDrop = (short)openSeatDrop;
    this.freshmanIncumbentAdvantage = (short)freshmanIncumbentAdvantage;
  }
  public short getRepublicanAdvantage(){
    return republicanAdvantage;
  }
  public short getIncumbentAdvantage(){
    return incumbentAdvantage;
  }

}*/

