import os
import sqlite3

class DB:
    DB_NAME = os.path.join(os.path.dirname(__file__), 'database', 'transactions.db3')

    def __init__(self):
        self.conn = sqlite3.connect(self.DB_NAME)
        self.cursor = self.conn.cursor()

    def set_up(self):
        self.create_table_terminal()
        self.create_table_transaction()
        self.fill_terminal()

    def create_table_terminal(self):
        query = """CREATE TABLE IF NOT EXISTS terminal (
                id INT PRIMARY KEY,
                last_transaction_id INT NOT NULL DEFAULT 0,
                cash BIGINT NOT NULL DEFAULT 0,
                state TINYINT NOT NULL DEFAULT 1
                )"""
        self.cursor.execute(query)

    def create_table_transaction(self):
        query = """CREATE TABLE IF NOT EXISTS ps_transaction (
                length SMALLINT NOT NULL,
                term_id INTEGER NOT NULL,
                transaction_id BIGINT NOT NULL,
                datetime DATE NOT NULL,
                type TINYINT NOT NULL,
                action VARCHAR(255),
                org_id INT,
                account BIGINT,
                collector_id INT,
                amount BIGINT,
                FOREIGN KEY (term_id) REFERENCES terminal(id)
                )"""
        self.cursor.execute(query)

    def fill_terminal(self):
        terminals = [(7, ), (55, ), (250, ), (304, ), (1049, )]
        query = 'INSERT INTO terminal (id) VALUES (?)'
        self.cursor.executemany(query, terminals)
        self.conn.commit()

    @staticmethod
    def flush():
        if os.path.exists(DB.DB_NAME):
            os.remove(DB.DB_NAME)

class DatabaseOrganization:
    DB_NAME = os.path.join(os.path.dirname(__file__), 'database', 'col_org.db3')

    def __init__(self):
        self.conn = sqlite3.connect(self.DB_NAME)
        self.cursor = self.conn.cursor()

    def set_up(self):
        self.create_table_org_types()
        self.create_table_organizations()
        self.create_table_collectors()
        self.fill_types()
        self.fill_organizations()
        self.fill_collectors()

    def create_table_org_types(self):
        query = """CREATE TABLE IF NOT EXISTS org_type(
                id INTEGER PRIMARY KEY,
                name VARCHAR(255) NOT NULL
                )"""
        self.cursor.execute(query)

    def create_table_organizations(self):
        query = """CREATE TABLE IF NOT EXISTS organization (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name VARCHAR(255) NOT NULL,
                commission TINYINT NOT NULL,
                type TINYINT NOT NULL,
                logo VARCHAR(255) NOT NULL,
                FOREIGN KEY (type) REFERENCES org_type(id)
                )"""
        self.cursor.execute((query))

    def create_table_collectors(self):
        query = """CREATE TABLE IF NOT EXISTS collector(
                id INT NOT NULL PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                surname VARCHAR(255) NOT NULL,
                phone VARCHAR(11) NOT NULL,
                secret VARCHAR(64) NOT NULL
                )
                """
        self.cursor.execute(query)

    def fill_types(self):
        query = 'INSERT INTO org_type (id, name) VALUES (?, ?)'
        types = [(1, 'Телефония'), (2, 'Интернет'), (3, 'Телевидение')]
        self.conn.executemany(query, types)
        self.conn.commit()

    def fill_organizations(self):
        query = 'INSERT INTO organization (name, commission, type, logo) VALUES (?, ?, ?, ?)'

        def logo(folder_name):
            return os.path.join('organizations_logo', folder_name, 'logo.png')
        organizations = [('МТС', 5, 1, logo('МТС')), ('МТС', 5, 2, logo('МТС')), ('МТС', 5, 3, logo('МТС')),
                         ('Билайн', 0, 1, logo('Билайн')), ('Билайн', 0, 2, logo('Билайн')), ('Билайн', 0, 3, logo('Билайн')),
                         ('Мегафон', 10, 1, logo('Мегафон')), ('Мегафон', 10, 2, logo('Мегафон')), ('Акадо-Урал', 1, 3, logo('Акадо-Урал')),
                         ('Мотив', 1, 1, logo('Мотив')), ('Ростелеком', 1, 2, logo('Ростелеком')), ('Планета', 1, 3, logo('Планета')),
                         ('Теле2', 1, 1, logo('Теле2')), ('Кабинет', 1, 2, logo('Кабинет')), ('Convex', 1, 3, logo('Convex')),
                         ('Utel', 1, 1, logo('Utel')), ('Акадо-Урал', 1, 2, logo('Акадо-Урал')), ('ДомРу', 1, 3, logo('ДомРу')),
                         ('Yota', 1, 1, logo('Yota')), ('Планета', 1, 2, logo('Планета')), ('Инсис', 1, 3, logo('Инсис')),
                         ('Таттелеком', 1, 1, logo('Таттелеком')), ('Convex', 1, 2, logo('Convex')), ('РусКом', 1, 3, logo('РусКом')),
                         ('Вайнах Телеком', 1, 1, logo('Вайнах Телеком')), ('ДомРу', 1, 2, logo('ДомРу')), ('Ростелеком', 1, 3, logo('Ростелеком')),
                         ('VK Mobile', 1, 1, logo('VK Mobile')), ('Инсис', 1, 2, logo('Инсис')), ('ТелеКарта', 1, 3, logo('ТелеКарта')),
                         ]
        self.cursor.executemany(query, organizations)
        self.conn.commit()

    def fill_collectors(self):
        query = '''INSERT INTO collector (id, name, surname, phone, secret) VALUES (?, ?, ?, ?, ?)'''
        collectors = [(488, 'Kirill', 'Cherkasov', '89049864438',
                       '9d6fa611b10c4a7ac6b68f953bbc536c4c45b8a4bc0fd215a5bf44254bc454d8'),
                      (1227, 'Larisa', 'Cherkasova', '89097019023',
                       '9d6fa611b10c4a7ac6b68f953bbc536c4c45b8a4bc0fd215a5bf44254bc454d8'),
                      ]
        self.cursor.executemany(query, collectors)
        self.conn.commit()

    @staticmethod
    def flush():
        if os.path.exists(DatabaseOrganization.DB_NAME):
            os.remove(DatabaseOrganization.DB_NAME)

if __name__ == '__main__':
    # DB.flush()
    DatabaseOrganization.flush()
    # db = DB()
    # db.set_up()
    dborg = DatabaseOrganization()
    dborg.set_up()


# Задача 30:  Заполните массив элементами арифметической прогрессии. Её первый элемент, разность и количество элементов нужно ввести с клавиатуры.

# a = int(input("Введите первый элемент прогресии "))
# d = int(input("Введите разность арифметической прогрессии "))
# max = int(input("Введите количество элементов в прогресии "))

# x=[a+(n-1)*d for n in range(1,max+1)]
# print(x)

#Задача 31: Определить индексы элементов массива (списка), значения которых принадлежат заданному диапазону (т.е. не меньше заданного минимума и не больше заданного максимума)

lst = [-5, 9, 0, 3, -1, -2, 1, 4, -2, 10, 2, 0, -9, 8, 10, -9, 0, -5, -5, 7]
a= int(input("Введите значение минимума "))
b= int(input("Введите значение максимума "))

index=[i for i, v in enumerate(lst) if a <= v <= b]
print(index)

#Задача 32:  Напишите программу, которая на вход принимает два числа A и B, и возводит число А в целую степень B с помощью рекурсии

# power = lambda base, exp: base * power(base, exp - 1) if exp!= 1 else base
# base = int(input("Введите число: "))
# exp = int(input("Введите его степень: "))
# print("Результат возведения в степень равен:", power(base, exp))


# Partie 1: Importation du jeu de données avec Pandas
from sklearn import metrics
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.read_csv("Iris.csv")
print("L'entête du dataframe: \n\n", df.head())

# sélectionner les observations des colonnes 1 à 4 dans X et de la colonne 5 dans Y
X = df.iloc[:, 1:5]
Y = df.iloc[:, 5]
print("\nL'entête de X: \n\n", X.head())
print("\nL'entête de Y: \n\n", Y.head())
# Partie 2: Visualisation des données avec Matplotlib
# méthode 1 avec boucle
# récuperer les valeurs uniques de Y (les 3 différentes espèces)
unique_y = np.unique(Y)

# initialiser une figure avec 10 pouces de large et 6 pouces de hauteur
plt.figure(figsize=(10, 6))

# créer un objet axe pour contenir nos données
axe = plt.subplot()

# ici par exemple, nous souhaitons avoir sur l'axe des abscices SepalLength, et sur les y PetalLength
data_x_col = 0
data_y_col = 2
axe.set_xlabel(X.columns.values[data_x_col])
axe.set_ylabel(X.columns.values[data_y_col])

# tracer un nuage de points pour chacune des espèces,
# en sélectionnant seulement les observations de l'espèce en question X[Y == i]
for i in unique_y:
    plt.scatter(X[Y == i].iloc[:, data_x_col],
            X[Y == i].iloc[:, data_y_col], label=i)

# afficher une légende correspondant à chaque nuage de points
plt.legend()

