from __future__ import print_function

import os
import numpy as np

import torch as t
import torch.nn as nn
from torch.optim.lr_scheduler import ReduceLROnPlateau
from torch.autograd import Variable
from torchnet import meter

from .log import logger

def get_learning_rates(optimizer):
    lrs = [pg['lr'] for pg in optimizer.param_groups]
    lrs = np.asarray(lrs, dtype=np.float)
    return lrs

class TrainParams(object):
    # required params
    max_epoch = 30

    # optimizer and criterion and learning rate scheduler
    optimizer = None
    criterion = None
    lr_scheduler = None         # should be an instance of ReduceLROnPlateau or _LRScheduler

    # params based on your local env
    gpus = []                   # default to use CPU mode
    save_dir = './models/'            # default `save_dir`

    # loading existing checkpoint
    ckpt = None                 # path to the ckpt file

    # saving checkpoints
    save_freq_epoch = 1         # save one ckpt per `save_freq_epoch` epochs

class Trainer(object):

    TrainParams = TrainParams

    def __init__(self, model, train_params, train_data, val_data=None):
        assert isinstance(train_params, TrainParams)
        self.params = train_params

        # Data loaders
        self.train_data = train_data
        self.val_data = val_data

        # criterion and Optimizer and learning rate
        self.last_epoch = 0
        self.criterion = self.params.criterion
        self.optimizer = self.params.optimizer
        self.lr_scheduler = self.params.lr_scheduler
        logger.info('Set criterion to {}'.format(type(self.criterion)))
        logger.info('Set optimizer to {}'.format(type(self.optimizer)))
        logger.info('Set lr_scheduler to {}'.format(type(self.lr_scheduler)))

        # load model
        self.model = model
        logger.info('Set output dir to {}'.format(self.params.save_dir))
        if os.path.isdir(self.params.save_dir):
            pass
        else:
            os.makedirs(self.params.save_dir)

        ckpt = self.params.ckpt
        if ckpt is not None:
            self._load_ckpt(ckpt)
            logger.info('Load ckpt from {}'.format(ckpt))

        # meters
        self.num_iter = self.model.num_iterations
        self.loss_meter = meter.AverageValueMeter()
        # self.confusion_matrix = [meter.ConfusionMeter(100), meter.ConfusionMeter(100),
        #                          meter.ConfusionMeter(100), meter.ConfusionMeter(100)]

        # set CUDA_VISIBLE_DEVICES
        if len(self.params.gpus) > 0:
            gpus = ','.join([str(x) for x in self.params.gpus])
            os.environ['CUDA_VISIBLE_DEVICES'] = gpus
            self.params.gpus = tuple(range(len(self.params.gpus)))
            logger.info('Set CUDA_VISIBLE_DEVICES to {}...'.format(gpus))
            self.model = nn.DataParallel(self.model, device_ids=self.params.gpus)
            self.model = self.model.cuda()

        self.model.train()

    def train(self):
        # vis = Visualizer()
        best_loss = np.inf
        for epoch in range(self.last_epoch, self.params.max_epoch):

            self.loss_meter.reset()
            # for i in range(self.num_iter):
            #     self.confusion_matrix[i].reset()

            self.last_epoch += 1
            logger.info('Start training epoch {}'.format(self.last_epoch))

            self._train_one_epoch()

            # save model
            if (self.last_epoch % self.params.save_freq_epoch == 0) or (self.last_epoch == self.params.max_epoch - 1):
                save_name = self.params.save_dir + 'ckpt_epoch_{}.pth'.format(self.last_epoch)
                t.save(self.model.state_dict(), save_name)

            self._val_one_epoch()

            if self.loss_meter.value()[0] < best_loss:
                logger.info('Found a better ckpt ({:.3f} -> {:.3f}), '.format(best_loss, self.loss_meter.value()[0]))
                best_loss = self.loss_meter.value()[0]

            # print info
            logger.info("The end of epoch:{epoch}, lr:{lr}, train loss:{loss}:".format(
                epoch=epoch, loss=self.loss_meter.value()[0], lr=get_learning_rates(self.optimizer)
            ))

            # adjust the lr
            # if epoch == 81 or epoch == 122:
            #     for i, param_group in enumerate(self.optimizer.param_groups):
            #         old_lr = float(param_group['lr'])
            #         new_lr = old_lr * 0.1
            #         param_group['lr'] = new_lr
            #         print('Epoch {:5d}: reducing learning rate'
            #               ' of group {} from {:.4e} to {:.4e}.'.format(epoch, i, old_lr, new_lr))
            if isinstance(self.lr_scheduler, ReduceLROnPlateau):
                self.lr_scheduler.step(self.loss_meter.value()[0], self.last_epoch)

    def _load_ckpt(self, ckpt):
        self.model.load_state_dict(t.load(ckpt))

    def _train_one_epoch(self):
        self.model.train()
        train_correct = np.zeros(self.num_iter)
        train_total = 0
        gamma = 1

        for step, (data, label) in enumerate(self.train_data):
            # train model
            inputs = Variable(data)
            target = Variable(label)
            loss = Variable(t.from_numpy(np.zeros(1))).float()
            if len(self.params.gpus) > 0:
                inputs = inputs.cuda()
                target = target.cuda()
                loss = loss.cuda()

            # forward
            outputs = self.model(inputs)
            losses = [self.criterion(out, target) for out in outputs]
            for it in range(len(losses)):
                loss += (gamma ** it) * losses[it]

            # backward
            self.optimizer.zero_grad()
            loss.backward(retain_graph=True)
            self.optimizer.step(None)

            # meters update
            self.loss_meter.add(loss.data[0])
            # for i in range(self.num_iter):
            #     self.confusion_matrix[i].add(outputs[i].data, target.data)

            # calculate correct number
            train_total += target.size(0)
            for it in range(self.num_iter):
                _, predicted = t.max(outputs[it].data, 1)
                train_correct[it] += (predicted == target.data).sum()

        for it in range(self.num_iter):
            print('Train accuracy for iteration %i: %f %%' % (it, 100 * train_correct[it] / train_total))

    def _val_one_epoch(self):
        self.model.eval()
        logger.info('Val on validation set...')
        correct_tp1 = np.zeros(self.num_iter)
        correct_tp5 = np.zeros(self.num_iter)
        total = 0

        for step, (data, label) in enumerate(self.val_data):
            # val model
            inputs = Variable(data, volatile=True)
            if len(self.params.gpus) > 0:
                inputs = inputs.cuda()

            outputs = self.model(inputs)
            total += label.size(0)
            for it in range(self.num_iter):
                for p_index, p in enumerate(outputs[it].data):
                    p = p.view(1, 100)
                    if label[p_index] in p.topk(1)[1].squeeze().tolist():
                        correct_tp1[it] += 1
                        correct_tp5[it] += 1
                    elif label[p_index] in p.topk(5)[1].squeeze().tolist():
                        correct_tp5[it] += 1

        for it in range(self.num_iter):
            print('Test accuracy(tp1) for iteration %i: %f %%' % (it, 100 * correct_tp1[it] / total))

        for it in range(self.num_iter):
            print('Test accuracy(tp5) for iteration %i: %f %%' % (it, 100 * correct_tp5[it] / total))


from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize

ps=PorterStemmer()

words='swim swimmer swimming swims swimly'

words=word_tokenize(words)

for w in words:
 print(ps.stem(w))


import json
import qrcode
import platform
import monerorequest
import PySimpleGUI as sg
from datetime import datetime

import config as cfg
import wallet_functions as wallet
import subscription_functions as sub

# MAIN WINDOW & SECTIONS ###############################################################################################
def headline_section():  # Main Window
    layout = [
        [sg.Text("Monero Subscriptions Wallet", font=(cfg.font, 24), expand_x=True, justification='center',
                 relief=sg.RELIEF_RIDGE, size=(None, 1), pad=(0, 0), text_color=cfg.main_text,
                 background_color=cfg.ui_overall_background)],
        [sg.Text("Subscriptions will be paid automatically if the wallet remains open", font=(cfg.font, 10),
                 expand_x=True, justification='center', background_color=cfg.ui_overall_background, pad=(0, 0))],
        [sg.Text("", font=(cfg.font, 8))],
    ]
    return layout

def balance_section():  # Main Window
    layout = [
        [sg.Text(f'        Balance:  ${cfg.wallet_balance_usd} USD', size=(25, 1), font=(cfg.font, 18), key='wallet_balance_in_usd', text_color=cfg.ui_sub_font, background_color=cfg.ui_overall_background)],
        [sg.Text(f'        XMR: {cfg.wallet_balance_xmr}', size=(25, 1), font=(cfg.font, 18), key='wallet_balance_in_xmr', background_color=cfg.ui_overall_background)],
    ]
    return layout

def deposit_section():  # Main Window
    layout = [
        [sg.Text('Deposit XMR:', size=(20, 1), font=(cfg.font, 18), justification='center', text_color=cfg.ui_sub_font,
                 background_color=cfg.ui_overall_background)],
        [sg.Column([
            [sg.Image(generate_monero_qr(cfg.wallet_address), size=(147, 147), key='qr_code', pad=(10, 0))],
            # Placeholder for the QR code image
            [sg.Button("Copy Address", size=(16, 1), key='copy_address', font=(cfg.font, 10), pad=(10, 10))],
        ],
            element_justification='center', pad=(0, 0))],
    ]
    return layout

def send_section():  # Main Window
    layout = [
        [sg.Text(f'      Send XMR:', size=(12, 1), font=(cfg.font, 14), pad=(10, 10), text_color=cfg.ui_sub_font, background_color=cfg.ui_overall_background),
         sg.InputText(default_text='[ Enter a wallet address ]', key='withdraw_to_wallet', pad=(10, 10), justification='center', size=(46, 1)),
         sg.InputText(default_text=' [ Enter an amount ]', key='withdraw_amount', pad=(10, 10), justification='center', size=(20, 1)),
         sg.Button("Send", size=(8, 1), key='send', font=(cfg.font, 10), pad=(10, 10), button_color=(cfg.ui_button_b_font, cfg.ui_button_b))
         ],
    ]
    return layout

def subscriptions_section(subscriptions):
    # Put all subscriptions into a row
    rows = []

    # Build each row
    for i, sub in enumerate(subscriptions):
        amount, custom_label, renews_in, currency = sub["amount"], sub['custom_label'], sub["days_per_billing_cycle"], sub["currency"]

        payment_is_due, payment_date = wallet.determine_if_a_payment_is_due(sub)

        if not payment_is_due and payment_date:
            days = wallet.check_date_for_how_many_days_until_payment_needed(date=payment_date, number_of_days=renews_in)
            renews_in = round(days)

        currency_indicator_left, currency_indicator_right = ('$', ' USD') if currency == 'USD' else ('', f' {currency}')

        layout = [
            sg.Text(f'    {currency_indicator_left}{amount}{currency_indicator_right}', justification='left', size=(12, 1), text_color=cfg.subscription_text_color, background_color=cfg.subscription_background_color),
            sg.Column([
                [sg.Text(custom_label, justification='center', size=(None, 1), text_color=cfg.subscription_text_color, background_color=cfg.subscription_background_color)]
            ], expand_x=True),
            sg.Text(f'Renews in {renews_in} day(s)', justification='right', size=(16, 1), text_color=cfg.subscription_text_color, background_color=cfg.subscription_background_color),
            sg.Button("Cancel", size=(7, 1), key=f'cancel_subscription_{i}', font=(cfg.font, 10), button_color=(cfg.ui_regular, cfg.ui_barely_visible)),
        ]

        rows.append(layout)

    add_button_layout = [[sg.Button("Add Monero Payment Request", size=(40, 1), key='add_subscription', font=(cfg.font, 12), pad=(10, 10))]]
    add_button_column = sg.Column(add_button_layout, expand_x=True, element_justification='center')

    rows.append([add_button_column])

    subscriptions_column = sg.Column(rows, key='subscriptions_column', pad=(10, 10))

    frame = sg.Frame('Upcoming Payments', layout=[[subscriptions_column]], key='subscriptions_frame', element_justification='center', pad=(10, 10), background_color=cfg.subscription_background_color)

    return [[frame]]

