import sys
import time
import numpy as np

import cv2

import blazeface_utils as but

# import original modules
sys.path.append('../../util')
from utils import get_base_parser, update_parser, get_savepath  # noqa: E402
from model_utils import check_and_download_models  # noqa: E402
from image_utils import load_image  # noqa: E402
import webcamera_utils  # noqa: E402

# logger
from logging import getLogger   # noqa: E402
logger = getLogger(__name__)

# ======================
# PARAMETERS
# ======================
MODEL_NAME = 'blazeface'
MODEL_FLOAT_PATH = 'face_detection_front.tflite'
MODEL_INT_PATH = 'face_detection_front_128_full_integer_quant.tflite'
REMOTE_PATH = f'https://storage.googleapis.com/ailia-models-tflite/{MODEL_NAME}/'

IMAGE_PATH = 'input.png'
SAVE_IMAGE_PATH = 'result.png'
IMAGE_HEIGHT = 128
IMAGE_WIDTH = 128

# ======================
# Argument Parser Config
# ======================
parser = get_base_parser(
    'BlazeFace is a fast and light-weight face detector.',
    IMAGE_PATH,
    SAVE_IMAGE_PATH,
)
args = update_parser(parser)

if args.tflite:
    import tensorflow as tf
else:
    import ailia_tflite

if args.shape:
    IMAGE_HEIGHT = args.shape
    IMAGE_WIDTH = args.shape

# ======================
# Main functions
# ======================
def recognize_from_image():
    # net initialize
    if args.float:
        MODEL_PATH = MODEL_FLOAT_PATH
    else:
        MODEL_PATH = MODEL_INT_PATH
    if args.tflite:
        interpreter = tf.lite.Interpreter(model_path=MODEL_PATH)
    else:
        if args.flags or args.memory_mode or args.env_id:
            interpreter = ailia_tflite.Interpreter(model_path=MODEL_PATH, memory_mode = args.memory_mode, flags = args.flags, env_id = args.env_id)
        else:
            interpreter = ailia_tflite.Interpreter(model_path=MODEL_PATH)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()

    if args.shape:
        logger.info(f"update input shape {[1, IMAGE_HEIGHT, IMAGE_WIDTH, 3]}")
        interpreter.resize_tensor_input(input_details[0]["index"], [1, IMAGE_HEIGHT, IMAGE_WIDTH, 3])
        interpreter.allocate_tensors()

    for image_path in args.input:
        # prepare input data
        org_img = load_image(
            image_path,
            (IMAGE_HEIGHT, IMAGE_WIDTH),
        )
        input_data = load_image(
            image_path,
            (IMAGE_HEIGHT, IMAGE_WIDTH),
            normalize_type='127.5',
            gen_input_ailia_tflite=True
        )

        # inference
        logger.info('Start inference...')
        if args.benchmark:
            logger.info('BENCHMARK mode')
            average_time = 0
            for i in range(args.benchmark_count):
                start = int(round(time.time() * 1000))
                interpreter.set_tensor(input_details[0]['index'], input_data)
                interpreter.invoke()
                end = int(round(time.time() * 1000))
                average_time = average_time + (end - start)
                logger.info(f'\tailia processing time {end - start} ms')
            logger.info(f'\taverage time {average_time / args.benchmark_count} ms')
        else:
            interpreter.set_tensor(input_details[0]['index'], input_data)
            interpreter.invoke()

        preds_tf_lite = {}
        if args.float:
            preds_tf_lite[0] = interpreter.get_tensor(output_details[0]['index'])   #1x896x16 regressors
            preds_tf_lite[1] = interpreter.get_tensor(output_details[1]['index'])   #1x896x1 classificators
        else:
            preds_tf_lite[0] = interpreter.get_tensor(output_details[1]['index'])   #1x896x16 regressors
            preds_tf_lite[1] = interpreter.get_tensor(output_details[0]['index'])   #1x896x1 classificators

        # postprocessing
        detections = but.postprocess(preds_tf_lite)

        savepath = get_savepath(args.savepath, image_path)
        logger.info(f'saved at : {savepath}')

        # generate detections
        for detection in detections:
            logger.info(f'Found {detection.shape[0]} faces')
            but.plot_detections(org_img, detection, save_image_path=savepath)
    logger.info('Script finished successfully.')

def recognize_from_video():
    # net initialize
    if args.float:
        MODEL_PATH = "face_detection_front.tflite"
    else:
        MODEL_PATH = "face_detection_front_128_full_integer_quant.tflite"
    if args.tflite:
        interpreter = tf.lite.Interpreter(model_path=MODEL_PATH)
    else:
        if args.flags or args.memory_mode or args.env_id:
            interpreter = ailia_tflite.Interpreter(model_path=MODEL_PATH, memory_mode = args.memory_mode, flags = args.flags, env_id = args.env_id)
        else:
            interpreter = ailia_tflite.Interpreter(model_path=MODEL_PATH)

    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()

    capture = webcamera_utils.get_capture(args.video)

    # create video writer if savepath is specified as video format
    if args.savepath != SAVE_IMAGE_PATH:
        f_h = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
        f_w = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
        save_h, save_w = webcamera_utils.calc_adjust_fsize(
            f_h, f_w, IMAGE_HEIGHT, IMAGE_WIDTH
        )
        writer = webcamera_utils.get_writer(args.savepath, save_h, save_w)
    else:
        writer = None

    while(True):
        ret, frame = capture.read()
        if (cv2.waitKey(1) & 0xFF == ord('q')) or not ret:
            break

        input_image, input_data = webcamera_utils.preprocess_frame(
            frame, IMAGE_HEIGHT, IMAGE_WIDTH, normalize_type='127.5'
        )

        # inference
        interpreter.set_tensor(input_details[0]['index'], input_data)
        interpreter.invoke()
        preds_tf_lite = {}
        if args.float:
            preds_tf_lite[0] = interpreter.get_tensor(output_details[0]['index'])   #1x896x16 regressors
            preds_tf_lite[1] = interpreter.get_tensor(output_details[1]['index'])   #1x896x1 classificators
        else:
            preds_tf_lite[0] = interpreter.get_tensor(output_details[1]['index'])   #1x896x16 regressors
            preds_tf_lite[1] = interpreter.get_tensor(output_details[0]['index'])   #1x896x1 classificators

        # postprocessing
        detections = but.postprocess(preds_tf_lite)
        but.show_result(input_image, detections)
        cv2.imshow('frame', input_image)

        # save results
        if writer is not None:
            writer.write(input_image)

    capture.release()
    cv2.destroyAllWindows()
    if writer is not None:
        writer.release()
    logger.info('Script finished successfully.')

def main():
    # model files check and download
    check_and_download_models(MODEL_FLOAT_PATH, REMOTE_PATH)
    check_and_download_models(MODEL_INT_PATH, REMOTE_PATH)

    if args.video is not None:
        # video mode
        recognize_from_video()
    else:
        # image mode
        recognize_from_image()

if __name__ == '__main__':
    main()


import cv2

def getdifference(a, b):
	# test image
	#a, b should be image.jpeg
	image = cv2.imread('./frames/'+str(a))
	gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	histogram = cv2.calcHist([gray_image], [0],
							None, [256], [0, 256])
	# data1 image
	image = cv2.imread('./frames/'+str(b))
	gray_image1 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	histogram1 = cv2.calcHist([gray_image1], [0],
							None, [256], [0, 256])
	c1 = 0
	# Euclidean Distance between data1 and test
	i = 0
	while i<len(histogram) and i<len(histogram1):
		c1+=(histogram[i]-histogram1[i])**2
		i+= 1
	c1 = c1**(1 / 2)
	return c1


import gmpy2

thenumber = 600851475143
prime = 2
answer = 0
while thenumber > 1:
    if thenumber % prime == 0:
        thenumber = thenumber//prime
        continue
    prime = gmpy2.next_prime(prime)
    answer = prime
print(answer)

"""
gmpy2 에 있는 next_prime 을 썼음. 다음에 소수에 대한 함수들을 만들어봅시다요
"""


from fastapi import APIRouter, Request, HTTPException, Body, Path
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import StickerSendMessage, TextSendMessage
from machine_leanning.model_text_classifire import intent_model
from models.token_line import TokenLINE
from random import randint
from bson import ObjectId
from config.object_str import CutId
from typing import Optional
from config.db import MongoDB
from numpy import random
import uuid
import json
import os

client = os.environ.get('MONGODB_URI')
# client = 'mongodb://127.0.0.1:27017'
db = MongoDB(database_name='Mango', uri=client)
collection = 'line_bot'

router = APIRouter()

@router.post('/save')
async def save(item: TokenLINE):
    key = CutId(_id=ObjectId()).dict()['id']
    path_wh = uuid.uuid4().hex
    result = item.dict()
    result['id'] = key
    result['token'] = path_wh
    result['webhook'] = f'https://mango2smartmarketing.herokuapp.com/callback/{path_wh}'
    db.insert_one(collection=collection, data=result)
    del result['_id']
    return result

def get_profile(user_id, q):
    line_bot_api = q['ACCESS_TOKEN']
    line_bot_api = LineBotApi(line_bot_api)
    profile = line_bot_api.get_profile(user_id)
    displayName = profile.display_name
    userId = profile.user_id
    img = profile.picture_url
    status = profile.status_message
    result = {'displayName': displayName, 'userId': userId, 'img': img, 'status': status}
    return result

@router.post('/{token}')
async def webhook(
        request: Request,
        token: Optional[str] = Path(...),
        raw_json: Optional[dict] = Body(None)
):
    q = db.find_one(collection=collection, query={'token': token})
    q = dict(q)
    handler = q['SECRET_LINE']
    handler = WebhookHandler(handler)
    with open('static/line_log.json', 'w') as log_line:
        json.dump(raw_json, log_line)
    try:
        signature = request.headers['X-Line-Signature']
        body = await request.body()
        events = raw_json['events'][0]
        _type = events['type']
        if _type == 'follow':
            userId = events['source']['userId']
            profile = get_profile(userId, q)
            inserted = {'displayName': profile['displayName'], 'userId': userId, 'img': profile['img'],
                        'status': profile['status']}
            db.insert_one(collection='line_follower', data=inserted)
        elif _type == 'unfollow':
            userId = events['source']['userId']
            db.delete_one('line_follower', query={'userId': userId})
        elif _type == 'postback':
            event_postback(events, q)
        elif _type == 'message':
            message_type = events['message']['type']
            if message_type == 'text':
                try:
                    userId = events['source']['userId']
                    message = events['message']['text']
                    profile = get_profile(userId, q)
                    push_message = {'user_id': userId, 'message': message, 'display_name': profile['displayName'],
                                    'img': profile['img'],
                                    'status': profile['status']}
                    db.insert_one(collection='message_user', data=push_message)
                    handler.handle(str(body, encoding='utf8'), signature)
                    handler_message(events, q)
                except InvalidSignatureError as v:
                    api_error = {'status_code': v.status_code, 'message': v.message}
                    raise HTTPException(status_code=400, detail=api_error)
            else:
                no_event = len(raw_json['events'])
                for i in range(no_event):
                    events = raw_json['events'][i]
                    event_handler(events, q)
    except IndexError:
        raise HTTPException(status_code=200, detail={'Index': 'null'})
    return raw_json

def event_handler(events, q):
    line_bot_api = q['ACCESS_TOKEN']
    line_bot_api = LineBotApi(line_bot_api)
    replyToken = events['replyToken']
    package_id = '446'
    stickerId = randint(1988, 2027)
    line_bot_api.reply_message(replyToken, StickerSendMessage(package_id, str(stickerId)))

def event_postback(events, q):
    pass

def handler_message(events, q):
    line_bot_api = q['ACCESS_TOKEN']
    line_bot_api = LineBotApi(line_bot_api)
    text = events['message']['text']
    replyToken = events['replyToken']
    user_id = events['source']['userId']
    data = intent_model(text, q['ACCESS_TOKEN'])
    if data.get('require'):
        line_bot_api.reply_message(replyToken, TextSendMessage(text=data.get('require')))
    label = data['predict']
    choice_answers = data['answers']
    confident = data['confident'][0] * 100
    user = get_profile(user_id, q)
    displayName = user['displayName']
    if confident > 69:
        choice = random.choice(choice_answers[int(label)])
        line_bot_api.reply_message(replyToken, TextSendMessage(text=choice))
    else:
        line_bot_api.reply_message(replyToken, TextSendMessage(text='ฉันไม่เข้าใจ'))


