# GLaDOS

# Audio/Speech Imports
import speech_recognition as sr
import sys
import re
import smtplib
#import vlc
from time import strftime
import getpass
import random
import pyttsx3
import engineio
import subprocess
import pyfiglet

# Abilities Imports
from abilities import website, reddit, weather, \
    joke, news, application, knowledge

# engineio
engineio = pyttsx3.init()
engineio.setProperty('rate',100)
voices = engineio.getProperty('voices')
engineio.setProperty('voice', 'english+f4')

# Get username of device
username = getpass.getuser()

# convert text to speech
def GLaDOS(audio):
    """speaks audio passed as argument"""
    print(audio)
    for line in audio.splitlines():
        engineio.say(audio)
        engineio.runAndWait()

ascii_banner = pyfiglet.figlet_format("GLaDOS")
print(ascii_banner)

# Commands
def myCommand():
    """listens for commands"""
    r = sr.Recognizer()
    # keyword = "hello"       ##keyword to wake from sleeping mode
    with sr.Microphone() as source:
        #subprocess.call('clear', shell=True)    #clear
        print('Say something...')
        r.pause_threshold = 1
        r.adjust_for_ambient_noise(source, duration=1)
        audio = r.listen(source)
    try:
        # if r.recognize_google(audio) == keyword:
        command = r.recognize_google(audio).lower()
        print('You said: ' + command + '\n')

    # loop back to continue to listen for commands if unrecognizable speech is received
    except sr.UnknownValueError:
        print('....')
        command = myCommand()
    return command

# Assistant
def assistant(command):
    """if statements for executing commands"""

    # SMALLTALK
    if 'hello' in command:
        day_time = int(strftime('%H'))
        if day_time < 12:
            GLaDOS('Hello ' + username + '. Good morning')
        elif 12 <= day_time < 18:
            GLaDOS('Hello ' + username + '. Good afternoon')
        else:
            GLaDOS('Hello ' + username + '. Good evening')

    elif 'how are you' in command:
        rnd = random.randint(0, 4)
        if rnd == 0:
            GLaDOS('I am very good. Thanks for asking!')
        elif rnd == 1:
            GLaDOS('I am good. And you?')
        elif rnd == 2:
            GLaDOS('You are here. Now I feel fantastic.')
        elif rnd == 3:
            GLaDOS('You want to get something done or chit chat mate!')
        else:
            GLaDOS('Are you trying to get my attention? I am very busy, you know.')

    # SHUTDOWN
    elif 'shut down' in command:
        GLaDOS('Bye bye ' + username + '. Have a nice day!')
        sys.exit()

    # WEBSITE
    elif 'open' in command:
        GLaDOS(website.openWebsite(re.search('open (.+)', command)) + username)

    # REDDIT
    elif 'open reddit' in command:
        GLaDOS(reddit.openSubreddit(re.search('open reddit (.*)', command)) + username)

    # JOKE
    elif 'joke' in command:
        GLaDOS(joke.badJoke())

    # NEWS
    elif 'news for today' in command:
        GLaDOS(news.getNews())

    # WEATHER
    elif 'current weather' in command:
        GLaDOS(weather.currentWeather(re.search('current weather in (.*)', command)))

    # TIME
    elif 'time' in command:
        import datetime
        now = datetime.datetime.now()
        GLaDOS('Current time is %d hours %d minutes' % (now.hour, now.minute))

    # APPLICATION
    elif 'launch' in command:
        GLaDOS(application.launchApp(re.search('launch (.*)', command)) + username)

    # E-MAIL
    elif 'email' in command:
        GLaDOS('Who is the recipient?')
        recipient = myCommand()
        if 'rajat' in recipient:
            GLaDOS('What should I say to him?')
            content = myCommand()
            mail = smtplib.SMTP('smtp.gmail.com', 587)
            mail.ehlo()
            mail.starttls()
            mail.login('your_email_address', 'your_password')
            mail.sendmail('sender_email', 'receiver_email', content)
            mail.close()
            GLaDOS('Email has been sent successfuly. You can check your inbox.')
        else:
            GLaDOS('I don\'t know what you mean!')

    # KNOWLEDGE
    elif 'tell me about' in command:
        GLaDOS(knowledge.citeWikipedia(re.search('tell me about (.*)', command)) + username)

# loop to continue executing multiple commands
while True:
    assistant(myCommand())


# models to use:
# dt
# nn
# boosting
# svm
# knn
# %%
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn as sk

from sklearn import metrics
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import learning_curve
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.model_selection import validation_curve
from sklearn.metrics import accuracy_score
from sklearn.linear_model import Ridge
from common import check_cv_score, grid_search, plot_lc
from common import plot_vc
from common import dtree_params
from common import dtree_extended_params
from common import knn_params
from common import check_cv_score
from common import check_test_score
from common import dtree_sample_split
from common import svm_params
from common import nn_params
from common import nn_learning_params

# basic structure from:
# https://www.kaggle.com/jchen2186/machine-learning-with-iris-dataset
# %%
pd.set_option('display.max_rows', 100)
p = np.linspace(0,20,100)

# %%
plt.plot(p,np.sin(p))
plt.show()
# %%
data = pd.read_csv('data/iris.data')
# %%
# !!! EDA !!!
data.head()
# %%
data.info()
# %%
data.describe()
# %%
data['class'].value_counts()
# %%
# pairplot = sns.pairplot(data, hue='class', markers='*')
# %%
# sepal_len = sns.violinplot(y='class', x='sepal_len', data=data, inner='quartile')
# %%
# sepal_width = sns.violinplot(y='class', x='sepal_width', data=data, inner='quartile')
# %%
# petal_len = sns.violinplot(y='class', x='petal_len', data=data, inner='quartile')
# %%
# petal_width = sns.violinplot(y='class', x='petal_width', data=data, inner='quartile')
# %%
sk.show_versions()
# %%
x = data.drop('class', axis=1)
y = data['class']
# %%
print(x.shape)
print(y.shape)
test = LogisticRegression()
# %%
test_ks = list(range(1,27))
scores = []
print('k | score')
for k in test_ks:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(x,y)
    y_pred = knn.predict(x)
    score = metrics.accuracy_score(y, y_pred)
    scores.append(score)
    print('%s | %s' % (k,score))

# plt.plot(test_ks, scores)
# plt.xlabel('k')
# plt.ylabel('score')
# plt.title('k-Nearest-Neighbors')
# plt.show()
# %%
def get_score(model, x, y):
    model.fit(x, y)
    y_pred = knn.predict(x)
    return metrics.accuracy_score(y, y_pred)
# %%
logreg = LogisticRegression()
logreg.fit(x, y)
y_pred = logreg.predict(x)
print(metrics.accuracy_score(y, y_pred))
# %%
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4, random_state=5)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
print(y_test.value_counts())
# %%
test_ks = list(range(1,27))
scores = []
print('k | score')
for k in test_ks:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(x_train,y_train)
    y_pred = knn.predict(x_test)
    score = metrics.accuracy_score(y_test, y_pred)
    scores.append(score)
    print('%s | %s' % (k,score))
# %%
logreg = LogisticRegression()
logreg.fit(x_train, y_train)
y_pred = logreg.predict(x_test)
print(metrics.accuracy_score(y_test, y_pred))
# %%
dtree = DecisionTreeClassifier()
dtree.fit(x_train,y_train)
y_pred = knn.predict(x_test)
score = metrics.accuracy_score(y_test, y_pred)
print(score)
# %%
clf = GridSearchCV(dtree, {
    'criterion': ['gini', 'entropy'],
    'splitter': ['best', 'random']
}, cv=5)
clf.fit(x_train, y_train)
reuslt_df = pd.DataFrame(clf.cv_results_)
reuslt_df[['params','mean_test_score']]
# %%
def grid_search_map(map, x, y):
    total_df = pd.DataFrame(columns=['model','params','mean_test_score'])
    for model in map:
        clf = GridSearchCV(model['model'],
                           model['params'], cv=5)
        clf.fit(x, y)
        result_df = pd.DataFrame(clf.cv_results_)
        result_df = result_df[['params','mean_test_score']]
        result_df['model'] = model['model']
        total_df = pd.concat([total_df,result_df])

    return total_df.sort_values('mean_test_score',axis=0,ascending=False)
# %%
def grid_search(model, params, x, y):
    clf = GridSearchCV(model, params, cv=5)
    clf.fit(x, y)
    result_df = pd.DataFrame(clf.cv_results_)
    result_df = result_df[['params','mean_test_score']]
    result_df['model'] = model['model']
    return result_df.sort_values('mean_test_score',axis=0,ascending=False)
# %%
testTree = DecisionTreeClassifier()
testknn = KNeighborsClassifier()
model_map = [
    {   'model': testTree, 'params': {
            'criterion': ['gini', 'entropy'],
            'splitter' : ['best', 'random']
        }
    },
    {   'model': testknn, 'params': {
            'n_neighbors': [i for i in range(1,7)],
            'weights' : ['uniform', 'distance']
        }
    }
]
# %%
# grid_search_map(model_map, x_train, y_train)
# %%

# def plot_lc(model, title, x, y, cv, train_sizes=np.linspace(.1, 1.0, 5), ylim=None):
#     fig, lc_plot = plt.subplots()
#     lc_plot.set_title(title)
#     lc_plot.set_ylim(*ylim) if ylim is not None else None
#     lc_plot.set_xlabel("Training examples")
#     lc_plot.set_ylabel("Score")