def main_window_layout():
    # Define the window layout
    layout = [
        ######## TOP SIDE
        # Title
        *headline_section(),
        ######## END TOP SIDE
        [
            sg.Column(
                [
                    ######## LEFT SIDE
                    # Balances
                    *balance_section(),
                    # Subscriptions
                    *subscriptions_section(subscriptions=cfg.subscriptions),
                    ######## END LEFT SIDE

                ], element_justification='center', expand_x=True, expand_y=True
            ),

            # Middle Separator
            sg.VerticalSeparator(pad=(0, 10)),

            sg.Column(
                [
                    ######## RIGHT SECTION
                    # Deposit QR Code
                    *deposit_section()
                    ######## END RIGHT SECTION

                ], expand_x=True, expand_y=True, element_justification='c'
            )
        ],

        [sg.Text("", font=(cfg.font, 8), expand_x=True, justification='center', size=(None, 1), pad=(0, 0),
                 text_color=cfg.main_text, background_color=cfg.ui_overall_background)],

        ######## BOTTOM SIDE
        [sg.Column([

            # Send Section
            *send_section(),

        ], element_justification='c', justification='center'),
            sg.Text('', pad=(15, 15))],
        ######## END BOTTOM SIDE

        [sg.Text("", font=(cfg.font, 8), expand_x=True, justification='center', size=(None, 1), pad=(0, 0),
                 text_color=cfg.main_text, background_color=cfg.ui_overall_background)],
    ]

    return layout

# POPUP LAYOUTS ########################################################################################################
def make_please_wait_popup():
    text_line_1 = 'Please Wait: Monero RPC Server Is Starting'
    text_line_2 = '                                   This may take a few minutes on first launch.'

    layout = [
        [sg.Text(text_line_1, key="wait_text", font=(cfg.font, 18), background_color=cfg.ui_overall_background)],
        [sg.Text(text_line_2, key="wait_text2", font=(cfg.font, 10), background_color=cfg.ui_overall_background)]
    ]
    return layout

def make_node_window_layout():
    layout = [
        [sg.Column([
            [sg.Text("Add A Monero Node:", font=(cfg.font, 24), text_color=cfg.monero_orange, background_color=cfg.ui_overall_background)],
            [sg.Text("     For maximum privacy: Add your own node, or one run by someone you trust     \n", font=(cfg.font, 16), text_color=cfg.ui_sub_font, background_color=cfg.ui_overall_background)],
            [
                sg.Input(default_text='node.sethforprivacy.com:18089', key='custom_node', justification='center', size=(30, 2), font=(cfg.font, 18)),
                sg.Button('Add Node', key='add_node', font=(cfg.font, 12), size=(12, 1), button_color=(cfg.ui_button_a_font, cfg.ui_button_a))
            ],
            [sg.Text('', font=(cfg.font, 4))],
            [sg.Text("...or add a random node (NOT RECOMMENDED)\n", font=(cfg.font, 12), text_color=cfg.ui_sub_font, background_color=cfg.ui_overall_background)],
            [sg.Button('          Add A Random Node          ', key='add_random_node', font=(cfg.font, 12), button_color=(cfg.ui_button_b_font, cfg.ui_button_b))],
            [sg.Text('')],
            [sg.Text("Random nodes pulled from: https://Monero.fail\n", font=(cfg.font, 10), text_color=cfg.monero_orange, background_color=cfg.ui_overall_background)],
        ], element_justification='c', justification='center')]
    ]

    return layout

def review_payment_layout(subscription_json):
    headline = "     Add This Payment Request?     "
    text_line_1 = f"     {str(subscription_json['custom_label'])}:     "
    text_line_2 = f"     {str(subscription_json['amount'])} {str(subscription_json['currency'])} worth of Monero will be sent to the merchant{' every ' + str(subscription_json['days_per_billing_cycle']) + ' days.     ' if subscription_json['number_of_payments'] > 1 or subscription_json['number_of_payments'] == 0 else '.     '}"
    text_line_3 = f"     You will be billed {'until canceled.     ' if subscription_json['number_of_payments'] == 0 else str(subscription_json['number_of_payments']) + ' time(s) in total.     '}"

    layout = [
        # Headline
        [sg.Column([
            [sg.Text(headline, font=(cfg.font, 18), text_color=cfg.ui_sub_font)],
        ], justification='center', background_color=cfg.ui_title_bar)],

        # Content
        [sg.Column([
            [sg.Text("")],
            [sg.Text(text_line_1, font=(cfg.font, 16), background_color=cfg.ui_overall_background)],
            [sg.Text("")],
            [sg.Text(text_line_2, font=(cfg.font, 14), background_color=cfg.ui_overall_background)],
            [sg.Text("")],
            [sg.Text(text_line_3, font=(cfg.font, 14), background_color=cfg.ui_overall_background)],
            [sg.Text("")],
            [
                sg.Button("     Confirm     ", key="yes", font=(cfg.font, 12)),
                sg.Button("     Cancel     ", key="no", font=(cfg.font, 12), button_color=(cfg.ui_regular, cfg.ui_barely_visible))
            ],
            [sg.Text("")]
        ], element_justification='c', justification='center')]
    ]

    return layout

def merchant_subscription_layout():
    dev_sub_code = ''

    layout = [
        [sg.Column([
            [sg.Text("     Paste Monero Payment Request Below     ", font=(cfg.font, 18), text_color=cfg.ui_sub_font)],
        ], justification='center', background_color=cfg.ui_title_bar)],

        [sg.Column([
            [sg.Text("")],
            [sg.Multiline(size=(80, 8), key="subscription_info", do_not_clear=False, autoscroll=False, default_text=dev_sub_code)],
            [sg.Text("")],
            [
                sg.Button("    Add Payment Request    ", key="add_merchant_subscription", font=(cfg.font, 12)),
                sg.Button("    Cancel    ", key="cancel_merchant_subscription", font=(cfg.font, 12), button_color=(cfg.ui_regular, cfg.ui_barely_visible))
            ],
            [sg.Text("")]
        ], element_justification='c', justification='center')]
    ]

    return layout

def manual_subscription_layout():
    today = datetime.today().strftime("%Y-%m-%d")  # Placeholder to display as a suggested start date

    layout = [

        # Headline
        [sg.Column([
            [sg.Text("Enter Monero Payment Details", font=(cfg.font, 18), text_color=cfg.ui_sub_font)],
        ], justification='center', background_color=cfg.ui_title_bar)],

        # Fields
        [sg.Column([
            [sg.Text("")],

            [sg.Text("Custom Name:", background_color=cfg.ui_overall_background),
             sg.Input(size=(35, 1), key="custom_label")],

            [sg.Text("Amount:", background_color=cfg.ui_overall_background),
             sg.Input(size=(15, 1), key="amount", default_text='0.00'),
             sg.Combo(cfg.supported_currencies, default_value=cfg.supported_currencies[0], key="currency")],

            [sg.Text("Billing Every:", background_color=cfg.ui_overall_background),
             sg.Input(size=(3, 1), key="days_per_billing_cycle"),
             sg.Text("Day(s)", background_color=cfg.ui_overall_background)],

            [sg.Text("Start Date (YYYY-MM-DD):", background_color=cfg.ui_overall_background),
             sg.Input(default_text=today, size=(10, 1), key="start_date")],

            [sg.Text("Total Number of Payments:", background_color=cfg.ui_overall_background),
             sg.Input(size=(3, 1), key="number_of_payments"),
             sg.Text("(For recurring until canceled, use 0)", background_color=cfg.ui_overall_background)],

            [sg.Text("Seller's Wallet:", background_color=cfg.ui_overall_background),
             sg.Input(size=(102, 1), key="sellers_wallet")],

            [sg.Text("Optional Change Indicator URL:", background_color=cfg.ui_overall_background),
             sg.Input(size=(60, 1), key="change_indicator_url"),
             sg.Text("(For advanced sellers)", background_color=cfg.ui_overall_background)],

            [sg.Text("Optional Payment ID From Seller:", background_color=cfg.ui_overall_background),
             sg.Input(size=(20, 1), key="payment_id"),
             sg.Text("(A random payment_id will be generated if left blank)", background_color=cfg.ui_overall_background)],

            [sg.Text("")],

            # Buttons
            [sg.Column([
                [
                    sg.Button("    Add Payment    ", key="add_manual_subscription", font=(cfg.font, 12)),
                    sg.Button("    Cancel    ", key="cancel_manual_subscription", font=(cfg.font, 12), button_color=(cfg.ui_regular, cfg.ui_barely_visible))
                ]], justification='center', element_justification='c')]
        ], element_justification='l')]
    ]

    return layout

# EVENT LOOPS ##########################################################################################################
def create_main_window(subscriptions, location=(None, None)):  # Creates the main window and returns it
    if platform.system() == 'Darwin':
        return sg.Window(cfg.title_bar_text, layout=main_window_layout(), margins=(20, 20), titlebar_icon='',
                         titlebar_background_color=cfg.ui_overall_background, use_custom_titlebar=False,
                         grab_anywhere=True, icon=cfg.icon_png_path, finalize=True, location=location)
    elif platform.system() == 'Linux':
        return sg.Window(cfg.title_bar_text, layout=main_window_layout(), margins=(20, 20), titlebar_icon='',
                         titlebar_background_color=cfg.ui_overall_background, use_custom_titlebar=False,
                         grab_anywhere=True, icon=cfg.icon_png_path, finalize=True, location=location)
    else:
        return sg.Window('', layout=main_window_layout(), margins=(20, 20), titlebar_icon='',
                         titlebar_background_color=cfg.ui_overall_background, use_custom_titlebar=True,
                         grab_anywhere=True, icon=cfg.icon, finalize=True, location=location)

def review_payment_popup(subscription_json, location=(None, None)):

    window = sg.Window("Are you sure?", layout=review_payment_layout(subscription_json), modal=True, margins=(20, 20),
                       background_color=cfg.ui_title_bar, titlebar_icon='', no_titlebar=True, use_custom_titlebar=True,
                       grab_anywhere=True, icon=cfg.icon, location=location)

    while True:
        event, values = window.read()

        # NO BUTTON PRESSED (OR CLOSE BUTTON)
        if event == sg.WIN_CLOSED or event == "no":
            window.close()
            break

        # YES BUTTON PRESSED
        elif event == "yes":
            sub.add_subscription(subscription_json)
            window.close()
            break