# afficher la figure
plt.show()
"""
# méthode 2 sans boucle
plt.figure(figsize=(10, 6))
plt.subplot()
plt.scatter(X[Y == 'Iris-setosa'].iloc[:, 0],
            X[Y == 'Iris-setosa'].iloc[:, 2], label='Iris-setosa')
plt.scatter(X[Y == 'Iris-versicolor'].iloc[:, 0], X[Y == 'Iris-versicolor'].iloc[:,
2],label='Iris-versicolor')
plt.scatter(X[Y == 'Iris-virginica'].iloc[:, 0],
            X[Y == 'Iris-virginica'].iloc[:, 2], label='Iris-virginica')
plt.legend()
plt.show()
"""
### FERMER LES FIGURES SUR PYCHARM POUR CONTINUER LA SUITE ###
# Partie 3: Apprentissage automatique avec Sklearn
# split du jeu de données
# split en 70% train et 30% test
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=1)
print("X_train.shape: ", X_train.shape)
print("X_test.shape : ", X_test.shape)
print("y_train.shape:", y_train.shape)
print("y_test.shape:", y_test.shape)
# entraînement du modèle k plus proche voisins
# considérer les 3 plus proches voisins (pour un meilleur fonctionnement, prendre un nombre impair)
classifier_knn=KNeighborsClassifier(n_neighbors = 3)
# entraîner le modèle
classifier_knn.fit(X_train, y_train)
# tester le modèle en utilisant la collection de test
y_pred=classifier_knn.predict(X_test)
# calculer l'accuracy du modèle en comparant les espèces prédites par le modèle 'y_pred' avec les vraies réponses 'y_test'
print("Accuracy:", metrics.accuracy_score(y_test, y_pred))
# faire une prédiction sur de nouvelles données
sample=[[5, 5, 3, 2], [2, 4, 3, 5]]
preds=classifier_knn.predict(sample)
print("Prédictions:", preds)
# Autre algorithme avec des forêts aléatoires
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(max_depth = 2, random_state = 1)
rfc.fit(X_train, y_train)
y_pred=rfc.predict(X_test)
print("Accuracy avec RFC:", metrics.accuracy_score(y_test, y_pred))
# Autre algorithme avec un réseau de neurones multi-couches
from sklearn.neural_network import MLPClassifier
clf=MLPClassifier(solver = 'adam', alpha = 1e-5, hidden_layer_sizes = (5, 5), max_iter = 2000,random_state = 1)
clf.fit(X_train, y_train)
y_pred=clf.predict(X_test)
print("Accuracy avec MLP:", metrics.accuracy_score(y_test, y_pred))


import tensorflow as tf
import numpy as np
from dbObL import dbOb
import pickle
import sys
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
import string
import math
import collections
import random
import datetime as dt
from sklearn.decomposition import PCA
from matplotlib import pyplot
from sklearn.feature_extraction.text import TfidfVectorizer
from config import *
import re
from sklearn.neighbors import NearestNeighbors
from nltk import bigrams

def get_mysql_data():
    dobj = dbOb()
    tcursor = dobj.db.cursor()
    fetchQry = "SELECT data FROM syllabotData"
    tcursor.execute(fetchQry, [])
    allFetch = tcursor.fetchall()
    allSents = [x[0] for x in allFetch]
    # print(allSents)
    return allSents

def tokenization_cleaning(allSents):
    tokens = [word_tokenize(report.lower()) for report in allSents]
    regex = re.compile('[%s]' % re.escape(string.punctuation)) #see documentation here: http://docs.python.org/2/library/string.html
    punct_remove = []
    for sent in tokens:
        new_tokens = []
        for token in sent:
            new_token = regex.sub(u'', token)
            if not new_token == u'':
                new_tokens.append(new_token)

        punct_remove.append(new_tokens)

    stop_remove = []
    for sent in punct_remove:
        new_term_vector = []
        for word in sent:
            if not word in stopwords.words('english'):
                new_term_vector.append(word)
        stop_remove.append(new_term_vector)
    return punct_remove, stop_remove

def knn_run(vectors, subject):
    nbrs = NearestNeighbors(n_neighbors=10, algorithm='ball_tree').fit(vectors)
    distances, indices = nbrs.kneighbors([subject])
    return indices

def join_bigrams(stop_remove):
    target_bigram_list = [('cs', '252'), ('email', 'id'), ('final', 'exam'), ('midterm', 'exam')]
    replace_bigram_list = ['cs_252', 'email_id', 'final_exam', 'midterm_exam']
    new_stop_remove = []
    for sent in stop_remove:
        new_sent = []
        bgrm = list(bigrams(sent))
        for tbgrm in target_bigram_list:
            if tbgrm in bgrm:
                new_sent.append(replace_bigram_list[target_bigram_list.index(tbgrm)])
                for bw in tbgrm:
                    sent.pop(sent.index(bw))
        for word in sent:
            new_sent.append(word)
        new_stop_remove.append(new_sent)
    return new_stop_remove

def attach_important_stops(punct_remove, stop_remove, wv, wordidx):
    question_stops = set(["what", "how", "when", "where", "which"])
    new_final_tokens = []
    # print("stop_remove", stop_remove)
    stop_remove = join_bigrams(stop_remove)
    for sent in stop_remove:
        if len(sent) == 1:
            idx = stop_remove.index(sent)
            punct_map = set(punct_remove[idx])
            hit_stop = list(set(punct_map).intersection(question_stops))
            if len(hit_stop) > 0:
                for hs in hit_stop:
                    indices = knn_run(wv, wv[wordidx.index(hs)])
                    for index in indices[0][1:]:
                        if wordidx[index] not in question_stops:
                            sent.insert(0, wordidx[index])
                            break
            else:
                new_final_tokens.append(sent)
        new_final_tokens.append(sent)
    return new_final_tokens

def cleaned_input(wv, widx):
    allSents = get_mysql_data()
    punct_remove, stop_remove = tokenization_cleaning(allSents)
    final_tokens = attach_important_stops(punct_remove, stop_remove, wv, widx)
    return final_tokens

def sort_mysql_data(final_tokens):
    f = open("./data/allData", "w")
    for list_token in final_tokens:
        f.write(' '.join(list_token))
        f.write("\n")
    f.close()

def build_data():
    pf = open("./data/pairings", "r")
    pairs = pf.read().split("\n")
    allwords = []
    for pair in pairs:
        pairword = pair.split(",")
        for pw in pairword:
            if pw not in allwords:
                allwords.append(pw)
    # print(allwords)
    pf.close()
    X = np.eye(len(allwords), dtype=int)
    pair2d = []
    for pair in pairs:
        pairsplit = pair.split(",")
        pair2d.append(pairsplit)

    y = np.zeros((len(allwords), len(allwords)), np.int)

    r = 0
    for x in X:
        idx = np.where(x == 1)[0][0]
        iw = allwords[idx]
        for p1d in pair2d:
            if iw in p1d:
                for ws in p1d:
                    y[r][allwords.index(ws)] = 1
        r += 1
    return X, y, allwords

def gen_w2v(X, y):
    x_train = np.asarray(X)
    y_train = np.asarray(y)
    vocab_size = len(X)
    x = tf.placeholder(tf.float32, shape=(None, vocab_size))
    y_label = tf.placeholder(tf.float32, shape=(None, vocab_size))

    EMBEDDING_DIM = 3
    W1 = tf.Variable(tf.random_normal([vocab_size, EMBEDDING_DIM]))
    b1 = tf.Variable(tf.random_normal([EMBEDDING_DIM])) #bias
    hidden_representation = tf.add(tf.matmul(x,W1), b1)

    W2 = tf.Variable(tf.random_normal([EMBEDDING_DIM, vocab_size]))
    b2 = tf.Variable(tf.random_normal([vocab_size]))
    prediction = tf.nn.softmax(tf.add( tf.matmul(hidden_representation, W2), b2))

    sess = tf.Session()
    init = tf.global_variables_initializer()
    sess.run(init)

    cross_entropy_loss = tf.reduce_mean(-tf.reduce_sum(y_label * tf.log(prediction), reduction_indices=[1]))
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy_loss)

    n_iters = 10000
    for _ in range(n_iters):
        sess.run(train_step, feed_dict={x: x_train, y_label: y_train})
        print('loss is : ', sess.run(cross_entropy_loss, feed_dict={x: x_train, y_label: y_train}))

    vectors = sess.run(W1 + b1)
    return vectors

def plot_vectors(wvs, wordidx):
    pca = PCA(n_components=2)
    result = pca.fit_transform(wvs)
    pyplot.scatter(result[:, 0], result[:, 1])
    for i, word in enumerate(wordidx):
    	pyplot.annotate(word, xy=(result[i, 0], result[i, 1]))
    pyplot.show()

def save_vocab(wordidx):
    np.save("./data/vocab", wordidx)

def main():
    buildFlag = None
    mysqlPullFlag = False
    if len(sys.argv) > 1:
        buildFlag = sys.argv[1]
        if "--data-pull=true" in sys.argv:
            mysqlPullFlag = True
    X, y, wordidx = build_data()
    save_vocab(wordidx)
    # print(np.load("./data/vocab.npy"))
    word_vec_file = "wv.pkl"
    wvs = None
    if buildFlag == '-n' or buildFlag is None:
        wvs = gen_w2v(X, y)
        with open(word_vec_file, "wb") as f:
            pickle.dump(wvs, f)
    elif buildFlag == "-o":
        with open(word_vec_file, "rb") as f:
            wvs = pickle.load(f)

    if wvs is None:
        print("error loading w2v model")
        sys.exit(-1)

    # plot_vectors(wvs, wordidx)
    if mysqlPullFlag:
        final_tokens = cleaned_input(wvs, wordidx)
        sort_mysql_data(final_tokens)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov  6 23:31:48 2019