#     train_sizes, train_scores, test_scores, fit_times, _ = \
#         learning_curve(model, x, y, cv=cv, n_jobs=4,
#                        train_sizes=train_sizes,
#                        return_times=True)
#     train_scores_mean = np.mean(train_scores, axis=1)
#     train_scores_std = np.std(train_scores, axis=1)
#     test_scores_mean = np.mean(test_scores, axis=1)
#     test_scores_std = np.std(test_scores, axis=1)
#     fit_times_mean = np.mean(fit_times, axis=1)
#     fit_times_std = np.std(fit_times, axis=1)
#     print(cross_val_score(model, x, y, scoring='accuracy', cv=cv))

#     # Plot learning curve
#     lc_plot.grid()
#     lc_plot.fill_between(train_sizes, train_scores_mean - train_scores_std,
#                          train_scores_mean + train_scores_std, alpha=0.1,
#                          color="r")
#     lc_plot.fill_between(train_sizes, test_scores_mean - test_scores_std,
#                          test_scores_mean + test_scores_std, alpha=0.1,
#                          color="g")
#     lc_plot.plot(train_sizes, train_scores_mean, 'o-', color="r",
#                  label="Training score")
#     lc_plot.plot(train_sizes, test_scores_mean, 'o-', color="g",
#                  label="Cross-validation score")
#     lc_plot.legend(loc="best")
#     lc_plot

# %%
# def plot_vc(model, x, y, param_key, param_val, cv=5):
#     train_score, test_score = validation_curve(model, x, y, param_key, param_val, cv=cv, scoring="accuracy")
#     # Calculating mean and standard deviation of training score
#     mean_train_score = np.mean(train_score, axis = 1)
#     std_train_score = np.std(train_score, axis = 1)

#     # Calculating mean and standard deviation of testing score
#     mean_test_score = np.mean(test_score, axis = 1)
#     std_test_score = np.std(test_score, axis = 1)

#     # Plot mean accuracy scores for training and testing scores
#     plt.plot(param_val, mean_train_score,
#         label = "Training Score", color = 'b')
#     plt.plot(param_val, mean_test_score,
#     label = "Cross Validation Score", color = 'g')

#     # Creating the plot
#     plt.title("Validation Curve with ")
#     plt.xlabel(param_key)
#     plt.ylabel("Accuracy")
#     plt.tight_layout()
#     plt.legend(loc = 'best')
#     plt.show()

# %%
lc_knn = KNeighborsClassifier(n_neighbors=13,weights='distance')
plot_lc(lc_knn, x_train, y_train, cv=10, ylim=(0.7,1.01))
# %%
plot_lc(testTree, x_train, y_train, cv=10, ylim=(0.7,1.01))

# %%
# def params_dict_to_pairs(params):
#     params_list = []
#     for param in params_obj:
#         pair = (param, params_obj[param])
#         params_list.append(pair)
#     return params_list

# %% [markdown]
# test case 1 - knn weight: UNIFORM
# the chart shows 3 & 4 are best score w/o overfitting
weights = ['uniform', 'distance']
model = KNeighborsClassifier(n_neighbors=3)
plot_vc(model, x_train, y_train, 'weights', weights)
# %% [markdown]
# # test case 2 - knn neighbors: 3
# the chart shows uniform is better it's not overfitting
n_neighbors = [i for i in range(1,42)]
model = KNeighborsClassifier()
plot_vc(model, x_train, y_train, 'n_neighbors', n_neighbors)
# %%
knn_model = KNeighborsClassifier(n_neighbors=3)
plot_lc(model, x_train, y_train, cv=10, ylim=(0.7,1.01))
print('knn | %s' % (get_score(knn, x_train, y_train)))
# %%
svn_model =  SVC()
svn_map = [
    {   'model': svn_model, 'params': {
            'C': [i for i in np.linspace(0,1,50)],
            'kernel' : ['linear', 'poly', 'rbf', 'sigmoid']
        }
    }
]
# print(grid_search_map(svn_map, x_train, y_train).to_string())
# %%
svn_linear_model =  SVC(kernel='linear')
# %%
C = [i for i in np.linspace(0.02,1,200)]
plot_vc(svn_model, x_train, y_train, 'C', C)
# %%
plot_lc(svn_linear_model, x_train, y_train, cv=10, ylim=(0.8,1.08))
# %%
svn_poly_model =  SVC(kernel='poly')
# %%
C = [i for i in np.linspace(0.02,1,200)]
plot_vc(svn_model, x_train, y_train, 'C', C)
# %% this model looks GREAT
plot_lc(svn_poly_model, x_train, y_train, cv=10, ylim=(0.8,1.08))

# %% this model sucks
svn_model =  SVC(C=0.8,kernel='poly')
plot_lc(svn_model, x_train, y_train, cv=10, ylim=(0.8,1.01))
# %% quite an improvement here
C = [i for i in range(1,42)]
plot_vc(svn_poly_model, x_train, y_train, 'degree', C)
# %% final SVN model
svn_final =  SVC(kernel='poly', degree=4)
plot_lc(svn_final, x_train, y_train, cv=10, ylim=(0.8,1.08))

# %%


from typing import List

import torch
from espnet_pytorch_library.conformer.encoder import Encoder
from espnet_pytorch_library.nets_utils import make_non_pad_mask
from espnet_pytorch_library.tacotron2.decoder import Postnet
from espnet_pytorch_library.transformer.decoder import Decoder
from torch import Tensor, nn
from torch.nn.utils.rnn import pad_sequence

from accent_estimator.config import NetworkConfig
from accent_estimator.network.index_positional_encoder import IndexPositionalEncoder

class Predictor(nn.Module):
    def __init__(
        self,
        phoneme_size: int,
        phoneme_embedding_size: int,
        hidden_size: int,
        encoder_block_num: int,
        attention_heads: int,
        decoder_block_num: int,
        post_layer_num: int,
    ):
        super().__init__()

        # encoder (frame level)
        self.encoder_phoneme_embedder = nn.Embedding(
            num_embeddings=phoneme_size + 1,  # with empty
            embedding_dim=phoneme_embedding_size,
        )

        self.pre_encoder = nn.Sequential(
            nn.Linear(1 + phoneme_embedding_size, hidden_size),
            nn.LayerNorm(hidden_size),
            nn.Dropout(0.1),
        )
        self.mora_positional_encoder = IndexPositionalEncoder(
            d_model=hidden_size,
            dropout_rate=0.1,
        )

        self.encoder = Encoder(
            idim=1 + phoneme_embedding_size,
            attention_dim=hidden_size,
            attention_heads=attention_heads,
            linear_units=hidden_size * 4,
            num_blocks=encoder_block_num,
            input_layer=None,
            dropout_rate=0.1,
            positional_dropout_rate=0.1,
            attention_dropout_rate=0.1,
            normalize_before=True,
            positionwise_layer_type="conv1d",
            positionwise_conv_kernel_size=3,
            macaron_style=True,
            pos_enc_layer_type="rel_pos",
            selfattention_layer_type="rel_selfattn",
            activation_type="swish",
            use_cnn_module=True,
            cnn_module_kernel=31,
        )

        # decoder (mora level)
        self.decoder_phoneme_embedder = nn.Embedding(
            num_embeddings=phoneme_size + 1,  # with empty
            embedding_dim=phoneme_embedding_size,
            padding_idx=0,
        )

        self.decoder = Decoder(
            odim=1 + phoneme_embedding_size,
            attention_dim=hidden_size,
            attention_heads=attention_heads,
            linear_units=hidden_size * 4,
            num_blocks=decoder_block_num,
            dropout_rate=0.1,
            positional_dropout_rate=0.1,
            self_attention_dropout_rate=0.1,
            src_attention_dropout_rate=0.1,
            input_layer="linear",
            use_output_layer=False,
        )

        self.post = torch.nn.Linear(hidden_size, 4)

        if post_layer_num > 0:
            self.postnet = Postnet(
                idim=4,
                odim=4,
                n_layers=post_layer_num,
                n_chans=hidden_size,
                n_filts=5,
                use_batch_norm=True,
                dropout_rate=0.5,
            )
        else:
            self.postnet = None

    def _mask(self, length: Tensor):
        x_masks = make_non_pad_mask(length).to(length.device)
        return x_masks.unsqueeze(-2)

    def forward(
        self,
        frame_f0_list: List[Tensor],  # [(fL, 1)]
        frame_phoneme_list: List[Tensor],  # [(fL, )]
        frame_mora_index_list: List[Tensor],  # [(fL, )]
        mora_f0_list: List[Tensor],  # [(mL, 1)]
        mora_vowel_list: List[Tensor],  # [(mL, )]
        mora_consonant_list: List[Tensor],  # [(mL, )]
    ):
        """
        B: batch size
        fL: frame length
        mL: mora length
        """
        device = frame_f0_list[0].device

        frame_length_list = [t.shape[0] for t in frame_f0_list]
        fh = pad_sequence(frame_f0_list, batch_first=True)  # (B, fL, ?)
        fp = pad_sequence(frame_phoneme_list, batch_first=True)  # (B, fL)
        fp = self.encoder_phoneme_embedder(fp + 1)  # (B, fL, ?)
        fh = torch.cat((fh, fp), dim=2)  # (B, fL, ?)

        fh = self.pre_encoder(fh)  # (B, fL, ?)
        fmi = pad_sequence(frame_mora_index_list, batch_first=True)  # (B, fL)
        fh = self.mora_positional_encoder(fh, index=fmi)  # (B, fL, ?)

        frame_mask = self._mask(torch.tensor(frame_length_list, device=device))
        fh, _ = self.encoder(fh, frame_mask)

        mora_length_list = [t.shape[0] for t in mora_f0_list]
        mh = pad_sequence(mora_f0_list, batch_first=True)  # (B, mL, ?)
        mv = pad_sequence(mora_vowel_list, batch_first=True)  # (B, mL)
        mc = pad_sequence(mora_consonant_list, batch_first=True)  # (B, mL)
        mp = self.decoder_phoneme_embedder(mv + 1) + self.decoder_phoneme_embedder(
            mc + 1
        )  # (B, mL, ?)
        mh = torch.cat((mh, mp), dim=2)  # (B, mL, ?)

        mora_mask = self._mask(torch.tensor(mora_length_list, device=device))
        mh, _ = self.decoder(mh, mora_mask, fh, frame_mask)

        output1 = self.post(mh)
        if self.postnet is not None:
            output2 = output1 + self.postnet(output1.transpose(1, 2)).transpose(1, 2)
        else:
            output2 = output1

        return (
            [output1[i, :l] for i, l in enumerate(mora_length_list)],
            [output2[i, :l] for i, l in enumerate(mora_length_list)],
        )

    def inference(
        self,
        frame_f0_list: List[Tensor],  # [(fL, 1)]
        frame_phoneme_list: List[Tensor],  # [(fL, 1)]
        frame_mora_index_list: List[Tensor],  # [(fL, )]
        mora_f0_list: List[Tensor],  # [(mL, 1)]
        mora_vowel_list: List[Tensor],  # [(mL, 1)]
        mora_consonant_list: List[Tensor],  # [(mL, 1)]
    ):
        _, h = self(
            frame_f0_list=frame_f0_list,
            frame_phoneme_list=frame_phoneme_list,
            frame_mora_index_list=frame_mora_index_list,
            mora_f0_list=mora_f0_list,
            mora_vowel_list=mora_vowel_list,
            mora_consonant_list=mora_consonant_list,
        )
        return h

