# -*- coding: utf-8 -*

######### From Segment Models #########
import segmentation_models as sm
from keras.layers import Input, Conv2D
from tensorflow.keras.optimizers import Adam, RMSprop
from keras.models import Model

if __name__ == "__main__":
    import train_utils
else:
    from . import train_utils

RESNET_BACKBONE = 'resnet34'
INCEPTION_BACKBONE = 'inceptionv3'
INCEPTION_RESNET_BACKBONE = 'inceptionresnetv2'
VGG_BACKBONE = 'vgg19'
EFFICIENTNET_BACKBONE = 'efficientnetb7'

sm.set_framework('tf.keras')
sm.framework()

###################################################################################
def get_sm_preproc_data(x_train_raw, x_test_raw, backbone):
    preprocess_input = sm.get_preprocessing(backbone)

    # preprocess input
    xtrain = preprocess_input(x_train_raw)
    xtest = preprocess_input(x_test_raw)
    return xtrain, xtest

def add_input_layer(backbone, numChannels):
    base_model = sm.Unet(backbone_name=backbone, encoder_weights='imagenet')

    input = Input(shape=(None, None, numChannels))
    l1 = Conv2D(3, (1, 1))(input) # map N channels data to 3 channels
    output = base_model(l1)

    model = Model(inputs=input, outputs=output, name=base_model.name)
    return model

def get_target_backbone(backbone):
    if 'inceptionresnet' in backbone:
        target_backbone = INCEPTION_RESNET_BACKBONE
    elif 'resnet' in backbone:
        target_backbone = RESNET_BACKBONE
    elif 'inception' in backbone:
        target_backbone = INCEPTION_BACKBONE
    elif 'efficientnet' in backbone:
        target_backbone = EFFICIENTNET_BACKBONE
    elif 'vgg' in backbone:
        target_backbone = VGG_BACKBONE
    return target_backbone

def get_sm_model(backbone, height, width, numChannels, numClasses):
    target_backbone = get_target_backbone(backbone)
    if 'pretrained' in backbone:
        model = add_input_layer(target_backbone, numChannels)
    else:
        model = sm.Unet(target_backbone, input_shape=(None, None, numChannels), encoder_weights=None, classes=numClasses)
    return model

def build_sm_model(framework, x_train_raw, x_test_raw, height, width, numChannels, numClasses,
        optimizerName = "Adam", learning_rate =  0.0001, decay = 0, lossFunction = "BCE+JC"):

    target_backbone = get_target_backbone(framework)
    x_train_preproc, x_test_preproc = get_sm_preproc_data(x_train_raw, x_test_raw, target_backbone)
    model = get_sm_model(framework, height, width, numChannels, numClasses)
    model = train_utils.compile_custom(framework, model, optimizerName, learning_rate, decay, lossFunction)

    return model, x_train_preproc, x_test_preproc

def fit_sm_model(framework, x_train_raw, ytrain, x_test_raw, ytest, height, width, numChannels, numClasses, numEpochs,
    optimizerName = "Adam", learning_rate =  0.0001, decay = 0, lossFunction = "BCE+JC"):

    model, x_train_prep, x_test_prep = build_sm_model(framework, x_train_raw, x_test_raw, height, width, numChannels,
        numClasses,  optimizerName, learning_rate, decay, lossFunction)

    model, history = train_utils.fit_model(framework, model, x_train_prep, ytrain, x_test_prep, ytest, numEpochs, batchSize = 64)

    return model, history


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

# Scrapy settings for imgdl project
#
# For simplicity, this file contains only the most important settings by
# default. All the other settings are documented here:
#
#     http://doc.scrapy.org/en/latest/topics/settings.html
#
import os

current_dir = os.path.dirname(os.path.realpath(__file__))

BOT_NAME = 'imgdl'

SPIDER_MODULES = ['imgdl.spiders']
NEWSPIDER_MODULE = 'imgdl.spiders'

# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'imgdl (+http://www.yourdomain.com)'

# 抓取频率
DOWNLOAD_DELAY = 0.25      # 250 ms of delay
# 页面抓取深度
DEPTH_LIMIT = 2
# 保存结果
DOWNLOAD_HANDLERS = {
    'file': 'scrapy.core.downloader.handlers.file.FileDownloadHandler',
}
# http://doc.scrapy.org/en/latest/topics/images.html#enabling-your-images-pipeline
ITEM_PIPELINES = {
    # Enabling your Images Pipeline
    'scrapy.contrib.pipeline.images.ImagesPipeline': 1
}
IMAGES_STORE = os.path.join(current_dir, 'images')
# 90 days of delay for image expiration
# IMAGES_EXPIRES = 90
# # 略缩图
# IMAGES_THUMBS = {
#     'small': (50, 50),
#     'big': (270, 270),
# }
# # 最小图片
# IMAGES_MIN_HEIGHT = 110
# IMAGES_MIN_WIDTH = 110


# https://www.hackerearth.com/practice/basic-programming/bit-manipulation/basics-of-bit-manipulation/practice-problems/algorithm/mattey-multiplication-6/

def solution():
    T = int(input())
    for i in range(T):
        N, M = map(int, input().strip().split())
        bin_m = "{0:b}".format(M)
        bin_m_len = len(bin_m)

        result = []
        for i in range(bin_m_len):
            if bin_m[i] == '1':
                result.append(f'({N}<<{bin_m_len - i - 1})')

        print(*result, sep=' + ')

solution()

02-BIT MANIPULATION/02 - hackerearth - Mattey Multiplication.py


from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils import to_categorical
from keras.layers import Dense, Input, LSTM, Embedding, Dropout, Activation, CuDNNGRU, Conv1D
from keras.layers import Bidirectional, GlobalMaxPool1D, CuDNNLSTM
from keras.models import Model

import numpy as np
import pandas as pd
import keras
import os
import re
from tqdm import tqdm
tqdm.pandas()

## 特殊符號
def clean_text(x):
    x = str(x)
    for punct in "/-'":
        x = x.replace(punct, ' ')
    for punct in '&':
        x = x.replace(punct, f' {punct} ')
    for punct in '?!.,"#$%\'()*+-/:;<=>@[\\]^_`{|}~' + '“”’':
        x = x.replace(punct, '')
    return x

## 二位數～五位數的數字
def clean_numbers(x):
    x = re.sub('[0-9]{5,}', '#####', x)
    x = re.sub('[0-9]{4}', '####', x)
    x = re.sub('[0-9]{3}', '###', x)
    x = re.sub('[0-9]{2}', '##', x)
    return x

## 一些單字的統稱、過去式跟現在式統一
def _get_mispell(mispell_dict):
    mispell_re = re.compile('(%s)' % '|'.join(mispell_dict.keys()))
    return mispell_dict, mispell_re

mispell_dict = {'colour':'color',
                'centre':'center',
                'didnt':'did not',
                'doesnt':'does not',
                'isnt':'is not',
                'shouldnt':'should not',
                'favourite':'favorite',
                'travelling':'traveling',
                'counselling':'counseling',
                'theatre':'theater',
                'cancelled':'canceled',
                'labour':'labor',
                'organisation':'organization',
                'wwii':'world war 2',
                'citicise':'criticize',
                'instagram': 'social medium',
                'whatsapp': 'social medium',
                'snapchat': 'social medium'
                }
mispellings, mispellings_re = _get_mispell(mispell_dict)

def replace_typical_misspell(text):
    def replace(match):
        return mispellings[match.group(0)]
    return mispellings_re.sub(replace, text)
test = pd.read_csv('../input/test.csv')
train = pd.read_csv('../input/train.csv')
print(test.shape)
print(train.shape)
MAX_NB_WORDS = 50000
EMBEDDING_DIM = 300
MAX_SEQUENCE_LENGTH = 50
y_train = train['target'].values
#train
# train[train['target']==1]
# train.loc[0]['question_text']
# train['question_text'].values
# Clean the text
train["question_text"] = train["question_text"].progress_apply(lambda x: clean_text(x))
test["question_text"] = test["question_text"].progress_apply(lambda x: clean_text(x))

# Clean numbers
train["question_text"] = train["question_text"].progress_apply(lambda x: clean_numbers(x))
test["question_text"] = test["question_text"].progress_apply(lambda x: clean_numbers(x))

# Clean speelings
train["question_text"] = train["question_text"].progress_apply(lambda x: replace_typical_misspell(x))
test["question_text"] = test["question_text"].progress_apply(lambda x: replace_typical_misspell(x))

# fill up the missing values
# train_X = train["question_text"].fillna("_##_").values
# test_X = test["question_text"].fillna("_##_").values
# load embeddings
embeddings_glove = {}
with open ('../input/embeddings/glove.840B.300d/glove.840B.300d.txt', 'r', encoding='UTF-8') as f:
    for line in f.readlines():
        line = line.split(" ")
        key = line[0]
        values = np.asarray(line[1:], dtype='float32')
        embeddings_glove[key] = values
#         print(key)
embeddings_glove['a']
# create token 建token表
token = Tokenizer(num_words=MAX_NB_WORDS)
token.fit_on_texts(list(train['question_text'].values))
token.word_index
# 利用建好的token表，將問題字串轉換
x_train = token.texts_to_sequences(train['question_text'].fillna("_##_").values)
x_test = token.texts_to_sequences(test['question_text'].fillna("_##_").values)
print(train['question_text'].values[0])
print(x_train[0])
# 將問題字串截長補短
x_train = pad_sequences(x_train, maxlen=MAX_SEQUENCE_LENGTH)
x_test = pad_sequences(x_test, maxlen=MAX_SEQUENCE_LENGTH)
print(x_train[0])
num_words = min(MAX_NB_WORDS, len(token.word_index))
num_words
embedding_matrix = np.zeros((num_words, EMBEDDING_DIM))
# print(embedding_matrix)
embedding_matrix.shape
for word, i in token.word_index.items():
    if i >= MAX_NB_WORDS:
        continue
    embedding_vector = embeddings_glove.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector
embedding_matrix
embedding_layer = Embedding(num_words,
                            EMBEDDING_DIM,
                            weights=[embedding_matrix],
                            input_length=MAX_SEQUENCE_LENGTH,
                            trainable=False)
inp = Input(shape=(MAX_SEQUENCE_LENGTH,))
x = embedding_layer(inp)
x = Bidirectional(CuDNNGRU(64, return_sequences=True))(x)
x = Bidirectional(CuDNNGRU(64))(x)
x = Dropout(0.2)(x)
x = Dense(1, activation="sigmoid")(x)
model = Model(inputs=inp, outputs=x)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

print(model.summary())
model.fit(x_train, y_train,
          batch_size=128,
          epochs=8,
          validation_split=0.1)
glove_test_y  = model.predict(x_test, batch_size=128, verbose=1)
# for i in glove_test_y:
#     print(i)
test_y = (glove_test_y>0.4).astype(int)
out = pd.DataFrame({"qid":test["qid"].values})
out['prediction'] = test_y
out.to_csv("submission.csv", index=False)


