import numpy as np

from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.layers import LSTM, Dense, Dropout, Embedding, Input
from keras.layers.merge import concatenate
from keras.layers.normalization import BatchNormalization
from keras.layers.wrappers import Bidirectional
from keras.models import Model
from keras.optimizers import Nadam

hyperparam_opts = {
    'lstm_size': np.arange(100, 550, 25).tolist(),
    'dense_size': np.arange(100, 550, 25).tolist(),
    'dropout_p': np.around(np.arange(0, 0.8, 0.1), 3).tolist(),
    'rec_dropout_p': np.around(np.arange(0, 0.8, 0.1), 3).tolist(),
    'batch_size': [512],
    'activation': ['relu', 'tanh', 'elu'],
    'bidirectional': [True, False],
    'lstm_depth': [1, 2],
    'dense_depth': [1, 2, 3],
    'batchnorm': [True, False],
    'lr': [0.0005, 0.001, 0.002, 0.005]
}

def train(x1, x2, y, val_x1, val_x2,
          val_y, embeddings, stamp, exp_num, **hyperparams):

    val_weights = np.ones(len(val_y))
    val_weights *= 0.472001959
    val_weights[val_y == 0] = 1.309028344

    n_tokens = embeddings.shape[0]
    embedding_size = embeddings.shape[1]
    maxlen = x1.shape[1]

    lstm_size = hyperparams['lstm_size']
    dense_size = hyperparams['dense_size']
    dropout_p = hyperparams['dropout_p']
    rec_dropout_p = hyperparams['rec_dropout_p']
    batch_size = hyperparams['batch_size']
    activation = hyperparams['activation']
    bidirectional = hyperparams['bidirectional']
    lstm_depth = hyperparams['lstm_depth']
    dense_depth = hyperparams['dense_depth']
    batchnorm = hyperparams['batchnorm']
    lr = hyperparams['lr']

    embedding = Embedding(n_tokens, embedding_size,
                          input_length=maxlen, weights=[embeddings],
                          trainable=False, mask_zero=False)

    lstms = []
    for i in range(lstm_depth):
        return_sequences = i != lstm_depth - 1
        lstm = LSTM(
            lstm_size, dropout=rec_dropout_p,
            recurrent_dropout=rec_dropout_p, return_sequences=return_sequences)
        if bidirectional:
            lstm = Bidirectional(lstm)
        lstms.append(lstm)

    q2_in = Input(shape=[maxlen], dtype='int32')
    q2_vec = embedding(q2_in)
    for lstm in lstms:
        q2_vec = lstm(q2_vec)

    q1_in = Input(shape=[maxlen], dtype='int32')
    q1_vec = embedding(q1_in)
    for lstm in lstms:
        q1_vec = lstm(q1_vec)

    q2_in = Input(shape=[maxlen], dtype='int32')
    q2_vec = embedding(q2_in)
    for lstm in lstms:
        q2_vec = lstm(q2_vec)

    net = concatenate([q1_vec, q2_vec])
    net = Dropout(dropout_p)(net)
    if batchnorm:
        net = BatchNormalization()(net)

    for i in range(dense_depth):
        net = Dense(dense_size, activation=activation)(net)
        net = Dropout(dropout_p)(net)
        if batchnorm:
            net = BatchNormalization()(net)

    y_hat = Dense(1, activation='sigmoid')(net)

    model = Model(inputs=[q1_in, q2_in], outputs=y_hat)
    optim = Nadam(lr=lr)
    model.compile(loss='binary_crossentropy', optimizer=optim, metrics=['acc'])

    early_stopping = EarlyStopping(monitor='val_loss', patience=3)
    ckpt_path = 'params/exp_{}.ckpt'.format(exp_num)
    ckpt = ModelCheckpoint(
        ckpt_path, save_best_only=True, save_weights_only=True)

    hist = model.fit([x1, x2], y,
                     validation_data=([val_x1, val_x2], val_y, val_weights),
                     epochs=200, batch_size=batch_size, shuffle=True,
                     callbacks=[early_stopping, ckpt],
                     class_weight={0: 1.309028344, 1: 0.472001959})

    best_val = min(hist.history['val_loss'])
    return best_val, {'model_fnm': ckpt_path, 'hist': hist.history}


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

# COPYRIGHT (C) 2014-2020 Mitsuo KONDOU.
# This software is released under the MIT License.
# https://github.com/konsan1101
# Thank you for keeping the rules.

import sys
import os
import time
import datetime
import codecs
import glob

import queue
import threading
import subprocess

import pyautogui

# インターフェース
qCtrl_control_kernel     = 'temp/control_kernel.txt'
qCtrl_control_speech     = 'temp/control_speech.txt'
qCtrl_control_vision     = 'temp/control_vision.txt'
qCtrl_control_desktop    = 'temp/control_desktop.txt'
qCtrl_control_bgm        = 'temp/control_bgm.txt'
qCtrl_control_browser    = 'temp/control_browser.txt'
qCtrl_control_player     = 'temp/control_player.txt'
qCtrl_control_chatting   = 'temp/control_chatting.txt'
qCtrl_control_knowledge  = 'temp/control_knowledge.txt'

# 外部プログラム
qExt_program             = '__ext_program.bat'

# qLog,qFunc 共通ルーチン
import  _v5__qLog
qLog  = _v5__qLog.qLog_class()
import  _v5__qFunc
qFunc = _v5__qFunc.qFunc_class()

qPLATFORM       = qFunc.getValue('qPLATFORM'      )
qRUNATTR        = qFunc.getValue('qRUNATTR'       )
qHOSTNAME       = qFunc.getValue('qHOSTNAME'      )
qUSERNAME       = qFunc.getValue('qUSERNAME'      )
qPath_pictures  = qFunc.getValue('qPath_pictures' )
qPath_videos    = qFunc.getValue('qPath_videos'   )
qPath_cache     = qFunc.getValue('qPath_cache'    )
qPath_sounds    = qFunc.getValue('qPath_sounds'   )
qPath_icons     = qFunc.getValue('qPath_icons'    )
qPath_fonts     = qFunc.getValue('qPath_fonts'    )
qPath_log       = qFunc.getValue('qPath_log'      )
qPath_work      = qFunc.getValue('qPath_work'     )
qPath_rec       = qFunc.getValue('qPath_rec'      )

qPath_s_ctrl    = qFunc.getValue('qPath_s_ctrl'   )
qPath_s_inp     = qFunc.getValue('qPath_s_inp'    )
qPath_s_wav     = qFunc.getValue('qPath_s_wav'    )
qPath_s_jul     = qFunc.getValue('qPath_s_jul'    )
qPath_s_STT     = qFunc.getValue('qPath_s_STT'    )
qPath_s_TTS     = qFunc.getValue('qPath_s_TTS'    )
qPath_s_TRA     = qFunc.getValue('qPath_s_TRA'    )
qPath_s_play    = qFunc.getValue('qPath_s_play'   )
qPath_v_ctrl    = qFunc.getValue('qPath_v_ctrl'   )
qPath_v_inp     = qFunc.getValue('qPath_v_inp'    )
qPath_v_jpg     = qFunc.getValue('qPath_v_jpg'    )
qPath_v_detect  = qFunc.getValue('qPath_v_detect' )
qPath_v_cv      = qFunc.getValue('qPath_v_cv'     )
qPath_v_photo   = qFunc.getValue('qPath_v_photo'  )
qPath_v_msg     = qFunc.getValue('qPath_v_msg'    )
qPath_d_ctrl    = qFunc.getValue('qPath_d_ctrl'   )
qPath_d_play    = qFunc.getValue('qPath_d_play'   )
qPath_d_prtscn  = qFunc.getValue('qPath_d_prtscn' )
qPath_d_movie   = qFunc.getValue('qPath_d_movie'  )
qPath_d_upload  = qFunc.getValue('qPath_d_upload' )

qBusy_dev_cpu   = qFunc.getValue('qBusy_dev_cpu'  )
qBusy_dev_com   = qFunc.getValue('qBusy_dev_com'  )
qBusy_dev_mic   = qFunc.getValue('qBusy_dev_mic'  )
qBusy_dev_spk   = qFunc.getValue('qBusy_dev_spk'  )
qBusy_dev_cam   = qFunc.getValue('qBusy_dev_cam'  )
qBusy_dev_dsp   = qFunc.getValue('qBusy_dev_dsp'  )
qBusy_dev_scn   = qFunc.getValue('qBusy_dev_scn'  )
qBusy_s_ctrl    = qFunc.getValue('qBusy_s_ctrl'   )
qBusy_s_inp     = qFunc.getValue('qBusy_s_inp'    )
qBusy_s_wav     = qFunc.getValue('qBusy_s_wav'    )
qBusy_s_STT     = qFunc.getValue('qBusy_s_STT'    )
qBusy_s_TTS     = qFunc.getValue('qBusy_s_TTS'    )
qBusy_s_TRA     = qFunc.getValue('qBusy_s_TRA'    )
qBusy_s_play    = qFunc.getValue('qBusy_s_play'   )
qBusy_v_ctrl    = qFunc.getValue('qBusy_v_ctrl'   )
qBusy_v_inp     = qFunc.getValue('qBusy_v_inp'    )
qBusy_v_QR      = qFunc.getValue('qBusy_v_QR'     )
qBusy_v_jpg     = qFunc.getValue('qBusy_v_jpg'    )
qBusy_v_CV      = qFunc.getValue('qBusy_v_CV'     )
qBusy_d_ctrl    = qFunc.getValue('qBusy_d_ctrl'   )
qBusy_d_inp     = qFunc.getValue('qBusy_d_inp'    )
qBusy_d_QR      = qFunc.getValue('qBusy_d_QR'     )
qBusy_d_rec     = qFunc.getValue('qBusy_d_rec'    )
qBusy_d_play    = qFunc.getValue('qBusy_d_play'   )
qBusy_d_browser = qFunc.getValue('qBusy_d_browser')
qBusy_d_upload  = qFunc.getValue('qBusy_d_upload' )
qRdy__s_force   = qFunc.getValue('qRdy__s_force'  )
qRdy__s_fproc   = qFunc.getValue('qRdy__s_fproc'  )
qRdy__s_sendkey = qFunc.getValue('qRdy__s_sendkey')
qRdy__v_reader  = qFunc.getValue('qRdy__v_reader' )
qRdy__v_sendkey = qFunc.getValue('qRdy__v_sendkey')
qRdy__d_reader  = qFunc.getValue('qRdy__d_reader' )
qRdy__d_sendkey = qFunc.getValue('qRdy__d_sendkey')