@author: bala
"""

from time import sleep

def getUsernput(waitTime):
    print(f'Please provide input in {waitTime} seconds! (Hit Ctrl-C to start)')
    try:
        discreteInterval = int(waitTime/0.05)
        for i in range(0,discreteInterval):
            sleep(0.05) # could use a backward counter to be preeety :)
        print('No input is given.')
    except KeyboardInterrupt:
        x = input('Input x:')
        print(f'Given Input : {x}')
        return x


from bcbcpy.__ import __author__

from bcbcpy.blockchain.block.block import Block
from bcbcpy.blockchain.block.transaction import TransactionBlock, TransactionData
from bcbcpy.node import Node as _Node

__all__ = ["Node"]

class Node(_Node):
    def make_transaction_data(
        self,
        assets: float,
        to: "Node",
        prev_block: Block,
    ) -> TransactionData:
        trans_data = TransactionData(assets, self, to.id, to.pub, prev_block)
        return trans_data

    def make_transaction_block(
        self,
        assets: float,
        to: "Node",
        prev_block: Block,
        next_difficulty: int = 4,
    ) -> TransactionBlock:
        trans_data = self.make_transaction_data(assets, to, prev_block)
        trans_block = TransactionBlock(trans_data, next_difficulty)
        return trans_block


from tic_tac_toe.board import Board
from tic_tac_toe.constants import board_size
from tic_tac_toe.constants import player_dict
from tic_tac_toe.constants import win_pos
from tic_tac_toe.ql import QLearning
import random
import copy
import csv

def init_board_states():
    state = ['0'] * board_size
    for i in range(3):
        state[0] = str(i)
        for j in range(3):
            state[1] = str(j)
            for k in range(3):
                state[2] = str(k)
                for l in range(3):
                    state[3] = str(l)
                    for m in range(3):
                        state[4] = str(m)
                        for n in range(3):
                            state[5] = str(n)
                            for o in range(3):
                                state[6] = str(o)
                                for p in range(3):
                                    state[7] = str(p)
                                    for q in range(3):
                                        state[8] = str(q)
                                        if valid_state(state):
                                            state_str = "".join(state)
                                            states[state_str] = Board(copy.deepcopy(state))

    set_board_actions()

def set_board_actions():
    i = 0
    for key in states:
        # if i == 10:
        #     break
        print(i)
        i += 1
        board = states[key]

        if not board.terminal:
            if board.move == player_dict['X'] or board.move == player_dict['EMPTY']:
                add_x_actions(board)
            if board.move == player_dict['O'] or board.move == player_dict['EMPTY']:
                add_o_actions(board)

def add_x_actions(board):
    for key in states:
        temp_board = states[key]
        if board.compare(temp_board.state, player_dict['X']) == 1 and \
                board.compare(temp_board.state, player_dict['O']) == 0 and board.x_count == temp_board.x_count - 1:
            board.add_action(temp_board, player_dict['X'])

def add_o_actions(board):
    for key in states:
        temp_board = states[key]
        if board.compare(temp_board.state, player_dict['O']) == 1 and \
                board.compare(temp_board.state, player_dict['X']) == 0 and board.o_count == temp_board.o_count - 1:
            board.add_action(temp_board, player_dict['O'])

def valid_state(state):
    valid = True
    x_player = player_dict['X']
    o_player = player_dict['O']

    x_count = 0
    o_count = 0

    for pos in state:
        if pos == x_player:
            x_count += 1
        elif pos == o_player:
            o_count += 1

    if abs(x_count - o_count) > 1:
        valid = False

    o_wins = False
    x_wins = False
    for w in win_pos:
        if state[w[0]] == x_player and state[w[1]] == x_player and state[w[2]] == x_player:
            x_wins = True
        if state[w[0]] == o_player and state[w[1]] == o_player and state[w[2]] == o_player:
            o_wins = True

    if x_wins and o_wins:
        valid = False

    return valid

def save_boards_to_csv():
    with open('tic_tac_toe_x_actions.csv', mode='w') as csv_file:
        csv_writer = csv.writer(csv_file, delimiter=',', lineterminator='\n')

        for key in states:
            temp_list = [key]
            state = states[key]
            for action_board in state.x_q:
                board_str = "".join(action_board[0].state)
                temp_list.append(board_str)
            csv_writer.writerow(temp_list)

    with open('tic_tac_toe_o_actions.csv', mode='w') as csv_file:
        csv_writer = csv.writer(csv_file, delimiter=',', lineterminator='\n')

        for key in states:
            temp_list = [key]
            state = states[key]
            for action_board in state.o_q:
                board_str = "".join(action_board[0].state)
                temp_list.append(board_str)
            csv_writer.writerow(temp_list)

def read_board_states():
    with open('tic_tac_toe_x_actions.csv') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        for row in csv_reader:
            board = row[0]
            states[board] = Board(list(board))

    with open('tic_tac_toe_x_actions.csv') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        for row in csv_reader:
            board = row[0]
            row_length = len(row)
            for i in range(1, row_length):
                action = states[row[i]]
                states[board].add_action(action, player_dict['X'])

    with open('tic_tac_toe_o_actions.csv') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        for row in csv_reader:
            board = row[0]
            row_length = len(row)
            for i in range(1, row_length):
                action = states[row[i]]
                states[board].add_action(action, player_dict['O'])

states = {}
# init_board_states()
# save_boards_to_csv()
read_board_states()
# print(states['202100121'].o_q)
ql = QLearning(states)
ql.ql()

# choice_one = random.choice(list(states.keys()))
# choice_two = random.choice(list(states.keys()))
# print(len(states))
# print(states[choice_one].compare(states[choice_one].state, player_dict['EMPTY']))
# print(choice_one)
# state = states[choice_one]
# state.display()
# for action in states[choice_one].x_q:
#     print(action[0].state)
# print(states[choice_one].state)
# print(states[choice_two].state)


"""create user_role table

Revision ID: 227d7972fc56
Revises: 40a51d118d42
Create Date: 2019-07-22 02:30:45.180876

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '227d7972fc56'
down_revision = '40a51d118d42'
branch_labels = None
depends_on = None

def upgrade():
    op.create_table(
        'role_user',
        sa.Column('user_id', sa.Integer, sa.ForeignKey('user.id')),
        sa.Column('role_id', sa.Integer, sa.ForeignKey('role.id'))
    )

def downgrade():
    op.drop_table('role_user')


from os import path
import numpy as np

from models.loss_functions import *
from utilities.utls import read_pretrained_data, make_dirs