# -*- coding: utf-8 -*-
import onnx
import time
import numpy as np
import onnxruntime as rt
from onnx import checker
from onnx import helper
from onnx import TensorProto

def conver_rknn_tensor_type_to_onnx_type(tensor_dtype):
    datatype = tensor_dtype.split("_")[-1]
    if datatype == "INT8":
        return TensorProto.INT8
    elif datatype == "UINT8":
        return TensorProto.UINT8
    elif datatype == "INT16":
        return TensorProto.INT16
    elif datatype == "UINT16":
        return TensorProto.UINT16
    elif datatype == "INT32":
        return TensorProto.INT32
    elif datatype == "UINT32":
        return TensorProto.UINT32
    elif datatype == "FLOAT16":
        return TensorProto.FLOAT16
    elif datatype == "FLOAT32":
        return TensorProto.FLOAT
    elif datatype == "BOOL8":
        return TensorProto.BOOL
    else:
        assert False, "unspoorted datatype {}, when convert rknn tensor type to onnx type".format(datatype)

def conver_rknn_tensor_type_to_numpy_type(tensor_dtype):
    datatype = tensor_dtype.split("_")[-1]
    if datatype == "INT8":
        return np.int8
    elif datatype == "UINT8":
        return np.uint8
    elif datatype == "INT16":
        return np.int16
    elif datatype == "UINT16":
        return np.uint16
    elif datatype == "INT32":
        return np.int32
    elif datatype == "UINT32":
        return np.uint32
    elif datatype == "FLOAT16":
        return np.float16
    elif datatype == "FLOAT32":
        return np.float32
    elif datatype == "BOOL8":
        return np.bool
    else:
        assert False, "unspoorted datatype {}, when convert rknn tensor type to np type".format(datatype)

def convert_onnxruntime_type_to_numpy_dtype(onnxruntime_type):
    if onnxruntime_type == "tensor(int8)":
        return np.int8
    elif onnxruntime_type == "tensor(uint8)":
        return np.uint8
    elif onnxruntime_type == "tensor(int16)":
        return np.int16
    elif onnxruntime_type == "tensor(uint16)":
        return np.uint16
    elif onnxruntime_type == "tensor(int32)":
        return np.int32
    elif onnxruntime_type == "tensor(uint32)":
        return np.uint32
    elif onnxruntime_type == "tensor(float16)":
        return np.float16
    elif onnxruntime_type == "tensor(float)":
        return np.float32
    elif onnxruntime_type == "tensor(bool)":
        return np.bool
    else:
        assert False, "unspoorted datatype {}, when convert rknn tensor type to np type".format(onnxruntime_type)

def construct_pool_attr(op_attr):
    node_attr = {}
    for key in op_attr.keys():
        if key == "round_type":
            round_type = op_attr[key]
            if round_type == "VSI_NN_ROUND_CEIL":
                node_attr["ceil_mode"] = 1
            elif round_type == "VSI_NN_ROUND_FLOOR":
                node_attr["ceil_mode"] = 0
            else:
                assert False, "unsupported pool round type {}".format(round_type)
        elif key == "type":
            continue
        elif key == "ksize":
            node_attr["kernel_shape"] = op_attr[key]
        elif key == "stride":
            node_attr["strides"] = op_attr[key]
        elif key == "pad":
            node_attr["pads"] = op_attr[key]
        else:
            assert False, "unsupported pool attribute {}".format(key)
    return node_attr

def construct_node_attr(node_info):
    node_attr = {}
    if node_info["type"] == "POOL":
        op_attr = node_info["attribute"]["pool"]
        node_attr = construct_pool_attr(op_attr)

    return node_attr

def get_rknn_tensor_info(rknn_model_info, tensor_name):
    tensors_info = rknn_model_info["tensors"]
    for key in tensors_info.keys():
        if key == tensor_name:
            return tensors_info[key]
    assert False, "rknn model have no tensor: {}".format(tensor_name)

def insert_dequant_node(quant_input_tensor_info, onnx_model_info, log_flag):
    tensor_name = quant_input_tensor_info["name"]
    node_name = tensor_name + "_dequant"
    dequant_out_name = tensor_name + "_dequant_out"
    inserted = False
    for node_index in range(len(onnx_model_info["nodes"])):
        node = onnx_model_info["nodes"][node_index]
        if node.name == node_name:
            inserted = True
            break
    if not inserted:
        op_inputs = []
        op_inputs.append(tensor_name)
        op_inputs.append(tensor_name+"_scale")
        op_inputs.append(tensor_name+"_zero_point")
        op_outputs = []
        op_outputs.append(dequant_out_name)
        node = helper.make_node("DequantizeLinear", inputs=op_inputs, outputs=op_outputs, name=node_name)
        onnx_model_info["nodes"].append(node)
        if log_flag:
            print("insert dequant node for {}".format(tensor_name))
    return dequant_out_name

def insert_quant_node(dequant_out_tensor_info, quant_input_name, onnx_model_info, log_flag):
    tensor_name = dequant_out_tensor_info["name"]
    node_name = tensor_name + "_quant"
    op_inputs = []
    op_inputs.append(quant_input_name)
    op_inputs.append(tensor_name+"_scale")
    op_inputs.append(tensor_name+"_zero_point")
    op_outputs = []
    op_outputs.append(tensor_name)
    node = helper.make_node("QuantizeLinear", inputs=op_inputs, outputs=op_outputs, name=node_name)
    onnx_model_info["nodes"].append(node)
    if log_flag:
        print("insert dequant node for {}".format(tensor_name))

def construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    op_inputs = []
    for index in range(len(input_names)):
        op_inputs.append(input_names[index])
    op_outputs = []
    for index in range(len(output_names)):
        op_outputs.append(output_names[index])

    for index in range(len(op_inputs)):
        input_tensor_info = get_rknn_tensor_info(rknn_model_info, op_inputs[index])
        input_dtype = conver_rknn_tensor_type_to_onnx_type(input_tensor_info["dtype"]["vx_type"])
        if input_dtype == TensorProto.UINT8 or \
            input_dtype == TensorProto.INT8:
            quant_input_tensor_info = {}
            quant_input_tensor_info["name"] = op_inputs[index]
            quant_input_tensor_info["dtype"] = input_tensor_info["dtype"]
            dequant_out_name = insert_dequant_node(quant_input_tensor_info, onnx_model_info, log_flag)
            op_inputs[index] = dequant_out_name

    need_quant = []
    quant_inputs = []
    for index in range(len(op_outputs)):
        output_tensor_info = get_rknn_tensor_info(rknn_model_info, op_outputs[index])
        output_dtype = conver_rknn_tensor_type_to_onnx_type(output_tensor_info["dtype"]["vx_type"])
        need_quant.append(False)
        quant_inputs.append(None)
        if output_dtype == TensorProto.UINT8 or \
            output_dtype == TensorProto.INT8:
            need_quant[-1] = True
            op_outputs[index] = op_outputs[index] + "_quant_input"
            quant_inputs[-1] = op_outputs[index]

    node_name = node_info["name"]
    if log_flag:
        print("node_name  : {}".format(node_name))
        print("node_input : {}".format(op_inputs))
        print("node_output: {}".format(op_outputs))

    node_attr = construct_node_attr(node_info)
    if len(node_attr.keys()) > 0:
        node = helper.make_node(onnx_op_name, inputs=op_inputs, outputs=op_outputs, name=node_name, **node_attr)
    else:
        node = helper.make_node(onnx_op_name, inputs=op_inputs, outputs=op_outputs, name=node_name)
    onnx_model_info["nodes"].append(node)

    for index in range(len(need_quant)):
        if need_quant[index]:
            quant_input_name = quant_inputs[index]
            dequant_out_tensor_info = {}
            dequant_out_tensor_info["name"] = output_names[index]
            dequant_out_tensor_info["dtype"] = output_tensor_info["dtype"]
            insert_quant_node(dequant_out_tensor_info, quant_input_name, onnx_model_info, log_flag)

def construct_sigmoid_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn sigmoid op should have 1 input"
    assert len(output_names) == 1, "rknn sigmoid op should have 1 output"
    construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag)
    return True

def construct_add_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 2, "rknn add op should have 2 input"
    assert len(output_names) == 1, "rknn add op should have 1 output"
    construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag)
    return True

def construct_relu_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn relu op should have 1 input"
    assert len(output_names) == 1, "rknn relu op should have 1 output"
    construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag)
    return True

def construct_conv2d_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 2 or len(input_names) == 3, "rknn conv2d op should have 2 or 3 input"
    assert len(output_names) == 1, "rknn conv2d op should have 1 output"
    op_inputs = []
    for index in range(len(input_names)):
        if index > 1:
            break
        op_inputs.append(input_names[index])
        op_inputs.append(input_names[index]+"_scale")
        op_inputs.append(input_names[index]+"_zero_point")
    op_inputs.append(output_names[0]+"_scale")
    op_inputs.append(output_names[0]+"_zero_point")
    if len(input_names) == 3:
        op_inputs.append(input_names[2])
        tensor_info = get_rknn_tensor_info(rknn_model_info, input_names[2])
        if tensor_info["dtype"]["zero_point"] != 0:
            print(tensor_info)
    op_outputs = []
    for index in range(len(output_names)):
        op_outputs.append(output_names[index])
    op_attr = node_info["attribute"]["conv2d"]
    if "ksize" in op_attr.keys():
        kernel_shape = op_attr["ksize"]

    if "group" in op_attr.keys():
        group = op_attr["group"]

    if "dilation" in op_attr.keys():
        dilations = op_attr["dilation"]

    if "stride" in op_attr.keys():
        strides = op_attr["stride"]

    if "pad" in op_attr.keys():
        pads = op_attr["pad"]

    node_name = node_info["name"]
    if log_flag:
        print("node_name  : {}".format(node_name))
        print("node_input : {}".format(op_inputs))
        print("node_output: {}".format(op_outputs))
        print("kenel_shape: {}".format(kernel_shape))
        print("group     : {}".format(group))
        print("dilations  : {}".format(dilations))
        print("strides    : {}".format(strides))
        print("pads       : {}".format(pads))

    node = helper.make_node(onnx_op_name, inputs=op_inputs, outputs=op_outputs, name=node_name,
        kernel_shape=kernel_shape,
        group=group,
        dilations=dilations,
        strides=strides,
        pads=pads)
    onnx_model_info["nodes"].append(node)
    return True

def construct_constant_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn variable op should have 1 input"
    assert len(output_names) == 1, "rknn variable op should have 1 output"
    # replace node input tensor name(virtural tensor) with virable node input tensor(const tensor), to simulate constant op
    replace_nodes = []
    nodes = rknn_model_info["nodes"]
    for index in range(len(nodes)):
        node = nodes[index]
        for input_index in range(len(node["inputs"])):
            if output_names[0] == node["inputs"][input_index]:
                node["inputs"][input_index] = input_names[0]
                replace_nodes.append(node["name"])
    if log_flag:
        for node in replace_nodes:
            print("replace node {} input with const tensor".format(node))
    return True

