'''
Created on 04-Feb-2017

@author: vijay
'''

import wx.adv
from wx.adv import Wizard
from wx.adv import WizardPage, WizardPageSimple
from src.view.connection.DatabaseNavigation import DatabaseNavigationTree
from src.sqlite_executer.ConnectExecuteSqlite import ManageSqliteDatabase, \
    SQLExecuter
from sqlite3 import OperationalError
from src.view.constants import LOG_SETTINGS
import logging.config
import os

logger = logging.getLogger('extensive')

logging.config.dictConfig(LOG_SETTINGS)

class TitledPage(WizardPageSimple):

    def __init__(self, parent, title):
        WizardPageSimple.__init__(self, parent)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        titleText = wx.StaticText(self, -1, title)
        titleText.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(titleText, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0,
                wx.EXPAND | wx.ALL, 5)

class SelectDatabaseNamePage(WizardPageSimple):

    def __init__(self, parent, title='Select new connection type'):
        WizardPageSimple.__init__(self, parent)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        titleText = wx.StaticText(self, -1, title)

        fs = self.GetFont().GetPointSize()
        bf = wx.Font(fs + 4, wx.SWISS, wx.NORMAL, wx.BOLD)
        nf = wx.Font(fs + 2, wx.SWISS, wx.NORMAL, wx.NORMAL)
        titleText.SetFont(bf)
        ####################################################################
        '''
        Header section
        '''
        self.tree = DatabaseNavigationTree(self)
        self.filter = wx.SearchCtrl(self, style=wx.TE_PROCESS_ENTER)
        self.filter.SetDescriptiveText("Type filter database name")
        self.filter.ShowCancelButton(True)
        self.filter.Bind(wx.EVT_TEXT, self.RecreateTree)
        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda e: self.filter.SetValue(''))
        self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
        self.RecreateTree()

        ####################################################################

        self.sizer.Add(titleText, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, 5)
        self.sizer.Add(self.filter , 0, wx.EXPAND | wx.ALL)
        self.sizer.Add(self.tree , 1, wx.EXPAND | wx.ALL)

    def OnSearch(self, event=None):

        value = self.filter.GetValue()
        if not value:
            self.RecreateTree()
            return

        wx.BeginBusyCursor()
        try:
            for category, items in self._treeList[1]:
                self.searchItems[category] = []
                for childItem in items:
    #                 if SearchDemo(childItem, value):
                    self.searchItems[category].append(childItem)
        except Exception as e:
            logger.error(e, exc_info=True)
        wx.EndBusyCursor()
        self.RecreateTree()

    #---------------------------------------------
    def RecreateTree(self, evt=None):
        # Catch the search type (name or content)
#         searchMenu = self.filter.GetMenu().GetMenuItems()
#         fullSearch = searchMenu[1].IsChecked()
        fullSearch = False

        if evt:
            if fullSearch:
                # Do not`scan all the demo files for every char
                # the user input, use wx.EVT_TEXT_ENTER instead
                return

        expansionState = self.tree.GetExpansionState()

        current = None
        item = self.tree.GetSelection()
        if item:
            prnt = self.tree.GetItemParent(item)
            if prnt:
                current = (self.tree.GetItemText(item),
                           self.tree.GetItemText(prnt))

        self.tree.Freeze()
        self.tree.DeleteAllItems()
        self.root = self.tree.AddRoot("Connections")
        self.tree.SetItemImage(self.root, 0)
        self.tree.SetItemData(self.root, 0)

        treeFont = self.tree.GetFont()
        catFont = self.tree.GetFont()

        # The native treectrl on MSW has a bug where it doesn't draw
        # all of the text for an item if the font is larger than the
        # default.  It seems to be clipping the item's label as if it
        # was the size of the same label in the default font.
        if 'wxMSW' not in wx.PlatformInfo:
            treeFont.SetPointSize(treeFont.GetPointSize() + 2)

        treeFont.SetWeight(wx.BOLD)
        catFont.SetWeight(wx.BOLD)
#         self.tree.SetItemFont(self.root, treeFont)

        firstChild = None
        selectItem = None
        filter = self.filter.GetValue()
        count = 0

        databaseLeaf = self.tree.AppendItem(self.root, 'SQLite', image=16)

class ConncectionSettings(WizardPageSimple):

    def __init__(self, parent, title='define title'):
        WizardPageSimple.__init__(self, parent)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        titleText = wx.StaticText(self, -1, title)

        fs = self.GetFont().GetPointSize()
        bf = wx.Font(fs + 4, wx.SWISS, wx.NORMAL, wx.BOLD)
        nf = wx.Font(fs + 2, wx.SWISS, wx.NORMAL, wx.NORMAL)
        titleText.SetFont(bf)

        self.sizer.Add(titleText, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, 5)
        ####################################################################
        self.panel = wx.Panel(self, -1)

        vbox1 = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        connectionNameLabel = wx.StaticText(self.panel, -1, "Connection name : ")
        self.connectionNameTextCtrl = wx.TextCtrl(self.panel, size=(300, -1))
        dbFileNameLabel = wx.StaticText(self.panel, -1, "Database File name : ")
        self.dbFileNameTextCtrl = wx.TextCtrl(self.panel, size=(300, -1))
        self.connectionNameTextCtrl.Bind(wx.EVT_TEXT, self.onConnectionName)
        hbox1.Add(connectionNameLabel)
        hbox1.Add(self.connectionNameTextCtrl, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.ALL, 1)
        hbox3.Add(dbFileNameLabel)
        hbox3.Add(self.dbFileNameTextCtrl, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.ALL, 1)

        import wx.lib.filebrowsebutton as filebrowse
        self.dbb = filebrowse.DirBrowseButton(self.panel, -1, size=(450, -1), changeCallback=self.dbbCallback, startDirectory = wx.GetHomeDir())
        self.dbb.SetValue(wx.GetHomeDir(), self.dbbCallback)
#         self.markFile = brows.FileBrowseButton(self.panel, labelText="File path                  :", fileMode=wx.FD_OPEN, size=(400, 30), toolTip='Type database filename or click browse to choose file')
#         self.markFile.Bind(wx.EVT_TEXT, self.onMarkFile)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2.Add(self.dbb)

        vbox1.Add(hbox1)
        vbox1.Add(hbox2)
        vbox1.Add(hbox3)
        self.panel.SetSizer(vbox1)
        self.sizer.Add(self.panel, 0, wx.ALL , 5)

        ####################################################################
    def onConnectionName(self, event):
        logger.debug('onConnectionName')
        if self.connectionNameTextCtrl.GetValue():
            self.GetParent().Children[1].Enable()
            dbFileName=self.connectionNameTextCtrl.GetValue().replace(" ","_")+".sqlite"
            self.dbFileNameTextCtrl.SetValue(dbFileName)
    def dbbCallback(self, evt):
        logger.debug('DirBrowseButton: {}\n'.format( evt.GetString()))
    def onMarkFile(self, event):
        logger.debug('onMarkFile')

class CreateNewConncetionWixard(wx.Panel):

    def __init__(self, parent=None, *args, **kw):
        wx.Panel.__init__(self, parent, id=-1)
        self.wizard = None
        self.pages = []

    def createWizard(self):
        self.wizard = Wizard(None, -1, "Create new connection")

        self.wizard.Bind(wx.adv.EVT_WIZARD_PAGE_CHANGED, self.onPageChange)
        self.wizard.Bind(wx.adv.EVT_WIZARD_PAGE_CHANGING, self.onPageChanging)
        self.wizard.Bind(wx.adv.EVT_WIZARD_CANCEL, self.onCancel)
        self.wizard.Bind(wx.adv.EVT_WIZARD_FINISHED, self.onFinished)

        page1 = SelectDatabaseNamePage(self.wizard, "Select new connection type")
        page2 = ConncectionSettings(self.wizard, "Connection settings")
        self.page1=page1

#         self.pages.append(page1)
#         self.pages.append(page2)
#         page3 = TitledPage(wizard, "Page 3")
#         page4 = TitledPage(wizard, "Page 4")
#         page1.sizer.Add(wx.StaticText(page1, -1, "Testing the wizard"))
#         page4.sizer.Add(wx.StaticText(page4, -1, "This is the last page."))
#         WizardPageSimple.Chain(page1, page2)
#         WizardPageSimple_Chain(page2, page3)
#         WizardPageSimple_Chain(page3, page4)
        self.wizard.FitToPage(page1)
        # Set the initial order of the pages
        page1.SetNext(page2)
        page2.SetPrev(page1)
        self.wizard.GetPageAreaSizer().Add(page1)
        if self.wizard.RunWizard(page1):
            logger.debug("Success")
            selectedItem = page1.tree.GetSelection()
            logger.debug(page1.tree.GetItemText(selectedItem))
            logger.debug("%s, %s", page2.connectionNameTextCtrl.GetValue(), page2.dbb.GetValue())
#             databasefile = page2.markFile.GetValue()
            connectionName = page2.connectionNameTextCtrl.GetValue()
            databaseFileName=connectionName.replace(" ","_")+".sqlite"
            databasefile=os.path.join(page2.dbb.GetValue(), databaseFileName)
            self.createNewDatabase(connectionName=connectionName, databaseAbsolutePath=databasefile)
            self.GetTopLevelParent()._mgr.GetPane("databaseNaviagor").window.tree.initialize()
        else:
            wx.MessageBox("Create new connection was cancelled", "Create new connection")

    def createNewDatabase(self, databaseAbsolutePath=None, connectionName=None):
        try:
            manageSqliteDatabase = ManageSqliteDatabase(databaseAbsolutePath=databaseAbsolutePath, connectionName=connectionName)
            manageSqliteDatabase.createTable()
            sqlExecuter = SQLExecuter()
            sqlTypeObjectList = sqlExecuter.getSqlObjects()
            if len(sqlTypeObjectList) == 0:
                sqlExecuter.createOpalTables()
            sqlExecuter.addNewConnectionRow(databaseAbsolutePath, connectionName)
        except OperationalError as err:
            logger.error(err, exc_info=True)

    def onPageChange(self, event):
        '''Executed after the page has changed.'''
        logger.debug('onPageChange')
        if event.GetDirection():
            dir = "forward"
        else:
            dir = "backward"

        page = event.GetPage()
        logger.debug("OnWizPageChanged: %s, %s\n" % (dir, page.__class__))

    def onPageChanging(self, event):
        '''Executed before the page changes, so we might veto it.'''
        logger.debug('onPageChanging')
        if event.GetDirection():
            dir = "forward"
        else:
            dir = "backward"

        page = event.GetPage()
        logger.debug("OnWizPageChanging: %s, %s\n" % (dir, page.__class__))

    def onCancel(self, event):
        '''Cancel button has been pressed.  Clean up and exit without continuing.'''
        logger.debug('onCancel')
        page = event.GetPage()
        logger.debug("on_cancel: %s\n", page.__class__)
        self.wizard.Destroy()

#         # Prevent cancelling of the wizard.
#         if page in self.pages:
# #             wx.MessageDialog("Cancelling on the first page has been prevented.", "Sorry")
# #             event.Veto()
#             dlg = wx.MessageDialog(page,
#                 "Do you really want to close ?",
#                 "Confirm Exit", wx.YES_NO |wx.ICON_QUESTION)
#             result = dlg.ShowModal()
#             if result == wx.ID_YES:
#                 logger.debug( "Yes pressed")
#                 self.wizard.Destroy()
#             else:
#                 logger.debug( "No pressed")
#                 dlg.Destroy()
    def onFinished(self, event):
        logger.debug('onFinished')

        wx.GetApp().ExitMainLoop()

if __name__ == "__main__":

    app = wx.App()
    CreateNewConncetionWixard().createWizard()


# CAZy home page
CAZY_HOME = "http://www.cazy.org"