class hed_net():

    def __init__(self, args):
        self.args =args
        self.im_height= args.image_height
        self.im_width = args.image_width
        if args.use_trained_weights:
            weights_fir = 'models'
            self.vgg16_weights = read_pretrained_data(weights_fir,args.vgg16_param)
        self.input = tf.placeholder(tf.float32,[None,args.image_height, \
            args.image_width, args.n_channels],name='input')

        self.edgemaps = tf.placeholder(tf.float32,shape=[
            None, args.image_height, args.image_width,1], name = 'label')
        m = args.mean_pixel_values

        self.mean = tf.constant([m[2],m[1],m[0]], dtype=tf.float32, shape=[1,1,1,3],
                                name='img_mean')if not args.use_nir else \
            tf.constant([m[2], m[1], m[0], m[-1]], dtype=tf.float32, shape=[1, 1, 1, 3],
                        name='img_mean')

        self.define_model()

    def variable_on_cpu(self,name, shape, initializer):

        with tf.device('/cpu:0'):
            var = tf.get_variable(name=name,shape=shape,initializer=initializer,dtype=tf.float32)
        return var

    def variable_with_weight_decay(self, name, shape, stddev,wd=None):

        var = self.variable_on_cpu(name=name,shape=shape, \
                initializer=tf.keras.initializers.Zeros())  # previous tf.truncated_normal_initializer(mean=0.,stdded=0.01)
        # tf.contrib.layers.xavier_initializer() / tf.keras.initializers.Zeros()
        if wd is not None:
            weight_decay = tf.multiply(tf.nn.l2_loss(var), wd, name=name+'_weight_loss')
            tf.add_to_collection('losses', weight_decay)
        return var

    def get_bilinear_weight(self, k_size,out_chanels=1,name=''):

        factor = (k_size+1)//2
        if k_size%2==1:
            center =factor-1
        else:
            center=factor-0.5
        og = np.ogrid[:k_size,:k_size]
        filt = (1-abs(og[0]-center)/factor)*(1-abs(og[1]-center)/factor)
        w=np.zeros((k_size,k_size,out_chanels,out_chanels))
        for i in range(out_chanels):
            for j in range(out_chanels):
                if i==j:
                    w[:,:,i,j]=filt
        init = tf.constant_initializer(value=w,dtype=tf.float32)
        return tf.get_variable(name=name, initializer=init,shape=w.shape)

    def conv2d(self, input, output, k, s, name='',use_bias=True,use_trained=False,weight_decay=None):

        if use_trained:
            with tf.variable_scope(name):

                w_shape = self.vgg16_weights[name+'_W'].shape
                w_init = tf.constant_initializer(self.vgg16_weights[name+'_W'], dtype=tf.float32)
                w = tf.get_variable(name=name+'_W', initializer=w_init, shape=w_shape)
                conv = tf.nn.conv2d(input=input,filter=w,strides=[1,s,s,1],padding="SAME",
                                    name=name)
                if use_bias:
                    b_shape = self.vgg16_weights[name + '_b'].shape
                    b_init =tf.constant_initializer(self.vgg16_weights[name + '_b'],dtype=tf.float32)
                    b = tf.get_variable(name=name+'_b',shape=b_shape, initializer=b_init)
                    conv = tf.nn.bias_add(conv,b)
                return tf.nn.relu(conv)
        else:
            in_size = input.get_shape().as_list()[-1]
            w = self.variable_with_weight_decay(name=name+'_W',shape=[k,k,in_size,output],
                                                stddev=0.01, wd=weight_decay) # previous  stddev=0.1
            conv = tf.nn.conv2d(input=input,filter=w,strides=[1, s, s, 1],padding="SAME",
                                name=name)
            if use_bias:
                b = self.variable_on_cpu(name=name + '_b', shape=[output],
                                         initializer=tf.constant_initializer(0.0))
                conv = tf.nn.bias_add(conv,b)

        return conv

    def max_polling(self, input,name=''):

        max_pool = tf.nn.max_pool(value=input, ksize=[1,2,2,1],strides=[1,2,2,1],
                                  padding='SAME',name=name)
        return max_pool

    def _upscore_layer(self, input, shape, n_outputs, name,
                       ksize=4, stride=2):
        strides = [1, stride, stride, 1]
        with tf.variable_scope(name):
            in_features = input.get_shape()[3].value

            if shape is None:
                # Compute shape out of Bottom
                in_shape = tf.shape(input)

                h = ((in_shape[1] - 1) * stride) + 1
                w = ((in_shape[2] - 1) * stride) + 1
                new_shape = [in_shape[0], h, w, n_outputs]
            else:
                new_shape = [shape[0], shape[1], shape[2], n_outputs]
            output_shape = tf.stack(new_shape)

            f_shape = [ksize, ksize, n_outputs, in_features]

            # create
            num_input = ksize * ksize * in_features / stride
            stddev = (2 / num_input) ** 0.5

            weights = self.get_deconv_filter(f_shape)
            deconv = tf.nn.conv2d_transpose(input, weights, output_shape,
                                            strides=strides, padding='SAME')
        # _activation_summary(deconv)
        return deconv

    def get_deconv_filter(self, f_shape):
        width = f_shape[0]
        heigh = f_shape[0]
        f = np.ceil(width / 2.0)
        c = (2 * f - 1 - f % 2) / (2.0 * f)
        bilinear = np.zeros([f_shape[0], f_shape[1]])
        for x in range(width):
            for y in range(heigh):
                value = (1 - abs(x / f - c)) * (1 - abs(y / f - c))
                bilinear[x, y] = value
        weights = np.zeros(f_shape)
        for i in range(f_shape[2]):
            weights[:, :, i, i] = bilinear

        init = tf.constant_initializer(value=weights,
                                       dtype=tf.float32)

        return tf.get_variable(name="up_filter", initializer=init, shape=weights.shape)

    def side_output(self,input,weigth_decay=None,name=None, up_scale=2):

        output = self.conv2d(input=input,output=1, k=1,s=1,name=name+'_conv', use_bias=False,
                             weight_decay=self.args.weight_decay)
        c_shape = output.get_shape().as_list()[2]

        if c_shape != self.args.image_width:
            output = tf.image.resize_bilinear(images=output,size=[self.args.image_height, \
                        self.args.image_width],align_corners=True)
            # in_shape = tf.shape(input)
            # out_shape = [in_shape[0],self.args.image_height,self.args.image_width,1]
            # output = self.up_sampling(input=output,stride=2,output_shape=out_shape,
            #                           name=name+'_ldconv',up_scale=up_scale)
        return output

    def prepare_aligned_crop(self):
        """ Prepare for aligned crop. """
        # Re-implement the logic in deploy.prototxt and
        #   /hed/src/caffe/layers/crop_layer.cpp of official repo.
        # Other reference materials:
        #   hed/include/caffe/layer.hpp
        #   hed/include/caffe/vision_layers.hpp
        #   hed/include/caffe/util/coords.hpp
        #   https://groups.google.com/forum/#!topic/caffe-users/YSRYy7Nd9J8

        def map_inv(m):
            """ Mapping inverse. """
            a, b = m
            return 1 / a, -b / a

        def map_compose(m1, m2):
            """ Mapping compose. """
            a1, b1 = m1
            a2, b2 = m2
            return a1 * a2, a1 * b2 + b1

        def deconv_map(kernel_h, stride_h, pad_h):
            """ Deconvolution coordinates mapping. """
            return stride_h, (kernel_h - 1) / 2 - pad_h

        def conv_map(kernel_h, stride_h, pad_h):
            """ Convolution coordinates mapping. """
            return map_inv(deconv_map(kernel_h, stride_h, pad_h))

        def pool_map(kernel_h, stride_h, pad_h):
            """ Pooling coordinates mapping. """
            return conv_map(kernel_h, stride_h, pad_h)

        x_map = (1, 0)
        conv1_1_map = map_compose(conv_map(3, 1, 35), x_map)
        conv1_2_map = map_compose(conv_map(3, 1, 1), conv1_1_map)
        pool1_map = map_compose(pool_map(2, 2, 0), conv1_2_map)

        conv2_1_map = map_compose(conv_map(3, 1, 1), pool1_map)
        conv2_2_map = map_compose(conv_map(3, 1, 1), conv2_1_map)
        pool2_map = map_compose(pool_map(2, 2, 0), conv2_2_map)

        conv3_1_map = map_compose(conv_map(3, 1, 1), pool2_map)
        conv3_2_map = map_compose(conv_map(3, 1, 1), conv3_1_map)
        conv3_3_map = map_compose(conv_map(3, 1, 1), conv3_2_map)
        pool3_map = map_compose(pool_map(2, 2, 0), conv3_3_map)

        conv4_1_map = map_compose(conv_map(3, 1, 1), pool3_map)
        conv4_2_map = map_compose(conv_map(3, 1, 1), conv4_1_map)
        conv4_3_map = map_compose(conv_map(3, 1, 1), conv4_2_map)
        pool4_map = map_compose(pool_map(2, 2, 0), conv4_3_map)

        conv5_1_map = map_compose(conv_map(3, 1, 1), pool4_map)
        conv5_2_map = map_compose(conv_map(3, 1, 1), conv5_1_map)
        conv5_3_map = map_compose(conv_map(3, 1, 1), conv5_2_map)

        score_dsn1_map = conv1_2_map
        score_dsn2_map = conv2_2_map
        score_dsn3_map = conv3_3_map
        score_dsn4_map = conv4_3_map
        score_dsn5_map = conv5_3_map

        upsample2_map = map_compose(deconv_map(4, 2, 0), score_dsn2_map)
        upsample3_map = map_compose(deconv_map(8, 4, 0), score_dsn3_map)
        upsample4_map = map_compose(deconv_map(16, 8, 0), score_dsn4_map)
        upsample5_map = map_compose(deconv_map(32, 16, 0), score_dsn5_map)

        crop1_margin = int(score_dsn1_map[1])
        crop2_margin = int(upsample2_map[1])
        crop3_margin = int(upsample3_map[1])
        crop4_margin = int(upsample4_map[1])
        crop5_margin = int(upsample5_map[1])

        return crop1_margin, crop2_margin, crop3_margin, crop4_margin, crop5_margin

    def define_model(self):
        with tf.variable_scope(self.args.model_name.lower()):

            use_tw = self.args.use_trained_weights  # if true use trained weights from VGG16

            #block 1
            self.conv1_1 = self.conv2d(input=self.input,output=64,k=3,s=1,name='conv1_1',use_trained=True)
            self.conv1_2 = self.conv2d(input=self.conv1_1,output=64,k=3,s=1,name='conv1_2', use_trained=True)
            self.output_1 = self.side_output(self.conv1_2,name='output1')
            self.max_pool1 = self.max_polling(self.conv1_2,name='maxpool1')

            # block 2
            self.conv2_1 = self.conv2d(input=self.max_pool1,output=128,k=3,s=1,name='conv2_1',use_trained=True)
            self.conv2_2 = self.conv2d(input=self.conv2_1,output=128,k=3,s=1,name='conv2_2',use_trained=True)
            self.output_2 = self.side_output(self.conv2_2, name='output2', up_scale=2)
            self.max_pool2 = self.max_polling(self.conv2_2, name='maxpool2')

            # block 3
            self.conv3_1 = self.conv2d(input=self.max_pool2,output=256,k=3,s=1,name='conv3_1',use_trained=True)
            self.conv3_2 = self.conv2d(input=self.conv3_1, output=256, k=3, s=1, name='conv3_2',use_trained=True)
            self.conv3_3 = self.conv2d(input=self.conv3_2, output=256, k=3, s=1, name='conv3_3',use_trained=True)
            self.output_3 = self.side_output(self.conv3_3, name='output3', up_scale=4)
            self.max_pool3 = self.max_polling(self.conv3_3, name='maxpool3')

            # block 4
            self.conv4_1 = self.conv2d(input=self.max_pool3, output=512, k=3, s=1, name='conv4_1',use_trained=True)
            self.conv4_2 = self.conv2d(input=self.conv4_1, output=512, k=3, s=1, name='conv4_2',use_trained=True)
            self.conv4_3 = self.conv2d(input=self.conv4_2, output=512, k=3, s=1, name='conv4_3',use_trained=True)
            self.output_4 = self.side_output(self.conv4_3, name='output4',up_scale=8)
            self.max_pool4 = self.max_polling(self.conv4_3, name='maxpool4')

            # block 5
            self.conv5_1 = self.conv2d(input=self.max_pool4, output=512, k=3, s=1, name='conv5_1',use_trained=True)
            self.conv5_2 = self.conv2d(input=self.conv5_1, output=512, k=3, s=1, name='conv5_2',use_trained=True)
            self.conv5_3 = self.conv2d(input=self.conv5_2, output=512, k=3, s=1, name='conv5_3',use_trained=True)
            self.output_5 = self.side_output(self.conv5_3, name='output5',up_scale=16)

            self.side_outputs = [self.output_1, self.output_2, self.output_3,
                                 self.output_4, self.output_5]
            side_outputs = tf.concat(self.side_outputs, axis=3)

            fw = self.variable_on_cpu(name='fuse',shape=[1,1,len(self.side_outputs),1],
                                      initializer=tf.constant_initializer(0.2))
            self.fuse = tf.nn.conv2d(side_outputs,filter=fw,strides=[1,1,1,1],padding='SAME',
                                      name='fuse')

            self.outputs = self.side_outputs+[self.fuse]

    # ***************************END MODEL DEFINITION **************************

    def test_model(self, session):
        self.predictions = []

        for idx, b in enumerate(self.outputs):
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            self.predictions.append(output)

    def train_model(self, session):

        self.predictions = []
        self.loss = 0

        print('Deep supervision application set to {}'.format(self.args.deep_supervision))

        for idx, b in enumerate(self.side_outputs):
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            cost = sigmoid_cross_entropy_balanced(b, self.edgemaps, name='cross_entropy{}'.format(idx))
            # before sigmoid_cross_entropy_balanced

            self.predictions.append(output)
            if self.args.deep_supervision:
                s_cost = (self.args.loss_weights * cost)
                tf.add_to_collection('losses', s_cost)
                self.loss += cost
                #deep_supervision
        self.fuse_output = tf.nn.sigmoid(self.fuse, name='fuse')
        fuse_cost = sigmoid_cross_entropy_balanced(self.fuse, self.edgemaps, name='cross_entropy_fuse')

        self.predictions.append(self.fuse_output)
        f_cost = (self.args.loss_weights * fuse_cost)
        tf.add_to_collection('losses', f_cost)
        self.loss += f_cost

        # *************evaluation code
        tf.add_to_collection('losses',self.loss)
        self.all_losses = tf.add_n(tf.get_collection('losses'), name='all_losses')
        mean_loss = tf.train.ExponentialMovingAverage(0.9, name='avg')
        all_loss = tf.get_collection('losses')
        self.mean_average_op = mean_loss.apply(all_loss+[self.all_losses])
        # end ***************************

        pred = tf.cast(tf.greater(self.fuse_output, 0.5), tf.int32, name='predictions')
        error = tf.cast(tf.not_equal(pred, tf.cast(self.edgemaps, tf.int32)), tf.float32)
        self.error = tf.reduce_mean(error, name='pixel_error')

        tf.summary.scalar('Train', self.all_losses) # previously self.loss
        tf.summary.scalar('Validation', self.error)

        train_log_dir = path.join(self.args.logs_dir, self.args.model_name.lower() +
                                  '_' + self.args.dataset4training.lower(),self.args.model_state)
        val_log_dir = path.join(self.args.logs_dir, self.args.model_name.lower() +
                                '_' + self.args.dataset4training.lower(), 'val')
        _ = make_dirs(train_log_dir)
        _ = make_dirs(val_log_dir)

        self.merged_summary = tf.summary.merge_all()
        self.train_writer = tf.summary.FileWriter(train_log_dir, session.graph)
        self.val_writer = tf.summary.FileWriter(val_log_dir)