def construct_transpose_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn permute op should have 1 input"
    assert len(output_names) == 1, "rknn permute op should have 1 output"
    op_inputs = []
    for index in range(len(input_names)):
        op_inputs.append(input_names[index])
    op_outputs = []
    for index in range(len(output_names)):
        op_outputs.append(output_names[index])
    op_attr = node_info["attribute"]["permute"]
    assert "perm" in op_attr.keys(), "rknn permute op should have perm attribute"
    if "perm" in op_attr.keys():
        perm = op_attr["perm"]
    node_name = node_info["name"]
    node = helper.make_node(onnx_op_name,
        inputs=op_inputs,
        outputs=op_outputs,
        name=node_name,
        perm=perm)
    onnx_model_info["nodes"].append(node)
    return True

def construct_reshape_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn reshape op should have 1 input"
    assert len(output_names) == 1, "rknn reshape op should have 1 output"
    op_inputs = []
    for index in range(len(input_names)):
        op_inputs.append(input_names[index])
    op_outputs = []
    for index in range(len(output_names)):
        op_outputs.append(output_names[index])
    op_attr = node_info["attribute"]["reshape"]
    assert "size" in op_attr.keys(), "rknn reshape op should have size attribute"
    assert "dim_num" in op_attr.keys(), "rknn reshape op should have dim_num attribute"
    dim_num = op_attr["dim_num"]
    size = op_attr["size"]
    assert dim_num == len(size), "rknn reshape op attribute dim_num not equal to len of attribute size"
    node_name = node_info["name"]
    reshape_shape_tesnor_name = node_name + "_shape"
    reshape_shape_tesnor_type = TensorProto.INT64
    reshape_shape_tesnor_shape = np.array(size, dtype=np.int64).shape
    reshape_shape_tesnor_data = size
    reshape_shape_tesnor = helper.make_tensor(reshape_shape_tesnor_name,
        reshape_shape_tesnor_type,
        reshape_shape_tesnor_shape,
        reshape_shape_tesnor_data)
    onnx_model_info["initializers"].append(reshape_shape_tesnor)
    op_inputs.append(reshape_shape_tesnor_name)
    node = helper.make_node(onnx_op_name,
        inputs=op_inputs,
        outputs=op_outputs,
        name=node_name)
    onnx_model_info["nodes"].append(node)
    return True

def pre_run(onnx_model_info, out_tensor_name):
    ori_outputs = onnx_model_info["outputs"]
    onnx_model_info["outputs"] = []
    out_tensor_value_info = helper.make_tensor_value_info(out_tensor_name, TensorProto.UINT8, [-1,-1,-1,-1])
    onnx_model_info["outputs"].append(out_tensor_value_info)
    time_stamp = time.localtime()
    doc_string = "created on {}".format(time.strftime('%Y-%m-%d %H-%M-%S', time_stamp))
    onnx_initializer_list = onnx_model_info["initializers"]
    onnx_input_list = onnx_model_info["inputs"]
    onnx_output_list = onnx_model_info["outputs"]
    onnx_node_list = onnx_model_info["nodes"]
    onnx_graph_def = helper.make_graph(onnx_node_list, 'rknn_graph', onnx_input_list, onnx_output_list, initializer=onnx_initializer_list, doc_string=doc_string)
    op = onnx.OperatorSetIdProto()
    op.version = 11
    onnx_mode_def = helper.make_model(onnx_graph_def, producer_name='rknn_parser', opset_imports=[op])
    onnx_mode_def.ir_version = 6
    onnx.save_model(onnx_mode_def, "shape_infer.onnx")
    sess = rt.InferenceSession("shape_infer.onnx")
    onnx_input = {}
    for input in sess.get_inputs():
        input_name = input.name
        input_shape = input.shape
        input_dtype = convert_onnxruntime_type_to_numpy_dtype(input.type)
        input_data = np.array(np.zeros(input_shape)).astype(input_dtype)
        onnx_input[input_name] = input_data
    pred_out = sess.run([out_tensor_name,], onnx_input)
    onnx_model_info["outputs"] = ori_outputs
    return list(pred_out[0].shape)

def construct_resize_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn resize op should have 1 input"
    assert len(output_names) == 1, "rknn resize op should have 1 output"
    op_inputs = []
    for index in range(len(input_names)):
        op_inputs.append(input_names[index])
    op_outputs = []
    for index in range(len(output_names)):
        op_outputs.append(output_names[index])
    node_name = node_info["name"]
    op_attr = node_info["attribute"]["resize"]
    if op_attr["type"] == 'VSI_NN_INTERPOLATION_NEAREST_NEIGHBOR':
        mode = "nearest"

    roi_init_tensor_name = node_name + "_roi"
    roi_init_tensor_type = TensorProto.FLOAT
    roi_init_tensor_shape = [0]
    roi_init_tensor_data = []
    roi_tesnor_def = helper.make_tensor(roi_init_tensor_name,
        roi_init_tensor_type,
        roi_init_tensor_shape,
        roi_init_tensor_data)
    onnx_model_info["initializers"].append(roi_tesnor_def)
    op_inputs.append(roi_init_tensor_name)

    scales_init_tensor_name = node_name + "_scales"
    scales_init_tensor_type = TensorProto.FLOAT
    scales_init_tensor_shape = [0]
    scales_init_tensor_data = []
    scales_tesnor_def = helper.make_tensor(scales_init_tensor_name,
        scales_init_tensor_type,
        scales_init_tensor_shape,
        scales_init_tensor_data)
    onnx_model_info["initializers"].append(scales_tesnor_def)
    op_inputs.append(scales_init_tensor_name)

    expect_shape = pre_run(onnx_model_info, op_inputs[0])
    sizes_init_tensor_name = node_name + "_sizes"
    sizes_init_tensor_type = TensorProto.INT64
    sizes_init_tensor_shape = [len(expect_shape),]
    sizes_init_tensor_data = expect_shape
    if len(op_attr["size"]) < 4:
        start = len(expect_shape) - len(op_attr["size"])
        sizes_init_tensor_data[start:] = op_attr["size"]

    sizes_tesnor_def = helper.make_tensor(sizes_init_tensor_name,
        sizes_init_tensor_type,
        sizes_init_tensor_shape,
        sizes_init_tensor_data)
    onnx_model_info["initializers"].append(sizes_tesnor_def)
    op_inputs.append(sizes_init_tensor_name)

    node = helper.make_node(onnx_op_name,
        inputs=op_inputs,
        outputs=op_outputs,
        name=node_name,
        mode=mode)
    onnx_model_info["nodes"].append(node)

    # expect_shape = pre_run(onnx_model_info, op_outputs[0])
    return True

def construct_mul_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 2, "rknn multiply op should have 2 input"
    assert len(output_names) == 1, "rknn multiply op should have 1 output"
    construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag)
    return True

def construct_pool_op(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag):
    node_info = rknn_model_info["nodes"][node_index]
    input_names = node_info["inputs"]
    output_names = node_info["outputs"]
    assert len(input_names) == 1, "rknn pool op should have 1 input"
    assert len(output_names) == 1, "rknn pool op should have 1 output"
    construct_with_dequant_quant_node(rknn_op_name, onnx_op_name, rknn_model_info, node_index, onnx_model_info, log_flag)
    return True

def get_actual_onnx_name(onnx_op_name, rknn_model_info, node_index):
    node_info = rknn_model_info["nodes"][node_index]
    if onnx_op_name == "Pool":
        op_attr = node_info["attribute"]
        if op_attr["pool"]["type"] == "VX_CONVOLUTIONAL_NETWORK_POOLING_MAX":
            return "MaxPool"
        elif op_attr["pool"]["type"] == "VX_CONVOLUTIONAL_NETWORK_POOLING_AVG":
            return "AveragePool"
        else:
            assert False, "unspported {} pool type".format(op_attr["pool"]["type"])
    return onnx_op_name

class ConstructOnnxOp(object):
    op_construct_funcs = {}
    rknn_op_onnx_op_map = {}
    def register(self, rknn_op_name, onnx_op_name, op_func):
        if rknn_op_name not in self.rknn_op_onnx_op_map.keys():
            self.rknn_op_onnx_op_map[rknn_op_name] = onnx_op_name
            self.op_construct_funcs[onnx_op_name] = op_func
        else:
            print("already register {}".format(rknn_op_name))

    def construct_node(self, rknn_model_info, node_index, onnx_model_info, log_flag = False):
        node_info = rknn_model_info["nodes"][node_index]
        rknn_op_name = node_info['type']
        if rknn_op_name not in self.rknn_op_onnx_op_map.keys():
            print("have not register {}".format(rknn_op_name))
            return False
        else:
            onnx_op_name = self.rknn_op_onnx_op_map[rknn_op_name]
            actual_onnx_op_name = get_actual_onnx_name(onnx_op_name, rknn_model_info, node_index)
            if log_flag:
                print("{}: --------------- convert {} to {}".format(node_index, rknn_op_name, actual_onnx_op_name))
                node_input_list = node_info['input']
                node_output_list = node_info['output']
                for index in range(len(node_input_list)):
                    input_name = node_input_list[index]
                    print("input {}: {}".format(index, input_name))
                for index in range(len(node_output_list)):
                    output_name = node_output_list[index]
                    print("output {}: {}".format(index, output_name))

            convert_flag = self.op_construct_funcs[onnx_op_name](
                rknn_op_name,
                actual_onnx_op_name,
                rknn_model_info,
                node_index,
                onnx_model_info,
                log_flag)
            return convert_flag

def init_onnx_construct_obj():
    onnx_obj = ConstructOnnxOp()
    onnx_obj.register('SIGMOID', 'Sigmoid', construct_sigmoid_op)
    onnx_obj.register('ADD', 'Add', construct_add_op)
    onnx_obj.register('RELU', 'Relu', construct_relu_op)
    onnx_obj.register('CONV2D', 'QLinearConv', construct_conv2d_op)
    onnx_obj.register('VARIABLE', 'Constant', construct_constant_op)
    onnx_obj.register('PERMUTE', 'Transpose', construct_transpose_op)
    onnx_obj.register('RESHAPE', 'Reshape', construct_reshape_op)
    onnx_obj.register('RESIZE', 'Resize', construct_resize_op)
    onnx_obj.register('MULTIPLY', 'Mul', construct_mul_op)
    onnx_obj.register("POOL", "Pool", construct_pool_op)
    return onnx_obj