# URL page names for CAZy enzyme classes and other modules
ENZYME_CLASSES = {'Glycoside Hydrolases': 'Glycoside-Hydrolases.html',
	          'GlycosylTransferases': 'GlycosylTransferases.html',
		  'Polysaccharide Lyases': 'Polysaccharide-Lyases.html',
		  'Carbohydrate Esterases': 'Carbohydrate-Esterases.html',
                  'Auxiliary Activities': 'Auxiliary-Activities.html',
                  'Carbohydrate-Binding Modules':
                  'Carbohydrate-Binding-Modules.html'}

# Abbreviations for CAZy enzyme classes/modules
ENZYME_CLASS_ABBR = {'GH': 'Glycoside Hydrolases',
                     'GT': 'Glycosyl Transferases',
                     'PL': 'Polysaccharide Lyases',
                     'CE': 'Carbohydrate Esterases',
                     'AA': 'Auxiliary Activities',
                     'CBM': 'Carbohydrate-Binding Modules'}

# Subscripts for enzyme family links
FAMILY_SUBSCRIPTS = {'all': '_all.html',
                     'archaea': '_archaea.html',
                     'bacteria': '_bacteria.html',
                     'eukaryota': '_eukaryota.html',
                     'unclassified': '_unclassified.html',
                     'structure': '_structure.html',
                     'characterized': '_characterized.html'}


# coding:utf-8
from pymongo import MongoClient
import pymongo
import random
from setting import MONGO_URL
from utlis.log import logger
from ipmd import Proxy

class MongoPool(object):

    def __init__(self):
        '''mongodb'''
        # 建立链接
        self.cloent = MongoClient(MONGO_URL)
        # 获取操作集合
        self.proxies = self.cloent['proxies_pool']['proxies']

    def __del__(self):
        '''关闭数据库链接'''
        self.cloent.close()

    # 增删改查
    def insert_one(self,proxy):
        '''插入/去重'''
        count = self.proxies.count({'_id':proxy.ip})
        if count == 0:
            dic = proxy.__dict__
            dic['_id'] = proxy.ip
            self.proxies.insert_one(dic)
            logger.info('代理新插入:{}'.format(proxy))
        else:
            logger.info('代理已存在:{}'.format(proxy))

    def update_one(self, proxy):
        '''更新功能'''
        self.proxies.update_one({'_id':proxy.ip},{'$set':proxy.__dict__})
        logger.info('代理已更新:{}'.format(proxy))

    def delete_one(self,proxy):
        '''删除功能'''
        self.proxies.delete_one({'_id': proxy.ip})
        logger.info('代理已删除:{}'.format(proxy))

    def find_all(self):
        '''查询功能'''
        cursor = self.proxies.find()
        for item in cursor:
            item.pop('_id')
            proxy = Proxy(**item)
            yield proxy

    def find(self, conditions={}, count=0):
        # print(conditions)
        '''API实现'''
        cursor = self.proxies.find(conditions, limit=count).sort([('score',pymongo.DESCENDING),('speed', pymongo.ASCENDING)]) # 实现顺序排列
        proxy_list = []
        for item in cursor:
            item.pop('_id')
            proxy = Proxy(**item)
            proxy_list.append(proxy)
        return proxy_list

    def get_proxies(self, protocol=None, domain=None, count=0, nick_type=0):
        '''根据协议类型 和 要访问的网站域名,获取对应的ip代理'''
        #定义查询条件
        conditions = {'nick_type':nick_type}
        # 根据协议,指定查询条件

            # 没有传入协议类型,返回支持http/https协议
        if protocol is None:
            conditions['protocol'] = {'$in':[0, 1, 2]}
        elif protocol.lower() == 'http':
            conditions['protocol'] = {'$in':[0, 2]}
        else:
            conditions['protocol'] = {'$in':[1, 2]}

        if domain:
            conditions['disable_domains'] = {'$nin':[domain]}

        return self.find(conditions, count=count)

    def random_proxy(self, protocol=None, domain=None, count=0, nick_type=0):
        '''随机返回满足要求的一个ip代理'''
        proxy_list = self.get_proxies(protocol=protocol, domain=domain, count=count, nick_type=nick_type)
        # print(proxy_list)
        return random.choice(proxy_list)

    def disable_domains(self, ip, domain):
        '''添加指定域名信息到disable_domains列表中'''

        if self.proxies.count({'_id':ip,'disable_domains':domain}) == 0:
            self.proxies.update_one({'_id':ip},{'$push':{'disable_domains':domain}})

            return True
        return False

if __name__ == '__main__':

    mongo = MongoPool()
    # proxy = Proxy('39.98.189.211', prot='1111')
    # mongo.insert_one(proxy)
    # proxy = Proxy('39.98.189.212', prot='2222')
    # mongo.insert_one(proxy)
    # proxy = Proxy('39.98.189.213', prot='3333')
    # mongo.insert_one(proxy)
    # proxy = Proxy('39.98.189.214', prot='4444')
    # mongo.insert_one(proxy)
    # for porxy in mongo.find_all():
    #     print(porxy)
    # proxy = Proxy('39.98.189.213', prot='5555')
    # mongo.update_one(proxy)
    # proxy = Proxy('39.98.189.214', prot='4444')
    # mongo.delete_one(proxy)
    # proxy = Proxy('39.98.189.212', prot='2222')
    # mongo.delete_one(proxy)
    # proxy = Proxy('39.98.189.213', prot='5555')
    # mongo.delete_one(proxy)
    # proxy = Proxy('39.98.189.214', prot='4444')
    # mongo.delete_one(proxy)

    # for proxy in mongo.find({'nick_type': 0, 'protocol': {'$in': [0, 2]}}):
    #     print(proxy)

    # proxy = Proxy(**dic)
    # mongo.insert_one(proxy)
    #
    # for proxy in mongo.get_proxies(protocol='http'):
    #     print(proxy)
    # print(mongo.disable_domains('39.98.189.215', 'taobao.com'))


import os
import torch
import numpy as np
import pickle
import config
from config import args
from torch import nn
from torch.nn import functional as F
from copy import deepcopy
from collections import OrderedDict

from util import align_by_pelvis, batch_rodrigues, copy_state_dict
from model_meta import HMRNetBase
from Discriminator import Discriminator
from meta_weight_update import gradient_update_parameters
from dataloader.human36m_Taskloader import load_tasks

device = torch.device('cuda', 1)

def _fetch_data(data, batch_idx):
    poses, shapes = torch.from_numpy(data[0]).to(device, dtype=torch.float32), torch.from_numpy(data[1]).to(device, dtype=torch.float32)
    data_3d_j3ds, has_3d_joints = torch.from_numpy(data[2]).to(device, dtype=torch.float32), torch.from_numpy(data[3]).to(device)
    data_3d_j2ds, has_2d_joints = torch.from_numpy(data[4]).to(device, dtype=torch.float32), torch.from_numpy(data[5]).to(device)
    has_smpls, imgs = torch.from_numpy(data[6]).to(device), torch.from_numpy(data[7]).to(device)
    thetas = torch.from_numpy(data[8]).to(device, dtype=torch.float32)

    return poses[batch_idx], shapes[batch_idx], data_3d_j3ds[batch_idx], has_3d_joints[batch_idx], data_3d_j2ds[batch_idx], has_2d_joints[batch_idx], has_smpls[batch_idx], imgs[batch_idx], thetas[batch_idx]

def _accumulate_thetas(generator_outputs):
    thetas = []
    for (theta, verts, j2d, j3d, Rs) in generator_outputs:
        thetas.append(theta)
    return torch.cat(thetas, 0)