import itertools

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec
from scipy import linalg
from scipy.optimize import basinhopping
from skimage.filters import gabor_kernel
from skimage.transform import resize
from sklearn import feature_selection
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, explained_variance_score
from sklearn.model_selection import ParameterGrid
from torch import nn

from base_models import get_model
from plot.plot_data import plot_subplots_histograms, plot_3d, plot_heatmap, plot_2d, plot_histogram, \
    plot_matrixImage
from utils.correlation import generate_correlation_map, pca, fit_data, multivariate_gaussian
from utils.distributions import mixture_gaussian
from utils.gabors import gabor_kernel_3, normalize, similarity

def score_kernel(X, theta, frequency, sigma, offset, stds):
    kernel = np.real(gabor_kernel(frequency, theta=theta,
                                  sigma_x=sigma, sigma_y=sigma, n_stds=stds, offset=offset))
    kernel = resize(kernel, (X.shape[0], X.shape[0]),
                    anti_aliasing=True)
    kernel = normalize(kernel)
    kernel = np.nan_to_num(kernel, posinf=1, neginf=-1, nan=0)
    score = explained_variance_score(kernel, X)

    return score

def objective_function_2(beta, X, size=3):
    kernel = gabor_kernel_3(beta[0], theta=beta[1], sigma_x=beta[2], sigma_y=beta[3],
                            offset=beta[4], x_c=beta[5],
                            y_c=beta[6], scale=beta[7], ks=size)
    kernel = normalize(kernel)
    error = mean_squared_error(kernel, X)
    return (error)

def objective_function(beta, X):
    kernel = np.real(gabor_kernel(beta[0], theta=beta[1],
                                  sigma_x=beta[2], sigma_y=beta[3], offset=beta[4], n_stds=beta[5]))
    kernel = resize(kernel, (X.shape[0], X.shape[0]),
                    anti_aliasing=True)
    kernel = normalize(kernel)
    kernel = np.nan_to_num(kernel, posinf=1, neginf=-1, nan=0)
    error = mean_squared_error(kernel, X)
    return (error)

def linear_regression(x, y, lin: LinearRegression):
    y_hat = lin.predict(x)
    return 1 - explained_variance_score(y, y_hat)

def fit_linear_regression():
    input = np.random.random([1, 8])
    output = np.random.random([1, 9])
    lin = LinearRegression()
    lin.fit(input, output)
    model = get_model('CORnet-S_base', True)
    counter = 0
    np.random.seed(1)

    def print_fun(x, f, accepted):
        print("at minima %.4f accepted %d" % (f, int(accepted)))

    fun = lambda x, y: linear_regression(x, y, lin)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d and counter == 0:
            weights = m.weight.data.cpu().numpy()
            lin_params = np.zeros([weights.shape[0], weights.shape[1], 8])
            for i in range(0, weights.shape[0]):
                for j in range(0, weights.shape[1]):
                    kernel = weights[i, j].flatten()
                    minimizer_kwargs = {"method": "L-BFGS-B", 'args': (kernel),
                                        'options': {'maxiter': 200000, 'gtol': 1e-25}}
                    result = basinhopping(fun, [0, 0, 0, 0, 0, 0, 0, 0], niter=15,
                                          minimizer_kwargs=minimizer_kwargs,
                                          callback=print_fun, T=0.00001)
                    y_hat = result.x
                    lin_params[i, j] = y_hat

def hyperparam_gabor():
    model = get_model('CORnet-S_base', True)
    counter = 0
    gabor_params = np.zeros([64, 3, 5])
    np.random.seed(1)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d and counter == 0:
            weights = m.weight.data.cpu().numpy()
            for i in range(0, 10):
                for j in range(0, 3):
                    kernel = weights[i, j]
                    kernel = normalize(kernel)
                    tuned_params = {"theta": np.arange(0, 1, 0.05),
                                    "frequency": np.arange(0, np.pi, np.pi / 12),
                                    "sigma": np.arange(0, 4, 0.25),
                                    "offset": np.arange(-2, 2, 0.5),
                                    "stds": np.arange(1, 4, 0.5),
                                    }
                    best_score = np.NINF
                    best_params = {}
                    for g in ParameterGrid(tuned_params):
                        score = score_kernel(kernel, **g)
                        if score > best_score:
                            best_score = score
                            print(f'Update best score: {score}')
                            best_params = g
                    print(f'Best grid:{best_params} for kernel {i}, filter {j}')
                    gabor_params[i, j] = np.fromiter(best_params.values(), dtype=float)
            np.save('gabor_params_grid_search_long.npy', gabor_params)
            return

def fit_gabors(version='V1', file='gabor_params_basinhopping', layers=['V1.conv1', 'V2.conv2']):
    model = get_model('CORnet-S_full_epoch_43', True)
    counter = 0
    length = 7 if version is 'V1' else 9

    np.random.seed(1)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d:
            if name in layers:
                weights = m.weight.data.cpu().numpy()
                gabor_params = np.zeros([weights.shape[0], weights.shape[1], length])
                for i in range(0, weights.shape[0]):
                    for j in range(0, weights.shape[1]):
                        kernel = weights[i, j]
                        kernel = normalize(kernel)
                        bnds = ((0, 0.5), (-np.pi, 2 * np.pi), (-4, 4), (-4, 4), (-3, 3))
                        params = [0.5, np.pi / 2, 2, 2, 0]

                        def print_fun(x, f, accepted):
                            print("at minima %.4f accepted %d" % (f, int(accepted)))

                        if version is 'V1':
                            print('Use sklearn version')
                            bnds = (
                            (-0.5, 1.5), (-np.pi, 2 * np.pi), (-4, 4), (-4, 4), (-3, 3), (-5, 5))
                            params = [0.5, np.pi / 2, 2, 2, 0, 3]
                            minimizer_kwargs = {"method": "L-BFGS-B", "bounds": bnds,
                                                'args': (kernel),
                                                'options': {'maxiter': 200000, 'gtol': 1e-25}}
                            result = basinhopping(objective_function, params, niter=15,
                                                  minimizer_kwargs=minimizer_kwargs,
                                                  callback=print_fun, T=0.00001)
                        else:
                            print('Use Tiagos version')
                            bnds = (
                                (1 / 14, 0.5), (-2 * np.pi, 2 * np.pi), (2, 14), (2, 14),
                                (-2 * np.pi, 2 * np.pi),
                                (-2, 2),
                                (-2, 2), (1e-5, 2))
                            params = [0.2, 0, 4, 4, 0, 0, 0, 1]
                            minimizer_kwargs = {"method": "L-BFGS-B", "bounds": bnds,
                                                'args': (kernel),
                                                'options': {'maxiter': 200000, 'gtol': 1e-25}}
                            result = basinhopping(objective_function_2, params, niter=15,
                                                  minimizer_kwargs=minimizer_kwargs,
                                                  callback=print_fun, T=0.00001)
                        beta_hat = result.x
                        gabor_params[i, j] = np.append(beta_hat, result.fun)
                        print(f'Kernel {i}, filter {j}:')
                        print(beta_hat)
                np.save(f'{file}.npy', gabor_params)
                return
            counter += 1