def create_predictor(config: NetworkConfig):
    return Predictor(
        phoneme_size=config.phoneme_size,
        phoneme_embedding_size=config.phoneme_embedding_size,
        hidden_size=config.hidden_size,
        encoder_block_num=config.encoder_block_num,
        attention_heads=config.attention_heads,
        decoder_block_num=config.decoder_block_num,
        post_layer_num=config.post_layer_num,
    )


import re
import sys
import time
from re import Pattern

from comm_support_lib.comm_interfaces.debug_cli import DebugCLI
from tests.common.common_const import CommonConst
from tests.common.common_regex import CommonRegex
from utils.cli_common_util import CliCommonUtil
from utils.common.cli_command_consts import CliCommandConsts
from utils.common.cli_regex_consts import CliRegexConsts

class CommonHelper:
    __debug_cli = DebugCLI()
    __cli_common_util = CliCommonUtil(__debug_cli)

    assert __debug_cli is not None
    assert __cli_common_util is not None

    @staticmethod
    def copy_file(source_file, target_path):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_CP + source_file + " " + target_path)
        while True:
            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)
            if not message:
                continue
            if CommonRegex.PATH_FILE_NOT_FOUND.search(message):
                print("copy_file(). No file/path found on the storage device", file=sys.stderr)
                return False
            if CliRegexConsts.REGEX_LOGGED_IN2.search(message):
                print("copy_file() done for " + source_file)
                return True

    @staticmethod
    def remove_file(filename, forced=False, recursive=False, timeout=CommonConst.TIMEOUT_10_SEC):
        command = CommonConst.COMMAND_RM
        if forced:
            command += CommonConst.RM_ARGUMENT_FORCED
        if recursive:
            command += CommonConst.RM_ARGUMENT_RECURSIVE
        command += filename

        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(command)
        while True:
            message = CommonHelper.__debug_cli.get_message(timeout)
            if not message:
                continue
            if CommonRegex.PATH_FILE_NOT_FOUND.search(message):
                print(f"Cannot remove '{filename}': no such file", file=sys.stderr)
                return False
            if CliRegexConsts.REGEX_LOGGED_IN.search(message):
                print(f"File '{filename}' removed successfully")
                return True

    # Check the file for presence in current or alternating partition
    @staticmethod
    def check_file(partition, filename, timeout=CommonConst.TIMEOUT_2_SEC):
        if partition == 'A':
            cmd_tmp = CommonConst.PARTITION_A + filename
        elif partition == 'B':
            cmd_tmp = CommonConst.PARTITION_B + filename
        else:
            print("Undefine partition")
            return False
        CommonHelper.__debug_cli.flush_incoming_data()
        command = f"[ -f '{cmd_tmp}' ] && echo {CommonConst.FOUND_FILE}"
        CommonHelper.__debug_cli.send_message(command)
        while True:
            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if not message:
                continue
            if CliRegexConsts.REGEX_LOGGED_IN2.search(message):
                print(f"Cannot find file '{filename}'", file=sys.stderr)
                return False
            if CliRegexConsts.REGEX_FOUND_FILE.search(message):
                print(f"File '{filename}' found successfully")
                return True

    @staticmethod
    def check_file(partition, filename, timeout=CommonConst.TIMEOUT_2_SEC):
        if partition == 'A':
            cmd_tmp = CommonConst.PARTITION_A + filename
        elif partition == 'B':
            cmd_tmp = CommonConst.PARTITION_B + filename
        else:
            print("Undefine partition")
            return False
        CommonHelper.__debug_cli.flush_incoming_data()
        command = f"[ -f '{cmd_tmp}' ] && echo {CommonConst.FOUND_FILE}"
        CommonHelper.__debug_cli.send_message(command)
        while True:
            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if not message:
                continue
            if CliRegexConsts.REGEX_LOGGED_IN2.search(message):
                print(f"Cannot find file '{filename}'", file=sys.stderr)
                return False
            if CliRegexConsts.REGEX_FOUND_FILE.search(message):
                print(f"File '{filename}' found successfully")
                return True

    @staticmethod
    def list_directory(directory):
        command = f'{CommonConst.COMMAND_LS}{directory}'
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(command)
        start_time = time.time()
        while True:
            if time.time() - start_time > CommonConst.TIMEOUT_60_SEC:
                return None

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC,
                                                           CommonRegex.LIST_DIR_COMMAND_RESULT)
            if not message:
                continue
            else:
                return message

    @staticmethod
    def package_remove(package_name):
        command = f'{CommonConst.COMMAND_PACKAGE_REMOVE}{package_name}'
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(command)
        start_time = time.time()
        while True:
            if time.time() - start_time > CommonConst.TIMEOUT_30_SEC:
                return None

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)
            if not message:
                continue

            if CliRegexConsts.REGEX_LOGGED_IN2.search(message):
                print(f"'{package_name}' removed ")
                return True

    @staticmethod
    def switch_ethernet(state: bool):
        CommonHelper.__debug_cli.flush_incoming_data()

        if state:
            CommonHelper.__debug_cli.send_message("ifconfig eth0 up")
            assert CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CommonRegex.ETH0_READY)
        else:
            CommonHelper.__debug_cli.send_message("ifconfig eth0 down")
            assert CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CliRegexConsts.REGEX_LOGGED_IN)

    @staticmethod
    def wifi_radio_on():
        CommonHelper.__debug_cli.flush_incoming_data()

        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_WIFI_RADIO_ON)
        assert CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CliRegexConsts.REGEX_LOGGED_IN)

    @staticmethod
    def switch_wifi(state: bool):
        CommonHelper.__debug_cli.flush_incoming_data()

        if state:
            CommonHelper.__debug_cli.send_message(
                CommonConst.COMMAND_IFCONFIG + f"{CommonConst.IFACE_WIFI} {CommonConst.IFACE_STATE_UP}")
            # If wlan0 has no suitable AP configurations, "wlan0: link becomes ready" will not be occurred.
            # Any way, checking of "wlan0: link becomes ready" is required to be sure that the system is
            # completely configured the wlan device
            CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CommonRegex.WLAN0_READY)
        else:
            CommonHelper.__debug_cli.send_message(
                CommonConst.COMMAND_IFCONFIG + f"{CommonConst.IFACE_WIFI} {CommonConst.IFACE_STATE_DOWN}")
            CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CliRegexConsts.REGEX_LOGGED_IN)

    @staticmethod
    def wifi_connect(ssid, password, timeout):
        CommonHelper.__debug_cli.flush_incoming_data()

        test_start_time = time.time()
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_WIFI_CONNECT + f"{ssid} password \"{password}\"")
        while True:
            if time.time() - test_start_time > timeout:
                print("wifi_connect() timeout occurred", file=sys.stderr)
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)
            if message is None:
                continue

            if CommonRegex.WLAN_ACTIVATED.search(message):
                print("wifi_connect() successfully connected to: " + ssid)
                return True
            if CommonRegex.WLAN_SSID_NOT_FOUND.search(message):
                print("wifi_connect() ssid is not found: " + ssid, file=sys.stderr)
                return False
            if CommonRegex.WLAN_CONN_FAILED.search(message):
                print("wifi_connect() connection failed with : " + message, file=sys.stderr)
                return False

    @staticmethod
    def wifi_disconnect(ssid):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_WIFI_DISCONNECT + ssid)
        assert CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, CliRegexConsts.REGEX_LOGGED_IN)

    @staticmethod
    def set_wlan_tx_power(power):
        output_command = f"{CommonConst.COMMAND_IW}{CommonConst.IFACE_WIFI} {CommonConst.IW_SET_TXPOWER}{power}"

        start_time = time.time()
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(output_command)
        while True:
            if time.time() - start_time > CommonConst.TIMEOUT_30_SEC:
                print("__set_wlan_tx_power() timeout occurred", file=sys.stderr)
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)

            if CommonRegex.IW_ERROR.search(message):
                print("__set_wlan_tx_power() execution error", file=sys.stderr)
                return False
            if CliRegexConsts.REGEX_LOGGED_IN.search(message):
                return True

    @staticmethod
    def wifi_check_connection():
        connection_ssid = None

        CommonHelper.__debug_cli.flush_incoming_data()
        result_searching_start_time = time.time()
        CommonHelper.__debug_cli.send_message(
            f"{CommonConst.COMMAND_IW}{CommonConst.IW_DEV}{CommonConst.IFACE_WIFI} {CommonConst.IW_LINK}")
        while True:
            if time.time() - result_searching_start_time > CommonConst.TIMEOUT_20_SEC:
                print("__wifi_check_connection() unknown ping result, timeout occurred", file=sys.stderr)
                return None

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if message is None:
                continue

            if CommonRegex.IW_LINK_SSID.search(message):
                connection_ssid = message.split(": ")[1]
            if connection_ssid is not None and CliRegexConsts.REGEX_LOGGED_IN.search(message):
                break

        return connection_ssid

    @staticmethod
    def ping(host, ping_time):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_PING + host)
        time.sleep(ping_time)

        result_searching_start_time = time.time()
        CommonHelper.__debug_cli.send_message(CliCommandConsts.COMMAND_CTRL_C)
        while True:
            if time.time() - result_searching_start_time > CommonConst.TIMEOUT_20_SEC:
                print("ping() unknown ping result, timeout occurred", file=sys.stderr)
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if message is None:
                continue

            if CommonRegex.BAD_PING.search(message):
                print("ping() return state False")
                return False
            if CommonRegex.GOOD_PING.search(message):
                print("ping() return state True")
                return True

    @staticmethod
    def check_package_presence(package: str):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_TYPE + package)
        type_result = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, re.compile(f"{package} {CommonConst.TYPE_PACKAGE_IS}"))

        if type_result is None:
            print("__check_package_presence() unsuccessful. No response on \'type\' command", file=sys.stderr)
            return False
        else:
            return True

    @staticmethod
    def check_package_help(package: str, help_argument: str):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(package + help_argument)
        if CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC, CommonRegex.COMMAND_NOT_FOUND) is None:
            return True
        else:
            print("__check_package_help() unsuccessful. \'Command not found\' occurred", file=sys.stderr)
            return False

    @staticmethod
    def check_package_version(package: str, version_argument: str, result_regex: Pattern):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(package + version_argument)
        if CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC, result_regex) is not None:
            return True
        else:
            print("__check_package_version() unsuccessful", file=sys.stderr)
            return False

    @staticmethod
    def perform_ethtool(device: str, speed: str, duplex: str, auto_negotiation: str):
        check_speed = False
        check_duplex = False
        check_autoneg = False

        ethtool_command = f"{CommonConst.COMMAND_ETHTOOL}-s {device} speed {speed} duplex {duplex} autoneg {auto_negotiation}"

        CommonHelper.__debug_cli.flush_incoming_data()

        test_start_time = time.time()
        CommonHelper.__debug_cli.send_message(ethtool_command)
        # wait some time ensure that the function is done and the device is completely reconfigured
        time.sleep(CommonConst.TIMEOUT_10_SEC)

        ethtool_check_command = f"{CommonConst.COMMAND_ETHTOOL}{device}"
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(ethtool_check_command)
        while True:
            if time.time() - test_start_time > CommonConst.TIMEOUT_60_SEC:
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)
            if message is None:
                continue

            result = CommonRegex.ETHTOOL_SPEED.search(message)
            if result:
                if speed in result.group(0):
                    check_speed = True
                else:
                    print("__perform_ethtool() failed to set speed: " + speed, file=sys.stderr)
                    return False

            result = CommonRegex.ETHTOOL_DUPLEX.search(message)
            if result:
                if duplex in result.group(0).lower():
                    check_duplex = True
                else:
                    print("__perform_ethtool() failed to set duplex: " + duplex, file=sys.stderr)
                    return False

            result = CommonRegex.ETHTOOL_AUTONEG.search(message)
            if result:
                if auto_negotiation in result.group(0):
                    check_autoneg = True
                else:
                    print("__perform_ethtool() failed to set autoneg: " + auto_negotiation, file=sys.stderr)
                    return False

            if check_speed and check_duplex and check_autoneg:
                return True

    @staticmethod
    def find_matches(command_to_perform: str, matches_regex: Pattern, timeout: int):
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(command_to_perform)
        found_list = []
        test_start_time = time.time()
        while True:
            if time.time() - test_start_time > timeout:
                break

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if message is None:
                continue
            elif matches_regex.search(message):
                found_list.append(message)

        return found_list

    @staticmethod
    def configure_can(iface: str, enable: bool, bit_rate: int = 20000):
        CommonHelper.__debug_cli.flush_incoming_data()
        if enable:
            CommonHelper.__debug_cli.send_message(
                f"{CommonConst.COMMAND_IP_LINK}{CommonConst.IP_LINK_SET}{iface} {CommonConst.IFACE_STATE_UP} {CommonConst.IP_LINK_TYPE_CAN}{CommonConst.IP_LINK_BITRATE}{bit_rate}")
        else:
            CommonHelper.__debug_cli.send_message(
                f"{CommonConst.COMMAND_IP_LINK}{CommonConst.IP_LINK_SET}{iface} {CommonConst.IFACE_STATE_DOWN}")

        return_state = True
        test_start_time = time.time()
        while True:
            if time.time() - test_start_time > CommonConst.TIMEOUT_30_SEC:
                print("__configure_can() timeout occurred", file=sys.stderr)
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_5_SEC)
            if message is None:
                continue
            elif CliRegexConsts.REGEX_LOGGED_IN.search(message):
                return return_state
            elif CommonRegex.CAN_DEV_BUSY.search(message):
                print("__configure_can() Device or resource busy", file=sys.stderr)
                return_state = False

    @staticmethod
    def perform_cangen(iface: str, extended_id: bool, data: bytes, id: int, delay_msec: int, generation_time_sec: int,
                       additional_arguments: str = None):
        output_command = f"{CommonConst.COMMAND_CANGEN} {iface} "

        if extended_id:
            output_command += CommonConst.CANGEN_EXTENDED

        data_len = len(data)
        if data_len == 0 or data_len > CommonConst.CAN_MAX_PAYLOAD:
            return False

        output_command += f"{CommonConst.CANGEN_DATA_LEN}{data_len} {CommonConst.CANGEN_DATA}{data.hex().upper()} "
        output_command += f"{CommonConst.CANGEN_ID}{hex(id).upper()} "
        output_command += f"{CommonConst.CANGEN_INTERVAL} {delay_msec} "

        if additional_arguments:
            output_command += additional_arguments

        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(output_command)
        time.sleep(generation_time_sec)

        CommonHelper.__debug_cli.send_message(CliCommandConsts.COMMAND_CTRL_C)
        return CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_20_SEC,
                                                    CliRegexConsts.REGEX_LOGGED_IN) is not None

    @staticmethod
    def create_folder(folder: str, with_patents: bool = False):
        CommonHelper.__debug_cli.flush_incoming_data()

        command = CommonConst.COMMAND_MKDIR
        if with_patents:
            command += CommonConst.MKDIR_ARGUMENT_P
        command += folder

        return_state = True
        test_start_time = time.time()
        CommonHelper.__debug_cli.send_message(command)
        while True:
            if time.time() - test_start_time > CommonConst.TIMEOUT_60_SEC:
                print("create_folder() timeout occurred", file=sys.stderr)
                return False

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC)
            if message is None:
                continue

            if CommonRegex.MKDIR_ERROR.search(message):
                print(f"create_folder() error while creating {folder}", file=sys.stderr)
                return_state = False
            if CliRegexConsts.REGEX_LOGGED_IN.search(message):
                print(f"create_folder() done for {folder}")
                return return_state

    @staticmethod
    def get_md5_checksum(file):
        command = f'{CommonConst.COMMAND_MD5_CHECKSUM} {file}'
        CommonHelper.__debug_cli.flush_incoming_data()
        CommonHelper.__debug_cli.send_message(command)

        start_time = time.time()
        while True:
            if time.time() - start_time > CommonConst.TIMEOUT_60_SEC:
                return None

            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC,
                                                           CommonRegex.MD5_CHECKSUM_COMMAND_RESULT)
            if not message:
                continue
            else:
                return message.split(" ")[0]

    @staticmethod
    def hard_reset(boot_from_emmc=False):
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_ECHO + CommonConst.SET_SYSRQ)
        CommonHelper.__debug_cli.send_message(CommonConst.COMMAND_ECHO + CommonConst.SET_SYSRQ_TRIGG)

        if boot_from_emmc:
            command_start_time = time.time()
            CommonHelper.__debug_cli.flush_incoming_data()
            while True:
                if time.time() - command_start_time > CommonConst.TIMEOUT_60_SEC:
                    print("Boot system after hard reset failed. Timeout occurred", file=sys.stderr)
                    return False
                CommonHelper.__debug_cli.send_message(CliCommandConsts.COMMAND_EMPTY)
                if CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_500_MSEC, CliRegexConsts.REGEX_UBOOT_CLI):
                    break
            CommonHelper.__debug_cli.send_message(CliCommandConsts.COMMAND_BOOT_FROM_EMMC)

        command_start_time = time.time()
        CommonHelper.__debug_cli.flush_incoming_data()
        while True:  # Wait system to boot after hard reset
            if time.time() - command_start_time > CommonConst.TIMEOUT_60_SEC:
                print("Boot system after hard reset failed. Timeout occurred", file=sys.stderr)
                return False
            message = CommonHelper.__debug_cli.get_message(CommonConst.TIMEOUT_10_SEC, CliRegexConsts.REGEX_LOGIN)
            if message:
                print("Boot system after hard reset succeeded.")
                return True