class MetaLearner(nn.Module):
    def __init__(self):
        super(MetaLearner, self).__init__()
        self.update_step = 4
        self.update_step_test = 4
        self._build_model()

    def _build_model(self):
        print('start building modle.')

        '''
            load pretrain model
        '''
        generator = HMRNetBase()
        # model_path = config.pre_trained_model['generator']
        # if os.path.exists(model_path):
        #     copy_state_dict(generator.state_dict(), torch.load(model_path), prefix = 'module.')
        # else:
        #     print('model {} not exist!'.format(model_path))

        discriminator = Discriminator()
        # model_path = config.pre_trained_model['discriminator']
        # if os.path.exists(model_path):
        #     copy_state_dict(discriminator.state_dict(), torch.load(model_path), prefix = 'module.')
        # else:
        #     print('model {} not exist!'.format(model_path))

        self.generator = generator.to(device)
        self.discriminator = discriminator.to(device)

        self.generator.train()
        self.discriminator.train()
        model_path = config.pre_trained_model['generator']
        if os.path.exists(model_path):
            copy_state_dict(generator.state_dict(), torch.load(model_path))
        else:
            print('model {} not exist!'.format(model_path))

        model_path = config.pre_trained_model['discriminator']
        if os.path.exists(model_path):
            copy_state_dict(discriminator.state_dict(), torch.load(model_path))
        else:
            print('model {} not exist!'.format(model_path))

        self.e_base_lr, self.d_base_lr = args.e_lr*50, args.d_lr*50
        # optimizer for the generater
        self.e_opt = torch.optim.Adam(self.generator.parameters(), lr = args.e_lr, weight_decay = args.e_wd)
        self.e_sche = torch.optim.lr_scheduler.StepLR(self.e_opt, step_size = 500, gamma = 0.9)
        # optimizer for the discriminator
        self.d_opt = torch.optim.Adam(self.discriminator.parameters(), lr = args.d_lr, weight_decay = args.d_wd)
        self.d_sche = torch.optim.lr_scheduler.StepLR(self.d_opt, step_size = 500, gamma = 0.9)

        print('finished build model.')

    def forward(self, spt_data, qry_data):

        # spt data shape: [batch size, n_way*k_spt, ...]
        # qry data shape: [batch size, n_way*k_qry, ...]

        batch_size = spt_data[0].shape[0]
        e_loss_list_qry = [0 for _ in range(self.update_step + 1)]
        d_loss_list_qry = [0 for _ in range(self.update_step + 1)]

        for i in range(batch_size):

            # gen_clone = HMRNetBase().to(device)
            # disc_clone = Discriminator().to(device)
            # gen_clone.train()
            # disc_clone.train()

            # gen_clone.load_state_dict(deepcopy(self.generator.state_dict()))
            # disc_clone.load_state_dict(deepcopy(self.discriminator.state_dict()))
            # e_opt_clone = torch.optim.Adam(gen_clone.parameters(), lr = self.e_base_lr, weight_decay = args.e_wd)
            # d_opt_clone = torch.optim.Adam(disc_clone.parameters(), lr = self.d_base_lr, weight_decay = args.d_wd)

            # Update step 0
            # calculate the updated and making a deep copy of it
            spt_imgs = torch.from_numpy(spt_data[7][i]).to(device)
            generator_outputs = self.generator(spt_imgs, params = None)
            loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, spt_data, i, params = None)

            e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
            d_loss = d_disc_loss

            e_fast_weights_net,  e_fast_weights_grad = gradient_update_parameters(self.generator, e_loss, step_size=self.e_base_lr)
            d_fast_weights_net,  d_fast_weights_grad = gradient_update_parameters(self.discriminator, d_loss, step_size=self.d_base_lr)
            # e_opt_clone.zero_grad()
            # e_loss.backward()
            # e_opt_clone.step()

            # d_opt_clone.zero_grad()
            # d_loss.backward()
            # d_opt_clone.step()

            # Test on the query set: using the weights before upadte
            with torch.no_grad():
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = self.generator(qry_imgs, params = OrderedDict(self.generator.meta_named_parameters()))
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                   e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = OrderedDict(self.discriminator.meta_named_parameters()))

                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[0] += e_loss
                d_loss_list_qry[0] += d_loss

            # Test on the query set: using the upadte weighted
            with torch.no_grad():
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = self.generator(qry_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = d_fast_weights_net)
                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[1] += e_loss
                d_loss_list_qry[1] += d_loss

            for k in range(1, self.update_step):
                # Uptate step k: using updaated weights from step 0
                spt_imgs = torch.from_numpy(spt_data[7][i]).to(device)
                generator_outputs = self.generator(spt_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, spt_data, i, params = d_fast_weights_net)

                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_fast_weights_net,  e_fast_weights_grad = gradient_update_parameters(self.generator, e_loss, updated_params = e_fast_weights_net, params = e_fast_weights_grad, step_size=self.e_base_lr)
                d_fast_weights_net,  d_fast_weights_grad = gradient_update_parameters(self.discriminator, d_loss, updated_params = d_fast_weights_net, params = d_fast_weights_grad, step_size=self.d_base_lr)
                # e_opt_clone.zero_grad()
                # e_loss.backward()
                # e_opt_clone.step()

                # d_opt_clone.zero_grad()
                # d_loss.backward()
                # d_opt_clone.step()

                # Test on the query set: using updated weights from step k
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = self.generator(qry_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = d_fast_weights_net)
                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[k+1] += e_loss
                d_loss_list_qry[k+1] += d_loss

                # del gen_clone
                # del disc_clone

                # del e_opt_clone
                # del d_opt_clone

        e_loss_qry = e_loss_list_qry[-1] / batch_size
        d_loss_qry = d_loss_list_qry[-1] / batch_size

        self.e_opt.zero_grad()
        e_loss_qry.backward()
        self.e_opt.step()

        self.d_opt.zero_grad()
        d_loss_qry.backward()
        self.d_opt.step()

        e_loss = np.array([loss.item() for loss in e_loss_list_qry]) / batch_size
        d_loss = np.array([loss.item() for loss in d_loss_list_qry]) / batch_size

        return e_loss, d_loss

    def _calc_loss(self, generator_outputs, data_3d, batch_idx, params, finetune = False, new_dis = None):
        poses, shapes, data_3d_j3ds, has_3d_joints, data_3d_j2ds, has_2d_joints, has_smpls, imgs, thetas = _fetch_data(data_3d, batch_idx)

        theta = torch.cat((torch.zeros((poses.shape[0], 3)).to(device), poses, shapes), axis = 1).float().to(device)
        data_3d_theta, w_3d, w_smpl = theta, has_3d_joints.float().to(device), has_smpls.float().to(device)

        total_predict_thetas = _accumulate_thetas(generator_outputs)
        (predict_theta, predict_verts, predict_j2d, predict_j3d, predict_Rs) = generator_outputs[-1]

        data_3d_j2d = data_3d_j2ds
        data_3d_j3d = data_3d_j3ds[:, :, :-1].clone()

        real_2d, real_3d = data_3d_j2d.to(device), data_3d_j3d.to(device)

        loss_kp_2d = self.batch_kp_2d_l1_loss(real_2d, predict_j2d[:,:14,:]) *  args.e_loss_weight
        loss_kp_3d = self.batch_kp_3d_l2_loss(real_3d, predict_j3d[:,:14,:], w_3d) * args.e_3d_loss_weight * args.e_3d_kp_ratio

        real_shape, predict_shape = data_3d_theta[:, 75:], predict_theta[:, 75:]
        loss_shape = self.batch_shape_l2_loss(real_shape, predict_shape, w_smpl) * args.e_3d_loss_weight * args.e_shape_ratio

        real_pose, predict_pose = data_3d_theta[:, 3:75], predict_theta[:, 3:75]
        loss_pose = self.batch_pose_l2_loss(real_pose.contiguous(), predict_pose.contiguous(), w_smpl) * args.e_3d_loss_weight * args.e_pose_ratio

        if finetune:
            encoder_disc_value = new_dis(total_predict_thetas, params = params)
            e_disc_loss = self.batch_encoder_disc_l2_loss(encoder_disc_value) * args.d_loss_weight * args.d_disc_ratio

            real_thetas = thetas.to(device)
            thetas = []
            for theta in real_thetas:
                thetas.append(theta)
            real_thetas = torch.cat(thetas, 0)
            fake_thetas = total_predict_thetas.detach()
            fake_disc_value, real_disc_value = new_dis(fake_thetas, params = params), new_dis(real_thetas, params = params)
            d_disc_real, d_disc_fake, d_disc_loss = self.batch_adv_disc_l2_loss(real_disc_value, fake_disc_value)
            d_disc_real, d_disc_fake, d_disc_loss = d_disc_real  * args.d_loss_weight * args.d_disc_ratio, d_disc_fake  * args.d_loss_weight * args.d_disc_ratio, d_disc_loss * args.d_loss_weight * args.d_disc_ratio
        else:
            encoder_disc_value = self.discriminator(total_predict_thetas, params = params)
            e_disc_loss = self.batch_encoder_disc_l2_loss(encoder_disc_value) * args.d_loss_weight * args.d_disc_ratio

            real_thetas = thetas.to(device)
            thetas = []
            for theta in real_thetas:
                thetas.append(theta)
            real_thetas = torch.cat(thetas, 0)
            fake_thetas = total_predict_thetas.detach()
            fake_disc_value, real_disc_value = self.discriminator(fake_thetas, params = params), self.discriminator(real_thetas, params = params)
            d_disc_real, d_disc_fake, d_disc_loss = self.batch_adv_disc_l2_loss(real_disc_value, fake_disc_value)
            d_disc_real, d_disc_fake, d_disc_loss = d_disc_real  * args.d_loss_weight * args.d_disc_ratio, d_disc_fake  * args.d_loss_weight * args.d_disc_ratio, d_disc_loss * args.d_loss_weight * args.d_disc_ratio

        return loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, e_disc_loss, d_disc_loss, d_disc_real, d_disc_fake
    # Calc L1 error
    def batch_kp_2d_l1_loss(self, real_2d_kp, predict_2d_kp):
        kp_gt = real_2d_kp.view(-1, 3) # (224, 3)
        kp_pred = predict_2d_kp.contiguous().view(-1, 2) # (224, 2)
        vis = kp_gt[:, 2]
        k = torch.sum(vis) * 2.0 + 1e-8
        dif_abs = torch.abs(kp_gt[:, :2] - kp_pred).sum(1)
        return torch.matmul(dif_abs, vis) * 1.0 / k

    # calc mse * 0.5
    def batch_kp_3d_l2_loss(self, real_3d_kp, fake_3d_kp, w_3d):
        shape = real_3d_kp.shape
        k = torch.sum(w_3d) * shape[1] * 3.0 * 2.0 + 1e-8

        #first align it
        # real_3d_kp, fake_3d_kp = align_by_pelvis(real_3d_kp), align_by_pelvis(fake_3d_kp)
        kp_gt = real_3d_kp
        kp_pred = fake_3d_kp
        kp_dif = (kp_gt - kp_pred) ** 2
        return torch.matmul(kp_dif.sum(1).sum(1), w_3d) * 1.0 / k

    # calc mse * 0.5
    def batch_shape_l2_loss(self, real_shape, fake_shape, w_shape):
        k = torch.sum(w_shape) * 10.0 * 2.0 + 1e-8
        shape_dif = (real_shape - fake_shape) ** 2
        return  torch.matmul(shape_dif.sum(1), w_shape) * 1.0 / k

    # calc mse * 0.5
    def batch_pose_l2_loss(self, real_pose, fake_pose, w_pose):
        k = torch.sum(w_pose) * 207.0 * 2.0 + 1e-8
        real_rs, fake_rs = batch_rodrigues(real_pose.view(-1, 3)).view(-1, 24, 9)[:,1:,:], batch_rodrigues(fake_pose.view(-1, 3)).view(-1, 24, 9)[:,1:,:]
        dif_rs = ((real_rs - fake_rs) ** 2).view(-1, 207)
        return torch.matmul(dif_rs.sum(1), w_pose) * 1.0 / k

    def batch_encoder_disc_l2_loss(self, disc_value):
        k = disc_value.shape[0]
        return torch.sum((disc_value - 1.0) ** 2) * 1.0 / k

    def batch_adv_disc_l2_loss(self, real_disc_value, fake_disc_value):
        ka = real_disc_value.shape[0]
        kb = fake_disc_value.shape[0]
        lb, la = torch.sum(fake_disc_value ** 2) / kb, torch.sum((real_disc_value - 1) ** 2) / ka
        return la, lb, la + lb

    def save_model(self, result):
        exclude_key = 'module.smpl'
        def exclude_smpl(model_dict):
            result = OrderedDict()
            for (k, v) in model_dict.items():
                if exclude_key in k:
                    continue
                result[k] = v
            return result

        parent_folder = '/home/richie/MAML_HMR/src/trained_model_1'
        if not os.path.exists(parent_folder):
            os.makedirs(parent_folder)

        title = result['epoch']
        generator_save_path = os.path.join(parent_folder, str(title) + '_generator.pkl')
        torch.save(exclude_smpl(self.generator.state_dict()), generator_save_path)
        disc_save_path = os.path.join(parent_folder, str(title) + '_discriminator.pkl')
        torch.save(exclude_smpl(self.discriminator.state_dict()), disc_save_path)

        # gen_clone.load_state_dict(deepcopy(self.generator.state_dict()))
        # disc_clone.load_state_dict(deepcopy(self.discriminator.state_dict()))
        with open(os.path.join(parent_folder, str(title) + '.txt'), 'w') as fp:
            fp.write(str(result))

    def finetuning(self, spt_data, qry_data):

        batch_size = spt_data[0].shape[0]
        query_size = spt_data[0].shape[1]
        e_loss_list_qry = [0 for _ in range(self.update_step + 1)]
        d_loss_list_qry = [0 for _ in range(self.update_step + 1)]
        loss_kp_2d_list_qry = [0 for _ in range(self.update_step + 1)]
        loss_kp_3d_list_qry = [0 for _ in range(self.update_step + 1)]
        loss_shape_list_qry = [0 for _ in range(self.update_step + 1)]
        loss_spose_list_qry = [0 for _ in range(self.update_step + 1)]
        d_disc_loss_list_qry = [0 for _ in range(self.update_step + 1)]
        for i in range(batch_size):

            gen_clone = HMRNetBase().to(device)
            disc_clone = Discriminator().to(device)
            gen_clone.train()
            disc_clone.train()

            gen_clone.load_state_dict(deepcopy(self.generator.state_dict()))
            disc_clone.load_state_dict(deepcopy(self.discriminator.state_dict()))
            # e_opt_clone = torch.optim.Adam(gen_clone.parameters(), lr = self.e_base_lr, weight_decay = args.e_wd)
            # d_opt_clone = torch.optim.Adam(disc_clone.parameters(), lr = self.d_base_lr, weight_decay = args.d_wd)
            # Update step 0
            # calculate the updated and making a deep copy of it
            spt_imgs = torch.from_numpy(spt_data[7][i]).to(device)
            generator_outputs = gen_clone(spt_imgs, params = None)
            loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, spt_data, i, params = None, finetune = True, new_dis = disc_clone)
                # self._calc_loss(generator_outputs, spt_data, i, params = d_fast_weights_net)
            e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
            d_loss = d_disc_loss

            e_fast_weights_net,  e_fast_weights_grad = gradient_update_parameters(gen_clone, e_loss, step_size=self.e_base_lr)
            d_fast_weights_net,  d_fast_weights_grad = gradient_update_parameters(disc_clone, d_loss, step_size=self.d_base_lr)

            # Test on the query set: using the weights before upadte
            with torch.no_grad():
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = gen_clone(qry_imgs, params = OrderedDict(gen_clone.meta_named_parameters()))
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = d_fast_weights_net, finetune = True, new_dis = disc_clone)

                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[0] += e_loss
                d_loss_list_qry[0] += d_loss
                loss_kp_2d_list_qry[0] += loss_kp_2d
                loss_kp_3d_list_qry[0] += loss_kp_3d
                loss_shape_list_qry[0] += loss_shape
                loss_spose_list_qry[0] += loss_pose
                d_disc_loss_list_qry[0] += e_disc_loss
            # Test on the query set: using the upadte weighted
            with torch.no_grad():
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = gen_clone(qry_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = d_fast_weights_net, finetune = True, new_dis = disc_clone)
                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[1] += e_loss
                d_loss_list_qry[1] += d_loss
                loss_kp_2d_list_qry[1] += loss_kp_2d
                loss_kp_3d_list_qry[1] += loss_kp_3d
                loss_shape_list_qry[1] += loss_shape
                loss_spose_list_qry[1] += loss_pose
                d_disc_loss_list_qry[1] += e_disc_loss

            for k in range(1, self.update_step):
                # Uptate step k: using updaated weights from step 0
                spt_imgs = torch.from_numpy(spt_data[7][i]).to(device)
                generator_outputs = gen_clone(spt_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, spt_data, i, params = d_fast_weights_net, finetune = True, new_dis = disc_clone)

                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_fast_weights_net,  e_fast_weights_grad = gradient_update_parameters(gen_clone, e_loss, updated_params = e_fast_weights_net, params = e_fast_weights_grad, step_size=self.e_base_lr)
                d_fast_weights_net,  d_fast_weights_grad = gradient_update_parameters(disc_clone, d_loss, updated_params = d_fast_weights_net, params = d_fast_weights_grad, step_size=self.d_base_lr)

                # Test on the query set: using updated weights from step k
                qry_imgs = torch.from_numpy(qry_data[7][i]).to(device)
                generator_outputs = gen_clone(qry_imgs, params = e_fast_weights_net)
                loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, \
                    e_disc_loss, d_disc_loss, d_disc_real, d_disc_predict = self._calc_loss(generator_outputs, qry_data, i, params = d_fast_weights_net, finetune = True, new_dis = disc_clone)
                e_loss = loss_kp_2d + loss_kp_3d + loss_shape + loss_pose + e_disc_loss
                d_loss = d_disc_loss

                e_loss_list_qry[k+1] += e_loss
                d_loss_list_qry[k+1] += d_loss
                loss_kp_2d_list_qry[k+1] += loss_kp_2d
                loss_kp_3d_list_qry[k+1] += loss_kp_3d
                loss_shape_list_qry[k+1] += loss_shape
                loss_spose_list_qry[k+1] += loss_pose
                d_disc_loss_list_qry[k+1] += e_disc_loss

            # generator_outputs = gen_clone(spt_imgs, params = None)
            del gen_clone
            del disc_clone

        # write python dict to a file
        mydict = {}
        mydict['imgs'] = qry_imgs
        mydict['thetas'] = generator_outputs[2]
        # generator_outputs[i][0]: theta; shape:[16, 85]
        # generator_outputs[i][1]: verts; shape:[16, 6890, 3]
        # generator_outputs[i][2]: j2d; shape:[16, 19, 2]
        # generator_outputs[i][3]: j3d; shape:[16, 19, 3]
        # generator_outputs[i][4]: Rs; shape:[16, 24, 3, 3]
        output = open('./results/finetuned_data.pkl', 'wb')
        pickle.dump(mydict, output)
        output.close()

        e_loss = np.array([loss.item() for loss in e_loss_list_qry]) / batch_size
        d_loss = np.array([loss.item() for loss in d_loss_list_qry]) / batch_size
        loss_kp_2d = np.array([loss.item() for loss in loss_kp_2d_list_qry]) / batch_size
        loss_kp_3d = np.array([loss.item() for loss in loss_kp_3d_list_qry]) / batch_size
        loss_shape = np.array([loss.item() for loss in loss_shape_list_qry]) / batch_size
        loss_pose = np.array([loss.item() for loss in loss_spose_list_qry]) / batch_size
        e_disc_loss = np.array([loss.item() for loss in d_disc_loss_list_qry]) / batch_size

        return e_loss, d_loss, loss_kp_2d, loss_kp_3d, loss_shape, loss_pose, e_disc_loss


