import math

def vier_kwadraten(getal):
    a=b=c=d = getal *0.25

    a = math.sqrt(a)
    b = math.sqrt(b)
    c = math.sqrt(c)
    d = math.sqrt(d)
    l = (a, b, c, d)
    print(l)

    h = a**2,b**2,c**2,d**2
    p = sum(h)
    if p//2 == 0:
        print("hoi")
    else:
        print('koi')
    print(p)
    return l

"""==============================================[ HU TESTRAAMWERK ]====================================================
Onderstaand staan de tests voor je code -- hieronder mag je niets wijzigen!
Je kunt je code testen door deze file te runnen of met behulp van pytest.
"""
from functools import reduce
import random
from time import perf_counter

def test_vier_kwadraten():
    # Simulated test cases
    for cnt in range(10):
        n = random.randrange(1, 10)

        for _ in range(4):
            n *= 10
            n += random.randrange(0, 10)

        lst = vier_kwadraten(n)
        assert n == reduce(lambda x, y: x + y, (map(lambda x: x ** 2, lst))), \
            f"Fout: vier_kwadraten({n}) geeft {lst}, maar {lst[0]}^2 + {lst[1]}^2 + {lst[2]}^2 + {lst[3]}^2 != {n}"

def test_vier_kwadraten_tijd():
    # Test cases
    testcases = [36624, 73504, 54296, 40923, 33504, 42627, 70798, 90815, 55367, 52699]

    for case in testcases:
        print(case)
        lst = vier_kwadraten(case)
        assert case == reduce(lambda x, y: x + y, (map(lambda x: x ** 2, lst))), \
            f"Fout: vier_kwadraten({case}) geeft {lst}, maar {lst[0]}^2 + {lst[1]}^2 + {lst[2]}^2 + {lst[3]}^2 != {case}"

if __name__ == '__main__':
    try:
        print("\x1b[0;32m")
        test_vier_kwadraten()
        print("Je functie vier_kwadraten(getal) werkt goed!\n")

        print("\x1b[0;30m")
        print("Timing van 10 getallen...")

        start_time = perf_counter()
        test_vier_kwadraten_tijd()
        delta_time = perf_counter() - start_time
        print(f"Totale tijd: {delta_time*1000:.0f}ms")

    except AssertionError as ae:
        print("\x1b[0;31m")
        print(ae)


import logging
import threading
import time
import random

from configs import platform_list
from secret.bot_secret import discord_token

chats = {
    'fu6kme_':'666666',
    'lsls8787':'都看到一堆手電筒了還選隱鬼是斗M喔',
    'Km55489':'我不喜歡吃苦瓜',
    'Eeggggg0':'66666666',
    '溫蒂':'我叫我阿嬤來打都比你強，而且她已經過世了',
    '散步牛奶':'帶手電筒跟著鬼跑的都小王八蛋',
    'mad_Steve':'What\'s this game?',
    '魔法阿公':'苦瓜是歷史的罪人',
    'yukiko88':'請問小屋到底要怎麼追人？',
    '東亞病夫':'這個不修機的在幹嘛啦',
    'ssgew859':'?????',
    'james9576':'我每次鋼筋鐵骨都會被吃掉',
    '看衰仔':'這場應該四殺',
    'labmen007':'ZZZZZZZ'
}
class demo_bot(threading.Thread):
    platform = platform_list[0]
    title_tag = '@title'
    def __init__(self, main, args):
        super().__init__()
        self.main = main
        self.channel = args['channel']
        self.texts = {}
        self.EMOTE_MODE = self.main.from_setting(self.platform, 'emote', 'bool')
        self.TAKING = False
        self.TOKEN = discord_token
        self.BUSY = False
        self.go = True

    def login_and_run(self):
        self.start()

    def run(self):
        self.texts[self.title_tag] = ['已成功連結']
        # self.main.set_platform_when_logining(self.platform)
        self.main.ui.bot_login_signal.click()
        logging.info('Logged on demo')
        while self.go:
            for name in chats:
                self.texts[name] = [chats[name]]
                time.sleep(random.random() + 1)

    def fetch_text(self):
        _list = self.texts
        self.TAKING = True
        self.texts = {}
        self.TAKING = False
        return _list

    def too_busy(self):
        self.BUSY = True
        logging.info('bot is busy now.')

    def close(self):
        self.go = False
        self.join()


from sklearn.model_selection import train_test_split
import pandas as pd
import tensorflow as tf
import tensorflow_hub as hub
from datetime import datetime
import bert
from bert import run_classifier
from bert import optimization
from bert import tokenization
from tensorflow import keras
import os
import re
from ConexionBaseDeDatos import ConexionBaseDeDatos
from ExtractData import ExtractData

from datetime import date, datetime, timedelta

'''
Rate cambiado
'''
def datespan(startDate, endDate, delta=timedelta(days=1)):
    currentDate = startDate
    while currentDate < endDate:
        yield currentDate
        currentDate += delta

def create_tokenizer_from_hub_module():
    """Get the vocab file and casing info from the Hub module."""
    with tf.Graph().as_default():
        bert_module = hub.Module(BERT_MODEL_HUB)
        tokenization_info = bert_module(signature="tokenization_info", as_dict=True)
        with tf.Session() as sess:
            vocab_file, do_lower_case = sess.run([tokenization_info["vocab_file"],
                                                  tokenization_info["do_lower_case"]])

    return bert.tokenization.FullTokenizer(
        vocab_file=vocab_file, do_lower_case=do_lower_case)

'''

create_model hace esto a continuación.
Primero, vuelve a cargar el módulo concentrador BERT tf (esta vez para extraer el gráfico
de cálculo). A continuación, crea una nueva capa única que será entrenada para adaptar BERT
a nuestra tarea de sentimiento (es decir, clasificar si una crítica de película es positiva
o negativa). Esta estrategia de usar un modelo mayormente entrenado se llama ajuste fino.
'''
def create_model(is_predicting, input_ids, input_mask, segment_ids, labels,
                 num_labels):
  """Creates a classification model."""

  bert_module = hub.Module(
      BERT_MODEL_HUB,
      trainable=True)
  bert_inputs = dict(
      input_ids=input_ids,
      input_mask=input_mask,
      segment_ids=segment_ids)
  bert_outputs = bert_module(
      inputs=bert_inputs,
      signature="tokens",
      as_dict=True)

  # Use "pooled_output" for classification tasks on an entire sentence.
  # Use "sequence_outputs" for token-level output.
  output_layer = bert_outputs["pooled_output"]

  hidden_size = output_layer.shape[-1].value

  # Create our own layer to tune for politeness data.
  output_weights = tf.get_variable(
      "output_weights", [num_labels, hidden_size],
      initializer=tf.truncated_normal_initializer(stddev=0.02))

  output_bias = tf.get_variable(
      "output_bias", [num_labels], initializer=tf.zeros_initializer())

  with tf.variable_scope("loss"):

    # Dropout helps prevent overfitting
    output_layer = tf.nn.dropout(output_layer, rate=1-0.9)

    logits = tf.matmul(output_layer, output_weights, transpose_b=True)
    logits = tf.nn.bias_add(logits, output_bias)
    log_probs = tf.nn.log_softmax(logits, axis=-1)

    # Convert labels into one-hot encoding
    one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)

    predicted_labels = tf.squeeze(tf.argmax(log_probs, axis=-1, output_type=tf.int32))
    # If we're predicting, we want predicted labels and the probabiltiies.
    if is_predicting:
      return (predicted_labels, log_probs)

    # If we're train/eval, compute loss between predicted and actual label
    per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)
    loss = tf.reduce_mean(per_example_loss)
    return (loss, predicted_labels, log_probs)

'''
A continuación, incluiremos nuestra función de modelo en una función model_fn_builder
 que adapta nuestro modelo para que funcione con fines de capacitación, evaluación y predicción.
'''
def model_fn_builder(num_labels, learning_rate, num_train_steps,
                     num_warmup_steps):
    """Returns `model_fn` closure for TPUEstimator."""

    def model_fn(features, labels, mode, params):  # pylint: disable=unused-argument
        """The `model_fn` for TPUEstimator."""

        input_ids = features["input_ids"]
        input_mask = features["input_mask"]
        segment_ids = features["segment_ids"]
        label_ids = features["label_ids"]

        is_predicting = (mode == tf.estimator.ModeKeys.PREDICT)

        # TRAIN and EVAL
        if not is_predicting:

            (loss, predicted_labels, log_probs) = create_model(
                is_predicting, input_ids, input_mask, segment_ids, label_ids, num_labels)

            train_op = bert.optimization.create_optimizer(
                loss, learning_rate, num_train_steps, num_warmup_steps, use_tpu=False)

            # Calculate evaluation metrics.
            def metric_fn(label_ids, predicted_labels):
                accuracy = tf.metrics.accuracy(label_ids, predicted_labels)
                '''
                f1_score = tf.contrib.metrics.f1_score(
                    label_ids,
                    predicted_labels)
                '''
                '''
                auc = tf.metrics.auc(
                    label_ids,
                    predicted_labels)
                '''
                recall = tf.metrics.recall(
                    label_ids,
                    predicted_labels)
                precision = tf.metrics.precision(
                    label_ids,
                    predicted_labels)
                true_pos = tf.metrics.true_positives(
                    label_ids,
                    predicted_labels)
                true_neg = tf.metrics.true_negatives(
                    label_ids,
                    predicted_labels)
                false_pos = tf.metrics.false_positives(
                    label_ids,
                    predicted_labels)
                false_neg = tf.metrics.false_negatives(
                    label_ids,
                    predicted_labels)
                return {
                    "eval_accuracy": accuracy,
                    #"f1_score": f1_score,
                    #"auc": auc,
                    "precision": precision,
                    "recall": recall,
                    "true_positives": true_pos,
                    "true_negatives": true_neg,
                    "false_positives": false_pos,
                    "false_negatives": false_neg
                }

            eval_metrics = metric_fn(label_ids, predicted_labels)

            if mode == tf.estimator.ModeKeys.TRAIN:
                return tf.estimator.EstimatorSpec(mode=mode,
                                                  loss=loss,
                                                  train_op=train_op)
            else:
                return tf.estimator.EstimatorSpec(mode=mode,
                                                  loss=loss,
                                                  eval_metric_ops=eval_metrics)
        else:
            (predicted_labels, log_probs) = create_model(
                is_predicting, input_ids, input_mask, segment_ids, label_ids, num_labels)

            predictions = {
                'probabilities': log_probs,
                'labels': predicted_labels
            }
            return tf.estimator.EstimatorSpec(mode, predictions=predictions)

    # Return the actual model function in the closure
    return model_fn