import json

json_File = '../data/fixed_json/QoA_dialog.fixed_json'
answers = []
questions = []
with open('data/txt/questions.txt', 'r') as Question_file:
    readerQ = Question_file.readlines()

    for raw in readerQ:
        questions.append(raw)

with open('data/txt/answers.txt', 'r') as Answer_file:
    readerA = Answer_file.readlines()

    for raw in readerA:
        answers.append(raw)

z = zip(questions, answers)
zipped = list(z)
zipped_data = []

for i in zipped:
    zipped_data.append(i)

QoA_to_dict = []
for i in zipped_data:
    question = i[0].replace('\n','')
    answer = i[1].replace('\n','')
    QoA_to_dict.append(
        {
            'tag': question,
            'question': question,
            'answer': answer
        }
    )

with open(json_File, 'w') as jsonFile:
    jsonFile.write(json.dumps(QoA_to_dict, indent=4))


"""
A Fetcher that is responsible of fetching (i.e. requesting) contents (e.g. M3U8, Key)
from given URL
"""

import sys
import logging
import requests

class Fetcher:

    def __init__(self, fet_logger: logging.Logger) -> None:
        """
        Welcoming the logger assigned
        :param fet_logger: the logger assigned
        """
        self._logger = fet_logger

    def fetch_m3u(self, m3u_url: str) -> bytes:
        """
        Fetching the content of M3U8 and return it
        :param m3u_url: the URL to M3U8 file
        :return: the content of M3U8 in bytes
        """
        m3u_content = requests.get(url=m3u_url).content
        self._logger.debug('M3U8 content: {}'.format(m3u_content))
        return m3u_content

    def fetch_key(self, key_url: str=None) -> bytes:
        """
        Fetching the content of key and return it
        :param key_url: the URL to key file
        :return: the content of key in bytes
        """
        self._logger.debug('Key URL: {}'.format(key_url))
        key_content = requests.get(url=key_url).content if key_url else None
        self._logger.debug('Key content: {}'.format(key_content))
        return key_content

