<repo_name>Xenira/GenDev<file_sep>/src/gendev.spec.ts
/// <reference path="../typings/index.d.ts" />
import { GenDev } from '../src/gendev'

describe('GenDev', () => {
    var gendev: GenDev;
    beforeEach(() => {
        gendev = new GenDev();
    });

    describe('#RegisterInput', () => {
        it('should add an input to the list', () => {
            expect(gendev.seed.inputs.length).toBe(0);
            gendev.RegisterInput("test");
            expect(gendev.seed.inputs.length).toBe(1);
        });

        it('should throw error if duplicate name', () => {
            var addTestInput = () => {
                gendev.RegisterInput("test");
            }

            addTestInput();
            expect(addTestInput).toThrow()
        });
    });

    describe('#RegisterOutput', () => {
        var addTestOutput = () => {
            gendev.RegisterOutput("test");
        }

        it('should add an output to the list', () => {
            expect(gendev.seed.outputs.length).toBe(0);
            addTestOutput();
            expect(gendev.seed.outputs.length).toBe(1);
        });

        it('should throw error if duplicate name', () => {
            addTestOutput();
            expect(addTestOutput).toThrow();
            expect(gendev.seed.outputs.length).toBe(1);
        });
    });

    describe('#RegisterEvalFunction', () => {
        it('should set the eval function', () => {
            let evalFunc = (values: Object) => {
                return 1;
            }

            expect(gendev.seed.evalFunc).toBeUndefined();
            gendev.RegisterEvalFunction(evalFunc);
            expect(gendev.seed.evalFunc).toBe(evalFunc);
        })
    });

    describe('#Initiate', () => {
        it('should create a new incubator instance', () => {
            expect(gendev.incubator).toBeUndefined();
            gendev.Initiate();
            expect(gendev.incubator).toBeDefined();
        });

        it('should start the incubator', () => {

        });
    });
})<file_sep>/README.md
# GenDev
Small project to experiment with genetic development
<file_sep>/src/core/incubator.spec.ts
/// <reference path="../../typings/index.d.ts" />
import { Incubator, GenDevOptions } from './incubator';

describe('Incubator', () => {
    var incubator: Incubator = new Incubator(null, new GenDevOptions);
});<file_sep>/src/core/gene.spec.ts
/// <reference path="../../typings/index.d.ts" />
import { Gene } from './gene'

describe('Gene', () => {
    let gene: Gene
    beforeEach(() => {
        gene = new Gene([123], 10);
    });

    describe('#ReciveInput', () => {
        beforeEach(() => {
            gene.func = () => {};
            gene.input = new Array(3);
            spyOn(gene, 'func');
        });

        it('should call func on input', () => {
            gene.ReciveInput(0, 1);
            expect(gene.func).toHaveBeenCalledTimes(1);
        });

        it('should not call func on same input', () => {
            gene.ReciveInput(0, 1);
            gene.ReciveInput(0, 1);
            gene.ReciveInput(1, 1);
            expect(gene.func).toHaveBeenCalledTimes(2);
        });
    });

    describe('#SendOutput', () => {
        beforeEach(() => {
            gene.output = () => {}
            spyOn(gene, 'output');
        });

        it('should call the output function', () => {
            gene.SendOutput('test');
            expect(gene.output).toHaveBeenCalledTimes(1);
        });

        it('should not call output again for same output', () => {
            gene.SendOutput([]);
            gene.SendOutput([]);
            expect(gene.output).toHaveBeenCalledTimes(1);
        });

        it('should not call output after burnout reached', () => {
            for (var i = 0; i < 12; i++) {
                gene.SendOutput('test' + i)         
            }
            expect(gene.output).toHaveBeenCalledTimes(10);
        })
    });
});<file_sep>/src/core/generation.spec.ts
/// <reference path="../../typings/index.d.ts" />
import { Incubator, GenDevOptions, GenDevSeed } from './incubator'
import { Generation } from './generation'