def getPrediction(in_sentences):
    labels = [0, 1, 2]
    input_examples = [run_classifier.InputExample(guid="", text_a=x, text_b=None, label=0) for x in
                      in_sentences]  # here, "" is just a dummy label
    input_features = run_classifier.convert_examples_to_features(input_examples, label_list, MAX_SEQ_LENGTH, tokenizer)
    predict_input_fn = run_classifier.input_fn_builder(features=input_features, seq_length=MAX_SEQ_LENGTH,
                                                       is_training=False, drop_remainder=False)
    predictions = estimator.predict(predict_input_fn)
    indice=0
    resultado = []

    try:
        for prediction in predictions:
            resultado.append((in_sentences[indice], prediction['probabilities'], labels[prediction['labels']]))

            print(str(indice) +"###"+str(len(in_sentences)))
            indice = indice + 1
            '''
            if indice>100:
                return resultado
            '''

    except Exception as e:
        print(e)
        return resultado

    return resultado
    '''
    try:
        return [(sentence, prediction['probabilities'], labels[prediction['labels']]) for sentence, prediction in
                zip(in_sentences, predictions)]
    except Exception as e:
        print(e)
    '''

if __name__ == '__main__':
    '''
    Configuración
    '''
    OUTPUT_DIR = 'Modelo_Sia'#@param {type:"string"}
    # Compute train and warmup steps from batch size
    # These hyperparameters are copied from this colab notebook (https://colab.sandbox.google.com/github/tensorflow/tpu/blob/master/tools/colab/bert_finetuning_with_cloud_tpus.ipynb)
    BATCH_SIZE = 32
    LEARNING_RATE = 2e-5
    NUM_TRAIN_EPOCHS = 3.0
    # Warmup is a period of time where hte learning rate
    # is small and gradually increases--usually helps training.
    WARMUP_PROPORTION = 0.1
    # Model configs
    SAVE_CHECKPOINTS_STEPS = 500
    SAVE_SUMMARY_STEPS = 100

    # Compute train and warmup steps from batch size
    # These hyperparameters are copied from this colab notebook (https://colab.sandbox.google.com/github/tensorflow/tpu/blob/master/tools/colab/bert_finetuning_with_cloud_tpus.ipynb)
    BATCH_SIZE = 32
    LEARNING_RATE = 2e-5
    NUM_TRAIN_EPOCHS = 3.0
    # Warmup is a period of time where hte learning rate
    # is small and gradually increases--usually helps training.
    WARMUP_PROPORTION = 0.1
    # Model configs
    SAVE_CHECKPOINTS_STEPS = 500
    SAVE_SUMMARY_STEPS = 100

    # Compute # train and warmup steps from batch size

    '''
    Genero el test y el train, importante todos los twwets  son lower
    '''
    DATA_COLUMN = 'sentence'
    LABEL_COLUMN = 'polarity'
    label_list = [0, 1, 2]
    datos= ExtractData()
    tweets=datos.cargarDatos()
    '''
    Fin carga de datos
     '''

    '''

    Data Preprocessing
    Necesitaremos transformar nuestros datos en un formato que BERT entienda.
    Esto implica dos pasos.

    Primero, creamos InputExample usando el constructor provisto en la biblioteca BERT.
        text_a es el texto que queremos clasificar,
        etiqueta es la etiqueta de nuestro ejemplo, es decir, Verdadero, Falso

    '''
    # Use the InputExample class from BERT's run_classifier code to create examples from the data
    train_InputExamples = tweets[0].apply(lambda x: bert.run_classifier.InputExample(guid=None,
                                                                                # Globally unique ID for bookkeeping, unused in this example
                                                                                text_a=x[DATA_COLUMN],
                                                                                text_b=None,
                                                                                label=x[LABEL_COLUMN]), axis=1)

    test_InputExamples = tweets[1].apply(lambda x: bert.run_classifier.InputExample(guid=None,
                                                                               text_a=x[DATA_COLUMN],
                                                                               text_b=None,
                                                                               label=x[LABEL_COLUMN]), axis=1)

    '''
       A continuación, debemos preprocesar nuestros datos para que coincidan con los datos
       en los que BERT recibió capacitación. Para esto, tendremos que hacer un par de cosas :

            Minúsculas en nuestro texto (si estamos usando un modelo de minúsculas BERT)
            Tokenize (es decir, "sally dice hola" -> ["sally", "dice", "hola"))
            Divida las palabras en WordPieces (es decir, "llamando" -> ["call", "## ing"])
            Asigne nuestras palabras a los índices utilizando un archivo de vocabulario que proporciona BERT
            Agregue tokens especiales "CLS" y "SEP" (consulte el archivo Léame)
            Agregue tokens de "índice" y "segmento" a cada entrada (vea el documento BERT)
            Afortunadamente, no tenemos que preocuparnos por la mayoría de estos detalles.

        Para comenzar, necesitaremos cargar un archivo de vocabulario y
        una información de minúsculas directamente desde el módulo del concentrador BERT tf:
    '''
    BERT_MODEL_HUB = "https://tfhub.dev/google/bert_uncased_L-12_H-768_A-12/1"
    tokenizer = create_tokenizer_from_hub_module()
    print(tokenizer.tokenize("This here's an example of using the BERT tokenizer"))

    '''
    Usando nuestro tokenizer, llamaremos run_classifier.convert_examples_to_features
     en nuestros InputExamples para convertirlos en características que BERT entiende.
    '''

    # We'll set sequences to be at most 128 tokens long.
    ''' Modifico a 300 '''
    MAX_SEQ_LENGTH = 300
    # Convert our train and test features to InputFeatures that BERT understands.
    train_features = bert.run_classifier.convert_examples_to_features(train_InputExamples, label_list, MAX_SEQ_LENGTH,
                                                                      tokenizer)
    test_features = bert.run_classifier.convert_examples_to_features(test_InputExamples, label_list, MAX_SEQ_LENGTH,
                                                                     tokenizer)

    '''
    importante verificar
    num_train_steps = int(len(train_features) / BATCH_SIZE * NUM_TRAIN_EPOCHS)
    '''
    num_train_steps = int(len(train_features))
    num_warmup_steps = int(num_train_steps * WARMUP_PROPORTION)

    # Specify outpit directory and number of checkpoint steps to save
    run_config = tf.estimator.RunConfig(
        model_dir=OUTPUT_DIR,
        save_summary_steps=SAVE_SUMMARY_STEPS,
        save_checkpoints_steps=SAVE_CHECKPOINTS_STEPS)
    model_fn = model_fn_builder(
        num_labels=len(label_list),
        learning_rate=LEARNING_RATE,
        num_train_steps=num_train_steps,
        num_warmup_steps=num_warmup_steps)

    estimator = tf.estimator.Estimator(
        model_fn=model_fn,
        config=run_config,
        params={"batch_size": BATCH_SIZE})

    '''A continuación, creamos una función de creación de entradas que toma nuestro
    conjunto de funciones de entrenamiento (train_features) y produce un generador.
    Este es un patrón de diseño bastante estándar para trabajar con Tensorflow Estimators.'''

    # Create an input function for training. drop_remainder = True for using TPUs.
    train_input_fn = bert.run_classifier.input_fn_builder(
        features=train_features,
        seq_length=MAX_SEQ_LENGTH,
        is_training=True,
        drop_remainder=False)
    print("Beginning Training!")
    current_time = datetime.now()
    estimator.train(input_fn=train_input_fn, max_steps=num_train_steps)
    print("Training took time ", datetime.now() - current_time)
    test_input_fn = run_classifier.input_fn_builder(
        features=test_features,
        seq_length=MAX_SEQ_LENGTH,
        is_training=False,
        drop_remainder=False)

    #print(estimator.evaluate(input_fn=test_input_fn, steps=None))

    '''
    calculate auc multiclass python
    parte de fechas
    '''

    conexionBase = ConexionBaseDeDatos()
    anterior=datetime(2019, 4,1, 1, 30)
    result = {}
    result["positivo"] = []
    result["neutral"] = []
    result["negativo"] = []
    result["total"] = []
    result["precio"] = []
    result["sentimiento_positivo"] = []
    result["sentimiento_negativo"] = []
    result["fecha"] = []

    indice=0
    for timestamp in datespan( datetime(2019, 4,1, 2, 30),  datetime(2019, 7,31, 23, 30),delta=timedelta(hours=1)):

        print("Iteracion"+str(timestamp))
        if conexionBase.existe_hora(timestamp):
            pass
        else:
            pred_sentences = conexionBase.ObtenerEntreHoras(anterior, timestamp)
            auxiliar = []
            for i in pred_sentences:
                auxiliar.append(i[0])
            sentimiento = []
            positivo=0
            negativo=0

            for z in pred_sentences:
                if z[1]=='positive':
                    positivo=positivo+1
                else:
                    negativo=negativo+1
                sentimiento.append(z[1])

            if len(auxiliar)>0:
                predictions = getPrediction(auxiliar)
                '''print(type(predictions).__name__)'''
                df = pd.DataFrame(list(predictions), sentimiento[0:len(predictions)])
                precio = conexionBase.ObtenerPrecio(timestamp)
                result["positivo"].append(len(df.loc[df[2] == 1]))
                result["neutral"].append(len(df.loc[df[2] == 2]))
                result["negativo"].append(len(df.loc[df[2] == 0]))
                result["total"].append(len(pred_sentences))
                for total_precio in precio:
                    result["precio"].append(total_precio[0].replace(".", ","))
                    break
                result["sentimiento_positivo"].append(positivo)
                result["sentimiento_negativo"].append(negativo)
                result["fecha"].append(str(timestamp))
                conexionBase.almacenar_datos_valoracion(result["precio"][indice],result["positivo"][indice],result["negativo"][indice],  result["neutral"][indice], result["sentimiento_negativo"] [indice], result["sentimiento_positivo"][indice],  result["total"][indice],result["fecha"][indice])
            else:
                precio = conexionBase.ObtenerPrecio(timestamp)
                result["positivo"].append(0)
                result["neutral"].append(0)
                result["negativo"].append(0)
                result["total"].append(0)
                for total_precio in precio:
                    result["precio"].append(total_precio[0].replace(".", ","))
                    break
                result["sentimiento_positivo"].append(positivo)
                result["sentimiento_negativo"].append(negativo)
                result["fecha"].append(str(timestamp))
                conexionBase.almacenar_datos_valoracion(result["precio"][indice],result["positivo"][indice],result["negativo"][indice],  result["neutral"][indice], result["sentimiento_negativo"] [indice], result["sentimiento_positivo"][indice],  result["total"][indice],result["fecha"][indice])
            indice=indice+1
        anterior = timestamp