# Demo
if __name__ == '__main__':
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(logging.StreamHandler(sys.stdout))
    minion = Fetcher(logger)
    print(minion.fetch_m3u("http://sample.m3u8"))
    print(minion.fetch_key("http://sample.key"))


from typing import Optional

from aiogram.types import User

from bot.config_reader import config
from bot.database.models import Transaction, Currency, TransStatus, MessageTransaction, TransactionComplain
from bot.database.models import User as UserModel
from bot.utils.calculate_amount import calculate_get_amount
from . import users, transactions, merchants
from .query_controller import QueryController
from ..handlers.errors import MyTgException, ChangeMessage, DelMessage

class BotQueryController:
    def __init__(self, query_controller: QueryController):
        self._query_controller: QueryController = query_controller

        self._user_tg: Optional[User] = None
        self._user: Optional[UserModel] = None

        self._work_transactions: Optional[list[Transaction]] = None

    # Users
    async def get_other_user(self, user_id: int):
        if not self.is_admin():
            raise MyTgException(inline_message = 'Permission denied')
        return await users.get_user(self._query_controller, user_id)

    def get_user(self):
        return self._user

    async def get_and_update_user(self, user: User):
        self._user_tg = user
        self._user = await users.get_user(self._query_controller, self._user_tg.id)
        if self._user:
            await users.update_user(self._query_controller, self._user, {
                'username': self._user_tg.username,
                'first_name': self._user_tg.first_name,
                'last_name': self._user_tg.last_name
            })

    async def create_user(self) -> UserModel:
        self._user = await users.create_user(self._query_controller, self._user_tg.id,
                                             self._user_tg.first_name,
                                             self._user_tg.last_name,
                                             self._user_tg.username,
                                             self._user_tg.language_code)
        return self._user

    async def set_phone(self, number: str) -> None:
        await users.update_user(self._query_controller, self._user, {
            'phone': number
        })

    async def change_language(self, lang: str) -> None:
        await users.update_user(self._query_controller, self._user, {
            'language': lang
        })

    # Merchants
    def is_merchant(self) -> bool:
        return self._user_tg.id in config.merchants

    def is_admin(self) -> bool:
        return self._user_tg.id in config.admins

    async def add_merchant(self, user_id: int):
        if not self.is_admin():
            raise MyTgException(inline_message = 'Permission denied')
        return await merchants.add_merchant(self._query_controller, user_id)

    async def get_merchants(self):
        if not self.is_admin():
            raise MyTgException(inline_message = 'Permission denied')
        return await merchants.get_merchants(self._query_controller)

    # Transactions
    async def create_transaction(self, data):
        if self.is_merchant():
            raise MyTgException(text_message = 'Merchant cant make transaction')
        if len(await self.get_exchange_transactions()) >= config.max_user_transaction:
            raise MyTgException(text_message = 'You have limit count of your transaction')

        out = {
            'have_amount': data['amount'],
            'get_amount': calculate_get_amount(data['have_currency'], data['get_currency'],
                                               data['amount'], data['rate']),
            'commission_merchant': round(data['amount'] * config.merchant_commission, 2),
            'commission_user': 0
        }

        return out

    async def public_transaction(self, data: dict) -> Transaction:
        if self.is_merchant():
            raise MyTgException(text_message = 'Merchant cant make transaction')
        if len(await self.get_exchange_transactions()) >= config.max_user_transaction:
            raise MyTgException(text_message = 'You have limit count of your transaction')

        return await transactions.create_transaction(
            self._query_controller,
            user_id = self._user.id,
            **data
        )

    async def set_channel_message_transaction(self, transaction: Transaction, message_id: int):
        return await transactions.update_transaction(self._query_controller, transaction,
                                                     {'merchant_message_id': message_id})

    async def get_transaction(self, transaction_id: int) -> Transaction:
        transaction = await transactions.get_transaction(self._query_controller, transaction_id)
        if self.is_merchant() and transaction.merchant_id is None:
            return transaction
        if (self.is_merchant() and (transaction.merchant_id == self._user.id)) or (
                transaction.user_id == self._user.id):
            return transaction
        raise MyTgException(text_message = 'You can not get this transaction')

    async def get_exchange_transactions(self) -> list[Transaction]:
        if self._work_transactions:
            return self._work_transactions
        self._work_transactions = await transactions.get_work_transaction(self._query_controller, self._user.id,
                                                                          self.is_merchant())
        return self._work_transactions

    async def merchant_take_transaction(self, transaction: Transaction):
        if not self.is_merchant():
            raise MyTgException(inline_message = 'You is not merchant')
        if transaction.status != TransStatus.in_stack:
            raise MyTgException(inline_message = 'Cant take this transaction')
        thb_amount = transaction.get_amount if transaction.get_currency in Currency.change() \
            else transaction.have_amount
        if self._user.merchant.allow_max_amount < thb_amount:
            raise MyTgException(inline_message = 'Too much amount for you')
        if len(await self.get_exchange_transactions()) > 3:  # todo const
            raise MyTgException(inline_message = 'You have too much transactions')

        transaction.merchant_id = self._user.id
        transaction.status = TransStatus.in_exchange
        await transactions.update_transaction(self._query_controller, transaction,
                                              {'status': TransStatus.in_exchange, 'merchant_id': self._user.id})

        return transaction

    async def merchant_get_transaction_money(self, transaction: Transaction):
        if transaction.merchant_id != self._user.id:
            raise DelMessage(inline_message = 'You is not merchant of this transaction')
        if transaction.status != TransStatus.in_exchange:
            raise DelMessage(inline_message = 'Cant accept money for this transaction')
        if transaction.complain:
            raise MyTgException(inline_message = 'Transaction is complain')

        transaction.status = TransStatus.wait_good_user
        await transactions.update_transaction(self._query_controller, transaction,
                                              {'status': TransStatus.wait_good_user})
        return transaction

    async def user_get_transaction_money(self, transaction: Transaction) -> Transaction:
        if transaction.user_id != self._user.id:
            raise DelMessage(inline_message = 'You is not maker of this transaction')
        if transaction.status != TransStatus.wait_good_user:
            raise DelMessage(inline_message = 'Cant accept money for this transaction')
        if transaction.complain:
            raise MyTgException(inline_message = 'Transaction is complain')

        return await transactions.finish_transaction(self._query_controller, transaction, TransStatus.good_finished)

    async def user_cancel_transaction(self, transaction: Transaction) -> Transaction:
        if transaction.user_id != self._user.id:
            raise DelMessage(inline_message = 'You is not maker of this transaction')
        if transaction.status not in [TransStatus.in_stack, TransStatus.in_exchange]:
            raise MyTgException(inline_message = 'You can not cancel this transaction')
        if transaction.complain:
            raise DelMessage(inline_message = 'Transaction is complain')

        return await transactions.finish_transaction(self._query_controller, transaction, TransStatus.canceled)

    async def complain_transaction(self, transaction: Transaction, cause: str) -> TransactionComplain:
        if transaction.complain:
            raise DelMessage(inline_message = 'Already complain')

        return await transactions.create_complain(self._query_controller, transaction,
                                                  transaction.merchant_id == self._user.id, cause)

    async def un_complain_transaction(self, transaction):
        if not transaction.complain:
            raise DelMessage(inline_message = 'Is not complain')
        if (transaction.complain.is_merchant and transaction.merchant_id != self._user.id) and \
                (transaction.user_id != self._user.id):
            raise MyTgException(inline_message = 'Not you complained')

        await transactions.delete_complain(self._query_controller, transaction)

    async def change_transaction(self, transaction, key: str, value: float):
        if transaction.user_id != self._user.id:
            raise DelMessage(inline_message = 'You is not maker of this transaction')
        if transaction.status not in [TransStatus.in_stack, TransStatus.in_exchange]:
            raise DelMessage(inline_message = 'You cant edit this transaction')
        if transaction.complain:
            raise DelMessage(inline_message = 'transaction is complain')

        if key == 'have_amount':
            return await transactions.update_transaction(
                self._query_controller, transaction,
                {
                    'have_amount': value,
                    'get_amount': calculate_get_amount(transaction.have_currency,
                                                       transaction.get_currency,
                                                       value, transaction.rate),
                    'commission_merchant': round(
                        value * config.merchant_commission, 2),
                    'commission_user': 0
                })
        elif key == 'rate':
            return await transactions.update_transaction(
                self._query_controller, transaction,
                {
                    'rate': value,
                    'get_amount': calculate_get_amount(transaction.have_currency,
                                                       transaction.get_currency,
                                                       transaction.have_amount, value),
                })

        elif key == 'get_amount':
            new_amount = calculate_get_amount(transaction.get_currency, transaction.have_currency,
                                              value, transaction.rate)
            return await transactions.update_transaction(
                self._query_controller, transaction,
                {
                    'have_amount': new_amount,
                    'get_amount': value,
                    'commission_merchant': round(
                        new_amount * config.merchant_commission, 2),
                    'commission_user': 0
                })
        else:
            raise DelMessage(inline_message = 'Unknown key')

    async def send_sms_transaction(self, transaction, text: str) -> MessageTransaction:
        if transaction.merchant_id != self._user.id and transaction.user_id != self._user.id:
            raise DelMessage(inline_message = 'You is not merchant or maker of this transaction')
        if transaction.status not in TransStatus.exchange():
            raise DelMessage(inline_message = 'You can not write message for this transaction')
        return await transactions.create_message(self._query_controller, transaction.id, text,
                                                 transaction.merchant_id != self._user.id)

    async def get_sms_history_transaction(self, transaction):
        if transaction.merchant_id != self._user.id and transaction.user_id != self._user.id:
            raise DelMessage(inline_message = 'You is not merchant or maker of this transaction')
        if transaction.status not in TransStatus.exchange():
            raise DelMessage(inline_message = 'You can not write message for this transaction')
        return await transactions.get_messages(self._query_controller, transaction.id)