def add_subscription_from_merchant(location=(None, None)):
    window = sg.Window(cfg.title_bar_text, layout=merchant_subscription_layout(), modal=True, margins=(20, 20),
                       background_color=cfg.ui_title_bar, titlebar_icon='', no_titlebar=True, use_custom_titlebar=True,
                       grab_anywhere=True, icon=cfg.icon, location=location)

    while True:
        event, values = window.read()

        # CLOSE BUTTON PRESSED
        if event == sg.WIN_CLOSED or event == "cancel_merchant_subscription":
            break

        # ADD MERCHANT SUBSCRIPTION BUTTON PRESSED
        elif event == "add_merchant_subscription":
            subscription_info = values["subscription_info"]
            subscription_info = subscription_info.strip()  # in case user added any spaces or new lines

            if len(subscription_info) < 1:
                print("Merchant code cannot be empty! Not adding.")

            else:
                # Check if the user submitted a JSON dictionary rather than a Monero Payment Request
                if '{' in subscription_info[0] and '}' in subscription_info[len(subscription_info) - 1]:
                    try:
                        subscription_json = json.loads(subscription_info)

                        # Calculate location to be in the center of cfg.window position
                        location = calculate_window_position(main_window=cfg.window, layout_creation_func=lambda: review_payment_layout(subscription_json))

                        review_payment_popup(subscription_json, location=location)
                    except:
                        print('JSON for subscription is not valid. Not adding.')

                else:  # Assume that the user submitted a Monero Payment Request
                    try:
                        subscription_json = monerorequest.decode_monero_payment_request(subscription_info)

                        # Calculate location to be in the center of cfg.window position
                        location = calculate_window_position(main_window=cfg.window, layout_creation_func=lambda: review_payment_layout(subscription_json))

                        review_payment_popup(subscription_json, location=location)
                    except:
                        print('Monero subscription code is not valid. Not adding.')
                break
            break
    window.close()

def confirm_send_layout():
    layout = [
        [sg.Column([
            [sg.Text(f"Are you sure you want to send all your XMR to this address?\n", font=(cfg.font, 18), text_color=cfg.ui_sub_font)]
        ], justification='center', background_color=cfg.ui_title_bar)],

        [sg.Column([
            [
                sg.Button("     Confirm     ", key="confirm", font=(cfg.font, 12)),
                sg.Button("     Cancel     ", key="cancel", font=(cfg.font, 12), button_color=(cfg.ui_regular, cfg.ui_barely_visible)),
            ],
        ], element_justification='c', justification='center', expand_x=True, background_color=cfg.ui_title_bar)]
    ]

    return layout

def confirm_send(location=(None, None)):
    window = sg.Window('', layout=confirm_send_layout(), no_titlebar=True, background_color=cfg.ui_title_bar, modal=True, grab_anywhere=True, icon=cfg.icon, location=location)

    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED or event == 'cancel':
            print("Cancelled wallet sweep!")
            break
        elif event == 'confirm':
            wallet.send_monero(destination_address=cfg.withdraw_to_wallet, amount=cfg.xmr_unlocked_balance)
            print("The wallet has been swept!")
            break

    window.close()

def manual_or_from_code_layout():
    layout = [
        [sg.Column([
            [sg.Text("     Add Payment Request:     ", font=(cfg.font, 18), text_color=cfg.ui_sub_font)],
        ], justification='center', background_color=cfg.ui_title_bar)],

        [sg.Column([
            [
                sg.Button("    From Merchant    ", key="merchant", font=(cfg.font, 12)),
                sg.Button("    Manually    ", key="manually", font=(cfg.font, 12), button_color=(cfg.ui_regular, cfg.ui_barely_visible)),
            ],
        ], element_justification='c', justification='center', expand_x=True, background_color=cfg.ui_title_bar)]
    ]

    return layout

def manual_or_from_code(location=(None, None)):
    window = sg.Window('', layout=manual_or_from_code_layout(), no_titlebar=True, background_color=cfg.ui_title_bar, modal=True, grab_anywhere=True, icon=cfg.icon, location=location)

    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED:
            break

        elif event == 'manually':
            # Calculate location to be in the center of cfg.window position
            location = calculate_window_position(main_window=cfg.window, layout_creation_func=lambda: manual_subscription_layout())

            add_subscription_manually(location=location)
            break

        elif event == 'merchant':
            # Calculate location to be in the center of cfg.window position
            location = calculate_window_position(main_window=cfg.window, layout_creation_func=lambda: merchant_subscription_layout())

            add_subscription_from_merchant(location=location)
            break

    window.close()

def add_subscription_manually(location=(None, None)):
    window = sg.Window(cfg.title_bar_text, layout=manual_subscription_layout(), modal=True, margins=(20, 20),
                       titlebar_icon='', no_titlebar=True, background_color=cfg.ui_title_bar, use_custom_titlebar=True,
                       grab_anywhere=True, icon=cfg.icon, location=location)
    # Event Loop
    while True:
        event, values = window.read()

        # CLOSE BUTTON PRESSED
        if event == sg.WIN_CLOSED or event == "cancel_manual_subscription":
            break

        # ADD MANUAL SUBSCRIPTION BUTTON PRESSED
        elif event == "add_manual_subscription":
            custom_label = values["custom_label"]
            sellers_wallet = values["sellers_wallet"]
            currency = values["currency"]
            amount = values["amount"]
            start_date = monerorequest.convert_datetime_object_to_truncated_RFC3339_timestamp_format(
                datetime_object=datetime.strptime(values["start_date"], "%Y-%m-%d"))
            days_per_billing_cycle = int(values["days_per_billing_cycle"])
            number_of_payments = int(values["number_of_payments"])
            change_indicator_url = values["change_indicator_url"]

            try:
                payment_id = values["payment_id"]
            except:
                payment_id = None

            if not payment_id:
                payment_id = monerorequest.make_random_payment_id()  # generates a random payment ID.

            subscription_info = monerorequest.make_monero_payment_request(
                custom_label=custom_label,
                sellers_wallet=sellers_wallet,
                currency=currency,
                amount=amount,
                payment_id=payment_id,
                start_date=start_date,
                days_per_billing_cycle=days_per_billing_cycle,
                number_of_payments=number_of_payments,
                change_indicator_url=change_indicator_url)

            subscription_json = monerorequest.decode_monero_payment_request(subscription_info)
            sub.add_subscription(subscription_json)

            print(custom_label)
            print(sellers_wallet)
            print(currency)
            print(amount)
            print(payment_id)
            print(start_date)
            print(days_per_billing_cycle)
            print(number_of_payments)
            print(change_indicator_url)

            print(subscription_info)

            window.close()
            break

    window.close()

# ACTIONS & EFFECTS ####################################################################################################
def refresh_gui():
    cfg.subscriptions = sub.read_subscriptions()
    old_window = cfg.window
    location = old_window.CurrentLocation()
    cfg.window = create_main_window(subscriptions=cfg.subscriptions, location=location)
    old_window.close()

def make_transparent():
    # Make the main window transparent
    cfg.window.TKroot.attributes('-alpha', 0.00)

def make_visible():
    # Make the main window transparent
    cfg.window.TKroot.attributes('-alpha', 1.00)