import os

def inpread(fname, header_lines = 0):
    """
    Nacitanie input suboru
    Vystupom bude dict premenna s keys: nazvy premennych; values: hodnoty
    """

    # kontrola existencie suboru
    if os.path.isfile(fname):
        # otvorenie suboru
        with open(fname, encoding='utf-8') as file:
            # pripadne odstranenie hlavicky suboru
            if header_lines != 0:
                for a in range(header_lines):
                    header = file.readline()

            # cyklus cez jednotlive riadky
            i = -1
            var_name = []
            var_val = []
            for line in file:
                i += 1
                read_line = line.rstrip()
                read_line = read_line.split()

                # testovanie, ci je parameter cislo a jeho pripadna transformacia
                read_line[1] = numtest(read_line[1])

                var_name.append(read_line[0])
                var_val.append(read_line[1])

        # tvorba slovnika
        inp_pairs = list(zip(var_name, var_val))
        inp_dict = dict(inp_pairs)

        return inp_dict

    else:
        raise FileNotFoundError('Subor neexistuje')

def numtest(x):
    '''
    Tetsovanie, co je hodnota x cislo alebo string
    :param x: string
    :return: float cislo alebo string
    '''
    try:
        return float(x)
    except ValueError:
        return x


import sys
from os.path import *

from ReportUtils import CMLParser,ReportPipeline

cml_parser = CMLParser(arg_count_threshold=1)
cml_parser.arg('--subject','R1196N')
cml_parser.arg('--task','PAL3')
cml_parser.arg('--workspace-dir','/scratch/leond/PAL3_reports')
cml_parser.arg('--mount-point','')
#cml_parser.arg('--recompute-on-no-status')

args = cml_parser.parse()

import numpy as np
from RamPipeline import RamPipeline
from RamPipeline import RamTask

from PAL1EventPreparation import PAL1EventPreparation

from EventPreparation import EventPreparation

from ComputePAL1Powers import ComputePAL1Powers

from ComputeClassifier import ComputeClassifier

from ComputePALStimPowers import ComputePALStimPowers

from MontagePreparation import MontagePreparation

from ComputePALStimTable import ComputePALStimTable

from ComposeSessionSummary import ComposeSessionSummary

from GenerateReportTasks import *

# turn it into command line options

class Params(object):
    def __init__(self):
        self.width = 5

        self.pal1_start_time = 0.3
        self.pal1_end_time = 2.0
        self.pal1_buf = 1.0

        self.filt_order = 4

        self.freqs = np.logspace(np.log10(3), np.log10(180), 8)

        self.log_powers = True

        self.ttest_frange = (70.0, 200.0)

        self.penalty_type = 'l2'
        self.C = 7.2e-4

        self.n_perm = 200

params = Params()

#
# class ReportPipeline(RamPipeline):
#     def __init__(self, subject, task, workspace_dir, mount_point=None):
#         RamPipeline.__init__(self)
#         self.subject = subject
#         self.task = self.experiment = task
#         self.mount_point = mount_point
#         self.set_workspace_dir(workspace_dir)

# sets up processing pipeline
report_pipeline = ReportPipeline(subject=args.subject, task=args.task,experiment=args.task,sessions=args.sessions,
                                 workspace_dir=join(args.workspace_dir,args.subject), mount_point=args.mount_point, exit_on_no_change=args.exit_on_no_change,
                                 recompute_on_no_status=args.recompute_on_no_status)

# sets up processing pipeline
# report_pipeline = ReportPipeline(subject=args.subject, task=args.task,
#                                        workspace_dir=join(args.workspace_dir,args.task+'_'+args.subject), mount_point=args.mount_point)
#

report_pipeline.add_task(PAL1EventPreparation(mark_as_completed=False))

report_pipeline.add_task(EventPreparation(mark_as_completed=False))

report_pipeline.add_task(MontagePreparation(params=params, mark_as_completed=False))

report_pipeline.add_task(ComputePAL1Powers(params=params, mark_as_completed=True))

report_pipeline.add_task(ComputeClassifier(params=params, mark_as_completed=True))

report_pipeline.add_task(ComputePALStimPowers(params=params, mark_as_completed=True))

report_pipeline.add_task(ComputePALStimTable(params=params, mark_as_completed=True))

report_pipeline.add_task(ComposeSessionSummary(params=params, mark_as_completed=False))
#
report_pipeline.add_task(GeneratePlots(mark_as_completed=False))
#
report_pipeline.add_task(GenerateTex(mark_as_completed=False))
#
report_pipeline.add_task(GenerateReportPDF(mark_as_completed=False))

# starts processing pipeline
report_pipeline.execute_pipeline()


from PoolDB import Pool

class Operation:
    @staticmethod
    def execute_query(sql):
        conn = Pool.connection()
        cur = conn.cursor()
        cur.execute(sql)
        r = cur.fetchall()
        cur.close()
        conn.close()
        print(r)
        return r

    @staticmethod
    def execute_commit(sql):
        conn = Pool.connection()
        cur = conn.cursor()
        cur.execute(sql)
        conn.commit()
        cur.close()
        conn.close()
        return