import os
import sys
from stat import S_ISDIR, ST_MODE

from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils.text import slugify

from bober_simple_competition.models import Question, QuestionSet

class Command(BaseCommand):
    args = "<dirname>"
    help = "Add a whole questionset at a time"

    def add_arguments(self, parser):
        parser.add_argument('dirname', nargs='+', type=str)

    @transaction.atomic
    def handle(self, *args, **options):
        if len(args) > 0:
            dirname = options.get('dirname', [args[0]])[0]
        else:
            dirname = options['dirname'][0]
        mode = os.stat(dirname)[ST_MODE]
        if not S_ISDIR(mode):
            self.stderr.write("Not a directory")
            sys.exit(1)
        questions = []
        split_path = os.path.split(dirname)
        name = split_path[1]
        if name == '':
            name = os.path.split(split_path[0])[1]
        slug = slugify(name)
        for i in os.listdir(dirname):
            try:
                q = Question.from_dir(os.path.join(dirname, i))
                questions.append(q)
            except Exception as e:
                self.stdout.write("Error in {}: {}".format(i, e))
        self.stdout.write("created {}".format(slug))
        question_set, _ = QuestionSet.objects.get_or_create(name=name, slug=slug)
        question_set.questions.clear()
        self.stdout.write("filling questionset")
        for q in questions:
            q_dict = Question.objects.filter(id=q.id).values_list()[0]
            self.stdout.write(str(q_dict))
            question_set.questions.add(q)
        question_set.rebuild_caches()


# BFS
def canVisitAll(rooms):
    visited, queue = {0}, [0]
    while queue:
        room_index = queue.pop()
        for key in rooms[room_index]:
            if key not in visited:
                visited.add(key)
                queue.insert(0, key)
    return len(visited) == len(rooms)

rooms = eval(input())
print(canVisitAll(rooms))

data structure and algorithm_exercise/ex8/ex8_3.py


from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
def main():
    return render_template('home.html')

@app.route('/resultado', methods=['POST'])
def calcular():
    if request.method == 'POST':

        voltaje_bateria=float(request.form.get('voltaje'))
        voltaje_panel=float(request.form.get('voltaje_paneles'))
        corriente_pico=float(request.form.get('corriente_pico'))
        corriente_corto=float(request.form.get('corriente_corto'))
        watts_paneles=float(request.form.get('watts'))
        amperios_bateria=float(request.form.get('amperios'))
        array = request.form.getlist('field[]')
        #Variables
        consumo_promeido_diario=0
        watts_totales=0
        amperes_hora_dia=0
        amperes_pico=0
        baterias_serie=0
        baterias_paralelo=0
        baterias_totales=0
        modulos_serie=0
        modulos_paralelo=0
        modulos_totales=0
        array=list(map(float, array))

        for i in range(0,len(array),4):
            consumo_promeido_diario+=array[i]*array[i+1]*array[i+2]*array[i+3]/7
            watts_totales+=array[i+1]

        #Dimensionado de baterias
        amperes_hora_dia=consumo_promeido_diario/0.9/48
        baterias_paralelo=round(amperes_hora_dia*4/0.5/amperios_bateria)
        baterias_serie=round(48/voltaje_bateria)
        baterias_totales=baterias_paralelo*baterias_serie

        #Dimensionado del sistema
        amperes_pico=amperes_hora_dia/0.8/4
        #Numero de modulos fotovoltaicos
        modulos_paralelo=round(amperes_pico/corriente_pico)
        modulos_serie=48/voltaje_panel
        modulos_totales=modulos_paralelo*modulos_serie

        respuesta={
            "consumo_diario":round(consumo_promeido_diario),
            "watts_totales":watts_totales,
            "amperes_hora_dia":round(amperes_hora_dia,2),
            "amperes_pico_arreglo":round(amperes_pico,2),
            "baterias_serie":baterias_serie,
            "baterias_paralelo":baterias_paralelo,
            "baterias_totales":baterias_totales,
            "capacidad_bateria":amperios_bateria,
            "voltaje_bateria":voltaje_bateria,
            "modulos_serie":int(modulos_serie),
            "modulos_paralelo":int(modulos_paralelo),
            "modulos_totales":int(modulos_totales),
            "corriente_pico":corriente_pico,
            "corriente_corto":corriente_corto,
            "voltaje_paneles":voltaje_panel,
            "watts_paneles":watts_paneles

        }

        return render_template('result.html', rs=respuesta)

if __name__ == ' __main__':
    app.debug = True
    app.run()


import telebot
import requests
import json

TKN = '5812655786:AAF6wr3qY5USkYRgDET2dKq1vaDHz_oYkzI'

ANC = 'https://api.weather.yandex.ru/v2/informers?lat=55.75222&lon=37.61556'

bot = telebot.TeleBot(TKN)

@bot.message_handler(content_types=['text'])
def echo(message):
    bot.send_message(message.chat.id, text=f"{message.text}")

bot.polling(none_stop=True)


from pyomo.environ import *
from pyomo.opt import SolverFactory
from pyomo.opt import SolverStatus, TerminationCondition
import time

### Auxiliary code ###
###This part allows to have a "machine-independent" code if some conventions are respected

import os, sys
sys.path.insert(0,os.path.abspath(os.path.join(os.path.dirname(__file__),'../utilities')))
from optmodel_utilities import *

def create_solver(solver_name = 'cplex'):
    solver_path = get_solver_path(solver_name)
    return  SolverFactory(solver_name, executable=str(solver_path), solver_io = 'nl')

#
# Model
#