def constrtut_graph_initializer(rknn_model_info, layout="WHCN", log_flag=False):
    initializer_list = []
    tensor_info = rknn_model_info["tensors"]
    for tensor_name in tensor_info.keys():
        onnx_const_tensor_list = []
        tensor = tensor_info[tensor_name]
        if "norm_tensor" in tensor_name:
            continue
        onnx_dtype = conver_rknn_tensor_type_to_onnx_type(tensor["dtype"]["vx_type"])
        np_dtype = conver_rknn_tensor_type_to_numpy_type(tensor["dtype"]["vx_type"])
        if "const_tensor" in tensor_name:
            # init weight data
            shape = tensor["shape"][::-1]
            weight_data_arr = np.frombuffer(tensor["raw_data"], dtype=np_dtype).reshape(shape)
            # if layout == "WHCN":
            #     shape_len = len(tensor["shape"])
            #     transpose_axes = [shape_len - i - 1 for i in range(shape_len)]
            #     weight_data_arr = np.transpose(weight_data_arr, transpose_axes)

            onnx_const_tensor = {}
            onnx_const_tensor["name"] = tensor_name
            onnx_const_tensor["type"] = onnx_dtype
            onnx_const_tensor["shape"] = weight_data_arr.shape
            onnx_const_tensor["data"] = weight_data_arr
            onnx_const_tensor_list.append(onnx_const_tensor)

        # init scale
        if isinstance(tensor["dtype"]["scale"], list):
            scale_data_arr = np.array(tensor["dtype"]["scale"]).astype(np.float32)
        else:
            scale_data_arr = np.array([tensor["dtype"]["scale"],]).astype(np.float32)
        # init zero point
        if isinstance(tensor["dtype"]["zero_point"], list):
            zero_point_data_arr = np.array(tensor["dtype"]["zero_point"]).astype(np_dtype)
        else:
            zero_point_data_arr = np.array([tensor["dtype"]["zero_point"],]).astype(np_dtype)

        onnx_const_tensor = {}
        onnx_const_tensor["name"] = tensor_name + "_scale"
        onnx_const_tensor["type"] = TensorProto.FLOAT
        onnx_const_tensor["shape"] = scale_data_arr.shape
        onnx_const_tensor["data"] = scale_data_arr
        onnx_const_tensor_list.append(onnx_const_tensor)

        onnx_const_tensor = {}
        onnx_const_tensor["name"] = tensor_name + "_zero_point"
        onnx_const_tensor["type"] = onnx_dtype
        onnx_const_tensor["shape"] = zero_point_data_arr.shape
        onnx_const_tensor["data"] = zero_point_data_arr
        onnx_const_tensor_list.append(onnx_const_tensor)

        for index in range(len(onnx_const_tensor_list)):
            init_tensor_name = onnx_const_tensor_list[index]["name"]
            init_tensor_type = onnx_const_tensor_list[index]["type"]
            init_tensor_shape = onnx_const_tensor_list[index]["shape"]
            init_tensor_data = onnx_const_tensor_list[index]["data"].flatten().tolist()
            if log_flag:
                print("construct const tensor with:")
                print("tensor name: {}".format(init_tensor_name))
                print("tensor shape: {}".format(init_tensor_shape))
                print("tensor type: {}".format(init_tensor_type))
                print("tensor data: {}".format(init_tensor_data))
            tesnor_def = helper.make_tensor(init_tensor_name, init_tensor_type, init_tensor_shape, init_tensor_data)
            initializer_list.append(tesnor_def)
    return initializer_list

def constrtut_graph_input_output(rknn_model_info, layout="WHCN", log_flag=False):
    input_list = []
    output_list = []
    initializer_list = []
    tensor_info = rknn_model_info["tensors"]
    input_names = []
    for input in rknn_model_info["inputs"]:
        input_names.append(input["tensor_info"]["url"])
    output_names = []
    for output in rknn_model_info["outputs"]:
        output_names.append(output["tensor_info"]["url"])
    for tensor_name in tensor_info.keys():
        tensor = tensor_info[tensor_name]
        if "norm_tensor" in tensor_name:
            onnx_dtype = conver_rknn_tensor_type_to_onnx_type(tensor["dtype"]["vx_type"])
            np_dtype = conver_rknn_tensor_type_to_numpy_type(tensor["dtype"]["vx_type"])
            # init scale
            if isinstance(tensor["dtype"]["scale"], list):
                scale_data_arr = np.array(tensor["dtype"]["scale"]).astype(np.float32)
            else:
                scale_data_arr = np.array([tensor["dtype"]["scale"],]).astype(np.float32)
            # init zero point
            if isinstance(tensor["dtype"]["zero_point"], list):
                zero_point_data_arr = np.array(tensor["dtype"]["zero_point"]).astype(np_dtype)
            else:
                zero_point_data_arr = np.array([tensor["dtype"]["zero_point"],]).astype(np_dtype)

            if layout == "WHCN":
                tensor_shape = tensor["shape"][::-1]
            onnx_norm_tensor_value_info = helper.make_tensor_value_info(tensor_name, onnx_dtype, tensor_shape)
            if tensor['url'] in input_names:
                input_list.append(onnx_norm_tensor_value_info)
            elif tensor['url'] in output_names:
                output_list.append(onnx_norm_tensor_value_info)
            else:
                assert False, "unrecognize norm tensor {}".format(tensor_name)
            if log_flag:
                print("construct norm tensor with:")
                print("tensor name: {}".format(tensor_name))
                print("tensor shape: {}".format(tensor_shape))
                print("tensor type: {}".format(onnx_dtype))
            onnx_const_tensor_list = []
            onnx_const_tensor = {}
            onnx_const_tensor["name"] = tensor_name + "_scale"
            onnx_const_tensor["type"] = TensorProto.FLOAT
            onnx_const_tensor["shape"] = scale_data_arr.shape
            onnx_const_tensor["data"] = scale_data_arr
            onnx_const_tensor_list.append(onnx_const_tensor)

            onnx_const_tensor = {}
            onnx_const_tensor["name"] = tensor_name + "_zero_point"
            onnx_const_tensor["type"] = onnx_dtype
            onnx_const_tensor["shape"] = zero_point_data_arr.shape
            onnx_const_tensor["data"] = zero_point_data_arr
            onnx_const_tensor_list.append(onnx_const_tensor)
            for index in range(len(onnx_const_tensor_list)):
                init_tensor_name = onnx_const_tensor_list[index]["name"]
                init_tensor_type = onnx_const_tensor_list[index]["type"]
                init_tensor_shape = onnx_const_tensor_list[index]["shape"]
                init_tensor_data = onnx_const_tensor_list[index]["data"].flatten().tolist()
                if log_flag:
                    print("construct const tensor with:")
                    print("tensor name: {}".format(init_tensor_name))
                    print("tensor shape: {}".format(init_tensor_shape))
                    print("tensor type: {}".format(init_tensor_type))
                    print("tensor data: {}".format(init_tensor_data))
                tesnor_def = helper.make_tensor(init_tensor_name, init_tensor_type, init_tensor_shape, init_tensor_data)
                initializer_list.append(tesnor_def)
    return input_list, output_list, initializer_list

def constrtut_graph_node(rknn_model_info, onnx_model_info, onnx_construct_obj, log_flag=False):
    for index in range(len(rknn_model_info["nodes"])):
        convert_flag = onnx_construct_obj.construct_node(rknn_model_info, index, onnx_model_info, log_flag)
        assert convert_flag, "convert node {} fail!!!!".format(rknn_model_info["nodes"][index]["name"])

def construct_onnx_from_rknn_model_info(rknn_model_info, onnx_construct_obj, layout="WHCN", log_flag=False):
    graph_initializer = constrtut_graph_initializer(rknn_model_info, layout, log_flag)
    graph_input, graph_output, graph_input_output_initializer = constrtut_graph_input_output(rknn_model_info, layout, log_flag)
    graph_initializer.extend(graph_input_output_initializer)
    onnx_model_info = {}
    onnx_model_info["initializers"] = graph_initializer
    onnx_model_info["inputs"] = graph_input
    onnx_model_info["outputs"] = graph_output
    onnx_model_info["nodes"] = []
    constrtut_graph_node(rknn_model_info, onnx_model_info, onnx_construct_obj, log_flag)
    time_stamp = time.localtime()
    doc_string = "created on {}".format(time.strftime('%Y-%m-%d %H-%M-%S', time_stamp))
    onnx_initializer_list = onnx_model_info["initializers"]
    onnx_input_list = onnx_model_info["inputs"]
    onnx_output_list = onnx_model_info["outputs"]
    onnx_node_list = onnx_model_info["nodes"]
    onnx_graph_def = helper.make_graph(onnx_node_list, 'rknn_graph', onnx_input_list, onnx_output_list, initializer=onnx_initializer_list, doc_string=doc_string)
    op = onnx.OperatorSetIdProto()
    op.version = 11
    onnx_mode_def = helper.make_model(onnx_graph_def, producer_name='rknn_parser', opset_imports=[op])
    onnx_mode_def.ir_version = 6
    checker.check_model(onnx_mode_def)
    if log_flag:
        print('Model Graph:\n\n{}'.format(helper.printable_graph(onnx_mode_def.graph)))
    return onnx_mode_def

def format_onnx_nodes(rknn_model_info, layout):
    nodes_info = rknn_model_info["nodes"]
    for node in nodes_info:
        if node["type"] == "RESIZE":
            node_attr = node["attribute"]["resize"]
            if layout == "WHCN":
                node_attr["size"] = node_attr["size"][::-1]

def convert_rknn_to_onnx(rknn_model_info, save_file="convert.onnx", layout="WHCN", log_flag=False):
    construct_onnx_obj = init_onnx_construct_obj()
    format_onnx_nodes(rknn_model_info, layout)
    onnx_model = construct_onnx_from_rknn_model_info(rknn_model_info, construct_onnx_obj, layout, log_flag)
    onnx.save_model(onnx_model, save_file)


import fileinput
import re
from collections import defaultdict
from functools import cache
import itertools

lines = [line.strip() for line in fileinput.input()]
rate = defaultdict(int)
graph = defaultdict(list)
time = 30
released = 0
D = defaultdict(lambda: 1000)
for l in lines:
    source, r, dests = re.findall(r' ([\w]{2}).*=([\d]+).*es? (.+)', l)[0]
    dests = dests.split(', ')
    for dest in dests:
        graph[source].append(dest)
        D[source, dest] = 1
    if r != '0':
        rate[source] = int(r)

visited = set()

@cache
def dfs(node='AA', nodeb='AA', time=30, rel_rate=0, turn=1, silver=True):
    # if not silver and time == 1 and turn == 1:
    #     print(node, nodeb, time, rel_rate, turn, silver)
    if time == 0:
        return 0
    res = turn*rel_rate
    # path.append(node)
    if silver:
        cur = node
        time -= 1
        turn = 1
    elif not turn:
        cur = nodeb
        time -= 1
    else:
        cur = node
    if rate[cur] > 0:
        old = rate[cur]
        rate[cur] = 0
        res = max(
            res, turn*rel_rate + dfs(node, nodeb, time, rel_rate+old, turn ^ 1, silver))
        rate[cur] = old
    for dest in graph[cur]:
        if (turn) or silver:
            res = max(
                res, (turn)*rel_rate + dfs(dest, nodeb, time, rel_rate, turn ^ 1, silver))
        else:
            res = max(
                res, dfs(node, dest, time, rel_rate, turn ^ 1, silver))
    # path.pop()
    return res