import io
import sys

_INPUT = """\
2
3
1 1
2 2
3 3
7
3 4
1 1 10
3 4
2 1 0
2 3 0
3 4
3 2
4
11
19
-1
4
2
2 3
2 1
1
3 2
1
4
"""

#ここから下を提出
class segtree():
  n=1
  size=1
  log=2
  d=[0]
  op=None
  e=10**15
  def __init__(self,V,OP,E):
      self.n=len(V)
      self.op=OP
      self.e=E
      self.log=(self.n-1).bit_length()
      self.size=1<<self.log
      self.d=[E for i in range(2*self.size)]
      for i in range(self.n):
          self.d[self.size+i]=V[i]
      for i in range(self.size-1,0,-1):
          self.update(i)
  def set(self,p,x):
      assert 0<=p and p<self.n
      p+=self.size
      self.d[p]=x
      for i in range(1,self.log+1):
          self.update(p>>i)
  def get(self,p):
      assert 0<=p and p<self.n
      return self.d[p+self.size]
  def prod(self,l,r):
      assert 0<=l and l<=r and r<=self.n
      sml=self.e
      smr=self.e
      l+=self.size
      r+=self.size
      while(l<r):
          if (l&1):
              sml=self.op(sml,self.d[l])
              l+=1
          if (r&1):
              smr=self.op(self.d[r-1],smr)
              r-=1
          l>>=1
          r>>=1
      return self.op(sml,smr)
  def all_prod(self):
      return self.d[1]
  def max_right(self,l,f):
      assert 0<=l and l<=self.n
      assert f(self.e)
      if l==self.n:
          return self.n
      l+=self.size
      sm=self.e
      while(1):
          while(l%2==0):
              l>>=1
          if not(f(self.op(sm,self.d[l]))):
              while(l<self.size):
                  l=2*l
                  if f(self.op(sm,self.d[l])):
                      sm=self.op(sm,self.d[l])
                      l+=1
              return l-self.size
          sm=self.op(sm,self.d[l])
          l+=1
          if (l&-l)==l:
              break
      return self.n
  def min_left(self,r,f):
      assert 0<=r and r<=self.n
      assert f(self.e)
      if r==0:
          return 0
      r+=self.size
      sm=self.e
      while(1):
          r-=1
          while(r>1 & (r%2)):
              r>>=1
          if not(f(self.op(self.d[r],sm))):
              while(r<self.size):
                  r=(2*r+1)
                  if f(self.op(self.d[r],sm)):
                      sm=self.op(self.d[r],sm)
                      r-=1
              return r+1-self.size
          sm=self.op(self.d[r],sm)
          if (r& -r)==r:
              break
      return 0
  def update(self,k):
      self.d[k]=self.op(self.d[2*k],self.d[2*k+1])
  def __str__(self):
      return str([self.get(i) for i in range(self.n)])

def solve(N,cards,Q,query):
  score=sorted(list(set([cards[i][0] for i in range(N)]+[query[i][2] for i in range(Q) if query[i][0]==1])))
  ans=[]
  dic={score[i]:i for i in range(len(score))}
  count_ini=[0 for i in range(len(score))]
  score_ini=[0 for i in range(len(score))]
  for i in range(N):
    a,b=cards[i]
    count_ini[dic[a]]+=b
    score_ini[dic[a]]+=a*b
  st_count=segtree(count_ini,(lambda x,y: x+y),0)
  st_score=segtree(score_ini,(lambda x,y: x+y),0)
  for i in range(Q):
    if query[i][0]==1:
      x,y=query[i][1:]
      x-=1
      a,b=cards[x]
      from_id=dic[a]
      to_id=dic[y]
      cards[x][0]=y
      st_count.set(from_id,st_count.get(from_id)-b)
      st_count.set(to_id,st_count.get(to_id)+b)
      st_score.set(from_id,st_score.get(from_id)-a*b)
      st_score.set(to_id,st_score.get(to_id)+y*b)
    elif query[i][0]==2:
      x,y=query[i][1:]
      x-=1
      a,b=cards[x]
      id=dic[a]
      cards[x][1]=y
      st_count.set(id,st_count.get(id)+y-b)
      st_score.set(id,st_score.get(id)+a*(y-b))
    else:
      x=query[i][1]
      l=st_count.min_left(len(score), lambda func: func<=x)
      if st_count.all_prod()<x: ans.append(-1)
      else:
        if l>0: ans.append(st_score.prod(l,len(score))+score[l-1]*(x-st_count.prod(l,len(score))))
        else: ans.append(st_score.prod(l,len(score)))
  return ans

def simple_solution(N,cards,Q,query):
  ans=[]
  for i in range(Q):
    if query[i][0]==1:
      x,y=query[i][1:]
      x-=1
      cards[x][0]=y
    elif query[i][0]==2:
      x,y=query[i][1:]
      x-=1
      cards[x][1]=y
    else:
      x=query[i][1]
      tmp=sorted(cards,reverse=True)
      cnt=0
      now=0
      ans2=0
      if sum([cards[i][1] for i in range(N)])<x: ans.append(-1)
      else:
        while now<N and cnt+tmp[now][1]<=x:
          ans2+=tmp[now][0]*tmp[now][1]
          cnt+=tmp[now][1]
          now+=1
        if cnt<x: ans2+=tmp[now][0]*(x-cnt)
        ans.append(ans2)
  return ans

from random import randint
def random_case():
  N=randint(1,10)
  cards=[[randint(0,10),randint(0,10)] for _ in range(N)]
  Q=randint(1,10)
  query=[]
  for i in range(Q):
    d=randint(1,3)
    if d<=2: x,y=randint(1,N),randint(0,10); query.append([d,x,y])
    else: x=randint(1,20); query.append([d,x])
  return N,cards,Q,query

def read_input():
  N=int(input())
  cards=[list(map(int,input().split())) for _ in range(N)]
  Q=int(input())
  query=[list(map(int,input().split())) for _ in range(Q)]
  return N,cards,Q,query

def read_output():
  res=[]
  l=int(input())
  for i in range(l): res.append(int(input()))
  return res

def output(ans):
  for i in range(len(ans)):
    print(ans[i])

def test():
  sys.stdin = io.StringIO(_INPUT)
  case_no=int(input())
  for i in range(case_no):
    sol=solve(*read_input())
    ans=read_output()
    if sol!=ans:
      print(sol)
      print(ans)

def main():
  ans=solve(*read_input())
  output(ans)

from copy import deepcopy
def random_test():
  while True:
    N,cards,Q,query=random_case()
    N2=N
    cards2=deepcopy(cards)
    Q2=Q
    query2=deepcopy(query)
    a=solve(N,cards,Q,query)
    b=simple_solution(N2,cards2,Q2,query2)
    if a!=b:
      print(N)
      for i in range(N): print(*cards[i])
      print(Q)
      for i in range(Q): print(*query[i])
      print(a)
      print(b)
      break

if __name__ == "__main__":
  flg=1
  if flg==0: main()
  elif flg==1: test()
  else: simple_solution()


import pandas as pd
import numpy as np
import pickle
import pymc3 as pm
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import pearsonr, mode

def extract_mode_as_array(trace, var='z', astype='array'):

    def trace_mode(x):
        return pd.Series(mode(x).mode[0], name='mode')

    df = pm.summary(trace, stat_funcs=[trace_mode], varnames=[var])
    df = df.reset_index()

    def split_fun(x):
        if '__' in x:
            return [int(x) for x in x.split('__')[1].split('_')]
        else:
            return [0]

    df['var type'] = df['index'].apply(lambda x: x.split('__')[0])
    df = df.loc[df['var type'] == var, :]
    var_idxs = df['index'].apply(split_fun)
    indexs = np.stack(var_idxs)
    if astype == 'array':
        sizes = indexs.max(axis=0) + 1
        var_array = df['mode'].copy().values.reshape(sizes)
        return var_array
    else:
        df_out = pd.DataFrame(np.concatenate([indexs, np.expand_dims(df['mode'].values, -1)], axis=1))
        df_out.columns = list(df_out.columns[:-1]) + [var]
        return df_out