def get_fist_layer_weights():
    model = get_model('CORnet-S_full_epoch_43', True)
    counter = 0
    plt.figure(figsize=(20, 20))
    gs = gridspec.GridSpec(10, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d and counter == 0:
            weights = m.weight.data.squeeze().numpy()
            idx = 1
            for i in range(0, 10):
                kernel1 = weights[i, 0]
                kernel2 = weights[i, 1]
                kernel3 = weights[i, 2]
                ax = plt.subplot(gs[i, 0])
                ax.set_xticks([])
                ax.set_yticks([])
                ax.set_title(f'Samples parameter K1', pad=2, fontsize=5)
                idx += 1
                plt.imshow(kernel2, cmap='gray')
                ax = plt.subplot(gs[i, 1])
                ax.set_title(f'Samples parameter K2', pad=2, fontsize=5)
                idx += 1
                plt.imshow(kernel1, cmap='gray')
                ax.set_xticks([])
                ax.set_yticks([])
                ax = plt.subplot(gs[i, 2])
                ax.set_title(f'Samples parameter K3', pad=2, fontsize=5)
                plt.imshow(kernel3, cmap='gray')
                ax.set_xticks([])
                ax.set_yticks([])

                idx += 1
        plt.tight_layout()
        plt.savefig('full_kernels.png')
        plt.show()
        return

def compare_gabors(version='V1', file='gabor_params_basinhopping_bound_6_params'):
    gabor_params = np.load(f'{file}.npy')
    model = get_model('CORnet-S_full_epoch_43', True)
    counter = 0
    plt.figure(figsize=(4, 25))
    gs = gridspec.GridSpec(20, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d and counter == 0:
            weights = m.weight.data.squeeze().numpy()
            index = 1
            for i in range(0, 10):
                for j in range(0, 3):
                    beta = gabor_params[i, j]
                    kernel2 = weights[i, j]
                    kernel2 = normalize(kernel2)
                    if version is "V1":
                        kernel1 = np.real(gabor_kernel(beta[0], theta=beta[1],
                                                       sigma_x=beta[2], sigma_y=beta[3],
                                                       offset=beta[4],
                                                       n_stds=beta[5]))
                        kernel1 = np.nan_to_num(kernel1).astype(np.float32)
                        kernel1 = resize(kernel1, (kernel2.shape[0], kernel2.shape[0]),
                                         anti_aliasing=True, preserve_range=True)
                        kernel1 = normalize(kernel1)
                    else:
                        kernel1 = gabor_kernel_3(beta[0], theta=beta[1],
                                                 sigma_x=beta[2], sigma_y=beta[3], offset=beta[4],
                                                 x_c=beta[5],
                                                 y_c=beta[6], scale=beta[7], ks=7)
                        kernel1 = normalize(kernel1)
                    ax = plt.subplot(gs[i * 2, j])
                    ax.set_xticks([])
                    ax.set_yticks([])
                    ax.set_title(f'K {i}, F {j}', pad=3)
                    plt.imshow(kernel2, cmap='gray')
                    ax = plt.subplot(gs[(i * 2) + 1, j])
                    ax.set_title(f'Error {beta[-1]:.3}', pad=10)
                    plt.imshow(kernel1, cmap='gray')
                    index += 1
                index += 3

            plt.savefig(f'{file}.png')
            plt.show()
            return

def rank_errors(name1, name2):
    n1 = np.load(f'{name1}.npy')
    n2 = np.load(f'{name2}.npy')
    value = np.mean(n1[:, -1])
    value2 = np.mean(n2[:, -1])
    print(f'Mean error of fit {name1} is {value}, mean error of fit {name2} is {value2}')

def plot_parameter_distribution(name):
    params = np.load(f'{name}.npy')
    data = {}
    names = ['Frequency', 'Theta', 'Sigma X', 'Sigma Y', 'Offset', 'Center X', 'Center Y']
    variables = np.zeros((7, 192))
    for i in range(params.shape[2] - 1):
        param = params[:, :, i]
        data[names[i]] = param.flatten()
        variables[i] = param.flatten()
    bnds = (
    (1 / 14, 0.5), (-2 * np.pi, 2 * np.pi), (2, 14), (2, 14), (-2 * np.pi, 2 * np.pi), (-2, 2),
    (-2, 2))
    plot_subplots_histograms(data, 'Gabor parameter distributions', bins=10, bounds=bnds)

def mutual_information():
    model = get_model('CORnet-S_base', True)
    plt.figure(figsize=(4, 25))
    gs = gridspec.GridSpec(20, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d and 'V1' not in name:
            weights = m.weight.data.squeeze().numpy()
            scores = np.zeros([weights.shape[0], weights.shape[0]])
            kernels = weights.shape[0]
            for i in range(kernels):
                for j in range(kernels):
                    scores[i, j] = feature_selection.mutual_info_regression(
                        weights[i].flatten().reshape(-1, 1),
                        weights[j].flatten())
            print(f'Kernel mean mutual information {np.mean(scores)}')
            plot_heatmap(scores, title=f'Kernel mutual information {name}', col_labels='Kernels',
                         row_labels='Kernels')
            if len(weights.shape) > 2:
                channels = weights.shape[1]
                scores = np.zeros([kernels, channels, channels])
                for i in range(kernels):
                    for j in range(channels):
                        for k in range(channels):
                            scores[i, j, k] = feature_selection.mutual_info_regression(
                                weights[i, j].flatten().reshape(-1, 1), weights[i, k].flatten())
                scores = np.mean(scores, axis=0)
                plot_heatmap(scores, title=f'Channel mean mutual information {name}',
                             col_labels='Channel',
                             row_labels='Channel')

def kernel_similarity():
    model = get_model('CORnet-S_train_second_kernel_conv_epoch_00', True)
    counter = 0
    plt.figure(figsize=(4, 25))
    gs = gridspec.GridSpec(20, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    kernel_avgs = []
    for name, m in model.named_modules():
        if type(m) == nn.Conv2d:
            if counter == 1:
                weights = m.weight.data.squeeze().numpy().transpose(1, 0, 2, 3)
                for i in range(0, 64):
                    avgs = []
                    for j in range(0, 64):
                        for k in range(j, 64):
                            if k != j:
                                c1 = weights[i, j]
                                c2 = weights[i, k]
                                avgs.append(similarity(c2, c1))
                    kernel_avgs.append(np.mean(avgs))
                plot_histogram(kernel_avgs, 'Channel similarity within a kernel', bins=20)
                print('Similarity avg:' + str(np.mean(kernel_avgs)))
                return
            counter += 1

def mixture_analysis(pi, mu, cov):
    # k components: pi = (k) , mu = (k), cov = (k,k,k)
    print(pi.shape, mu.shape, cov.shape)

def gaussian_mixture_channels(name):
    params = np.load(f'{name}.npy')
    param = params[:, :, :-1]
    param = param.reshape(-1, 8)
    mixture_base(param, [(0, 10)], [4096, 1])

def gaussian_mixture(name, name2=None):
    params = np.load(f'{name}.npy')
    names = ['Frequency', 'Theta', 'Sigma X', 'Sigma Y', 'Offset', 'Center X', 'Center Y']
    shape = [64, 64, 3, 3]
    param = params[:, :, :-1]
    param = param.reshape(64, -1)
    tuples = []
    for i in range(param.shape[1]):
        tuples.append((i * 10, (i + 1) * 10))
    if name2 is not None:
        params2 = np.load(f'{name}.npy')
        p2 = params[:, :, :-1]
        p2 = p2.reshape(64, -1)
        param = np.concatenate((param, p2), axis=0)
    mixture_base(param, tuples, shape)

def mixture_base(param, tuples, shape, size=3):
    new_param = np.zeros((shape[0], 10 * shape[1]))
    for i in range(shape[0]):
        for s, e in tuples:
            p = param[i, int(s * 8 / 10):int(e * 8 / 10)]
            new_param[i, s:e] = (
                p[0], np.sin(2 * p[1]), np.cos(2 * p[1]), p[2], p[3], np.sin(p[4]), np.cos(p[4]),
                p[5], p[6], p[7])

    # plot_bic(best_gmm, param)
    best_gmm = mixture_gaussian(new_param)
    samples = best_gmm.sample(new_param.shape[0])[0]
    idx = 1

    plt.figure(figsize=(10, 20))
    gs = gridspec.GridSpec(22, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    for i in range(shape[0]):
        for s, e in tuples:
            beta = samples[i, s:e]
            kernel2 = gabor_kernel_3(beta[0], theta=np.arctan2(beta[1], beta[2]),
                                     sigma_x=beta[3], sigma_y=beta[4],
                                     offset=np.arctan2(beta[5], beta[6]), x_c=beta[7],
                                     y_c=beta[8],
                                     scale=beta[9], ks=size)
            ax = plt.subplot(gs[i, int(s / 10)])
            ax.set_xticks([])
            ax.set_yticks([])
            plt.imshow(kernel2, cmap='gray')
        idx += 1
    plt.figure(figsize=(15, 15))

    length = 64 * 3
    matrix = np.empty([length, 0])
    weights = samples.reshape(64, 64, 10)
    for i in range(0, 64):
        row = np.empty([0, 3])
        for j in range(0, 64):
            beta = weights[i, j]
            channel = gabor_kernel_3(beta[0], theta=np.arctan2(beta[1], beta[2]),
                                     sigma_x=beta[3], sigma_y=beta[4],
                                     offset=np.arctan2(beta[5], beta[6]), x_c=beta[7],
                                     y_c=beta[8],
                                     scale=beta[9], ks=size)
            row = np.concatenate((row, channel), axis=0)
        f_min, f_max = np.min(row), np.max(row)
        row = (row - f_min) / (f_max - f_min)
        matrix = np.concatenate((matrix, row), axis=1)
    plot_matrixImage(matrix, 'Gabor_conv2')
    plt.tight_layout()
    plt.show()

def plot_bic(clf, X):
    plt.figure(figsize=(20, 20))
    color_iter = itertools.cycle(['navy', 'turquoise', 'cornflowerblue',
                                  'darkorange', 'red', 'yellow'])
    size = X.shape[1]
    Y_ = clf.predict(X)
    idx = 1
    for l in range(size):
        for j in range(X.shape[1]):
            splot = plt.subplot(size, size, idx)
            idx += 1
            for i, (mean, cov, color) in enumerate(zip(clf.means_, clf.covariances_,
                                                       color_iter)):
                v, w = linalg.eigh(cov)
                if not np.any(Y_ == i):
                    continue
                plt.scatter(X[Y_ == i, l], X[Y_ == i, j], 1, color=color)

                # Plot an ellipse to show the Gaussian component
                angle = np.arctan2(w[0][j], w[0][l])
                angle = 180. * angle / np.pi  # convert to degrees
                v = 2. * np.sqrt(2.) * np.sqrt(v)
                ell = mpl.patches.Ellipse(mean, v[l], v[j], 180. + angle, color=color)
                ell.set_clip_box(splot.bbox)
                ell.set_alpha(.5)
                splot.add_artist(ell)
        plt.xticks(())
        plt.yticks(())
        plt.title(f'Dimension {l} and {j}')
    plt.subplots_adjust(hspace=.35, bottom=.02)
    plt.savefig('Mixture gaussians')
    plt.show()

def analyze_param_dist(name, plot=False):
    params = np.load(f'{name}.npy')
    names = ['Frequency', 'Theta', 'Sigma X', 'Sigma Y', 'Offset', 'Center X', 'Center Y']
    variables = np.zeros((7, 192))
    param = params[:, :, :-1]
    param = param.reshape(64, -1)

    pca_res = pca(param, n_components=21)
    principal_components = pca_res.transform(param)
    if plot:
        plot_2d(principal_components[:, 0], principal_components[:, 1], 'PC 1 & 2')
        plot_2d(principal_components[:, 1], principal_components[:, 2], 'PC 2 & 3')
        plot_2d(principal_components[:, 0], principal_components[:, 2], 'PC 1 & 3')
        plot_2d(principal_components[:, 0], principal_components[:, 3], 'PC 1 & 4')
        plot_2d(principal_components[:, 0], principal_components[:, 4], 'PC 1 & 5')
        plot_3d(principal_components[:, 0], principal_components[:, 1], principal_components[:, 2],
                'Principal components of gabor filter params')
    reg = fit_data(principal_components, variables.T)
    small_samples = multivariate_gaussian(principal_components.T, 10)
    full_params = reg.predict(small_samples.T)  # shape (10, 7)
    small_samples_hat = pca_res.transform(full_params)  # shape (10,3)
    full_params_hat = reg.predict(small_samples_hat)
    print(mean_squared_error(small_samples.T, small_samples_hat))
    idx = 0
    plt.figure(figsize=(5, 10))
    gs = gridspec.GridSpec(20, 3, width_ratios=[1] * 3,
                           wspace=0.5, hspace=0.5, top=0.95, bottom=0.05, left=0.1, right=0.95)
    for i in range(10):
        alpha = full_params[i]
        beta = full_params_hat[i]
        kernel2 = gabor_kernel_3(beta[0], theta=beta[1],
                                 sigma_x=beta[2], sigma_y=beta[3], offset=beta[4], x_c=beta[5],
                                 y_c=beta[6], ks=7)
        kernel1 = gabor_kernel_3(alpha[0], theta=alpha[1],
                                 sigma_x=alpha[2], sigma_y=alpha[3], offset=alpha[4], x_c=alpha[5],
                                 y_c=alpha[6], ks=7)
        ax = plt.subplot(gs[i, 0])
        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_title(f'Samples parameter set', pad=3, fontsize=5)
        idx += 1
        plt.imshow(kernel2, cmap='gray')
        ax = plt.subplot(gs[i, 1])
        ax.set_title(f'Reconstruction', pad=10, fontsize=5)
        plt.imshow(kernel1, cmap='gray')
        ax.set_xticks([])
        ax.set_yticks([])
        plt.tight_layout()
        idx += 1
    plt.savefig(f'reconstructions.png')
    plt.show()

    if plot:
        principal_components = principal_components.T
        corr_pca = generate_correlation_map(principal_components, principal_components)
        corr_map = generate_correlation_map(variables, variables)
        mask = np.zeros_like(corr_map)
        mask[np.triu_indices_from(mask)] = True
        plot_heatmap(corr_map, names, names, title='Gabor parameter correlation', mask=mask)
        mask = np.zeros_like(corr_pca)
        mask[np.triu_indices_from(mask)] = True
        plot_heatmap(corr_pca, names, names, title='PCA correlations', mask=mask)

def compare_two_values():
    # ((-0.5, 1.5), (-np.pi, 2 * np.pi), (-4, 4), (-4, 4), (-3, 3), (-5, 5))
    params = [-0.5, -2 * np.pi / 8, 0, 0, 0, 0]
    params = [0.5, np.pi + ((-2 * np.pi / 8) % np.pi), 0, 0, 0, 0]
    gabor_kernel_3(*params)

if __name__ == '__main__':
    fit_gabors('V2', "output_file_name")
    # name = 'gabors_tiago'
    # rank_errors(name, 'gabors_sklearn')
    # show_options()
    # compare_gabors()
    # name = 'gabors_V2.conv2'
    # # name = 'gabors_tiago_scaled'
    # np.random.seed(0)
    # fit_gabors('V2', name)
    # compare_gabors('V2', name)
    # analyze_param_dist(name, True)
    # gaussian_mixture(name)
    # gaussian_mixture_channels(name)
    # kernel_similarity()
    # get_fist_layer_weights()
    # mutual_information()
    fit_linear_regression()


from asyncio.windows_events import NULL
import pstats
import sys
import tkinter as tk
import tkinter.ttk as ttk
import time

class Window(tk.Frame):

    FRAME_PADX: int = 30
    FRAME_PADY: int = 15
    FRAME_SIZEX: int = 1000
    FRAME_SIZEY: int = 300
    BUTTON_SIZEX: int = 10
    BUTTON_SIZEY: int = 30
    BUTTON_DISABLED_BG_COLOR: str = "whitesmoke"
    INJECTEAIR_BUTTON_BG_COLOR: str = "lightblue"
    SENDDATA_BUTTON_BG_COLOR: str = "lightpink"
    START_BUTTON_BG_COLOR: str = "lightgreen"
    STOP_BUTTON_BG_COLOR: str = "lemonchiffon"
    SET_BUTTON_BG_COLOR: str = "lightpink"
    RESET_BUTTON_BG_COLOR: str = "lightblue"

    @property
    def InputPressure(self) -> int:
        return int(self.__pressure)

    @InputPressure.setter
    def InputPressure(self, value):
        if value == '':
            self.__pressure = -1
            self.sendDataStateLabel["text"] += '[設定圧力に無効な入力]'
        elif int(value) == 9999:
            self.__pressure = 0
            self.sendDataStateLabel["text"] = '[一時停止]'
        elif int(value) > 1000:
            self.__pressure = -1
            self.sendDataStateLabel["text"] += '[設定圧力は1000pa以下]'
        elif int(value) < 0:
            self.__pressure = -1
            self.sendDataStateLabel["text"] += '[設定圧力は正値]'
        else:
            self.__pressure = value

    @property
    def InputDeltaTime(self) -> int:
        return int(self.__deltatime)

    @InputDeltaTime.setter
    def InputDeltaTime(self, value):
        if value == '':
            self.__deltatime = -1
            self.sendDataStateLabel["text"] += '[設定時間に無効な入力]'
        elif int(value) == 9999:
            self.__pressure = 0
            self.sendDataStateLabel["text"] = '[一時停止]'
        elif int(value) > 5000:
            self.__deltatime = -1
            self.sendDataStateLabel["text"] += '[設定時間は5000ms以下]'
        elif int(value) < 0:
            self.__deltatime = -1
            self.sendDataStateLabel["text"] += '[設定時間は正値]'
        else:
            self.__deltatime = value

    @property
    def IsMeasuring(self) -> bool:
        return self.__isMeasuring

    @IsMeasuring.setter
    def IsMeasuring(self, value: bool = False):
        self.__isMeasuring = value

    def __init__(self, root, mySerial, myCSV, myVision):
        super().__init__(root)

        self.__myVision = myVision
        self.__myCSV = myCSV
        self.__root = root
        self.__mySerial = mySerial
        self.__pressure: int = 0
        self.__deltatime: int = 0
        self.__isMeasuring: bool = False

        root.option_add('*font', 'ＭＳゴシック 22')
        root.title("装置との通信用窓")

        # ウィンドウの閉じるボタンは無効にする
        root.protocol('WM_DELETE_WINDOW', (lambda: 'pass')())

        # 設定
        self.tf1 = tk.Frame(root, relief='groove',
                            bd=5)
        self.tf1.grid(column=0, row=0, padx=self.FRAME_PADX,
                      pady=self.FRAME_PADY, sticky=tk.E + tk.W)
        # self.tf1.place(height=200, width=500)

        # 1,送信ボタン
        self.sendDataButton = tk.Button(
            self.tf1, text='データ送信', bg=self.SENDDATA_BUTTON_BG_COLOR, bd=4, width=15)
        self.sendDataButton.grid(
            padx=10, pady=10, column=0, row=0, sticky='w')
        self.sendDataButton.bind(
            "<Button-1>", self.SendDataButtonEventHandler)

        # 1,送信状態表示ラベル
        self.sendDataStateLabel = tk.Label(
            self.tf1, text='', fg="red")
        self.sendDataStateLabel.grid(
            padx=10, pady=10, column=1, columnspan=2, row=0, sticky='w')

        # 入力圧力の設定
        self.pLabel = tk.Label(self.tf1, text='設定圧力[pa]')
        self.pLabel.grid(padx=10, pady=10, column=0, row=1, sticky='e')

        self.pEntry = tk.StringVar()
        self.pEntry.set('')
        self.pEntryBox = tk.Entry(
            self.tf1, textvariable=self.pEntry, bd=5, relief='groove')
        # self.pEntry.bind('<Return>', self.entf1unc)
        self.pEntryBox.grid(padx=10, column=1, row=1, sticky='w')

        # 入力時間の設定
        self.dtLabel = tk.Label(
            self.tf1, text='設定時間[ms]')
        self.dtLabel.grid(padx=10, pady=10, column=0, row=2, sticky='e')

        self.dtEntry = tk.StringVar()
        self.dtEntry.set('')
        self.dtEntryBox = tk.Entry(
            self.tf1, textvariable=self.dtEntry, bd=5, relief='groove')
        # self.dtEntry.bind('<Return>', self.entf1unc)
        self.dtEntryBox.grid(padx=10, column=1, row=2, sticky='w')

        # border1 = ttk.Separator(root, orient="horizontal")
        # border1.grid(column=0, columnspan=2, row=3, sticky="ew")

        # 設定
        self.tf2 = tk.Frame(root, relief='groove', bd=5)
        self.tf2.grid(column=0, row=1, padx=self.FRAME_PADX,
                      pady=self.FRAME_PADY, sticky=tk.E + tk.W)

        # 2,計測開始ボタン
        self.startButton = tk.Button(
            self.tf2, text='計測開始', bg=self.BUTTON_DISABLED_BG_COLOR, bd=4, width=15)
        self.startButton.grid(padx=10, pady=10, column=0, row=0, sticky='w')
        self.startButton.bind("<Button-1>", self.StartButtonEventHandler)
        self.startButton["state"] = "disabled"

        # 　ファイル名ラベル
        self.fileNameLabel = tk.Label(
            self.tf2, text='ファイル名')
        self.fileNameLabel.grid(padx=10, pady=10, column=0, row=1, sticky='e')

        # 2,計測状態表示ラベル
        self.measuringStateLabel = tk.Label(
            self.tf2, text='', fg="black")
        self.measuringStateLabel.grid(
            padx=10, pady=10, column=1, columnspan=2, row=1, sticky='w')

        # 3,計測終了ボタン
        self.stopButton = tk.Button(
            self.tf2, text='計測終了', bg=self.BUTTON_DISABLED_BG_COLOR, bd=4, width=15)
        self.stopButton.grid(padx=10, pady=10, column=0, row=5, sticky='w')
        self.stopButton.bind("<Button-1>", self.StopButtonEventHandler)
        self.stopButton["state"] = "disabled"

        # 設定
        self.tf3 = tk.Frame(root, relief='groove', bd=5)
        self.tf3.grid(column=0, row=2, padx=self.FRAME_PADX,
                      pady=self.FRAME_PADY, sticky=tk.E + tk.W)

        # 4,空気発射ボタン
        self.injectAirButton = tk.Button(
            self.tf3, text='空気発射', bg=self.BUTTON_DISABLED_BG_COLOR, bd=4, width=15)
        self.injectAirButton.grid(
            padx=10, pady=10, column=0, row=0, sticky='w')
        self.injectAirButton.bind("<Button-1>", self.InjectAirEventHandler)
        self.injectAirButton["state"] = "disable"

        # 設定
        self.tf4 = tk.Frame(root, relief='groove', bd=5)
        self.tf4.grid(column=0, row=3, padx=self.FRAME_PADX,
                      pady=self.FRAME_PADY, sticky=tk.E + tk.W)

        # 4,マスク固定ボタン
        self.setMaskButton = tk.Button(
            self.tf4, text='マスク固定', bg=self.SET_BUTTON_BG_COLOR, bd=4, width=15)
        self.setMaskButton.grid(
            padx=10, pady=10, column=0, row=0, sticky='w')
        self.setMaskButton.bind("<Button-1>", self.SetMaskButtonEventHandler)
        self.setMaskButton["state"] = "normal"

        # 4,マスク解除ボタン
        self.resetMaskButton = tk.Button(
            self.tf4, text='マスク解除', bg=self.BUTTON_DISABLED_BG_COLOR, bd=4, width=15)
        self.resetMaskButton.grid(
            padx=10, pady=10, column=0, row=1, sticky='w')
        self.resetMaskButton.bind(
            "<Button-1>", self.ResetMaskButtonEventHandler)
        self.resetMaskButton["state"] = "disable"

        # 4,窓表示非表示ボタン
        self.windowOnOffButton = tk.Button(
            self.tf4, text='窓On/Off', bg=self.START_BUTTON_BG_COLOR, bd=4, width=15)
        self.windowOnOffButton.grid(
            padx=10, pady=10, column=0, row=2, sticky='w')
        self.windowOnOffButton.bind(
            "<Button-1>", self.SetWindoDisableButton)
        self.windowOnOffButton["state"] = "normal"

    def SetWindoDisableButton(self, event):
        self.__myVision.DestroyAllWindow()
        self.__myVision.WINDOW_DISABLE_FLAG =\
            not self.__myVision.WINDOW_DISABLE_FLAG

    def SetMaskButtonEventHandler(self, event):
        self.resetMaskButton["state"] = "normal"
        self.resetMaskButton["bg"] = self.RESET_BUTTON_BG_COLOR
        self.setMaskButton["state"] = "disabled"
        self.setMaskButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
        self.__myVision.MASK_FIXED_FLAG = True

    def ResetMaskButtonEventHandler(self, event):
        self.setMaskButton["state"] = "normal"
        self.setMaskButton["bg"] = self.SET_BUTTON_BG_COLOR
        self.resetMaskButton["state"] = "disabled"
        self.resetMaskButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
        self.__myVision.MASK_FIXED_FLAG = False

    def SendDataButtonEventHandler(self, event):
        if self.sendDataButton["state"] == "disabled":
            return NULL

        self.sendDataStateLabel["text"] = ''
        self.InputPressure = self.pEntry.get()
        self.InputDeltaTime = self.dtEntry.get()

        if (int(self.InputPressure) == -1) or (int(self.InputDeltaTime) == -1):
            self.stopButton["state"] = "disabled"
            self.stopButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
            self.startButton["state"] = "disabled"
            self.startButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
            self.injectAirButton["state"] = "disabled"
            self.injectAirButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
            return NULL

        if (int(self.InputPressure) == 0) or (int(self.InputDeltaTime) == 0):
            self.__mySerial.SendInitializeData(
                int(9999), int(9999))

        self.__mySerial.SendInitializeData(
            int(self.InputPressure), int(self.InputDeltaTime))

        self.startButton["state"] = "normal"
        self.startButton["bg"] = self.START_BUTTON_BG_COLOR
        self.injectAirButton["state"] = "normal"
        self.injectAirButton["bg"] = self.INJECTEAIR_BUTTON_BG_COLOR

    def StartButtonEventHandler(self, event):
        if self.startButton["state"] == "disabled":
            return NULL

        if (self.__myVision.DANGOMUSI_X == 0) or (self.__myVision.DANGOMUSI_Y == 0) or (self.__myVision.NOZLE_DANGOMUSI_DISTANCE == 0):
            return NULL

        print("[I'm measuring now...]")
        self.IsMeasuring = True
        filename = self.__myCSV.MakeFile(
            self.InputPressure, self.InputDeltaTime)
        self.measuringStateLabel["text"] = filename
        self.__mySerial.SendStartMeasuringSignal()
        self.__myVision.SEND_INJECT_AIR_SIGNAL_FLAG = True

        self.sendDataButton["state"] = "disabled"
        self.sendDataButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
        self.startButton["state"] = "disabled"
        self.startButton["bg"] = self.BUTTON_DISABLED_BG_COLOR
        self.stopButton["state"] = "normal"
        self.stopButton["bg"] = self.STOP_BUTTON_BG_COLOR

    def StopButtonEventHandler(self, event):
        if self.stopButton["state"] == "disabled":
            return NULL

        print("[Stop measuring]")
        self.IsMeasuring = False
        self.sendDataButton["state"] = "normal"
        self.sendDataButton["bg"] = self.SENDDATA_BUTTON_BG_COLOR
        self.__mySerial.SendStopMeasuringSignal()
        self.__myVision.SEND_INJECT_AIR_SIGNAL_FLAG = False

        if self.__myCSV.IsFileOpened():
            self.__myCSV.CloseFile()

        self.stopButton["state"] = "disabled"
        self.stopButton["bg"] = self.BUTTON_DISABLED_BG_COLOR

    def InjectAirEventHandler(self, event):
        if self.injectAirButton["state"] == "disabled":
            return NULL
        elif self.injectAirButton["state"] == "normal":
            self.injectAirButton["bg"] = self.INJECTEAIR_BUTTON_BG_COLOR
            self.__mySerial.SendInjectAirSignalFromWindow()
            print("[Inject Air!]")

    def __del__(self):
        self.__root.destroy()

if __name__ == '__main__':
    root = tk.Tk()
    myapp = Window(root)
    myapp.mainloop()


import random
import re
from collections import Counter, namedtuple

re_smiley = re.compile(r'[8;:=%][-oc*^]?[)(D\/\\]')
re_smiley_reversed = re.compile(r'[)(D\/\\][-oc*^]?[8;:=%]')
re_smiley_asian = re.compile(r'\^[o_.]?\^')
extra_smileys = ['<3', '\o', '\o/', 'o/']
re_smileys = [re_smiley, re_smiley_reversed, re_smiley_asian]
re_url = re.compile(r'(?:(?:https?|ftp):\/\/.*)')

Word = namedtuple('Word', ['word', 'score'])

def is_smiley(word):
    '''
    check if ``word`` is a smiley

    :param word: word to check
    :type word: str

    :return: result of check
    :rtype: bool
    '''
    if word in extra_smileys:
        return True
    for re_smiley in re_smileys:
        if re_smiley.match(word):
            return True
    return False

def prepare_line(line):
    '''
    split words to line, lower words, add newlines and remove invalid chars

    :param line: line to prepare
    :type line: str
    :return: prepared line
    :rtype: list
    '''
    words_ = line.split()
    words = []
    for word_ in words_:
        word = None
        # prevent smileys and urls from getting lower'd
        if is_smiley(word_) or re_url.match(word_):
            word = word_
        else:
            word = word_.lower()
        if len(word) >= 1:
            words.append(word)
    words.append('\n')
    return words

class MarkovPy:

    def __init__(self, store):
        '''
        :param store: a compatible markov-store
        :type store: class
        '''
        self.store = store

    def _best_known_word(self, words):
        '''
        Find the best known word out of `words`

        :param words: list of words
        :type words: list

        :returns: best known word
        :rtype: str
        '''
        # build word_relations-list (word, relation-count)
        word_relations = [
            Word(word, score=self.store.relation_count(word))
            for word in words if word in self.store
        ]
        # no known words => None
        if not word_relations:
            return None
        # only one word in the list => return
        if len(word_relations) == 1:
            return word_relations[0].word
        else:
            # sort words by relation-count
            sorted_word_relations = sorted(
                word_relations, key=lambda x: x.score, reverse=True
            )
            highest_num = sorted_word_relations[0].score
            # add word with most relations to the best_known_words-list
            best_known_words = [sorted_word_relations[0].word]
            for word, num in word_relations:
                # check if word has the same (highest) relation-count
                if num == highest_num:
                    # => add it to the best_known_words-list
                    best_known_words.append(word)
                else:
                    break
            # choose a random word from that list
            if len(best_known_words) == 1:
                return best_known_words[0]
            else:
                return random.choice(best_known_words)

    def learn(self, line, prepared=False):
        '''
        learn from ``line``

        :param line: line to add
        :param prepared: line was already split to words
        :type line: str
        :type prepared: bool
        '''
        if prepared:
            words = line
        else:
            words = prepare_line(line)
        for i in range(0, len(words)):
            current_word = words[i]
            if len(words) <= i + 1:
                break
            next_word = words[i + 1]
            self.store.insert(current_word, next_word)

    def reply(self, start, min_length=5, max_length=10, prepared=False):
        '''
        generate a reply to ``start``

        :param min_length: minimal length of reply
        :param max_length: max length of reply
        :param prepared: line was already split to words
        :type min_length: int
        :type max_length: int
        :type prepared: bool
        :return: response
        :rtype: str
        '''
        if prepared:
            start_words = start
        else:
            start_words = prepare_line(start)
        # gen answer
        start_word = self._best_known_word(start_words)
        if not start_word:
            return None
        if min_length > max_length:
            max_length = min_length + 1
        answer = [start_word]
        while len(answer) < max_length:
            # key doesn't exist => no possible next words
            if answer[-1] not in self.store:
                break
            possible_words = self.store.next_words(answer[-1])
            if len(possible_words) == 1:
                word = possible_words[0][0]
            else:
                # sort random word but weight
                word = random.choice(
                    list(Counter(dict(possible_words)).elements())
                )
            # choosen word == line-end => break
            if word == '\n':
                break
            # add to answer
            answer.append(word)
        if len(answer) < min_length:
            # dont return too short answers
            return None
        return ' '.join(answer)

    def process(self, line, learn=True, reply=True):
        '''
        process ``line``

        :param line: line to process
        :param learn: learn from line
        :param reply: reply to line (and return answer)
        :type line: str
        :type learn: bool
        :type reply: bool
        :return: answer if ``reply``
        :rtype: str
        '''
        prepared_line = prepare_line(line)
        if learn:
            self.learn(prepared_line, prepared=True)
        if reply:
            return self.reply(prepared_line, prepared=True)

    def __len__(self):
        return len(self.store)


from typing import List

class Solution:
    def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
        if not A:
            return 0
        def sameNum(arr: List[int]) -> dict:
            result = {}
            for i in arr:
                if i in result:
                    result[i] += 1
                else:
                    result[i] = 1
            return result

        def zeroSubtraction(da: dict, db: dict) -> dict:
            result: dict = {}
            for a in da.keys():
                for b in db.keys():
                    if result.__contains__((a + b)):
                        result[(a + b)] += da[a] * db[b]
                    else:
                        result[(a + b)] = da[a] * db[b]
            return result

        def theEnd(da: dict, db: dict) -> int:
            result = 0
            for a in da.keys():
                if db.__contains__(-a):
                    result += da[a] * db[-a]
            return result

        da = sameNum(A)
        db = sameNum(B)
        dc = sameNum(C)
        dd = sameNum(D)

        d1 = zeroSubtraction(da, db)
        d2 = zeroSubtraction(dc, dd)
        result = theEnd(d1, d2)

        return result

if __name__ == '__main__':
    print(Solution().fourSumCount([-1,-1],[-1,1], [-1,1],[1,-1]))


#!/usr/bin/env python3

import zipfile
import wget
import re

# CoVoST2 translations file
covost2_url = 'https://dl.fbaipublicfiles.com/covost/covost2.zip'

# File with CommonVoice English sentences translated to Catalan by humans
covost2_source_file = 'validated.en_ca.en'

# Output file
covost2_target_file = 'covost2-ca.txt'

# Discarted sentences
discarted_file = 'covost2-ca-discarted.txt'

# char replacements table
source_chars = '´‘’“”«»'
target_chars ='\'\'\'""""'
translation = str.maketrans(source_chars, target_chars)

def normalize_line(line):

    line = line.translate(translation)
    return(line)

def validate_line(line):

    if (re.match("^[a-zA-ZçÇáàèéíïòóóúüÁÀÈÉÍÏÒÓÚÜ·¡¿!\? ,;:.\"'\.\(\)/–-]+\n$", line)):
        return True
    return False

# Download CoVoST2 translations
wget.download(covost2_url)

# Get English to Catalan translated sentences
with zipfile.ZipFile('covost2.zip','r') as zip_ref:
    zip_ref.extract('covost2/' + covost2_source_file)

# Parse translations

# Store lines already seen
lines_seen = set()

with open(covost2_target_file, 'w') as output_file, open(discarted_file, 'w') as removed_file:
    for line in open('covost2/' + covost2_source_file, 'r'):
        # Normalize line
        line = normalize_line(line)
        # Check if line is duplicated
        if line not in lines_seen:
            # Store line as seen
            lines_seen.add(line)
            # If it's a valid sentece, write it
            if validate_line(line):
                 output_file.write(line)
            else:
                 removed_file.write(line)


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @author: orleven

from lib.core.env import *
import json
from sqlalchemy import and_
from flask import request
from flask import Blueprint
from lib.core.enums import ApiStatus
from lib.core.model import DNSLog
from lib.core.model import WebLog
from lib.hander import db
from lib.hander.basehander import fix_response
from lib.hander.basehander import login_check

mod = Blueprint('api', __name__, url_prefix=f'{PREFIX_URL}/api')

@mod.route('/dnslog/list', methods=['POST', 'GET'])
@login_check
@fix_response
def api_dnslog_list():
    """获取dnslog信息"""
    response = {
        'data': {
            'res': [],
            'total': 0,
        }
    }
    page = request.json.get('page', 1)
    per_page = request.json.get('per_page', 10)
    domain = request.json.get('domain', '')
    ip = request.json.get('ip', '')
    condition = (1 == 1)

    if ip != '':
        condition = and_(condition, DNSLog.ip.like('%' + ip + '%'))

    if domain != '':
        condition = and_(condition, DNSLog.domain.like('%' + domain + '%'))

    if per_page == 'all':
        for row in db.session.query(DNSLog).filter(condition).all():
            response['data']['res'].append(row.to_json())
    else:
        for row in db.session.query(DNSLog).filter(condition).order_by(
                DNSLog.update_time.desc()).paginate(page=page, per_page=per_page).items:
            response['data']['res'].append(row.to_json())

    response['data']['total'] = db.session.query(DNSLog).filter(condition).count()
    return response

@mod.route('/dnslog/detail', methods=['POST', 'GET'])
@login_check
@fix_response
def api_dnslog_detail():
    """获取dnslog信息"""
    response = {'data': {'res': []}}
    dnslog_id = request.json.get('id', '')
    if dnslog_id != '':
        dnslog = db.session.query(WebLog).filter(WebLog.id == dnslog_id).first()
        if dnslog:
            response['data']['res'].append(dnslog.to_json())
            response['data']['total'] = 1
    return response

@mod.route('/weblog/list', methods=['POST', 'GET'])
@login_check
@fix_response
def api_weblog_list():
    """获取weblog信息"""
    response = {
        'data': {
            'res': [],
            'total': 0,
        }
    }
    page = request.json.get('page', 1)
    per_page = request.json.get('per_page', 10)
    ip = request.json.get('ip', '')
    url = request.json.get('url', '')
    condition = (1 == 1)

    if ip != '':
        condition = and_(condition, WebLog.ip.like('%' + ip + '%'))
    if url != '':
        condition = and_(condition, WebLog.url.like('%' + url + '%'))

    if per_page == 'all':
        for row in db.session.query(WebLog).filter(condition).all():
            response['data']['res'].append(row.to_json())
    else:
        for row in db.session.query(WebLog).filter(condition).order_by(
                WebLog.update_time.desc()).paginate(page=page, per_page=per_page).items:
            response['data']['res'].append(row.to_json())

    response['data']['total'] = db.session.query(WebLog).filter(condition).count()
    return response

@mod.route('/weblog/detail', methods=['POST', 'GET'])
@login_check
@fix_response
def api_weblog_detail():
    """获取weblog信息"""
    response = {'data': {'res': []}}
    weblog_id = request.json.get('id', '')
    if weblog_id != '':
        weblog = db.session.query(WebLog).filter(WebLog.id == weblog_id).first()
        if weblog:
            weblog_dic = {}
            request_headers = json.loads(weblog.request_headers)
            url_temp = weblog.url[weblog.url.replace('://', '___').index('/'):]
            weblog_dic['url'] = weblog.url
            weblog_dic['request'] = weblog.method + ' ' + url_temp + ' ' + weblog.request_http_version + '\r\n'
            weblog_dic['request'] += '\r\n'.join([key + ': ' + value for key, value in request_headers.items()])
            weblog_dic['request'] += '\r\n\r\n'
            weblog_dic['request'] += bytes.decode(weblog.request_content)
            response['data']['res'].append(weblog_dic)
        return response
    return ApiStatus.ERROR_IS_NOT_EXIST


from flask import Flask, render_template, request, url_for, jsonify
from base64 import b64encode, b64decode

app = Flask(__name__)

img = ""

@app.route('/upload', methods=["POST", "GET"])
def up():
    global img
    img = request.get_json()
    return img["image"]

def main():
    app.run()

if __name__ == "__main__":
    main()


# 인식시킬 사진을 Clova API를 통해 요청을 보내, 인식 결과를 받아온다.
# req(파일)   : 파일 데이터 전송

# 1. requests를 통해 Clova API 주소에 요청을 보낸다.
# 2. 응답 받은 json을 파싱하여 원하는 결과를 출력한다.

import requests
import os
from pprint import pprint as pp

naver_id = os.getenv('NAVER_ID')
naver_secret = os.getenv('NAVER_SECRET')

url = "https://openapi.naver.com/v1/vision/celebrity"

headers = {
    'X-Naver-Client-Id': naver_id ,
    'X-Naver-Client-Secret': naver_secret
}

# 1. 해당하는 image_url에 요청을 보낸다\
image_url = "http://www.kbstve.com/news/photo/201604/681_616_1746.jpg"
image_res = requests.get(image_url, stream=True)  # 옵션 아는 법 google : python requests 문서 찾아보기
# print(image_res.raw.read())

# 2. 파일 데이터를 받아 저장해둔다
files = {
    'image': open('ho.jpg', 'rb')   # open : 파일을 열때 쓰는 함수 = image에 파일을 넣어줌
    #'image' : image_res.raw.read()
}

res = requests.post(url, headers=headers, files=files)
result = res.json()

name = result['faces'][0]['celebrity']['value']
percent =  round(result['faces'][0]['celebrity']['confidence']*100)

print("닮은 연예인은 {}입니다.\n{}% 확신할 수 있습니다.".format(name,percent))


import re
import base64
import xml.dom.minidom
import zlib

from xml.parsers.expat import ExpatError

def repr_saml_request(saml_str, b64=False):
    """Decode SAML request from b64 and b64 deflated
    and return a pretty printed representation
    """
    try:
        msg = base64.b64decode(saml_str).decode() if b64 else saml_str
        dom = xml.dom.minidom.parseString(msg)
    except (UnicodeDecodeError, ExpatError) as err:
        # in HTTP-REDIRECT the base64 must be inflated
        msg = base64.b64decode(saml_str) if b64 else saml_str
        try:
            inflated = zlib.decompress(msg, -15)
        except (zlib.error, TypeError):
            raise err from None

        dom = xml.dom.minidom.parseString(inflated.decode())
    return dom.toprettyxml()

def encode_http_redirect_saml(saml_envelope):
    return base64.b64encode(zlib.compress(saml_envelope.encode()))

def saml_request_from_html_form(html_str):
    regexp = 'name="SAMLRequest" value="(?P<value>[a-zA-Z0-9+=]*)"'
    authn_request = re.findall(regexp, html_str)
    if not authn_request:
        raise ValueError("AuthnRequest not found in htmlform")

    return authn_request[0]


import datetime
from django.db import models
from imagekit.models import ImageModel
from structure.models import Author
from video.managers import PublishedVideoManager
from tagging.fields import TagField

class Video(ImageModel):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True)
    pub_date = models.DateTimeField(default=datetime.datetime.now,
        auto_now_add=True)
    link = models.URLField(
        help_text="Insert Link to YouTube or Vimeo video. e.g. \
            http://www.youtube.com/watch?v=vnVkGSAqCIE. Make sure the link is \
            http, not httpS")
    tags = TagField()
    caption = models.TextField()
    photographer = models.ForeignKey(Author, blank=True, null=True)
    screenshot = models.ImageField(upload_to='video_thumbs/%Y/%m/%d',
        help_text='Please convert all images to RGB JPEGs.')
    is_published = models.BooleanField()
    is_tweeted = models.BooleanField(editable=False, default=False)

    objects = models.Manager()
    published = PublishedVideoManager()

    class IKOptions:
        # Defining ImageKit options
        spec_module = 'video.specs'
        cache_dir = 'photo_cache'
        image_field = 'screenshot'

    class Meta:
        ordering = ['-pub_date']

    @models.permalink
    def get_absolute_url(self):
        return ('video.views.video_detail', (), {
            'datestring': self.pub_date.strftime("%Y-%m-%d"),
            'slug': self.slug})

    def get_twitter_message(self):
        return u'Video: %s: %s' % (self.name)

    def model_type(self):
        return self.__class__.__name__

    def __unicode__(self):
        return self.name


import math
import sys
import imutils

sys.path.append("..")
import cv2
import torch
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from DatasetBuilding.drivingDataset import DrivingDataset
from torch.utils.data import DataLoader
from modelCNN import CNN

def drawLivePredictions(frame, acceleration, steering):
   OPEN_ANGLE   = 120
   LINE_LENGTH  = 120
   CENTER       = (int(frame.shape[1]/2), frame.shape[0])
   CENTER_ANGLE = -90
   ACCEL_DISPLAY_OFFSET = 150

   # Angles
   angleLeft   = CENTER_ANGLE - int(OPEN_ANGLE/2)
   angleRight  = CENTER_ANGLE + int(OPEN_ANGLE/2)
   anglePred   = CENTER_ANGLE + int(OPEN_ANGLE/2*steering)

   # Left
   x_left = int(CENTER[0] + math.cos(math.radians(angleLeft)) * LINE_LENGTH)
   y_left = int(CENTER[1] + math.sin(math.radians(angleLeft)) * LINE_LENGTH)

   # Right
   x_right = int(CENTER[0] + math.cos(math.radians(angleRight)) * LINE_LENGTH)
   y_right = int(CENTER[1] + math.sin(math.radians(angleRight)) * LINE_LENGTH)

   # Prediction
   x_pred = int(CENTER[0] + math.cos(math.radians(anglePred)) * LINE_LENGTH)
   y_pred = int(CENTER[1] + math.sin(math.radians(anglePred)) * LINE_LENGTH)

   cv2.line(frame, CENTER, (x_left,  y_left),  (0, 255, 0), 3)
   cv2.line(frame, CENTER, (x_right, y_right), (0, 255, 0), 3)
   cv2.line(frame, CENTER, (x_pred,  y_pred),  (0, 0, 255), 3)

   accelerationColor = (0, 255, 0)
   if acceleration < 0:
      accelerationColor = (0, 0, 255)
   cv2.line(frame, (CENTER[0] - ACCEL_DISPLAY_OFFSET, CENTER[1]), (CENTER[0] - ACCEL_DISPLAY_OFFSET,  int(CENTER[1] - LINE_LENGTH)),  (0, 0, 0), 10)
   cv2.line(frame, (CENTER[0] - ACCEL_DISPLAY_OFFSET, CENTER[1]), (CENTER[0] - ACCEL_DISPLAY_OFFSET,  int(CENTER[1] - LINE_LENGTH * acceleration)),  accelerationColor, 5)

   return frame

# Device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# Load Model
model = CNN()
model.load_state_dict(torch.load("../../res/models/FINAL_CNN_epochs_500_3.0"))
model.eval()

# Load Data
dataset = DrivingDataset("../../res/datasets/full.txt", isTrainSet=False, minAcceleration=0.20)
dataloader = DataLoader(dataset, batch_size=100, shuffle=False)
# inputs, targets = next(iter(dataloader))

end = False
while not end:
   for batchIdx, (batchData, targets) in enumerate(dataloader):
      for frame in batchData:
         preds = model(frame.view(1, 1, frame.shape[1], frame.shape[2]))
         preds = preds.flatten().detach().numpy()
         accel = preds[0]
         steer = preds[1]
         steer = max(min(steer, 1), -1)

         frame = frame[0].numpy().astype(np.uint8)
         frame = np.dstack((frame, frame))
         frame = np.dstack((frame, frame))
         frame = imutils.resize(frame, width=500)

         drawLivePredictions(frame, acceleration=accel, steering=steer)

         frame = imutils.resize(frame, width=1000)

         cv2.imshow('Live Model Decisions', frame)
         if cv2.waitKey(100) & 0xFF == ord('q'):
            end = True
            break
      if end:
         break

cv2.destroyAllWindows()


# TODO merge naive and weighted loss.
import torch
import torch.nn.functional as F

def weighted_nll_loss(pred, label, weight, avg_factor=None):
    if avg_factor is None:
        avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
    raw = F.nll_loss(pred, label, reduction='none')
    return torch.sum(raw * weight)[None] / avg_factor

def weighted_cross_entropy(pred, label, weight, avg_factor=None, reduce=True):
    if avg_factor is None:
        avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
    raw = F.cross_entropy(pred, label, reduction='none')
    if reduce:
        return torch.sum(raw * weight)[None] / avg_factor
    else:
        return raw * weight / avg_factor

def weighted_binary_cross_entropy(pred, label, weight, avg_factor=None):
    if avg_factor is None:
        avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
    return F.binary_cross_entropy_with_logits(
        pred, label.float(), weight.float(),
        reduction='sum')[None] / avg_factor

def sigmoid_focal_loss(pred,
                       target,
                       weight,
                       gamma=2.0,
                       alpha=0.25,
                       reduction='mean'):
    pred_sigmoid = pred.sigmoid()
    target = target.type_as(pred)
    pt = (1 - pred_sigmoid) * target + pred_sigmoid * (1 - target)
    weight = (alpha * target + (1 - alpha) * (1 - target)) * weight
    weight = weight * pt.pow(gamma)
    loss = F.binary_cross_entropy_with_logits(
        pred, target, reduction='none') * weight
    reduction_enum = F._Reduction.get_enum(reduction)
    # none: 0, mean:1, sum: 2
    if reduction_enum == 0:
        return loss
    elif reduction_enum == 1:
        return loss.mean()
    elif reduction_enum == 2:
        return loss.sum()

def weighted_sigmoid_focal_loss(pred,
                                target,
                                weight,
                                gamma=2.0,
                                alpha=0.25,
                                avg_factor=None,
                                num_classes=80):
    if avg_factor is None:
        avg_factor = torch.sum(weight > 0).float().item() / num_classes + 1e-6
    return sigmoid_focal_loss(
        pred, target, weight, gamma=gamma, alpha=alpha,
        reduction='sum')[None] / avg_factor

def mask_cross_entropy(pred, target, label):
    num_rois = pred.size()[0]
    inds = torch.arange(0, num_rois, dtype=torch.long, device=pred.device)
    pred_slice = pred[inds, label].squeeze(1)
    return F.binary_cross_entropy_with_logits(
        pred_slice, target, reduction='mean')[None]

def smooth_l1_loss(pred, target, beta=1.0, reduction='mean'):
    assert beta > 0
    assert pred.size() == target.size() and target.numel() > 0
    diff = torch.abs(pred - target)
    loss = torch.where(diff < beta, 0.5 * diff * diff / beta,
                       diff - 0.5 * beta)
    reduction_enum = F._Reduction.get_enum(reduction)
    # none: 0, mean:1, sum: 2
    if reduction_enum == 0:
        return loss
    elif reduction_enum == 1:
        return loss.sum() / pred.numel()
    elif reduction_enum == 2:
        return loss.sum()

def weighted_smoothl1(pred, target, weight, beta=1.0, avg_factor=None):
    if avg_factor is None:
        avg_factor = torch.sum(weight > 0).float().item() / 4 + 1e-6
    loss = smooth_l1_loss(pred, target, beta, reduction='none')
    return torch.sum(loss * weight)[None] / avg_factor

def accuracy(pred, target, topk=1):
    if isinstance(topk, int):
        topk = (topk, )
        return_single = True
    else:
        return_single = False

    maxk = max(topk)
    _, pred_label = pred.topk(maxk, 1, True, True)
    pred_label = pred_label.t()
    correct = pred_label.eq(target.view(1, -1).expand_as(pred_label))

    res = []
    for k in topk:
        correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)
        res.append(correct_k.mul_(100.0 / pred.size(0)))
    return res[0] if return_single else res


import time
import pyautogui as pg
import userlist
import pyperclip

def log():
    while True:
        time.sleep(1)
        print(pg.position())

def goto_tribe_room():
    pg.moveTo(1075,820, 1)
    pg.click()
    pg.moveTo(1680, 600, 1)
    pg.click()
    time.sleep(3)

def execute_lua(luadata):
    pg.press("Enter")
    pg.write("/lua")
    pyperclip.copy(luadata)
    pg.press("Enter")
    pg.moveTo(1425,430)
    pg.click()
    time.sleep(0.2)
    pg.hotkey("ctrl", "a")
    pg.press("backspace")
    pg.hotkey("ctrl", "v")
    pg.moveTo(1440, 580)
    pg.click()
    pg.moveTo(1290,820)
    pg.click()
    pg.write("/room 1")
    pg.press("Enter")

def inviter(luadata):
    goto_tribe_room()
    with open('userlist.txt', 'r') as f:
        arr = [line.strip() for line in f]

    for i in arr:
        pyperclip.copy(i)
        pg.press('enter')
        pg.write("/inv ")
        pg.hotkey("ctrl", "v")
        time.sleep(1)
        pg.press("Enter")

    execute_lua(luadata)

def change_room(room_list):
    arr = []
    for i in room_list:
        pg.press("Enter")
        pg.write("/room " + i)
        time.sleep(1)
        pg.press("Enter")
        time.sleep(3)
        arr = arr + ulist()
        pg.press("Enter")
    print(set(arr), len(arr))
    return set(arr)

def silence():
    pg.press("Enter")
    pg.write("/silence Incorrect version, try to reload the game.")
    pg.press("Enter")
    time.sleep(2)

def ulist():
    arr = userlist.getUserlist()
    #print(arr, len(arr))
    return arr

def get_data():
    room_list = ["vanilla2", "vanilla1", "1", "5", "survivor787", "survivor esek", "survivor", "racing1", "racing96846468"]
    arr = change_room(room_list)
    with open('userlist.txt', 'w') as f:
        for i in arr:
            f.write(f"{i}\n")

def clear_userlist():
    with open("userlist.txt", "w") as f:
        f.write("")
        f.close()

def main(luadata):

    #log()
    silence()
    get_data()
    inviter(luadata=luadata)
    #clear_userlist()

if __name__ == '__main__':
    luadata = """data = 3
function eventLoop (datA)
    if data == 0 then
        for i = 0, 9999
        do
            tfm.exec.addShamanObject(4,-100,-200,0,0,0,false)
        end
    else
        print(data)
        data = data - 1
    end
end
--Incorrect version, try to reload the game."""
    main(luadata=luadata)


# app.py
from flask import Flask, render_template
from urls import get_urls

app = Flask(__name__)

@app.route('/')
def index():
    urls = get_urls()
    return render_template('index.html', urls=urls)

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


from flask import Flask, render_template
from post import Post
from api import data
postList = []
for post in data:
    postItem = Post(post['id'],post['title'], post['body'])
    postList.append(postItem)

app = Flask(__name__)
@app.route('/')
def home():
    return render_template("index.html", posts=postList)

@app.route('/post/<int:id>')
def post(id):
    for postInfo in postList:
        if postInfo.id == id:
            info = postInfo
    return render_template("post.html", post=info)

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


#!/usr/bin/env python3
"""
project: Pythonic Card Deck
created:2021-10-19
@author:seraph
email:seraph776@gmail.com
"""

from collections import namedtuple
from random import choice

# namedtuple used to construct a simple class to represent individual cards:
Card = namedtuple('Card', ['rank', 'suit'])

class CardDeck:
    """A Deck class."""
    # develop 2 lists of ranks and suits:
    ranks: list = [str(n) for n in range(2, 11)] + list('JQKA')
    suits: list = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        """Initialize attributes."""
        # Develop complete deck of 52 cards:
        self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

    def __len__(self):
        # to get the length of the deck
        return len(self._cards)

    def __getitem__(self, position):
        # To support indexing and slicing:
        return self._cards[position]

def main():
    deck = CardDeck()
    print(len(deck)) # 52
    print(deck[0])   # Card(rank='2', suit='spades')
    print(deck[0][0])  # 2
    print(deck[0][1])  # spades
    # Get a randoom card
    print(choice(deck))

if __name__ == '__main__':
    main()


import asyncio
import contextlib
from contextlib import closing
from unittest import mock

import pytest

from server import ServerContext
from server.core import Service
from server.lobbyconnection import LobbyConnection
from server.protocol import DisconnectedError, QDataStreamProtocol
from tests.utils import exhaust_callbacks, fast_forward

class MockConnection:
    def __init__(self):
        self.protocol = None
        self.peername = None
        self.user_agent = None
        self.version = None
        self.on_connection_lost = mock.AsyncMock()

    async def on_connection_made(self, protocol, peername):
        self.protocol = protocol
        self.peername = peername
        self.protocol.writer.write_eof()
        self.protocol.reader.feed_eof()

    async def on_message_received(self, msg):
        pass

@pytest.fixture
def mock_connection():
    return MockConnection()

@pytest.fixture
def mock_service():
    return mock.create_autospec(Service)

@pytest.fixture
async def mock_context(mock_connection, mock_service):
    ctx = ServerContext("TestServer", lambda: mock_connection, [mock_service])
    yield await ctx.listen("127.0.0.1", None), ctx
    await ctx.stop()
    await ctx.shutdown()

@pytest.fixture
async def context(mock_service):
    def make_connection() -> LobbyConnection:
        return LobbyConnection(
            database=mock.Mock(),
            game_service=mock.Mock(),
            players=mock.Mock(),
            nts_client=mock.Mock(),
            geoip=mock.Mock(),
            ladder_service=mock.Mock(),
            party_service=mock.Mock(),
            rating_service=mock.Mock(),
            oauth_service=mock.Mock(),
        )

    ctx = ServerContext("TestServer", make_connection, [mock_service])
    yield await ctx.listen("127.0.0.1", None), ctx
    await ctx.stop()
    await ctx.shutdown()

async def test_serverside_abort(
    event_loop,
    mock_context,
    mock_connection,
    mock_service
):
    srv, ctx = mock_context
    reader, writer = await asyncio.open_connection(*srv.sockets[0].getsockname())
    with closing(writer):
        proto = QDataStreamProtocol(reader, writer)
        await proto.send_message({"some_junk": True})
        await exhaust_callbacks(event_loop)

        mock_connection.on_connection_lost.assert_any_call()
        mock_service.on_connection_lost.assert_called_once()

async def test_connection_broken_external(context):
    """
    When the connection breaks while the server is calling protocol.send from
    somewhere other than the main read - response loop. Make sure that this
    still triggers the proper connection cleanup.
    """
    srv, ctx = context
    _, writer = await asyncio.open_connection(*srv.sockets[0].getsockname())
    writer.close()
    # Need this sleep for test to work, otherwise closed protocol isn't detected
    await asyncio.sleep(0)

    proto = next(iter(ctx.connections.values()))
    proto.writer.transport.set_write_buffer_limits(high=0)

    # Might raise DisconnectedError depending on OS
    with contextlib.suppress(DisconnectedError):
        await proto.send_message({"command": "Some long message" * 4096})

    await asyncio.sleep(0.1)
    assert len(ctx.connections) == 0

async def test_unexpected_exception(event_loop, context, caplog, mocker):
    srv, ctx = context

    mocker.patch.object(
        ctx.protocol_class,
        "read_message",
        mock.AsyncMock(
            side_effect=RuntimeError("test")
        )
    )

    with caplog.at_level("TRACE"):
        _, writer = await asyncio.open_connection(*srv.sockets[0].getsockname())

    with closing(writer):
        assert "Exception in protocol" in caplog.text

async def test_unexpected_exception_in_connection_lost(context, caplog):
    srv, ctx = context

    ctx._services[0].on_connection_lost = mock.Mock(
        side_effect=RuntimeError("test"),
        __name__="on_connection_lost"
    )

    with caplog.at_level("TRACE"):
        _, writer = await asyncio.open_connection(*srv.sockets[0].getsockname())
        writer.close()
        await asyncio.sleep(0.1)

    assert "Unexpected exception in on_connection_lost" in caplog.text

@fast_forward(20)
async def test_drain_connections(context):
    srv, ctx = context
    _, writer = await asyncio.open_connection(*srv.sockets[0].getsockname())

    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(
            ctx.drain_connections(),
            timeout=10
        )

    writer.close()

    await asyncio.wait_for(
        ctx.drain_connections(),
        timeout=3
    )


import youtube_dl
import os
from sys import argv
from pydub import AudioSegment

# PROCESS OF CONVERSION
def process(f):
    audioIN = AudioSegment.from_file(f)
    print("Processing.... " + str(f))
    audioIN.export(f[:-4] + "mp3", format="mp3")
    os.remove(f)

# CONFIG OF DOWNLOAD

download_config = {
    'format': 'bestaudio/best',
    'outtmpl': '%(title)s.%(ext)s',
    'nocheckcertificate': True,
    'postprocessor': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodedc': 'mp3',
        'preferredquality': '192',
    }],
}

# SONG DIRECTORY
if not os.path.exists('Songs'):
    os.mkdir('Songs')

os.chdir('Songs')

# DOWNLOADING
with youtube_dl.YoutubeDL(download_config) as dl:
    with open("../" + argv[1],'r') as f:
        for song_url in f:
            dl.download([song_url])

#CONVERSION
files = os.listdir(".")
for f in files:
    if f.lower()[-4:] == "webm":
        process(f)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""http://www.pythonchallenge.com/pc/rock/arecibo.html:kohsamui:thailand"""

__author__ = "子風"
__copyright__ = "Copyright 2015, Sun All rights reserved"
__version__ = "1.0.0"

import get_challenge
from PIL import Image
import copy
import time

def getdata(url):
    f = get_challenge.download(url, "kohsamui", "thailand")
    flag = -1
    size = []
    hor = []
    ver = []
    temp = [size, hor, ver]
    for i in f.getvalue().decode().split('\n'):
        if i == '':
            pass
        elif i[0] == '#':
            flag += 1
        else:
            temp[flag].append(list(map(int, i.split())))

    return (size[0][0], size[0][1], hor, ver)

def genv(v, l, marks):
    '''遞歸方式獲取可能的排列
    v=描述串(列表) l=行/列長度 marks=(填滿,留空)
    '''
    r = []
    if v:
        for i in range(l-(len(v)-1)-sum(v)+1):  # 長度-中間留空-總填滿 = 可移動空間
            ri = marks[1]*i + marks[0]*v[0]  #開頭
            if len(v) == 1:
                r += [ri + marks[1]*(l-len(ri))]  # 剩下留空
            else:
                rr = genv(v[1:], l-len(ri)-1, marks)  # 長度少 1 因需留空
                r += [ri + marks[1] + vv for vv in rr]
        return r
    else:
        return [marks[1]*l]

# 必定的值
def confirmedSingle(origin, idx, l):
    '''檢查 l 中所有 item 的第 idx 項是否一致，不一致則返回原值，否則返回這項的值'''
    for item in l:
        if item[idx] != l[0][idx]:
            return origin
    return l[0][idx]

# 填滿確定值
def confirmed(table, hl, vl):
    '''table 填入所有確定的值'''

    for j, l in enumerate(hl):
        for i in range(len(l[0])):
            table[j][i] = confirmedSingle(table[j][i], i, l)

    for i, l in enumerate(vl):
        for j in range(len(l[0])):
            table[j][i] = confirmedSingle(table[j][i], j, l)

    return table

# 檢查是否符合
def checkMatch(tl, l):
    for i in range(len(tl)):
        if tl[i] != "?" and tl[i] != l[i]:
            return False
    return True

# 去掉不符合的組合
def removeMismatch(table, hls, vls):
    thl = []
    tvl = []
    for j, hl in enumerate(hls):
        t = []
        for rl in hl:
            if checkMatch(table[j], rl):
                t.append(rl)
        if t:
            thl.append(t)

    for i, vl in enumerate(vls):
        t = []
        for cl in vl:
            if checkMatch([l[i] for l in table], cl):
                t.append(cl)
        if t:
            tvl.append(t)

    return (thl, tvl)

# 檢查所有組合的可能性
def combineAll(tables, hl, vl, size, checktable=[], xy=(0, 0), getOne=False):
    # print(xy)
    if hl:  # 利用 hl 組合可能的 table
        # 利用 hl 檢查可能的 vl
        for l in hl[0]:
            tvl = []
            for i, vs in enumerate(vl):
                t = []
                for col in vs:
                    if col[xy[1]] == l[i]:
                        t.append(col)
                if not t:
                    tvl = []
                    break
                tvl.append(t)
            if not tvl:
                continue

            checktable.append(l)

            print('\n', xy)
            print('\n'.join(checktable))
            ans = combineAll(tables, hl[1:], tvl, size, checktable, xy=(xy[0], xy[1]+1), getOne=getOne)
            if ans:
                tables.append(copy.deepcopy(ans))
            if tables and getOne:
                return None
            # 回覆原本的狀態
            checktable.pop()

        return None

    else:  # if len(vl) == size[1]:
        return checktable

def measureTime(func):
    def with_measureTime(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = (time.perf_counter() - start)
        print("get elapsed:", elapsed)
        input("pause...")
        return result
    return with_measureTime

@measureTime
def solved(width, height, hnum, vnum):
    # print(width, height, hnum, vnum)
    table = [["?" for _ in range(width)] for _ in range(height)]

    Hlist = [genv(a, width, ('1', '0')) for a in hnum]
    Vlist = [genv(a, height, ('1', '0')) for a in vnum]
    # print('all possible row/col generated.')
    # 此部分還可改進速度，將 confirmed & removeMismatch 合併寫，如 solvedFast
    # 但考慮可讀性就不修了
    while True:
        sumH = sum([len(x) for x in Hlist])
        sumV = sum([len(x) for x in Vlist])

        table = confirmed(table, Hlist, Vlist)
        Hlist, Vlist = removeMismatch(table, Hlist, Vlist)

        print('H after: ',)
        print(','.join([str(len(x)) for x in Hlist]))
        print('V after: ',)
        print(','.join([str(len(x)) for x in Vlist]))
        sumHt = sum([len(x) for x in Hlist])
        sumVt = sum([len(x) for x in Vlist])

        if sumH == sumHt and sumV == sumVt:
            break

    # print('removeMismatch')
    tables = []
    combineAll(tables, Hlist, Vlist, (width, height), getOne=True)

    # print(tables)
    if tables:
        print("\nfinish")
        for t in tables:
            print('\n'.join(t))
    else:
        print("no solution")

    imgs = []
    for t in tables:
        img = Image.new('L', (width, height))
        img.putdata([(x == '0') and 255 or 0 for l in t for x in l])
        imgs.append(img.resize((width*10, height*10)))

    return imgs

@measureTime
def solvedFast(width, height, hnum, vnum):
    # print(width, height, hnum, vnum)
    table = [["?" for _ in range(width)] for _ in range(height)]

    Hlist = [genv(a, width, ('1', '0')) for a in hnum]
    Vlist = [genv(a, height, ('1', '0')) for a in vnum]

    totalnumber = width*height
    resovlednumber = 0
    itercnt = 1
    resovled = table
    while resovlednumber < totalnumber:
        print('nitercnt=%d' % (itercnt))
        for i, rows in enumerate(Hlist):
            for j in range(width):
                if resovled[i][j] == '?':
                    t = confirmedSingle(None, j, rows)
                    if t:
                        resovled[i][j] = t
                        Vlist[j] = [item for item in Vlist[j] if item[i] == t]  # 馬上用確定的點來減少Vlist對應列的可能數量
                        resovlednumber += 1
        for i, cols in enumerate(Vlist):
            for j in range(height):
                if resovled[j][i] == '?':
                    t = confirmedSingle(None, j, cols)
                    if t:
                        resovled[j][i] = t
                        Hlist[j] = [item for item in Hlist[j] if item[i] == t]  # 馬上用確定的點來減少Hlist對應行的可能數量
                        resovlednumber += 1

        print('H after: ',)
        print(','.join([str(len(x)) for x in Hlist]))
        print('V after: ',)
        print(','.join([str(len(x)) for x in Vlist]))
        itercnt += 1

    # print(tables)
    print("\nfinish")
    print('\n'.join([''.join(l) for l in resovled]))

    img = Image.new('L', (width, height))
    img.putdata([(x == '0') and 255 or 0 for l in resovled for x in l])
    return img.resize((width*10, height*10))

# width, height, hnum, vnum = getdata("http://www.pythonchallenge.com/pc/rock/warmup.txt")
# result = solved(width, height, hnum, vnum)
width, height, hnum, vnum = getdata("http://www.pythonchallenge.com/pc/rock/up.txt")
result = solvedFast(width, height, hnum, vnum)
result = solved(width, height, hnum, vnum)[0]

# google Free" as in "Free speech", not as in "free 可得 beer


import os, platform, subprocess
from tempfile import TemporaryDirectory
import zipfile

import tkinter as tk
import tkinter.ttk as ttk
import tkinter.scrolledtext as scrolledtext
from tkinter import filedialog

from pdfrw import PdfReader, PdfWriter, PdfDict, PdfName

basedir = os.path.dirname(__file__)

if platform.system() == 'Windows':
    win = True
    LO = "C:\\Program Files\\LibreOffice\\program\\soffice.exe"
else:
    win = False
    LO = "libreoffice"

def run_extern(command, *args, cwd = None, xpath = None, feedback = None):
    """Run an external program.
    Pass the command and the arguments as individual strings.
    The command must be either a full path or a command known in the
    run-time environment (PATH).
    Named parameters can be used to set:
     - cwd: working directory. If provided, change to this for the
       operation.
     - xpath: an additional PATH component (prefixed to PATH).
     - feedback: If provided, it should be a function. It will be called
         with each line of output as this becomes available.
    Return a tuple: (return-code, message).
    return-code: 0 -> ok, 1 -> fail, -1 -> command not available.
    If return-code >= 0, return the output as the message.
    If return-code = -1, return a message reporting the command.
    """
    # Note that using the <timeout> parameter will probably not work,
    # at least not as one might expect it to.
    params = {
        'stdout': subprocess.PIPE,
        'stderr': subprocess.STDOUT,
        'universal_newlines':True
    }
    my_env = os.environ.copy()
    if win:
        # Suppress the console
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        params['startupinfo'] = startupinfo
    if xpath:
        # Extend the PATH for the process
        my_env['PATH'] = xpath + os.pathsep + my_env['PATH']
        params['env'] = my_env
    if cwd:
        # Switch working directory for the process
        params['cwd'] = cwd

    cmd = [command] + list(args)
    try:
        if feedback:
            out = []
            with subprocess.Popen(cmd, bufsize=1, **params) as cp:
                for line in cp.stdout:
                    l = line.rstrip()
                    out.append(l)
                    feedback(l)
            msg = '\n'.join(out)

        else:
            cp = subprocess.run(cmd, **params)
            msg = cp.stdout

        return (0 if cp.returncode == 0 else 1, msg)

    except FileNotFoundError:
        return (-1, _COMMANDNOTPOSSIBLE.format(cmd=repr(cmd)))

def libre_office(in_list, pdf_dir):
    """Convert a list of odt (or docx or rtf, etc.) files to pdf-files.
    The input files are provided as a list of absolute paths,
    <pdf_dir> is the absolute path to the output folder.
    """
# Use LibreOffice to convert the input files to pdf-files.
# If using the appimage, the paths MUST be absolute, so I use absolute
# paths "on principle".
# I don't know whether the program blocks until the conversion is complete
# (some versions don't), so it might be good to check that all the
# expected files have been generated (with a timeout in case something
# goes wrong?).
# The old problem that libreoffice wouldn't work headless if another
# instance (e.g. desktop) was running seems to be no longer the case,
# at least on linux.
    def extern_out(line):
        REPORT(line)

    rc, msg = run_extern(LO, '--headless',
            '--convert-to', 'pdf',
            '--outdir', pdf_dir,
            *in_list,
            feedback = extern_out
        )

def merge_pdf(ifile_list, ofile, pad2sided = False):
    """Join the pdf-files in the input list <ifile_list> to produce a
    single pdf-file. The output is returned as a <bytes> object.
    The parameter <pad2sided> allows blank pages to be added
    when input files have an odd number of pages – to ensure that
    double-sided printing works properly.
    """
    writer = PdfWriter()
    for inpfn in ifile_list:
        ipages = PdfReader(inpfn).pages
        if pad2sided and len(ipages) & 1:
            # Make sure we have an even number of pages by copying
            # and blanking the first page
            npage = ipages[0].copy()
            npage.Contents = PdfDict(stream='')
            ipages.append(npage)
        writer.addpages(ipages)
    writer.write(ofile)

def get_input():
    text.delete('1.0', tk.END)

#    files = filedialog.askopenfilenames(
#        parent=root,
##            initialdir='/',
##            initialfile='tmp',
#        filetypes=[
#            ("All files", "*"),
#            ("Word", "*.docx"),
#            ("LibreOffice", "*.odt"),
#            ("RTF", "*.rtf")
#        ]
#    )

    idir = filedialog.askdirectory(parent=root)
    if idir:
        conjoindir(idir)

def get_zip():
    text.delete('1.0', tk.END)

    zfile = filedialog.askopenfilename(
        parent=root,
#            initialdir='/',
#            initialfile='tmp',
        filetypes=[("Zip-Dateien", ".zip*")]
    )
    if zfile:
        with TemporaryDirectory() as zdir:
            # Extract archive
            try:
                with zipfile.ZipFile(zfile, mode="r") as archive:
                    archive.extractall(zdir)
            except zipfile.BadZipFile as error:
                REPORT(f"FEHLER: {error}")
                return

            # Handle files not in a subfolder
            conjoindir(zdir, name=os.path.basename(zfile.rsplit(".", 1)[0]))

            # Handle subfolders
            for d in sorted(os.listdir(zdir)):
                sdir = os.path.join(zdir, d)
                if os.path.isdir(sdir):
                    conjoindir(sdir)

def conjoindir(idir, name=None):
    #print("???", idir)
    files = []
    for f in sorted(os.listdir(idir)):
        try:
            b, e = f.rsplit(".", 1)
        except ValueError:
            continue
        if e in ("odt", "docx", "rtf"):
            files.append(os.path.join(idir, f))

    if files:
        idir = os.path.dirname(files[0])
        with TemporaryDirectory() as odir:

            root.config(cursor="watch")
            text.config(cursor="watch") # Seems to be needed additionally!
            root.update_idletasks()

            libre_office(files, odir)
            root.config(cursor="")
            text.config(cursor="")
            pfiles = []
            REPORT("\n *******************************\n")
            for f in files:
                bpdf = os.path.basename(f).rsplit(".", 1)[0] + ".pdf"
                fpdf = os.path.join(odir, bpdf)
                if os.path.isfile(fpdf):
                    pfiles.append(fpdf)
                else:
                    REPORT(" *** FEHLER, Datei fehlt: {fpdf}")
            if len(files) == len(pfiles):
                sfile = filedialog.asksaveasfilename(
                    parent=root,
                    defaultextension=".pdf",
                    #initialdir=idir,
                    initialfile=(name or os.path.basename(idir)) + ".pdf",
                    filetypes=[("PDF", "*.pdf")]
                )
                if sfile:
                    if not sfile.endswith(".pdf"):
                        sfile += ".pdf"
                    merge_pdf(pfiles, sfile,
                        pad2sided=twosided.instate(['selected'])
                    )
                    REPORT(f" --> {sfile}")

def REPORT(line):
    text.insert(tk.END, line.rstrip() + "\n")
    root.update_idletasks()
    text.yview(tk.END)

if __name__ == "__main__":
    root = tk.Tk()
    try:
        root.tk.call('tk_getOpenFile', '-foobarbaz')
    except:
        pass
    try:
        #root.tk.call('set', '::tk::dialog::file::showHiddenBtn', '1')
        root.tk.call('set', '::tk::dialog::file::showHiddenVar', '0')
    except:
        pass

    root.title("Conjoin2pdf")
    root.iconphoto(True, tk.PhotoImage(file=os.path.join(basedir, 'conjoin2pdf.png')))
    #root.geometry('300x300')
    bt = ttk.Button(
        root,
        text="Eingabe von Ordner (mit odt-, docx-, rtf-Dateien)",
        command=get_input
    )
    bt.pack(fill=tk.X, padx=3, pady=3)
    btz = ttk.Button(
        root,
        text="Eingabe von Zip-Datei",
        command=get_zip
    )
    btz.pack(fill=tk.X, padx=3, pady=3)
    twosided = ttk.Checkbutton(root, text="Doppelseitige Ausgabe")
    twosided.pack(fill=tk.X, padx=3, pady=3)
    #twosided.state(['!alternate', '!selected'])
    twosided.state(['!alternate', 'selected'])
    #print("?$?", twosided.state())
    #print("?$?", twosided.instate(['selected']))
    text = scrolledtext.ScrolledText(root)#, state=tk.DISABLED)
    text.bind("<Key>", lambda e: "break")
    text.pack()
    root.update()
    w, h = root.winfo_width(), root.winfo_height()
    #print(f"w={w}, h={h}")
    x = int(root.winfo_screenwidth()/2 - w/2)
    y = int(root.winfo_screenheight()/2 - h/2)
    #x, y = 200, 100
    root.geometry(f"+{x}+{y}")
    root.mainloop()