// Path: src/ch/epfl/bigdata/ts/dataparser/Tick.java
// public class Tick implements Comparable<Tick> {
// 
//     long orderID;
//     long timestamp;
//     char type;
//     long numberShares;
//     double price;
// 
//     public long getOrderID() {
//         return orderID;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public char getType() {
//         return type;
//     }
// 
//     public long getNumberShares() {
//         return numberShares;
//     }
// 
//     public double getPrice() {
//         return price;
//     }
// 
//     public Tick(long orderID, long timestamp, char type, long numberShares, long price) {
//         this.orderID = orderID;
//         this.timestamp = timestamp;
//         this.type = type;
//         this.numberShares = numberShares;
//         this.price = price / 10000;
//     }
// 
//     public Tick(long orderID, long timestamp, long numberShares, long price) {
//         this.orderID = orderID;
//         this.timestamp = timestamp;
//         this.numberShares = numberShares;
//         this.price = price / 10000.0;
//     }
// 
// 
//     @Override
//     public int compareTo(Tick o) {
//         if (this.timestamp < o.timestamp)
//             return -1;
//         else if (this.timestamp==o.timestamp)
//              return  0;
// 
//         return 1;
//     }
// 
//     @Override
//     public String toString() {
//         return timestamp +
//                 "," + type +
//                 "," + numberShares +
//                 "," + price;
//     }
// }
// 
// Path: src/ch/epfl/bigdata/ts/ga/Chromosome.java
// public class Chromosome {
// 
// 	private List<Gene> genes; //TODO: check if HashMap of genes would be more suitable
// 	private double fitness = 0, fitnessSelection = 0;
//     private int numberOfTransactions=0;
// 
// 	public Chromosome(List<Gene> genes) { //TODO: organize Gene and Chromosome
// 		this.genes = genes;
// 	}
// 
// 	public Chromosome(Chromosome chr) {
// 		genes = new ArrayList<Gene>();
// 		for(int i = 0; i < chr.genes.size(); i++) {
// 			genes.add(new Gene(chr.genes.get(i)));
// 		}
// 	}
// 
// 	public double getFitness() {
// 		return fitness;
// 	}
// 
// 	public void setFitness(double fitness) {
// 		this.fitness = fitness;
// 	}
// 
// 	public double getFitnessSelection() {
// 		return fitnessSelection;
// 	}
// 
// 	public void setFitnessSelection(double fitnessSelection) {
// 		this.fitnessSelection = fitnessSelection;
// 	}
// 
// 	public int getNumGenes() {
// 		return genes.size();
// 	}
// 
// 	public List<Gene> getGenes() {
// 		return genes;
// 	}
// 
//     public int getNumberOfTransactions() {
//         return numberOfTransactions;
//     }
// 
//     public void setNumberOfTransactions(int numberOfTransactions) {
//         this.numberOfTransactions = numberOfTransactions;
//     }
// 
// 
// 	public void copyGenes(int startPoint, int endPoint, Chromosome child) {
// 		for(int i = startPoint; i < endPoint; i++) {
// 			child.genes.add(genes.get(i));
// 		}
// 	}
// 
// 	public void addGene(Gene gene) {
// 		genes.add(gene);
// 	}
// 
// 	public String toString() {
// 		StringBuilder sb = new StringBuilder();
// 		for(int i = 0; i < genes.size(); i++) {
// 			sb.append(genes.get(i));
// 		}
// 		return sb.toString();
// 	}
// }
// 
// Path: src/ch/epfl/bigdata/ts/ga/util/Range.java
// public class Range {
// 	public static Random R = new Random(System.currentTimeMillis());
//     private double upper, lower;
// 
//     public Range(double lower, double upper) {
//         this.upper = upper;
//         this.lower = lower;
//     }
// 
//     public double getLower() {
//         return lower;
//     }
// 
//     public double getUpper() {
//         return upper;
//     }
// 
// }


import ch.epfl.bigdata.ts.dataparser.Tick;
import ch.epfl.bigdata.ts.ga.Chromosome;
import ch.epfl.bigdata.ts.ga.util.Range;
import java.util.LinkedList;
import java.util.List;
package ch.epfl.bigdata.ts.pattern.fitness;



/**
 * Created by Ena, Poly on 5/10/2014.
 */

public class HeadAndShoulders extends FitnessFunction {

    public static final int GENE_BOTTOM_SHOULDER = 0;
    public static final int GENE_SHOULDER_HEAD = 1;
    public static final int GENE_MAX_DIFF_BOTTOMS = 2;
    public static final int GENE_PROTECT_BUY_GAIN = 3;
    public static final int GENE_PROTECT_BUY_LOSS = 4;
    public static final int GENE_TREND_STRENGTH = 5;

    private double shoulder1, shoulder2;
    private double head;
    private double bottom1, bottom2;
    private double bottom1Ts, bottom2Ts;
    private double necklinea, necklineb;

    private double buyLoss;
    private double buyGain;

    private boolean first = true;

    public HeadAndShoulders(int numOfDays, int startingAmountOfMoney, int numOfDaysInGeneration, int startForData, long time) {
        super(numOfDays, startingAmountOfMoney, numOfDaysInGeneration, startForData, time);
    }