from pathlib import Path
from collections import Counter

from dfs import graph

def test_compute_scc1():
    G = read_file(10, 'test_files/scc1.txt')
    expected_result = [3, 3, 3, 0, 0]
    G = graph(G)
    leaders = G.compute_scc().values()
    sizes = Counter(leaders).most_common(5)
    actual_result = [i[1] for i in sizes] + [0] * (5 - len(sizes))
    assert actual_result == expected_result

def test_compute_scc2():
    G = read_file(9, 'test_files/scc2.txt')
    expected_result = [3, 3, 2, 0, 0]
    G = graph(G)
    leaders = G.compute_scc().values()
    sizes = Counter(leaders).most_common(5)
    actual_result = [i[1] for i in sizes] + [0] * (5 - len(sizes))
    assert actual_result == expected_result

def test_compute_scc3():
    G = read_file(9, 'test_files/scc3.txt')
    expected_result = [3, 3, 1, 1, 0]
    G = graph(G)
    leaders = G.compute_scc().values()
    sizes = Counter(leaders).most_common(5)
    actual_result = [i[1] for i in sizes] + [0] * (5 - len(sizes))
    assert actual_result == expected_result

def test_compute_scc4():
    G = read_file(9, 'test_files/scc4.txt')
    expected_result = [7, 1, 0, 0, 0]
    G = graph(G)
    leaders = G.compute_scc().values()
    sizes = Counter(leaders).most_common(5)
    actual_result = [i[1] for i in sizes] + [0] * (5 - len(sizes))
    assert actual_result == expected_result

def test_compute_scc5():
    G = read_file(13, 'test_files/scc5.txt')
    expected_result = [6, 3, 2, 1, 0]
    G = graph(G)
    leaders = G.compute_scc().values()
    sizes = Counter(leaders).most_common(5)
    actual_result = [i[1] for i in sizes] + [0] * (5 - len(sizes))
    assert actual_result == expected_result

def read_file(num_nodes, filename):
    test_directory = Path(__file__).parent
    file = open(test_directory / filename, "r")
    data = file.readlines()
    G = [[] for i in range(num_nodes)]

    for line in data:
            items = line.split()
            G[int(items[0])-1] += [str(items[1])]
    G = dict(zip([str(i) for i in range(1, num_nodes, 1)], G))

    return G


#!/usr/bin/env python3

import numpy as np

import sys
sys.path.append('../')

from modules.alfa_feynman_procesamiento import wrapper_lectura, \
                                               metodo_alfa_feynman

if __name__ == '__main__':

    # -------------------------------------------------------------------------
    # Parámetros de entrada
    # -------------------------------------------------------------------------
    # Archivos a leer
    nombres = [
              '../datos/nucleo_01.D1.bin',
              '../datos/nucleo_01.D2.bin',
              ]
    # Intervalos para agrupar los datos adquiridos
    int_agrupar = 5
    # Técnica de agrupamiento
    numero_de_historias = 100  # Historias que se promediarán
    dt_maximo = 50e-3          # másimo intervalo temporal para cada historia
    # -------------------------------------------------------------------------
    # Lectura y agrupamiento
    leidos = wrapper_lectura(nombres, int_agrupar)
    # -------------------------------------------------------------------------

    calculos = [
                'var_paralelo',
                'cov_paralelo',
                'sum_paralelo',
                ]

    for calculo in calculos:
        Y_historias = metodo_alfa_feynman(leidos, numero_de_historias,
                                          dt_maximo, calculo, nombres)
        for Y_historia in Y_historias:
            print(np.array(Y_historia)[9, :])


from typing import Dict, List, Optional

import tensorflow as tf
from tensorflow.keras import layers

from ..layers.binarizer import RETVecBinarizer
from .layers import dense_block
from .outputs import build_outputs

def build_retvec_base_from_config(config: Dict) -> tf.keras.Model:
    m = config["model"]
    o = config["outputs"]
    return build_retvec_base(
        word_length=m["word_length"],
        char_encoding_size=m["char_encoding_size"],
        char_encoding_type=m["char_encoding_type"],
        replacement_char=m["replacement_char"],
        initial_spatial_dropout_rate=m["initial_spatial_dropout_rate"],
        projection_dims=m["projection_dims"],
        encoder_dims=m["encoder_dims"],
        encoder_dropout=m["encoder_dropout"],
        encoder_spatial_dropout_rate=m["encoder_spatial_dropout_rate"],
        encoder_initializer=m["encoder_initializer"],
        encoder_norm_type=m["encoder_norm_type"],
        encoder_norm_epsilon=m["encoder_norm_epsilon"],
        encoder_activation=m["encoder_activation"],
        encoder_seq_output_dim=m["encoder_seq_output_dim"],
        encoder_seq_output_activation=m["encoder_seq_output_activation"],
        encoder_seq_output_dropout=m["encoder_seq_output_dropout"],
        tokenizer_dense_dim=m["tokenizer_dense_dim"],
        tokenizer_activation=m["tokenizer_activation"],
        tokenizer_dropout=m["tokenizer_dropout"],
        similarity_dim=o["similarity_dim"],
        original_decoder_size=o["original_decoder_size"],
        aug_decoder_size=o["aug_decoder_size"],
        aug_vector_dim=o["aug_vector_dim"],
        aug_matrix_dim=o["aug_matrix_dim"],
        outputs_dropout_rate=o["outputs_dropout_rate"],
        similarity_norm_type=o["similarity_norm_type"],
    )