class proc_controls:

    def __init__(self, name='thread', id='0', runMode='debug',
        micDev='0', micType='bluetooth', micGuide='on', micLevel='777',  ):

        self.path      = qPath_s_ctrl

        self.runMode   = runMode
        self.micDev    = micDev
        self.micType   = micType
        self.micGuide  = micGuide
        self.micLevel  = micLevel

        self.breakFlag = threading.Event()
        self.breakFlag.clear()
        self.name      = name
        self.id        = id
        self.proc_id   = '{0:10s}'.format(name).replace(' ', '_')
        self.proc_id   = self.proc_id[:-2] + '_' + str(id)
        if (runMode == 'debug'):
            self.logDisp = True
        else:
            self.logDisp = False
        qLog.log('info', self.proc_id, 'init', display=self.logDisp, )

        self.proc_s    = None
        self.proc_r    = None
        self.proc_main = None
        self.proc_beat = None
        self.proc_last = None
        self.proc_step = '0'
        self.proc_seq  = 0

        # 変数
        self.last_text     = ''
        self.last_time     = time.time()

        # 起動条件（kernel.pyと合わせる）
        self.run_vision    = False
        self.run_desktop   = False
        self.run_bgm       = False
        self.run_browser   = False
        self.run_player    = False
        self.run_chatting  = False
        self.run_knowledge = False

        if   (self.runMode == 'debug'):
            self.run_vision    = True
            self.run_desktop   = True
            self.run_bgm       = True
            self.run_browser   = True
            self.run_player    = True
        elif (self.runMode == 'hud'):
            self.run_vision    = True
            self.run_desktop   = True
            self.run_bgm       = True
            self.run_browser   = True
            self.run_player    = True
        elif (self.runMode == 'live'):
            self.run_vision    = True
            self.run_desktop   = True
            self.run_bgm       = True
            self.run_browser   = True
            self.run_player    = True
        elif (self.runMode == 'translator'):
            pass
        elif (self.runMode == 'speech'):
            pass
        elif (self.runMode == 'number'):
            pass
        elif (self.runMode == 'camera'):
            self.run_vision    = True
            self.run_desktop   = True
        elif (self.runMode == 'assistant'):
            self.run_vision    = True
            self.run_desktop   = True
        elif (self.runMode == 'reception'):
            self.run_vision    = True

        # フォース
        self.force_last    = 0

    def __del__(self, ):
        qLog.log('info', self.proc_id, 'bye!', display=self.logDisp, )

    def begin(self, ):
        #qLog.log('info', self.proc_id, 'start')

        self.fileRun = qPath_work + self.proc_id + '.run'
        self.fileRdy = qPath_work + self.proc_id + '.rdy'
        self.fileBsy = qPath_work + self.proc_id + '.bsy'
        qFunc.statusSet(self.fileRun, False)
        qFunc.statusSet(self.fileRdy, False)
        qFunc.statusSet(self.fileBsy, False)

        self.proc_s = queue.Queue()
        self.proc_r = queue.Queue()
        self.proc_main = threading.Thread(target=self.main_proc, args=(self.proc_s, self.proc_r, ))
        self.proc_beat = time.time()
        self.proc_last = time.time()
        self.proc_step = '0'
        self.proc_seq  = 0

        self.proc_main.setDaemon(True)
        self.proc_main.start()

    def abort(self, waitMax=5, ):
        qLog.log('info', self.proc_id, 'stop', display=self.logDisp, )

        self.breakFlag.set()
        chktime = time.time()
        while (not self.proc_beat is None) and ((time.time() - chktime) < waitMax):
            time.sleep(0.25)
        chktime = time.time()
        while (os.path.exists(self.fileRun)) and ((time.time() - chktime) < waitMax):
            time.sleep(0.25)

    def put(self, data, ):
        self.proc_s.put(data)
        return True

    def checkGet(self, waitMax=5, ):
        chktime = time.time()
        while (self.proc_r.qsize() == 0) and ((time.time() - chktime) < waitMax):
            time.sleep(0.10)
        data = self.get()
        return data

    def get(self, ):
        if (self.proc_r.qsize() == 0):
            return ['', '']
        data = self.proc_r.get()
        self.proc_r.task_done()
        return data

    def main_proc(self, cn_r, cn_s, ):
        # ログ
        qLog.log('info', self.proc_id, 'start', display=self.logDisp, )
        qFunc.statusSet(self.fileRun, True)
        self.proc_beat = time.time()

        # 初期設定
        self.proc_step = '1'

        # 待機ループ
        self.proc_step = '5'

        while (self.proc_step == '5'):
            self.proc_beat = time.time()

            # 停止要求確認
            if (self.breakFlag.is_set()):
                self.breakFlag.clear()
                self.proc_step = '9'
                break

            # キュー取得
            if (cn_r.qsize() > 0):
                cn_r_get  = cn_r.get()
                inp_name  = cn_r_get[0]
                inp_value = cn_r_get[1]
                cn_r.task_done()
            else:
                inp_name  = ''
                inp_value = ''

            if (cn_r.qsize() > 1) or (cn_s.qsize() > 20):
                qLog.log('warning', self.proc_id, 'queue overflow warning!, ' + str(cn_r.qsize()) + ', ' + str(cn_s.qsize()))

            # レディ設定
            if (qFunc.statusCheck(self.fileRdy) == False):
                qFunc.statusSet(self.fileRdy, True)

            # ステータス応答
            if (inp_name.lower() == '_status_'):
                out_name  = inp_name
                out_value = '_ready_'
                cn_s.put([out_name, out_value])

            # フォース リセット
            if (qFunc.statusCheck(qRdy__s_force) == False):
                if (self.force_last != 0):
                    self.force_last  = 0
            else:
                if (self.force_last == 0):
                    self.force_last  = time.time()

            # フォース 自動終了（有効１０秒）
            if (qFunc.statusCheck(qRdy__s_force) == True):
                if ((time.time() - self.force_last) > 10):
                    qFunc.statusSet(qRdy__s_force, False)
                    qFunc.statusSet(qRdy__s_fproc, False)
                    self.force_last  = 0

            # 処理
            path = self.path
            path_files = glob.glob(path + '*.txt')
            if (len(path_files) > 0):

                #try:
                if (True):

                    for f in path_files:

                        # 停止要求確認
                        if (self.breakFlag.is_set()):
                            self.breakFlag.clear()
                            self.proc_step = '9'
                            break

                        proc_file = f.replace('\\', '/')

                        if (proc_file[-4:].lower() == '.txt' and proc_file[-8:].lower() != '.wrk.txt'):
                            f1 = proc_file
                            f2 = proc_file[:-4] + '.wrk.txt'
                            try:
                                os.rename(f1, f2)
                                proc_file = f2
                            except Exception as e:
                                pass

                        if (proc_file[-8:].lower() == '.wrk.txt'):
                            f1 = proc_file
                            f2 = proc_file[:-8] + proc_file[-4:]
                            try:
                                os.rename(f1, f2)
                                proc_file = f2
                            except Exception as e:
                                pass

                            # 実行カウンタ
                            self.proc_last = time.time()
                            self.proc_seq += 1
                            if (self.proc_seq > 9999):
                                self.proc_seq = 1
                            seq4 = '{:04}'.format(self.proc_seq)
                            seq2 = '{:02}'.format(self.proc_seq)

                            proc_name = proc_file.replace(path, '')
                            proc_name = proc_name[:-4]

                            work_name = self.proc_id + '.' + seq2
                            work_file = qPath_work + work_name + '.txt'
                            if (os.path.exists(work_file)):
                                os.remove(work_file)

                            if (proc_file[-9:].lower() != '_sjis.txt'):
                                proc_txts, proc_text = qFunc.txtsRead(proc_file, encoding='utf-8', exclusive=False, )
                            else:
                                proc_txts, proc_text = qFunc.txtsRead(proc_file, encoding='shift_jis', exclusive=False, )
                            if (proc_text != '') and (proc_text != '!'):
                                qFunc.txtsWrite(work_file, txts=[proc_text], encoding='utf-8', exclusive=False, mode='w', )

                            if (os.path.exists(work_file)):

                                qFunc.remove(proc_file)

                                # ログ
                                #if (self.runMode == 'debug') or (not self.micDev.isdigit()):
                                #    qLog.log('info', self.proc_id, '' + proc_name + u' → ' + work_name, display=self.logDisp,)

                                # 結果出力
                                if (cn_s.qsize() < 99):
                                    out_name  = '[txts]'
                                    out_value = proc_txts
                                    cn_s.put([out_name, out_value])

                                # ビジー設定
                                if (qFunc.statusCheck(self.fileBsy) == False):
                                    qFunc.statusSet(self.fileBsy, True)
                                    if (str(self.id) == '0'):
                                        qFunc.statusSet(qBusy_s_ctrl, True)

                                    if (self.micType == 'bluetooth') or (self.micGuide == 'on' or self.micGuide == 'sound'):
                                        qFunc.statusWait_false(qBusy_s_inp , 3)

                                # フォース 覚醒
                                force = False
                                if (qFunc.checkWakeUpWord(proc_text) == True):
                                    if (qFunc.statusCheck(qRdy__s_force) == False):
                                        qFunc.statusSet(qRdy__s_force, True)
                                        qFunc.statusSet(qRdy__s_fproc, True)
                                        force = True

                                # フォース 状態
                                if  (qFunc.statusCheck(qRdy__s_force) == False) \
                                and (qFunc.statusCheck(qRdy__s_fproc) == True):
                                    force = True

                                # フォース リセット
                                if (qFunc.statusCheck(qRdy__s_force) == False):
                                    if (self.force_last != 0):
                                        self.force_last  = 0
                                else:
                                    if (self.force_last == 0):
                                        self.force_last  = time.time()

                                # 処理
                                self.proc_last = time.time()
                                self.sub_proc(seq4, proc_file, work_file, proc_name, proc_text, force, cn_s, )

                                # フォース 終了
                                if  (qFunc.statusCheck(qRdy__s_force) == False):
                                    qFunc.statusSet(qRdy__s_fproc, False)

                #except Exception as e:
                #    pass

            # ビジー解除
            qFunc.statusSet(self.fileBsy, False)
            if (str(self.id) == '0'):
                qFunc.statusSet(qBusy_s_ctrl, False)

            # アイドリング
            slow = False
            if (qFunc.statusCheck(qBusy_dev_cpu) == True):
                slow = True

            if (slow == True):
                time.sleep(1.00)
            else:
                if (cn_r.qsize() == 0):
                    time.sleep(0.25)
                else:
                    time.sleep(0.10)

        # 終了処理
        if (True):

            # レディ解除
            qFunc.statusSet(self.fileRdy, False)

            # ビジー解除
            qFunc.statusSet(self.fileBsy, False)
            if (str(self.id) == '0'):
                qFunc.statusSet(qBusy_s_ctrl, False)

            # キュー削除
            while (cn_r.qsize() > 0):
                cn_r_get = cn_r.get()
                cn_r.task_done()
            while (cn_s.qsize() > 0):
                cn_s_get = cn_s.get()
                cn_s.task_done()

            # ログ
            qLog.log('info', self.proc_id, 'end', display=self.logDisp, )
            qFunc.statusSet(self.fileRun, False)
            self.proc_beat = None

    def sub_proc(self, seq4, proc_file, work_file, proc_name, proc_text, force, cn_s, ):

        jp_true = qFunc.in_japanese(proc_text)
        if (proc_text == self.last_text) and ((time.time() - self.last_time) < 15):
            word_true = False
        else:
            word_true = True
            self.last_text = proc_text
            self.last_time = time.time()

        qLog.log('debug', self.proc_id, 'fource = ' + str(force), )

        # 外部プログラム qExt_program
        if  ((proc_text.find(u'プログラム') >= 0) \
        and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0))) \
        or  ((proc_text.find(u'サープ') >= 0) \
        and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0))):
            if (os.name == 'nt'):
                if (os.path.exists(qExt_program)):
                    ext_program = subprocess.Popen([qExt_program, proc_text, ], )
                                  #stdout=subprocess.PIPE, stderr=subprocess.PIPE, )

        # 画面操作
        if (proc_text.find(u'メイン') >= 0) and (proc_text.find(u'スクリーン') >= 0):
            pyautogui.keyDown('ctrlleft')
            pyautogui.keyDown('winleft')
            pyautogui.press('left')
            pyautogui.press('left')
            pyautogui.press('left')
            pyautogui.press('left')
            pyautogui.press('left')
            pyautogui.keyUp('winleft')
            pyautogui.keyUp('ctrlleft')

        if (proc_text.find(u'サブ') >= 0) and (proc_text.find(u'スクリーン') >= 0):
            pyautogui.keyDown('ctrlleft')
            pyautogui.keyDown('winleft')
            pyautogui.press('right')
            pyautogui.keyUp('winleft')
            pyautogui.keyUp('ctrlleft')

        if (proc_text.find(u'スクリーン') >= 0) and (proc_text.find(u'キーボード') >= 0):
            pyautogui.keyDown('ctrlleft')
            pyautogui.keyDown('winleft')
            pyautogui.press('o')
            pyautogui.keyUp('winleft')
            pyautogui.keyUp('ctrlleft')

        # キーボード操作
        if (proc_text[-3:] == u'を入力'):
            qFunc.sendKey(proc_text[:-3],cr=True, lf=False)
        elif (proc_text[-2:] == u'入力'):
            qFunc.sendKey(proc_text[:-2],cr=True, lf=False)

        if (proc_text == u'改行') or (proc_text.lower() == 'enter'):
            pyautogui.press('enter')

        if (proc_text.lower() == 'f1') or (proc_text.lower() == 'f 1'):
            pyautogui.press('f1')
        if (proc_text.lower() == 'f2') or (proc_text.lower() == 'f 2'):
            pyautogui.press('f2')
        if (proc_text.lower() == 'f3') or (proc_text.lower() == 'f 3'):
            pyautogui.press('f3')
        if (proc_text.lower() == 'f4') or (proc_text.lower() == 'f 4'):
            pyautogui.press('f4')
        if (proc_text.lower() == 'f5') or (proc_text.lower() == 'f 5'):
            pyautogui.press('f5')
        if (proc_text.lower() == 'f6') or (proc_text.lower() == 'f 6'):
            pyautogui.press('f6')
        if (proc_text.lower() == 'f7') or (proc_text.lower() == 'f 7'):
            pyautogui.press('f7')
        if (proc_text.lower() == 'f8') or (proc_text.lower() == 'f 8'):
            pyautogui.press('f8')
        if (proc_text.lower() == 'f9') or (proc_text.lower() == 'f 9'):
            pyautogui.press('f9')
        if (proc_text.lower() == 'f10') or (proc_text.lower() == 'f 10'):
            pyautogui.press('f10')
        if (proc_text.lower() == 'f11') or (proc_text.lower() == 'f 11'):
            pyautogui.press('f11')
        if (proc_text.lower() == 'f12') or (proc_text.lower() == 'f 12'):
            pyautogui.press('f12')

        if (proc_text == u'ポーズ') \
        or (proc_text == u'閉じる'):
            pyautogui.press('pause')
        if (proc_text[-3:] == u'を検索'):
            qFunc.sendKey(proc_text[:-3],cr=False, lf=False)
            pyautogui.press('f9')

        if (cn_s.qsize() < 99):

            # システム制御
            if (proc_text.find(u'リセット') >= 0):
                out_name  = 'control'
                out_value = '_reset_'
                cn_s.put([out_name, out_value])
                qFunc.txtsWrite(qCtrl_control_kernel , txts=[out_value], encoding='utf-8', exclusive=True, mode='w', )
                qFunc.txtsWrite(qCtrl_control_vision , txts=[out_value], encoding='utf-8', exclusive=True, mode='w', )
                qFunc.txtsWrite(qCtrl_control_desktop, txts=[out_value], encoding='utf-8', exclusive=True, mode='w', )

            elif ((proc_text.find(u'システム') >= 0) and (proc_text.find(u'終了') >= 0)) \
            or    (proc_text == u'バルス'):
                out_name  = 'control'
                out_value = '_end_'
                cn_s.put([out_name, out_value])
                qFunc.txtsWrite(qCtrl_control_kernel , txts=[out_value], encoding='utf-8', exclusive=True, mode='w', )

            elif (proc_text.find(u'リブート') >= 0) \
              or (proc_text.find(u'再起動') >= 0):
                out_name  = 'control'
                out_value = '_reboot_'
                cn_s.put([out_name, out_value])
                qFunc.txtsWrite(qCtrl_control_kernel , txts=[out_value], encoding='utf-8', exclusive=True, mode='w', )
                self.run_bgm = False
                self.run_browser = False
                self.run_player = False
                self.run_chatting = False
                self.run_knowledge = False

            # 機能制御
            elif (proc_text.find(u'画面') >= 0) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_desktop_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_desktop = True
                qFunc.statusWait_false(qCtrl_control_kernel, 5)
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_vision_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_vision  = True

            elif (proc_text.find(u'画面') >= 0) and (proc_text.find(u'終了') >= 0):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_desktop_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_desktop = False
                qFunc.statusWait_false(qCtrl_control_kernel, 5)
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_vision_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_vision  = False

            elif (proc_text.find(u'ビジョン') >= 0) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_vision_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_vision = True

            elif (proc_text.find(u'ビジョン') >= 0) and (proc_text.find(u'終了') >= 0):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_vision_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_vision = False

            elif (proc_text.find(u'デスクトップ') >= 0) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_desktop_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_desktop = True

            elif (proc_text.find(u'デスクトップ') >= 0) and (proc_text.find(u'終了') >= 0):
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_desktop_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_desktop = False

            elif ((proc_text.find(u'ＢＧＭ') >= 0) or (proc_text.find('BGM') >= 0)) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                # BGM 起動
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_bgm_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_bgm = True
                # BGM 開始
                qFunc.statusWait_false(qCtrl_control_bgm, 5)
                qFunc.txtsWrite(qCtrl_control_bgm ,txts=['_start_'], encoding='utf-8', exclusive=True, mode='w', )

            elif ((proc_text.find(u'ＢＧＭ') >= 0) or (proc_text.find('BGM') >= 0)) \
            and (proc_text.find(u'終了') >= 0):
                # BGM 停止
                qFunc.statusWait_false(qCtrl_control_bgm, 5)
                qFunc.txtsWrite(qCtrl_control_bgm ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                # BGM 終了
                qFunc.statusWait_false(qCtrl_control_bgm, 5)
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_bgm_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_bgm = False

            elif ((proc_text.find(u'ＢＧＭ') >= 0) or (proc_text.find('BGM') >= 0)) \
            and ((proc_text.find(u'停止') >= 0) or (proc_text.find(u'ストップ') >= 0)):
                # BGM 停止
                qFunc.statusWait_false(qCtrl_control_bgm, 5)
                qFunc.txtsWrite(qCtrl_control_bgm ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )

            elif (proc_text.find(u'動画') >= 0) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                # 動画 起動
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_player_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_player = True
                # 動画 メニュー
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=[u'動画メニュー'], encoding='utf-8', exclusive=True, mode='w', )

            elif (proc_text.find(u'動画') >= 0) and (proc_text.find(u'終了') >= 0):
                # 動画 停止
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                # 動画 終了
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_player_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_player = False

            elif (proc_text.find(u'動画') >= 0) \
            and ((proc_text.find(u'停止') >= 0) or (proc_text.find(u'ストップ') >= 0)):
                # 動画 停止
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )

            elif (self.run_player == True) \
            and  (proc_text.find(u'動画') >=0) and (proc_text.find(u'メニュー') >=0):
                # 動画 メニュー
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=[u'動画メニュー'], encoding='utf-8', exclusive=True, mode='w', )

            elif (self.run_player == True) \
            and  (word_true == True) \
            and  (proc_text.lower() >= '01') and (proc_text.lower() <= '09'):
                # 動画 番号で開く
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                qFunc.statusWait_false(qCtrl_control_player, 5)
                qFunc.txtsWrite(qCtrl_control_player ,txts=[proc_text.lower()], encoding='utf-8', exclusive=True, mode='w', )

            elif ((proc_text.find(u'ブラウザ') >= 0) or (proc_text.find(u'ウェブ') >= 0)) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                # ブラウザ 起動
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_browser_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_browser = True
                # ブラウザ 開く
                qFunc.statusWait_false(qCtrl_control_browser, 5)
                qFunc.txtsWrite(qCtrl_control_browser ,txts=['_start_'], encoding='utf-8', exclusive=True, mode='w', )

            elif ((proc_text.find(u'ブラウザ') >= 0) or (proc_text.find(u'ウェブ') >= 0)) \
            and (proc_text.find(u'終了') >= 0):
                # ブラウザ 閉じる
                qFunc.statusWait_false(qCtrl_control_browser, 5)
                qFunc.txtsWrite(qCtrl_control_browser ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )
                # ブラウザ 終了
                qFunc.statusWait_false(qCtrl_control_browser, 5)
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_browser_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_browser = False

            elif ((proc_text.find(u'ブラウザ') >= 0) or (proc_text.find(u'ウェブ') >= 0)) \
            and ((proc_text.find(u'停止') >= 0) or (proc_text.find(u'ストップ') >= 0)):
                # ブラウザ 閉じる
                qFunc.statusWait_false(qCtrl_control_browser, 5)
                qFunc.txtsWrite(qCtrl_control_browser ,txts=['_stop_'], encoding='utf-8', exclusive=True, mode='w', )

            elif ((proc_text.find(u'チャット') >= 0) or (proc_text.find(u'雑談') >= 0)) \
            and ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                # チャット 起動
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_chatting_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_chatting = True

            elif ((proc_text.find(u'チャット') >= 0) or (proc_text.find(u'雑談') >= 0)) \
            and   (proc_text.find(u'終了') >= 0):
                # チャット 終了
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_chatting_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_chatting = False

            elif ((proc_text.find(u'チャット') >= 0) or (proc_text.find(u'雑談') >= 0)) \
            and  ((proc_text.find(u'停止') >= 0) or (proc_text.find(u'ストップ') >= 0)):
                # チャット 終了
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_chatting_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_chatting = False

            elif ((proc_text.find(u'知識') >= 0) or (proc_text.find(u'ナレッジ') >= 0)) \
            and  ((proc_text.find(u'開始') >= 0) or (proc_text.find(u'起動') >= 0)):
                # ナレッジ 開始
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_knowledge_begin_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_knowledge = True

            elif ((proc_text.find(u'知識') >= 0) or (proc_text.find(u'ナレッジ') >= 0)) \
            and   (proc_text.find(u'終了') >= 0):
                # ナレッジ 終了
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_knowledge_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_knowledge = False

            elif ((proc_text.find(u'知識') >= 0) or (proc_text.find(u'ナレッジ') >= 0)) \
            and  ((proc_text.find(u'停止') >= 0) or (proc_text.find(u'ストップ') >= 0)):
                # ナレッジ 終了
                qFunc.txtsWrite(qCtrl_control_kernel ,txts=['_knowledge_end_'], encoding='utf-8', exclusive=True, mode='w', )
                self.run_knowledge = False

            else:

                # インターフェース
                #if (self.run_vision    == True):
                #    qFunc.txtsWrite(qCtrl_control_vision   ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                #if (self.run_desktop   == True):
                #    qFunc.txtsWrite(qCtrl_control_desktop  ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                if (self.run_bgm       == True):
                        qFunc.txtsWrite(qCtrl_control_bgm       ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                if (self.run_browser   == True):
                    if (jp_true == True):
                        qFunc.txtsWrite(qCtrl_control_browser   ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                #if (self.run_player    == True):
                #        qFunc.txtsWrite(qCtrl_control_player    ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                if (self.run_chatting  == True):
                    if (jp_true == True):
                        qFunc.txtsWrite(qCtrl_control_chatting  ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )
                if (self.run_knowledge == True):
                    if (jp_true == True):
                        qFunc.txtsWrite(qCtrl_control_knowledge ,txts=[proc_text], encoding='utf-8', exclusive=True, mode='w', )

        self.last_text = proc_text
        self.last_time = time.time()

if __name__ == '__main__':

    # 共通クラス
    qFunc.init()

    # ログ
    nowTime  = datetime.datetime.now()
    filename = qPath_log + nowTime.strftime('%Y%m%d.%H%M%S') + '.' + os.path.basename(__file__) + '.log'
    qLog.init(mode='logger', filename=filename, )

    # 設定
    controls_thread = proc_controls('controls', '0', )
    controls_thread.begin()

    # ループ
    chktime = time.time()
    while ((time.time() - chktime) < 15):

        res_data  = controls_thread.get()
        res_name  = res_data[0]
        res_value = res_data[1]
        if (res_name != ''):
            print(res_name, res_value, )

        if (controls_thread.proc_s.qsize() == 0):
            controls_thread.put(['_status_', ''])

        time.sleep(0.05)

    time.sleep(1.00)
    controls_thread.abort()
    del controls_thread


import uuid
from typing import Sequence, Union, Optional

from django.utils import timezone
from django.http import Http404
from django.db.models.query import QuerySet
from django.http import HttpResponse
from django.conf import settings

from rest_framework.exceptions import NotFound, ValidationError, PermissionDenied
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.status import HTTP_200_OK, HTTP_201_CREATED
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.generics import CreateAPIView, ListAPIView, get_object_or_404

from . import models, serializers, utils

class UploadImageView(CreateAPIView):
    """
        View for uploading an image and then
        return data about the image that provided by a plan
    """

    permission_classes = [IsAuthenticated,]

    serializer_class = serializers.CreateImageSerializer

    def create(self, request: Request) -> Union[Response, ValidationError]:
        plan_obj: models.Plan = request.user.plan # type: ignore

        serializer = self.get_serializer(data=request.data)

        serializer.is_valid(raise_exception=True)

        img_obj: models.Image = serializer.save() # type: ignore

        data = utils.create_image_data_dict(
            plan_obj.thumbnail_heights,
            img_obj,
            plan_obj.is_expiring_link_generation_provided,
            plan_obj.is_link_to_original_provided,
        )

        return Response(data, status=HTTP_201_CREATED)

class ListImagesView(ListAPIView):
    """
        View that return a list of data about the image that provided by a plan
    """
    permission_classes = [IsAuthenticated,]

    serializer_class = serializers.ImageSerializer

    def get_queryset(self):
        user_id: int = self.request.user.id # type: ignore
        return models.Image.objects.filter(user_id=user_id).order_by('image')

    def list(self, request: Request) -> Union[Response, NotFound]:
        images_qs: QuerySet[models.Image] = self.get_queryset()
        plan_obj: models.Plan = request.user.plan # type: ignore

        if not images_qs:
            raise NotFound("You haven't sent any pictures yet")

        paginated_images_qs: Sequence[models.Image] = self.paginate_queryset(images_qs) # type: ignore
        response_data = []
        for img_obj in paginated_images_qs:
            data = utils.create_image_data_dict(
                plan_obj.thumbnail_heights,
                img_obj,
                plan_obj.is_expiring_link_generation_provided,
                plan_obj.is_link_to_original_provided,
            )
            response_data.append(data)
        return Response(response_data, status=HTTP_200_OK)

class ImageView(APIView):
    """
        View that return an original of image or thumbnail as file
    """
    permission_classes = [IsAuthenticated,]

    def get(self, request: Request, image_title: str, **kwargs) -> Union[HttpResponse, Http404, PermissionDenied]:
        height: Optional[int] = kwargs.get("height", None)
        plan_obj: models.Plan = request.user.plan # type: ignore
        user_id: int = request.user.id # type: ignore

        if height:
            if not height in range(1, 1001):
                raise ValidationError("thumbnail's height must be in range 1 to 1000")
            if not height in plan_obj.thumbnail_heights:
                raise PermissionDenied("Your plan doesn't provide this thumbnail height")
        else:
            if not plan_obj.is_expiring_link_generation_provided:
                raise PermissionDenied("Your plan doesn't provide fetch original image")

        image_queryset: QuerySet[models.Image] = models.Image.objects.all()
        image_obj = get_object_or_404(queryset=image_queryset, user_id=user_id, image="static/images/" + image_title)

        height: Optional[int] = kwargs.get("height", None)

        image_file = image_obj.get_image_file(height=height)

        response = HttpResponse(content_type="image/" + image_file.format)
        response['Content-Disposition'] = 'filename="{}.{}"'.format(
            image_obj.image_name,
            image_file.format
        )
        image_file.save(response, image_file.format)
        # print(response.code)
        return response

class FetchExpiringLinkView(APIView):
    """
        View that return a link to expiring a originall of image or thumbnail
    """
    permission_classes = [IsAuthenticated,]

    def get(
        self, request: Request, image_title: str, seconds: int, **kwargs
    ) -> Union[Response, Http404, PermissionDenied, ValidationError]:

        height: Optional[int] = kwargs.get("height", None)
        plan_obj: models.Plan = request.user.plan # type: ignore
        user_id: int = request.user.id # type: ignore

        if height:
            if not height in range(1, 1001):
                raise ValidationError("thumbnail's height must be in range 1 to 1000")
            if not height in plan_obj.thumbnail_heights:
                raise PermissionDenied("Your plan doesn't provide this thumbnail height")
        else:
            if not plan_obj.is_link_to_original_provided:
                raise PermissionDenied("Your plan doesn't provide fetch original image")

        if not plan_obj.is_expiring_link_generation_provided:
            raise PermissionDenied("Your plan doesn't provide generation expiring links")

        queryset: QuerySet[models.Image] = models.Image.objects.all()
        image_obj = get_object_or_404(queryset=queryset, user_id=user_id, image="static/images/" + image_title)

        exp_link_ser = serializers.CreateExpiringLinkSerializer(
            data={
                "id": uuid.uuid4,
                "link_to_image": settings.HOSTNAME + "/uploads/" + image_obj.image_name,
                "seconds": seconds
            }
        )
        exp_link_ser.is_valid(raise_exception=True)

        exp_link_obj: models.ExpiringLink = exp_link_ser.save() # type: ignore

        return Response({"url": exp_link_obj.get_expiring_link_to_image(height)}, status=HTTP_200_OK)

class ExpiringLinkView(APIView):

    permission_classes = [IsAuthenticated,]

    def get(self, request: Request, image_title: str, uuid: str, **kwargs) -> Union[HttpResponse, Http404, PermissionDenied]:
        height: Optional[int] = kwargs.get("height", None)
        plan_obj: models.Plan = request.user.plan # type: ignore
        user_id: int = request.user.id # type: ignore

        if height:
            if not height in range(1, 1001):
                raise ValidationError("thumbnail's height must be in range 1 to 1000")
            if not height in plan_obj.thumbnail_heights:
                raise PermissionDenied("Your plan doesn't provide this thumbnail height")
        else:
            if not plan_obj.is_link_to_original_provided:
                raise PermissionDenied("Your plan doesn't provide fetch original image")

        if not plan_obj.is_expiring_link_generation_provided:
            raise PermissionDenied("Your plan doesn't provide generation expiring links")

        image_queryset: QuerySet[models.Image] = models.Image.objects.all()
        image_obj = get_object_or_404(queryset=image_queryset, user_id=user_id, image="static/images/" + image_title)

        exp_link_queryset: QuerySet[models.ExpiringLink] = models.ExpiringLink.objects.all()
        exp_link_obj = get_object_or_404(queryset=exp_link_queryset, id=uuid)

        if exp_link_obj.expired_at < timezone.now():
            raise PermissionDenied("Link is expired")

        image_file = image_obj.get_image_file(height=height)

        response = HttpResponse(content_type="image/" + image_file.format)
        response['Content-Disposition'] = 'filename="{}.{}"'.format(
            image_obj.image_name,
            image_file.format
        )
        image_file.save(response, image_file.format)
        return response


from networks import networks
import ipaddress

if __name__ == '__main__':
    # python3 ./026/003_ipcheck/app.py > ./026/003_ipcheck/table.md
    hosts = dict()
    print(f'Сегмент сети | имя подсети | IP-адресация | broadcast-IP')
    print(f'--- | --- | --- | ---')
    for segment_name, subnetworks in networks.items():
        for subnetwork_ip, subnetwork_name in subnetworks.items():
            subnetwork_obj = ipaddress.ip_network(subnetwork_ip)
            print(f'{segment_name} | {subnetwork_name} | {subnetwork_ip} | {subnetwork_obj.broadcast_address} ')


import os
import sys
import argparse
import shutil

from glob import glob
from tqdm import tqdm

from robosat_pink.tiles import tiles_from_csv
from robosat_pink.web_ui import web_ui

def add_parser(subparser):
    parser = subparser.add_parser(
        "subset",
        help="filter images in a slippy map dir using a csv tiles cover",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument("--mode", type=str, default="copy", choices={"copy", "move", "delete"}, help="filtering mode")
    parser.add_argument("--web_ui", action="store_true", help="activate web ui output")
    parser.add_argument("--web_ui_base_url", type=str, help="web ui alternate base url")
    parser.add_argument("--web_ui_template", type=str, help="path to an alternate web ui template")
    parser.add_argument("--dir", type=str, required=True, help="directory to read slippy map tiles from for filtering")
    parser.add_argument("--cover", type=str, required=True, help="csv cover to filter tiles by")
    parser.add_argument("--out", type=str, help="directory to save filtered tiles to (on copy or move mode)")

    parser.set_defaults(func=main)

def main(args):
    tiles = set(tiles_from_csv(args.cover))
    extension = ""

    for tile in tqdm(tiles, desc="Subset", unit="tiles", ascii=True):

        paths = glob(os.path.join(args.dir, str(tile.z), str(tile.x), "{}.*".format(tile.y)))
        if len(paths) != 1:
            print("Warning: {} skipped.".format(tile))
            continue
        src = paths[0]

        try:
            if args.mode in ["copy", "move"]:
                assert args.out
                if not os.path.isdir(os.path.join(args.out, str(tile.z), str(tile.x))):
                    os.makedirs(os.path.join(args.out, str(tile.z), str(tile.x)), exist_ok=True)

                extension = os.path.splitext(src)[1][1:]
                dst = os.path.join(args.out, str(tile.z), str(tile.x), "{}.{}".format(tile.y, extension))

            if args.mode == "move":
                assert os.path.isfile(src)
                shutil.move(src, dst)

            if args.mode == "copy":
                shutil.copyfile(src, dst)

            if args.mode == "delete":
                assert os.path.isfile(src)
                os.remove(src)

        except:
            sys.exit("Error: Unable to process {}".format(tile))

    if args.web_ui:
        template = "leaflet.html" if not args.web_ui_template else args.web_ui_template
        base_url = args.web_ui_base_url if args.web_ui_base_url else "./"
        web_ui(args.out, base_url, tiles, tiles, extension, template)


from torch import nn
import torch.nn.functional as TNF

from ops.basic_ops import ConsensusModule, Identity
from transforms import *
import torch.nn.init as init
from torch.nn.init import normal_, constant_
import senet
import senet_branch

BN_MOMENTUM = 0.1

def initialize_weights(net_l, scale=1.):
    if not isinstance(net_l, list):
        net_l = [net_l]
    for net in net_l:
        for m in net.modules():
            if isinstance(m, nn.Conv2d):
                init.kaiming_normal_(m.weight, a=0, mode='fan_in')
                m.weight.data *= scale  # for residual block
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.Linear):
                init.kaiming_normal_(m.weight, a=0, mode='fan_in')
                m.weight.data *= scale
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.BatchNorm2d):
                init.constant_(m.weight, 1)
                init.constant_(m.bias.data, 0.0)

class STCNet(nn.Module):
    def __init__(self, num_class = 2, num_segments = 8, modality = "RGB",
                 base_model='se_resnext50_32x4d',branch_model='se_resnext50_32x4d', new_length=None,
                 consensus_type='avg', before_softmax=True,
                 dropout=0.5,img_feature_dim=256,
                 crop_num=1, partial_bn=True, print_spec=True):
        super(STCNet, self).__init__()
        self.modality = modality
        self.num_segments = num_segments
        self.reshape = True
        self.before_softmax = before_softmax
        self.dropout = dropout
        self.crop_num = crop_num
        self.consensus_type = consensus_type
        self.img_feature_dim = img_feature_dim  # the dimension of the CNN feature to represent each frame
        if not before_softmax and consensus_type != 'avg':
            raise ValueError("Only avg consensus can be used after Softmax")

        if new_length is None:
            self.new_length = 1 if modality == "RGB" else 5
        else:
            self.new_length = new_length
        if print_spec == True:
            print(("""
    Initializing STCNet with base model: {}.
    STCNet Configurations:
        input_modality:     {}
        num_segments:       {}
        new_length:         {}
        consensus_module:   {}
        dropout_ratio:      {}
        img_feature_dim:    {}
            """.format(base_model, self.modality, self.num_segments, self.new_length, consensus_type, self.dropout, self.img_feature_dim)))

        self._prepare_base_model(base_model)
        self._prepare_branch_model(branch_model) # initialize flow/residual branch

        self.conv_fuse_RGB = nn.Conv2d(2048, 256, 1, 1, bias=True)
        self.conv_fuse_FLOW = nn.Conv2d(2048, 256, 1, 1, bias=True)

        self.cross_down = [nn.Sequential(
                        nn.Conv2d(channels, channels, 1, 1, bias=True),
                        nn.BatchNorm2d(channels),
                        nn.ReLU(inplace=False)).cuda()
                         for channels in [256, 512, 1024, 2048]]
        self.cross_up = [nn.Sequential(
                        nn.Conv2d(channels, channels, 1, 1, bias=True),
                        nn.BatchNorm2d(channels),
                        nn.ReLU(inplace=False)).cuda()
                         for channels in [256, 512, 1024, 2048]]
        self.up_path = [nn.Sequential(
                        nn.Conv2d(channels, channels, 1, 1, bias=True),
                        nn.BatchNorm2d(channels),
                        nn.ReLU(inplace=False)).cuda()
                         for channels in [256, 512, 1024, 2048]]
        self.down_path = [nn.Sequential(
                        nn.Conv2d(channels, channels, 1, 1, bias=True),
                        nn.BatchNorm2d(channels),
                        nn.ReLU(inplace=False)).cuda()
                         for channels in [256, 512, 1024, 2048]]

        self.cls_module = nn.Sequential(
            nn.Conv2d(2048, 256, kernel_size=1, bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.AdaptiveAvgPool2d((1, 1)),
        )
        self.last_fc = nn.Linear(256, num_class)

        self._enable_pbn = partial_bn
        if partial_bn:
            self.partialBN(True)

    def forward(self, RGB_input, FLOW_input):
        sample_len = (3)

        #[64,56,56]
        feature_x0 = self.base_model.layer0(RGB_input.view((-1, sample_len) + RGB_input.size()[-2:]))
        branch_x0 = self.branch_model.layer0(FLOW_input.view((-1, sample_len) + FLOW_input.size()[-2:]))
        #[256,56,56]
        feature_x1 = self.base_model.layer1(feature_x0)
        branch_x1 = self.branch_model.layer1(branch_x0)
        #branch_x1_up = self.cross_up[0](branch_x1)
        #branch_x1_ = self.down_path[0](branch_x1)
        #feature_x1_down = self.cross_down[0](feature_x1)
        #feature_x1_ = self.up_path[0](feature_x1)
        feature_x1_merge = feature_x1 + branch_x1
        branch_x1_merge = branch_x1 + feature_x1
        #[512,28,28]
        feature_x2 = self.base_model.layer2(feature_x1_merge)
        branch_x2 = self.branch_model.layer2(branch_x1_merge)
        #branch_x2_up = self.cross_up[1](branch_x2)
        #branch_x2_ = self.down_path[1](branch_x2)
        #feature_x2_down = self.cross_down[1](feature_x2)
        #feature_x2_ = self.up_path[1](feature_x2)
        feature_x2_merge = feature_x2 + branch_x2
        branch_x2_merge = feature_x2 + branch_x2
        #[1024,14,14]
        feature_x3 = self.base_model.layer3(feature_x2_merge)
        branch_x3 = self.branch_model.layer3(branch_x2_merge)
        #branch_x3_up = self.cross_up[2](branch_x3)
        #branch_x3_ = self.down_path[2](branch_x3)
        #feature_x3_down = self.cross_down[2](feature_x3)
        #feature_x3_ = self.up_path[2](feature_x3)
        feature_x3_merge = feature_x3 + branch_x3
        branch_x3_merge = feature_x3 + branch_x3
        #[2048,7,7]
        feature_x4 = self.base_model.layer4(feature_x3_merge)
        branch_x4 = self.branch_model.layer4(branch_x3_merge)
        # branch_x4_up = self.cross_up[3](branch_x4)
        # feature_x4_down = self.cross_down[3](feature_x4)
        # feature_x4_ = feature_x4 + branch_x4_up
        # branch_x4_ = branch_x4 + feature_x4_down
        #[256,7,7]
        RGB_out = TNF.relu(self.conv_fuse_RGB(feature_x4 + branch_x4), inplace=False)
        B, C, H, W = RGB_out.size()
        RGB_out = RGB_out.view(-1, self.num_segments * C, H, W)

        cls_out = self.cls_module(RGB_out)
        cls_out = cls_out.view(-1, 256)
        cls_out = self.last_fc(cls_out)

        return cls_out#, ret_feature

    def _prepare_STCNet(self, num_class):
        feature_dim = getattr(self.base_model, self.base_model.last_layer_name).in_features
        if self.dropout == 0:
            setattr(self.base_model, self.base_model.last_layer_name, nn.Linear(feature_dim, num_class))
            self.new_fc = None
        else:
            setattr(self.base_model, self.base_model.last_layer_name, nn.Dropout(p=self.dropout))
            if self.consensus_type in ['TRN','TRNmultiscale']:
                # create a new linear layer as the frame feature
                self.new_fc = nn.Linear(feature_dim, self.img_feature_dim)
            else:
                # the default consensus types in STCNet
                self.new_fc = nn.Linear(feature_dim, num_class)

        std = 0.001
        if self.new_fc is None:
            normal_(getattr(self.base_model, self.base_model.last_layer_name).weight, 0, std)
            constant_(getattr(self.base_model, self.base_model.last_layer_name).bias, 0)
        else:
            normal_(self.new_fc.weight, 0, std)
            constant_(self.new_fc.bias, 0)
        return feature_dim

    def _prepare_base_model(self, base_model):

        if 'resnet' in base_model or 'resnext' in base_model:
            self.base_model = getattr(senet, base_model)(num_classes=1000, pretrained='imagenet')
            self.base_model.last_layer_name = 'last_linear'
            self.input_size = 224
            self.input_mean = [0.485, 0.456, 0.406]
            self.input_std = [0.229, 0.224, 0.225]
        else:
            raise ValueError('Unknown base model: {}'.format(base_model))

    def _prepare_branch_model(self, branch_model):

        if 'resnet' in branch_model or 'resnext' in branch_model:
            self.branch_model = getattr(senet, branch_model)(num_classes=1000, pretrained='imagenet')
            self.branch_model.last_layer_name = 'last_linear'
            self.input_size = 224
            self.input_mean = [0.485, 0.456, 0.406]
            self.input_std = [0.229, 0.224, 0.225]
        else:
            raise ValueError('Unknown base model: {}'.format(branch_model))

    def train(self, mode=True):
        """
        Override the default train() to freeze the BN parameters
        :return:
        """
        super(STCNet, self).train(mode)
        count = 0
        if self._enable_pbn:
            print("Freezing BatchNorm2D except the first one.")
            for m in self.base_model.modules():
                if isinstance(m, nn.BatchNorm2d):
                    count += 1
                    if count >= (2 if self._enable_pbn else 1):
                        m.eval()

                        # shutdown update in frozen mode
                        m.weight.requires_grad = False
                        m.bias.requires_grad = False

    def partialBN(self, enable):
        self._enable_pbn = enable

    def get_optim_policies(self):
        first_conv_weight = []
        first_conv_bias = []
        normal_weight = []
        normal_bias = []
        bn = []
        transpose = []

        conv_cnt = 0
        bn_cnt = 0
        for m in self.modules():
            if isinstance(m, torch.nn.Conv2d) or isinstance(m, torch.nn.Conv1d):
                ps = list(m.parameters())
                conv_cnt += 1
                if conv_cnt == 1:
                    first_conv_weight.append(ps[0])
                    if len(ps) == 2:
                        first_conv_bias.append(ps[1])
                else:
                    normal_weight.append(ps[0])
                    if len(ps) == 2:
                        normal_bias.append(ps[1])
            elif isinstance(m, torch.nn.Linear):
                ps = list(m.parameters())
                normal_weight.append(ps[0])
                if len(ps) == 2:
                    normal_bias.append(ps[1])

            elif isinstance(m, torch.nn.BatchNorm1d):
                bn.extend(list(m.parameters()))
            elif isinstance(m, torch.nn.BatchNorm2d):
                bn_cnt += 1
                # later BN's are frozen
                if not self._enable_pbn or bn_cnt == 1:
                    bn.extend(list(m.parameters()))
            elif isinstance(m, torch.nn.ConvTranspose2d):
                transpose.extend(m.parameters())
            elif len(m._modules) == 0:
                if len(list(m.parameters())) > 0:
                    raise ValueError("New atomic module type: {}. Need to give it a learning policy".format(type(m)))

        return [
            {'params': first_conv_weight, 'lr_mult': 5 if self.modality == 'Flow' else 1, 'decay_mult': 1,
             'name': "first_conv_weight"},
            {'params': first_conv_bias, 'lr_mult': 10 if self.modality == 'Flow' else 2, 'decay_mult': 0,
             'name': "first_conv_bias"},
            {'params': normal_weight, 'lr_mult': 1, 'decay_mult': 1,
             'name': "normal_weight"},
            {'params': normal_bias, 'lr_mult': 2, 'decay_mult': 0,
             'name': "normal_bias"},
            {'params': bn, 'lr_mult': 1, 'decay_mult': 0,
             'name': "BN scale/shift"},
            {'params': transpose, 'lr_mult': 1, 'decay_mult': 0,
             'name': 'conv transpose'}
        ]

    @property
    def crop_size(self):
        return self.input_size

    @property
    def scale_size(self):
        return self.input_size * 256 // 224

    def get_augmentation(self):
        #return torchvision.transforms.Compose([GroupMultiScaleCrop(self.input_size, [1, .875, .75, .66]),
        #                                           GroupRandomHorizontalFlip()])
        rrc = RandomResizedCrop(size=224, scale=(0.9, 1), ratio=(3./4., 4./3.))
        rp = RandomPerspective(anglex=3, angley=3, anglez=3, shear=3)
        # Improve generalization
        rhf = RandomHorizontalFlip(p=0.5)
        # Deal with dirts, ants, or spiders on the camera lense
        re = RandomErasing(p=0.5, scale=(0.003, 0.01), ratio=(0.3, 3.3), value=0)
        cj = ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3, hue=(-0.1, 0.1), gamma=0.3)

        return torchvision.transforms.Compose([cj, rrc, rp, rhf])
        #return torchvision.transforms.Compose([GroupMultiScaleCrop(self.input_size, [1, .9,]),
        #                                           GroupRandomHorizontalFlip()])

if __name__ == '__main__':
    import torch
    RGB_input = torch.zeros([1,8,3,224,224])
    FLOW_input = torch.zeros([1,8,3,224,224])
    model = STCNet()
    model = model.cuda()
    print(model)
    RGB_input = RGB_input.cuda()
    FLOW_input = FLOW_input.cuda()
    res = model(RGB_input,FLOW_input)
    print(res.shape)


import pytest
# from django.conf import settings
from django.urls import reverse, resolve

from mhep.assessments.models import Assessment, Library

pytestmark = pytest.mark.django_db

def test_assessments_home():
    assert (
        reverse("assessments:home") == "/"
    )
    assert resolve("/").view_name == "assessments:home"

def test_list_create_assessments(assessment: Assessment):
    assert (
        reverse("assessments:list-create-assessments") == "/api/v1/assessments/"
    )
    assert resolve("/api/v1/assessments/").view_name == "assessments:list-create-assessments"

def test_assessment_detail_update_destroy(assessment: Assessment):
    assert (
        reverse("assessments:retrieve-update-destroy-assessment", kwargs={"pk": assessment.id})
        == f"/api/v1/assessments/{assessment.id}/"
    )
    assert (
        resolve(f"/api/v1/assessments/{assessment.id}/").view_name
        == "assessments:retrieve-update-destroy-assessment"
    )

def test_list_create_libraries():
    assert (
        reverse("assessments:list-create-libraries") == "/api/v1/libraries/"
    )
    assert resolve("/api/v1/libraries/").view_name == "assessments:list-create-libraries"

def test_update_destroy_library(library: Library):
    assert (
        reverse("assessments:update-destroy-library", kwargs={"pk": library.id})
        == f"/api/v1/libraries/{library.id}/"
    )
    assert (
        resolve(f"/api/v1/libraries/{library.id}/").view_name
        == "assessments:update-destroy-library"
    )

def test_create_library_item(library: Library):
    assert (
        reverse("assessments:create-update-delete-library-item", kwargs={"pk": library.id})
        == f"/api/v1/libraries/{library.id}/items/"
    )
    assert (
        resolve(f"/api/v1/libraries/{library.id}/items/").view_name
        == "assessments:create-update-delete-library-item"
    )

def test_update_destroy_library_item(library: Library):
    tag = "SW_01"

    assert (
        reverse("assessments:create-update-delete-library-item", kwargs={"pk": library.id, "tag": tag})
        == f"/api/v1/libraries/{library.id}/items/{tag}/"
    )
    assert (
        resolve(f"/api/v1/libraries/{library.id}/items/{tag}/").view_name
        == "assessments:create-update-delete-library-item"
    )

def test_list_organisations():
    assert (
        reverse("assessments:list-organisations") == "/api/v1/organisations/"
    )
    assert (
        resolve("/api/v1/organisations/").view_name == "assessments:list-organisations"
    )

def test_list_create_organisation_assessments():
    assert (
        reverse("assessments:list-create-organisation-assessments", kwargs={"pk": 1})
        == "/api/v1/organisations/1/assessments/"
    )
    assert (
        resolve("/api/v1/organisations/1/assessments/").view_name
        == "assessments:list-create-organisation-assessments"
    )


import datetime

BITMEX = "bitmex"
MIN_DATE = datetime.date(2016, 5, 14)

URL = "https://s3-eu-west-1.amazonaws.com/public.bitmex.com/data/trade/"

API_URL = "https://www.bitmex.com/api/v1"
MAX_API_RESULTS = 500

uBTC = 0.000001  # 0.001 mXBT

XBT = "XBT"
ETH = "ETH"

XBTUSD = "XBTUSD"
ETHUSD = "ETHUSD"
BCHUSD = "BCHUSD"
LTCUSD = "LTCUSD"
XRPUSD = "XRPUSD"

JANUARY = "F"
FEBRUARY = "G"
MARCH = "H"
APRIL = "J"
MAY = "K"
JUNE = "M"
JULY = "N"
AUGUST = "Q"
SEPTEMBER = "U"
OCTOBER = "V"
NOVEMBER = "X"
DECEMBER = "Z"

MONTHS = [
    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER,
]


#!/usr/bin/env python3
# PYTHON_ARGCOMPLETE_OK

import sys
import os
import argcomplete
import argparse

from errors import FatalError, NotSupportedError
import common
import partition
import binary
import gen_partition
import traces

__version__ = "0.1"

PYTHON2 = sys.version_info[0] < 3  # True if on pre-Python 3
if PYTHON2:
	print("Fatal error: gen_flash_image needs to be run with python version 3")
	exit(1)

class FlashImage(object):

	def __init__(self, sectorSize, flashType):

		self.sectorSize = sectorSize
		if flashType not in ('hyper', 'spi'):
			raise FatalError('Flash type %s not suported. ROM boot loader supports hyper and spi flash type' % flashType)
		self.flashType = flashType

		self.image = bytearray()

		# Partition
		self.partitionTable = None
		self.partitionTableOffset = None
		# Partition 0 : Flash header + Second Stage BootLoader or unic APP
		self.ssbl = None

	def getCurrentSize(self):
		return len(self.image)

	def appendBootloader(self, elf, encrypt = False, aesKey = None, aesIv = None):
		self.ssbl = binary.SSBL(flashType = self.flashType, elf = elf, encrypt = encrypt, aesKey = aesKey,
		                        aesIv = aesIv)
		self.image = self.ssbl.dump()
		self.partitionTableOffset = self.ssbl.partitionTableOffset
		return self.partitionTableOffset

	def appendPartitionTable(self, partitionTable):
		self.partitionTable = partitionTable

		# Check if a boot loader has been added previously, if not, generating empty boot loader
		if len(self.image) == 0:
			traces.info("Warning: Empty boot loader partition. GAP will not be able to boot from flash.")
			self.ssbl = binary.SSBL(flashType = self.flashType)
			self.image += self.ssbl.dump()

		self.image += self.partitionTable.to_binary()

	def writeRAWImage(self, outputPath):
		# Creating folders if necessary
		try:
			os.makedirs(os.path.realpath(os.path.dirname(outputPath)))
		except FileExistsError:
			pass

		with open(outputPath, 'wb') as file:
			file.write(self.image)

	def writeStimuli(self, outputPath):
		# Warning: not tested!
		# Creating folders if necessary
		try:
			os.makedirs(os.path.dirname(outputPath))
		except:
			pass

		with open(outputPath, 'w') as file:
			if self.flashType == 'mram':
				last_bytes = len(self.buff) & 0x7
				for i in range(0, 8 - last_bytes):
					self.__appendByte(0)
				for i in range(0, len(self.buff) >> 3):
					value = (self.buff[i * 8 + 7] << 56) + (self.buff[i * 8 + 6] << 48) + (
							self.buff[i * 8 + 5] << 40) + (self.buff[i * 8 + 4] << 32) + (
							        self.buff[i * 8 + 3] << 24) + (self.buff[i * 8 + 2] << 16) + (
							        self.buff[i * 8 + 1] << 8) + self.buff[i * 8]
					dumpLongToSlm(file, i, value)
			elif self.flashType == 'hyper':
				if len(self.buff) & 1 != 0:
					self.__appendByte(0)
				for i in range(0, len(self.buff) >> 1):
					value = (self.buff[i * 2 + 1] << 8) + self.buff[i * 2]
					dumpShortToSlm(file, i, value)
			elif self.archi == 'vivosoc2' or self.archi == 'fulmine':
				if len(self.buff) % 4 != 0:
					for i in range(0, 4 - (len(self.buff) % 4)):
						self.buff.append(0)
				for i in range(0, len(self.buff), 4):
					dumpByteToSlm(file, i, self.buff[i + 3])
					dumpByteToSlm(file, i + 1, self.buff[i + 2])
					dumpByteToSlm(file, i + 2, self.buff[i + 1])
					dumpByteToSlm(file, i + 3, self.buff[i + 0])
			else:
				for i in range(0, len(self.buff)):
					dumpByteToSlm(file, i, self.buff[i])

def appendArgs(parser: argparse.ArgumentParser) -> None:
	"""
	Append specific module arguments.

	:param parser:
	:type parser: argparse.ArgumentParser
	"""

	# Bootloader
	parser.add_argument('--boot-loader',
	                    type = argparse.FileType('rb'), required = True,
	                    help = """Boot loader or unic application in elf format.
		                           In case of Gap boot from flash, this program will be loaded into memories and will be executed by the FC.""")

	# Partition table
	parser.add_argument('--partition-table', '-t',
	                    default = None, type = argparse.FileType('rb'), required = False,
	                    dest = 'partitionTable',
	                    help = """Partition table in binary or csv format.
	                    If the partition table is not mentioned, a typical partition table is generated with both filesystem partitions readfs and LittleFS.""")

	# Partition images
	parser.add_argument('--partition', '-p', metavar = 'partition-name partition-image',
	                    default = {},
	                    action = partition.PartitionNameFilenamePairAction,
	                    help = 'The name of the partition and its image file.')

	# Flash block size
	parser.add_argument('--block-size', '-b',
	                    required = True,
	                    type = common.argToInt, dest = 'blockSize',
	                    help = "Erasable flash sectore size. useful for aligning partitions.")

	# Flash size
	parser.add_argument('--flash-size', '-s',
	                    required = True,
	                    type = common.argToInt, dest = 'flashSize',
	                    help = "Flash size.")

	# Flash type
	parser.add_argument('--flash-type',
	                    required = True,
	                    choices = ('hyper', 'spi'), dest = 'flashType',
	                    help = "Flash type.")

	# Output
	parser.add_argument('-o',
	                    dest = 'output', default = 'flash.img',
	                    help = 'RAW image output')

def operationFunc(args):
	traces.verbose = args.verbose
	traces.info('Build flash image')

	flashImage = FlashImage(sectorSize = args.blockSize, flashType = args.flashType)

	#
	# Bootloader
	#
	endOfSSBLOffset = flashImage.appendBootloader(elf = args.boot_loader)
	traces.info("Partition boot loader size: 0x%X" % endOfSSBLOffset)

	#
	# Partition table
	#
	traces.info("\nGenerating partition table:")
	# Check if the partition table is lower than free space in current SSBL flash sector
	if (endOfSSBLOffset + partition.MAX_PARTITION_TABLE_SIZE) > binary.align(endOfSSBLOffset, args.blockSize):
		partitionTableOffset = binary.align(endOfSSBLOffset, args.blockSize)
		traces.info(
			"No free space to store partition table at the end of the SSBL partition, adding padding untill the next sector 0x%X" % partitionTableOffset)
		flashImage.image.padToOffset(partitionTableOffset)
	else:
		partitionTableOffset = endOfSSBLOffset

	traces.info("Partition table offset: 0x%X" % partitionTableOffset)

	if args.partitionTable:
		traces.infoWithoutNewLine('Open partition table: ')
		tableInput = args.partitionTable.read()
		if gen_partition.isBinaryPartitionTable(tableInput):
			# Binary format
			traces.info('Binary table format')
			table = gen_partition.PartitionTable.from_binary(tableInput)

		else:
			# CSV Format
			traces.info('CSV table format')

			try:
				tableInput = tableInput.decode()
			except UnicodeDecodeError:
				raise InputError(
					'"%s" input file must be a CSV text file or partition table binary.' % args.partitionTable.name)

			traces.info('Parsing CSV input...')
			table = gen_partition.PartitionTable.from_csv(tableInput, partitionTableOffset = partitionTableOffset,
			                                              sectorSize = args.blockSize, md5Sum = True)

	else:
		# Auto partitioning
		traces.info('Partition table was not provided, generating generic table.')
		table = gen_partition.PartitionTable(md5Sum = True)
		offset = partitionTableOffset + partition.MAX_PARTITION_TABLE_SIZE

		if "readfs" in args.partition.keys():
			traces.info("Creating ReadFS partition")
			readFSSize = os.path.getsize(args.partition['readfs'].name)
			traces.info("ReadFS image size: 0x%X" % readFSSize)
			readFSPartition = partition.PartitionDefinition(
				name = 'readfs',
				type = partition.DATA_TYPE,
				subtype = partition.READFS_SUBTYPE,
				size = readFSSize,
				offset = binary.align(offset, args.blockSize))
			table.append(readFSPartition)
			offset = readFSPartition.offset + readFSPartition.size

		#
		# LittleFS partition
		#
		lfsOffset = binary.align(offset, args.blockSize)
		if "lfs" in args.partition.keys():
			# LittleFS image from CLI
			traces.info("Creating LittleFS partition")
			lfsSize = os.path.getsize(args.partition['lfs'].name)
			traces.info("LittleFS image size: 0x%X" % lfsSize)
		else:
			# No LittleFS image, use of remaining free space
			lfsSize = args.flashSize - lfsOffset
			traces.info("Creating an empty LittleFS partition, using the rest of the flash space: 0x%X" % lfsSize)

		lfsPartition = partition.PartitionDefinition(
			name = 'lfs',
			type = partition.DATA_TYPE,
			subtype = partition.LFS_SUBTYPE,
			size = lfsSize,
			offset = binary.align(offset, args.blockSize))
		table.append(lfsPartition)
		offset = lfsPartition.offset + lfsPartition.size

	traces.info('Verifying table...')
	traces.info(table.to_csv(simple_formatting = False))
	table.verify(partitionTableOffset = partitionTableOffset, flashSectorSize = args.blockSize, flashSize = args.flashSize)

	flashImage.appendPartitionTable(table)

	#
	# Writting partition images
	#
	traces.info("Dumping partition image::")
	for p in sorted(table, key = lambda x: x.offset):
		if p.name in args.partition.keys():
			traces.info("%s partition [%s]" % (p.name, args.partition[p.name].name))
			flashImage.image.padToOffset(p.offset)
			flashImage.image += args.partition[p.name].read()

		else:
			traces.info("%s partition [None]" % p.name)

	# add padding to finish on 4 bytes align
	flashImage.image.padToOffset(binary.align(flashImage.getCurrentSize(), 4))

	#
	# Write output
	#

	traces.info("\nWritting output image to %s, size %uKB." %(args.output, flashImage.getCurrentSize() / 1024))
	flashImage.writeRAWImage(args.output)

def main(custom_commandline = None):
	"""
	Main
	function
	for build Flash image

	custom_commandline - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments
	as strings.Arguments and their values need to be added as individual items to the list e.g."-b 115200" thus
	becomes['-b', '115200'].
	"""

	parser = argparse.ArgumentParser(
		description = 'Build a Gap flash image from binary files, partition table and partition images - v%s' % __version__,
		prog = 'gen_flash_image',
		fromfile_prefix_chars = '@')

	common.appendCommonOptions(parser)
	appendArgs(parser)

	argcomplete.autocomplete(parser)
	args = parser.parse_args(custom_commandline)

	try:
		operationFunc(args)
	finally:
		try:  # Clean up AddrFilenamePairAction files
			for address, argfile in args.addr_filename:
				argfile.close()
		except AttributeError:
			pass

if __name__ == '__main__':
	try:
		main()
	except FatalError as e:
		print('\nA fatal error occurred: %s' % e)
		sys.exit(2)


"""
@author: Vincent Bonnet
@description : Client implementation to communicates with the server
"""

import functools
from multiprocessing.managers import SyncManager

class ServerQueueManager(SyncManager):
    pass

ServerQueueManager.register('get_job_queue')
ServerQueueManager.register('get_result_queue')

class ClientDispatcher:
    def __init__(self, client):
        self.client = client
        commands = self.client.run('get_commands')
        if not commands:
            return

        for command in commands:
            if hasattr(self, command):
                raise ValueError(f'in register_cmd() {command} already registered')

            func = functools.partial(self.run, command)
            setattr(self, command, func)

    def run(self, command_name, **kwargs):
        return self.client.run(command_name, **kwargs)

class Client:
    '''
    Client to connect and dispatch commands to a Server
    '''
    def __init__(self, name = "noname"):
        self._manager = None
        self._job_queue = None
        self._result_queue = None
        self._name = name # name of the client for server log

    def __del__(self):
        self.disconnect_from_server()

    def is_connected(self):
        return self._manager is not None

    def get_dispatcher(self):
        return ClientDispatcher(self)

    def connect_to_server(self, ip="127.0.0.1", port=8013, authkey='12345'):
        try:
            self._manager = ServerQueueManager(address=(ip, port), authkey=bytes(authkey,encoding='utf8'))
            self._manager.connect()
            self._job_queue = self._manager.get_job_queue()
            self._result_queue = self._manager.get_result_queue()
            print('Client connected to %s:%s' % (ip, port))
            return True
        except Exception as e:
            self._manager = None
            self._job_queue = None
            self._result_queue = None
            print('Exception raised by client : ' + str(e))
            return False

    def run(self, command_name, **kwargs):
        if self.is_connected():
            self._job_queue.put((command_name, self._name, kwargs))
            result = self._result_queue.get(block=True)
            return result
        return None

    def disconnect_from_server(self):
        if self.is_connected():
            self._job_queue.put(('close_server', self._name))


#!/usr/bin/env python3
import os
import re
from os import listdir
from os.path import isfile, join

import subprocess
import sys,json,uuid
import numpy as np
from collections import defaultdict

main = ["total", "modules", "resources" ]
net = [ "pnet", "dtau", "dmet" , "other" ]
type = dict()
type["pnet"] = ["BoostedJetONNXJetTagsProducer" , "ParticleNetSonicJetTagsProducer", "DeepFlavourONNXJetTagsProducer", "DeepDoubleXONNXJetTagsProducer" ]
type["dtau"] = ["DeepTauIdSonicProducer", "DeepTauId"]
type["dmet"] = ["DeepMETSonicProducer", "DeepMETProducer"]
type["other"] = ["other"]

def parse(fjson):

    data = json.load(open(fjson))
    nev = data["total"]["events"]

    rtime = dict()
    ctime = dict()
    for n in net:
        rtime[n] = 0
        ctime[n] = 0

    for m in data["modules"]:
        for n in net:
            if m["type"] in type[n]:
                rtime[n] += m["time_real"]
                ctime[n] += m["time_thread"]

    trtime = data["total"]["time_real"]
    tctime = data["total"]["time_thread"]

    # print("%s %f %f (%.2f%%) %f (%.2f%%) %f (%.2f%%) %f (%.2f%%)" % (cwd, trtime/nev,
    #                                                                   rtime['pnet']/nev, rtime['pnet']/trtime*100,
    #                                                                   rtime['dtau']/nev, rtime['dtau']/trtime*100,
    #                                                                   rtime['dmet']/nev, rtime['dmet']/trtime*100,
    #                                                                   rtime['other']/nev, rtime['other']/trtime*100) )
    return trtime/nev, rtime['pnet']/nev, rtime['dtau']/nev, rtime['dmet']/nev, rtime['other']/nev

dir = subprocess.check_output('ls q* -1d', shell=True).split()
sc = np.zeros(len(dir))
for c,d in zip(sc,dir):
    c = int(d[1:])

rtime = defaultdict(list)
pnet = defaultdict(list)
dtau = defaultdict(list)
dmet = defaultdict(list)
other = defaultdict(list)

for d in dir:
    sc = int(d[1:])
    print (d, sc)
    #outs = [ f for f in listdir(d) if f.endswith( ".json".encode()) ]
    outs = [ f for f in listdir(d) if f.startswith("result_sonic_".encode()) ]

    for out in outs:
        res = parse( join(d, out) )

        rtime[sc]  += [ res[0]  ]
        pnet[sc]   += [ res[1]  ]
        dtau[sc]   += [ res[2] ]
        dmet[sc]   += [ res[3] ]
        other[sc]  += [ res[4] ]

output = {
    "rtime": rtime,
    "pnet": pnet,
    "dtau": dtau,
    "dmet": dmet,
    "other": other
}

# write out
CWD = os.getcwd().split('/')[-1]
result = json.dumps(output,sort_keys=False,indent=4)
oname = "timers_{}.json".format(CWD)
with open(oname,'w') as ofile:
    ofile.write(result)


import json
import logging
import os

from discord import Embed
from discord.ext import commands
from dotenv import load_dotenv

import api
import interface
from api import request

load_dotenv(verbose=True, override=True)

with open("src/resources/box.json", encoding="utf-8") as f:
    box_types = json.load(f)

def describe_box(box: dict, is_premium: bool) -> str:
    key = box.get("key_premium", box["key"]) if is_premium else box["key"]
    max_point = max(p["point"] for p in box["probabilities"])
    return "{emoji} **{name}** (열쇠 {key}개 필요, 최대 {max_point}P)".format(
        **dict(box, key=key, max_point=max_point)
    )

def box_open_view(box: dict, is_premium: bool, key_count: int) -> Embed:
    embed = Embed(title=box["name"]).set_thumbnail(url=box["image"])

    # 필요 열쇠량
    description = f"열쇠 {box['key']}개 필요"
    if "key_premium" in box.keys():
        description += f" (프리미엄: {box['key_premium']}개 필요)"

    # 확률 분포
    description += "\n\n이 상자를 열면..\n"
    description += "\n".join(
        [
            f"{100 * prob['prob']:.0f}%의 확률로 {prob['point']}P 획득"
            for prob in box["probabilities"]
        ]
    )

    # 사용자에게 안내
    key = box.get("key_premium", box["key"]) if is_premium else box["key"]
    description += f"\n\n열쇠 {key}개를 사용해서 **{box['name']}**를 열어볼까요?\n"
    description += f"(현재 열쇠 **{key_count}개**를 가지고 있어요!)"

    embed.description = description
    return embed

class User(commands.Cog):
    guild_whitelist = [
        int(guild_id.strip()) for guild_id in os.getenv("GUILD_WHITELIST").split(",")
    ]
    logger = logging.getLogger("lara.user")

    def __init__(self, bot):
        self.bot = bot

        premium_role_env = os.getenv("PREMIUM_ROLE")
        if premium_role_env is None:
            raise ValueError("Environment variable PREMIUM_ROLE is not defined")
        self.premium_role = int(premium_role_env)

        subscriber_role_env = os.getenv("SUBSCRIBER_ROLE")
        if subscriber_role_env is None:
            raise ValueError("Environmant variable SUBSCRIBER_ROLE is not defined")
        self.subscriber_role = int(subscriber_role_env)

    async def cog_check(self, ctx):
        return ctx.guild is not None and ctx.guild.id in self.guild_whitelist

    async def cog_command_error(self, ctx, error):
        if isinstance(error, commands.CheckFailure):
            await ctx.send("⚠ **팀 크레센도 디스코드**에서만 사용 가능한 명령어입니다.")
            return

        self.logger.error(str(error))

    def is_premium(self, ctx: commands.Context) -> bool:
        return ctx.guild.get_role(self.premium_role) in ctx.author.roles

    @commands.command(
        "출석", aliases=["출석체크", "출첵", "ㅊ"], brief="팀 크레센도 디스코드 서버에 출석하고 열쇠를 얻습니다.",
    )
    async def attend(self, ctx):
        user, _ = await request("get", f"/discords/{ctx.author.id}")
        if len(user) == 0:
            return await ctx.send(
                f"""{ctx.author.mention}, ⚠ 팀 크레센도 FORTE에 가입하지 않은 계정입니다.
출석체크 보상으로 POINT를 지급받기 위해선 FORTE 가입이 필요합니다.
하단의 링크에서 Discord 계정 연동을 통해 가입해주세요.
> https://forte.team-crescendo.me/login/discord"""
            )

        try:
            key_count = await api.post_attendace(ctx.author.id)
        except api.AttendanceError as e:
            self.logger.log(e.level, f"{ctx.author.id} attend failure, {e.status}")
            return await ctx.send(f"{ctx.author.mention}, {e}")

        self.logger.info(f"{ctx.author.id} attend success, key_count = {key_count}")
        progress = key_count * "🔑" + (10 - key_count) * "❔"
        return await ctx.send(
            f"""{ctx.author.mention}, ⚡ **출석 체크 완료!**

{progress}

모은 열쇠로 상자를 열면 POINT를 받을 수 있습니다. (`라라야 상자` 입력)

※ `💎Premium` 역할을 갖고 있으면 상자를 열 때 필요한 열쇠가 줄어듭니다. (<#748566390528671774> 확인)"""
        )

    async def select_box(self, ctx: commands.Context) -> str:
        """
        사용자의 입력에 따라 TimeoutError 또는 KeyError가 발생할 수 있습니다.
        """
        is_premium = self.is_premium(ctx)
        description = "\n".join(
            describe_box(box, is_premium) for box in box_types.values()
        )
        embed = Embed(title="어떤 상자를 열어볼까요?", description=description)

        prompt = await ctx.send(ctx.author.mention, embed=embed)
        emoji_map = {box["emoji"]: key for key, box in box_types.items()}
        user_input = await interface.input_emojis(ctx, prompt, [*emoji_map.keys(), "❌"])
        return emoji_map[user_input]

    @commands.command("상자", brief="열쇠를 사용하여 상자를 열고 확률적으로 포인트를 받습니다.")
    async def unpack_box(self, ctx):
        key_count = await api.get_key_count(ctx.author.id)
        if key_count == 0:
            await ctx.send(
                f"{ctx.author.mention}, 상자를 열 수 있는 열쇠가 없습니다.\n"
                + "`라라야 출석` 명령어로 매일 열쇠를 하나씩 얻을 수 있습니다."
            )
            return

        box_type = await self.select_box(ctx)

        prompt = await ctx.send(
            ctx.author.mention,
            embed=box_open_view(box_types[box_type], self.is_premium(ctx), key_count),
        )
        if await interface.is_confirmed(ctx, prompt):
            await prompt.edit(
                content=f"{ctx.author.mention}, **{box_types[box_type]['name']}**를 여는 중...",
                embed=None,
            )
            try:
                point, remaining_keys = await api.unpack_box(
                    ctx.author.id, box_type, self.is_premium(ctx)
                )
                self.logger.info(
                    f"{ctx.author.id} unpack success, {box_type}, point = {point}, key_count = {remaining_keys}"
                )
                await ctx.send(
                    f"{ctx.author.mention}, 상자를 열어 **{point}P**를 얻었습니다! (남은 열쇠: **{remaining_keys}개**)"
                )
            except api.AttendanceError as e:
                self.logger.log(e.level, f"{ctx.author.id} unpack failure, {e.status}")
                return await ctx.send(f"{ctx.author.mention}, {e}")

    @commands.command("구독", brief="전용 구독자 역할을 지급받거나 반환합니다.")
    async def subscribe(self, ctx):
        role = ctx.guild.get_role(self.subscriber_role)
        if role is None:
            return await ctx.send("⚠ 구독자 역할을 찾을 수 없습니다.")

        if role not in ctx.author.roles:
            await ctx.author.add_roles(role)
            await ctx.send(f"{ctx.author.mention}, 구독자 역할을 지급했습니다.")
        else:
            await ctx.author.remove_roles(role)
            await ctx.send(f"{ctx.author.mention}, 구독자 역할을 회수했습니다.")

def setup(bot):
    bot.add_cog(User(bot))


import os
import shutil
import zipfile
from os.path import join, getsize

def zip_file(src_dir):
    # 压缩指定文件夹
    zip_name = src_dir + '.zip'
    # src_dir: 压缩的文件夹路径；zip_name: 压缩后zip文件的路径及名称
    z = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
    for dirpath, dirnames, filenames in os.walk(src_dir):
        fpath = dirpath.replace(src_dir,'')
        fpath = fpath and fpath + os.sep or ''
        for filename in filenames:
            z.write(os.path.join(dirpath, filename), fpath + filename)
            print ('==压缩成功==')
    z.close()

def unzip_file(zip_src, dst_dir):
    #zip_src: zip文件的全路径，dst_dir: 要解压到的目的文件夹
    r = zipfile.is_zipfile(zip_src)
    if r:
        fz = zipfile.ZipFile(zip_src, 'r')
        for file in fz.namelist():
            fz.extract(file,dst_dir)
    else:
        print("This is not zip")

"""
  python其他操作文件方法：
    1.剪切（移动）文件到指定目录
      shutil.move(filename, dst_dir)
    2.删除文件夹
      shutil.rmtree(src_dir)
    3.删除指定文件
      os.remove(file_src)
    4.新建文件夹
      os.mkdir(dst_dir)
    5.遍历文件夹
      for filename in os.listdir(src_dir)
    6.复制文件
      shutil.copyfile(src_file,dst_file)
    7.获取文件夹大小
      def get_dir_size(dir_path):
        size = 0L
        for root, dirs, files in os.walk(dir_path):
          size += sum([getsize(join(root, name)) for name in files])
        return size
      可以根据文件大小做出不同的判断：
        file_size = get_dir_size(DATA_PATH)
        max_size = file_size /1024/ 1024 #获取以MB为单位的值
        if max_size < 100:
          pass

"""


from datetime import datetime, timedelta
import threading
import time, json
from app.api import helpers
from elasticsearch import Elasticsearch

import celery
import os
import pandas as pd
import feather
import multiprocessing

from flask import request, Blueprint
from app.api.workers import arima_forecast, holt_winters, forecast

receiver = Blueprint('receiver', __name__)

def insert_sub_task(payload):
    result = helpers.post_request('http://localhost:5002/api/v1/subtasks/add', json.dumps(payload))
    return result

def get_initial_data(index, field, task_name, task_id, field_name, field_value, timestamp, count, filename):
    details = helpers.query_elastic_details(es, index, field)
    initial_sub_task_data = pd.DataFrame(columns=['Datetime', 'Count'])

    overall_datetime = []
    overall_count = []
    for _details in details['aggregations']['3']['buckets'][field]["2"]['buckets']:
        overall_datetime.append(datetime.strptime(_details['key_as_string'], '%Y-%m-%dT%H:%M:%S.%fZ'))
        overall_count.append(_details['doc_count'])

    overall_datetime.append(timestamp)
    overall_count.append(int(count))

    initial_sub_task_data['Datetime'] = overall_datetime
    initial_sub_task_data['Count'] = overall_count

    helpers.check_file("app/data/{}/{}".format(task_name, filename), initial_sub_task_data)
    sub_task = insert_sub_task({
        'task_id': task_id,
        'task_field_name': field_name.strip(),
        'task_field_value': field_value.strip(),
        'filename': filename
    })

    return sub_task['sub_task_id']

def check_previous_prediction(timestamp, count, subtask_id):
    check_result = helpers.get_request('http://localhost:5002/api/v1/results/{}'.format(subtask_id))

    payload = {
        'result_id': check_result['result_id'],
        'count': count,
        'hour': timestamp.hour,
        'day': helpers.convert_weekday(timestamp.weekday()),
        'minute': timestamp.minute
    }

    if check_result is not None:
        update_result = helpers.post_request('http://localhost:5002/api/v1/results/update', json.dumps(payload))

    return update_result

def process_prediction(sub_task_id, prediction_schedule, interval_type, timestamp, task_id, filename, source, task_name):
    # inserting of initial result
    result = helpers.get_request('http://localhost:5002/api/v1/results/add/{}'.format(sub_task_id))
    result_id = result['result_id']

    predicted_date = ''
    if interval_type == 1:
        predicted_date = timestamp + timedelta(minutes=prediction_schedule)

    model_data = helpers.get_request('http://localhost:5002/api/v1/taskmodels/{}'.format(task_id))

    model_list = []
    for _model in model_data['data']:
        model_name = _model['name'].lower().strip()
        if model_name == 'arima':
            arima_forecast.predict(sub_task_id, result_id, _model['model_id'], filename, predicted_date, source,
                                   task_name)
        # elif model_name == 'holt_winter':
        #     holt_winters.predict.delay(sub_task_id, result_id, _model['model_id'], filename, predicted_date, source, task_name)

    return model_list

def predict(task_queue):
    while not task_queue.empty():
        data = task_queue.get()
        source = data[0]
        task_name = data[1]
        field_name = data[2]
        field_value = data[3]
        timestamp = data[4]
        count = data[5]
        check_task_name = data[6]

        result = dict()

        filename = ''
        sub_task_id = ''

        helpers.check_dir("app/data/{}".format(task_name))
        check_sub_task = helpers.post_request('http://localhost:5002/api/v1/subtasks/exists', json.dumps({
            'task_id': check_task_name['task_id'],
            'task_field_name': field_name,
            'task_field_value': field_value
        }))
        timestamp = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')

        if check_sub_task['result']:
            filename = check_sub_task['filename']
            df = feather.read_dataframe("app/data/{0}/{1}".format(task_name, check_sub_task['filename']))
            df2 = pd.DataFrame({"Datetime": [timestamp], "Count": [count]})
            df = df.append(df2, ignore_index=True)
            os.remove("app/data/{0}/{1}".format(task_name, check_sub_task['filename']))
            df.to_feather("app/data/{0}/{1}".format(task_name, check_sub_task['filename']))
            sub_task_id = check_sub_task['sub_task_id']
            #check_previous_prediction(timestamp, count, check_sub_task['sub_task_id'])
            process_prediction(sub_task_id, check_task_name['prediction_schedule'], check_task_name['interval_type'],
                               timestamp, check_task_name['task_id'], filename, source, task_name)
        else:
            filename = '{0}_{1}'.format(field_value.strip().lower().replace(" ", "_"),
                                        datetime.now().strftime("%Y%m%d%H%M%S"))
            sub_task_id = get_initial_data('sjc01-c01-cdrs-acme-*', '{}:{}'.format(field_name, field_value), task_name,
                                           check_task_name['task_id'], field_name, field_value, timestamp, count,
                                           filename)

    return 'Prediction Running'

def fill_data(task_queue, _data, check_task_name):
    if _data:
        source = int(_data['source'])
        task_name = _data['task_name'].strip()
        field_name = _data['field_name']
        field_value = _data['field_value']
        timestamp = _data['timestamp']
        count = _data['count']

        task_queue.put([source, task_name, field_name, field_value, timestamp, count, check_task_name])

@receiver.route("/api/v1/formatter", methods=['POST', 'GET'])
def main():
    data = request.json
    prediction_start = datetime.now()
    thread_list = []

    check_task_name = helpers.get_request('http://localhost:5002/api/v1/tasks/exists/{}'
                                          .format(data['task_name'].strip()))

    if check_task_name['result']:
        task_queue = multiprocessing.Queue()
        for _data in data["data"]:
            fill_data(task_queue, _data, check_task_name)
        #     process = multiprocessing.Process(target=predict, args=(int(source), task_name, field_name, field_value,
        #                                                             timestamp, int(count), check_task_name))
        #     thread_list.append(process)
        #     process.start()
        #
        # #for thread in thread_list:
        #
        #
        # for thread in thread_list:
        #     thread.join()
        processes = []
        MAX_THREAD = 10

        for proc in range(MAX_THREAD):
            process = multiprocessing.Process(target=predict, args=(task_queue, ))

            ## then sa "predict" function, mag task_queue.get() then i-assign mo sa any variable

            processes.append(process)
            process.start()

        for p in processes:
            p.join()

        for p in processes:
            p.close()

    else:
        result['message'] = 'Task Name does not Exists'
        result['status'] = 'Error'

    prediction_end = datetime.now()
    prediction_time = prediction_end - prediction_start
    prediction_time = prediction_time.total_seconds()
    prediction_time = prediction_time / 60

    return 'Prediction Running'


# coding: utf8

import discord
import random

from texts import get_text
from discord.ext import commands

description = '''All credits for the Rocket League: Stats webiste goes to AeonLucid !

You can invite me on your server by sending me an invite by PM.'''
bot = commands.Bot(command_prefix='/', description=description)

@bot.event
async def on_message(message):
    if message.channel.is_private and message.content.startswith('https://discord.gg'):
        try:
            invite = await bot.get_invite(message.content)
            await bot.accept_invite(invite)
            await bot.send_message(message.channel, 'I joined your channel ! Thank you for the invite ;)')
        except:
            pass # do nothing, although you can show the error if you want
        finally:
            return
    await bot.process_commands(message)

@bot.event
async def on_ready():

    bot.load_extension("misc")

    print('               _      _                  _                   |')
    print('              | |    | |           _    | |            _     |')
    print(' _ _ _   ___  | |  _ | |  _  ____ | |_  | | _    ___  | |_   |')
    print('| | | | / _ \ | | / )| | / )/ _  )|  _) | || \  / _ \ |  _)  |')
    print('| | | || |_| || |< ( | |< (( (/ / | |__ | |_) )| |_| || |__  |')
    print(' \____| \___/ |_| \_)|_| \_)\____) \___)|____/  \___/  \___) |')

    print('-------------------------------------------------------------|')
    print('+++++ ' + bot.user.name + ' is ONLINE                         ')
    print('+++++ ID: ' + bot.user.id + '                                 ')
    print('-------------------------------------------------------------|')

bot.run('wokketbot@gmail.com', 'RockmyB0T')