def calculate_window_position(main_window, layout_creation_func):
    # Create a layout using the provided function
    temp_layout = layout_creation_func()

    # Create an off-screen popup to measure its size
    offscreen_popup = sg.Window('Temp', temp_layout, location=(2000, 2000))
    offscreen_popup.read(timeout=1)
    offscreen_popup.hide()

    # Fetch location and sizes
    x, y = main_window.CurrentLocation()
    w_main, h_main = main_window.size
    w_popup, h_popup = offscreen_popup.size

    # Calculate the centered position
    new_x = int(x + w_main // 2 - w_popup // 2)
    new_y = int(y + h_main // 2 - h_popup // 2)
    offscreen_popup.close()

    location = (new_x, new_y)
    return location

# OTHER VISUALS ########################################################################################################
def generate_monero_qr(wallet_address=cfg.wallet_address):
    if monerorequest.Check.wallet(wallet_address=wallet_address, allow_standard=True, allow_integrated_address=False,
                                  allow_subaddress=False):
        # Generate the QR code
        qr = qrcode.QRCode(version=1, box_size=3, border=4)
        qr.add_data("monero:" + wallet_address)
        qr.make(fit=True)
        qr_img = qr.make_image(fill_color=cfg.monero_orange, back_color=cfg.ui_overall_background)
        # Save the image to a file
        filename = "wallet_qr_code.png"
        with open(filename, "wb") as f:
            qr_img.save(f, format="PNG")
        return filename

    else:
        print('Monero Address is not valid')
        return None


import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
import sklearn.datasets
from matplotlib import pyplot as plt
import sklearn
from sklearn.metrics import roc_curve, auc
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB

def get_iris_df():
    ds = sklearn.datasets.load_iris()
    df = pd.DataFrame(ds['data'], columns=ds['feature_names'])
    code_species_map = dict(zip(range(3), ds['target_names']))
    df['species'] = [code_species_map[c] for c in ds['target']]
    return df

df = get_iris_df()

# 분류기 이름 -> (선 스타일, 분류기 인스턴스)
CLASS_MAP = {
    '로지스틱 회귀':
        ('-', LogisticRegression()),
    '나이브 베이즈':
        ('--', GaussianNB()),
    '결정 트리':
        ('.-', DecisionTreeClassifier(max_depth=5)),
    '렌덤 포레스트':
        (':', RandomForestClassifier(
                max_depth=5, n_estimators=10,
                max_features=1)),
}
print(df)
# 데이터프레임의 행을 학습/시험셋으로 나눈다.

X, Y = df[df.columns[:3]], (df['species']=='virginica')
X_train, X_test, Y_train, Y_test = \
    train_test_split(X, Y, test_size=.8)

for name, (line_fmt, model) in CLASS_MAP.items():
    model.fit(X_train, Y_train)
    # 열마다 True/False 예측값을 저장한다.
    preds = model.predict_proba(X_test) # shape: (120, 2)
    pred = pd.Series(preds[:,1])
    fpr, tpr, thresholds = roc_curve(Y_test, pred)
    auc_score = auc(fpr, tpr)
    label = '%s: auc=%f' % (name, auc_score)
    plt.plot(fpr, tpr, line_fmt, linewidth=5, label=label)

plt.legend(loc="lower right")
plt.title('분류기 성능 비교')

plt.plot([0,1], [0, 1], 'k--') # 비교를 위해 x=y 라인 추가
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('거짓 양성비')
plt.ylabel('참 양성비')
plt.show()


import poseidon.poseidon
from requests.models import PreparedRequest

def DeleteLogicalAsset(accessKey, secretKey, orgId, url, assetId):
    accessURL = url + '/asset-service/v2.1/logical-assets'
    params = {"action": "delete", "orgId": orgId}
    req = PreparedRequest()
    req.prepare_url(accessURL, params)
    print(req.url)

    body = {"assetId": assetId}
    print(body)

    response = poseidon.poseidon.urlopen(accessKey, secretKey, req.url, body)
    print(response)


#定义函数，用cKDTree匹配点与点
import numpy as np
import pandas as pd
from CoordinatesConverter import gcj02tobd09,bd09togcj02,wgs84togcj02,gcj02towgs84,wgs84tobd09,bd09towgs84,getdistance
from scipy.spatial import cKDTree
import itertools
from operator import itemgetter
#定义KDTree的函数
def ckdnearest(dfA_origin,dfB_origin,Aname = ['lon','lat'],Bname = ['lon','lat']):
    '''
    输入两个DataFrame，分别指定经纬度列名，为表A匹配表B中最近点，并计算距离
    '''
    gdA = dfA_origin.copy()
    gdB = dfB_origin.copy()
    from scipy.spatial import cKDTree
    #为gdB表的点建立KDTree
    btree = cKDTree(gdB[Bname].values)
    #在gdB的KDTree中查询gdA的点,dist为距离,idx为gdB中离gdA最近的坐标点
    dist,idx = btree.query(gdA[Aname].values,k = 1)
    #构建匹配的结果
    gdA['index'] = idx
    gdB['index'] = range(len(gdB))
    gdf = pd.merge(gdA,gdB,on = 'index')
    #计算
    if (Aname[0] == Bname[0])&(Aname[1] == Bname[1]):
        gdf['dist'] = getdistance(gdf[Aname[0]+'_x'],gdf[Aname[1]+'_y'],gdf[Bname[0]+'_x'],gdf[Bname[1]+'_y'])
    else:
        gdf['dist'] = getdistance(gdf[Aname[0]],gdf[Aname[1]],gdf[Bname[0]],gdf[Bname[1]])
    return gdf
def ckdnearest_point(gdA, gdB):
    '''
    输入两个geodataframe，gdfA、gdfB均为点，该方法会为gdfA表连接上gdfB中最近的点，并添加距离字段dsit
    '''
    #提取gdA中的所有点要素
    nA = np.array(list(gdA.geometry.apply(lambda x: (x.x, x.y))))
    #提取gdB中的所有点要素
    nB = np.array(list(gdB.geometry.apply(lambda x: (x.x, x.y))))
    #为gdB表的点建立KDTree
    btree = cKDTree(nB)
    #在gdB的KDTree中查询gdA的点,dist为距离,idx为gdB中离gdA最近的坐标点
    dist, idx = btree.query(nA, k=1)
    #构建匹配的结果
    gdA['dist'] = dist
    gdA['index'] = idx
    gdB['index'] = range(len(gdB))
    gdf = pd.merge(gdA,gdB,on = 'index')
    return gdf
def ckdnearest_line(gdfA, gdfB):
    '''
    输入两个geodataframe，其中gdfA为点，gdfB为线，该方法会为gdfA表连接上gdfB中最近的线，并添加距离字段dsit
    '''
    #提取gdA中的所有点要素
    A = np.concatenate(
        [np.array(geom.coords) for geom in gdfA.geometry.to_list()])
    #把gdfB的几何坐标提取到B，此时B为一个大list中包含多个小list，每个小list代表一个几何图形，小list中为坐标
    #B=[[[要素1坐标1],[要素1坐标2],...],[[要素2坐标1],[要素2坐标2],...]]
    B = [np.array(geom.coords) for geom in gdfB.geometry.to_list()]
    #B_ix代表B中的每个坐标点分别属于B中的哪个几何图形
    B_ix = tuple(itertools.chain.from_iterable(
        [itertools.repeat(i, x) for i, x in enumerate(list(map(len, B)))]))
    #把B表展开，B=[[要素1坐标1],[要素1坐标2],...,[要素2坐标2],[要素2坐标2],...]
    B = np.concatenate(B)
    #为B表建立KDTree
    ckd_tree = cKDTree(B)
    #在B的KDTree中查询A的点,dist为距离,idx为B中离A最近的坐标点
    dist, idx = ckd_tree.query(A, k=1)
    #由坐标点对应到几何要素
    idx = itemgetter(*idx)(B_ix)
    #构建匹配的结果
    gdfA['dist'] = dist
    gdfA['index'] = idx
    gdfB['index'] = range(len(gdfB))
    gdf = pd.merge(gdfA,gdfB,on = 'index')
    return gdf


#
# @lc app=leetcode id=735 lang=python3
#
# [735] Asteroid Collision
#

# @lc code=start
class Solution:
    def asteroidCollision(self, asteroids: List[int]) -> List[int]:
        res = []
        for new in asteroids:
            while res and new < 0 < res[-1]:
                if res[-1] < -new:
                    res.pop()
                    continue
                elif res[-1] == -new:
                    res.pop()
                break
            else:
                res.append(new)
        return res
# @lc code=end


"""
求一个数组中最小值与最大值的最小公倍数
lcm = a*b/gcd(a,b)
"""
import math
t = int(input())
for i in range(t):
    n = int(input())
    inp = [int(x) for x in input().split(" ")]
    inp.sort()
    min_num = inp[0]
    max_num = inp[-1]
    lcm = (min_num*max_num) // math.gcd(max_num, min_num)
    print(lcm)


import http.client

# Mengatur host dan port server
HOST = 'localhost'
PORT = 8080

# Membuat koneksi dengan server
conn = http.client.HTTPConnection(HOST, PORT)

# Meminta input pengguna
file_path = input("Masukkan path file yang ingin Anda minta: ")

# Mengirim permintaan ke server
conn.request('GET', file_path)

# Menerima respon dari server
response = conn.getresponse()

# Membaca data respon sebagai string
data = response.read().decode('utf-8')

# Menampilkan respon di terminal client
print(data)

# Menutup koneksi dengan server
conn.close()


from pyslam.metrics import TrajectoryMetrics
from matplotlib import rc
import matplotlib.pyplot as plt
import numpy as np

import matplotlib
# Removes the XWindows backend (useful for producing plots via tmux without -X)
matplotlib.use('Agg', warn=False)

plt.rc('text', usetex=True)
plt.rc('font', family='serif')

class TrajectoryVisualizer:
    """Visualization utility to create nice plots from TrajectoryMetrics."""

    def __init__(self, tm_dict):
        self.tm_dict = tm_dict
        """Dictionary of TrajectoryMetrics objects to plot."""

        self.endpoint_markers_list = ['o', '^', 's', '*', 'p', 'h',
                                      'X', 'D', 'P',  'v', '<', '>',
                                      '8', 'H', 'd']

    def _parse_kwargs(self, kwargs):
        plot_params = {}
        plot_params['gt_linewidth'] = kwargs.get('gt_linewidth', 2.)
        plot_params['est_linewidth'] = kwargs.get('est_linewidth', 1.)
        plot_params['grid_linewidth'] = kwargs.get('grid_linewidth', 0.2)
        plot_params['use_endpoint_markers'] = kwargs.get(
            'use_endpoint_markers', False)
        plot_params['fontsize'] = kwargs.get('fontsize', 10)
        plot_params['legend_fontsize'] = kwargs.get(
            'legend_fontsize', plot_params['fontsize'])
        plot_params['err_xlabel'] = kwargs.get('err_xlabel', 'Timestep')
        plot_params['line_colours'] = kwargs.get('line_colours', [
                                                 'tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 'tab:brown'])

        for key in plot_params.keys():
            try:
                del kwargs[key]
            except KeyError:
                pass

        return plot_params

    def plot_topdown(self, which_plane='xz', segment_range=None, outfile=None, **kwargs):
        """ Plot a top - down view of the trajectory.

            Args:
                which_plane     : which plane to plot ['xy' | 'xz' | 'yz']
                segment_range   : which segment of the trajectory to plot
                outfile         : full path and filename where the plot should be saved
                **kwargs        : additional keyword arguments passed to plt.subplots()
        """
        if which_plane == 'xy':
            x_dim, y_dim = 0, 1
        elif which_plane == 'xz':
            x_dim, y_dim = 0, 2
        elif which_plane == 'yz':
            x_dim, y_dim = 1, 2
        else:
            raise ValueError(
                "which_plane must be ['xy' | 'xz' | 'yz']. Got {}".format(which_plane))

        # Grab plot parameters, pass the rest to subplots
        plot_params = self._parse_kwargs(kwargs)

        # Use a sane default figsize if the user doesn't specify one
        figsize = kwargs.get('figsize', (4, 3))
        kwargs.update({'figsize': figsize})

        fig, ax = plt.subplots(**kwargs)

        if plot_params['use_endpoint_markers']:
            endpoint_markers_iter = iter(self.endpoint_markers_list)

        plotted_gt = False

        for p_i, (label, tm) in enumerate(self.tm_dict.items()):
            pos_gt = np.array([T.trans for T in tm.Twv_gt])
            pos_est = np.array([T.trans for T in tm.Twv_est])

            if segment_range is not None:
                pos_gt = pos_gt[segment_range, :]
                pos_est = pos_est[segment_range, :]

            if not plotted_gt:
                if plot_params['use_endpoint_markers']:
                    ax.plot(pos_gt[:, x_dim], pos_gt[:, y_dim], '-k',
                            linewidth=plot_params['gt_linewidth'],
                            marker=next(endpoint_markers_iter), markevery=[pos_gt.shape[0] - 1],
                            label='Ground Truth')
                else:
                    ax.plot(pos_gt[:, x_dim], pos_gt[:, y_dim], '-k',
                            linewidth=plot_params['gt_linewidth'], label='Ground Truth')

                plotted_gt = True

            if plot_params['use_endpoint_markers']:
                ax.plot(pos_est[:, x_dim], pos_est[:, y_dim],
                        linewidth=plot_params['est_linewidth'], color=plot_params['line_colours'][p_i],
                        marker=next(endpoint_markers_iter), markevery=[pos_est.shape[0] - 1],
                        label=label)
            else:
                ax.plot(pos_est[:, x_dim], pos_est[:, y_dim], color=plot_params['line_colours'][p_i],
                        linewidth=plot_params['est_linewidth'], label=label)

        ax.axis('equal')
        # ax.minorticks_on()
        ax.grid(which='both', linestyle=':',
                linewidth=plot_params['grid_linewidth'])
        ax.set_title('Trajectory', fontsize=plot_params['fontsize'])
        ax.set_xlabel('Easting (m)', fontsize=plot_params['fontsize'])
        ax.set_ylabel('Northing (m)', fontsize=plot_params['fontsize'])
        ax.legend(fontsize=plot_params['legend_fontsize'])

        if outfile is not None:
            print('Saving to {}'.format(outfile))
            fig.savefig(outfile, bbox_inches='tight', transparent=True)

        return fig, ax

    def plot_segment_errors(self, segs, outfile=None, **kwargs):
        """ Plot average errors for specified segment lengths,
            similar to the KITTI odometry leaderboard.

            Args:
                segs    : list of segment lengths to plot
                outfile : full path and filename where the plot should be saved
                **kwargs: additional keyword arguments passed to plt.subplots()
        """
        # Grab plot parameters, pass the rest to subplots
        plot_params = self._parse_kwargs(kwargs)

        # Use a sane default figsize if the user doesn't specify one
        figsize = kwargs.get('figsize', (8, 3))
        kwargs.update({'figsize': figsize})

        fig, ax = plt.subplots(1, 2, **kwargs)
        handles = []
        legend = []

        for p_i, (label, tm) in enumerate(self.tm_dict.items()):
            segerr, avg_segerr = tm.segment_errors(segs)

            h = ax[0].plot(avg_segerr[:, 0], avg_segerr[:, 1]
                           * 100., '-s', color=plot_params['line_colours'][p_i], label=label)
            ax[1].plot(avg_segerr[:, 0], avg_segerr[:, 2]
                       * 180. / np.pi, '-s', color=plot_params['line_colours'][p_i], label=label)

            handles.append(h[0])
            legend.append(label)

        ax[0].minorticks_on()
        ax[0].grid(which='both', linestyle=':',
                   linewidth=plot_params['grid_linewidth'])
        ax[0].set_title('Translational error',
                        fontsize=plot_params['fontsize'])
        ax[0].set_xlabel('Segment length (m)',
                         fontsize=plot_params['fontsize'])
        ax[0].set_ylabel('Avg. err. (\%)',
                         fontsize=plot_params['fontsize'])

        ax[1].minorticks_on()
        ax[1].grid(which='both', linestyle=':',
                   linewidth=plot_params['grid_linewidth'])
        ax[1].set_title('Rotational error',
                        fontsize=plot_params['fontsize'])
        ax[1].set_xlabel('Segment length (m)',
                         fontsize=plot_params['fontsize'])
        ax[1].set_ylabel('Avg. err. (deg/m)',
                         fontsize=plot_params['fontsize'])

        fig.legend(handles, legend, loc='lower center', ncol=len(self.tm_dict),
                   fontsize=plot_params['legend_fontsize'])
        fig.subplots_adjust(wspace=0.3, bottom=0.35)

        if outfile is not None:
            print('Saving to {}'.format(outfile))
            fig.savefig(outfile, bbox_inches='tight', transparent=True)

        return fig, ax

    def _trans_rot_err_subplot(self, err_type, segment_range, outfile, **kwargs):
        """ Convenience function to plot translational and rotational errors in subplots.

            Args:
                err_type        : 'rmse', or 'crmse'
                segment_range   : which segment of the trajectory to plot
                outfile         : full path and filename where the plot should be saved
                **kwargs        : additional keyword arguments passed to plt.subplots()
        """
        # Grab plot parameters, pass the rest to subplots
        plot_params = self._parse_kwargs(kwargs)

        # Use a sane default figsize if the user doesn't specify one
        figsize = kwargs.get('figsize', (8, 3))
        kwargs.update({'figsize': figsize})
        fig, ax = plt.subplots(1, 2, **kwargs)
        handles = []
        legend = []

        for p_i, (label, tm) in enumerate(self.tm_dict.items()):
            if segment_range is None:
                this_segment_range = range(len(tm.Twv_gt))

            if err_type == 'norm':
                trans_err, rot_err = tm.error_norms(this_segment_range)
                err_name = 'Err. Norm.'
            elif err_type == 'cum':
                trans_err, rot_err = tm.cum_err(this_segment_range)
                err_name = 'Cumulative Err. Norm.'
            else:
                raise ValueError(
                    'Got invalid err_type \'{}\''.format(err_type))

            h = ax[0].plot(trans_err, '-',
                           color=plot_params['line_colours'][p_i], label=label)
            ax[1].plot(rot_err * 180. / np.pi, '-',
                       color=plot_params['line_colours'][p_i], label=label)

            handles.append(h[0])
            legend.append(label)

        ax[0].minorticks_on()
        ax[0].grid(which='both', linestyle=':',
                   linewidth=plot_params['grid_linewidth'])
        # ax[0].set_xlim((segment_range.start, segment_range.stop - 1))
        ax[0].set_title('Translational {}'.format(err_name),
                        fontsize=plot_params['fontsize'])
        ax[0].set_xlabel(plot_params['err_xlabel'],
                         fontsize=plot_params['fontsize'])
        ax[0].set_ylabel('{} (m)'.format(err_name),
                         fontsize=plot_params['fontsize'])

        ax[1].minorticks_on()
        ax[1].grid(which='both', linestyle=':',
                   linewidth=plot_params['grid_linewidth'])
        # ax[1].set_xlim((segment_range.start, segment_range.stop - 1))
        ax[1].set_title('Rotational {}'.format(err_name),
                        fontsize=plot_params['fontsize'])
        ax[1].set_xlabel(plot_params['err_xlabel'],
                         fontsize=plot_params['fontsize'])
        ax[1].set_ylabel('{} (deg)'.format(err_name),
                         fontsize=plot_params['fontsize'])

        fig.legend(handles, legend, loc='lower center', ncol=len(self.tm_dict),
                   fontsize=plot_params['legend_fontsize'])
        fig.subplots_adjust(wspace=0.3, bottom=0.35)

        if outfile is not None:
            print('Saving to {}'.format(outfile))
            fig.savefig(outfile, bbox_inches='tight', transparent=True)

        return fig, ax

    def plot_pose_errors(self, segment_range=None, outfile=None, **kwargs):
        """ Plot translational and rotational errors over the trajectory.

            Args:
                segment_range   : which segment of the trajectory to plot
                outfile         : full path and filename where the plot should be saved
                **kwargs        : additional keyword arguments passed to plt.subplots()
        """
        return self._trans_rot_err_subplot('all', segment_range, outfile, **kwargs)

    def plot_norm_err(self, segment_range=None, outfile=None, **kwargs):
        """ Plot translational and rotational error norms over the trajectory.

            Args:
                segment_range   : which segment of the trajectory to plot
                outfile         : full path and filename where the plot should be saved
                **kwargs        : additional keyword arguments passed to plt.subplots()
        """
        return self._trans_rot_err_subplot('norm', segment_range, outfile, **kwargs)

    def plot_cum_norm_err(self, segment_range=None, outfile=None, **kwargs):
        """ Plot cmulative translational and rotational error norms over the trajectory.

            Args:
                segment_range   : which segment of the trajectory to plot
                outfile         : full path and filename where the plot should be saved
                **kwargs        : additional keyword arguments passed to plt.subplots()
        """
        return self._trans_rot_err_subplot('cum', segment_range, outfile, **kwargs)


import threading,time

def addNum():
    global num #在每个线程中都获取这个全局变量
    print('--get num:',num)
    time.sleep(1)
    lock.acquire()
    num -= 1  # 对此公共变量进行-1操作
    lock.release()

lock = threading.Lock()
num = 100 #设定一个共享变量
thread_list = []
for i in range(100):
    t = threading.Thread(target=addNum)
    print(t)
    s = t.start()
    print(s)
    thread_list.append(t)
for t in thread_list: #等待所有线程执行完
    t.join()
print('final num:',num)


from tkinter import *

App=Tk()
menu_c= StringVar()
options=['Red','Blue','White','Yellow']
menu= OptionMenu(App,menu_c,'Red','Blue','White','Yellow')
menu.pack()
t= Toplevel() #adding more windows
t.title('output')
def show():
    msg=Label(App,text='      ', background=(menu_c.get()).lower())
    msg.pack()

B = Button(App, text='show', command=show)
B.pack()
App=mainloop()


from os.path import abspath
import sys
from PyQt5 import QtWidgets, uic
from PyQt5 import QtGui

from src.controller.dialogWindow import ScrapeDialog
from src.scraper.scrapeController import Controller
from src.controller.model import PandasModel
from src.controller.actorWindow import Actor
from src.controller.aboutWindow import About
import src.utility.fileHandler as io

class MainWindow(QtWidgets.QMainWindow):
    """The class to show the main window.

    Args:
        QtWidgets (QtWidgets.QMainWindow): The type of the window.
    """

    def __init__(self):
        """Initializes the main window.
        """

        super().__init__()
        self._url = "https://www.imdb.com/list/ls053501318/"
        self._imdbScraper = Controller(self._url)
        self._aboutWindow = None
        self._dialogWindow = None
        self._newWindow = None
        self._model = None
        self._pathUI = io.getUIPath(abspath(__file__), "mainWindow.ui")
        self._pathIcon = io.getUIPath(abspath(__file__), "imdb.svg")

        # Retrieves the top 50 in case database does not exist (usually happens the very first time)
        #io.createDatabase(self._imdbScraper)

        # Load the .ui file
        uic.loadUi(self._pathUI, self)
        self.setWindowTitle("Top 50 List")
        self.setWindowIcon(QtGui.QIcon(self._pathIcon))

        # Initialize button
        #self.button_scrape.clicked.connect(self._scrape)
        # removed for now in favor of neat design
        self.button_scrape.setVisible(False)

        # Initialize table
        self._fillTable()

        # Set actions
        self.actionExit.triggered.connect(self._exitApp)
        self.actionScrape.triggered.connect(self._showDialogProgress)
        self.actionReload.triggered.connect(self._fillTable)
        self.actionAbout.triggered.connect(self._showAbout)

    def _fillTable(self) -> None:
        """Private method to fill the table with the top 50 list.
        """

        try:
            df = io.getTable("", "top50")
        except OSError:
            self._imdbScraper.getTop()
            df = io.getTable("", "top50")
        self._model = PandasModel(df)
        self.tableView.setModel(self._model)
        # Hide first column of dataframe as it was generated by Pandas
        self.tableView.setColumnHidden(0, True)
        # Click behaviour set up
        self.tableView.doubleClicked.connect(self._showActor)
        self.tableView.setSelectionBehavior(self.tableView.SelectRows)
        # Set up the columns. Last and second to last column get stretched for neat design
        header = self.tableView.horizontalHeader()
        header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
        header.setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)

    def _showActor(self, clickedIndex) -> None:
        """Private method to show the actor window of the clicked index.

        Args:
            clickedIndex (int): The index of the row which is clicked.
        """

        # Retrieve the id of the selected actress or actor
        row=clickedIndex.row()
        model=clickedIndex.model()
        actorID = model._df.iloc[row]["ID"]
        name = model._df.iloc[row]["Name"]
        print("Selected: ", name, "ID: ", actorID)

        # Show new window
        self._newWindow = Actor(actorID)
        self._newWindow.setWindowTitle(name)
        self._newWindow.setWindowIcon(QtGui.QIcon(self._pathIcon))

    def _showAbout(self) -> None:
        """Private method to show the about dialog.
        """

        self._aboutWindow = About()
        self._aboutWindow.setWindowIcon(QtGui.QIcon(self._pathIcon))

    def _exitApp(self) -> None:
        """Private method to shut down the application.
        """

        sys.exit()

    def _showDialogProgress(self) -> None:
        """Private method to show the dialog of the scraping process.
        """

        # todo
        print("Scrape process window")
        self._dialogWindow = ScrapeDialog(self._imdbScraper)
        self._dialogWindow.setWindowIcon(QtGui.QIcon(self._pathIcon))


# -*- coding: utf-8 -*-

"""Main module"""

import inspect
import typing

Self = typing.TypeVar("Self", bound="ClassPropertyDescriptor")

SetterReturnType = typing.TypeVar("SetterReturnType")  # Declare type
GetterReturnType = typing.TypeVar("GetterReturnType")  # Declare type variable
OwningClassType = typing.TypeVar(
    "OwningClassType", bound="object"
)  # Declare type variable

# AnyFuncType = typing.Union[classmethod, staticmethod, typing.Callable[[typing.Any], typing.Any]]
AnyFuncType = typing.Callable[[OwningClassType], GetterReturnType]

class ClassPropertyDescriptor(object):
    def __init__(
        self: Self,
        fget: typing.Union[classmethod, staticmethod],
        fset: typing.Optional[typing.Union[classmethod, staticmethod]] = None,
    ) -> None:
        self.fget = fget
        self.fset = fset

    def __get__(
        self: Self,
        obj: OwningClassType,
        klass: typing.Optional[typing.Type[OwningClassType]] = None,
    ) -> GetterReturnType:
        if klass is None:
            klass = type(obj)
        return self.fget.__get__(obj, klass)()

    def __set__(self: Self, obj: typing.Any, value: typing.Any) -> None:
        if not self.fset:
            raise AttributeError("can't set attribute")
        if inspect.isclass(obj):
            type_ = obj
            obj = None
        else:
            type_ = type(obj)
        return self.fset.__get__(obj, type_)(value)

    def setter(
        self: Self, func: typing.Callable[[OwningClassType, GetterReturnType], None]
    ) -> Self:
        if isinstance(func, (classmethod, staticmethod)):
            cm = func
        else:
            cm = classmethod(func)
        self.fset = cm
        return self

def class_property(
    func: typing.Callable[[OwningClassType], GetterReturnType]
) -> ClassPropertyDescriptor:
    if isinstance(func, (classmethod, staticmethod)):
        cm = func
    else:
        cm = classmethod(func)

    return ClassPropertyDescriptor(cm)

class ClassPropertyMetaClass(type):
    def __setattr__(self, key: typing.Any, value: typing.Any) -> typing.Any:
        if key in self.__dict__:
            obj = self.__dict__.get(key)
            if obj and type(obj) is ClassPropertyDescriptor:
                return obj.__set__(self, value)

        return super(ClassPropertyMetaClass, self).__setattr__(key, value)


from odoo import api, fields, models, tools, _

import logging
_logger = logging.getLogger(__name__)

class StockMove(models.Model):
    _inherit = "stock.move"

    @api.multi
    def write(self, vals):
        result = super(StockMove, self).write(vals)
        for record in self:
            if record.product_id.name:
                qty = 0
                stocks = self.env['stock.quant'].search([
                    ('product_id.name', '=', record.product_id.name),
                    ('location_id.location_id.name', '=', 'TKTAS')
                ])

                for stock in stocks:
                    qty += stock.qty

                self.send_field_updates(record.product_id.id, qty)

    @api.model
    def send_field_updates(self, product_id, qty, action=''):
        channel_name = "pos_product_available"
        data = {
            'message': "update_qty_product_available",
            'action': action,
            'product_id': product_id,
            'qty': qty
        }
        self.env['pos.config'].send_to_all_poses(channel_name, data)


from datetime import date
from django.contrib.auth.models import AbstractUser
from django.db import models
from slugify import slugify
from django.urls import reverse

# Метод для создания адаптивного пути для сохранения аватарок пользователей
def user_directory_path(instance, filename):
    return 'users/avatar/{0}/{1}'.format(instance.slug,filename)

# Расширение базового класса User путем наследования от AbstractUser
class CustomUser(AbstractUser):
    class Meta:
        verbose_name = 'Профили'
        verbose_name_plural = 'Профили'

    GENDERS = (
        ('', 'Не указано'),
        ('М', 'Мужчина'),
        ('Ж', 'Женщина'),
    )
    slug = models.SlugField(max_length=40, unique=True, db_index=True, verbose_name='URL')
    avatar = models.ImageField(verbose_name='Аватар', default='users/avatar/default/default_avatar.jpeg',
                                upload_to=user_directory_path, blank=True, )
    gender = models.CharField(verbose_name='Пол', max_length=1, choices=GENDERS, default='-', blank=True)
    age = models.PositiveSmallIntegerField(verbose_name='Возраст',null=True,  blank=True)
    birthday = models.DateField(verbose_name='Дата рождения', blank=True, null=True)
    email = models.EmailField(unique=True)

    def __str__(self):
        return self.username

    def get_absolute_url(self):
        return reverse('profile', kwargs={'user_slug': self.slug})

# Метод для отображения возраста пользователей в админке
    def save(self, *args, **kwargs,):
        if not self.slug:
            self.slug = slugify(self.username)
        if not self.age and self.birthday:
            birthday = self.birthday
            today = date.today()
            age = str(today - birthday)
            self.age = int(int(age.split()[0])/360)
        if self.age and self.birthday:
            birthday = self.birthday
            today = date.today()
            age = str(today - birthday)
            self.age = int(int(age.split()[0])/360)

        return super().save(*args, **kwargs)


import sys

class Teams:
    def __init__(self):
        self.name = ""
        self.played = 0
        self.won = 0
        self.lost = 0
        self.draw = 0
        self.score_for = 0
        self.score_against = 0

    def get_difference(self):
        return self.score_for - self.score_against

    def get_points(self):
        return self.won * 3 + self.draw

teams = {}

with open("results.txt", "r", encoding="utf-8") as results:
    for line in results:
        try:
            teams_and_scores = line.split(',')
            first_team = teams_and_scores[0]
            first_team_score = int(teams_and_scores[1])
            second_team = teams_and_scores[2]
            second_team_score = int(teams_and_scores[3])
            draw = False
            first_won = False
            if first_team not in teams:
                teams[first_team] = Teams()
                teams[first_team].name = first_team.ljust(15, " ")
            if second_team not in teams:
                teams[second_team] = Teams()
                teams[second_team].name = second_team.ljust(15, " ")

            teams[first_team].played += 1
            teams[first_team].score_for += int(first_team_score)
            teams[first_team].score_against += int(second_team_score)

            teams[second_team].played += 1
            teams[second_team].score_for += int(second_team_score)
            teams[second_team].score_against += int(first_team_score)
        except:
            print("Error in the data stored format.\nExiting the program")
            sys.exit()

        if first_team_score == second_team_score:
            teams[first_team].draw += 1
            teams[second_team].draw += 1
        elif first_team_score > second_team_score:
            teams[first_team].won += 1
            teams[second_team].lost += 1
        else:
            teams[first_team].lost += 1
            teams[second_team].won += 1

sorted_team = dict(sorted(teams.items(), key=lambda item: (item[1].get_points(), item[1].get_difference()), reverse=True))

adjust = 5

if len(sys.argv) >= 2:
    print(f"\n{sys.argv[1]}\n{'='*len(sys.argv[1])}\n")

print(" ".rjust(15, " "), "P".rjust(adjust, ' '), "W".rjust(adjust, ' '), "D".rjust(adjust, ' '), "L".rjust(adjust, ' '),
      "F".rjust(adjust, ' '), "A".rjust(adjust, ' '), "Diff".rjust(adjust, ' '), "Pts".rjust(adjust, ' '))

for i, j in sorted_team.items():
    print(f"{j.name} {str(j.played).rjust(adjust, ' ')} {str(j.won).rjust(adjust, ' ')} {str(j.draw).rjust(adjust, ' ')} "
          f"{str(j.lost).rjust(adjust, ' ')} {str(j.score_for).rjust(adjust, ' ')} "
          f"{str(j.score_against).rjust(adjust, ' ')} {str(j.get_difference()).rjust(adjust, ' ')} "
          f"{str(j.get_points()).rjust(adjust, ' ')}")


import pandas as pd
import math
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score
from keras.models import Sequential
from keras.layers import Dense, LSTM
import matplotlib.pyplot as plt
import time
import datetime as dt
from numpy import arange
from sklearn import metrics
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import RandomizedSearchCV
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from sklearn.tree import DecisionTreeRegressor

# data engineering
AMZN = pd.read_csv('AAPL.csv')
#AMZN['name'] = 'AMZN'
rename_dict = {
    'High': 'AMZN_high',
    'Low': 'AMZN_low',
    'Close': 'AMZN_close',
    'Open': 'AMZN_open',
    'Adj Close': 'AMZN_adj_close',
    'Volume': 'AMZN_volume'
}
AMZN = AMZN.rename(columns=rename_dict)

AAPL = pd.read_csv('AMZN.csv')
#AAPL['name'] = 'AAPL'
rename_dict = {
    'High': 'AAPL_high',
    'Low': 'AAPL_low',
    'Close': 'AAPL_close',
    'Open': 'AAPL_open',
    'Adj Close': 'AAPL_adj_close',
    'Volume': 'AAPL_volume'
}
AAPL = AAPL.rename(columns=rename_dict)

GOOG = pd.read_csv('GOOG.csv')
#GOOG['name'] = 'GOOG'
rename_dict = {
    'High': 'GOOG_high',
    'Low': 'GOOG_low',
    'Close': 'GOOG_close',
    'Open': 'GOOG_open',
    'Adj Close': 'GOOG_adj_close',
    'Volume': 'GOOG_volume'
}
GOOG = GOOG.rename(columns=rename_dict)

TSLA = pd.read_csv('TSLA(1).csv')
#TSLA['name'] = 'TSLA'
rename_dict = {
    'High': 'TSLA_high',
    'Low': 'TSLA_low',
    'Close': 'TSLA_close',
    'Open': 'TSLA_open',
    'Adj Close': 'TSLA_adj_close',
    'Volume': 'TSLA_volume'
}
TSLA = TSLA.rename(columns=rename_dict)
merged1 = pd.merge(AMZN, AAPL, on=['Date'], how='outer')
merged2 = pd.merge(GOOG, TSLA, on=['Date'], how='outer')

concat1 = pd.concat([AMZN[['AMZN_high', 'AMZN_low', 'AMZN_close', 'AMZN_open', 'AMZN_adj_close', 'AMZN_volume']], AAPL[['AAPL_high', 'AAPL_low', 'AAPL_close', 'AAPL_open', 'AAPL_adj_close', 'AAPL_volume']]], axis=1)
concat2 = pd.concat([GOOG[['GOOG_high', 'GOOG_low', 'GOOG_close', 'GOOG_open', 'GOOG_adj_close', 'GOOG_volume']], TSLA[['TSLA_high', 'TSLA_low', 'TSLA_close', 'TSLA_open', 'TSLA_adj_close', 'TSLA_volume']]], axis=1)

data = pd.merge(merged1, merged2, on=['Date'], how='outer')
data = pd.concat([data, concat1, concat2], axis=1)

data = data.dropna()
data['date'] = pd.to_datetime(data['Date'])
data['date_int'] = (data['date'] - data['date'].min()).dt.days
data['day_of_week'] = data['date'].dt.day_name()
# monday = 0, tuesday = 1
data['day_of_week_int'] = data['date'].dt.dayofweek
data['month_int'] = data['date'].dt.month
data['month_str'] = data['date'].dt.strftime('%B')
seasons = [(1, 'winter'), (4, 'spring'), (7, 'summer'), (10, 'fall')]
season_dict = dict(zip(range(1, 13), [s for m, s in seasons for s in [s]*3] ))
data['season_int'] = data['date'].dt.month.apply(lambda x: (x-1)//3 + 1)
data['season_str'] = data['date'].dt.month.map(season_dict)

#grouped = data.groupby('date')
print(data.head(5))
data.to_csv('complete_data.csv', index=False)


from fxdayu_sinta.IO.environment import get_env
from fxdayu_sinta.IO.master import Master
from fxdayu_sinta.IO.freq import Freq
from fxdayu_sinta.utils.field import START_OPTION_EMPTY, END_OPTION_EMPTY
import click
import os

class Init(object):

    def __init__(self):
        self.env = get_env()

    def create(self, start="", end="", cover=False):
        self.create_root()
        for code in self.env.stocks:
            self.create_stock(code, start, end, cover)

    def check(self):
        if not os.path.exists(self.env.file_root):
            click.echo('File root dir: %s does not exist' % self.env.file_root)
            return
        else:
            for code in self.env.stocks:
                if Master.env(code).exist:
                    click.echo("%s master OK" % code)
                else:
                    click.echo("%s master missing" % code)

                if Freq.env(code).exist:
                    click.echo("%s freq OK" % code)
                else:
                    click.echo("%s freq missing" % code)

    @staticmethod
    def create_stock(code, start, end, cover):
        master = Master.env(code)
        freq = Freq.env(code)
        if not os.path.exists(master.dir):
            os.makedirs(master.dir)

        if (not master.exist) or cover:
            master.create(start, end)
            master.flush()
            click.echo("Create master %s" % code)

        if (not freq.exist) or cover:
            freq.create()
            freq.flush()
            click.echo("Create freq %s" % code)

    def create_root(self):
        root = self.env.file_root
        if not os.path.exists(root):
            os.makedirs(root)

        log_dir = os.path.join(root, "log")
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

def create_config(root_dir):
    from fxdayu_sinta.IO.config import STORAGE, FILES, CODES, path, root
    from fxdayu_sinta.IO.default import storage
    from fxdayu_sinta.IO.codes import codes
    import json

    if not os.path.exists(root):
        os.makedirs(root)

    storage[FILES] = root_dir
    json.dump(storage, open(path(STORAGE), 'w'))

    json.dump(codes, open(path(CODES), 'w'))

    click.echo("Create config files in %s" % root)

def show():
    from fxdayu_sinta.IO.config import root

    click.echo(root)

def generate():

    init = Init()

    init_group = click.Group(
        "init",
        {"check": click.Command("check", callback=init.check, short_help="Find if required index files exist."),
         "create": click.Command("create", callback=init.create, short_help="Create require index files.",
                                 params=[START_OPTION_EMPTY, END_OPTION_EMPTY,
                                         click.Option(['-c', '--cover'], is_flag=True, flag_value=True, default=False,
                                                      help="If enabled, create file whether target file exists.")]),
         "config": click.Command("config", callback=create_config, short_help="Create config files.",
                                 params=[click.Argument(["root_dir"], nargs=1)]),
         "show": click.Command("show", callback=show, short_help="Show default config files dir.")},
        short_help="Init file system and create index files.",
        chain=True
    )
    return {'init': init_group}


"""
SETS are used to store multiple items in a single variable.
    - Set is one of 4 built-in data types in Python used to store collections of data, the other 3 are LIST, TUPLE, and DICTIONARY, all with different qualities and usage.
    - A set is a collection which is unordered, unchangeable*, unindexed and DO NOT allow DUPLICATE values.
    - Sets are written with curly brackets.
    - Set can contain ANY DATA TYPE

* Note: Set items are UNCHANGEABLE: Once a set is created, you cannot change its items but you can REMOVE items and ADD new items.
* Note: Sets are unordered, so you cannot be sure in which order the items will appear, cannot be referred to by index or key.

--> Example: Create a Set

thisset = {"abc", 34, True, 40, "male"}
print(thisset)
"""
#========|| Access Items ||========================
#You cannot access items in a set by referring to an index or a key.
#But you can loop through the set items using a for loop, ORRR ask if a specified value is present in a set, by using the in keyword.

#Example: Loop through the set, and print the values:
thisset = {"apple", "banana", "cherry"}
for x in thisset:
  print(x)

#Example: Check if "banana" is present in the set:
thisset = {"apple", "banana", "cherry"}
print("banana" in thisset) # -> True

#========|| Add Items ||========================
#Once a set is created, you cannot change its items, but you can add new items.
#To add one item to a set use the add() method.

#Example: Add an item to a set, using the add() method:
thisset = {"apple", "banana", "cherry"}
print(thisset)
thisset.add("orange")
print(thisset)

#========|| Add Sets ||========================
# To add items from another set into the current set, use the update() method.

#Example: Add elements from tropical into thisset:
thisset = {"apple", "banana", "cherry"}
tropical = {"pineapple", "mango", "papaya"}
print(thisset)              # -> {'apple', 'banana', 'cherry'}
thisset.update(tropical)    # -> {'mango', 'papaya', 'cherry', 'pineapple', 'apple', 'banana'}
print(thisset)

#========|| Add Any Iterable ||====================
#The object in the update() method does not have to be a set, it can be any iterable object (tuples, lists, dictionaries etc.).

#Example: Add elements of a LIST to at SET:
thisset = {"apple", "banana", "cherry"}
mylist = ["kiwi", "orange"]
thisset.update(mylist)  # -> {'kiwi', 'orange', 'apple', 'cherry', 'banana'}
                        # NOTE: que devuelve un SET y los items de la lista aparecen al principio (¿o en cualquier lugar????)
print(thisset)

#========|| Remove Item: .remove(),  .discard()  and   pop() ||========================
#To remove an item in a set, use the .remove(), or the .discard() method.
#       -NOTE: If the item to remove does not exist, .remove() will raise an ERROR.
#       -NOTE: If the item to remove does not exist, .discard() will NOT raise an ERROR.

#-------|| .remove() ||-------
#Example: Remove "banana" by using the remove() method:
thisset = {"apple", "banana", "cherry"}
thisset.remove("banana")    # -> {'cherry', 'apple'}
                            #NOTE: no queda ordenado!!!!
print(thisset)

#-------|| .discard() ||---------
#Example: Remove "banana" by using the discard() method:
thisset = {"apple", "banana", "cherry"}
thisset.discard("banana")   # -> {'apple', 'cherry'}
                            #NOTE: Parece que queda ordenado!!!!
print(thisset)

#------|| .pop() ||--------------
#NOTE: You can also use the .pop() method to remove an item, but this method will remove the last item. Remember that sets are unordered, so you will NOT KNOW what item that gets removed.

#Example: Remove the last item by using the .pop() method:
thisset = {"apple", "banana", "cherry"}
x = thisset.pop()   # -> cherry
print(x)
print(thisset)      # -> {'banana', 'apple'}

#========|| Empty Set: .clear()  and  del ||========================

#------|| .clear() ||--------------
#Example: The .clear() method empties the set:
thisset = {"apple", "banana", "cherry"}
thisset.clear() # --> set()  vacío
print(thisset)

#------|| del ||--------------
#Example: The del keyword will delete the set COMPLETELY:
thisset = {"apple", "banana", "cherry"}
print(thisset)
del thisset     # -> NameError: name 'thisset' is not defined
                # ¡Ya no existe!
print(thisset)

#========|| SET METHODS ||========================
"""
METHOD	DESCRIPTION
add()	            Adds an element to the set
clear()	            Removes all the elements from the set
copy()	            Returns a copy of the set
difference()        Returns a set containing the difference between two or more sets
difference_update()	Removes the items in this set that are also included in another, specified set
discard()	        Remove the specified item
intersection()	    Returns a set, that is the intersection of two other sets
intersection_update() Removes the items in this set that are not present in other, specified set(s)
isdisjoint()	    Returns whether two sets have a intersection or not
issubset()	        Returns whether another set contains this set or not
issuperset()	    Returns whether this set contains another set or not
pop()	            Removes an element from the set
remove()	        Removes the specified element
symmetric_difference() Returns a set with the symmetric differences of two sets
symmetric_difference_update() Inserts the symmetric differences from this set and another
union()	            Return a set containing the union of sets
update()	        Update the set with the union of this set and others
"""


# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class BttiantangScrapyItem(scrapy.Item):
    '''
    BT天堂电影数据结构
    '''
    # 电影名字
    name = scrapy.Field()
    # 豆瓣评分
    douban_score = scrapy.Field()
    # 更新时间
    update_time = scrapy.Field()
    # 国家
    contry = scrapy.Field()


def func7():
    x = int(input())
    y = int(input())
    num = 0
    while x != y:
        num += 1
        if x > y or 2 * x - y == 2:
            x -= 1
        else:
            x *= 2
    print(num)
func7()


import numpy as np

def sigmoid(x):
    return 1/(1+np.exp(-x))

training_inputs = np.array([[1,0,1],
                            [0,1,0],
                            [1,1,1],
                            [1,0,0]])

training_outputs = np.array([[1,0,1,1]]).T

np.random.seed(1)

synaptic_weights = 2 * np.random.random((3,1)) - 1

#Backpropogation
for i in range (10000):

    inputs = training_inputs
    outputs = sigmoid(np.dot(inputs,synaptic_weights))

    Error = training_outputs - outputs

    adjustement  = np.dot(inputs.T, Error * (outputs * (1 - outputs)) )

    synaptic_weights += adjustement

print(outputs)


import socket

HOST, PORT = '', 8000

# Declearing Socket type
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)  # AF_INET = Address Family ipv4, SOCK_STREAM = socket type TCP
# Setting socket options: # Avoid bind() exception: OSError: [Errno 48] Address already in use
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Binding to socket to HOST and port for identificaiton
server_socket.bind((HOST, PORT))
# Now our server starts listening at port localhot:8000
server_socket.listen(1)
print("Server listening on port {} ...".format(PORT))

# Never Ending Loop to accept incoming Requests
while True:
    client_connection, client_address = server_socket.accept()
    request_data = client_connection.recv(1024)
    print("Client request: \n {}".format(request_data.decode('utf-8')))
    response = b'''\
HTTP/1.1 200 OK

Hello Client
            '''
    client_connection.sendall(response)
    client_connection.close()


from argparse import Namespace
from typing import List, cast, Union, Dict
import base64
from mcstatus import JavaServer

from nonebot.adapters.onebot.v11.message import MessageSegment

from .data import McServerData, Server

class Handle:
    @classmethod
    def list(cls, args: Namespace) -> str:
        msg = ""

        if args.conv["group"]:
            args.conv["user"] = []
        elif args.conv["channel"]:
            args.conv["user"] = []

        if args.user or args.group:
            if args.is_superuser:
                args.conv = {
                    "user": args.user,
                    "group": args.group,
                    "channel": args.channel,
                }
            else:
                return "[ERROR] 获取指定会话的服务器列表需要超级用户权限！"

        for type in args.conv:
            for id in args.conv[type]:
                msg += f"{'用户'if type =='user'else '群' if type == 'group' else '频道'}{id}关注的服务器列表如下：\n"
                mcserver_list = McServerData().get_mcserver_list(
                    id if type == "user" else None,
                    id if type == "group" else None,
                    id if type == "channel" else None,
                )

        if mcserver_list:
            msg += "\n".join(
                f"[{'o'if server.status else 'x'}] {server.name}"
                for server in cast(List[Server], mcserver_list)
            )
        else:
            msg += "关注的服务器列表为空！"

        return msg

    @classmethod
    def ping(cls, args: Namespace) -> Union[str, MessageSegment]:

        if args.conv["group"]:
            args.conv["user"] = []
        elif args.conv["channel"]:
            args.conv["user"] = []

        # 无ip地址则选择列表第一个服务器，列表空则返回错误
        if args.ip == "default":
            for type in args.conv:
                for id in args.conv[type]:
                    mcserver_list = McServerData().get_mcserver_list(
                        id if type == "user" else None,
                        id if type == "group" else None,
                        id if type == "group" else None,
                    )
                    if mcserver_list:
                        args.ip = cast(str, mcserver_list[0].dict()["address"]).split(
                            "|"
                        )[0]
                    else:
                        return "请输入服务器ip地址！"

        try:
            mc_status = JavaServer.lookup(args.ip).status()
            ping = mc_status.latency
            fav = (
                base64.b64decode(mc_status.favicon.split(",")[1])
                if not mc_status.favicon == None
                else None
            )
            status = True
        except:
            fav = None
            ping = None
            status = False

        return MessageSegment.image(fav) + MessageSegment.text(
            f"服务器地址：{args.ip}\n"
            + f"状态：{'On' if status else 'Off'}"
            + (f"\nPing: {int(ping)}ms" if status else "")
        )

    @classmethod
    def online(cls, args: Namespace) -> str:

        if args.conv["group"]:
            args.conv["user"] = []
        elif args.conv["channel"]:
            args.conv["user"] = []

        # 无ip地址则选择列表第一个服务器，列表空则返回错误
        if args.ip == "default":
            for type in args.conv:
                for id in args.conv[type]:
                    mcserver_list = McServerData().get_mcserver_list(
                        id if type == "user" else None,
                        id if type == "group" else None,
                        id if type == "channel" else None,
                    )
                    if mcserver_list:
                        args.ip = cast(str, mcserver_list[0].dict()["address"])
                    else:
                        return "请输入服务器ip地址！"

        playersName = []
        online = False
        num = 0
        for ip in cast(str, args.ip).split("|"):
            try:
                playersInfo = JavaServer.lookup(ip).status().raw["players"]
                num += cast(Dict, playersInfo).get("online", 0)
                if not num == 0:
                    online = True
                playersList = cast(Dict, playersInfo).get("sample", [])
                for p in playersList:
                    playersName.append(p["name"])
            except:
                pass

            """
            try:
                query = server.query()
                players = "The server has the following players online: {0}".format(", ".join(query.players.names))
            except Exception as e:
                print("ERROR: " + str(e))
                players = "The server has the following players online: " + str([ user['name'] for user in status.raw['players']['sample'] ]).replace("'", "").replace("[", "").replace("]", "")
                pass
            """

        return f"服务器当前在线：{'空荡荡~' if not online else f'{num}人在线，暂无法获取玩家名称~' if len(playersName)==0 else '，'.join(playersName)}"

    @classmethod
    def remove(cls, args: Namespace) -> str:

        if args.conv["group"]:
            if not args.is_admin and not args.is_superuser:
                return "管理服务器需要管理员权限！"
            args.conv["user"] = []
        if args.conv["channel"]:
            if not args.is_admin and not args.is_superuser:
                return "管理服务器需要管理员权限！"
            args.conv["user"] = []

        if args.user or args.group:
            if args.is_superuser:
                args.conv = {
                    "user": args.user,
                    "group": args.group,
                    "channel": args.channel,
                }
            else:
                return "[ERROR] 管理指定会话的服务器列表需要超级用户权限！"

        # 移除服务器
        for type in args.conv:
            for id in args.conv[type]:
                McServerData().remove_server(
                    args.name,
                    id if type == "user" else None,
                    id if type == "group" else None,
                    id if type == "channel" else None,
                )

        return "移除服务器成功！"

    @classmethod
    def add(cls, args: Namespace) -> str:

        if args.conv["group"]:
            if not args.is_admin and not args.is_superuser:
                return "管理群插件需要群管理员权限！"
            args.conv["user"] = []
        if args.conv["channel"]:
            if not args.is_admin and not args.is_superuser:
                return "管理服务器需要管理员权限！"
            args.conv["user"] = []

        if args.user or args.group:
            if args.is_superuser:
                args.conv = {
                    "user": args.user,
                    "group": args.group,
                    "channel": args.channel,
                }
            else:
                return "[ERROR] 管理指定会话的服务器列表需要超级用户权限！"

        # 尝试连接mc服务器
        try:
            mc_status = (
                JavaServer.lookup(cast(str, args.ip).split("|")[0]).status().latency
            )
            status = True
        except:
            status = False

        for type in args.conv:
            for id in args.conv[type]:
                McServerData().add_server(
                    Server(name=args.name, address=args.ip, status=status),
                    id if type == "user" else None,
                    id if type == "group" else None,
                    id if type == "channel" else None,
                )

        return "添加服务器成功！"


import http.client, urllib
import json
import os
import collections
import time, datetime

pushover_api_token = os.environ.get('PUSHOVER_API_TOKEN', "nonesuch")
pushover_user_key = os.environ.get('PUSHOVER_USER_KEY', "nonesuch")

def send_notification(payload):
    conn = http.client.HTTPSConnection("api.pushover.net:443")
    conn.request("POST", "/1/messages.json",
    urllib.parse.urlencode({
        "token": pushover_api_token,
        "user": pushover_user_key,
        "message": payload,
    }), { "Content-type": "application/x-www-form-urlencoded" })
    conn.getresponse()

conn = http.client.HTTPSConnection("www.recreation.gov")

old_happy_isles_payload = ""
old_lyell_payload = ""

while True:
    print(f"Trying in 10 seconds (currently {datetime.datetime.now()})")
    time.sleep(10)
    payload = ""
    available = collections.defaultdict(list)

    for date in ["2023-07-01", "2023-08-01"]:
        conn.request("GET", f"/api/permitinyo/445859/availability?start_date={date}&commercial_acct=false", payload)
        res = conn.getresponse()
        data = res.read()
        data_json = json.loads(data.decode("utf-8"))["payload"]

        for date, divisions in data_json.items():
            for division_code, division in divisions.items():
                if division_code in ["44585918", "44585922"] and division["remaining"] > 0 and not division["is_walkup"] and division["remaining"] == division["total"]:
                    available[division_code].append((date, division["remaining"]))

    happy_isles_dates = ", ".join([f"{ent[1]} spots on {ent[0]}" for ent in available["44585918"]])
    happy_isles_payload = f"Happy Isles Permits Available: {happy_isles_dates}"

    lyell_dates = ", ".join([f"{ent[1]} spots on {ent[0]}" for ent in available["44585922"]])
    lyell_payload = f"Lyell Canyon Permits Available: {lyell_dates}"

    if happy_isles_payload==old_happy_isles_payload:
        if lyell_payload==old_lyell_payload:
            continue

    old_lyell_payload = lyell_payload
    old_happy_isles_payload=happy_isles_payload

    for dates, payload in [(available["44585918"], happy_isles_payload), (available["44585922"], lyell_payload)]:
        if dates:
            print(f"Sending notifications... {payload}")
            send_notification(payload=payload)


import sys
import random
import math
import pygame
from pygame.locals import *
from classes import Asteroid

def terminate():
    pygame.quit()
    sys.exit()

def draw_text(text, font, surface, x, y, TEXTCOLOR):
    textobj = font.render(text, 1, TEXTCOLOR)
    textrect = textobj.get_rect(center=(x // 2, y // 2 ))
    surface.blit(textobj, textrect)

def wait():

    waiting = True

    while waiting:

        for event in pygame.event.get():

            if event.type == QUIT:
                terminate()

            if event.type == KEYDOWN:
                waiting = False

def generate_asteroid(window):
    direction = random.uniform(0, 2 * math.pi)
    direction = random.uniform(0, 2 * math.pi)
    start_x = window.width / 2 + math.cos(direction) * window.width
    start_y = window.height / 2 + math.sin(direction) * window.height
    target_x = window.width / 2
    target_y = window.height / 2
    speed = random.randint(3, 5)
    dx = target_x - start_x
    dy = target_y - start_y
    size = random.randint(5, 10)
    angle = math.degrees(math.atan2(dy, dx))
    return Asteroid(start_x, start_y, target_x, target_y, angle, speed, size)


# encoding: utf-8
import numpy as np
import os
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import fitness_funs

class POF:
    """
    绘制pareto曲线的类
    """
    def __init__(self):
        # 绘制测试函数的曲面，（x1，x2）表示两位度的输入，（y1，y2）表示两位的适应值，
        self.x1 = np.linspace(-5, 5, 50)  # 0到10之间100个点
        self.x2 = np.linspace(-5, 5, 50)
        self.x1, self.x2 = np.meshgrid(self.x1, self.x2)
        self.m, self.n = np.shape(self.x1)
        self.y1, self.y2 = np.zeros((self.m, self.n)), np.zeros((self.m, self.n))
        # 将测试函数绘制出来
        for i in range(self.m):
            for j in range(self.n):
                [self.y1[i, j], self.y2[i, j]] = fitness_funs.test_func([self.x1[i, j], self.x2[i, j]])
        if not os.path.exists('./img_txt'):
            os.makedirs('./img_txt')
            print('创建文件夹img_txt:保存粒子群每一次迭代的图片')

    def draw(self, pop, fit, pop_archive, fit_archive, i):
        """
        绘图方法
        共3个子图，第1、2子图绘制输入坐标与适应值关系，第3图展示pareto边界的形成过程
        :param pop:
        :param fit:
        :param pop_archive:
        :param fit_archive:
        :param i: 迭代次数，第几代
        :return:
        """
        fig = plt.figure(13, figsize=(17, 5))  # 图片排列为一行三列

        ax1 = fig.add_subplot(131, projection='3d')
        ax1.set_xlabel('input_x1')
        ax1.set_ylabel('input_x2')
        ax1.set_zlabel('fit_y1')
        ax1.plot_surface(self.x1, self.x2, self.y1, alpha=0.6)  # 测试函数曲面图
        ax1.scatter(pop[:, 0], pop[:, 1], fit[:, 0], s=20, c='blue', marker=".")
        ax1.scatter(pop_archive[:, 0], pop_archive[:, 1], fit_archive[:, 0], s=50, c='red', marker=".")

        ax2 = fig.add_subplot(132, projection='3d')
        ax2.set_xlabel('input_x1')
        ax2.set_ylabel('input_x2')
        ax2.set_zlabel('fit_y2')
        ax2.plot_surface(self.x1, self.x2, self.y2, alpha=0.6)  # 测试函数曲面图
        ax2.scatter(pop[:, 0], pop[:, 1], fit[:, 1], s=20, c='blue', marker=".")
        ax2.scatter(pop_archive[:, 0], pop_archive[:, 1], fit_archive[:, 1], s=50, c='red', marker=".")

        ax3 = fig.add_subplot(133)
        ax3.set_xlim((0, 25))
        ax3.set_ylim((0, 25))
        ax3.set_xlabel('fitness_y1')
        ax3.set_ylabel('fitness_y2')
        ax3.scatter(fit[:, 0], fit[:, 1], s=10, c='blue', marker=".")
        ax3.scatter(fit_archive[:, 0], fit_archive[:, 1], s=30, c='red', marker=".", alpha=1.0)
        # plt.show()
        plt.savefig('./img_txt/第' + str(i + 1) + '次迭代.png')
        print('第' + str(i + 1) + '次迭代的图片保存于 img_txt 文件夹')
        plt.close()


from enum import Enum

class PlayType(Enum):
    ROCK = 1
    PAPER = 2
    SCISSORS = 3

class Game:
    def __init__(self, player1: PlayType, player2: PlayType):
        self.player1 = player1
        self.player2 = player2

class Result:
    def __init__(self, player1: int, player2: int):
        self.player1Score = player1
        self.player2Score = player2

def parsePlayType(encodedPlayType: str) -> PlayType:
    if encodedPlayType == 'A' or encodedPlayType == 'X':
        return PlayType.ROCK
    if encodedPlayType == 'B' or encodedPlayType == 'Y':
        return PlayType.PAPER
    if encodedPlayType == 'C' or encodedPlayType == 'Z':
        return PlayType.SCISSORS
    raise NameError('Unknown value')

def parseGameMove(gameLine: str) -> Game:
    return Game(parsePlayType(gameLine[0]), parsePlayType(gameLine[2]))

def getScore(player: int, winner: int, played: PlayType) -> int:
    if player == winner:
        winScore = 6
    elif winner == 0:
        winScore = 3
    else:
        winScore = 0

    return winScore + played.value

def playGame(game:Game) -> Result:
    if game.player1 == game.player2:
        winner = 0

    # Rock defeats Scissors, Scissors defeats Paper, and Paper defeats Rock
    elif game.player1 == PlayType.ROCK and game.player2 == PlayType.SCISSORS:
         winner = 1
    elif game.player1 == PlayType.SCISSORS and game.player2 == PlayType.PAPER:
         winner = 1
    elif game.player1 == PlayType.PAPER and game.player2 == PlayType.ROCK:
         winner = 1
    else:
        winner = 2

    return Result(
        getScore(1, winner, game.player1),
        getScore(2, winner, game.player2)
    )

def getPlayer2Scores(result: Result) -> int:
    return result.player2Score

with open('data.txt') as f:
    games = list(map(parseGameMove, f.read().splitlines()))
    results =  list(map(playGame, games))
    player2Score = list(map(getPlayer2Scores, results))

print(sum(player2Score))


from requests import get
from bs4 import BeautifulSoup

def extract_reok_jobs(keyword):
    headers = {
        "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
    }
    response = get(f"https://remoteok.com/remote-{keyword}-jobs",
                   headers=headers)

    if response.status_code != 200:
        print("Can't request website")

    else:
        results = []
        soup = BeautifulSoup(response.text, "html.parser")
        jobs = soup.find_all("tr", class_="job")
        for job_section in jobs:
            anchor = job_section.select_one("td a")
            position = job_section.find("h2", itemprop="title")
            company = job_section.find("h3", itemprop="name")
            location = job_section.find("div", class_="location")
            link = anchor['href']
            job_data = {
                "position": position.string.strip().replace(",", " "),
                "company": company.string.strip().replace(",", " "),
                "location": location.string.replace(",", " "),
                'link': f"https://remoteok.com/{link}"
            }
            results.append(job_data)
        return results