def build_retvec_base(
    word_length: int = 16,
    char_encoding_size: int = 24,
    char_encoding_type: str = "UTF-8",
    replacement_char: int = 65533,
    initial_spatial_dropout_rate: float = 0.0625,
    projection_dims: List[int] = [32, 32],
    encoder_dims: List[int] = [256],
    encoder_dropout: float = 0.0,
    encoder_spatial_dropout_rate: float = 0.0,
    encoder_initializer: str = "glorot_uniform",
    encoder_norm_type: Optional[str] = None,
    encoder_norm_epsilon: float = 1e-6,
    encoder_activation: str = "gelu",
    encoder_seq_output_dim: int = 0,
    encoder_seq_output_activation: Optional[str] = None,
    encoder_seq_output_dropout: float = 0.0,
    tokenizer_dense_dim: int = 256,
    tokenizer_activation: str = "tanh",
    tokenizer_dropout: float = 0.0,
    similarity_dim: int = 256,
    original_decoder_size: int = 0,
    aug_decoder_size: int = 0,
    aug_vector_dim: int = 0,
    aug_matrix_dim: int = 0,
    outputs_dropout_rate: float = 0.0,
    similarity_norm_type: str = "l2",
) -> tf.keras.Model:
    """RETVec model based on MLP architecture.

    Args:
        word_length: Maximum number of characters in input string to.

        char_encoding_size: Size of output character encoding.

        char_encoding_type: String name for the unicode encoding that should
            be used to decode each string.

        replacement_char: The replacement codepoint to be used in place
            of invalid substrings in input.

        initial_spatial_dropout_rate: Spatial dropout rate on character
            encoding.

        projection_dims: Dense dimensions before flatten layer.

        encoder_dims: Dense dimensions after flatten layer.

        encoder_dropout: Feature dropout rate in dense blocks.

        encoder_spatial_dropout: Spatial dropout rate in dense blocks.

        encoder_initializer: Initializer used for dense blocks in encoder.

        encoder_norm_type: Norm type. One of 'layer', 'scaled', 't5' or None.

        encoder_norm_epsilon: Epsilon value for norm.

        encoder_activation: Activation to use in encoder layers.

        encoder_seq_output_dim: Output encoder dimension to project encoder
            sequence outputs to if `encoder_sequence_pooling` is 'dense'.

        encoder_seq_output_activation: Activation applied onto the encoder
            sequence outputs.

        encoder_seq_output_dropout: Dropout on encoder seq dense layer.

        tokenizer_dense_dim: Dimension of tokenizer, applied after flattening.
            If set, expands or compresses the tokenizer to this dimension
            before the tokenizer activation is applied.

        tokenizer_activation: Activation of tokenizer layer, must
            constrain output between [-1, 1] or [0, 1].

        tokenizer_dropout: Dropout on tokenizer dense layer, if applicable.

        similarity_dim: Dimension of the similarity embedding output.
            0 to disable.

        original_decoder_size: Dimension of a single char one-hot
            auto-encoder decoder output for the original token.
            0 to disable.

        aug_decoder_size: Dimension of a single char one-hot
            auto-encoder decoder output for the augmented token.
            0 to disable.

        aug_vector_dim: Dimension of the aug vector prediction output.
            0 to disable.

        aug_matrix_dim: Dimension of the aug matrix prediction output.
            0 to disable.

        outputs_dropout_rate: Dropout rate after tokenizer layer and
            before outputs.

        similarity_norm_type: Norm used at the similarity output,
            one of ['layer', 'batch', 'l2', None]

    Returns:
        A MLP-based RetVec model, ready for pretraining.
    """
    inputs = layers.Input(shape=(1,), name="token", dtype=tf.string)

    # character embedding
    char_encoding = RETVecBinarizer(
        word_length=word_length,
        encoding_size=char_encoding_size,
        encoding_type=char_encoding_type,
        replacement_char=replacement_char,
        name="binarizer",
    )(inputs)

    if initial_spatial_dropout_rate:
        encoder = layers.SpatialDropout1D(initial_spatial_dropout_rate)(
            char_encoding
        )

    for projection_dim in projection_dims:
        encoder = dense_block(
            x=encoder,
            units=projection_dim,
            activation=encoder_activation,
            norm_type=encoder_norm_type,
            norm_epsilon=encoder_norm_epsilon,
            dropout_rate=encoder_dropout,
        )

        if encoder_spatial_dropout_rate:
            encoder = layers.SpatialDropout1D(encoder_spatial_dropout_rate)(
                encoder
            )

    # intermediate layers before tokenizer
    encoder = layers.Flatten()(encoder)

    for encoder_dim in encoder_dims:
        encoder = dense_block(
            x=encoder,
            units=encoder_dim,
            activation=encoder_activation,
            norm_type=encoder_norm_type,
            norm_epsilon=encoder_norm_epsilon,
            dropout_rate=encoder_dropout,
            kernel_initializer=encoder_initializer,
        )

    # this is the layer is used to bound the values outputed by the tokenizer
    # between -1 and 1 using tanh, softsign etc. Allows to use activation
    # functions in the tranformers block that are unbounded such as gelu.
    # this is the layers used as output for the retvec sentence tokenizer
    # ! do not change it or the sentence tokenizer will break
    tokenizer_layer = dense_block(
        x=encoder,
        units=tokenizer_dense_dim,
        activation=tokenizer_activation,
        dropout_rate=tokenizer_dropout,
        kernel_initializer=encoder_initializer,
        name="tokenizer",
    )

    # set up encoder sequence output for sequence prediction tasks
    encoder_seq_output = encoder

    # project encoder dim if needed
    if encoder_seq_output_dim:
        encoder_seq_output = dense_block(
            x=encoder_seq_output,
            units=encoder_seq_output_dim,
            activation=encoder_seq_output_activation,
            dropout_rate=encoder_seq_output_dropout,
            kernel_initializer=encoder_initializer,
            name="encoder_seq",
        )

    outputs = build_outputs(
        tokenizer_layer=tokenizer_layer,
        encoder_seq_output=encoder_seq_output,
        activation=encoder_activation,
        similarity_dim=similarity_dim,
        original_decoder_size=original_decoder_size,
        aug_decoder_size=aug_decoder_size,
        aug_vector_dim=aug_vector_dim,
        aug_matrix_dim=aug_matrix_dim,
        outputs_dropout_rate=outputs_dropout_rate,
        similarity_norm_type=similarity_norm_type,
    )
    return tf.keras.Model(inputs, outputs)


import webob.dec
import webob.exc

import wafflehaus.base
import wafflehaus.payload_filter as pf
import wafflehaus.resource_filter as rf

class DefaultPayload(wafflehaus.base.WafflehausBase):

    def __init__(self, app, conf):
        super(DefaultPayload, self).__init__(app, conf)
        self.log.name = conf.get('log_name', __name__)
        self.log.info('Starting wafflehaus default payload middleware')
        self.resources = rf.parse_resources(conf.get('resource'))
        self.defaults = pf.get_defaults(conf.get('defaults'))

    def _override(self, req):
        super(DefaultPayload, self)._override(req)
        new_resource = self._reconf(req, 'str', 'resource')
        if new_resource is not None:
            self.resources = rf.parse_resources(new_resource)
        new_defaults = self._reconf(req, 'str', 'defaults')
        if new_defaults is not None:
            self.defaults = pf.get_defaults(new_defaults)

    @webob.dec.wsgify
    def __call__(self, req):
        super(DefaultPayload, self).__call__(req)
        if not self.enabled:
            return self.app

        if not self.defaults:
            return self.app
        if rf.matched_request(req, self.resources):
            self.body = pf.json_set_unset_keys(req.body, self.defaults)
            req.body = self.body
        return self.app

def filter_factory(global_conf, **local_conf):
    """Returns a WSGI filter app for use with paste.deploy."""
    conf = global_conf.copy()
    conf.update(local_conf)

    def def_payload(app):
        return DefaultPayload(app, conf)
    return def_payload


# the script that handles the data
import json
from datetime import datetime

folder_location = "/home/razor/Downloads/nsr/projects/open_source/my_tool"
def load():
	with open(folder_location+"/data.json") as f:
		data = json.load(f)
	return data

def look_up(name):
	data = load()
	try:
		return data['records'][name]
	except KeyError:
		return False

def add_timestamp():
	data = load()
	data['last_modified'] = str(datetime.now())
	json.dump(data, open(folder_location+"/data.json", "w"), indent = 4)

def add(name,address):
	data = load()
	data['records'][name]=address
	json.dump(data, open(folder_location+"/data.json", "w"), indent = 4)
	add_timestamp()

def approval(cmd):
	while(True):
		ans = input(f'Do you want to proceed to {cmd} this entry (y/n)')
		if ans=='y' or ans=='y':
			return True
		elif ans=='n' or ans=='N':
			return False
		else:
			print("Invalid Argument")

def delete(name,forced=False):
	if (forced if forced==True else approval('delete')):
		data = load()
		removed = data['records'].pop(name,None)
		json.dump(data, open(folder_location+"/data.json", "w"), indent = 4)
		if not forced:
			print("Deleted alias corresponding to location "+removed)
		add_timestamp()

def append(name,address):
	if approval('append'):
		add(name,address)

def last_edited():
	data = load()
	return data['last_modified']


from typing import Union

def sun_angle(time: str) -> Union[int, str]:
    """
        Check if it's not the night time. If so - return sun angle. If not - return message "I don't see the sun!".
    """
    hour = int(time[0])*10 + int(time[1])
    minutes = int(time[3])*10 + int(time[4])

    if hour < 6:
        return "I don't see the sun!"
    elif hour >= 18 and minutes != 0:
        return "I don't see the sun!"

    # formula
    result = float((hour - 6) * 15 + minutes * 0.25)
    return result

if __name__ == '__main__':
    print(sun_angle("12:15")) # 93.75
    print(sun_angle("12:00")) # 90.0
    print(sun_angle("16:20")) # 155.0
    print(sun_angle("18:01")) # I don't see the sun!


from tori_test import *

# ---
# ヘルパー関数類

def run_tori_minus_test_code(code):
  evaluator = Evaluator()
  tokens = tr_lexer(code)
  trees = tr_parser(tokens)

  for tree in trees:
    ret = evaluator.eval(tree)

  return get_ret_value(ret)

def get_ret_value(ret):
  ret_kind = ret.kind

  if ret_kind == TR_Value_Kind.num_:
    return float(ret.value)

  elif ret_kind == TR_Value_Kind.str_:
    return ret.value

  elif ret_kind == TR_Value_Kind.bool_:
    return ret.value == "true"

  elif ret_kind == TR_Value_Kind.non_:
    return None

# ---


import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
import wave as we

sample_rate, data = wavfile.read('test_noise.wav')
t = int(len(data)/sample_rate)
Fs = t*sample_rate
print('sample rate=', sample_rate)
print('sample=', len(data))
print('time=', len(data)/sample_rate)

n = np.linspace(0, t, Fs)
plt.plot(n, data)
plt.xlabel('Time(s)')
plt.ylabel('Amplitude')
plt.title('Noisy Signal Waveforms')
plt.show()

def moving_avg(audio_data, avg_length):
    new_data = []
    for i in range(data.shape[0]-avg_length+1):
        new_data.append(np.average(data[i:i+avg_length]))
    new_data = np.array(new_data).reshape((-1, 1))
    new_data = np.int32(new_data)
    return new_data

length = data.shape[0]/16000
for i in range(80,100,10):
    new_data = moving_avg(data, i)
    time = np.linspace(0., length, new_data.shape[0])
    plt.plot(time, new_data)
    plt.xlabel("Time [s]")
    plt.ylabel("Amplitude")
    plt.title("Moving Avg Filter  "+str(i))
    plt.show()

    save_wav = new_data.real.reshape((len(new_data), 1)).T.astype(np.short)
    f = we.open("1)moving_avg_fliter.wav", "wb")
    f.setnchannels(1)
    f.setsampwidth(2)
    f.setframerate(16000)
    f.writeframes(save_wav.tostring())
    f.close()


import pygame
import sys
import random
from pygame.locals import *

pygame.init()

GAME_WINDOW = pygame.display.set_mode((150, 150), 0, 32)

pygame.display.set_caption('Tic Tac Toe')

# lista opisująca stan pola gry, 0 - pole puste, 1 - gracz, 2 - komputer
PLAYING_FIELD = [0, 0, 0,
            0, 0, 0,
            0, 0, 0]

MOVE = 1  # do kogo należy ruch: 1 – gracz, 2 – komputer
WINER = 0  # wynik gry: 0 - nikt, 1 - gracz, 2 - komputer, 3 - remis
WIN = False

# --------------------------- rysowanie planszy -----------------------------------

def draw_game_window():
    for i in range(0, 3):  # x
        for j in range(0, 3):  # y
            # argumenty: powierzchnia, kolor, x,y, w,h, grubość linii
            pygame.draw.rect(GAME_WINDOW, (255, 255, 255),
                             Rect((j * 50, i * 50), (50, 50)), 1)

# narysuj kółka

def draw_playing_game():
    for i in range(0, 3):
        for j in range(0, 3):
            field = i * 3 + j  # zmienna pole przyjmuje wartości od 0-8
            x = j * 50 + 25
            y = i * 50 + 25

            if PLAYING_FIELD[field] == 1:
                # rysuj kółko gracza
                pygame.draw.circle(GAME_WINDOW, (0, 0, 255), (x, y), 10)
            elif PLAYING_FIELD[field] == 2:
                # rysuj kółko komputera
                pygame.draw.circle(GAME_WINDOW, (255, 0, 0), (x, y), 10)

                # postaw kółko lub kółko inngo koloru

def put_a_sing(field, MOVE):
    if PLAYING_FIELD[field] == 0:
        if MOVE == 1:  # ruch gracza
            PLAYING_FIELD[field] = 1
            return 2
        elif MOVE == 2:  # ruch komputera
            PLAYING_FIELD[field] = 2
            return 1

    return MOVE

#Funkcja sprawdzająca czy komputer
# może wygrać
# musi blokować

def check_the_fields(uklad, winer=None):
    value = None
    # lista wielowymiarowa, której elementami są inne listy zagnieżdżone
    FIELDS_INDEX = [  # trójki pól planszy do sprawdzania
        [0, 1, 2], [3, 4, 5], [6, 7, 8],  # indeksy pól w poziomie (wiersze)
        [0, 3, 6], [1, 4, 7], [2, 5, 8],  # indeksy pól w pionie (kolumny)
        [0, 4, 8], [2, 4, 6]  # indeksy pól na skos (przekątne)
    ]

    for list in FIELDS_INDEX:
        li = []  # lista pomocnicza
        for ind in list:
            li.append(PLAYING_FIELD[ind])  # zapisz wartość odczytaną z PLAYING_FIELD
        if (li in uklad):  # jeżeli znalazłeś układ wygrywający lub blokujący
            # zwróć wygranego (1,2) lub indeks pola do zaznaczenia
            value = winer if winer else list[li.index(0)]

    return value

