
from pyevolve import G2DList
from pyevolve import GSimpleGA
from pyevolve import Selectors
from pyevolve import Mutators
from pyevolve import Initializators
from pyevolve import GAllele

from pyevolve import Crossovers

# fitness is sum of differences to target radius over some time period
from math import ceil
from chimp import QuietChimpanzee, Chimpanzee
from simulation import run_simulation
from translated_binaries import bin1

def to_float(m, *digits):
    return float(
        ''.join([str(i) for i in digits[:m]]) +
        '.' + 
        ''.join([str(i) for i in digits[m:]])
    )

def to_int(*digits):
    return int(''.join([str(i) for i in digits]))

X = 0x2
Y = 0x3

def flight_plan(chromosome):
    start_burn = 0
    stop_burn = to_int(*chromosome[0][:5])
    
    start_x = to_float(*chromosome[1])
    start_y = to_float(*chromosome[2])
    stop_x = to_float(*chromosome[3])
    stop_y = to_float(*chromosome[4])
    
    return [
        (start_burn, {X:start_x, Y:start_y}),
        (start_burn+1, {X:0.0, Y:0.0}),
        (stop_burn, {X:stop_x, Y:stop_y}),
        (stop_burn+1, {X:0.0, Y:0.0}),
    ]

def run_search(generations):
    def eval_func(chromosome):
        
        print flight_plan
        chimp = QuietChimpanzee(*flight_plan)
        sim_score = run_simulation( 
            bin1.OrbitalVirtualMachine(), 
            1002, 
            chimp,
            max = 10000
        )
        
        # inverse of the average distance from the target
        score = chimp.t / chimp.sum_distance
        print 'fitness:', score
        return score
        
    # Genome instance
    genome = G2DList.G2DList(5, 8)
    genome.setParams(
        rangemin = 0, 
        rangemax = 9
    )

    genome.evaluator.set(eval_func)

    #genome.mutator.set(Mutators.G1DListMutatorAllele)
    #genome.initializator.set(Initializators.G1DListInitializatorAllele)

    genome.crossover.set(Crossovers.G2DListCrossoverSingleHPoint)
    genome.mutator.set(Mutators.G2DListMutatorIntegerGaussian)


    # Genetic Algorithm Instance
    ga = GSimpleGA.GSimpleGA(genome)
    ga.selector.set(Selectors.GRouletteWheel)
    ga.setGenerations(generations)

    ga.evolve(freq_stats=50)

    # Best individual
    fittest = ga.bestIndividual()
    print fittest
    
    flight_plan = []
    t = 0
    for a,b,c in fittest.genomeList:
        t += abs(ceil(a))
        flight_plan.append((t, { 0x2: b, 0x3: c}))
    chimp = Chimpanzee(*flight_plan)
    run_simulation( 
        bin1.OrbitalVirtualMachine(), 
        1002, 
        chimp
    )
    
    return fittest
    