# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/04_properties.ipynb (unless otherwise specified).

__all__ = ['generate_evolvers', 'generate_option_files', 'additional_properties', 'write_to_file',
           'structure_parameters', 'configurable_parameters', 'description', 'fixed_parameters']

# Cell
import os

# Cell
def generate_evolvers(iters, envs=None, collection=None, configs=None, properties=None, varieties=None):
    for env in envs:
        if not os.path.isdir(env):
            os.mkdir(env)

    for env in envs:
        num_actions = varieties[env]['num_actions']
        nevals = varieties[env]['nevals']
        archs = varieties[env]['archs']
        for arch in archs:
            key = '_'.join((env,arch['name']))
            print(key)
            config = configs[key]
            generate_option_files(iters, env, num_actions, arch, config, nevals, properties, collection)


# Cell
def generate_option_files(iters, env, num_actions, arch, config, nevals, properties, collection):
    arch_name = arch['name']
    inputs_names = arch['inputs_names']
    ppars = ''

    collectors=collection[env]['arch'][arch_name]['collectors']
    responses=collection[env]['arch'][arch_name]['responses']
    weights=collection[env]['arch'][arch_name]['weights']
    structs=collection[env]['arch'][arch_name]['structs']


    for collector in collectors:
        for response in responses:
            for weight in weights:
                for struct in structs:
                    desc, filename = description(collector,response, weight, struct, arch_name)
                    fpars = fixed_parameters(env, arch, num_actions)
                    cpars = configurable_parameters(env, config, collector, response, nevals)
                    ppars = additional_properties(properties, response, collector)
                    spars = structure_parameters(collector,response, weight, struct, arch_name)
                    display = f'### Display\n\ninputs_names = {inputs_names}\n'

                    text = '\n'.join((desc, fpars, cpars, ppars, spars, display))
                    filepath = f'{env}{os.sep}{filename}.properties'
                    write_to_file(filepath, text)
                    cmd = f'python run-dynamic-evolver-multi.py {filepath} -i {iters}'
                    print(cmd, end='\n')

# Cell
def additional_properties(properties, response, collector):
    ppars = ''

    if len(properties)>0:
        ppars='### Additional properties\n\n'

    ctr = 1
    for  prop in properties:
        value = properties[prop]
        if response == 'SmoothError' and prop == 'error:smooth_factor':
            propstr = f'property{ctr} = {prop},{value}'
            ppars = ''.join((ppars, propstr, '\n'))
            ctr+=1

        if collector == 'ReferencedInputsError' and  prop == 'error:referenced_inputs':
            propstr = f'property{ctr} = {prop},{value}'
            ppars = ''.join((ppars, propstr, '\n'))
            ctr+=1


    return ppars

# Cell
def write_to_file(file, text):
     f = open(file, "w")
     f.write(text)
     f.close()

# Cell
def structure_parameters(collector,response, weight, struct, arch):
    header = '### Structure\n\n# modes - pattern of nodes at particular levels, zero, n, top and zerotop\n# the mode numbers refer to# 3 - per:ws, ref:ws, com:sub, out:ws\n# 4 - per:ws, ref:con, com:sub, out:ws\n# 5 - per:ws, ref:con, com:sub, out:smws\n# 6 - per:ws, ref:ws, com:sub, out:smws\n'
    modes = [3, 3, 4, 4]
    if struct == 'SmoothWeightedSum':
        modes = [6, 6, 5, 5]

    mstr = f'modes = {modes}'
    type_num = 1
    types = ''
    if weight == 'Floats' or weight == 'AllFloats':
        types = ''.join((types, f'type{type_num} = [LevelKey.ZERO, perception, Float]\n'))
        type_num += 1
        types = ''.join((types, f'type{type_num} = [LevelKey.N, perception, Float]\n'))
        type_num += 1
        types = ''.join((types, f'type{type_num} = [LevelKey.TOP, perception, Float]\n'))
        type_num += 1

    if weight == 'AllFloats':
        types = ''.join((types, f'type{type_num} = [LevelKey.ZERO, action, Float]\n'))
        type_num += 1

    if struct == 'SmoothWeightedSum':
        types = ''.join((types, f'type{type_num} = [LevelKey.ZERO, output, Smooth]\n'))
        type_num += 1
        types = ''.join((types, f'type{type_num} = [LevelKey.N, output, Smooth]\n'))
        type_num += 1
        types = ''.join((types, f'type{type_num} = [LevelKey.TOP, output, Smooth]\n'))
        type_num += 1



    rtn = '\n'.join((header, mstr, types))
    return rtn

# Cell
def configurable_parameters(env, config, collector, response, nevals):
    header = ''.join(("### Configurable parameters\n\n# Randomisation seed to reproduce results\n# Size of population\n",
                     "# Number of generations\n# Probability that an attribute will be mutated\n# Probability that the structure will be mutated\n",
                     "# Number of runs of environment\n# Lower limit of float values\n# Upper limit of float values\n",
                     "# Initial limit of levels\n# Initial limit of columns\n# Lower limit of levels\n# Lower limit of columns\n",
                     "# Limit of error on which to terminate individual evaluation\n# Probability for crossover\n# Probability for mutating an individual\n# Number of times the evaulation is run (with different random seeds)\n# Type of errors collected\n# Error function\n\n"))

    text = ''
    for key in config.keys():
        value = config[key]
        text = ''.join((text, key, ' = ', f'{value}', '\n'))

    text = ''.join((header, text, f'nevals = {nevals}\nerror_collector = {collector}\nerror_response = {response}\n'))

    #f'seed = {seed}\nPOPULATION_SIZE = {POPULATION_SIZE}\nMAX_GENERATIONS = {MAX_GENERATIONS}\nattr_mut_pb={attr_mut_pb}\nstructurepb={structurepb}\nruns={runs}\nlower_float = {lower_float}\nupper_float = {upper_float}\nlevels_limit = {levels_limit}\ncolumns_limit = {columns_limit}\nerror_limit = {error_limit}\np_crossover = {p_crossover}\np_mutation = {p_mutation}\nnevals = {nevals}\nerror_collector = {error_collector}\nerror_response = {error_response}\n'
    return text


# Cell
def description(collector,response, weight, struct, arch):
    filename = '-'.join((arch, collector,response, weight, struct))
    rtn = ''.join(('\n### Description:\n\n','desc = ', filename,'\n'))
    return rtn, filename

# Cell
def fixed_parameters(env, option, num_actions):
    top_inputs = None
    inputs=option['inputs']
    if 'top_inputs' in option.keys():
        top_inputs=option['top_inputs']
    references=option['references']

    header = '### Fixed parameters\n\n# List of input indexes from environment\n# List of reference values\n# Number of actions\n\n'
    text1 = f'env = {env}\ninputs = {inputs}\n'
    if top_inputs == None:
        text2=''
    else:
        text2 = f'top_inputs = {top_inputs}\n'
    text3 = f'references = {references}\nnum_actions = {num_actions}\n'
    return ''.join((header,text1,text2,text3))