# ruchy komputera

def ai_move(MOVE):
    field = None  # które pole powinien zaznaczyć komputer

    # listy wielowymiarowe, których elementami są inne listy zagnieżdżone
    winning_hands = [[2, 2, 0], [2, 0, 2], [0, 2, 2]]
    locking_hands = [[1, 1, 0], [1, 0, 1], [0, 1, 1]]

    # sprawdź, czy komputer może wygrać
    field = check_the_fields(winning_hands)
    if field is not None:
        return put_a_sing(field, MOVE)

    # jeżeli komputer nie może wygrać, blokuj gracza
    field = check_the_fields(locking_hands)
    if field is not None:
        return put_a_sing(field, MOVE)

    # jeżeli nie można wygrać i gracza nie trzeba blokować, wylosuj pole
    while field is None:
        pos = random.randrange(0, 9)  # wylosuj wartość od 0 do 8
        if PLAYING_FIELD[pos] == 0:
            field = pos

    return put_a_sing(field, MOVE)

# sprawdzanie wyniku

def who_win():
    # układy wygrywające dla gracza i komputera
    player_layout = [[1, 1, 1]]
    computer_layout = [[2, 2, 2]]

    WINER = check_the_fields(player_layout, 1)  # czy wygrał gracz?
    if not WINER:  # jeżeli gracz nie wygrywa
        WINER = check_the_fields(computer_layout, 2)  # czy wygrał komputer?

    # sprawdź remis
    if 0 not in PLAYING_FIELD and WINER not in [1, 2]:
        WINER = 3

    return WINER

# rysowanie tesktu z wynikiem

def print_result(WINER):
    fontObj = pygame.font.Font('freesansbold.ttf', 16)
    if WINER == 1:
        text = u'BRAWO, Wygrałeś'
    elif WINER == 2:
        text = u'Niestey przegrana'
    elif WINER == 3:
        text = 'Remis!'
    text_ob = fontObj.render(text, True, (20, 255, 20))
    text_pr = text_ob.get_rect()
    text_pr.center = (75, 75)
    GAME_WINDOW.blit(text_ob, text_pr)

# pętla główna programu
while True:
    # obsługa zdarzeń generowanych przez gracza
    for event in pygame.event.get():
        # przechwyć zamknięcie okna
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

        if WIN is False:
            if MOVE == 1:
                if event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:  # jeżeli naciśnięto 1. przycisk
                        mouseX, mouseY = event.pos  # rozpakowanie tupli
                        # wylicz indeks klikniętego pola
                        field = (int(mouseY / 50) * 3) + int(mouseX / 50)
                        MOVE = put_a_sing(field, MOVE)
            elif MOVE == 2:
                MOVE = ai_move(MOVE)

            WINER = who_win()
            if WINER is not None:
                WIN = True

    GAME_WINDOW.fill((0, 0, 0))  # definicja koloru powierzchni w RGB
    draw_game_window()
    draw_playing_game()
    if WIN:
        print_result(WINER)
    pygame.display.update()


"""Simple script to visualize trained policy"""
import tensorflow as tf
from acme.agents.tf import actors
from acme import wrappers
import matplotlib.pyplot as plt
import toml
import pandas as pd
from environments.dm_control.utils import episode_data
from dm_control.rl.control import Environment
from environments.dm_control import tank, moving_coil

STORE_PATH = '/root/acme/842e55d4-74b1-11ec-a60d-0242ac110002/'

def get_dict(filename):
    """"Read configuration file from folder"""
    with open(STORE_PATH + 'parameters/' + filename) as file:
        return  toml.load(file)

physics_par = get_dict('phys_par.toml')
task_par = get_dict('task_par.toml')

# Generate physics env and task with parameters as during training
if physics_par['phys_name'] == 'tank':
    physics = tank.physics.Physics(**physics_par)
    task = tank.tasks.Step(**task_par)
elif physics_par['phys_name'] == 'MovingCoil':
    physics = moving_coil.physics.Physics(**physics_par)
    task = moving_coil.tasks.Step(**task_par)
else:
    raise NameError(f'Physics env {physics_par["phys_name"]} not available')

# Set debug to True to store episode data
task.par_dict['debug'] = True

# Instantiate env
env = Environment(physics, task, time_limit=2.)
env = wrappers.CanonicalSpecWrapper(env, clip=True) # Clip actions by bounds
env = wrappers.SinglePrecisionWrapper(env)

# Load policy snapshot data
FOLDER_PATH =  STORE_PATH +'snapshots/policy'
ENV_LOGS_PATH = STORE_PATH + '/logs/environment_loop/logs.csv'
env_logs = pd.read_csv(ENV_LOGS_PATH)

# Load policy
policy_net = tf.saved_model.load(FOLDER_PATH)

# Create the actor which defines how we take actions.
actor = actors.FeedForwardActor(
    policy_network=policy_net)

# Replay policy
timestep = env.reset()
while not timestep.last():
    action = actor.select_action(timestep.observation)
    timestep = env.step(action)

# Fetch sim data
data = episode_data.pack_datadict(env.task.datadict)

# Plot all time traces in episode dictionary
for key in [k for k in data.keys() if k != 'time']:
    plt.plot(data['time'],data[key])
    plt.ylabel(key)
    plt.xlabel('time')
    plt.show()

plt.plot(env_logs.episodes, env_logs.episode_return)
plt.xlabel('episodes')
plt.ylabel('epsisode return')
plt.show()

plt.plot(env_logs.episodes, env_logs.steps_per_second)
plt.xlabel('episodes')
plt.ylabel('sps')
plt.show()


#!/usr/bin/env python3

import argparse
import datetime
import logging
import time

import dash_bootstrap_components as dbc
import requests
from dash import Dash, dcc, html
from dash.dependencies import Input, Output, State

from src import dash_page, flights_plot

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

parser = argparse.ArgumentParser(
    prog='Aviation Visualisation',
    description='A Dash app that visualises airline flights',
    epilog='Written for Special Topics Missing Semester 921CSPTST2K13'
)

parser.add_argument('-p', '--port')
parser.add_argument('-d', '--debug', choices=['true', 'false'])

app = Dash("Aviation Visualisation", external_stylesheets=[dbc.themes.SANDSTONE])
app.title = "Aviation Visualisation"
app.layout = dash_page.get_layout()
app.config.suppress_callback_exceptions = True

# global variables relevant for token
client_id = ""
client_secret = ""
access_token = ""
token_expiration_timestamp = 0

enable_debug = False
port = 8050

def handle_arguments():
    args = parser.parse_args()
    if args.port is not None:
        if not args.port.isdigit() or not 1 <= int(args.port) <= 65535:
            message = f"{args.port} is not a valid port number"
            raise ValueError(message)
        global port
        port = int(args.port)

    if args.debug is not None:
        global enable_debug
        enable_debug = bool(args.debug)

# converts a YYY-MM-DD date string to the SSIM format
def convert_date(date_string):
    date_object = datetime.datetime.strptime(date_string, '%Y-%m-%d')
    return date_object.strftime("%d%b%y").upper()

def get_token():
    global access_token, token_expiration_timestamp

    # if there is no token or the token is expired, get new oauth access token
    if access_token == "" or token_expiration_timestamp < int(time.time()):
        data = {
            'client_id': client_id,
            'client_secret': client_secret,
            'grant_type': "client_credentials"
        }
        response = requests.post("https://api.lufthansa.com/v1/oauth/token", data=data).json()
        access_token = response["access_token"]
        token_expiration_timestamp = int(time.time()) + response['expires_in']

    return access_token

@app.callback(Output('map-figure', 'children'),
              Input('submit-button', 'n_clicks'),
              State('airline-search', 'value'),
              State('date-search', 'date'),
              State('map-figure', 'children'), )
def search(n_clicks, airline_search, date_search, children):
    if n_clicks < 1 or airline_search is None:
        return

    logger.info("New search request for: %s, %s", airline_search, date_search)

    headers = {
        'Authorization': 'Bearer {}'.format(get_token()),
        'Accept': 'application/json'
    }

    query_params = {
        'airlines': airline_search,
        'startDate': convert_date(date_search),
        'endDate': convert_date(date_search),
        'daysOfOperation': '1234567',
        'timeMode': 'UTC',
    }

    retry_counter = 0
    while True:
        response = requests.get(url='https://api.lufthansa.com/v1/flight-schedules/flightschedules/passenger',
                                params=query_params, headers=headers)
        logger.info("Lufthansa API answered with status code %s", response.status_code)
        if response.status_code == 200:
            break

        time.sleep(5)
        retry_counter += 1
        if retry_counter > 5:
            raise ConnectionError("Unable to get proper Response from Lufthansa API")

    json = response.json()
    if len(json) == 0:
        return [html.H2("No flights have been found for the given search parameters.")]

    figure = flights_plot.create_connection_map(response.json())
    figure.to_html("test.html")

    return [dcc.Graph(figure=figure)]

handle_arguments()

if __name__ == '__main__':
    app.run(debug=enable_debug, port=port)


from collections import defaultdict

class Graph:

	def __init__(self,vertices):
		self.V= vertices #Number of vertices
		self.graph = [] # default dictionary to store graph

	def addEdge(self,u,v,w): #Adds an edge
		self.graph.append([u,v,w])

	def find(self, parent, i): #finds a vertex
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y): #union set
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)

		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else :
			parent[yroot] = xroot
			rank[xroot] += 1

	def KruskalMST(self):

		list = [] #list

		i = 0
		e = 0

		self.graph = sorted(self.graph,key=lambda item: item[2]) # order all edges in non ascedning order by weight #copy of graph

		parent = [] ; rank = []

		for node in range(self.V):
			parent.append(node)
			rank.append(0)

		while e < self.V -1 : #edges is equal to number of V-1

			u,v,w = self.graph[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent ,v)

			if x != y:  #if edge doesnt make cycle then add it to list
				e = e + 1
				list.append([u,v,w])
				self.union(parent, rank, x, y)
			# Else discard the edge

		print ("Kruskal's Algorithm: ")
		for u,v,weight in list:
			print ("Vertex %d to Vertex %d with a weight of  %d" % (u,v,weight))

# Homework Graph
g = Graph(9)
g.addEdge(0, 1, 4)
g.addEdge(0, 4, 3)
g.addEdge(1, 4, 2)
g.addEdge(1, 5, 5)
g.addEdge(1, 2, 4)
g.addEdge(2, 5, 6)
g.addEdge(2, 6, 9)
g.addEdge(3, 6, 13)
g.addEdge(4, 7, 1)
g.addEdge(4, 5, 12)
g.addEdge(5, 7, 21)
g.addEdge(7, 8, 14)
g.addEdge(5, 8, 11)
g.addEdge(5, 6, 17)
g.addEdge(6, 8, 10)
g.addEdge(8, 9, 16)
g.addEdge(3, 9, 20)

g.KruskalMST()


# -*- coding: utf-8 -*-
import asyncio
import websockets
import logging
import json

from .rpc import Rpc
from ..exceptions import RPCError

log = logging.getLogger(__name__)