# not 2349 ( too low)
print(dfs(silver=True))
# print(dfs(node='AA', nodeb='AA', time=26, rel_rate=0, turn=1, silver=False))
# cheating
for k, i, j in itertools.product(graph, graph, graph):    # floyd-warshall
    D[i, j] = min(D[i, j], D[i, k] + D[k, j])

d2 = dict()
for r in rate:
    if rate[r]:
        d2[r] = rate[r]

@ cache
def search(t, u='AA', vs=frozenset(d2), e=False):
    return max([rate[v] * (t-D[u, v]-1) + search(t-D[u, v]-1, v, vs-{v}, e)
                for v in vs if D[u, v] < t] + [search(26, vs=vs) if e else 0])

print(search(26, e=True))


import time as time
import threading as t
class MyThread(t.Thread):
    def __init__(self,tid):
        t.Thread.__init__(self)
        #self.name=name
        self.tid=tid
    def run(self):
        for i in range(5):
            time.sleep(2)
            print(self.getName())
t1=MyThread(100)
t2=MyThread(101)
t1.start()
t2.start()


#!/usr/bin/env python

import numpy as np

import rospy
from geometry_msgs.msg import PoseArray, Pose, Quaternion
from tf.transformations import quaternion_from_euler

from common import *

if __name__ == '__main__':

  rospy.init_node('waypoint_publisher')

  # Generate random waypoints
  waypoints = np.random.rand(num_waypoints, 3)
  waypoints[:, 0] = (x_lim[1] - x_lim[0]) * waypoints[:, 0] + x_lim[0]
  waypoints[:, 1] = (y_lim[1] - y_lim[0]) * waypoints[:, 1] + y_lim[0]
  waypoints[:, 2] = (theta_lim[1] - theta_lim[0]) * waypoints[:, 2] + theta_lim[0]

  # Waypoint publisher
  waypoints_pub = rospy.Publisher('waypoints', PoseArray, queue_size=10)

  waypoint_array = PoseArray()
  for i in range(0, num_waypoints):
    w = Pose()
    w.position.x = waypoints[i, 0]
    w.position.y = waypoints[i, 1]
    w.orientation = Quaternion(*quaternion_from_euler(0, 0, waypoints[i, 2]))

    waypoint_array.poses.append(w)

  # Publish the waypoints
  r = rospy.Rate(1)  # 10hz
  while not rospy.is_shutdown():
    waypoints_pub.publish(waypoint_array)
    r.sleep()


# -*- coding: utf-8 -*-
from typing import TYPE_CHECKING, Dict, Optional

from django.db import models
from jsonfield import JSONField

from paas_wl.platform.applications.models import UuidAuditedModel
from paas_wl.utils.models import validate_procfile

if TYPE_CHECKING:
    from paas_wl.platform.applications.models.app import EngineApp
    from paas_wl.platform.applications.models.build import Build
    from paas_wl.platform.applications.models.config import Config

class ReleaseManager(models.Manager):
    def new(
        self,
        owner: str,
        build: 'Build',
        procfile: Dict[str, str],
        summary: str = None,
        config: Optional['Config'] = None,
    ):
        """Create a new release

        :params owner str: 发布者, 目前该字段无意义
        :params build Build: 应用构建记录
        :params summary str:
        :params config Optional[Config]: 应用配置, 包含环境变量和资源限制等信息. 如果不提供, 则获取上一个发布版本的应用配置
        """
        from paas_wl.platform.applications.models.app import App

        # Get the largest(latest) version and increase it by 1.
        if not hasattr(self, "instance"):
            raise RuntimeError("Only call `new` method from RelatedManager.")

        if not isinstance(self.instance, App):
            raise RuntimeError("Only call from app.release_set.")

        if build is None:
            raise RuntimeError('No build associated with this release.')

        app = self.instance
        latest_release = self.order_by('-version').first()
        if latest_release:
            new_version = latest_release.version + 1
            cfg = config or latest_release.config
        else:
            new_version = 1
            cfg = config or app.config_set.latest()

        release = Release.objects.create(
            app=app,
            version=new_version,
            summary=summary,
            config=cfg,
            build=build,
            owner=owner,
            procfile=procfile or build.procfile,
        )
        return release

    def any_successful(self, app: 'EngineApp') -> bool:
        """Check if engine app has any successful releases"""
        # In legacy versions, "workloads" will create an initial release object for
        # apps after creation, the object's "build" field was set to `None` and
        # "version" is 1, it must be excluded or current method will always return
        # true.
        qs = self.get_queryset().exclude(version=1, build=None)
        return qs.filter(app=app, failed=False).exists()

    def get_latest(self, app: 'EngineApp', ignore_failed: bool = False) -> 'Release':
        """获取最后一次发布对象(不管是否成功或失败), 如果不存在, 则根据 allow_null 返回 None 或抛异常.

        :param EngineApp app: engine app 对象
        :param bool ignore_failed: 寻找最后一次发布对象时, 是否忽略发布失败
        """
        qs = self.filter(app=app).all()
        if ignore_failed:
            qs = qs.filter(failed=False)

        return qs.latest('version')

    def get_by_version(self, app: 'EngineApp', version: int) -> 'Release':
        """根据指定的 App，Version 获取对应的 Release"""
        return self.get(app=app, version=version)

class Release(UuidAuditedModel):
    """
    Software release deployed by the application platform

    Releases contain a class`Build` and a class`Config`.
    """

    owner = models.CharField(max_length=64)
    app = models.ForeignKey('App', on_delete=models.CASCADE)
    version = models.PositiveIntegerField()
    summary = models.TextField(blank=True, null=True)
    failed = models.BooleanField(default=False)
    procfile = JSONField(default={}, blank=True, validators=[validate_procfile])

    config = models.ForeignKey('Config', on_delete=models.CASCADE)
    build = models.ForeignKey('Build', null=True, on_delete=models.CASCADE)

    objects = ReleaseManager()

    class Meta:
        get_latest_by = 'created'
        ordering = ['-created']
        unique_together = (('app', 'version'),)

    def __str__(self):
        return 'Release: %s' % self.uuid

    @property
    def region(self):
        return self.app.region

    def fail(self, summary: str):
        self.failed = True
        self.summary = summary
        self.save(update_fields=['failed', 'summary', 'updated'])

    def get_procfile(self) -> Dict:
        """获取与这个发布对象关联的 procfile"""
        if self.procfile:
            return self.procfile
        return self.build.procfile

    def get_envs(self) -> Dict:
        """获取与这个发布对象关联的环境变量"""
        envs = {}
        if self.build:
            envs.update(self.build.get_env_variables())
        envs.update(self.config.envs)
        return envs

    def get_previous(self) -> 'Release':
        """获取上一次的 release

        :raise ObjectDoesNotExist: 如果不存在上一次的 release, 则抛该异常
        """
        return Release.objects.filter(app=self.app, version__lt=self.version).latest('version')


# 구명 보트 문제

# 문제는 통과하지만

# 3 5 6 2 8 8 8 8 8 8 8 과 같은 무게 배열이 있을 때

# 시간 복잡도가 linear time(선형 시간)만큼 증가하기 때문에 효율성 측면에서 떨어짐(시간 초과 발생)

# from bisect import bisect_right

# def solution(people, limit):
#     # 오름차순 정렬
#     people = sorted(people)
#     # 구명 보트 개수
#     boat = 0
#     while people:
#         # 제일 무거운 무게
#         heavy = people.pop(-1)
#         light_idx = bisect_right(people, limit-heavy)
#         print("light_idx : ", light_idx)
#         print("people :", people)
#         if 0 < light_idx: # 인덱스가 0 이상인 경우
#             people.pop(light_idx - 1)
#         boat += 1
#     return boat

# 시간 초과가 발생하지 않게 코드를 작성

# from bisect import bisect_right

# def solution(people, limit):
#     # 각 무게 횟수 딕셔너리 생성
#     weightCount = dict()

#     # people 무게를 딕셔너리에 담는다.
#     for w in people:
#         if w in weightCount:
#             weightCount[w] += 1
#         else:
#             weightCount[w] = 1

#     weights = sorted(list(set(people))) # 어떤 키 값이 남아 있는지 확인용 리스트를 정렬한 상태로 선언

#     boat = 0
#     print(boat, weightCount, weights)

#     while weights:
#         Heavyweight = weights[-1] # 제일 큰 무게
#         HeavyCount = weightCount[Heavyweight] # 그 무게의 등장 횟수

#         if HeavyCount == 1:
#             weights.pop(-1)

#         LightweightIdx = bisect_right(weights, limit - Heavyweight) # bisect 함수로 같이 탈 수 있는 무게 인덱스 반환

#         if 0< LightweightIdx: # 같이 탈 수 있는 친구가 있는 경우
#             Lightweight = weights[LightweightIdx - 1]
#             LightCount = weightCount[Lightweight]

#             if Heavyweight == Lightweight: # 같이 탈 수 있는 친구의 무게가 동일한 경우
#                 boat += HeavyCount // 2

#                 weightCount[Heavyweight] = HeavyCount % 2
#                 if weightCount[Heavyweight] == 0 and Heavyweight in weights:
#                     weights.remove(Heavyweight)

#             else: # 같이 탈 수 있는 친구의 무게가 다른 경우
#                 boat += min(HeavyCount, LightCount)

#                 weightCount[Heavyweight] -= min(HeavyCount, LightCount) # 보트를 타고 나간 사람만큼 제거
#                 # 해당 명수가 0명이면 제거
#                 if weightCount[Heavyweight] == 0 and Heavyweight in weights:
#                     weights.remove(Heavyweight)

#                 weightCount[Lightweight] -= min(HeavyCount, LightCount)
#                 if weightCount[Lightweight] == 0 and Lightweight in weights:
#                     weights.remove(Lightweight)

#         else: # 같이 탈 수 있는 무게가 없는 경우
#             boat += HeavyCount

#             weightCount[Heavyweight] -= HeavyCount
#             if weightCount[Heavyweight] == 0 and Heavyweight in weights:
#                 weights.remove(Heavyweight)

#         print(boat, weightCount, weights)
#     return boat

# 더 간결한 코드로 작성하기