class Query:
    @staticmethod
    def query_limit(table_name, limit, qr_field_list, order_list):
        order = []
        for i in order_list:
            order.append('%s desc' % i)
        sql = 'select %s from %s order by %s limit %s' \
              % (','.join(qr_field_list), table_name, ','.join(order), limit)
        print(sql)
        return Operation.execute_query(sql)

    @staticmethod
    def query_field_primary_key(table_name, primary_key, where, qr_field_list):
        sql = 'select %s from %s where %s=%s' % (','.join(qr_field_list), table_name, primary_key, where)
        return Operation.execute_query(sql)

    @staticmethod
    def query_comment(table_name, where, offset):
        sql = 'select * from %s where comment_for_post_id=%s order by comment_time desc limit %s,10' % \
              (table_name,
               where,
               offset)
        return Operation.execute_query(sql)

    @staticmethod
    def query_field_by_time(table_name, qr_field_list, st, et, tag):
        if tag:
            sql = 'select %s from %s where article_time>="%s" and article_time<="%s" and article_tag="%s"' \
                  % (','.join(qr_field_list), table_name, st, et, tag)
        else:
            sql = 'select %s from %s where article_time>="%s" and article_time<="%s"' \
                  % (','.join(qr_field_list), table_name, st, et)
        return Operation.execute_query(sql)

    @staticmethod
    def query_search(table_name, kw, offset):
        sql = 'select count(*) from %s where match(' \
              'article_tag, article_title, text_for_search) against("+%s" in boolean mode)' % (table_name, kw)
        total = Operation.execute_query(sql)[0]["count(*)"]
        print(total)
        sql = 'select ' \
              'article_read,article_tag,article_time,article_title,post_key,text_for_search ' \
              'from %s where match(article_tag, article_title, text_for_search) ' \
              'against("+%s" in boolean mode) limit %s,10' % (table_name, kw, offset)
        print(sql)
        data = Operation.execute_query(sql)
        return {"data": data, "total": total}

    @staticmethod
    def get_previous(table_name, post_id):
        sql = "select post_key from %s where article_id < %s order by article_id desc limit 1" % (table_name, post_id)
        return Operation.execute_query(sql)

    @staticmethod
    def get_next(table_name, post_id):
        sql = "select post_key from articles where article_id > %s order by article_id limit 1" % (table_name, post_id)
        return Operation.execute_query(sql)

    @staticmethod
    def query_quantity(table_name):
        # 查询表中有多少条数据
        sql = "select count(*) from %s" % table_name
        return Operation.execute_query(sql)["count(*)"]

class Commit:
    # 更新表中的某一条记录,并且可以指定更新的字段
    @staticmethod
    def update_data(table_name, primary_key, where, **kwargs):
        update_content = []
        for field, value in kwargs.items():
            update_content.append(field + '=' + "'" + value + "'")
        sql = "update %s set %s where %s=%s" % (table_name, ",".join(update_content), primary_key, where)
        Operation.execute_commit(sql)
        return

    @staticmethod
    def save_data(table_name, **kwargs):
        fields = []
        values = []
        for field, value in kwargs.items():
            fields.append(field)
            values.append("'"+value+"'")
        print(fields, values)
        sql = "insert into %s (%s) values (%s)" % (table_name, ",".join(fields), ",".join(values))
        Operation.execute_commit(sql)
        return

    @staticmethod
    def del_where(table_name, primary_key, where):
        sql = "delete from %s where %s=%s" % (table_name, primary_key, where)
        Operation.execute_commit(sql)
        return

    @staticmethod
    def del_reply_belong(table_name, reply_for):
        sql = "delete from %s where reply_belong=%s" % (table_name, reply_for)
        Operation.execute_commit(sql)
        return

class DataBase:
    def query_quantity(self):
        return Query.query_quantity(self.table_name)

    def query_search(self, kw, offset):
        return Query.query_search(self.table_name, kw, offset)

    def query_limit(self, limit, qr_field_list, order_list):
        return Query.query_limit(self.table_name, limit, qr_field_list, order_list)

    def query_comment(self, where, *qr_field):
        return Query.query_comment(self.table_name, where, *qr_field)

    def query_field_primary_key(self, where, qr_field_list):
        return Query.query_field_primary_key(self.table_name, self.primary_key, where, qr_field_list)

    def query_field_by_time(self, qr_field_list, st, et, tag):
        return Query.query_field_by_time(self.table_name, qr_field_list, st, et, tag)

    def get_previous(self, post_id):
        return Query.get_previous(self.table_name, post_id)

    def get_next(self, post_id):
        return Query.get_previous(self.table_name, post_id)

    def update_data(self, where, **kwargs):
        Commit.update_data(self.table_name, self.primary_key, where, **kwargs)
        return

    def save_data(self, **kwargs):
        Commit.save_data(self.table_name, **kwargs)
        return

    def del_where(self, where):
        Commit.del_where(self.table_name, self.primary_key, where)
        return

    def del_reply_belong(self, reply_for):
        Commit.del_where(self.table_name, "reply_belong", reply_for)
        return

class Table(DataBase):
    def __init__(self, table_name, primary_key):
        self.table_name = table_name
        self.primary_key = primary_key

my_articles = Table("articles", "post_key")
my_comments = Table("comment", "comment_key")
my_timeline = Table("timeline", "timeline_id")
my_admin = Table("admin", "admin_id")
my_blog = Table("blog", "id")


# uncompyle6 version 3.7.4
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: /home/cameron/Dev/kanban-dev/django-autotask/djautotask/migrations/0046_auto_20200207_1002.py
# Compiled at: 2020-02-28 16:41:52
# Size of source mod 2**32: 773 bytes
from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):
    dependencies = [
     ('djautotask', '0045_resourceroledepartment_resourceservicedeskrole')]
    operations = [
     migrations.AddField(model_name='resource',
       name='default_service_desk_role',
       field=models.ForeignKey(blank=True, null=True, on_delete=(django.db.models.deletion.SET_NULL), to='djautotask.Role')),
     migrations.AddField(model_name='ticket',
       name='role',
       field=models.ForeignKey(blank=True, null=True, on_delete=(django.db.models.deletion.SET_NULL), to='djautotask.Role'))]


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('app', '0002_auto_20150510_1558'),
    ]

    operations = [
        migrations.CreateModel(
            name='InstitucionEducativa',
            fields=[
                ('codigo', models.CharField(serialize=False, max_length=10, primary_key=True)),
                ('nombre', models.CharField(max_length=100)),
                ('sede', models.CharField(max_length=100)),
                ('municipio', models.CharField(max_length=50)),
                ('zona', models.PositiveSmallIntegerField(choices=[(0, 'Urbana'), (1, 'Urbana marginal'), (2, 'Rural'), (3, 'Rural de difícil acceso')])),
                ('modalidad', models.PositiveSmallIntegerField(choices=[(0, 'Académica'), (1, 'Ténica'), (2, 'Agropecuaria'), (3, 'Comercial'), (4, 'Promoción Social'), (5, 'Finanzas'), (6, 'Administación'), (7, 'Ecología'), (8, 'Medio Ambiente'), (9, 'Industrial'), (10, 'Informática'), (11, 'Minería'), (12, 'Salud'), (13, 'Recreación'), (14, 'Turismo'), (15, 'Deporte'), (16, 'Otro')])),
                ('slug', models.SlugField()),
            ],
        ),
        migrations.CreateModel(
            name='SecretariaEducacion',
            fields=[
                ('codigo', models.CharField(serialize=False, max_length=15, primary_key=True)),
                ('entidad', models.PositiveSmallIntegerField(choices=[(0, 'Municipal'), (1, 'Departamental')])),
                ('nombre', models.CharField(max_length=50)),
                ('slug', models.SlugField()),
            ],
            options={
                'ordering': ['nombre'],
            },
        ),
    ]


'''
favorite_language = {'jen':'python',
                     'sarah':'c',
                     'edward':'ruby',
                     'phil':'python',}

print("这些KEY有：")
for key in favorite_language.keys():
    print(key)

print("这些Value有：")
for value in set(favorite_language.values()):
    print(value)

#创建一个字典，在其中存储三条大河流及流经的国家
rivers = {'nile':'Egypt',
          'Amazon':'Brazil',
          'Yangtze':'China',}

for river,key in rivers.items():
    print("The "+river.title() +" runs through "+ key.title()+".")

#使用循环将字典中的每条河流的名字都打印出来
print("世界三大河流是：")
for key in rivers.keys():
    print(key)

#使用循环将字典中名含的每个国家的名字都打印出来
print("这些河流流经的国家都有：")
for value in rivers.values():
    print(value)
'''
#创建一个应该 会接受调查的人员名单，其中有些人已经包含在字典中，而其他人未包含在字典中
favorite_language = {'jen':'python',
                     'sarah':'c',
                     'edward':'ruby',
                     'phil':'python',}
names = ['phil','sarah','tony','jon','ailen']
for name in names:
    if name in favorite_language.keys():
        print("%s Thank you for you intend"%name)
    else:
        print("welcome to here %s"%name)


#!/usr/bin/python
# -*- coding: utf-8 -*-

from recordclass import recordclass
from collections import deque
import heapq

Item = recordclass('Item', 'index value weight')
Node = recordclass('Node', 'level value weight items')
PQNode = recordclass('PQNode', 'level value weight bound items')

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]

    def empty(self):
        if (len(self._queue) is 0):
            return True
        else:
            return False

    def length(self):
        return len(self._queue)

#def knapsack(capacity, items, int n):
def solve_it_branch_bound_breadth_first(input_data):
    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])

    items = []

    for i in range(1, item_count+1):
        line = lines[i]
        parts = line.split()
        items.append(Item(i-1, int(parts[0]), int(parts[1])))

    # sorting Item on basis of value per unit
    # weight.
    items = sorted(items,key=lambda Item: Item.weight/Item.value)

    # make a queue for traversing the node
    v = Node(level = -1, value = 0, weight = 0, items = [])
    Q = deque([])
    Q.append(v)

    #One by one extract an item from decision tree
    #compute profit of all children of extracted item
    #and keep saving maxProfit
    maxValue = 0
    bestItems = []

    while (len(Q) != 0):
        #Dequeue a node
        v = Q[0]

        Q.popleft()

        u = Node(level = None, weight = None, value = None, items = [])

        u.level = v.level + 1
        u.weight = v.weight + items[u.level].weight
        u.value = v.value + items[u.level].value
        u.items = list(v.items)
        u.items.append(items[u.level].index)

        if (u.weight <= capacity and u.value > maxValue):
            maxValue = u.value
            bestItems = u.items

        bound_u = bound(u, capacity, item_count, items)

        if (bound_u > maxValue):
            Q.append(u)

        u = Node(level = None, weight = None, value = None, items = [])
        u.level = v.level + 1
        u.weight = v.weight
        u.value = v.value
        u.items = list(v.items)

        bound_u = bound(u, capacity, item_count, items)

        if (bound_u > maxValue):
            Q.append(u)

    taken = [0]*len(items)
    for i in range(len(bestItems)):
        taken[bestItems[i]] = 1
    output_data = str(maxValue) + ' ' + str(0) + '\n'
    output_data += ' '.join(map(str, taken))
    return output_data