def VNFHeurist1(VNFix):

    infinity = float('inf')

    model = AbstractModel()

    #number of services
    model.nb_f=Param()

    #Set of service type
    model.F=Set()

    #number of possible module
    model.nb_m=Param()

    # arc capacity
    model.uu = Param()

    #capacity of each module
    model.mu =Param()

    # nodes capacity
    model.nu = Param()

    #number of nodes
    model.nb_n=Param()

    #number of demand
    model.nb_d=Param()

    #auxiliaire node
    model.a=Param(default=0)

    model.a_set = RangeSet(model.a,model.a)

    #Set of services
    model.S=RangeSet(model.nb_f)
    model.S1=RangeSet(model.nb_f+1)

    #Set of module
    model.L=RangeSet(model.nb_m)

    #Set of nodes
    model.N=RangeSet(model.nb_n)

    #Set of nodes union {a}
    model.N_a = RangeSet(0,model.nb_n)
    #model.N_a = Set(model.N | model.a)

    #Set of demands
    model.D=RangeSet(model.nb_d)

    # Arcs
    model.A=Set(within=model.N*model.N)

    model.all_a=Set(initialize=model.N*model.a_set)

    model.a_all=Set(initialize=model.a_set*model.N)
    #Arcs union {a}
    #model.AMD=Set(within=model.N_a*model.N_a)
    model.AMD=model.all_a | model.a_all | model.A

    #Demand parameters
    model.o = Param(model.D,within=NonNegativeIntegers)
    model.t = Param(model.D,within=NonNegativeIntegers)
    model.d = Param(model.D,within=NonNegativeIntegers)

    #Parameter of fixe order
    #f is a bidimentional matrix, indexes are demand and VNF position
    # the value is the VNF type that is in a given position for the demand
    model.f=Param(model.D,model.S,within=model.F) #BA:

    #Assignment and location variables
    model.Y=Var(model.N_a,model.F,model.L,within=Binary)
    model.Z=Var(model.N_a,model.D,model.F,within=Binary)

    #Routing variables
    model.X=Var(model.AMD,model.D,model.S1,within=Binary)

    #Add Constraint
    #model.Const=ConstraintList() #BA Why this?!

    #objective function
    def SP(model):
        value=sum(model.Z[i,k,f] for i in model.N for k in model.D for f in model.F)
        return value

    model.cost = Objective(rule=SP, sense=maximize)

    #constraint 1 : each demand to be assigned to one service
    def D_to_S(model,k,f):
        return sum(model.Z[i,k,f] for i in model.N_a) == 1

    model.Demand_Service = Constraint(model.D,model.F,rule= D_to_S)

    #Constraint 2 :  a demand is assigned to a node only if a service instance is located on the node
    def D_to_S_Node(model,i,k,f):
        return model.Z[i,k,f] <= sum(model.Y[i,f,l] for l in model.L)

    model.Demand_Service_node = Constraint(model.N_a,model.D,model.F,rule= D_to_S_Node)

    #Constraint 3 : the link capacity constraints #range(1,model.nb_f+1)
    def Link_Capacity(model,i,j):
        value=[]
        value=sum(sum(model.d[k]*model.X[i,j,k,s] for s in model.S1) for k in model.D)
        return value <= model.uu

    model.Link_capacity_const = Constraint(model.AMD,rule= Link_Capacity)# Ajouter AMD

    #Constraint 4 : a simple path is used to route each demand
    def routing_first_subpath(model,i,k):
        value=sum(model.X[i,j,k,1] for j in model.N if (i,j) in model.AMD) - sum(model.X[j,i,k,1] for j in model.N if (i,j) in model.AMD)

        if i == model.o[k] :
            return value == 1-model.Z[i,k,model.f[k,1]]
        else :
            return value == -model.Z[i,k,model.f[k,1]]

    model.routing_first_subpath_const = Constraint(model.N_a,model.D,rule= routing_first_subpath)

    #Constraint 5 : a simple path is used to route each demand
    def routing_last_subpath(model,i,k):
        value = sum(model.X[i,j,k,model.nb_f] for j in model.N if (i,j) in model.AMD) - sum(model.X[j,i,k,model.nb_f] for j in model.N if (i,j) in model.AMD)
        if i == model.t[k] :
            return value == model.Z[i,k,model.f[k,model.nb_f]]-1
        else :
            return value==model.Z[i,k,model.f[k,model.nb_f]]

    model.routing_last_subpath_const = Constraint(model.N_a,model.D,rule= routing_last_subpath)

    #Constraint 6 : forbid the two paths to both enter #range(1,model.nb_f+1)
    def simple_path1(model,i,k):
        #if not any(model.X[j,i,k,s] for j in model.N if (j,i) in model.AMD for s in model.S1):
         #   return Constraint.Skip
        value = sum(sum(model.X[j,i,k,s] for j in model.N if (j,i) in model.AMD) for s in model.S1)
        return value <= 1

    model.simple_path1_const = Constraint(model.N_a,model.D,rule= simple_path1)

    #Constraint 7 : forbid the two paths to both enter #range(1,model.nb_f+1)
    def simple_path2(model,i,k):
        #if not any(model.X[i,j,k,s] for j in model.N if (i,j) in model.AMD for s in model.S1):
        #    return Constraint.Skip
        value=sum(sum(model.X[i,j,k,s] for j in model.N if (i,j) in model.A) for s in model.S1)
        return value <= 1

    model.simple_path2_const = Constraint(model.N,model.D,rule= simple_path2)

    #Constraint 8 : given the number of installed VNF
    def NbVNF(model,f,l):
        value=sum(model.Y[i,f,l] for i in model.N)
        return value <= VNFix

    model.NbVNF_const=Constraint(model.F,model.L,rule = NbVNF)

    #Constraint 9 :  using arcs incident in a for routing a demand that is not served by the VNF on a
    def Paths2_a(model,k,f):
        value=sum(sum(model.X[i,model.a.value,k,s] for i in model.N if (i,model.a.value) in model.AMD) for s in model.S1)
        return value <= model.Z[model.a.value,k,f]

    model.Paths2a_const = Constraint(model.D,model.F,rule= Paths2_a)

    return model

def AFRHeurist(file,Limit):
    # chosing the solver
    optsolver =  create_solver()

    model=VNFHeurist1(1) #create model

    instance = model.create_instance(file+".dat")#create

    VNFix=instance.nb_n.value
    res1=0

    model=VNFHeurist1(VNFix) #create model

    instance = model.create_instance(file+".dat")#create
    print("la valeur du n", instance.nb_n.value)
    starttime=time.time()
    while (time.time()-starttime)<Limit :
        results = optsolver.solve(instance)# resolve problem
        res0=(getObjectiveValue(instance))/3 # objective
        print("le nombre de demande",instance.nb_d.value)
        print("Le temps limite",Limit)
        if res0 == instance.nb_d.value:
            results = optsolver.solve(instance) # resolve problem
            filename = open("resultat heureustique.txt",'w')
            printObjectiveValue(instance, filename)
            printPointFromModel(instance, filename)
            filename.close()
            a=0
            for i in instance.N_a:
                for f in instance.F:
                    for l in instance.L:
                        a=a+instance.Y[i,f,l].value
            #a = getObjectiveValue(instance)
            print("Le temps d'exécution ",time.time()-starttime)
            return print("le nombre de demande servi avec l'heuristique pour une fonction est ",a)

        if res1< res0 and res0<instance.nb_d.value:
            for i in instance.N:
                for k in instance.D:
                    for f in instance.F:
                        if instance.Z[i,k,f].value == 1:
                            print("instance.Z[i,k,f].value ")
                            instance.Z[i,k,f].fixe() #{ fix Z}

            res1 = res0

    return print("No feasible solution found")

def main():
    # file
    file = "nobel-eu_s_s_h_l"
    Limit= 1200
    AFRHeurist(file,Limit)

'''
def main():
    # chosing the solver
    optsolver =  create_solver()

    #Creating the model
    model = VNFHeurist1(1)

    #Load the data file (and create an instance)
    instance = model.create_instance('di-yuan_s_s_l_l.dat')
    #instance.pprint()
    #solving the problem
    results = optsolver.solve(instance)

    objective =  getObjectiveValue(instance)
    print("Optimal solution found with value ", objective)
    filename = open("di-yuan_s_s_l_l.txt",'w')
    printObjectiveValue(instance, filename)
    printPointFromModel(instance, filename)
    filename.close()
    #printPointFromModel(instance)
'''
if __name__ == '__main__':

    main()


import argparse
import datetime
import subprocess
import threading
import time
import os
from enum import Enum

import telebot

import libremu_backend as engine
import text_data as text
import keyboards

import config

base_error_message = 'There are some problem with request. Forward messages to @nikolay_klimov if you think this is a bag.'

bot = telebot.TeleBot(config.tg_token, num_threads=4)
fsm = {} # Finite State Machine
current_shown_dates={} # TODO: get rid off

class BotState(Enum):
    WAIT                = 0
    REP_DELETE_CHOOSE   = 1
    AT_CALENDAR         = 2
    AT_TIME             = 10
    AT_TIME_TEXT        = 3
    AFTER_INPUT         = 4
    GROUPE_CHOOSE       = 5
    GROUP_ADD_ITEM      = 6
    GROUP_DEL_ITEM      = 7
    GROUP_ADD           = 8
    GROUP_DEL           = 9

class FSMData:
    state = BotState.WAIT
    data = {}

    def reset(self):
        self.state = BotState.WAIT
        self.data = {}

@bot.message_handler(content_types=["text"])
def handle_text(message):
    input_text = message.text
    id = message.chat.id

    # Special case
    if input_text.find('/start') == 0:
        on_start_command(message)
        fsm[id] = FSMData()
        return

    engine.log_debug("Processing input text message: %s. Bot state = %s"%(input_text, str(fsm[id].state)))

    if fsm[id].state == BotState.WAIT:
        on_wait_status(message)

    elif fsm[id].state == BotState.REP_DELETE_CHOOSE:
        on_rep_delete_choose_status(message)

    elif fsm[id].state == BotState.AT_CALENDAR:
        on_at_calendar_status(message)

    elif fsm[id].state == BotState.AT_TIME_TEXT:
        on_at_time_text_status(message)

    elif fsm[id].state == BotState.AFTER_INPUT:
        on_after_input_status(message)

    elif fsm[id].state == BotState.GROUP_ADD_ITEM:
        on_group_add_item_status(message)

    elif fsm[id].state == BotState.GROUP_DEL_ITEM:
        on_group_del_item_status(message)

    elif fsm[id].state == BotState.GROUP_ADD:
        on_group_add_status(message)

    elif fsm[id].state == BotState.AT_TIME:
        on_at_time_status(message)

    else:
        engine.log_error("Unknown bot state: uid = " + str(id) + " state = " + str(fsm[id].state))
        fsm[id].reset()
        handle_text(message)

def on_wait_status(message):
    input_text = message.text
    id = message.chat.id

    if input_text.find('/help') == 0:
        on_help_command(message)

    elif input_text.find('/delete_rep') == 0:
        on_delete_rep_command(message)

    elif input_text.find('/at') == 0:
        on_at_command(message)

    elif input_text.find('/group') == 0:
        # on_group_command(message)
        pass

    elif input_text.find('/add_group') == 0:
        # on_add_group_command(message)
        pass

    elif input_text.find('/del_group') == 0:
        # on_del_group_command(message)
        pass

    elif input_text.find('/del_group_item') == 0:
        # on_del_group_item_command(message)
        pass

    elif input_text.find('/list') == 0:
        on_list_command(message)

    else:
        (text, error) = engine.handle_text_message(message.chat.id, input_text)
        if error == 0:
            bot.send_message(message.chat.id, text)
        else:
            keyboard = keyboards.action()
            bot.send_message(id, input_text, reply_markup=keyboard)

def on_rep_delete_choose_status(message):
    delete_rep_event(message)

def on_at_calendar_status(message):
    id = message.chat.id
    message_id = fsm[id].data['message_id']
    bot.delete_message(chat_id=id, message_id=message_id)
    fsm[id].reset()
    handle_text(message)

def on_at_time_status(message):
    # id = message.chat.id
    # keyboard = keyboards.time()
    # bot.send_message(id, )
    pass

def on_at_time_text_status(message):
    id = message.chat.id
    input_text = message.text
    if fsm[id].data['text']:
        input_text += ' ' + fsm[id].data['text']
    command = fsm[id].data['date_spec'] + ' at ' + input_text
    bot.send_message(id, 'Resulting command:\n' + command)
    (text, err) = engine.handle_text_message(id, command)
    if err:
        bot.send_message(id, 'Wrong resulting command. Try again')
    else:
        bot.send_message(id, text)
    fsm[id].reset()