def extract_mean_as_array(trace, var='z', astype='array'):
    df = pm.summary(trace)
    df = df.reset_index()

    def split_fun(x):
        if '__' in x:
            return [int(x) for x in x.split('__')[1].split('_')]
        else:
            return [0]

    df['var type'] = df['index'].apply(lambda x: x.split('__')[0])
    df = df.loc[df['var type'] == var, :]
    var_idxs = df['index'].apply(split_fun)
    indexs = np.stack(var_idxs)
    if astype == 'array':
        sizes = indexs.max(axis=0)+1
        var_array = df['mean'].copy().values.reshape(sizes)
        return var_array
    else:
        df_out = pd.DataFrame(np.concatenate([indexs, np.expand_dims(df['mean'].values, -1)], axis=1))
        df_out.columns = list(df_out.columns[:-1])+[var]
        return df_out

def plot_expertise(model_r, annotator_file):
    df = pm.summary(trace)
    df['e'] = df['mean']
    df['gs'] = df['variable']

def compare_to_gs_data(all_gs_data):
    fp = 0
    fn = 0
    tp = 0
    for gs, gs_data in all_gs_data.groupby('cluster'):
        if gs_data.shape[0] <= 2:
            print('Found a cluster of more than one matlab and one model, added a tp, and moving on')
        found_type = gs_data['Type'].values
        if 'matlab' in found_type and 'model' in found_type:
            tp += 1
        elif 'matlab' not in found_type and 'model' in found_type:
            fp += 1
        elif 'matlab' in found_type and 'model' not in found_type:
            fn += 1
        elif 'matlab' not in found_type and 'model' not in found_type:
            raise ValueError

    print('Recall:', tp/(tp+fn), 'Precision:', tp/(tp + fp))

def compare_r_data(r_data, annotator_data):
    r_data = pd.merge(r_data, annotator_data, on='annotatorID')
    sns.scatterplot(x='E', y='E_sd', hue='Scorer Type', data=r_data)
    plt.show()
    pass
    # plt.figure()
    # plt.subplot(1, 2, 1)
    # p1 = sns.scatterplot(x=matlab_gs['s'], y=model_gs['s'])
    # r, p = pearsonr(matlab_gs['s'], model_gs['s'])
    # p1.text(0.5, 0.5, "r="+str(r)+', p='+str(p))
    # plt.subplot(1, 2, 2)
    # p2 = sns.scatterplot(x=matlab_gs['e'], y=model_gs['e'])
    # p2.text(0.5, 0.5, "r=" + str(r) + ', p=' + str(p))
    # plt.show()


# Load fixture

import os, sys
if __name__ == '__main__':
    execfile(os.path.join(sys.path[0], 'framework.py'))

from lxml import etree
from BaseTestCase import BaseTestCase
from Products.CNXMLDocument import XMLService

noNS = "<tag>Hello</tag>"
cnxml = "<para xmlns='http://cnx.rice.edu/cnxml' id='hello'>Hello</para>"
cnxml_mathml = "<para xmlns='http://cnx.rice.edu/cnxml' xmlns:m='http://www.w3.org/1998/Math/MathML' id='hello'>Hello</para>"
cnxml_mathml2 = "<para xmlns='http://cnx.rice.edu/cnxml' xmlns:m='http://www.w3.org/1998/Math/MathML' id='hello'>Hello<m:math><m:cn>0</m:cn></m:math></para>"
nested_cnxml = "
<para id='hello'>Hello</para>
"

cnxml_dtd = \
"""<?xml version='1.0'?>
<!DOCTYPE para PUBLIC "-//CNX//DTD CNXML 0.5//EN" "http://cnx.rice.edu/cnxml/0.5/DTD/cnxml_plain.dtd">
<para xmlns="http://cnx.rice.edu/cnxml" id="hello">Hello</para>
"""

cnxml_mathml_dtd = \
"""<?xml version='1.0'?>
<!DOCTYPE para PUBLIC "-//CNX//DTD CNXML 0.5 plus MathML//EN" "http://cnx.rice.edu/cnxml/0.5/DTD/cnxml_mathml.dtd">
<para xmlns="http://cnx.rice.edu/cnxml" xmlns:m='http://www.w3.org/1998/Math/MathML' id="hello">Hello<m:math><m:cn>0</m:cn></m:math></para>
"""

class ParseDoc(BaseTestCase):
    """
    Test the parseDoc() method
    """

    def testParseBadDocument(self):
        """parseDoc() must fail if the document cannot be parsed"""
        self.assertRaises(XMLService.XMLError, XMLService.parseDoc, 'non-XML')

    def testParseDocumentReturnsXMLDoc(self):
        """parseDoc must return an xmlDoc"""
        doc = XMLService.parseDoc(noNS)
        self.failUnless(isinstance(doc, etree._ElementTree))

    def testParseDocument(self):
        """return of parseDoc must serializes correctly"""
        doc = XMLService.parseDoc(noNS)
        self.assertEquals(etree.tostring(doc), '<tag>Hello</tag>')

class XsltPipeline(BaseTestCase):
    """
    Test the xsltPipeline() method
    """

    def testEmptyPipeline(self):
        """xsltPipeline must serialize original doc if pipeline is empty"""
        doc = XMLService.parseDoc(noNS)
        self.assertEquals(XMLService.xsltPipeline(doc, []), '<tag>Hello</tag>')

    def testSingleTransform(self):
        """xsltPipeline must correctly perform single transform"""
        doc = XMLService.parseDoc(noNS)
        self.assertEquals(XMLService.xsltPipeline(doc, ['test.xsl']), 'Success')

    def testDoubleTransform(self):
        """xsltPipeline must correctly perform double transform"""
        doc = XMLService.parseDoc(noNS)
        self.assertEquals(XMLService.xsltPipeline(doc, ['step1.xsl', 'step2.xsl']), 'Success')

def test_suite():
    from unittest import TestSuite, makeSuite
    suite = TestSuite()
    #suite.addTest(makeSuite(ParseDoc))
    suite.addTest(makeSuite(XsltPipeline))
    return suite

if __name__ == '__main__':
    framework()


import torch as th
from torch.utils.tensorboard import SummaryWriter

class learning_loop():
    def __init__(self, N_EPOCH,model,device,train_data,val_data,test_data,optimizer,criterion, directory,mode ) -> None:
        self.N_EPOCH = N_EPOCH
        self.model = model
        self.device = device
        self.train_data = train_data
        self.val_data = val_data
        self.test_data = test_data
        self.optimizer = optimizer
        self.criterion = criterion
        self.mode = mode
        self.writer1=SummaryWriter('logs/'+directory+'/train',flush_secs=60)
        self.writer2=SummaryWriter('logs/'+directory+'/val',flush_secs=60)

    def train(self):
        for epoch in range(1, self.N_EPOCH+1):
            for (_,train) , (_,test) in zip(enumerate(self.train_data, 0),enumerate(self.val_data, 0)):
                self.model.train()
                X_train_ts, y_train_ts = train
                X_val_ts, y_val_ts = test

                X_train_ts, y_train_ts = X_train_ts.to(self.device), y_train_ts.to(self.device)
                X_val_ts, y_val_ts = X_val_ts.to(self.device), y_val_ts.to(self.device)

                out = self.model(X_train_ts.to(th.float32))
                loss = self.criterion(out, y_train_ts)

                self.optimizer.zero_grad()
                loss.backward()
                self.optimizer.step()

                if self.mode == 'classification':
                    acc = (th.argmax(out, dim=1) == y_train_ts).float().mean().item()

                self.model.eval()
                with th.no_grad():
                    out_val = self.model(X_val_ts.to(th.float32))
                    loss_val = self.criterion(out_val, y_val_ts)
                    if self.mode == 'classification':
                        acc_val = (th.argmax(out_val, dim=1) == y_val_ts).float().mean().item()

            self.writer1.add_scalar('Loss', loss.item(), epoch)
            self.writer2.add_scalar('Loss', loss_val.item(), epoch)

            if self.mode == 'classification':
                self.writer1.add_scalar('Accuracy', acc*100 , epoch)
                self.writer2.add_scalar('Accuracy', acc_val*100, epoch)

            if epoch % 20 == 0:
                    if self.mode == 'classification':
                        print('Epoch : {:3d} / {}, Loss : {:.4f}, Accuracy : {:.2f} %, Val Loss : {:.4f}, Val Accuracy : {:.2f} %'.format(
                            epoch, self.N_EPOCH, loss.item(), acc*100, loss_val.item(), acc_val*100))
                    else:
                        print('Epoch : {:3d} / {}, Loss : {:.4f},  Val Loss : {:.4f}'.format(
                            epoch, self.N_EPOCH, loss.item(), loss_val.item()))

        self.writer1.close()
        self.writer2.close()

    def test(self):
        acc_avg = 0
        loss_avg = 0
        y_list = [] # i,y_test,y_pred

        for (i,test) in enumerate(self.test_data, 0):

            X_test_ts, y_test_ts = test
            X_test_ts, y_test_ts = X_test_ts.to(self.device), y_test_ts.to(self.device)

            self.model.eval()
            with th.no_grad():
                out_test = self.model(X_test_ts.to(th.float32))
                loss_test = self.criterion(out_test, y_test_ts)
                if self.mode == 'classification':
                    acc_test = (th.argmax(out_test, dim=1) == y_test_ts).float().mean().item()

            if self.mode == 'classification':
                acc_avg += acc_test
            else:
                y_list.append([i,y_test_ts.cpu().numpy(),out_test.cpu().numpy()])

            loss_avg += loss_test
        if self.mode == 'classification':
            print('Val avg Loss : {:.4f}, Val avg Accuracy : {:.2f} %'.format(
                loss_avg/i,acc_avg/i*100))
        else:
            print('Val avg Loss : {:.4f}'.format(
                loss_avg/i))
            return y_list