def solve_it_branch_bound_best_first(input_data):
    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])

    items = []

    for i in range(1, item_count+1):
        line = lines[i]
        parts = line.split()
        items.append(Item(i-1, int(parts[0]), int(parts[1])))

    # sorting Item on basis of value per unit
    # weight.
    items = sorted(items,key=lambda Item: Item.weight/Item.value)

    # make a queue for traversing the node
    v = PQNode(level = -1, value = 0, weight = 0, bound = 0, items = [])
    v.bound = bound(v, capacity,item_count, items)
    Q = PriorityQueue()
    Q.push(v, v.bound)

    #One by one extract an item from decision tree
    #compute profit of all children of extracted item
    #and keep saving maxProfit
    maxValue = 0
    bestItems = []

    while not Q.empty():
        #Dequeue a node
        v = Q.pop()
        if (v.bound > maxValue):
            u = PQNode(level = None, weight = None, value = None, bound = None, items = [])
            u.level = v.level + 1
            u.weight = v.weight + items[u.level].weight
            u.value = v.value + items[u.level].value
            u.items = list(v.items)
            u.items.append(items[u.level].index)

            if (u.weight <= capacity and u.value > maxValue):
                maxValue = u.value
                bestItems = u.items

            u.bound = bound(u, capacity, item_count, items)

            if (u.bound > maxValue):
                Q.push(u, u.bound)

            u = PQNode(level = None, weight = None, value = None, bound = None, items = [])
            u.level = v.level + 1
            u.weight = v.weight
            u.value = v.value
            u.items = list(v.items)

            u.bound = bound(u, capacity, item_count, items)

            if (u.bound > maxValue):
                Q.push(u, u.bound)

    taken = [0]*len(items)
    for i in range(len(bestItems)):
        taken[bestItems[i]] = 1
    output_data = str(maxValue) + ' ' + str(0) + '\n'
    output_data += ' '.join(map(str, taken))
    return output_data

def bound(u, capacity, item_count, items):
    if (u.weight >= capacity):
        return 0
    else:
        result = u.value
        j = u.level + 1
        totweight = u.weight

        while (j < item_count and totweight + items[j].weight <= capacity):
            totweight = totweight + items[j].weight
            result = result + items[j].value
            j = j + 1

        k = j
        if (k <= item_count - 1):
            result = result + (capacity - totweight)*items[k].value/items[k].weight

        return result

def solve_it_default(input_data):
    # Modify this code to run your optimization algorithm

    # parse the input
    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])

    items = []

    for i in range(1, item_count+1):
        line = lines[i]
        parts = line.split()
        print(line)
        items.append(Item(i-1, int(parts[0]), int(parts[1])))

    # a trivial greedy algorithm for filling the knapsack
    # it takes items in-order until the knapsack is full

    print(items)

    value = 0
    weight = 0
    taken = [0]*len(items)

    for item in items:
        if weight + item.weight <= capacity:
            taken[item.index] = 1
            value += item.value
            weight += item.weight

    # prepare the solution in the specified output format
    output_data = str(value) + ' ' + str(0) + '\n'
    output_data += ' '.join(map(str, taken))
    return output_data

def solve_it_dynamic_programming(input_data):
    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])

    items = []

    #print("item_count = ", item_count, ", capacity = ", capacity)

    for i in range(1, item_count+1):
        line = lines[i]
        parts = line.split()
        #print(line)
        items.append(Item(i-1, int(parts[0]), int(parts[1])))

#    for i in range(len(items)):
#        print("item = ", i, ", weight = ", items[i].weight, ", value = ", items[i].value )
        #print(items[i].weight)
        #print(items[i].value)

    obj = [[0 for y in range(0,item_count+1)] for x in range(0,capacity+1)]

    #for w in range(0, capacity):
    #    for i in range(0,item_count):
    #        print("capacity = ",capacity,", item_count = ", item_count,", obj[",w,"][", i, "] = ", obj[w][i])

    for i in range(1,item_count+1):
        for w in range(1,capacity+1):
            #print(obj[w][i-1])
            obj[w][i] = obj[w][i-1]
            if (items[i-1].weight <= w):
                val = obj[w-items[i-1].weight][i-1] + items[i-1].value
                if obj[w][i] < val:
                    obj[w][i] = val
            #print("w = ", w, ", i = ", i, ", obj[",w,"][",i,"] = ", obj[w][i])

    taken = [0]*len(items)

    curr_item = item_count-1
    curr_weight = capacity

    while (curr_item >= 0):
        #print("curr_item = ", curr_item, ", curr_weight = ", curr_weight, "obj[curr_weight][curr_item] = ", obj[curr_weight][curr_item+1])
        if obj[curr_weight][curr_item] != obj[curr_weight][curr_item + 1]:
            taken[curr_item] = 1
            curr_weight = curr_weight - items[curr_item].weight
        #print("taken[curr_item] = ", taken[curr_item])
        curr_item = curr_item - 1

    output_data = str(obj[capacity][item_count]) + ' ' + str(0) + '\n'
    output_data += ' '.join(map(str, taken))
    return output_data
    #print("hello")
 #   print(obj[0][capacity])

def solve_it(input_data):
    #return solve_it_branch_bound_breadth_first(input_data)
    #return solve_it_branch_bound_best_first(input_data)

    return solve_it_dynamic_programming(input_data)
    #return solve_it_default(input_data)

if __name__ == '__main__':
    import sys
    if len(sys.argv) > 1:
        file_location = sys.argv[1].strip()
        #print("I'm here")
        #print(file_location)
        with open(file_location, 'r') as input_data_file:
            #print("in loop")
            input_data = input_data_file.read()
        print(solve_it(input_data))
    else:
        print('This test requires an input file.  Please select one from the data directory. (i.e. python solver.py ./data/ks_4_0)')


def binary_search(elem, arr):
    """Performs binary search of given element inside of array
    :param elem: element to be found
    :param arr: array where element is to be found
    :return: Index of element if it's presented in the arr, None otherwise"""

    x = 0
    y = len(arr)

    while x <= y:
        z = (x + y) // 2
        if elem < arr[z]:
            y = z - 1
        elif elem > arr[z]:
            x = z + 1
        else:
            return z


#main.py,主要是调用所有功能模块，主要分为三部分:
#        第一部分为设备检查部分，gState = 1;
#        第二部分是正常交互模式（是后期用户交互使用），gState = 2;
#        第三部分是Debug模式（为后面调试阶段做准备），gState = 3

#!/usr/bin/python
#导入所需工作包
import sys      				#sys模块是python自带系统模块，可通过此模块方法进行对localhost的cmd操控。
import os       				#os模块是路径模块，通常用os来完成路径文件的调用和查看，一般和sys合用。
import Image                                    #导入图像处理的功能包

def main():
    global gState                               #全局变量gState；
    #global gDir                                 #全局变量gDir；
    if gState == 1:                             #判断gState状态；若为 1 ，进入init，设备检查部分；
        Image.connectCam()                      #连接相机
        Image.loadYolo()                        #Tiny-Yolov3模型参数初始化;
        Image.bgLearn()                         #learn the backgroud by pics from cam then get a background model；
        Image.checkState()                      #检测gState状态，返回 1 ；
        print("gState = 1")                     #打印gState状态；
        gState = 2                              #设置给State状态为 2 ；
    elif gState == 2:                           #判断gState状态；若为 2 ，进入run，正常交互状态；
        Image.generate()                        #
        Image.detectImage()                    #检测输入图像
        Image.checkImage()                      #check the cnn detected result by image process and image track and then update the bottle dict
        Image.checkState()                      #检测gState状态，返回 2 ；
        print("gState = 2")                     #打印gState状态；
    elif gState == 3:                           #判断gState状态；若为 3 ，进入debug，调试阶段；
        print("gState = 3")                     #打印gState状态；
        #   if ()...
        gState = 1
if __name__ == "__main__":                      #main模块
    print("please type the gState: ")
    gState = int(input())                       #手动输入gState
    while (True):
        try:                                                    # 执行main()
            main()
        except KeyboardInterrupt:
            sys.stderr.write("Keyboard interrupt.\n")
            sys.exit(main())