def on_after_input_status(message):
    id = message.chat.id
    command = message.text + ' ' + fsm[id].data['text']
    bot.send_message(id, 'Resulting command:\n' + command)
    (text, _) = engine.handle_text_message(id, command)
    bot.send_message(id, text)
    fsm[id].reset()

def on_group_add_item_status(message):
    # should be cathced in keyboard handle
    pass

def on_group_del_item_status(message):
    id = message.chat.id
    event_id_str = message.text
    if not event_id_str.isdigit():
        msg = bot.reply_to(message, 'You should write number')
        return

    event_id = int(event_id_str)-1
    id_list = fsm[id].data['id_list']
    if id_list and event_id >= 0 and event_id < len(id_list):
        del_id = id_list[event_id]
        if engine.delete_group_item(del_id):
            bot.send_message(id, "Done.")
        else:
            bot.send_message(id, base_error_message)
        fsm[id].reset()
    else:
        fsm[id].reset()
        bot.send_message(id, "Number is out of limit. Operation abort.")
    pass

def on_group_add_status(message):
    id = message.chat.id
    group_name = message.text
    if engine.add_user_group(id, group_name):
        bot.send_message(id, 'Done.')
    else:
        bot.send_message(id, base_error_message)
    fsm[id].reset()

# ------------------- command handlers

def on_start_command(message):
    username = ''
    first_name = ''
    last_name = ''
    if message.from_user.username: username = message.from_user.username
    if message.from_user.first_name: first_name = message.from_user.first_name
    if message.from_user.last_name: last_name = message.from_user.last_name
    engine.add_user(message.from_user.id,
                    username,
                    message.chat.id,
                    first_name,
                    last_name,
                    -3)
    bot.send_message(message.chat.id, 'Hello! ^_^\nType /help')

def on_help_command(message):
    if message.text == '/help more':
        bot.send_message(message.chat.id, text.detailed_help_message_ru, parse_mode='Markdown')
    else:
        bot.send_message(message.chat.id, text.main_help_message_ru, parse_mode='Markdown')

def on_delete_rep_command(message):
    global fsm
    uid = message.chat.id
    fsm[uid].state = BotState.WAIT
    rep_event_list = engine.get_rep_events(uid)

    if not rep_event_list:
        bot.send_message(message.chat.id, 'No current rep event')
        return

    [text_list, rep_id_list] = list(zip(*rep_event_list))
    fsm[uid].state = BotState.REP_DELETE_CHOOSE
    fsm[uid].data['rep_id_list'] = rep_id_list

    header = "Here is yout rep events list. Choose witch to delete:\n"
    list_str = '\n'.join([ str(i+1) + ") " + key for i, key in enumerate(text_list)])
    bot.send_message(uid, header + list_str)

def on_at_command(message):
    handle_calendar_call(message.chat.id)

def on_group_command(message):
    choose_group_message(message.from_user.id)

def on_add_group_command(message):
    uid = message.chat.id
    offset = len('/add_group ')
    if offset >= len(message.text):
        bot.send_message(uid, 'You should write group name')
    group_name = message.text[offset:]
    if group_name == '':
        fsm[uid].state = BotState.GROUP_ADD
        bot.send_message(uid, 'Ok, write new group name')
    else:
        if engine.add_user_group(uid, group_name):
            bot.send_message(uid, 'Done.')
        else:
            bot.send_message(uid, base_error_message)

def on_del_group_command(message):
    choose_group_message(message.chat.id, next_state=BotState.GROUP_DEL)

def on_list_command(message):
    text_list = engine.get_active_events(message.from_user.id)
    if not text_list:
        bot.send_message(message.chat.id, 'No current active event')
    else:
        list_str = '\n'.join([ str(i+1) + ") " + key for i, key in enumerate(text_list)])
        bot.send_message(message.chat.id, list_str, parse_mode='Markdown')

def on_del_group_item_command(message):
    choose_group_message(message.chat.id, next_state=BotState.GROUP_DEL_ITEM)

# --------------- Keyboard callback handlers