from flask import flash
from html import escape
import re
from .logger_config import setup_logger
from flask_login import current_user

logger = setup_logger()

class InvalidInputError(ValueError):
    pass

def sanitize_pay_amount(pay_amount):
    pay_amount2 = str(pay_amount)
    if not re.match(r'^[0-9]+(\.[0-9]{1,2})?$|^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]{1,2})?$', pay_amount2):
        flash("Invalid pay amount. Please enter a valid float like '0.25' or '0,50'.", category='error')
        raise ValueError("Invalid pay amount, the pay amount included was:", pay_amount)

def sanitize_participant_ids(participant_id_list):
    if type(participant_id_list) == list:
        for id in participant_id_list:
            sanitize_participant_id(id)
    else:
        raise InvalidInputError

def sanitize_participant_id(participant_id):
    if not re.match(r'^[0-9]+', str(participant_id)):
        raise InvalidInputError("This input provided is invalid {}".format(id))

def sanitize_string(description) -> str:
    description = escape(description).strip()
    if not description or description.isspace():
        flash("Error: Please enter a valid description.", "error")
        raise ValueError("Invalid description.")
    if len(description) > 249 or len(description) <= 1:
        flash("Error: The description cannot be more than 250 characters or less than 1 Character.", "error")
        logger.info("Description was invalid and got blocked, Description: {}, by user: {}").format(current_user.email,description)
        raise ValueError("Invalid description.")

    # remove any characters that from these: <=":(');>
    description = re.sub(r'[<=:("\');>-]', '', description)

    return description


import torch
import random
import numpy as np
from NeuralNetwork import NN
from control import BASE, policy
from utils import converter
from control import policy
import time
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# self.converter = converter.Converter(self.envname)

class Render(BASE.BasePolicy):
    def __init__(self, p, *args):
        super().__init__(*args)
        self.policy = p

    def rend(self):
        n_p_o = self.env.reset()
        n_o = self.env.reset()
        t = 0
        local = 0
        color = np.random.randint(256, size=3)
        board = 1
        self.env.render(board, color, n_p_o, n_o)
        while t < 1000:
            board = 0
            n_a = self.policy.select_action(n_p_o)
            n_o, n_r, n_d, info = self.env.step(n_a)
            self.env.render(board, color, n_p_o, n_o)
            time.sleep(0.02)
            t = t + 1
            n_d = 0
            if t % 50 == 0:
                n_d = 1
            local = local + 1
            if n_d:
                board = 1
                n_o = self.env.reset()
                # self.env.render(board, color, n_o, n_o)
                print("Episode finished after {} timesteps".format(local+1))
                local = 0
            n_p_o = n_o


# Nikita Akimov
# interplanety@interplanety.org

import bpy
import sys
from .addon import Addon
from .node_common import NodeCommon
from .node_shader_cycles import *
from .node_compositor import *

class NodeShaderNodeGroup(NodeCommon):

    @classmethod
    def node_to_json(cls, node):
        # enumerate nodes in group
        __class__.enumerate(node)
        return super(__class__, cls).node_to_json(node)

    @classmethod
    def _node_to_json_spec(cls, node_json, node):
        node_json['tree_type'] = bpy.context.area.spaces.active.tree_type
        node_json['nodes'] = []
        node_json['links'] = []
        node_json['name'] = node.node_tree.name
        node_json['BIS_addon_version'] = Addon.current_version()
        # nodes in group
        for current_node in node.node_tree.nodes:
            node_class = NodeCommon
            if hasattr(sys.modules[__name__], 'Node' + current_node.bl_idname):
                node_class = getattr(sys.modules[__name__], 'Node' + current_node.bl_idname)
            current_node_json = node_class.node_to_json(current_node)
            node_json['nodes'].append(current_node_json)
        # links
        for link in node.node_tree.links:
            from_node = link.from_node['BIS_node_id']
            to_node = link.to_node['BIS_node_id']
            # for group nodes, reroute and group inputs/output nodes - by number, for other nodes - by identifier
            if link.from_node.type in ['GROUP', 'GROUP_INPUT', 'GROUP_OUTPUT', 'REROUTE']:
                from_output = link.from_node.outputs[:].index(link.from_socket)
            else:
                from_output = link.from_socket.identifier
            if link.to_node.type in ['GROUP', 'GROUP_INPUT', 'GROUP_OUTPUT', 'REROUTE']:
                to_input = link.to_node.inputs[:].index(link.to_socket)
            else:
                to_input = link.to_socket.identifier
            node_json['links'].append([from_node, from_output, to_node, to_input])
        return node_json

    @classmethod
    def _json_to_node_spec(cls, node, node_json):
        node['BIS_addon_version'] = node_json['BIS_addon_version'] if 'BIS_addon_version' in node_json else Addon.node_group_first_version
        # Nodes
        for current_node_in_json in node_json['nodes']:
            node_class = NodeCommon
            if hasattr(sys.modules[__name__], 'Node' + current_node_in_json['bl_idname']):
                node_class = getattr(sys.modules[__name__], 'Node' + current_node_in_json['bl_idname'])
            node_class.json_to_node(node_tree=node.node_tree, node_json=current_node_in_json)
        # links
        for link_json in node_json['links']:
            from_node = __class__._node_by_bis_id(node.node_tree, link_json[0])
            to_node = __class__._node_by_bis_id(node.node_tree, link_json[2])
            # for group nodes and group inputs/output nodes - by number, for other nodes - by identifier
            if isinstance(link_json[1], str):
                from_output = __class__.output_by_identifier(from_node, link_json[1])
            else:
                from_output = from_node.outputs[link_json[1]]
            if isinstance(link_json[3], str):
                to_input = __class__.input_by_identifier(to_node, link_json[3])
            else:
                to_input = to_node.inputs[link_json[3]]
            if from_output and to_input:
                node.node_tree.links.new(from_output, to_input)
        # Frames
        for c_node in node.node_tree.nodes:
            if c_node['parent_str']:
                parent_node = node.node_tree.nodes[c_node['parent_str']]
                c_node.parent = parent_node
                c_node.location += parent_node.location

    @staticmethod
    def enumerate(node, start=0):
        # enumerates all nodes in the group
        # don't enumerate node group itself - not to loose if it is already enumerated by parent node group
        for current_node in node.node_tree.nodes:
            start += 1
            current_node['BIS_node_id'] = start
        return start

    @staticmethod
    def _node_by_bis_id(node_tree, bis_node_id):
        rez = None
        for node in node_tree.nodes:
            if 'BIS_node_id' in node and node['BIS_node_id'] == bis_node_id:
                rez = node
        return rez

class NodeCompositorNodeGroup(NodeShaderNodeGroup):
    pass


#{0.author.mention}
import time
import discord
from discord.ext import commands

bot = commands.Bot(command_prefix='!')

@bot.command()
async def ping(ctx):
    await ctx.send('Pong!')

@bot.command()
async def hello(ctx):
    await ctx.send('Hello!')

@bot.command()
async def slap(ctx, members: commands.Greedy[discord.Member], *, reason='no reason'):
    slapped = ", ".join(x.name for x in members)
    await ctx.send('{} just got slapped for {}'.format(slapped, reason))

@bot.command()
async def info(ctx, *, member: discord.Member):
    """Tells you some info about the member."""
    fmt = '{0} joined on {0.joined_at} and has {1} roles.'
    await ctx.send(fmt.format(member, len(member.roles)))

@info.error
async def info_error(ctx, error):
    if isinstance(error, commands.BadArgument):
        await ctx.send('I could not find that member...')

bot.run('key')


import time
from collections import deque
import sys

# Question 1.3

def bfs(maze, start, goal, queue=None, visited=None, parent=None):
    sys.setrecursionlimit(10000000)
    if queue is None:
        # Creates a queue with start node in
        queue = deque([start])
    if visited is None:
        # Creates a set for visited nodes
        visited = set()
    if parent is None:
        parent = {}
    if not queue:
        return None

    # Creates gives the current variable with the value of the current node
    current = queue.popleft()
    # Adds the current node location the the visited nodes set
    visited.add(current)

    if current == goal:
        # Checks if the current node matches the goal
        path = [current]
        while current in parent:
            current = parent[current]
            # Adds current node to the path list
            path.append(current)
        path.reverse()
        # Reverses the list to get the path in the order of start to finish
        return path

    row, col = current
    # All possible moves from the current location
    for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
        r, c = row + dr, col + dc
        # Checking if moves are possible
        if r < 0 or c < 0 or r >= len(maze) or c >= len(maze[0]) or maze[r][c] == 1 or (r, c) in visited:
            continue
        parent[(r, c)] = current
        queue.append((r, c))
        #print("Total nodes visited ", len(visited))

    return bfs(maze, start, goal, queue, visited, parent)

def main():
   # Takes an imputted filename and coverts it into a 1 and 0 maze form
   filename = input("Enter the name of your file ")
   with open(filename) as f:
                contents = f.read()
                maze = contents.replace('#','1').replace('-', '0')
                maze = [[int(i) for i in line.split()] for line in maze.split('\n')]

# Finds the start and end location of the inputted maze
   for i in range(len(maze[0])):
            if maze[0][i] == 0:
                start = (0,i)

   for i in range(len(maze[0])):
            if maze[len(maze)-1][i] == 0:
                goal = (len(maze)-1,i)
   start_time = time.time()
   path = bfs(maze, start, goal)
   print("--- %s seconds ---" % (time.time() - start_time))
   # Time import used either side of the function call to time just the algorithm speed
   print("The length of the chose path: ", len(path),"And the shorest path: ", path)

if __name__ == "__main__":
 main()