"""
.. module:: sensors

This module contains class definitions for sensors.
The Sensor class provides methods for handling generic sensors connected to specific pins of a board.
It also provides easily accessible attributes for useful parameters automatically evaluated during the acquisition.

Every Sensor instance implements the following methods:

    * getRaw: reads a raw value from the sensor and returns it
    * setNormFunc: sets a normalization function
    * getNormalized: read a raw value from the sensor and returns a normalized one
    * currentSample: returns last read sample
    * previousSample: returns the last but one read sample
    * doEverySample: appends to a list a function to be executed every time a get function is called
    * resetSampleActions: resets Actions list
    * addCheck: appends to a list a couple of a condition to be checked every time a get function is called the action to be executed if the condition is verified
    * resetChek: resets Checks list
    * startSampling: sets a sampling interval
    * stopSampling: clears the sampling interval
    * wait: sleeps
    * setObservationWindow: sets the length of the window used to evaluate a set of useful parameters
    * setSamplingTime: sets the private attribute _samplingTime ( use carefully )

Every Sensor instance provides the following parameters evaluated in a window of n acquisitions ( both in sampling mode and simple get calls ):

    * currentAverage: moving average for last n samples
    * currentDerivative: last sample minus penultimate sample, all divided by sampling time in seconds ( only sampling mode )
    * currentTrend: last sample minus first sample of the window, all divided by sampling time in seconds ( only sampling mode )
    * minSample: smallest sample of the window
    * maxSample: greatest sample of the window

And the following attributes to control the process of evaluation of the parameters:

    * skipEval: if True skips the whole process of evaluation
    * storeAverage: if False skips average evaluation
    * storeTrend: if False skips trend evaluation
    * storeMinMax: if False skips min and max evaluation

"""

import timers
import hwtimers

class Sensor:
    """
    ================
    The Sensor class
    ================

    .. class:: Sensor

        This is the base class for generic sensors connected to pins

    """

    def __init__(self):
        self._sampleBuffer = None
        self.storeMinMax = False
        self.storeAverage = False
        self.storeTrend = False
        self.skipEval = False
        self._currentSample = None
        self._observationWindowN = None
        self._observationWindowT = None
        self._samplingGetType = None
        self._everySampleActions = []
        self.resetCheck()
        self.highPrecision = False
        self._readFunc = None
        self.normFunc  = None
        self._samplingTimer = None

    def _resetSamplingParams(self):
        """
        .. method:: _resetSamplingParams()

            Resets sampling parameters
        """
        self._currentBufferIndex = -1
        if self.storeAverage:
            self.currentAverage = None
        if self.storeTrend:
            self.currentTrend = None
        self.currentDerivative = None
        if self.storeMinMax:
            self.minSample = None
            self.maxSample = None
        self._samplingTime = None

    def setObservationWindow(self,n):
        """
        .. method:: setObservationWindow(n)

            Sets the length of the window (n) used to evaluate a set of useful parameters.
            Needed to evaluate those parameters during manual acquisition ( calling getRaw/getNormalized functions ), in sampling mode ( entered by startSampling call ) the length is given as a parameter of startSampling method.

            **N.B.** self._samplingTime can be found set in:
                * sampling mode: setObservationWindow should not have been called
                * get mode: self._samplingTime has been manually set because samplingTime dependent parameters ( like trend and derivatived ) are necessary in a non-sampling mode ( shold be very rare )

        """
        self._observationWindowN = n
        if self._samplingTime:
            self._observationWindowT = n*self._samplingTime

    def setSamplingTime(self,time):
        """
        .. method:: setSamplingTime(time)

            Manually sets _samplingTime private attribute.

            **Use carefully**: setObservationWindow method *N.B.* section

            This attribute is automatically set when startSampling method is called.

        """
        self._samplingTime = time

    def currentSample(self):
        """
        .. method:: currentSample()

            Returns last read sample: stored as the last element of the buffer list.

            The buffer is a list of _observationWindowN elements ) if the window evaluation process is not skipped, as a private attribute otherwise.
        """
        if self.skipEval:
            return self._currentSample
        if self._currentBufferIndex != -1:
            return self._sampleBuffer[self._currentBufferIndex]

    def previousSample(self):
        """
        .. method:: previousSample()

            Returns last but one read sample: stored in the buffer list ( see currentSample() )

            **N.B.** not available if evaluation process is skipped
        """
        return self._sampleBuffer[(self._currentBufferIndex-1) % self._observationWindowN]

    def _evalParams(self,val):
#         """
#         .. method:: _evalParams(val)

#         Private method to evaluate window parameters ( currentAverage, currentDerivative, currentTrend, minSample, maxSample )
# based on current and last _observationWindowN read values.
#                 Controlled by boolean attributes: storeAverage, storeTrend, storeMinMax