describe('Generation', () => {
    let incubator: Incubator;
    let generation: Generation;
    beforeEach(() => {
        incubator = new Incubator(null, null);
    });

    afterEach(() => {
        generation = undefined;
    });

    describe('#ResolveSequence', () => {
        it('should add genes for every "row" of the sequence', () => {
            
        });
    });
})<file_sep>/src/core/gene.ts
import { EventEmitter } from 'events'
import { Incubator } from './incubator'

export class Gene {
    func: (Array) => any;

    output: (any) => void;
    lastOutput: any = '';
    outputCount: number = 0;

    input: any[];
    inputString: string[];
    constructor(private gene: number[], private burnout?: number) {}

    ReciveInput(index: number, value: any) {
        if (!this.inputString || this.input.length != this.inputString.length) {
            this.inputString = new Array<string>(this.input.length);
        }

        let valueString = JSON.stringify(value);
        if (this.inputString[index] === valueString) { return; }

        this.inputString[index] = valueString;
        this.input[index] = value;
        this.func(this.input)
    }

    SendOutput(result: any) {
        if(this.outputCount >= this.burnout) { return; }
        this.outputCount ++;

        let stringResult = JSON.stringify(result);
        if (stringResult === this.lastOutput) { return; }

        this.lastOutput = stringResult;
        this.output(result);
    }
}

export interface IGene {
    sequence: number[];
    execute: () => void;
}<file_sep>/test/simple-add-test.ts
import { GenDev, IInput } from '../src/gendev'

var gendev: GenDev = new GenDev();

gendev.RegisterInput('var1');
gendev.RegisterInput('var2');

gendev.RegisterOutput('result');

gendev.SetEvalFunction();

function eval (inputs ) {

}<file_sep>/src/gendev.ts
import { Incubator, GenDevOptions, GenDevSeed, IInput, IOutput } from './core/incubator';

export class GenDev {
    incubator: Incubator;
    seed: GenDevSeed = new GenDevSeed();

    RegisterInput(name: String) {
        if (this.seed.inputs.some(data => 
            data.event === name)) {
            throw(`Unable to register duplicate input with name '${name}'`);
        }

        let input: IInput = {
            event: name
        }

        this.seed.inputs.push(input);
    }

    RegisterOutput(name: String) {
        if (this.seed.outputs.some(data => 
            data.event === name)) {
            throw(`Unable to register duplicate output with name '${name}'`);
        }

        let output: IOutput = {
            event: name
        };

        this.seed.outputs.push(output);
    }

    RegisterEvalFunction(evalFunction: (Object, GameDev) => Number) {
        this.seed.evalFunc = evalFunction;
    }

    Initiate(options?: GenDevOptions) {
        this.incubator = new Incubator(null, options || new GenDevOptions());
        //this.incubator.Start();
    }
}<file_sep>/src/core/functions/add.function.ts
import { IGDFunction } from '../core/function'

export class AddFunction implements IGDFunction {
    
}<file_sep>/src/core/incubator.ts
import { EventEmitter } from 'events';
import { Generation } from './generation'
export class GendevEventEmitter extends EventEmitter { }

export class Incubator {
    generations: Generation[];
    constructor(private seed: GenDevSeed, private options: GenDevOptions) {}
}

export class GenDevOptions {
    evalNumberMode: 'percent' | 'absolute' = 'percent';
}

export interface IInput {
    event: String
}

export interface IOutput {
    event: String
}

export class GenDevSeed {
    inputs: IInput[] = [];
    outputs: IOutput[] = [];
    inputEvents: EventEmitter
    outputEvents: EventEmitter
    evalFunc: (IGenDevSeed, Object, String) => Number
}<file_sep>/src/core/generation.ts
import { Gene } from './gene'
import { Incubator } from './incubator'

export class Generation {
    genes: Gene[] = [];
    constructor(private incubator: Incubator, sequence: number[][]) {
        this.ResolveSequence(sequence);
    }

    ResolveSequence(sequence: number[][]) {
        let output: number[] = sequence.pop();
        for (var i = 0; i < sequence.length; i++) {
            var element = sequence[i];
            var gene = new Gene(element);
            
        }
    }
}<file_sep>/src/core/function.ts
import { IGene } from './gene'

export class IGDFunction implements IGene {
    sequence: number[];
    input: any;
    output: any;

    execute() {

    }
}