def solution(people, limit):
    answer = 0
    # L        H
    people.sort() # 정렬
    Lidx, Hidx = 0, len(people) - 1 # 가장 가벼운 무게, 가장 무거운 무게로 나눈다.

    while Lidx < Hidx: # 무게 인덱스가 서로 교차되면 while 종료
        # 2명이 타고 나가는 경우 (H + L)
        # 몸무게가 제일 무거운 친구와 제일 가벼운 친구의 합이 limit 안에 있는 경우 탄다.
        if people[Lidx] + people[Hidx] <= limit:
            Lidx += 1
            Hidx -= 1
        # 아닌 경우라면 오름차순 정렬되어 있기 때문에 그 다음 값은 당연히 같이 타고 못나간다.
        # Hidx를 내려주면서 Lidx와 타고 갈 수 있는지만 검사
        else:
            Hidx -= 1

        answer += 1

    if Hidx == Lidx: # 만약 숫자가 가운데에서 뭉쳐있는 경우 혼자 타고 나오기 때문에 + 1
        answer += 1
    return answer

print(solution([70, 50, 80, 50], 100))
print(solution([70, 80, 50], 100))


import numpy as np
import random

def get_response(self, question):
    # This part classifies the response as either "glossary", "general" or "events"
    user_bag = self.bag_of_words(question, self.wordbank)  # Creates a bag of words out of the question.
    predicted_results = self.model.predict([user_bag])  # Returns an np.array of probabilities for each of the tags in the wordbank.
    result_index = np.argmax(predicted_results)  # Finds the largest
    result_tag = self.tags[result_index]
    responses = []
    for pattern in self.dataset["intents"]:  # Finds the response that corresponds with the tag.
        if pattern['tag'] == result_tag:
            if predicted_results[0, result_index] > 0.3:  # If it is more than 30 percent sure that that is the correct response, return the response
                responses = pattern['response']
            else:
                responses = ["Sorry I did not quite understand that. Please try again!"]

    return random.choice(responses)


# coding=utf-8
from application import bot
from boto3.session import Session
from model.song import Song
import requests
import os
import uuid
import spotipy

humming_mode = False

TOKEN = os.environ.get('BOT_TOKEN')
AUDD_API_TOKEN = os.environ.get('AUDD_API_TOKEN')

SPOTIFY_API_TOKEN = os.environ.get('SPOTIFY_API_TOKEN')
spotify = spotipy.Spotify(auth=SPOTIFY_API_TOKEN)

session = Session(aws_access_key_id=os.environ.get('AWS_S3_ACCESS_KEY'),
                  aws_secret_access_key=os.environ.get('AWS_S3_SECRET_KEY'))
s3 = session.resource('s3')
s3Client = session.client('s3')

@bot.message_handler(commands=['start'])
def start(message):
    bot.reply_to(message, 'Hello, ' + message.from_user.first_name)

@bot.message_handler(commands=['humming'])
def set_humming(message):
    global humming_mode
    humming_mode = True
    bot.reply_to(message, 'Se reconocerá como tarareo')

@bot.message_handler(commands=['recording'])
def set_recording(message):
    global humming_mode
    humming_mode = False
    bot.reply_to(message, 'Se reconocerá como grabación')

def get_song_info(title, artist, album, score = None):
    message = ""
    if title: message = message + "*Titulo:* " + title + "\n"
    if artist: message = message + "*Artista:* " + artist.translate({ord(c): None for c in '!@#$()_'}) + "\n"
    if album: message = message + "*Album:* " + album + "\n"
    if score: message = message + "*Probabilidad:* " + str(score) + "\n"

    return message

@bot.message_handler(func=lambda message: True, content_types=['voice'])
def recognize_song(message):

    bot.reply_to(message, "⚙ Procesando tu audio...", parse_mode="Markdown")

    fileId = message.voice.file_id
    getPathRequest = requests.get('https://api.telegram.org/bot' + TOKEN + '/getFile?file_id=' + fileId)
    if getPathRequest.status_code == 200:
        path = getPathRequest.json()['result']['file_path']
        rawFileRequest = requests.get('https://api.telegram.org/file/bot'+ TOKEN + '/' + path)
        if rawFileRequest.status_code == 200:
            fileKey = str(uuid.uuid4())

            upload = s3.Bucket('musictelegram').put_object(Key=fileKey, Body=rawFileRequest.content, ACL='public-read')

            bucket_location = s3Client.get_bucket_location(Bucket='musictelegram')
            object_url = "http://s3-{0}.amazonaws.com/{1}/{2}".format(
            bucket_location['LocationConstraint'],
            'musictelegram',
            fileKey)

            method = "recognizeWithOffset/" if humming_mode else ""

            getSongInfo = requests.get('https://api.audd.io/' + method +'?api_token=' + AUDD_API_TOKEN + '&url=' + object_url)
            if getSongInfo.status_code == 200:
                songInfo = getSongInfo.json()['result']
                if songInfo:
                    if humming_mode:
                        if songInfo['count']:
                            predictionList = songInfo['list']
                            bot.send_message(message.chat.id, "Tu canción puede ser una de estas:")
                            for prediction in predictionList:
                                title = None
                                artist = None
                                album = None
                                score = None
                                if prediction.has_key('title'): title = prediction['title']
                                if prediction.has_key('artist'): artist = prediction['artist']
                                if prediction.has_key('album'): album = prediction['album']
                                if prediction.has_key('score'): score = prediction['score']
                                bot.send_message(message.chat.id, get_song_info(title, artist, album, score).encode('utf-8'), parse_mode="Markdown")
                        else:
                            bot.reply_to(message, "Lo has hecho fatal, intenta tararear de nuevo.")
                    else:
                        songTitle = songInfo['title']
                        songArtist = songInfo['artist']
                        songAlbum = songInfo['album']

                        messageToSend = "Tu cancion es:\n" + get_song_info(songTitle, songArtist, songAlbum)

                        bot.send_message(message.chat.id, messageToSend, parse_mode="Markdown")

                        spotifySearch = spotify.search(q='track:' + songTitle.encode('utf-8'), type='track')
                        if(len(spotifySearch)):
                            spotifyURL = spotifySearch['tracks']['items'][0]['external_urls']['spotify']

                        bot.send_message(message.chat.id, "*URL Spotify:* " + spotifyURL, parse_mode="Markdown")
                        Song.set_config(message.chat.id, 'memory', songTitle, songAlbum, songArtist)
                else:
                    bot.reply_to(message, "No se ha podido reconocer ninguna canción. Inténtalo de nuevo.")
            else:
                bot.reply_to(message, "Error de reconocimiento de audio.")
        else:
            bot.reply_to(message, "Error procesando tu audio. Intentalo de nuevo.")
    else:
            bot.reply_to(message, "Error procesando tu audio. Intentalo de nuevo.")


import numpy as np
import sys
import random

class SlidingGameMatch:
    def __init__(self, board_size, board_generation_moves):
        self._board_size = board_size
        self._board_generation_moves = board_generation_moves
        self._board = self._create_board_of_n_size(self._board_size)
        self._generate_board()
        self._valid_numbers = self._board[~np.isnan(self._board)]
        self._move_counter = 0

    @staticmethod
    def _create_board_of_n_size(size: int):
        return np.array(list(range(1, size * size)) + [np.nan]).reshape([size, size])

    def is_number_valid(self, number: int):
        return number in self._valid_numbers

    def _print_board(self):
        print(self._board)

    def _get_piece_position(self, value):
        pos = np.where(np.isnan(self._board)) if np.isnan(value) else np.where(self._board == value)
        if pos[0].size == 0:
            return None
        return pos

    def _is_move_allowed(self, piece_pos: np.array, empty_pos: np.array):
        if not piece_pos[0][0] > 0 or not piece_pos[0][0] < self._board.shape[1]:
            return False
        if not piece_pos[1][0] > 0 or not piece_pos[1][0] < self._board.shape[0]:
            return False
        if piece_pos[0] == empty_pos[0] and (1 >= piece_pos[1] - empty_pos[1] >= -1):
            return True
        elif piece_pos[1] == empty_pos[1] and (1 >= piece_pos[0] - empty_pos[0] >= -1):
            return True
        return False

    def _move_piece(self, piece_pos: np.array, empty_pos: np.array):
        self._board[empty_pos] = self._board[piece_pos]
        self._board[piece_pos] = None

    def _is_board_ordered(self):
        try:
            np.testing.assert_equal(np.sort(self._board[~np.isnan(self._board)]), self._board[~np.isnan(self._board)])
        except AssertionError:
            return False
        return True

    def _move_piece_by_number(self, number: int):
        piece_pos, empty_pos = self._get_piece_position(number), self._get_piece_position(np.NaN)
        if self._is_move_allowed(piece_pos, empty_pos):
            self._move_piece(piece_pos, empty_pos)
            return True
        return False

    def _get_random_move(self, last_pos=None):
        curr_pos = self._get_piece_position(np.NaN)
        possible_new_pos = [
            tuple([curr_pos[0], np.array([curr_pos[1][0] + 1])]),
            tuple([curr_pos[0], np.array([curr_pos[1][0] - 1])]),
            tuple([np.array([curr_pos[0][0] + 1]), curr_pos[1]]),
            tuple([np.array([curr_pos[0][0] - 1]), curr_pos[1]])
        ]
        valid_new_pos = []
        for new_pos in possible_new_pos:
            if self._is_move_allowed(new_pos, curr_pos) and last_pos != new_pos:
                valid_new_pos.append(new_pos)
        return random.choice(valid_new_pos), curr_pos

    def _generate_board(self):
        last_pos = None
        for move_index in range(0, self._board_generation_moves):
            new_pos, cur_pos = self._get_random_move(last_pos)
            self._move_piece(new_pos, cur_pos)
            last_pos = cur_pos

    def play_match(self):
        self._print_board()
        while not self._is_board_ordered():
            piece = input(">> ")
            try:
                piece_number = int(piece)
                if not self.is_number_valid(piece_number):
                    raise TypeError
                if not self._move_piece_by_number(piece_number):
                    print("This move is not allowed!")
                    continue
                self._move_counter += 1
                self._print_board()
            except TypeError:
                print("Invalid number, please try again")

        return self._move_counter

class SlidingGame:
    BOARD_SIZE = 4
    BOARD_GENERATION_MOVES = 60

    def __init__(self):
        self._matches_moves_counter = np.array([np.NaN, np.NaN, np.NaN])

    def play(self):
        print("--- SLIDING PUZZLE ---")
        for match_number in range(0, self._matches_moves_counter.size):
            print("++++ MATCH {} ++++".format(match_number + 1))
            print("Please enter the number of the piece you want to move")
            match = SlidingGameMatch(self.BOARD_SIZE, self.BOARD_GENERATION_MOVES)
            self._matches_moves_counter[match_number] = match.play_match()
            print("==== MATCH FINISHED ====".format(match_number + 1))
        print("In your best match, you needed {} moves to solve the puzzle!".format(int(self._matches_moves_counter.min())))

if __name__ == "__main__":
    game = SlidingGame()
    game.play()


from urllib2 import Request, urlopen
import json
import datetime
import os
#from V2Authorization import V2Authorization
directory = os.path.dirname(__file__)