#         Args:
#             val (TYPE): Description
#         """
        if self._currentBufferIndex == -1:
            self._sampleBuffer = self._observationWindowN*[None]
        self._currentBufferIndex = ((self._currentBufferIndex+1) % self._observationWindowN)
        rmSample = self.currentSample()
        #N.B.currentBufferIndex now points at oldest sample ( currentSample call )
        self._sampleBuffer[self._currentBufferIndex] = val
        if self.storeAverage:
            if self.currentAverage:
                if self.highPrecision:
                    self.currentAverage = (((self.currentAverage*self._observationWindowN)+val-rmSample)/self._observationWindowN)
                else:
                    self.currentAverage = (((self.currentAverage*self._observationWindowN)+val-rmSample)//self._observationWindowN)
            else:
                if self._currentBufferIndex == (self._observationWindowN-1):
                    if self.highPrecision:
                        self.currentAverage = (sum(self._sampleBuffer) / self._observationWindowN)
                    else:
                        self.currentAverage = (sum(self._sampleBuffer) // self._observationWindowN)
        if self.storeMinMax or self.storeTrend:
            oldestIndex  = ((self._currentBufferIndex+1) % self._observationWindowN)
            oldestSample = self._sampleBuffer[oldestIndex]
        if self._samplingTime:
            if type(self.previousSample()) != PNONE:
                if self.highPrecision:
                    self.currentDerivative = ((val - self.previousSample()) / (self._samplingTime/1000))
                else:
                    self.currentDerivative = ((val - self.previousSample()) // (self._samplingTime/1000))
            if self.storeTrend:
                if type(oldestSample) != PNONE:
                    if self.highPrecision:
                        self.currentTrend = ((val - oldestSample)/(self._observationWindowT/1000))
                    else:
                        self.currentTrend = ((val - oldestSample)//(self._observationWindowT/1000))
        if self.storeMinMax:
            if type(oldestSample) != PNONE:
                if type(self.minSample) == PNONE:
                    self.minSample = min(*self._sampleBuffer)
                    self.maxSample = max(*self._sampleBuffer)
                else:
                    ### eval min
                    if rmSample == self.minSample:
                        if val > self.minSample:
                            self.minSample = min(*self._sampleBuffer)
                        else:
                            self.minSample = val
                    else:
                        if val < self.minSample:
                            self.minSample = val
                    ### eval max
                    if rmSample == self.maxSample:
                        if val < self.maxSample:
                            self.maxSample = max(*self._sampleBuffer)
                        else:
                            self.maxSample = val
                    else:
                        if val > self.maxSample:
                            self.maxSample = val

    def _getValue(self,get_type):
#         """
# .. method:: _getValue(get_type)

#         Main acquisition method:

#             * get_type can be "raw" or "norm" that stand respectively for raw and normalized acquisition.
#             * pin can be both real pin and a tuple containing a sensor object and a parameter to read.
#             * _evalParams is called only if skipEval is False and _observationWindowN is set
#             * _everySampleActions and current object checks are performed ( see doEverySample_, addCheck_ )
#               both passing current object to these functions.

#         """
        if type(self.pin) == 0:
            val = self._readFunc(self.pin)
        elif type(self.pin) == PTUPLE:
            if self.pin[1] == "currentAverage":
                val = getattr(self.pin[0],"currentAverage")
            elif self.pin[1] == "currentDerivative":
                val = getattr(self.pin[0],"currentDerivative")
        if type(val) != PNONE:
            if get_type == "norm":
                if not self.normFunc:
                    return False
                val = self.normFunc(val,self)
            if self.skipEval:
                self._currentSample = val
            else:
                if self._observationWindowN:
                    self._evalParams(val)

            if (len(self._everySampleActions) != 0):
                for action in self._everySampleActions:
                    action(self)
            if (len(self._checkConditions) != 0):
                self._checkCurrentObj()

        return val

    def getRaw(self):
        """
        .. method:: getRaw()

            Main acquisition method for raw data

        """

        return self._getValue("raw")

    def getNormalized(self):
        """
        .. method:: getNormalized()

            Main acquisition method for normalized data
        """
        return self._getValue("norm")

    def doEverySample(self,to_do):
        """
        .. method:: doEverySample(to_do)

            Appends a function to the list of those to be executed when _getValue is called.
            **N.B.** _getValue is called both in sampling and manual acquisition mode.

            Example::

                def out(obj):
                    print(obj.currentSample())

                mySensor.doEverySample(out)

                ### 'out' is executed in both cases:
                mySensor.startSampling(...)
                mySensor.getRaw()

            Returns self to allow a compact code::

                mySensor.doEverySample(out).addCheck(...).startSampling(...)
        """
        self._everySampleActions.append(to_do)
        return self

    def resetSampleActions(self):
        """
        .. method:: resetSampleActions()

            Resets _everySampleActions list
        """
        self._everySampleActions = []

    def _checkCurrentObj(self):
#         """
# .. method:: _checkCurrentObj()

#         Iterates through _checkConditions and executed _checkFunctions if they are verified
#         """
        for i in range(0,len(self._checkFunctions)):
            if self._checkConditions[i](self):
                self._checkFunctions[i](self)

    def addCheck(self,condition,to_do):
        """
        .. method:: addCheck(condition,to_do)

            Appends a condition to those to be checked every time _getValue is called and a function to the list of those to be executed when their conditions are verified.

            'condition' must be a function that takes the current sensor object as a parameter and returns a boolean value::

                        def averageGreaterThanThreshold(obj):
                            if type(obj.currentAverage) != PNONE:
                                if obj.currentAverage > 50:
                                    return True
                                else:
                                    return False
                            else:
                                return False

            'to_do' must be a function that takes the current sensor object as a parameter and performs some actions::

                        def succeed(obj):
                            print("Average is greater than threshold!")
                            print(obj.currentAverage)

                    Returns self to allow a compact code ( see doEverySample_ )

        """
        self._checkConditions.append(condition)
        self._checkFunctions.append(to_do)
        return self

    def resetCheck(self):
        """
        .. method:: resetCheck()

            Resets _checkFunctions and _checkConditions lists
        """
        self._checkFunctions = []
        self._checkConditions = []

    def setNormFunc(self,fn):
        """
        .. method:: setNormFunc(fn)

            Sets a normalization function.
            A normalization function takes the last raw acquired value and the current sensor
            object as parameters.
            Example::

                def normalizeData(val,obj):
                    return obj.scale*(val/100)

            It is recommended to use only *static* parameters stored in current object like scale factors.
            **N.B.** in the object passed, obj.currentSample() returns the last but one read value because
            the buffer list is updated only after the normalization.

            Returns self to allow a compact code ( see doEverySample_ )
        """
        self.normFunc = fn
        return self

    def _microSample(self):
        # """
        # .. method:: _microSample()

        # Starts a loop to acquire samples every _samplingTime microseconds
        # """
        while True:
            if self._samplingTime:
                self._getValue(self._samplingGetType)
                hwtimers.sleep_micros(self._samplingTime)
            else:
                break

    def _sample(self):
        # """
        # .. method:: _sample()

        # Performs a _getValue call according to the type specified in startSampling call
        # """
        if self._samplingTime:
            self._getValue(self._samplingGetType)

    def startSampling(self,time,observation_window,get_type = "raw",time_unit = MILLIS):
        """
        .. method:: startSampling(time,observation_window,get_type,time_unit)

            Starts reading samples every _samplingTime.
            Length of _observationWindowN to evaluate window parameters ( see _evalParams_ ), type of
            acquisition ( see _getValue ) and time_unit characterize the acquisition itself.
            If no observation_window is passed the evaluation of window parameters is skipped.

            Returns self to allow a compact code ( see doEverySample_ )
        """
        self._samplingTime = time
        self._samplingGetType = get_type
        if type(observation_window) != PNONE:
            self._observationWindowN = observation_window
            self._observationWindowT = observation_window * time
        else:
            self.skipEval = True
        if time_unit == MILLIS:
            self._samplingTimer = timers.timer()
            self._samplingTimer.interval(self._samplingTime,self._sample)
        elif time_unit == MICROS:
            thread(self._microSample)
        return self

    def stopSampling(self):
        """
        .. method:: stopSampling()

            Depending on mode:

                * sampling mode: clears timer interval and stops sampling
                * non sampling mode: resets sampling parameters

            Returns self to allow a compact code ( see doEverySample_ )
        """
        if self._samplingTimer:
            self._samplingTimer.clear()
        self._resetSamplingParams()
        return self

    def wait(self,time):
        """
        .. method:: wait(time)

            Sleeps for *time* milliseconds and returns self to allow a compact code::

            mySensor.doEverySample(out).startSampling(...).wait(5000).stopSampling()
        """
        sleep(time)
        return self


import numpy as np
from scipy import stats
import pandas as pd
import uuid
from abc import ABCMeta
from copy import deepcopy

### gene regulatory network class to iterate genetic interaction and expression dynamics ###

class GeneRegulatoryNetwork():
    """Class to make a gene regulatory network for use in evo-devo simulation."""

    __metaclass__ = ABCMeta

    def __init__(self, name):
        # founder properties
        self.uuid = str(uuid.uuid1())
        self.name = str(name)
        self.n = 0
        self.c = 0.
        self.a = 0

        # to run iterations
        self.bp = 0
        self.mxi = 0
        self.epsilon = 0.
        self.wc = 10  # value tau from Siegal & Bergman
        # self.wc = 3 # works well too but may exclude oscillators

        self.df = None

        # to hold values from iterations
        self.calc_var_buffer = []
        self.sbuffer = []
        self.dbuffer = []

        # for gene expression
        self.s0 = []
        self.s = []
        self.s_final = []
        self.ref_state = []

        #holds GRN
        self.w = []

        # to mutate the founder object
        self.delta = float
        self.mutated = False
        self.nom = 0  # number of mutations
        self.mut_index = []

        # quality of individual object values
        self.stabilized = False
        self.fitness = float
        self.distance = float
        self.path_at_stability = int
        self.is_accepted = bool

        # multicellular development
        self.corpus = object
        return

    def make_grn(self, n, c, a, mxi):
        """Set up basic GRN."""
        self.n = n
        self.c = c
        self.a = a
        self.mxi = mxi

        self.sbuffer = np.zeros((self.n, self.mxi))
        self.dbuffer = np.zeros((self.n, self.mxi))

        s0 = np.ndarray((self.n, 1))
        i = 0
        for _ in s0:
            s0[i] = (np.random.choice((0, 1)) * (np.random.rand(1) < .5))
            i+=1
        del i

        self.s0 = s0
        randweights = np.random.normal(size=(self.n, self.n))
        r = np.random.rand(self.n, self.n)
        self.w = np.multiply((r < self.c), randweights)
        del s0, randweights, r

    def __calculate_variance(self, bp, values):
        """Private method to calculate variance of gene expression during development."""
        bp = bp
        mxi = self.mxi
        wc = self.wc
        if bp < mxi:
            self.sbuffer[:, bp] = np.ndarray.flatten(values)
            result = 1.0
            if bp >= wc and bp < mxi:
                sp = bp - wc
                result = np.mean(np.var(self.sbuffer[:, sp:bp], axis=1)) / (4 * self.n)  # mean of the local variance
                del sp
                self.dbuffer[:, bp] = np.var(self.sbuffer[:, 0:bp], axis=1)  # distance measure from the start
            self.bp = bp + 1
            del bp, mxi, wc
            return result

    def __calculate_distance(self, ref, test):
        dist = np.vdot(np.subtract(test, ref), np.subtract(test, ref)) / (4*self.n)
        return dist

    def sigmoid(self, a, x):
        np.seterr(all='ignore')
        r = np.round(1. / (1. + np.exp(-a * x)))
        del a, x
        return r

    def start_development(self, ss, epsilon):
        """Method to develop and grow"""
        # print('starting development')
        self.stabilized = False
        self.path_at_stability = 100
        self.s_final = []
        self.epsilon = epsilon
        self.calc_var_buffer = []
        self.sbuffer = np.zeros((self.n, self.mxi))
        self.dbuffer = np.zeros((self.n, self.mxi))

        s = ss
        w = self.w
        i = 0
        while not self.stabilized and i < self.mxi:
            s = self.sigmoid(self.a, np.dot(w, s))
            calc_var = self.__calculate_variance(i, s)
            self.calc_var_buffer.append(calc_var)
            if calc_var < self.epsilon:
                self.s_final = s
                self.stabilized = True
                self.path_at_stability = i
                self.distance = []
                self.distance = self.__calculate_distance(self.s0, self.s_final)
                # print('done developing!', self.path_at_stability)
            else:
                self.path_at_stability = i
                self.stabilized = False
                self.s_final = s
            i += 1
        return

    def mutate(self, delta, forced):
        """Method to mutate GRN, allows for new connections to be formed"""
        self.delta = np.divide(0.1,(self.c * (self.n * self.n)))
        if forced is True:
            self.delta = delta
        d = self.w
        u = np.random.uniform(0, 1, (self.n, self.n))
        mutate_mask = np.less(u,self.delta)
        self.nom = np.sum(mutate_mask)
        while self.nom == 0:
            del mutate_mask
            del d
            del u
            return
        else:
            normal_mask = u >= self.delta
            normal_w = np.multiply(normal_mask, d)
            mutant_w = np.multiply(mutate_mask, d)
            mutant_w = np.multiply(mutate_mask, np.random.normal(0, 1, (self.n, self.n)))
            rr, cc = np.nonzero(mutant_w) # find what is mutant
            self.mut_index = (rr,cc)
            # print(self.w[rr,cc]==0) # print if new connections
            new_w = normal_w + mutant_w
            self.w = new_w
            self.mutated = True
            del new_w
            del u
            del mutate_mask
            del mutant_w
            del normal_mask
            del normal_w
            del d
            return

    def perturb(self):
        self.ref_state = self.s_final
        rows, cols = np.nonzero(self.w)
        ridx = np.random.choice(rows)
        cidx = np.random.choice(cols)
        self.w[ridx][cidx] = np.random.normal(0,1)
        return

    def multicellular_development(self):
        self.corpus.coordinated = []
        self.corpus.state_buffer = []
        for cell in self.corpus.cells:
            self.s_final = []
            self.sbuffer = []
            cell.state_buffer = []
            self.start_development(cell.initial_state, self.epsilon)
            cell.final_state = self.s_final
            cell.state_buffer = self.sbuffer
            cell.path_at_stability = self.path_at_stability
            cell.stabilized = self.stabilized
            # print('cell',cell.stabilized)
            if cell.path_at_stability in self.corpus.developmental_ranges:
                self.corpus.coordinated.append(True)
            else:
                self.corpus.coordinated.append(False)
        return

    def characterize(self):
        self.df = pd.Series({
                    'uuid': self.uuid,
                    'N':self.n,
                    'c':self.c,
                    'a':self.a,
                    'mxi':self.mxi,
                    'nom':self.nom,
                    'soma':self.corpus.cells[0].path_at_stability,
                    'gonad':self.corpus.cells[1].path_at_stability,
                    'path_at_stability': self.path_at_stability,
                    'stabilized': self.stabilized,
                    's0': self.s0.flatten(),
                    's_final': self.s_final.flatten(),
                    'dev_distance': self.distance,
                })
        return

    def __deepcopy__(self, memo):
        deepcopy_method = self.__deepcopy__
        self.__deepcopy__ = None
        cp = deepcopy(self, memo)
        self.__deepcopy__ = deepcopy_method
        cp.name = str(self.uuid) + '.copy'
        cp.bp = 0
        cp.stabilized = False
        return cp

### organism class to govern GRN dynamics for simulation ###

class Organism(GeneRegulatoryNetwork):
    """Superclass of GeneRegulatoryNetwork to perform operations with"""
    pass
def generate_combinations(m, n, g, i, founder):
    """
        Function to generate all state vector combinations for a given founder.
        m = vector length, n = options [0.,1.], g = job index, i = chunk size of state space

    """
    tmp = founder
    combinations = []
    vectors = []
    paths = []
    states = []
    attractors = []
    sbuff = []
    t = g + i if g + i < (len(n) ** m) else len(n) ** m
    for num in np.arange(g, t):
        combination = []
        while num != 0:
            combination.insert(0, n[num % len(n)])
            num = int(num/len(n))
        while len(combination) < m:
            combination.insert(0, n[0])
        if combination not in combinations:
            tmp.s0 = np.reshape(combination,(m,1))
            tmp.start_development(tmp.s0, founder.epsilon)
            combinations.append(combination)
            vectors.append(tmp.s0)
            paths.append(tmp.path_at_stability)
            states.append(tmp.s_final)
            attractors.append(tmp.sbuffer[:,1])
            sbuff.append(tmp.sbuffer)
        i -= 1
        if i == 0:
            break
    return vectors, np.asarray(states).squeeze(), paths, attractors, sbuff

def state_space(founder):
    options = [0.0, 1.0]
    chunk_size = len(options)**founder.n
    gob_id = np.arange(0,1)
    plas_buffer = []
    vector_buffer = []
    state_buffer = []
    for gob in gob_id:
        gob_idx = gob_id[gob] * chunk_size
        vectors, states, plas, attractors, sbuff  = generate_combinations(founder.n, options, gob_idx, chunk_size, founder)
        plas_buffer.append(plas)
        vector_buffer.append(vectors)
        state_buffer.append(states)
    plas_buffer = np.asarray(plas_buffer).squeeze()
    vector_buffer = np.asarray(vector_buffer).squeeze()
    state_buffer = np.asarray(state_buffer).squeeze()

    return plas_buffer, vector_buffer, state_buffer

def analyze_attractors(founder, vector_buffer, state_buffer):
    """Takes a founder, all vectors and all outputs as input and generates the attractor network in one iteration"""
    # sigmoid parameter
    a=100

    # sigmoid function
    def sigmoid(a, w, s):
        np.seterr(all='ignore')
        x = np.dot(w,s)
        r = np.round(1. / (1. + np.exp(-a * x)))
        del a, x
        return r

    # founder network
    w = founder.w

    ### starting and final vectors are supplied ###

    # vector buffer of starting vectors
    vb = vector_buffer

    # final state at stability buffer
    sb = state_buffer

    # next buffer for first iteration to find the attractor network mapping ###
    nb = []

    # compute and keep the next state from the network
    for v in vb:
        nb.append(sigmoid(a,w,v))

    # create an edges list from location of final state vector found in vector_buffer
    i=0
    sedge_list = []
    sidx = []
    for s in sb:
        j=0
        for v in vb:
            x = np.equal(s,v)
            if np.sum(x)==10:
                sedge_list.append((i,j))
                sidx.append(j)
            j+=1
        i+=1

    # finding the frequencies finds how many edges each state gets
    sfreqs = stats.itemfreq(sidx)

    # create an edges list and index from first vectors in vector_buffer to location of next vector found in vector_buffer
    i=0
    nedge_list = []
    nidx = []
    for n in nb:
        j=0
        for v in vb:
            x = np.equal(n,v)
            if np.sum(x)==10:
                nedge_list.append((i,j))
                nidx.append(j)
            j+=1
        i+=1

    ### pull out the item frequencies for next states identified in nb ###
    nfreqs = stats.itemfreq(nidx)

    # split out index of unique states in state_buffer (this is also the attractor index)
    x1 = np.asarray(list([row[0] for row in sfreqs]))
    # split out frequencies of unique states in state buffer
    y1 = np.asarray(list([row[1] for row in sfreqs]))

    # pull out to store the attractors and index together in tuple
    attractors = []
    for u in x1:
        attractors.append((u,state_buffer[u]))

    att_map = []
    i=0
    for att in attractors:
        for tta in attractors:
            diffs = np.subtract(att[1], tta[1])
            steps = np.vdot(diffs, diffs)
            att_map.append(steps)
            i+=1

    att_map = np.asarray(att_map).reshape((len(attractors),len(attractors)))

    # all the unique vectors present in nb
    x2 = np.asarray(list([row[0] for row in nfreqs]))
    y2 = np.asarray(list([row[1] for row in nfreqs]))

    return att_map,attractors,(x1,y1),(x2,y2)

# find state within a reference and return index
def find_state_index(states, reference):
    """takes inputs of state vectors and compares to reference, states,
    returns linear array the length of states."""
    res = []
    for s in states:
        s=np.asarray(s)
        i=0
        while i < 1024:
            t = np.asarray(reference[i])
            tf = np.equal(s,t)
            if np.sum(tf)==10:
                res.append(i)
            i+=1
    return np.asarray(res)


from __future__ import unicode_literals

import ffmpeg
import os
from track import crawl_timestamps
from configure import configure_tracks

def splitAudioFile(filename, tracks, outputFolder = "./Tracks"):
	if not os.path.exists(outputFolder):
		os.makedirs(outputFolder)

	numTracks = len(tracks)
	for i in range(numTracks):
		track = tracks[i]
		startTime = track.startTime
		name = track.filename()

		endTime = tracks[i + 1].startTime if i + 1 < numTracks else None

		t = track.pretty()
		print(f" - Making Track ({i + 1}/{numTracks}): {t}")
		trimOne(filename, f"{outputFolder}/{name}", startTime, endTime)

def trimOne(inputFile, outputFile, startTime, endTime):
	inputArgs = {
		"ss": startTime,
		"loglevel": "warning"
	}

	if endTime != None:
		inputArgs["t"] = endTime - startTime

	stream = ffmpeg.input(inputFile, **inputArgs)
	stream = ffmpeg.output(stream, outputFile)
	ffmpeg.run(stream);

def splitUpTrack(track, desc_path, desc_format, outputFolder, metadata):
	with open(desc_path, "r") as f:
		description = f.read()

		tracks = crawl_timestamps(description, desc_format)

		print()
		for t in tracks:
			print(t.pretty())

		if metadata["artist"] == None:
			i = input("\nAre these track names & artists correct? [y/n, f=flip] ")

			if i == 'f':
				print("Ok, flipping artists and tracks for new tracklist:\n")
				separator = desc_format.split("artist")[1].split("track")[0]
				comps = desc_format.split(separator)
				rev = comps[1] + separator + comps[0]
				tracks = crawl_timestamps(description, rev)
				for t in tracks:
					print(t.pretty())
			elif i != 'y':
				print("Ok, ignoring artists...")
				tracks = crawl_timestamps(description, None)

		outputFolder = outputFolder if outputFolder != None else "./Tracks"

		print()
		splitAudioFile(track, tracks, outputFolder)

		print("\n=> Configuring Tracks...\n")
		configure_tracks(outputFolder, tracks, metadata)

		print("\n=> Done! Your tracks are at " + outputFolder)

if __name__ == "__main__":
	track = "test resources/test.m4a"
	description = "test resources/test.description"
	thumbnail = "test resources/test.jpg"

	desc_format = "artist - title"
	outputFolder = "./Tracks"

	metadata = {
		"thumbnail": thumbnail,
		"artist": None,
		"album": None
	}

	splitUpTrack(track, description, desc_format, outputFolder, metadata)