    public FitnessFunction constructorWrapper(int numOfDays, int startingAmountOfMoney, int numOfDaysInGeneration, int startForData, long time) {
        return new HeadAndShoulders(numOfDays, startingAmountOfMoney, numOfDaysInGeneration, startForData, time);
    }

// Path: src/ch/epfl/bigdata/ts/dataparser/Tick.java
// public class Tick implements Comparable<Tick> {
// 
//     long orderID;
//     long timestamp;
//     char type;
//     long numberShares;
//     double price;
// 
//     public long getOrderID() {
//         return orderID;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public char getType() {
//         return type;
//     }
// 
//     public long getNumberShares() {
//         return numberShares;
//     }
// 
//     public double getPrice() {
//         return price;
//     }
// 
//     public Tick(long orderID, long timestamp, char type, long numberShares, long price) {
//         this.orderID = orderID;
//         this.timestamp = timestamp;
//         this.type = type;
//         this.numberShares = numberShares;
//         this.price = price / 10000;
//     }
// 
//     public Tick(long orderID, long timestamp, long numberShares, long price) {
//         this.orderID = orderID;
//         this.timestamp = timestamp;
//         this.numberShares = numberShares;
//         this.price = price / 10000.0;
//     }
// 
// 
//     @Override
//     public int compareTo(Tick o) {
//         if (this.timestamp < o.timestamp)
//             return -1;
//         else if (this.timestamp==o.timestamp)
//              return  0;
// 
//         return 1;
//     }
// 
//     @Override
//     public String toString() {
//         return timestamp +
//                 "," + type +
//                 "," + numberShares +
//                 "," + price;
//     }
// }
// 
// Path: src/ch/epfl/bigdata/ts/ga/Chromosome.java
// public class Chromosome {
// 
// 	private List<Gene> genes; //TODO: check if HashMap of genes would be more suitable
// 	private double fitness = 0, fitnessSelection = 0;
//     private int numberOfTransactions=0;
// 
// 	public Chromosome(List<Gene> genes) { //TODO: organize Gene and Chromosome
// 		this.genes = genes;
// 	}
// 
// 	public Chromosome(Chromosome chr) {
// 		genes = new ArrayList<Gene>();
// 		for(int i = 0; i < chr.genes.size(); i++) {
// 			genes.add(new Gene(chr.genes.get(i)));
// 		}
// 	}
// 
// 	public double getFitness() {
// 		return fitness;
// 	}
// 
// 	public void setFitness(double fitness) {
// 		this.fitness = fitness;
// 	}
// 
// 	public double getFitnessSelection() {
// 		return fitnessSelection;
// 	}
// 
// 	public void setFitnessSelection(double fitnessSelection) {
// 		this.fitnessSelection = fitnessSelection;
// 	}
// 
// 	public int getNumGenes() {
// 		return genes.size();
// 	}
// 
// 	public List<Gene> getGenes() {
// 		return genes;
// 	}
// 
//     public int getNumberOfTransactions() {
//         return numberOfTransactions;
//     }
// 
//     public void setNumberOfTransactions(int numberOfTransactions) {
//         this.numberOfTransactions = numberOfTransactions;
//     }
// 
// 
// 	public void copyGenes(int startPoint, int endPoint, Chromosome child) {
// 		for(int i = startPoint; i < endPoint; i++) {
// 			child.genes.add(genes.get(i));
// 		}
// 	}
// 
// 	public void addGene(Gene gene) {
// 		genes.add(gene);
// 	}
// 
// 	public String toString() {
// 		StringBuilder sb = new StringBuilder();
// 		for(int i = 0; i < genes.size(); i++) {
// 			sb.append(genes.get(i));
// 		}
// 		return sb.toString();
// 	}
// }
// 
// Path: src/ch/epfl/bigdata/ts/ga/util/Range.java
// public class Range {
// 	public static Random R = new Random(System.currentTimeMillis());
//     private double upper, lower;
// 
//     public Range(double lower, double upper) {
//         this.upper = upper;
//         this.lower = lower;
//     }
// 
//     public double getLower() {
//         return lower;
//     }
// 
//     public double getUpper() {
//         return upper;
//     }
// 
// }


// Path: src/ch/epfl/bigdata/ts/pattern/fitness/HeadAndShoulders.java
import ch.epfl.bigdata.ts.dataparser.Tick;
import ch.epfl.bigdata.ts.ga.Chromosome;
import ch.epfl.bigdata.ts.ga.util.Range;
import java.util.LinkedList;
import java.util.List;

package ch.epfl.bigdata.ts.pattern.fitness;



/**
 * Created by Ena, Poly on 5/10/2014.
 */

public class HeadAndShoulders extends FitnessFunction {

    public static final int GENE_BOTTOM_SHOULDER = 0;
    public static final int GENE_SHOULDER_HEAD = 1;
    public static final int GENE_MAX_DIFF_BOTTOMS = 2;
    public static final int GENE_PROTECT_BUY_GAIN = 3;
    public static final int GENE_PROTECT_BUY_LOSS = 4;
    public static final int GENE_TREND_STRENGTH = 5;

    private double shoulder1, shoulder2;
    private double head;
    private double bottom1, bottom2;
    private double bottom1Ts, bottom2Ts;
    private double necklinea, necklineb;

    private double buyLoss;
    private double buyGain;

    private boolean first = true;

    public HeadAndShoulders(int numOfDays, int startingAmountOfMoney, int numOfDaysInGeneration, int startForData, long time) {
        super(numOfDays, startingAmountOfMoney, numOfDaysInGeneration, startForData, time);
    }

    public FitnessFunction constructorWrapper(int numOfDays, int startingAmountOfMoney, int numOfDaysInGeneration, int startForData, long time) {
        return new HeadAndShoulders(numOfDays, startingAmountOfMoney, numOfDaysInGeneration, startForData, time);
    }

    protected int trade(Tick transaction, Chromosome chr, boolean logForViz, StringBuilder vizLog, int order) {