class Websocket(Rpc):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.ws = None
        self.client = None
        self._messages = {}
        self.notifications = asyncio.Queue(loop=self.loop)
        self._event = asyncio.Event(loop=self.loop)
        self._parser_terminated = False

    async def connect(self):
        ssl = True if self.url[:3] == "wss" else None
        self.ws = await websockets.connect(self.url, ssl=ssl, loop=self.loop)
        self.loop.create_task(self._parsing_wrapper())

    async def disconnect(self):
        if self.ws:
            await self.ws.close()

    async def _parsing_wrapper(self):
        """Wraps parse_messages() coroutine to retrieve and handle exceptions

        When parse_messages() stopped for any reason, websocket transport should be
        stopped, and get_response_by_id() should be notified about broken parser
        """
        try:
            await self.parse_messages()
        except asyncio.CancelledError:
            log.debug("Parsing task cancelled")
        except Exception:
            log.exception("Task stopped with exception")
        else:
            log.info("Task stopped")
        finally:
            await self.disconnect()
            # When parse_messages() terminated for any reason, some coroutines may still
            # be in waiting state waiting for API response. Indicate that parser was
            # terminated and set the event to let them proceed and shutdown
            self._parser_terminated = True
            self._event.set()

    async def parse_messages(self):
        """Listen websocket for incoming messages in infinity manner

        Messages which are responses (has id) are stored in dict, while
        messages which are notifies are stored in asyncio queue and are
        supposed to be processed later by whom who sets the subscribtion
        callback
        """

        async for message in self.ws:
            m = json.loads(message, strict=False)
            if "id" in m:
                log.debug("got mesage id {}".format(m["id"]))
                if m["id"] is None:
                    # Got message with null id
                    try:
                        for entry in m["error"]["data"]["stack"]:
                            # Iterate over all entries in error details
                            try:
                                original_message = json.loads(entry["data"]["str"])
                                m["id"] = original_message["id"]
                            except KeyError:
                                continue
                            else:
                                break
                    except KeyError:
                        pass
                    finally:
                        if not m["id"]:
                            # Fuckup, we was unable to extract original message
                            log.critical(
                                "Got error and unable to match it with proper request"
                            )
                            raise RuntimeError(m)
                        log.debug(
                            "restored message id by parsing node response: {}".format(
                                m["id"]
                            )
                        )
                self._messages[m["id"]] = m
                # Notify waiting coroutines that we have a new response
                self._event.set()
            elif m.get("method") == "notice":
                await self.notifications.put(m)

    async def get_response_by_id(self, request_id):
        """Pop response from dict containing all query results

        :param int request_id: request id to get response to
        """
        response = None
        while not response:
            if self._parser_terminated:
                break
            # Reset event state
            self._event.clear()
            # Lock until response ready
            await self._event.wait()
            log.debug("looking for response id {}".format(request_id))
            response = self._messages.pop(request_id, None)
        return response

    async def rpcexec(self, payload):
        """Execute a RPC call

        :param dict payload: json-rpc request in format:
            {"jsonrpc": "2.0", "method": "call", "params": "[x, y, z]", "id": 1}
        """
        if not self.ws:
            await self.connect()

        request_id = payload["id"]
        request_json = json.dumps(payload)

        await self.ws.send(request_json)
        response = await self.get_response_by_id(request_id)

        return response


# Imports
import random

# display board
def display_board(board):
    print(board[7]+'|'+board[8]+'|'+board[9])
    print(board[4]+'|'+board[5]+'|'+board[6])
    print(board[1]+'|'+board[2]+'|'+board[3])

test_board = ['#','X','O','X','O','X','O','X','O','X']
clear_board = [' ']*10
clear_board[0] = '#'
# display_board(test_board)

def player_input():
    marker = ''

    # Keep asking player 1 to choose 'X' or 'O'
    while marker != 'X' or marker != 'O':
        marker = input("Choose 'X' or 'O': ")

        player1 = marker

        # Assign Player2 the opposite marker
        if player1 == 'X':
            player2 = 'O'
        else:
            player2 = 'X'

        return (player1, player2)

# Display player markers
# print('\n')
# player1_marker, player2_marker = player_input()
# print('Player 1: '+player1_marker)
# print('Player 2: '+player2_marker)

def user_choice():
    # Variables
    choice = 'wrong'
    acceptable_range = range(0,10)
    within_range = False

    while choice.isdigit() == False or within_range == False:

        choice = input('Please enter a number (1-9): ')

        # Check that choice is an integer
        if choice.isdigit() == False:
            print('Please enter a digit from your number pad.')

        # Check that choice is within range
        if choice.isdigit() == True:
            if int(choice) in acceptable_range:
                within_range = True
            else:
                print('Sorry, you are out of acceptable range.')
                within_range = False

        return int(choice)

def place_marker(board, marker, position):
    marker_chosen = marker

    move = position

    board[move] = marker_chosen
    display_board(board)

    return board

# place_marker(clear_board, player1_marker, pos)

def win_check(board, mark):
    if board[1] == mark and board[2] == mark and board[3] == mark:
        return 'Winner'
    elif board[4] == mark and board[5] == mark and board[6] == mark:
        return 'Winner'
    elif board[7] == mark and board[8] == mark and board[9] == mark:
        return 'Winner'
    elif board[1] == mark and board[4] == mark and board[7] == mark:
        return 'Winner'
    elif board[2] == mark and board[5] == mark and board[8] == mark:
        return 'Winner'
    elif board[3] == mark and board[6] == mark and board[9] == mark:
        return 'Winner'
    elif board[3] == mark and board[5] == mark and board[7] == mark:
        return 'Winner'
    elif board[1] == mark and board[5] == mark and board[9] == mark:
        return 'Winner'
    else:
        pass

# print(win_check(test_board, 'X'))

def choose_first():
    rando_num = random.randint(1,2)

    if rando_num == 1:
        print('Player 1 goes first!')
        return 'Player 1'
    else:
        print('Player 2 goes first!')
        return 'Player 2'

def space_check(board, position):
    available_pos = False

    while available_pos == False:
        if board[position] == ' ':
            available_pos = True
        else:
            available_pos = False

    return available_pos

def full_board_check(board):
    for x in board:
        if x != ' ':
            return True
        else:
            return False

def replay():
    player_response = input('Would you like to play again? (Y or N): ')

    if player_response == 'Y':
        return True
    else:
        return False

print('Welcome To Tic Tac Toe!')

while True:

    # Play The Game

    ## Set Everything Up (Board, Whos First, Choose Marker)
    the_board = [' ']*10
    player1_marker, player2_marker = player_input()

    turn = choose_first()
    print(turn + ' will go first')

    play_game = input('Ready to play? y or n? ')

    if play_game == 'y':
        game_on = True
    else:
        game_on = False

    ## Game Play

    while game_on:

        if turn == 'Player 1':

            # Show the board
            display_board(the_board)
            # Choose a position
            position = user_choice()
            # Place the marker on the position
            place_marker(the_board, player1_marker,position)
            # Check if they won
            if win_check(the_board,player1_marker):
                display_board(the_board)
                print('Player 1 Has Won!!')
                game_on = False
            else:
                if full_board_check(the_board):
                    display_board(the_board)
                    print("TIE GAME!")
                    break
                else:
                    turn = 'Player 2'

        else:
            # Show the board
            display_board(the_board)
            # Choose a position
            position = user_choice()
            # Place the marker on the position
            place_marker(the_board, player1_marker,position)
            # Check if they won
            if win_check(the_board,player1_marker):
                display_board(the_board)
                print('Player 2 Has Won!!')
                game_on = False
            else:
                if full_board_check(the_board):
                    display_board(the_board)
                    print("TIE GAME!")
                    break
                else:
                    turn = 'Player 1'
            # Or check if there is a tie

            # No tie and no win? Then next player's turn

        ### PLAYER ONE TURN

    if not replay():
        break


from datetime import datetime
from typing import Dict, Any, Union

DATE_FORMAT = '%Y-%m-%d'

class Accounting:
    def __init__(self, id: int, date: str, price: Dict[str, Union[int, float]],
                payment: Dict[str, Union[str, str]], info: Dict[str, str], **kwargs):
        self._id = id
        self._date = datetime.strptime(date, DATE_FORMAT)
        self._price = Price(**price)
        self._payment = Payment(**payment)
        self._info = Info(**info)
        self._year = self._date.year
        self._month = self._date.month

    def to_dict(self):
        return {
            'id': self._id,
            'date': self._date.strftime(DATE_FORMAT),
            'price': self._price.to_dict(),
            'payment': self._payment.to_dict(),
            'info': self._info.to_dict(),
            'year': self._year,
            'month': self._month
        }

class Price:
    def __init__(self, price: float, tax_percent: float, tax_free_price: float, **kwargs):
        self._price = price
        self._tax_free_price = tax_free_price
        self._tax_percent = tax_percent

    def to_dict(self):
        return {
            'price': self._price,
            'tax_free_price': self._tax_free_price,
            'tax_percent': self._tax_percent
        }

class Payment:
    def __init__(self, method: str, cheque_number: str, **kwargs):
        self._method = method
        self._cheque_number = cheque_number

    def to_dict(self):
        return {
            'method': self._method,
            'cheque_number': self._cheque_number
        }

class Info:
    def __init__(self, description: str, invoice_number: str, **kwargs):
        self._description = description
        self._invoice_number = invoice_number

    def to_dict(self):
        return {
            'description': self._description,
            'invoice_number': self._invoice_number
        }


import json
from pprint import pprint

def movie_info(movie):
    # pprint(movie)
    # id, title, poster_path, vote_average, overview, genre_ids
   result = {
    'id': movie['id'],
    'title': movie['title'],
    'poster_path': movie.get('poster_path'),
    'vote_average': movie['vote_average'],
    'overview': movie['overview'],
    'genre_ids': movie.get('genre_ids'),
   }
   return result

# movie.get # 해당 key가 있으면 해당 value를 반환, 없으면 None을 반환

# 아래의 코드는 수정하지 않습니다.
if __name__ == '__main__':
    movie_json = open('data/movie.json', encoding='utf-8')
    movie_dict = json.load(movie_json)

    pprint(movie_info(movie_dict))


"""This is a script to apply tags to the gaze coordinates found in each participant's gaze.csv.

The gaze point that falls next to the nearest box's center point will acquire the
tag associated with that box.

A new csv file will be generated with the tag column appended to the end of the
gaze.csv file.

The second half of the script combines all the participants' tagged csvs into one final csv.

It is specifically reading the final_tagged_csvs, the gaze files that are tagged
with the names of the features that people were observing.

Author: Eric Rios-Soderman

"""
import pandas as pd
import os
import datetime as dt
import sys
from map_functions import (
    gaze_tagger,
    ref_coordinate_processing,
)

path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, path)

from config.config import *

# Set env variables based on config file
try:
    env = sys.argv[1]
    env_var = eval(env + "_config")
except:
    print("Enter valid env variable. Refer to classes in the config.py file")
    sys.exit()

# the path will be the same, regardless if supplied or generated
data_folder_path = os.path.join(
    env_var.ROOT_PATH, env_var.ART_PIECE
)  # all the participant folders are here

output_folder_path = os.path.join(env_var.OUTPUT_PATH, env_var.ART_PIECE)

tag_file_path = os.path.join(output_folder_path, "tags_coordinates.csv")
user_tag_coordinates = pd.read_csv(tag_file_path)

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

for index, folder in enumerate(sorted(os.listdir(output_folder_path))):
    print(f"Starting mapping for folder {index} : {folder}")
    try:
        files = os.listdir(os.path.join(output_folder_path, folder))
    except:
        print(f"{folder} is not a folder")
        continue
    participant_id = folder.split(os.sep)[-1]  # get the participant id

    file_found = False
    for file in files:
        if "updated_gaze" in file and ".csv" in file:
            updated_gaze_path = os.path.join(output_folder_path, folder, file)
            participant_reference_gaze_csv = pd.read_csv(updated_gaze_path)
            file_found = True

    if not file_found:
        print(f"No Updated Gaze Csv found for folder : {folder}")
        continue

    participant_reference_gaze_csv = ref_coordinate_processing(
        participant_reference_gaze_csv
    )

    participant_reference_gaze_csv["tag"] = participant_reference_gaze_csv[
        "ref_coordinates"
    ].apply(lambda x: gaze_tagger(x, user_tag_coordinates))
    participant_output_path = os.path.join(output_folder_path, folder)
    participant_reference_gaze_csv.to_csv(
        os.path.join(participant_output_path, "final_gaze_tagged.csv")
    )

    del participant_reference_gaze_csv

    print("Done for folder -- ", folder)

# the final csv which will house the concatenated rows
target_csv = pd.DataFrame()

participant_list = []
no_gaze_csv = []

for folder in sorted(os.listdir(data_folder_path)):
    try:
        os.listdir(os.path.join(data_folder_path, folder))
        participant_list.append(folder)

    except:
        print(f"{folder} is not a folder")
        continue