# Class deals with API calls
class DataRetriever:

    defaultStartDate = datetime.datetime.strptime("2015-01-01 00:00", "%Y-%m-%d %M:%S")
    formatTime = datetime.datetime.strptime

    PREFIX = "https://data.solarnetwork.net"

    def __init__(self, node_id, src_id, start_date, end_date):
        #self.auth = V2Authorization(#construct using variables
         #    )
        self.nodeId = node_id
        self.srcId = src_id
        self.chunksFolder = os.path.join(directory, "chunks/")
        self.weatherFolder = os.path.join(directory, "weather/")
        start_date_i, end_date_i = self.get_interval()

        # if the difference between the last datum and the current date is too large, fail.
        if abs((datetime.datetime.strptime(end_date_i, "%Y-%m-%d %M:%S") - datetime.datetime.utcnow()).days) > 15:
            raise Exception

        # if no date range is defined, use default
        if (start_date is None) | (end_date is None):

            if (self.formatTime(start_date_i, "%Y-%m-%d %M:%S") < self.defaultStartDate):
                self.startDate = self.defaultStartDate
            else:
                self.startDate = self.formatTime(start_date_i, "%Y-%m-%d %M:%S")
            self.endDate = self.formatTime(end_date_i, "%Y-%m-%d %M:%S")

        else:
            self.startDate = self.formatTime(start_date, "%Y-%m-%d:%H:%M")
            self.endDate = self.formatTime(end_date, "%Y-%m-%d:%H:%M")

    @staticmethod
    def get_chunk_end_date(current, end_date, min_interval):

        out = current + datetime.timedelta(minutes=500 * min_interval)
        if out > end_date:
            return end_date
        else:
            return out

    # downloads all node datum within a range as JSON files
    def get_node_data(self):

        chunk_start = self.startDate
        while chunk_start < self.endDate:

            chunk_end = self.get_chunk_end_date(chunk_start, self.endDate, 20)
            start_string = datetime.datetime.strftime(chunk_start, "%Y-%m-%dT12%%3A00")
            end_string = datetime.datetime.strftime(chunk_end, "%Y-%m-%dT12%%3A00")

            request = Request(self.PREFIX + "/solarquery/api/v1/pub/datum/"
                                            "list?nodeId=" + self.nodeId + "&aggregation=ThirtyMinute&startDate=" +
                              start_string + "&endDate=" + end_string + "&sourceIds=" + self.srcId + "&max=5000000")
            #request.add_header("Authorization: " + self.auth.build("dfsdfsdf"))

            try:
                response = urlopen(request)
                data = json.loads(response.read())

                # writes each request into json file with start date as string
                with open(self.chunksFolder + 'chunk_' + start_string + '.json', 'w') as outfile:

                    outfile.write(json.dumps(data, indent=4))

            except:
                print("Failed")
            chunk_start = chunk_end

    # downloads all weather datum within a range as JSON files
    def get_weather_data(self):

        chunk_start = self.startDate

        while chunk_start < self.endDate:
            # moves sliding window of time over chunks
            chunk_end = self.get_chunk_end_date(chunk_start, self.endDate, 30)
            start_string = datetime.datetime.strftime(chunk_start, "%Y-%m-%d")
            end_string = datetime.datetime.strftime(chunk_end, "%Y-%m-%d")

            request = Request(self.PREFIX + "/solarquery/api/v1/pub/location/datum/list?locationId=301025&sourceIds="
                                            "NZ%20MetService&offset=0&"
                                            "startDate=" + start_string + "&endDate=" + end_string)
            try:
                response = urlopen(request)
                data = json.loads(response.read())
                with open(self.weatherFolder + '/weather_' + start_string + '.json', 'w') as outfile:
                    outfile.write(json.dumps(data, indent=4))
            except:
                print("Failed")
            chunk_start = chunk_end

    # gets the range of datum for the node, from start date to end date.
    def get_interval(self):
        request = Request(self.PREFIX + "/solarquery/api/v1/pub/range/interval?nodeId={}".format(self.nodeId))
        data = ""
        try:
            response = urlopen(request)
            data = json.loads(response.read())

        except:
            print("Failed")

        return data['data']['startDate'], data['data']['endDate']


from otree.api import Currency as c, currency_range
from ._builtin import Page, WaitPage
from .models import Constants
import random

class Background(Page):
    def before_next_page(self):
        self.participant.vars['age'] = self.player.age
        self.participant.vars['city'] = self.player.city

    form_model = 'player'
    form_fields = ['age', 'city']

class Novel_combination(Page):
    def vars_for_template(self):
        age = self.participant.vars['age']
        city = self.participant.vars['city']

        return dict(
            age=age,
            city=city,
        )

    def before_next_page(self):
        persons = [self.player.person1, self.player.person2, self.player.person3, self.player.person4, self.player.person5]
        places = [self.player.place1, self.player.place2, self.player.place3, self.player.place4, self.player.place5]

        two_persons = random.sample(persons, 3)
        two_places = random.sample(places, 3)

        self.participant.vars['combinations'] = dict(
            persons=two_persons,
            places=two_places
        )

    form_model = 'player'
    form_fields = [
        'person1', 'person2', 'person3', 'person4', 'person5',
        'place1', 'place2', 'place3', 'place4', 'place5'
    ]

page_sequence = [Background]


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

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^update_session/(?P<id_producte>[0-9]+)/$', views.update_session, name='update_session'),
    url(r'^update_sessionPost/$', views.update_sessionPost, name='update_sessionPost'),

    url(r'^veure_comande/$', views.veure_comande, name='veure_comande'),
    url(r'^veure_comande/esborra_carro/$', views.esborra_carro, name='esborra_carro'),
    url(r'^veure_comande/esborra_linia/(?P<id_producte>[0-9]+)/$', views.esborra_linia, name='esborra_linia'),
    url(r'^veure_comande/comfimar_carro/$', views.comfimar_carro, name='comfimar_carro'),

    url(r'^llista_comandes/$', views.llista_comandes, name='llista_comandes'),
    url(r'^llista_comandes/detall_comanda/(?P<id_comanda>[0-9]+)/$', views.detall_comanda, name='detall_comanda'),

]


#!/usr/bin/env python3

import asyncio
import websockets

import json
from types import SimpleNamespace

from pyfirmata import Arduino, util
from time import sleep

board = Arduino("/dev/ttyACM0", baudrate=57600)

#print(board.get_firmata_version())
# #checks generell woking connection

flagIncomingFromVirtual = False
flagHoererOben = False
data = '{"event": "RingsMaybe"}'

# Start iterator to receive input data
it = util.Iterator(board)
it.start()
board.analog[0].enable_reporting()

async def server(websocket, path):
    # Get received data from websocket
    JSONIncomingFromVirtual = await websocket.recv()
    DictIncomingFromVirtual = eval(JSONIncomingFromVirtual)
    flagIncomingFromVirtual = DictIncomingFromVirtual["event"]
    print("flagIncomingFromVirtual type: " + type(flagIncomingFromVirtual))
    print(flagIncomingFromVirtual)

    #ring the bell
    if flagIncomingFromVirtual == "RingingStart":

        for x in range(10):
            board.digital[2].write(1)
            sleep(0.03)
            board.digital[2].write(0)
            board.digital[3].write(1)
            sleep(0.03)
            board.digital[3].write(0)

        print("ring")
        sleep(2)
    else:
        pass

    await asyncio.sleep(0.05)

    """ readResult = board.analog[0].read()
    print(readResult)
    if readResult <= 0.2:
        flagHoererOben = 1
    else:
        flagHoererOben = 0
    await asyncio.sleep(0.2)

    #if different stat: build JSON
    flagHoererObenJSON =

    # Send response back to client to acknowledge receiving message
    await websocket.send(flagHoererObenJSON) """

# Create websocket server
start_server = websockets.serve(server, "localhost", 3003)

# Start and run websocket server forever
# Server has to be running before browser ist loaded
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()


import tqdm
import numpy as np
import random
from collections import deque
import pickle5 as pickle

from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam

class Supervisor :
    def __init__(self, game) :
        self.game = game

    def simulate(self, p1, p2, nb_round, verbose=False) :
        for battle_count in tqdm.tqdm(range(nb_round)) :
            current_game = self.game(p1, p2, verbose)
            p1_mem = []
            p2_mem = []
            turn_p1 = []
            turn_p2 = []
            for i in range(9) :
                if current_game.p1_turn :
                    turn_p1.append(current_game.board.board.copy())
                    move = current_game.next_moves()
                    turn_p1.append(move)
                    if not current_game.is_legal_move(move) :
                        turn_p1.append(current_game.board.board.copy())
                        turn_p1.append(True)
                        turn_p1.append(-1)
                        p1_mem.append(turn_p1)
                        p1.memorize(p1_mem)
                        break
                    else :
                        current_game.apply_move(move)
                        current_game.detect_end(current_game.board)
                else :
                    current_game.board.invert()
                    turn_p2.append(current_game.board.board.copy())
                    move = current_game.next_moves()
                    turn_p2.append(move)
                    if not current_game.is_legal_move(move) :
                        turn_p2.append(current_game.board.board.copy())
                        turn_p2.append(True)
                        turn_p2.append(-1)
                        p2_mem.append(turn_p2)
                        p2.memorize(p2_mem)
                        break
                    else :
                        current_game.apply_move(move)
                        current_game.detect_end(current_game.board)
                    current_game.board.invert()

                if i != 0 :
                    if current_game.p1_turn :
                        turn_p1.append(current_game.board.board.copy())
                        turn_p1.append(current_game.done)
                        if current_game.done :
                            if current_game.final_state == 1 :
                                turn_p1.append(1)
                            elif current_game.final_state == 0 :
                                turn_p1.append(0)
                            else :
                                turn_p1.append(-1)
                        else :
                            turn_p1.append(0)
                        p1_mem.append(turn_p1)
                        turn_p1 = []
                    else :
                        turn_p2.append(current_game.board.board.copy())
                        turn_p2.append(current_game.done)
                        if current_game.done :
                            if current_game.final_state == 2 :
                                turn_p2.append(1)
                            elif current_game.final_state == 0 :
                                turn_p2.append(0)
                            else :
                                turn_p2.append(-1)
                        else :
                            turn_p2.append(0)
                        p2_mem.append(turn_p2)
                        turn_p2 = []

                    if current_game.done :
                        if not current_game.p1_turn :
                            turn_p1.append(current_game.board.board.copy())
                            turn_p1.append(current_game.done)
                            if current_game.final_state == 1 :
                                turn_p1.append(1)
                            elif current_game.final_state == 0 :
                                turn_p1.append(0)
                            else :
                                turn_p1.append(-1)
                            p1_mem.append(turn_p1)
                        else :
                            turn_p2.append(current_game.board.board.copy())
                            turn_p2.append(current_game.done)
                            if current_game.final_state == 1 :
                                turn_p2.append(-1)
                            elif current_game.final_state == 0 :
                                turn_p2.append(0)
                            else :
                                turn_p2.append(1)
                            p2_mem.append(turn_p2)

                        p1.memorize(p1_mem)
                        p2.memorize(p2_mem)
                        break
                if verbose :
                    print(current_game.board)