@bot.callback_query_handler(func=lambda call: call.data == 'next-month' or call.data == 'previous-month')
def change_month(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    next_month = call.data == 'next-month'
    chat_id = call.message.chat.id
    saved_date = current_shown_dates.get(chat_id)
    if saved_date is None:
        engine.log_error("Called calendar change_month handler, but there no saved_date by " + str(chat_id) + " chat_id")
        return

    year, month = saved_date
    if next_month:
        month += 1
        if month > 12:
            month, year = (1, year+1)
    else:
        month -= 1
        if month < 1:
            month, year = (12, year-1)

    now = datetime.datetime.now()
    cur_day = now.day if now.month == month and now.year == year else None
    current_shown_dates[chat_id] = (year, month)
    markup = keyboards.calendar(year, month, cur_day)
    bot.edit_message_text("Please, choose a date", call.from_user.id, call.message.message_id, reply_markup=markup)
    bot.answer_callback_query(call.id, text="")

@bot.callback_query_handler(func=lambda call: call.data[0:13] == 'calendar-day-')
def get_day(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    chat_id = call.message.chat.id
    saved_date = current_shown_dates.get(chat_id)
    if(saved_date is None):
        engine.log_error("Called calendar get_day handler, but there no saved_date by " + str(chat_id) + " chat_id")
        return

    day = call.data[13:]
    date = datetime.datetime(int(saved_date[0]), int(saved_date[1]), int(day), 0, 0, 0)
    fsm[chat_id].state = BotState.AT_TIME_TEXT
    fsm[chat_id].data['date_spec'] = day + '-' + str(saved_date[1]) + '-' + str(saved_date[0])
    # delete keyboard
    bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.message.text)
    if fsm[chat_id].data['text']:
        bot.send_message(chat_id, 'Ok, ' + date.strftime(r'%b %d') + '. Now write the time of event.')
    else:
        bot.send_message(chat_id, 'Ok, ' + date.strftime(r'%b %d') + '. Now write the time and text of event.')
    bot.answer_callback_query(call.id, text="")
    handle_hour_keyboard(chat_id)

@bot.callback_query_handler(func=lambda call: call.data == 'today' or call.data == 'tomorrow')
def on_calendar_today(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    chat_id = call.message.chat.id

    date = datetime.datetime.now()
    if call.data == 'tomorrow':
        date += datetime.timedelta(days=1)
    # date = datetime.datetime(int(saved_date[0]), int(saved_date[1]), int(day), 0, 0, 0)
    fsm[chat_id].state = BotState.AT_TIME_TEXT
    fsm[chat_id].data['date_spec'] = str(date.day) + '-' + str(date.month) + '-' + str(date.year)
    # delete keyboard
    bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.message.text)
    if fsm[chat_id].data['text']:
        bot.send_message(chat_id, 'Ok, ' + date.strftime(r'%b %d') + '. Now write the time of event.')
    else:
        bot.send_message(chat_id, 'Ok, ' + date.strftime(r'%b %d') + '. Now write the time and text of event.')
    bot.answer_callback_query(call.id, text="")
    handle_hour_keyboard(chat_id)

@bot.callback_query_handler(func=lambda call: call.data[:10] == 'time_hour:')
def on_time_hour(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    chat_id = call.message.chat.id
    hour = int(call.data[10:])
    fsm[chat_id].data['hour'] = hour
    handle_minutes_keyboard(chat_id)

@bot.callback_query_handler(func=lambda call: call.data[:12] == 'time_minute:')
def on_time_minutes(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    chat_id = call.message.chat.id
    minute = int(call.data[12:])
    message_id = fsm[chat_id].data['message_id']
    bot.delete_message(chat_id, message_id)

    hour = fsm[chat_id].data['hour']
    text = fsm[chat_id].data['text']
    date_spec = fsm[chat_id].data['date_spec']
    if hour is not None and minute is not None:
        result_command = date_spec + ' at ' + str(hour) + '.' + str(minute) + ' ' + text
        (reply, err) = engine.handle_text_message(chat_id, result_command)
        if err:
            bot.send_message(chat_id, base_error_message)
        else:
            bot.send_message(chat_id, reply)
    fsm[chat_id].reset()

@bot.callback_query_handler(func=lambda call: call.data[0:3] == 'grp')
def on_select_group(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    uid = call.message.chat.id
    gid = int(call.data[3:])
    engine.log_debug("Processing keyboard callback. Call.data = %s. Bot state = %s"%(call.data, str(fsm[uid].state)))
    if fsm[uid].state == BotState.GROUP_ADD_ITEM:
        text = fsm[uid].data['text']
        if engine.add_group_item(gid, text):
            bot.send_message(uid, 'Done')
        else:
            bot.send_message(uid, base_error_message)
    elif fsm[uid].state == BotState.GROUP_DEL:
        if engine.delete_user_group(gid):
            bot.send_message(uid, 'Done')
        else:
            bot.send_message(uid, base_error_message)
    else:
        items = engine.get_group_items(gid)
        if items:
            [text_list, id_list] = list(zip(*items)) # TODO: add group name
            text = '\n'.join([ str(i+1) + ') ' + item for i, item in enumerate(text_list) ])
            fsm[uid].data['id_list'] = id_list
            bot.send_message(uid, text)
        else:
            bot.send_message(uid, 'No items in group')

    bot.delete_message(uid, fsm[uid].data['message_id'])
    if fsm[uid].state == BotState.GROUP_DEL_ITEM:
        bot.send_message(uid, 'Choose element to delete')
    else:
        fsm[uid].reset()

@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
    engine.log_debug("Processing button callback: %s"%(call.data))
    id = call.message.chat.id
    engine.log_debug("Processing keyboard callback. Call.data = %s. Bot state = %s"%(call.data, str(fsm[id].state)))
    if call.message:
        if call.data == 'at':
            handle_calendar_call(id, call.message.text)
        elif call.data == 'after':
            fsm[id].state = BotState.AFTER_INPUT
            fsm[id].data['text'] = call.message.text
            bot.send_message(id, 'Ok, now write time duration.')
        elif call.data == 'group':
            fsm[id].state = BotState.GROUP_ADD_ITEM
            fsm[id].data['text'] = call.message.text
            choose_group_message(id, next_state=BotState.GROUP_ADD_ITEM, add_if_not_exist=False)
        elif call.data == 'Ok':
            bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id)
            return
        elif call.data == 'ignore':
            fsm[id].reset()
        elif call.data != "Ok":
            call.message.text = call.data + " " + call.message.text
            handle_text(call.message)
        bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)

# ------------- helper function

def delete_rep_event(message):
    event_id_str = message.text
    if not event_id_str.isdigit():
        msg = bot.reply_to(message, 'You should write number. Operation aborted.')
        fsm[message.chat.id].reset()
        return

    event_id = int(event_id_str)-1
    id_list = fsm[message.chat.id].data['rep_id_list']
    if id_list and event_id >= 0 and event_id < len(id_list):
        del_id = id_list[event_id]
        if engine.del_rep_event(del_id):
            bot.send_message(message.chat.id, "Done.")
        else:
            bot.send_message(uid, base_error_message)
        fsm[message.chat.id].reset()
    else:
        bot.send_message(message.chat.id, "Number is out of limit. Operation aborted.")
        fsm[message.chat.id].reset()

def handle_calendar_call(chat_id, text=None):
    now = datetime.datetime.now()
    date = (now.year,now.month)
    current_shown_dates[chat_id] = date

    markup = keyboards.calendar(now.year, now.month, now.day)
    fsm[chat_id].state = BotState.AT_CALENDAR
    fsm[chat_id].data['text'] = text
    keyboard_message = bot.send_message(chat_id, "Please, choose a date", reply_markup=markup)
    fsm[chat_id].data['message_id'] = keyboard_message.message_id

def handle_hour_keyboard(chat_id):
    if fsm[chat_id].data['message_id']:
        message_id = fsm[chat_id].data['message_id']
        bot.delete_message(chat_id, message_id)

    markup = keyboards.hour()
    fsm[chat_id].state = BotState.AT_TIME
    keyboard_message = bot.send_message(chat_id, "Please, choose hour", reply_markup=markup)
    fsm[chat_id].data['message_id'] = keyboard_message.message_id

def handle_minutes_keyboard(chat_id):
    if fsm[chat_id].data['message_id']:
        message_id = fsm[chat_id].data['message_id']
        bot.delete_message(chat_id, message_id)

    markup = keyboards.minutes()
    fsm[chat_id].state = BotState.AT_TIME
    hour = fsm[chat_id].data['hour']
    text = 'Ok, %d. Now choose minute.'%hour
    keyboard_message = bot.send_message(chat_id, text, reply_markup=markup)
    fsm[chat_id].data['message_id'] = keyboard_message.message_id

def choose_group_message(id, next_state=None, add_if_not_exist=False):
    groups = engine.get_user_groups(id)
    if not groups:
        if add_if_not_exist:
            fsm[id].state = BotState.GROUP_ADD
            bot.send_message(id, 'There is not group yet. Write name for your new group')
        else:
            bot.send_message(id, 'No groups.')
        return
    [text_list, id_list] = list(zip(*groups))
    if next_state:
        fsm[id].state = next_state
    keyboard = keyboards.groups(text_list, id_list)
    keyboard_message = bot.send_message(id, 'Choose group.', reply_markup=keyboard)
    fsm[id].data['message_id'] = keyboard_message.message_id

@bot.message_handler(content_types=['voice'])
def voice_processing(message):
    engine.log_debug('Start to processing voice. File id = ' + message.voice.file_id)
    file_info = bot.get_file(message.voice.file_id)
    file = bot.download_file(file_info.file_path)
    if not os.path.exists('voice'):
        os.makedirs('voice')
    filename_ogg = message.voice.file_id + '.ogg'
    filename_wav = message.voice.file_id + '.wav'
    with open('voice/' + filename_ogg, 'wb') as f:
        f.write(file)

    command = [
        'opusdec',
        '--rate', '16000',
        '--force-wav',
        '--quiet',
        'voice/' + filename_ogg,
        'voice/' + filename_wav
    ]
    proc = subprocess.Popen(command,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    err = proc.stderr.read()
    if err: engine.log_error(err)

    command = [
        'asrclient-cli.py',
        '--key=' + config.yandex_api_token,
        '--silent',
        'voice/' + filename_wav
    ]
    proc = subprocess.Popen(' '.join(command), shell=True,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    result = []
    for line in proc.stdout:
        result.append(line)

    err = proc.stderr.read()
    if err: engine.log_error(err)

    engine.log_info('Speech rec result: ' + str(result))

    if len(result) <= 1:
        bot.send_message(message.chat.id, "Can't recognize =(")
    else:
        keyboard = keyboards.action()
        bot.send_message(message.chat.id, result[:-1], reply_markup=keyboard)

def on_engine_event(text, chat_id):
    keyboard = keyboards.action()
    bot.send_message(chat_id, text, reply_markup=keyboard)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-v",
                        "--verbose",
                        help="show log lines in stdout",
                        action="store_true")
    parser.add_argument("--one-poll",
                        help="do not try to polling againg after error",
                        action="store_true")
    args = parser.parse_args()
    verbose = True if args.verbose else False
    one_poll = True if args.one_poll else False

    engine.initialize(verbose)
    engine.register_callback(on_engine_event)
    user_chat_id_list = engine.get_user_chat_id_all()
    for chat_id in user_chat_id_list:
        fsm[chat_id] = FSMData()

    engine.run()

    while True:
        try:
            bot.polling()
        except:
            engine.log_error("I am down =(")
            for key in fsm:
                fsm[key].reset()

        if one_poll:
            break
        time.sleep(10)

    engine.stop()


from email_sender import *
from database.dbservice import create_connection, insert_item, post_exist
from database.models.course_info import Course_info
from database.models.user_info import User_Info
from fgraph import *
from dotenv import load_dotenv
import json
import time

load_dotenv()

def send_to_course_users(user_info, course_name, post):

    users_info = User_Info.objects()
    for course in users_info:
        if course_name == course_name:
            emails = course[course_name]
            for email in emails:
                send_email(receiver_email=email,
                           subject=course_name, message=main_post)
        else:
            break
        break

def make_mail_body():
    pass

if __name__ == "__main__":

    # creating sent_post table
    create_connection()

    # fetching data of users
    users = json.loads(User_Info.objects()[0].to_json())

    while True:
        # do something
        feeds = get_feed()
        for posts in feeds['feed']['data']:
            if post_exist(posts['id']) == False:
                post = get_post(posts['id'])
                for course in users['info']:
                    print(post)
                    if post['message'].find(course['course_name']) != -1:
                        main_post = post['message']
                        main_post += '\n'
                        if len(post) == 3:
                            attachment = 'Attched pictures\n'
                            attachment += posts['full_picture']
                        main_post += attachment
                        main_post += '\n'
                        main_post += ('Post link '+posts['permalink_url'])
                        print(main_post)
                        insert_item(
                            course_no=course['course_name'], post_id=posts['id'], post=main_post)
                        send_to_course_users(
                            user_info=users, course_name=course['course_name'], post=main_post)
            else:
                break
        break
        time.sleep(1800)


# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:

class Solution:
    def firstBadVersion(self, n: int) -> int:
        first = 1
        last = n
        while (first < last):
            mid = (last+first)//2
            if isBadVersion(mid):
                last = mid
            else:
                first =mid + 1
        return first


from __future__ import division

def pageRankCentrality(graph, confidence, damping=1.0e-5):
	tmp = {}
	pageRank = {}
	# for every node contains the set of nodes that links to it
	incomings = {}

	done = False

	nodes = graph.keys()

	size = len(graph)
	for i in nodes:
		pageRank[i] = 1/size
		incomings[i] = set()

	for i in nodes:
		for j in graph[i]:
			incomings[j].add(i)

	#it = 1
	while not done:
		maxPageRank = 0.0
		for i in nodes:
			tmp[i] = pageRank[i]
			tmp[i] = (1-damping) * sum( [ pageRank[j]/len(graph[j]) + (damping/size) for j in incomings[i] ])
			if tmp[i] > maxPageRank:
				maxPageRank = tmp[i]

		#it += 1
		diff = 0
		for i in nodes:
			diff += abs(pageRank[i]-float(tmp[i])/maxPageRank) # Distance between old and new centrality vector
			pageRank[i] = tmp[i]/maxPageRank

		if diff < confidence:
			done = True

	return pageRank


import random
import time

def strTimeProp(start, end, format, prop):
    stime = time.mktime(time.strptime(start, format))
    etime = time.mktime(time.strptime(end, format))
    ptime = stime + prop * (etime - stime)
    return time.strftime(format, time.localtime(ptime))

def randomDate(start, end, prop):
    return strTimeProp(start, end, '%d-%m-%Y', prop)

random.seed(a=322)

with open('client_status.sql', 'w') as output:
    output.write('SET SEARCH_PATH = crypto_exchange;\n\n')
    output.write('INSERT INTO client_status (client_id, verified_flg, frozen_flg, status_code, valid_from, valid_to)\nVALUES\n')
    for i in range(1, 51):
        query = '''  ({}, {}, {}, {}, '{}', '{}'),\n'''.format(i, 'TRUE', 'FALSE', random.randint(1, 4), randomDate('1-4-2019', '31-5-2019', random.random()), '01-01-9999')
        output.write(query)
    output.write('''  ({}, {}, {}, {}, '{}', '{}'),\n'''.format(5, 'TRUE', 'FALSE', random.randint(1, 4), randomDate('1-6-2019', '5-6-2019', random.random()), '01-01-9999'))
    output.write('''  ({}, {}, {}, {}, '{}', '{}'),\n'''.format(11, 'TRUE', 'FALSE', random.randint(1, 4), randomDate('1-6-2019', '5-6-2019', random.random()), '01-01-9999'))