ideal_rows = 0
participant_count = 0
for folder in sorted(os.listdir(output_folder_path)):
    try:
        files = os.listdir(os.path.join(output_folder_path, folder))
    except:
        print(f"{folder} is not a folder")
        continue
    participant_id = folder.split(os.sep)[-1]

    gaze_csv_path = os.path.join(
        os.path.join(output_folder_path, folder), "final_gaze_tagged.csv"
    )

    try:
        gaze_csv = pd.read_csv(gaze_csv_path)
    except:
        print(f"No 'final_gaze_tagged.csv' found in {folder}")
        no_gaze_csv.append(folder)
        continue

    print(f"Final gaze csv found in {folder}, combining now...")
    participant_count += 1

    gaze_csv["participant_folder"] = folder.split(os.sep)[-1]

    # this vts bool is a distinction made for our stakeholders
    # It is representative of surveys that were taken during the study,
    # which are only applicable to the participants that took them.
    if "vts" in participant_id:
        gaze_csv["vts_bool"] = True
    else:
        gaze_csv["vts_bool"] = False

    ideal_rows += gaze_csv.shape[0]
    target_csv = pd.concat([target_csv, gaze_csv], axis=0)
    del gaze_csv

try:
    target_csv.drop(columns=["Unnamed: 0"], inplace=True)

except:
    print("No Unnamed column found")
    pass

assert ideal_rows == target_csv.shape[0]

try:
    assert participant_count == len(participant_list)

except AssertionError:
    print(f"Number of participants found: {participant_count}")
    print(f"Number of folders found: {len(participant_list)}")
    print(f"Participants unable to be processed : {no_gaze_csv}")
    print(f"Participant count does not match number of folders")

    with open(
        os.path.join(output_folder_path, "Error Log - Folder Count.txt"), "w"
    ) as f:
        f.write(f"Number of participants found: {participant_count}")
        f.write(f"Number of folders found: {len(participant_list)}")
        f.write(f"Participant count does not match number of folders")
        f.write(f"Participants without gaze csvs : {no_gaze_csv}")

# change to all gaze for final implementation
target_csv.to_csv(
    os.path.join(output_folder_path, "all_gaze.csv"), index=False, compression="gzip"
)
print("all_gaze.csv created")


#-*-coding:utf8;-*-
#qpy:2
#qpy:console

print("Work in progress")
#print "This is console module"
import math
import numpy as np

def collatzStep(num, even):
    if even:
        nextNum = num/2
    else:
        nextNum = 3*num + 1
    return nextNum

startNum = np.linspace(9e5, 1e6 - 1, 1e6 - 9e5)
#print(startNum)
steps = np.zeros(len(startNum))
for i in range(0, len(startNum)):
    logCheck = 0
    num = startNum[i]
   # print(num)
    while num > 1 and not logCheck:
        even = (num % 2 == 0)
        if even:
            log = math.log(num, 2)
            logCheck = (log % 1 == 0)
        if logCheck:
            steps[i] += log
        else:
            num = collatzStep(num, even)
            steps[i] += 1
    #print(steps[i])

answer = startNum[np.argmax(steps)]
print("Starting number, under one million, producting the longest Collatz chain")
print("Answer: %d" % answer)


# 파이썬 10일차

import openpyxl

wb = openpyxl.load_workbook('./파일입출력/서울지하철.xlsx')
ws=wb.active

subway=list(map(list, ws.values))
answer=[]

while True :
  line = input("지하철 노선을 입력하세요(1~4호선) : ")
  if line in ['1호선','2호선','3호선','4호선']:
    answer.extend(subway[int(line[0])-1])
    break
  else :
    print("다시 입력하세요(ex. 3호선)")

del(answer[0])
print(answer)

already=[]
while True :
  station=input(line+'의 정차역 입력(종료=0) : ')
  if station == '0' :
    print("지하철 게임 종료!")
    break
  else :
    if (station in answer) :
      if (station not in already) :
        already.append(station)
        print(already)
        print("존재하는 정차역입니다! 통과")
      else :
        print("이미 입력하신 역입니다! 벌칙")
    else :
      print("존재하지 않는 정차역입니다! 벌칙")


class JobEntry:
    def __init__(self, lusin, sisa, nominal):
        self.lusin = lusin
        self.sisa = sisa
        self.nominal = nominal
        self.subtotal = self.count_subtotal()

    def count_subtotal(self):
        float_lusin = self.lusin + (self.sisa / 12)
        return float_lusin*self.nominal

    def __str__(self):
        return "{:5d} | {:4d} | {:>7s} | {:>10s}".format(self.lusin, self.sisa, format_currency(self.nominal), format_currency(self.subtotal))

def format_currency(amount):
    amount = str(int(amount))
    formatted = ""
    for i in range(len(amount)):
        if (i % 3 == 0):
            formatted = "," + formatted
        formatted = amount[len(amount)-i-1] + formatted
    return formatted[:-1]

def count_total(lst):
    dash_line = "------------------------------------------"
    print("No. | Lusin | Sisa |  Biaya  |  Subtotal")
    print(dash_line)
    total = 0
    i = 0
    for job in lst:
        i += 1
        print("{:3d} | {}".format(i, job))
        total += job.subtotal
        if not (i % 5): print(dash_line)
    print(dash_line + " +")
    print("                        Total: {:>10s}".format(format_currency(total)))

def delete_last(lst, num):
    if (len(lst) == 0):
        print("Job List is empty!")
        return
    if (not num):
        print("Undo zero is useless!")
        return
    for i in range(num):
        job = lst[-1]
        print("Removed {} {} {}.".format(job.lusin, job.sisa, job.nominal))
        lst.remove(job)

def payroll_calc_runner():
    print("""=====================================
** Welcome to Konveksi Payroll Calculator! **

* Type 'help' and Enter to show available commands.
* Type 'exit' or 'quit' and Enter to exit..
=====================================""")
    keep_asking = True
    job_list = list()
    worker_name = ""
    while keep_asking:
        row = input(">>> ")
        row = row.split()
        if (row[0] in ['exit', 'quit', 'e', 'q']):
            job_list = list()
            keep_asking = False
        elif (row[0] in ['undo', 'u']):
            try:
                num = int(row[1])
                delete_last(job_list, num)
            except(IndexError):
                print("Undo needs lst and num arguments!")
        elif (row[0] in ['total', 't']):
            print("Nama: {}".format(worker_name))
            count_total(job_list)
        elif (row[0] in ['reset', 'r']):
            job_list = list()
            worker_name = ""
            print("============RESET============")
        elif (row[0] in ['name', 'nama', 'n']):
            worker_name = " ".join(row[1:])
        elif (len(row) == 3):
            lusin = int(row[0])
            sisa = int(row[1])
            nominal = int(row[2])
            row_entry = JobEntry(lusin, sisa, nominal)
            job_list.append(row_entry)
        elif (len(row) == 2):
            lusin = int(row[0])
            sisa = 0
            nominal = int(row[1])
            row_entry = JobEntry(lusin, sisa, nominal)
            job_list.append(row_entry)
        else:
            print("Format masukan salah. Masukkan dengan format yang benar.")


import requests
from datetime import datetime
import smtplib
from time import sleep
my_email = "francesco.tintori93@gmail.com"
MY_LAT = 40#51.080258
MY_LNG = 167#-114.146711
resp = requests.get("http://api.open-notify.org/iss-now.json")
resp.raise_for_status()

data = resp.json()
iss_longitude = float(data["iss_position"]["longitude"])
iss_latitude = float(data["iss_position"]["latitude"])

iss_position = (iss_latitude, iss_longitude,)

params = {
            "lat": MY_LAT,
            "lng": MY_LNG,
            "formatted": 0
}
resp_sun = requests.get("https://api.sunrise-sunset.org/json", params=params)
resp_sun.raise_for_status()
sunrise = resp_sun.json()["results"]["sunrise"]
sunrise_hour = int((sunrise.split("T")[1]).split(":")[0])-7
sunset = resp_sun.json()["results"]["sunset"]
sunset_hour = int((sunset.split("T")[1]).split(":")[0])-7

time_now = datetime.now()

is_night_time = time_now.hour > sunset_hour or time_now.hour < sunrise_hour
def iss_close():
    iss_close = abs(MY_LAT - iss_latitude) < 5 and abs(MY_LNG - iss_longitude) < 5
    return iss_close

def send_email():
    with smtplib.SMTP_SSL('smtp.gmail.com',465) as server:
        server.ehlo()
        # server.starttls()
        server.ehlo()
        server.login(my_email, "hfvmawpgrjmgcvtv")
        subject = f"Look UP! ISS is in the sky!"
        body = "The ISS should be visible in the sky right now. You should look!"
        msg = f"Subject: {subject}\n\n{body}"
        server.sendmail(
            'francesco.tintori93@gmail.com',
            'francesco.tintori93@gmail.com',
            msg
        )

while True:
    if iss_close() and is_night_time:
        send_email()
        sleep(5)
    elif not is_night_time:
        sleep(3600)
    elif is_night_time and not iss_close():
        sleep(300)

print(iss_position)

Python Coding Projects/International Space Station Tracker/main.py


import unittest
from unittest import mock
from tests.recipes.recipe_lib_test import BaseTestForMakeRecipe

class TestOpensslRecipe(BaseTestForMakeRecipe, unittest.TestCase):
    """
    An unittest for recipe :mod:`~pythonforandroid.recipes.openssl`
    """

    recipe_name = "openssl"
    sh_command_calls = ["perl"]

    @mock.patch("pythonforandroid.recipes.openssl.sh.patch")
    @mock.patch("pythonforandroid.util.chdir")
    @mock.patch("pythonforandroid.build.ensure_dir")
    @mock.patch("shutil.which")
    def test_build_arch(
        self,
        mock_shutil_which,
        mock_ensure_dir,
        mock_current_directory,
        mock_sh_patch,
    ):
        # We overwrite the base test method because we need to mock a little
        # more with this recipe.
        super().test_build_arch()
        # make sure that the mocked methods are actually called
        mock_sh_patch.assert_called()

    def test_versioned_url(self):
        self.assertEqual(
            self.recipe.url.format(url_version=self.recipe.url_version),
            self.recipe.versioned_url,
        )

    def test_include_flags(self):
        inc = self.recipe.include_flags(self.arch)
        build_dir = self.recipe.get_build_dir(self.arch)
        for i in {"include/internal", "include/openssl"}:
            self.assertIn(f"-I{build_dir}/{i}", inc)

    def test_link_flags(self):
        build_dir = self.recipe.get_build_dir(self.arch)
        openssl_version = self.recipe.version
        self.assertEqual(
            f" -L{build_dir} -lcrypto{openssl_version} -lssl{openssl_version}",
            self.recipe.link_flags(self.arch),
        )

    def test_select_build_arch(self):
        expected_build_archs = {
            "armeabi": "android",
            "armeabi-v7a": "android-arm",
            "arm64-v8a": "android-arm64",
            "x86": "android-x86",
            "x86_64": "android-x86_64",
        }
        for arch in self.ctx.archs:
            self.assertEqual(
                expected_build_archs[arch.arch],
                self.recipe.select_build_arch(arch),
            )


netAmount = 0
while(1):
    transaction=input("Enter the transaction \n (W for withdraw D for Deposit and Press Ok to stop): ")
    if transaction == "OK":
        break
    transactionId = transaction[0:1]
    transactionAmount=int(transaction[2:len(transaction)])
    if transactionId == "D":
        netAmount += transactionAmount
        print(f"Rs.{transactionAmount} successfully deposited.\n Your remaining balance is {netAmount}")
    elif transactionId == "W":
        if netAmount>=transactionAmount:
            netAmount -= transactionAmount
            print(f"Rs.{transactionAmount} is successfully withdraw \n Your remaining balance is {netAmount}")
        else:
            print(f"Insufficient funds \n You have only Rs.{netAmount}")