class Morpion :
    def __init__(self, p1, p2, verbose=False) :
        self.p1 = p1
        self.p1.jeu = self
        self.p2 = p2
        self.p2.jeu = self
        self.board = Board()
        self.p1_turn = True
        self.verbose = verbose
        self.final_state = None
        self.done = False

    def possible_moves(self, board, p1_turn) :
        possibilities = []
        for i in range(9) :
            if board.board[i] == 0 :
                possibility = np.zeros((9), dtype=np.int8)
                possibility[i] = 1 if p1_turn else 2
                possibilities.append(possibility)

        print(possibilities)
        return possibilities

    def detect_end(self, board) :
        is_win = False
        for i in range(3) : # horizontal
            if board.board[0+i*3] != 0 and board.board[1+i*3] == board.board[0+i*3] and board.board[2+i*3] == board.board[0+i*3] :
                is_win = True
        for i in range(3) : # vertical
            if board.board[0+i] != 0 and board.board[3+i] == board.board[0+i] and board.board[6+i] == board.board[0+i] :
                is_win = True
        if board.board[0] != 0 and board.board[4] == board.board[0] and board.board[8] == board.board[0] :
            is_win = True
        if board.board[6] != 0 and board.board[4] == board.board[6] and board.board[2] == board.board[6] :
            is_win = True

        if is_win :
            self.final_state = 1 if not self.p1_turn else 2
            self.done = True
            if self.verbose :
                print("Le joueur {} gagne !".format(1 if not self.p1_turn else 2))
            return

        is_draw = True
        for i in range(9) :
            if board.board[i] == 0 :
                is_draw = False
        if is_draw :
            self.final_state = 0
            self.done = True
            if self.verbose :
                print("Egalitée")
            return

    def is_legal_move(self, move) :
        return self.board.board[np.argmax(move)] == 0

    def apply_move(self, move) :
        self.board.board[np.argmax(move)] = 1

    def next_moves(self) :
        if self.p1_turn :
            if self.verbose :
                print('Joueur 1')
            move = self.p1.play(self.board.copy(), self.p1_turn)
        else :
            if self.verbose :
                print('Joueur 2')
            move = self.p2.play(self.board.copy(), self.p1_turn)

        self.p1_turn = not self.p1_turn
        return move

class Board :
    def __init__(self) :
        self.board = np.zeros((9), dtype=np.int8)

    def __repr__(self) :
        delimiteur = "\n+---+---+---+\n"
        rep = delimiteur
        for i in range(9) :
            if i % 3 == 0 and i != 0 :
                rep += "|" + delimiteur
            rep += "| {} ".format(self.board[i])
        rep += "|" + delimiteur

        return rep

    def copy(self) :
        board_copy = Board()
        board_copy.board = self.board.copy()
        return board_copy

    def invert(self) :
        for i in range(9) :
            if self.board[i] == 1 : self.board[i] = 2; continue
            if self.board[i] == 2 : self.board[i] = 1
        return self

class Agent :
    def __init__(self) :
        raise NotImplementedError

    def play(self) :
        raise NotImplementedError

    def memorize(self, game_history) :
        self.memory.append(game_history)

    def save_memory(self, file) :
        with open(file, 'wb') as f :
            pickle.dump(self.memory, f)

    def load_memory(self, file) :
        with open(file, 'rb') as f :
            self.memory = pickle.load(f)

class Singe(Agent) :
    def __init__(self, jeu=None) :
        self.jeu = jeu
        self.memory = deque(maxlen=10000)

    def play(self, board, p1_turn) :
        possibilities = []
        for i in range(9) :
            if board.board[i] == 0 :
                possibility = np.zeros((9), dtype=np.int8)
                possibility[i] = 1
                possibilities.append(possibility)
        move = random.choice(possibilities)
        return move

class Debug(Agent) :
    def __init__(self, jeu=None) :
        self.jeu = jeu
        self.memory = deque(maxlen=200)

    def play(self, board, p1_turn) :
        print(board.board)
        choice = int(input("Position à jouer \n>>"))
        move = np.zeros((9), dtype=np.int8)
        move[choice] = 1
        return move

class DQNAgent(Agent) :
    def __init__(self, state_size, action_size) :
        self.state_size = state_size
        self.action_size = action_size
        self.memory = deque(maxlen=2000)
        self.gamma = 0.95    # discount rate
        self.epsilon = 0  # exploration rate
        self.epsilon_min = 0.01
        self.epsilon_decay = 0.995
        self.learning_rate = 0.0005
        self.model = self._build_model()

    def _build_model(self):
        # Neural Net for Deep-Q learning Model
        model = Sequential()
        model.add(Dense(24, input_dim=self.state_size, activation='relu'))
        model.add(Dense(24, activation='relu'))
        model.add(Dense(self.action_size, activation='linear'))
        model.compile(loss='mse',
                      optimizer=Adam(lr=self.learning_rate))
        return model

    def play(self, board, p1_turn):
        if np.random.rand() <= self.epsilon:
            move = np.zeros((9), dtype=int)
            move[random.randrange(9)] = 1
            return move
        formated_board = np.reshape(board.board, [1, 9])
        act_values = self.model.predict(formated_board)
        move = np.zeros((9), dtype=np.int8)
        move[np.argmax(act_values[0])] = 1
        return move

    def train(self, minibatch_size, batch):
        minibatch = random.sample(batch, batch_size)
        for state, action, next_state, done, reward in minibatch:
            target = reward                                                    # A implementer correctement
            if not done:                                                       #
                target = (reward + self.gamma *                                #
                          np.amax(self.model.predict(next_state)[0]))          #
            target_f = self.model.predict(state)                               #
            target_f[0][action] = target                                       #
            self.model.fit(state, target_f, epochs=1, verbose=0)
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

    def load_model(self, name):
        self.model.load_weights(name)

    def save_model(self, name):
        self.model.save_weights(name)

class BatchMorpion :
    def __init__(self, gamma=0.8) :
        self.gamma = gamma

    def is_bad_move(self, game) :
        last = game[-1]
        return last[-1] == -1 and np.array_equal(last[0], last[2])

    def create_batch(self, file) :
        batch = []
        p1_win = 0
        p2_win = 0
        with open(file, 'rb') as f :
            games = pickle.load(f)
        for game in games :
            if self.is_bad_move(game) :
                game = [game[-1]]
            else :
                reward = game[-1][-1]
                for i, turn in enumerate(game[:-1]) :
                    turn[-1] = turn[-1] + reward * self.gamma**(len(game)-i)
            for turn in game :
                batch.append(turn)

        return batch

if __name__ == '__main__' :
    p1 = DQNAgent(9, 9)
    #p1 = Singe()
    p2 = Singe()

    mj = Supervisor(Morpion)
    mj.simulate(p1, p2, 10, verbose=False)

    p1.save_memory('p1.mem')

    batcher = BatchMorpion()
    batch = batcher.create_batch('p1.mem')

    #p1.train(32, batch)


#!/usr/bin/env python
# -*- coding: utf-8 -*- #
#from __future__ import unicode_literals
MATH_JAX = {'message_style': 'none'}
DIRECT_TEMPLATES = ['index', 'archives', 'tags', 'search']
AUTHOR_FEED_RSS = None
TIMEZONE = 'Canada/Atlantic'
EMAIL = 'someone@something.com'
CATEGORY_SAVE_AS = ''
DEFAULT_LANG = 'en'
CACHE_CONTENT = True
PUBLICATIONS_SRC = '/home/chris/Code/scribbler/tests/test_notebook/'
PAGE_PATHS = ['appendices']
ARTICLE_SAVE_AS = 'notes/{slug}.html'
DEFAULT_PAGINATION = 10
AUTHOR_FEED_ATOM = None
STATIC_PATHS = ['files']
SLUGIFY_SOURCE = 'basename'
CATEGORY_FEED_ATOM = None
YEAR = 2017
STREET_ADDRESS = '5415 Victoria Road'
LINKS = [['Link 1 Display Text', 'http://link1url.com'], ['Link 2 Display Text', 'http://link2url.com']]
ARTICLE_PATHS = ['notes']
REGION = 'Nova Scotia'
DEFAULT_ORPHANS = 2
CACHE_PATH = '.__cache__'
ADDRESS = True
COUNTRY = 'Canada'
DELETE_OUTPUT_DIRECTORY = True
PATH = '/home/chris/Code/scribbler/tests/test_notebook/.__content__'
POSTAL = 'B3H 4K5'
AUTHOR = 'Chris MacMackin'
SITENAME = 'Test Notebook'
ARTICLE_URL = 'notes/{slug}.html'
PLUGINS = ['scribbler.render_math', 'scribbler.tipue_search', 'scribbler.neighbors', 'scribbler.pdf-img', 'scribbler.slugcollision', 'scribbler.pelican-cite', 'scribbler.figure-ref']
TYPOGRIFY = True
FEED_ALL_ATOM = None
PAGINATED_DIRECT_TEMPLATES = ('index', 'tag', 'archives', 'period_archives')
THEME = '/home/chris/Code/scribbler/scribbler/notebook-theme'
AUTHOR_SAVE_AS = ''
RELATIVE_URLS = True
CITY = 'Halifax'
SITEURL = 'http://www.null.org'
DESCRIPTION = "This notebook is for unit testing purposes. It doesn't contain much...\n"
MD_EXTENSIONS = ['scribbler.figureAltCaption', 'superscript', 'markdown_checklist.extension', 'extra', 'subscript', 'MarkdownHighlight.highlight', 'codehilite(css_class=highlight)', 'del_ins', 'markdown_include.include(base_path={})', 'scribbler.plantuml']
OUTPUT_PATH = '/home/chris/Code/scribbler/tests/test_notebook/html'


"""try:
    numero1 = 5
    numero2 = 3
    div = numero1 / numero2
    print(div)
except ZeroDivisionError:
    print("No puedes dividir por cero")
except:
    print("Ha ocurrido un error")
else:
    print("La division funciono correctamente") # cuando funciona
finally:
    print("Estamos aprendiendo excepctiones") # siempre se muestra"""

# ejercicio
"""
crear la fn "operacion" que dados 3 num, divida el primer numero entre la resta de los otros dos numeros
utilizar la fn creado con los nmeros 5,4,2
utilizar la fn creada con los numeros 6,3,3
"""
def operacion(num1, num2, num3):
    try:
        operacion_matematica = num1 / (num2 - num3)
        print(operacion_matematica)
    except:
        print("Hubo un error, revise si esta ingresando los dos ultimos dos numeros con el mismo valor y/o esta dividiendo en cero :/ ")
    else:
        print("Operacion realizada con exito")
    finally:
        print("La operacion ha terminado")

operacion(5,4,4)