# ██████╗░██╗░░░██╗██████╗░██╗░░░░░░█████╗░░█████╗░███████╗  ░░░░░░
# ██╔══██╗╚██╗░██╔╝██╔══██╗██║░░░░░██╔══██╗██╔══██╗██╔════╝  ░░░░░░
# ██████╔╝░╚████╔╝░██████╔╝██║░░░░░███████║██║░░╚═╝█████╗░░  █████╗
# ██╔═══╝░░░╚██╔╝░░██╔═══╝░██║░░░░░██╔══██║██║░░██╗██╔══╝░░  ╚════╝
# ██║░░░░░░░░██║░░░██║░░░░░███████╗██║░░██║╚█████╔╝███████╗  ░░░░░░
# ╚═╝░░░░░░░░╚═╝░░░╚═╝░░░░░╚══════╝╚═╝░░╚═╝░╚════╝░╚══════╝  ░░░░░░

# ██████╗░██╗░░░██╗██╗░░░░░██╗░░██╗  ██████╗░███████╗██╗░░░░░███████╗████████╗███████╗
# ██╔══██╗██║░░░██║██║░░░░░██║░██╔╝  ██╔══██╗██╔════╝██║░░░░░██╔════╝╚══██╔══╝██╔════╝
# ██████╦╝██║░░░██║██║░░░░░█████═╝░  ██║░░██║█████╗░░██║░░░░░█████╗░░░░░██║░░░█████╗░░
# ██╔══██╗██║░░░██║██║░░░░░██╔═██╗░  ██║░░██║██╔══╝░░██║░░░░░██╔══╝░░░░░██║░░░██╔══╝░░
# ██████╦╝╚██████╔╝███████╗██║░╚██╗  ██████╔╝███████╗███████╗███████╗░░░██║░░░███████╗
# ╚═════╝░░╚═════╝░╚══════╝╚═╝░░╚═╝  ╚═════╝░╚══════╝╚══════╝╚══════╝░░░╚═╝░░░╚══════╝

# 🄱🅈 🄳🄰🄽🅃🄴_🄽🄻
# Welcome to the PyPlace Bulk Delete script! This is an official
# and experimental thing for PyPlace, that allows you to delete
# a bunch of applications at once.

# 𝗖𝘂𝗿𝗿𝗲𝗻𝘁 𝘃𝗲𝗿𝘀𝗶𝗼𝗻
# Default: 0.4 (changes	every version)
# Possible options:	any	number

# This is the version of PyPlace - Bulk Delete and is
# absolutely not recommended to change,
# except for testing purposes.
Version = 0.4

# ————————————————————————————

import os
import sys
import json
import requests
from os.path import	exists

class bcolors:
	LOG = '\033[95m'
	INFO = '\033[94m'
	OKCYAN = '\033[96m'
	OKGREEN = '\033[92m'
	WARNING = '\033[93m'
	FAIL = '\033[91m'
	END = '\033[0m'
	BOLD = '\033[1m'
	UNDERLINE = '\033[4m'

if exists("setup.json") == False:
	print(f"{bcolors.FAIL}Error:{bcolors.END} It appears you have not set up PyPlace yet! Please run PyPlace and set it up.")
	sys.exit(0)

def error(error_msg):
	print(f"{bcolors.FAIL}Error:{bcolors.END} {error_msg}")

def info(info_msg):
	print(f"{bcolors.INFO}{info_msg}{bcolors.END}")

if exists("setup.json") == True:
    with open('setup.json') as SetupFile:
        _data = json.load(SetupFile)
        PyCommand = _data["PythonCommand"]

with open('applications.json') as AppsFile:
	AppDict = json.load(AppsFile)

def update():
	response = requests.get("https://cdn.dantenl.tk/PyPlace/bd-version.json")
	if response.status_code != 200:
		print(f"{bcolors.FAIL}Error:{bcolors.END} Could not check for updates! Response code: {response.status_code}")
		return

	RequestText = response.text
	data = json.loads(RequestText)

	if data["version"] < Version:
		print(f"{bcolors.WARNING}WARNING:{bcolors.END} Your current version seems to be newer than the latest version that is released!")
	elif data["version"] > Version:
		print("————————")
		print(f"{bcolors.BOLD}UPDATE AVAILABLE!{bcolors.END}")
		print(
			f"Your current version ({Version}) is no longer the latest version! The latest one is {data['version']}")
		print(f"""Here are the release notes:
{data["release_notes"]}
		""")
		NotAnswered = True
		while NotAnswered == True:
			Answer = input("Would you like to update right now? (y/n) ")
			Answer = Answer.lower()
			if Answer == "y":
				NotAnswered = False
				print(
					f"{bcolors.INFO}Downloading latest version of PyPlace...{bcolors.END}")
				r = requests.get(
					"https://cdn.dantenl.tk/PyPlace/Experiments/PyPlace-BD-Latest.py", allow_redirects=True)
				if not r.ok:
					print(f"{bcolors.FAIL}Error:{bcolors.END} Could not get the PyPlace file! Status code: {r.status_code}")
					return
				open('{FileName}', 'wb').write(r.content)
				print(
					f"{bcolors.OKGREEN}The latest version of PyPlace is now ready in {bcolors.BOLD}{FileName}!{bcolors.END}")
				NotAnswered2 = True
				while NotAnswered2 == True:
					Answer2 = input("Would you like to run it? (y/n) ")
					Answer2 = Answer2.lower()
					if Answer2 == "y":
						print(
							f"{bcolors.INFO}Attempting to run {FileName}...{bcolors.END}")
						os.system(f"{PyCommand} {FileName}")
						NotAnswered2 = False
						sys.exit(1)
					elif Answer2 == "n":
						print(
							f"Continuing with current version. {bcolors.BOLD}NOTE:{bcolors.END} Next time you start {FileName}, it will be on the latest version!")
						NotAnswered2 = False
						return
					else:
						print(
							f"{bcolors.FAIL}Error:{bcolors.END} I'm not sure what you mean with \"{Answer2}\".")

def bulk_delete(nums):
	if exists("applications.json") == False:
		error("You do not have any applications installed.")
		return "Error"
	items = len(nums)
	info(f"Deleting {items} apps...")
	RightApps = []
	for number in nums:
		if number == str(ErrorNumber):
			print(f"{bcolors.FAIL}Error:{bcolors.END} Please delete PyPlace - Bulk Delete via the PyPlace settings instead.")
			items -= 1
		else:
			current_num_app_dict = 0
			for app in AppDict["apps"]:
				current_num_app_dict += 1
				if str(current_num_app_dict) == str(number):
					RightApps.append(app)

	for RightApp in RightApps:
		if exists(AppDict["apps"][RightApp]["file_name"]):
			os.remove(AppDict["apps"][RightApp]["file_name"])
		del AppDict["apps"][RightApp]
		with open('applications.json', 'w') as data_file:
				data = json.dump(AppDict, data_file,
									indent=4,
									separators=(',', ': '))
	if items == 0:
		print(f"{bcolors.INFO}No apps to be deleted.{bcolors.END}")
	else:
		print(f"{bcolors.OKGREEN}Deleted {items} app(s)!{bcolors.END}")

print()
print("""————————————————————————————
Welcome to the PyPlace Bulk Delete script! This is an official
and experimental thing for PyPlace, that allows you to delete
a bunch of applications at once.
""")

FileName = f"{os.path.splitext(os.path.basename(__file__))[0]}.py"

update()

print(f"{bcolors.WARNING}■{bcolors.END}: Experimental application")
print(f"{bcolors.OKCYAN}■{bcolors.END}: Application downloaded from the PyPlace store")
print(f"{bcolors.FAIL}■{bcolors.END}: The PyPlace - Bulk Delete app. This can not be deleted here.")
print()

num_app = 0
for item in AppDict["apps"]:
	num_app += 1
	if AppDict["apps"][item]["file_name"] == FileName:
		print(f"{bcolors.FAIL}[{num_app}] {AppDict['apps'][item]['name']}{bcolors.END}")
		ErrorNumber = num_app
	elif "StoreApp" in AppDict["apps"][item]:
		if AppDict["apps"][item]["StoreApp"] == "true":
			print(f"{bcolors.OKCYAN}[{num_app}] {AppDict['apps'][item]['name']}{bcolors.END}")
	elif "experiment" in AppDict["apps"][item]:
		if AppDict["apps"][item]["experiment"] == "true":
			print(f"{bcolors.WARNING}[{num_app}] {AppDict['apps'][item]['name']}{bcolors.END}")

if num_app == 0:
	error("You do not have any applications installed!")
	sys.exit(0)

print(f"[{bcolors.FAIL}c{bcolors.END}] Cancel")

input = input("What apps do you want to delete? (seperated by a comma, so for applications 1, 2 and 3 you would enter 1,2,3) ")
if input.lower() == "c":
	sys.exit(0)
input = input.split(",")

bulk_delete(input)


#import blockchain
from transaction import *
import json

import hashlib

import Crypto
import Crypto.Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

class Block:
	def __init__(self, index, previousHash, timestamp, nonce, listOfTransactions):
		##set
		self.index = index
		self.previousHash = previousHash
		self.timestamp = timestamp
		self.hash = 42 					#dummy initializer
		self.nonce = nonce
		self.listOfTransactions = listOfTransactions

	def __eq__(self,other):
		return sorted(self.listOfTransactions) == sorted(other.listOfTransactions)

	def to_dict(self):
		newlist = []
		for trans in self.listOfTransactions:
			newlist.append(trans.to_dict())
		#newlist = json.dumps(newlist)
		return OrderedDict({'block_index': self.index,
							'previousHash': self.previousHash,
							'timestamp': self.timestamp,
							'hash': self.hash,
							'nonce': self.nonce,
							'listOfTransactions': newlist,
							})

	def myHash(self):
		#CHECK AGAIN IF THAT"S WHAT WE WANT
		#calculate self.hash
		guess = (str(self.previousHash)+str(self.nonce)+str(self.timestamp)).encode()
		return hashlib.sha256(guess).hexdigest()

	# def add_transaction(self, transaction transaction, blockchain blockchain):
	# 	#add a transaction to the block

	# 	self.listOfTransactions.append(transaction)


import json
from datetime import datetime

from pandas import DataFrame

import R50_general.advanced_helper_funcs as ahf
import R50_general.dfm_to_table_common as df2db
import R50_general.general_constants
import R50_general.general_helper_funcs as gcf
from R50_general.general_helper_funcs import logprint, parse_chinese_uom, floatN, intN, pertentage_conversion

global_module_name = gcf.get_cur_file_name_by_module_name(__name__)

def fetch2DB(stockid:str = ''):
    # 1.init step
    # create DD tables for data store and add chars for stock structure.
    # 1.1 setup DB structure for core concept table
    dict_misc_pars_sh_num = gcf.set_dict_misc_pars('EASTMONEY','D','N',global_module_name,'SHAREHOLDER10')   #股东人数
    dict_misc_pars_tensh_tradable = gcf.set_dict_misc_pars('EASTMONEY','D','Y',global_module_name,'SHAREHOLDER20') #十大流通股东
    dict_misc_pars_tensh = gcf.set_dict_misc_pars('EASTMONEY','D','Y',global_module_name,'SHAREHOLDER30') #十大股东
    dict_misc_pars_tensh_changes = gcf.set_dict_misc_pars('EASTMONEY','D','Y',global_module_name,'SHAREHOLDER40') #十大股东持股变动
    dict_misc_pars_funds = gcf.set_dict_misc_pars('EASTMONEY','D','Y',global_module_name,'SHAREHOLDER50') #基金持股
    dict_misc_pars_nontradable_rls =  gcf.set_dict_misc_pars('EASTMONEY','D','N',global_module_name,'SHAREHOLDER60')    #限售解禁

    # check whether db table is created.
    # 股东人数
    dfm_db_chars_sh_sum = df2db.get_chars('EASTMONEY', ['SHAREHOLDER10'])
    table_name_sh_num = R50_general.general_constants.dbtables['stock_shareholder_number_eastmony']
    df2db.create_table_by_template(table_name_sh_num,table_type='stock_date')
    dict_cols_sh_num = {'股东人数': 'int',
                         '较上期变化比例': 'decimal(10,4)',
                         '筹码集中度': 'nvarchar(50)',
                         '股价':'decimal(10,2)',
                         '前十大股东持股合计比例':'decimal(10,4)',
                         '前十大流通股东持股合计比例':'decimal(10,4)',
                         }
    df2db.add_new_chars_and_cols(dict_cols_sh_num, list(dfm_db_chars_sh_sum['Char_ID']), table_name_sh_num, dict_misc_pars_sh_num)

    # 十大流通股东
    dfm_db_chars_tensh_tradable = df2db.get_chars('EASTMONEY', ['SHAREHOLDER20'])
    table_name_tensh_tradable = R50_general.general_constants.dbtables['stock_top_ten_tradable_shareholder_eastmoney']
    df2db.create_table_by_template(table_name_tensh_tradable, table_type='stock_date_multi_value')
    dict_cols_tensh_tradable = { '名次': 'int',
                                 '股东名称':'nvarchar(500)',
                                 '股东性质':'nvarchar(50)',
                                 '股份类型':'nvarchar(50)',
                                 '持股数':'bigint',
                                 '占总流通股本持股比例':'decimal(10,4)',
                                 '增减股数':'nvarchar(50)',  # 值可能为'不变','新进'
                                 '变动比例':'decimal(10,4)',
                                 }
    df2db.add_new_chars_and_cols(dict_cols_tensh_tradable, list(dfm_db_chars_tensh_tradable['Char_ID']), table_name_tensh_tradable, dict_misc_pars_tensh_tradable)

    #十大股东
    dfm_db_chars_tensh = df2db.get_chars('EASTMONEY', ['SHAREHOLDER30'])
    table_name_tensh = R50_general.general_constants.dbtables['stock_top_ten_shareholder_eastmoney']
    df2db.create_table_by_template(table_name_tensh, table_type='stock_date_multi_value')
    dict_cols_tensh = { '名次': 'int',
                     '股东名称':'nvarchar(500)',
                     '股份类型':'nvarchar(50)',
                     '持股数':'bigint',
                     '占总流通股本持股比例':'decimal(10,4)',
                     '增减股数':'nvarchar(50)',  # 值可能为'不变','新进'
                     '变动比例':'decimal(10,4)',
                     }
    df2db.add_new_chars_and_cols(dict_cols_tensh, list(dfm_db_chars_tensh['Char_ID']), table_name_tensh, dict_misc_pars_tensh)

    # 十大股东持股变动
    dfm_db_chars_tensh_changes = df2db.get_chars('EASTMONEY', ['SHAREHOLDER40'])
    table_name_tensh_changes = R50_general.general_constants.dbtables['stock_top_ten_shareholder_shares_changes_eastmoney']
    df2db.create_table_by_template(table_name_tensh_changes, table_type='stock_date_multi_value')
    dict_cols_tensh_changes = {'变动时间':'datetime',
                               '名次': 'int',
                                '股东名称':'nvarchar(500)',
                                '股份类型':'nvarchar(50)',
                                '持股数':'bigint',
                                '占总流通股本持股比例':'decimal(10,4)',
                                '增减股数':'nvarchar(50)',  # 值可能为'不变','新进'
                                '增减股占原股东持股比例':'decimal(10,4)',
                                '变动原因':'nvarchar(50)',
                               }

    df2db.add_new_chars_and_cols(dict_cols_tensh_changes, list(dfm_db_chars_tensh_changes['Char_ID']),
                                 table_name_tensh_changes, dict_misc_pars_tensh_changes)

    # 基金持股
    dfm_db_chars_funds = df2db.get_chars('EASTMONEY', ['SHAREHOLDER50'])
    table_name_funds = R50_general.general_constants.dbtables['stock_fund_shareholder_eastmoney']
    df2db.create_table_by_template(table_name_funds, table_type='stock_date_multi_value')
    dict_cols_funds = {'名次': 'int',
                        '基金代码':'nvarchar(50)',
                        '基金名称':'nvarchar(500)',
                        '持股数':'bigint',
                        '持仓市值':'decimal(18,2)',
                        '占总股本比':'decimal(10,4)',
                        '占流通比':'decimal(10,4)',
                        '占净值比':'decimal(10,4)',
                       }

    df2db.add_new_chars_and_cols(dict_cols_funds, list(dfm_db_chars_funds['Char_ID']),
                                 table_name_funds, dict_misc_pars_funds)

    # 限售解禁
    dfm_db_chars_nontradable_rls = df2db.get_chars('EASTMONEY', ['SHAREHOLDER60'])
    table_name_nontradable_rls = R50_general.general_constants.dbtables['stock_nontradable_shares_release_eastmoney']
    df2db.create_table_by_template(table_name_nontradable_rls, table_type='stock_date')
    dict_cols_nontradable_rls = {'解禁股数': 'bigint',
                                 '股票类型':'nvarchar(50)',
                                 '解禁股占总股本比例':'decimal(10,4)',
                                 '解禁股占流通股本比例':'decimal(10,4)',
                                 }

    df2db.add_new_chars_and_cols(dict_cols_nontradable_rls, list(dfm_db_chars_nontradable_rls['Char_ID']),
                                 table_name_nontradable_rls, dict_misc_pars_nontradable_rls)

    # step2.1: get current stock list
    dfm_stocks = df2db.get_cn_stocklist(stockid)

    for index,row in dfm_stocks.iterrows():
        logprint('Processing stock %s' % row['Stock_ID'])
        # step1:parse webpage and get raw data
        url_stock_sh = R50_general.general_constants.weblinks['stock_shareholder_eastmoney'] % row['MktStk_ID']
        json_stock_sh = gcf.get_webpage(url_stock_sh,flg_return_json=True)

        dfm_stk_sh_sum = json_parse_stock_sh10(json_stock_sh)

        if len(dfm_stk_sh_sum) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_sh_sum, columns=dict_cols_sh_num)
            # print(dfm_stk_sh_sum.dtypes)
            df2db.load_dfm_to_db_single_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                            row['Stock_ID'],
                                                            dfm_stk_sh_sum,
                                                            table_name_sh_num,dict_misc_pars_sh_num,partial_ind=True)
        else:
            logprint("Stock %s doesn't have shareholder number info" % (row['MktStk_ID']))

        dfm_stk_tensh_tradable = json_parse_stock_sh20(json_stock_sh)
        if len(dfm_stk_tensh_tradable) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_tensh_tradable, columns=dict_cols_tensh_tradable)
            df2db.load_dfm_to_db_multi_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                            row['Stock_ID'],
                                                            dfm_stk_tensh_tradable,
                                                            table_name_tensh_tradable,dict_misc_pars_tensh_tradable,partial_ind=True)
        else:
            logprint("Stock %s doesn't have ten tradable shareholders info" % (row['MktStk_ID']))

        dfm_stk_tensh = json_parse_stock_sh30(json_stock_sh)
        if len(dfm_stk_tensh) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_tensh, columns=dict_cols_tensh)
            df2db.load_dfm_to_db_multi_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                               row['Stock_ID'],
                                                               dfm_stk_tensh,
                                                               table_name_tensh,
                                                               dict_misc_pars_tensh, partial_ind=True)
        else:
            logprint("Stock %s doesn't have ten shareholders info" % (row['MktStk_ID']))

        dfm_stk_tensh_changes = json_parse_stock_sh40(json_stock_sh)
        if len(dfm_stk_tensh_changes) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_tensh_changes, columns=dict_cols_tensh_changes)
            df2db.load_dfm_to_db_multi_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                               row['Stock_ID'],
                                                               dfm_stk_tensh_changes,
                                                               table_name_tensh_changes,
                                                               dict_misc_pars_tensh_changes, partial_ind=True)
        else:
            logprint("Stock %s doesn't have ten shareholders share changes info" % (row['MktStk_ID']))

        dfm_stk_funds = json_parse_stock_sh50(json_stock_sh)
        if len(dfm_stk_funds) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_funds, columns=dict_cols_funds)
            df2db.load_dfm_to_db_multi_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                               row['Stock_ID'],
                                                               dfm_stk_funds,
                                                               table_name_funds,
                                                               dict_misc_pars_funds, partial_ind=True)
        else:
            logprint("Stock %s doesn't have funds shareholders info" % (row['MktStk_ID']))

        dfm_stk_nontradable_rls = json_parse_stock_sh60(json_stock_sh)
        if len(dfm_stk_nontradable_rls) > 0:
            gcf.dfm_col_type_conversion(dfm_stk_nontradable_rls, columns=dict_cols_nontradable_rls)
            df2db.load_dfm_to_db_single_value_by_mkt_stk_w_hist(row['Market_ID'],
                                                               row['Stock_ID'],
                                                               dfm_stk_nontradable_rls,
                                                               table_name_nontradable_rls,
                                                               dict_misc_pars_nontradable_rls, partial_ind=False)
        else:
            logprint("Stock %s doesn't have funds shareholders info" % (row['MktStk_ID']))

        # TODO: error handling

def json_parse_stock_sh10(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    ls_sh10 = []    #股东人数
    ls_sh10_index = []

    if dt_json_stksh:
        ls_gdrs = dt_json_stksh['gdrs']
        if ls_gdrs == None:
            return DataFrame()
        for item in ls_gdrs:
            item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
            dt_sh10 = {}
            dt_sh10['股东人数'] = parse_chinese_uom(item['gdrs'])
            dt_sh10['较上期变化比例'] = floatN(item['gdrs_jsqbh'], '/', 100)
            dt_sh10['筹码集中度'] = item['cmjzd']
            dt_sh10['股价'] = floatN(item['gj'])
            dt_sh10['前十大股东持股合计比例'] = floatN(item['qsdgdcghj'], '/', 100)
            dt_sh10['前十大流通股东持股合计比例'] = floatN(item['qsdltgdcghj'], '/', 100)
            ls_sh10.append(dt_sh10)
            ls_sh10_index.append(datetime.strptime(item['rq'],'%Y-%m-%d'))
            """
            "rq": "2017-09-30",          Trans_Datetime
			"gdrs": "3.49万",            '股东人数'
			"gdrs_jsqbh": "-10.28",      '较上期变化比例'
			"rjltg": "4.5万",
			"rjltg_jsqbh": "11.46",
			"cmjzd": "非常集中",          '筹码集中度'
			"gj": "16.08",                '股价'
			"rjcgje": "72万",
			"qsdgdcghj": "65.09",         '前十大股东持股合计比例'
			"qsdltgdcghj": "42.95"        '前十大流通股东持股合计比例'
            """
        return DataFrame(ls_sh10,index = ls_sh10_index)
    else:
        return DataFrame()

def json_parse_stock_sh20(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    # print(dt_soup_stkcpt)
    ls_sh10 = []    #十大流通股东
    ls_sh10_index = []
    if dt_json_stksh:
        ls_sdltgd_l1 = dt_json_stksh['sdltgd']
        for item_l1 in ls_sdltgd_l1:
            ls_sdltgd_l2 = item_l1['sdltgd']
            for item in ls_sdltgd_l2:
                item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
                dt_sh10 = {}
                dt_sh10['名次'] = intN(item['mc'])
                dt_sh10['股东名称'] = item['gdmc']
                dt_sh10['股东性质'] = item['gdxz']
                dt_sh10['股份类型'] = item['gflx']
                dt_sh10['持股数'] = intN(item['cgs'])
                dt_sh10['占总流通股本持股比例'] = pertentage_conversion(item['zltgbcgbl'])
                dt_sh10['增减股数'] = item['zj']
                dt_sh10['变动比例'] = pertentage_conversion(item['bdbl'])
                ls_sh10.append(dt_sh10)
                ls_sh10_index.append(datetime.strptime(item['rq'],'%Y-%m-%d'))
                """
                        "rq": "2017-09-30",
                        "mc": "1",                          '名次': 'int',
                        "gdmc": "三花控股集团有限公司",       '股东名称':'nvarchar(50)',
                        "gdxz": "其它",                       '股东性质':'nvarchar(50)',
                        "gflx": "A股",                       '股份类型':'nvarchar(50)',
                        "cgs": "788,374,733",                   '持股数':'int',
                        "zltgbcgbl": "50.41%",                '占总流通股本持股比例':'decimal(10,6)',
                        "zj": "不变",                         '增减股数':'nvarchar(50)',
                        "bdbl": "--",                        '变动比例':'decimal(10,6)',
                """
        return DataFrame(ls_sh10,index = ls_sh10_index)
    else:
        return DataFrame()

def json_parse_stock_sh30(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    # print(dt_soup_stkcpt)
    ls_sh10 = []    #十大股东
    ls_sh10_index = []
    if dt_json_stksh:
        ls_sdgd_l1 = dt_json_stksh['sdgd']
        for item_l1 in ls_sdgd_l1:
            ls_sdgd_l2 = item_l1['sdgd']
            for item in ls_sdgd_l2:
                item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
                dt_sh10 = {}
                dt_sh10['名次'] = intN(item['mc'])
                dt_sh10['股东名称'] = item['gdmc']
                dt_sh10['股份类型'] = item['gflx']
                dt_sh10['持股数'] = intN(item['cgs'])
                dt_sh10['占总流通股本持股比例'] = pertentage_conversion(item['zltgbcgbl'])
                dt_sh10['增减股数'] = item['zj']
                dt_sh10['变动比例'] = pertentage_conversion(item['bdbl'])
                ls_sh10.append(dt_sh10)
                ls_sh10_index.append(datetime.strptime(item['rq'],'%Y-%m-%d'))
                """
                        "rq": "2017-09-30",
                        "mc": "1",                          '名次': 'int',
                        "gdmc": "三花控股集团有限公司",       '股东名称':'nvarchar(50)',
                        "gflx": "A股",                       '股份类型':'nvarchar(50)',
                        "cgs": "788,374,733",                   '持股数':'int',
                        "zltgbcgbl": "50.41%",                '占总流通股本持股比例':'decimal(10,6)',
                        "zj": "不变",                         '增减股数':'nvarchar(50)',
                        "bdbl": "--",                        '变动比例':'decimal(10,6)',
                """
        return DataFrame(ls_sh10,index = ls_sh10_index)
    else:
        return DataFrame()

def json_parse_stock_sh40(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    ls_sh10 = []    #持股变化
    ls_sh10_index = []

    if dt_json_stksh:
        ls_sdgdcgbd = dt_json_stksh['sdgdcgbd']
        if ls_sdgdcgbd == None:
            return DataFrame()
        for item in ls_sdgdcgbd:
            item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
            dt_sh10 = {}
            dt_sh10['变动时间'] = item['bdsj']
            dt_sh10['名次'] = intN(item['mc'])
            dt_sh10['股东名称'] = item['gdmc']
            dt_sh10['股份类型'] = item['gflx']
            dt_sh10['持股数'] = intN(item['cgs'])
            dt_sh10['占总流通股本持股比例'] = pertentage_conversion(item['zzgbcgbl'])
            dt_sh10['增减股数'] = item['cj']
            dt_sh10['增减股占原股东持股比例'] = pertentage_conversion(item['cjgzygdcgbl'])
            dt_sh10['变动原因'] = item['bdyy']
            ls_sh10.append(dt_sh10)
            ls_sh10_index.append(datetime.strptime(item['bdsj'],'%Y-%m-%d'))
            """
			"bdsj": "2017-09-19",               '变动时间': 'datetime',
			"mc": "1",                          '名次': 'int',
			"gdmc": "三花控股集团有限公司",       '股东名称': 'nvarchar(50)',
			"gflx": "流通A股",                     '股份类型': 'nvarchar(50)',
			"cgs": "788,374,733.00",                '持股数': 'bigint',
			"zzgbcgbl": "37.18%",               '占总流通股本持股比例': 'decimal(10,4)',
			"cj": "--",                         '增减股数': 'nvarchar(50)',  # 值可能为'不变','新进'
			"cjgzygdcgbl": "--",                '增减股占原股东持股比例': 'decimal(10,4)',
			"bdyy": "增发上市"                  '变动原因': 'nvarchar(50)',
            """

        return DataFrame(ls_sh10,index = ls_sh10_index)
    else:
        return DataFrame()

def json_parse_stock_sh50(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    ls_sh10 = []    #基金股东
    ls_sh10_index = []
    if dt_json_stksh:
        ls_jjcg_l1 = dt_json_stksh['jjcg']
        if ls_jjcg_l1 == None:
            return DataFrame()
        for item_l1 in ls_jjcg_l1:
            ls_jjcg_l2 = item_l1['jjcg']
            for item in ls_jjcg_l2:
                item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
                dt_sh10 = {}
                dt_sh10['名次'] = intN(item['id'])
                dt_sh10['基金代码'] = item['jjdm']
                dt_sh10['基金名称'] = item['jjmc']
                dt_sh10['持股数'] = intN(item['cgs'])
                dt_sh10['持仓市值'] = floatN(item['cgsz'])
                dt_sh10['占总股本比'] = pertentage_conversion(item['zzgbb'])
                dt_sh10['占流通比'] = pertentage_conversion(item['zltb'])
                dt_sh10['占净值比'] = pertentage_conversion(item['zjzb'])
                ls_sh10.append(dt_sh10)
                ls_sh10_index.append(datetime.strptime(item_l1['rq'],'%Y-%m-%d'))
                """
			"rq": "2017-09-30",
			"jjcg": [
				{
					"id": "",                       '名次': 'int',
					"jjdm": "020001",               '基金代码': 'nvarchar(50)',
					"jjmc": "国泰金鹰增长混合",         '基金名称': 'nvarchar(50)',
					"cgs": "12,488,801.00",         '持股数': 'bigint',
					"cgsz": "200,819,920.08",       '持仓市值': 'decimal(18,2)',
					"zzgbb": "0.59%",               '占总股本比': 'decimal(10,4)',
					"zltb": "0.78%",                '占流通比': 'decimal(10,4)',
					"zjzb": "--",                   '占净值比': 'decimal(10,4)',
					"order": "12488801"
                """

        return DataFrame(ls_sh10,index = ls_sh10_index)
    else:
        return DataFrame()

def json_parse_stock_sh60(json_stock_sh:str):
    dt_json_stksh= json.loads(json_stock_sh)
    ls_sh10 = []    #限售解禁
    ls_sh10_index = []

    if dt_json_stksh:
        ls_xsjj = dt_json_stksh['xsjj']
        if not ls_xsjj:
            return DataFrame()
        for item in ls_xsjj:
            item = {x:y.strip() if y != '--' and y else None for (x,y) in item.items()}
            dt_sh10 = {}
            dt_sh10['解禁股数'] = parse_chinese_uom(item['jjsl'])
            dt_sh10['解禁股占总股本比例'] = pertentage_conversion(item['jjgzzgbbl'])
            dt_sh10['解禁股占流通股本比例'] = pertentage_conversion(item['jjgzltgbbl'])
            dt_sh10['股票类型'] = item['gplx']

            ls_sh10.append(dt_sh10)
            ls_sh10_index.append(datetime.strptime(item['jjsj'],'%Y-%m-%d'))
            """
			"jjsj": "2018-07-23",
			"jjsl": "2.09亿",                    '解禁股数': 'bigint',
			"jjgzzgbbl": "9.85%",                '解禁股占总股本比例': 'decimal(10,4)',
			"jjgzltgbbl": "13.35%",             '解禁股占流通股本比例': 'decimal(10,4)',
			"gplx": "定向增发机构配售股份"        '股票类型': 'nvarchar(50)',
            """

        # if same transaction datetime has multiple lines, need to combine them into one line.
        ls_sh10_index_new = []
        ls_sh10_new =[]
        for i in range(len(ls_sh10)):
            if ls_sh10_index[i] not in ls_sh10_index_new:
                ls_sh10_new.append(ls_sh10[i])
                ls_sh10_index_new.append(ls_sh10_index[i])
            else:
                # find the index of the duplicated entry
                j = ls_sh10_index_new.index(ls_sh10_index[i])
                ls_sh10_new[j]['解禁股数'] += ls_sh10[i]['解禁股数']
                ls_sh10_new[j]['解禁股占总股本比例'] += ls_sh10[i]['解禁股占总股本比例']
                ls_sh10_new[j]['解禁股占流通股本比例'] += ls_sh10[i]['解禁股占流通股本比例']
                ls_sh10_new[j]['股票类型'] += '|'+ls_sh10[i]['股票类型']

        return DataFrame(ls_sh10_new,index = ls_sh10_index_new)
    else:
        return DataFrame()

def auto_reprocess():
    ahf.auto_reprocess_dueto_ipblock(identifier=global_module_name, func_to_call=fetch2DB, wait_seconds=60)

if __name__ == '__main__':
    fetch2DB('002195')
    # auto_reprocess()


import cv2
import pytesseract

# 저장한 이미지를 불러와서
image = cv2.imread("pytesseract1.png")

# Display the image
cv2.imshow("Image", image)

# Wait for the user to press a key
cv2.waitKey(0)

# 글씨가 있는 좌표만 짤라서 다시 target.png로 저장함
#Image = image[0:0, 20:500]
# image_tmp = cv2.imread("pytesseract1.png")
# cv2.imwrite("target.png", image_tmp)
#
# # Display the image
# cv2.imshow("Image2", image_tmp)

# 저장한 이미지를 다시 불러옴
image2 = cv2.imread("sample/target1.png")
cv2.imshow("Image2", image2)
# Wait for the user to press a key
cv2.waitKey(0)

pytesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# 해당 이미지에 있는 글씨(문자)를 pytersseract를 이용하여 추출함
pytesseract.pytesseract.tesseract_cmd = pytesseract_cmd
text = pytesseract.image_to_string(image2)

print("pytersseract -> ", text)

# ---------------------------------------------
# https://github.com/UB-Mannheim/tesseract/wiki
# * The latest installer can be downloaded here:
# https://github.com/tesseract-ocr/tessdoc
# tesseract-ocr-w64-setup-5.3.1.20230401.exe (64 bit)
#
# ---------------------------------------------
# * https://github.com/UB-Mannheim/tesseract/wiki/Install-additional-language-and-script-models
#
# Choose the additional language and script models from e.g. one of the places linked from https://github.com/tesseract-ocr/tesseract/wiki/Data-Files .
# Download the traineddata file to the tessdata folder of tesseract on your PC, e.g. C:\Program Files\Tesseract-OCR\tessdata. It is also possible to create new subfolders within that folder to distinguish for example the best and fast models.
# tesseract --list-langs


from typing import Sequence, Optional, Tuple, Union
from warnings import warn

import numpy as np
import cv2
from torch.utils.data import Dataset

from shar._utils.argparser import WithDefaultsWrapper, ParserType

class SkeletonDataset(Dataset):
    """
    Torch dataset class that can be passed into a dataloader.

    Expects a Sequence-type interface (providing __len__ and __getitem__) to
    the data, which returns the data as (keypoints, action_class) tuples, with
    the keypoints in a (persons,frames,landmarks,dimensios) format. Optionally
    can also take a str to a numpy file containing the data in the same format,
    i.e. an array of shape (batch, [keypoints,label],...) where [batch,0]
    contains the keypoint array and [batch,1] the action id.
    Returns samples as tuples (keypoints, action_class) with the keypoints of
    shape either
    (persons, dimensions, frames, landmarks) or (dimensions, frames, landmarks)
    with the latter only occuring when both num_persons == 1 and
    keep_person_dim == False.
    The person dimension is automatically equalised to the selected number by
    truncation/padding with zeros as appropriate.
    Can optionally re-scale the time dimension to a fixed length, using either
    linear interpolation, looping of the sequence or padding with zeros or the
    last frame. Warning: Only interpolation will currently also deal with
    sequences shorter than the target length.
    """
    @staticmethod
    def add_argparse_args(parser: ParserType,
                          default_adjust_len: str = "interpolate",
                          default_target_len: Optional[int] = None,
                          default_num_persons: int = 2) -> ParserType:
        """
        Add skeleton dataset options to argparser.

        Adds command line options for adjusting the length and the person
        dimension of individual sequences.

        Parameters
        ----------
        default_adjust_len : str, optional (default is 'interpolate')
            Sets the default value for the adjust_len parameter.
        default_target_len : int, optional (default is None)
            Sets the default value for the target_len parameter.
        default_num_persons : int, optional (default is 2)
            Sets the default value for the num_persons parameter.
        """
        if isinstance(parser, WithDefaultsWrapper):
            local_parser = parser
        else:
            local_parser = WithDefaultsWrapper(parser)
        local_parser.add_argument(
            '--adjust_len',
            type=str,
            choices=["interpolate", "loop", "pad_zero", "pad_last"],
            default=default_adjust_len,
            help="Adjust the length of individual sequences to a common length"
            " by interpolation, looping the sequence or padding with either "
            "zeros or the last frame.")
        local_parser.add_argument(
            '-l',
            '--target_len',
            type=int,
            default=default_target_len,
            help="Number of frames to scale action sequences to")
        local_parser.add_argument(
            '--num_persons',
            type=int,
            default=default_num_persons,
            help="Number of people to return (extra persons are discarded, "
            "missing persons zero padded)")
        local_parser.add_argument(
            '--keep_person_dim',
            action="store_true",
            help="Only relevevant if num_persons == 1. In that case if set "
            "the keypoint data is returned as a 4D array with a person-"
            "dimension of size 1. If not set the keypoint data is returned as "
            "a 3D array without a person dimension.")

        return parser

    def __init__(self,
                 data: Union[Sequence, str],
                 adjust_len: Optional[str] = None,
                 target_len: Optional[int] = None,
                 num_persons: int = 2,
                 keep_person_dim: bool = False,
                 **kwargs) -> None:
        """
        Parameters
        ----------
        data : Sequence or str
            A Sequence type object (providing __len__ and __getitem__)
            providing access to the data. Or alternatively a filename of a
            numpy file containing the data in appropriate shape (see class doc
            for a description)
        adjust_len : str, optional (default is None)
            One of ('interpolate', 'loop', 'pad_zero', 'pad_last')
            Optionally adjust the length of each sequence to a fixed number of
            frames by either linear interpoaltion, looping the sequence,
            padding at the end with zeros or padding at the end with the last
            frame. If set target_len must be specified.
        target_len : int, optional (default is None)
            Length to adjust every sample to. Only used if adjust_len is not
            None. Must be specified if adjust_len is not None.
        num_persons : int, optional (default is 2)
            The returned keypoint array is for exactly this number of persons.
            Extra entries in the data are discarded, if fewer skeletons exist
            zeros are aded as padding.
        keep_person_dim : bool, optional (default is False)
            Only relevevant if num_persons == 1. In that case if True the
            keypoint data is returned as a 4D array with a person-dimension of
            size 1. If False the keypoint data is returned as a 3D array
            without a person dimension.
        """
        if isinstance(data, str):
            self._data = np.load(data, allow_pickle=True)
        else:
            self._data = data

        if adjust_len is not None and target_len is None:
            raise ValueError("Target length must be specified when selecting "
                             "to adjust length of samples")
        self._adjust_len = adjust_len
        self._target_len = target_len
        self._num_persons = num_persons
        self._keep_person_dim = keep_person_dim

    def __len__(self) -> int:
        """
        Returns the number of samples in the dataset.
        """
        return len(self._data)

    def __getitem__(self, index: int) -> Tuple[np.ndarray, int]:
        """
        Get keypoints and action label for given sequence.

        Adjusts sequence length and person dimension as defined by constructor
        arguments.

        Parameters
        ----------
        index : int
            Index of the dataset sample

        Returns
        -------
        keypoints, action tuple
            Keypoints is numpy array of shape
               (person, coordinates, frame, landmark) or
               (coordinates, frame, landmark)
            action is integer id
        """
        keypoints, action = self._data[index]
        if len(keypoints.shape) == 3:
            # if data has no person dimension temporarily add one
            keypoints = np.expand_dims(keypoints, 0)
        # keypoints = (person, frame, landmark, coordinates)

        # optionally adjust length
        if self._adjust_len is not None:
            keypoints = self._adjust_seq_len(keypoints)

        # reorder for PyTorch channels first convention
        #    -> new order: (person, coordinates, frame, landmark)
        keypoints = keypoints.transpose((0, 3, 1, 2))

        # adjust person dimension if need be
        keypoints = self._adjust_person_dimension(keypoints)

        return np.ascontiguousarray(keypoints, dtype=np.float32), action

    def _adjust_person_dimension(self, data):
        if not self._keep_person_dim and self._num_persons == 1:
            data = data[0]
        elif data.shape[0] < self._num_persons:
            data = np.concatenate(
                (data,
                 np.zeros(
                     (self._num_persons - data.shape[0], ) + data.shape[1:],
                     dtype=data.dtype)),
                axis=0)
        elif data.shape[0] > self._num_persons:
            data = data[:self._num_persons]
        return data

    def _adjust_seq_len(self, data):
        if self._adjust_len == "interpolate":
            # Linearly interpolate the frame dimension
            shape = (data.shape[2], self._target_len)
            rescaled = []
            for i in range(data.shape[0]):
                rescaled.append(
                    cv2.resize(data[i], shape, interpolation=cv2.INTER_LINEAR))
            data = np.stack(rescaled, axis=0)
        elif self._adjust_len == "loop":
            # Loop the frame dimension, repeating the sequence as many times as
            # necessary
            padding_size = self._target_len - data.shape[1]
            full_loops = padding_size // data.shape[1]
            if full_loops > 0:
                padding_size -= full_loops * data.shape[1]
                padding = np.repeat(data, full_loops, axis=1)
                data = np.concatenate((data, padding), axis=1)
            data = np.concatenate((data, data[:, :padding_size]), axis=1)
        elif self._adjust_len.startswith("pad"):
            # Pad the sequence at the end with zeros or the last frame
            padding_size = self._target_len - data.shape[1]
            if self._adjust_len.endswith("zero"):
                padding = np.zeros(
                    (data.shape[0], padding_size) + data.shape[2:],
                    dtype=data.dtype)
            elif self._adjust_len.endswith("last"):
                padding = np.expand_dims(data[:, -1], 1)
                padding = np.repeat(padding, padding_size, axis=1)
            data = np.concatenate((data, padding), axis=1)
        return data

    def get_num_keypoints(self) -> int:
        """
        Determines the number of keypoints from the given data.

        Useful when loading data directly from a file and the info is otw not
        known.
        """
        if len(self._data) == 0:
            raise ValueError("No data to determine number of keypoints.")
        else:
            keypoints, __ = self._data[0]
            # keypoints = (frame, landmark, coordinates) or
            #             (person, frame, landmark, coordinates)
        return keypoints.shape[-2]

    def get_num_actions(self) -> int:
        """
        Determines the number of actions from the given data.

        Useful when loading data directly from a file and the info is otw not
        known. Very inefficient though as it requires going through the data,
        if there is a direct way of knowing the number of actions that should
        be preferred.
        """
        if len(self._data) == 0:
            raise ValueError("No data to determine number of keypoints.")
        else:
            if isinstance(self._data, np.ndarray):
                max_action = np.amax(self._data[:, 1])
            else:
                warn(
                    "get_num_actions from sequence object is very inefficient!"
                )
                max_action = 0
                for __, action in self._data:
                    max_action = max(max_action, action)
            return max_action + 1

    def get_keypoint_dim(self) -> int:
        """
        Determines the dimension of keypoints from the given data.

        Useful when loading data directly from a file and the info is otw not
        known.
        """
        if len(self._data) == 0:
            raise ValueError("No data to determine number of keypoints.")
        else:
            keypoints, __ = self._data[0]
            # keypoints = (frame, landmark, coordinates) or
            #             (person, frame, landmark, coordinates)
        return keypoints.shape[-1]


import time

def upload_holiday():
    """ HR's Function that used for Uploading Public and University Holidays,
    and store the holidays in dictionary of list data type afterward write it to plain text file.
    Note: Dictionary Key is holidays name and the value is a list consisting of only start date and end date, 2 elements """

    PU_holidays = {} # initialize the empty FAQs dictionary
    n = 1 # Declare the holiday counting number

    while True:
        holiday_name = input(f"\nPls Enter the name for {n} Public and University Holidays and integer [-1] for exit:") # user input for holiday

        if holiday_name == str(-1): #Exit the Uploading
            print("Upload the Public and University Holidays and exit successfully!!! ")
            time.sleep(1)
            break

        else: # Enter the Leave holiday rule
            holiday_range = [] # initialize the empty list for storing holidays range
            start_date = input(f"Enter starting date for {holiday_name} in YYYY-MM-DD form:")
            holiday_range.append(start_date)
            end_date = input(f"Enter ending date for {holiday_name} in YYYY-MM-DD form:")
            holiday_range.append(end_date)

            PU_holidays[holiday_name] = holiday_range # add the key,value pair to holiday dictionary
            print(f"\nsuccessfully add the {holiday_name} holiday and the current Public and University holidays shown as below\n")
            time.sleep(1)
            print(PU_holidays)
            n += 1
            continue

    with open("Public&University_Holidays.txt","w") as f: # write the policies to plain txt file
        for k,v in PU_holidays.items(): # iterate the holiday dictionary
            f.write(f"{k}:{v}\n")

    return PU_holidays


import time
from macaca import WebDriverException
from requests import HTTPError

import Data_.common as common

def click_by_id(drvier,id):
    try:
        if drvier.element_if_exists('id',id):
            log('click Element by id:'+id)
            drvier.element('id',id).click()
        else:
            log('Type:id ,can\'t get element,Please check ID value:'+id)
    except WebDriverException as Exception:
        log("Exception:"+str(Exception))
    except HTTPError as HT:
        log('except:' + str(HT))

def click_by_xpath(drvier,xpath):
    try:
        if drvier.element_if_exists('xpath',xpath):
            log('click Element by xpath:'+xpath)
            drvier.element('xpath',id).click()
        else:
            log('Type:xpath ,can\'t get element,Please check xpath value:'+xpath)
    except WebDriverException as Exception:
        log("Exception:"+str(Exception))
    except HTTPError as HT:
        log('except:' + str(HT))

def click_by_Name_index(driver,name,index):
    try:
        Elements = driver.elements_by_name(name)
        if len(Elements) >=index+1:
            if Elements[index].rect.get('y')==0 and Elements[index].rect.get('x')==0:
                log('element Name:' + name + ' index:' + str(index) + ' is invisible,rect:'+str(Elements[index].rect))
            else:
                log('click Element by Name:' + name + ',index:' + str(index))
                Elements[index].click()
        else:
            log('Can\'t get element by Name:'+name+',index:'+str(index))
    except WebDriverException as Exception:
        log('Exception:'+str(Exception))
    except HTTPError as HT:
        log('except:' + str(HT))

def click_by_Name(driver,name):
    try:
        if driver.element_if_exists('name',name):
            log('click Element by Name:' + name)
            driver.element('name',name).click()
        else:
            log('Type:Name ,can\'t get element,Please check Name value:' + name)
    except WebDriverException as Exception:
        log('Exception:'+str(Exception))
    except HTTPError as HT:
        log('except:' + str(HT))

def click_by_class_index(driver,className,index):
    try:
        Elements = driver.elements_by_class_name(className)
        if len(Elements)>=index+1:
            if Elements[index].rect.get('y')==0 and Elements[index].rect.get('x')==0:
                log('element class:' + className + ' index:' + str(index) + ' is invisible,rect:'+str(Elements[index].rect))
            else:
                log('click Element by ClassName:' + className + ',index:' + str(index))
                Elements[index].click()
        else:
            log('Can\'t get element by ClassName:' + className + ',index:' + str(index))
    except WebDriverException as Exception:
        log('Exception:'+str(Exception))
    except HTTPError as HT:
        log('except:' + str(HT))

def log(Keyword):
    print(Keyword)
    path = common.log_adress
    fw = open(path, 'a')
    content = str(getTime())+":"+Keyword + '\n'
    fw.write(content)
    fw.close()

def getTime():
    return time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())

def drag(driver,Type):
    log('Drag '+Type)
    if Type=='UP':
        driver.touch('drag', {
            'fromX': common.width / 2,
            'fromY': common.Height / 4 * 3,
            'toX': common.width / 2,
            'toY': common.Height / 4 * 2,
            'duration': 10
        })
    elif Type=='DOWN':
        driver.touch('drag', {
            'fromX': common.width / 2,
            'fromY': common.Height / 4 * 2,
            'toX': common.width / 2,
            'toY': common.Height / 4 * 3,
            'duration': 10
        })
    elif Type=='LEFT':
        driver.touch('drag', {
            'fromX': common.width / 3*2,
            'fromY': common.Height / 2 ,
            'toX': common.width / 3,
            'toY': common.Height / 2,
            'duration': 10
        })
    elif Type=='RIGHT':
        driver.touch('drag', {
            'fromX': common.width / 3,
            'fromY': common.Height / 2,
            'toX': common.width / 3*2,
            'toY': common.Height /2,
            'duration': 10
        })


def enqueue(n):
    global rear
    rear += 1
    q[rear] = n

q = [0] * 10
front = -1
rear = -1

rear += 1  # enqueue
q[rear] = 1

enqueue(2)
enqueue(3)

while front != rear:  # 큐가 비어있지 않으면
    front += 1
    print(q[front])

queue = []
queue.append(1)
queue.append(2)
queue.append(3)

while len(queue) > 0:
    print(queue.pop(0))  # dequeue : queue.pop(0)

print(queue)


import bottle
import quizfragen
import json

@bottle.route("/")
def index():
    with open("static/index.html") as file:
        return bottle.template(file.read(),kategorien=json.dumps(quizfragen.allekategorien()))

@bottle.route("/init")
@bottle.route("/init/")
def init():

    if "kategorie" in bottle.request.query:
        kategorie=bottle.request.query.kategorie
    else:
        kategorie=""
    with open("static/init.html") as file:
        return bottle.template(file.read(),datensatz=json.dumps(quizfragen.fragenvon(kategorie)))

@bottle.route("/frage")
@bottle.route("/frage/")
def frage():
    with open("static/frage.html") as file:
        return file.read()

@bottle.route("/balle-sport.png")
@bottle.route("/balle-sport.png/")
def frage():
    with open("static/balle-sport.png") as file:
        return file.read()

@bottle.route("/main.css")
@bottle.route("/main.css/")
def frage():
    with open("static/main.css") as file:
        return file.read()

@bottle.route("/ergebnis")
@bottle.route("/ergebnis/")
def ergebnis():
    with open("static/ergebnis.html") as file:
        return file.read()

@bottle.route("/ergebnis/<n>")
@bottle.route("/ergebnis/<n>/")
def ergebnis(n="n"):
    with open("static/ergebnis-detail.html") as file:
        return bottle.template(file.read(),n=n)

bottle.run(host="localhost", port=8080, debug=True)


"""
This solution will have o(2n) ~~ O(n) as space complexity. and O(1) as time complexity.
"""
class MyStack(object):
    top = -1
    stck = []
    size = 5
    min_max_dic = []
    first = True

    def isFull(self):
        return self.top == self.size -1

    def isEmpty(self):
        return(self.top == -1)

    def push(self, element):
        if(self.isFull()):
            print("The stack is full::")
            return
        if(self.first):
            self.min_max_dic.append({'min': element , 'max':element})
            first = False

        self.top += 1
        self.stck.append(element)

        if (element < self.min_max_dic[self.top]['min']):
            self.min_max_dic[self.top+1]['min'] = element  ## This is maintaining min and max values in  stack
        if(element > self.min_max_dic[self.top]['max']):
            self.min_max_dic[self.top+1]['max'] = element

        return("The element {} is inserted".format(element))

    def pop(self):
        if(self.isEmpty()):
            print("The Stack is already empty:")
            return
        ele = self.stck[self.top]
        self.stck.remove(ele)
        self.top -= 1
        return("The element {} is popped".format(ele))

    def peek(self):
        return(self.stck[self.top])

    def min(self):
        return(min(self.min_max_dic[self.top]['min']))

    def max(self):
        return(max(self.min_max_dic[self.top]['max']))

st = MyStack()
print("Creating stack:::::")
st.push(60)
st.push(30)
st.push(40)
print("Current stack after pushing elements: " , st.stck)
st.pop()
st.push(80)
print("Current stack after pushing another element : ", st.stck)
print("The next element to be deleted :",st.peek())
st.push(100)
st.push(120)
st.push(10)
print("Current stack after pushing elements : ", st.stck)
print("Minimum element in Stack :",st.min())
print("Maximum element in Stack :",st.max())
st.pop()
print("Current stack after popping elements : ", st.stck)
print("Minimum element in Stack :",st.min())
print("Maximum element in Stack :",st.max())
st.pop()
st.pop()
st.pop()
st.pop()
print("Current stack after popping elements : ", st.stck)
st.pop()


class DataManager:
    """Manages & decides on possible and confirmed demo data

    Example usage:

    dm = DataManager()

    # CERTAIN values don't need attention
    dm.insert('complevel', 3, DataManager.CERTAIN)
    evaluation = dm.evaluate('complevel')
    evaluation.possible_values # [3]
    evaluation.needs_attention # False
    evaluation.message # 'The value is certain'

    # Mismatched POSSIBLE values need attention
    dm.insert('category', 'Pacifist', DataManager.POSSIBLE)
    dm.insert('category', 'UV Speed', DataManager.POSSIBLE)
    evaluation = dm.evaluate('category')
    evaluation.possible_values # ['Pacifist', 'UV Speed']
    evaluation.needs_attention # True
    evaluation.message # 'Multiple sources disagreed on the possible value'

    # CERTAIN values override POSSIBLE values
    dm.insert('category', 'Pacifist', DataManager.CERTAIN)
    dm.evaluate('category').possible_values # ['Pacifist']
    """

    CERTAIN = 'certain'
    POSSIBLE = 'possible'
    ONE_CERTAIN = 'The value is certain'
    ONE_POSSIBLE = 'Only one source reported a possible value'
    AGREED_POSSIBLE = 'Multiple sources agreed on the possible value'
    DISAGREED_CERTAIN = 'Multiple sources disagreed on the certain value'
    DISAGREED_POSSIBLE = 'Multiple sources disagreed on the possible value'
    NO_VALUE = 'No source reported any value'

    def __init__(self):
        self.data = {}

    def insert(self, field, value, certainty):
        self.__ensure_field_exists(field)

        self.data[field].insert(value, certainty)

    def evaluate(self, field):
        self.__ensure_field_exists(field)

        return self.data[field].evaluate()

    def __ensure_field_exists(self, field):
        if field not in self.data:
            self.data[field] = self.FieldManager()

    class FieldManager:
        """Manages the value hierarchy of a field"""

        def __init__(self):
            self.data = {
                DataManager.CERTAIN: {},
                DataManager.POSSIBLE: {}
            }

        def insert(self, value, certainty):
            if value not in self.data[certainty]:
                self.data[certainty][value] = self.ValueCounter(value)

            self.data[certainty][value].increment()

        # This is quite verbose, but inevitably there are a lot of cases
        def evaluate(self):
            certain_count = len(self.__certain())
            possible_count = len(self.__possible())

            if certain_count > 0:
                possible_values = self.__raw_values(self.__certain())

                if certain_count == 1:
                    needs_attention = False
                    message = DataManager.ONE_CERTAIN
                elif certain_count > 1:
                    needs_attention = True
                    message = DataManager.DISAGREED_CERTAIN

            elif possible_count > 0:
                possible_values = self.__raw_values(self.__possible())

                if possible_count == 1:
                    if self.__possible().values()[0].agreement():
                        needs_attention = False
                        message = DataManager.AGREED_POSSIBLE
                    else:
                        needs_attention = True
                        message = DataManager.ONE_POSSIBLE
                else:
                    needs_attention = True
                    message = DataManager.DISAGREED_POSSIBLE

            else:
                possible_values = []
                needs_attention = True
                message = DataManager.NO_VALUE

            return self.Evaluation(possible_values, needs_attention, message)

        def __certain(self):
            return self.data[DataManager.CERTAIN]

        def __possible(self):
            return self.data[DataManager.POSSIBLE]

        def __raw_values(self, value_dict):
            value_counters = value_dict.values()
            return [x.value for x in value_counters]

        class ValueCounter:
            """Counts the number of times a value is reported"""

            def __init__(self, value):
                self.value = value
                self.count = 0

            def increment(self):
                self.count += 1

            def agreement(self):
                return self.count > 1

        class Evaluation:
            """Contains the final evaluation of a field"""

            def __init__(self, possible_values, needs_attention, message):
                self.possible_values = possible_values
                self.needs_attention = needs_attention
                self.message = message


from setuptools import setup

with open("README.md", "r") as f:
    long_description = f.read()

requires = ["betfairlightweight", "betfairutil[files]>=0.0.2", "ipywidgets"]

setup(
    name="betfairviz",
    version="0.1.0",
    description="Create visualisations of Betfair order books",
    long_description=long_description,
    long_description_content_type="text/markdown",
    author="Maurice Berk",
    author_email="maurice@mauriceberk.com",
    url="https://github.com/mberk/betfairviz",
    packages=["betfairviz"],
    install_requires=requires,
    tests_require=[],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.5",
)


#!/usr/bin/env python3
# Name: Jonathan Lyda (jlyda)
# Group Members: None

'''
Reads a FASTQ file through std in, uses command line parameters to know what file type to convert the std in file to,
eliminates errors found in the file provided, and redirects the filtered and converted FASTQ file to std out.

input (command line)(illumina 1.8 to Phred+64):
python FastQ+translater.py <illumina1.8.fastq >newesttest1.8to1.3.fastq -P33in -P64out

output (std out) (redirected to newesttest1.8to1.3.fastq): output file is created in current directory
'''

import sys

class CommandLine():
    '''
    Handle the command line, usage and help requests.

    CommandLine uses argparse, now standard in 2.7 and beyond.
    it implements a standard command line argument parser with various argument options,
    a standard usage and help.

    attributes:
    all arguments received from the commandline using .add_argument will be
    avalable within the .args attribute of object instantiated from CommandLine.
    For example, if myCommandLine is an object of the class, and requiredbool was
    set as an option using add_argument, then myCommandLine.args.requiredbool will
    name that option.
    '''

    def __init__(self, inOpts=None):
        '''
        Implement a parser to interpret the command line argv string using argparse.
        '''

        import argparse
        self.parser = argparse.ArgumentParser(
            description='Program prolog - allows user to specify input and output fastq formats.',
            epilog='Program epilog - will convert fastq file format based on user arguments.',
            add_help=True,  # default is True
            prefix_chars='-',
            usage='%(prog)s [options] -option1[default] <input >output'
        )
        # self.parser.add_argument('inFile', action='store', help='input file name')
        # self.parser.add_argument('outFile', action='store', help='output file name')
        self.parser.add_argument('-P33in', '--PHRED33input', action='store', nargs='?', const=True, default=False,
                                 help='input of Phred 33 (illumina 1.8)')

        self.parser.add_argument('-P64in', '--PHRED64input', action='store', nargs='?', const=True, default=False,
                                 help='input of Phred 64 (illumina 1.3)')

        self.parser.add_argument('-P64Bin', '--PHRED64withBoffsetinqualityvalues', action='store', nargs='?',
                                 const=True, default=False, help='input of Phred 64 with B offset in quality values')

        self.parser.add_argument('-P64SOLin', '--PHRED64withSOLEXAinterpretationsofQscore', action='store',
                                 nargs='?', const=True, default=False, help='input of Phred 64 Solexa (SOLEXA)')

        self.parser.add_argument('-P33out', '--PHRED33output', action='store', nargs='?', const=True, default=True,
                                 help='desired output of Phred 33')  # default set to True

        self.parser.add_argument('-P64out', '--PHRED64output', action='store', nargs='?', const=True, default=False,
                                 help='desired output of Phred 64')

        self.parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1')
        if inOpts is None:
            self.args = self.parser.parse_args()
        else:
            self.args = self.parser.parse_args(inOpts)

class FastQTranslator:
    """
    Reads a Fastq file, parses it, and executes the specified format conversion using various conversion methods.
    """

    def __init__(self, filename):
        """
        initializes a dictionary of solexa values, the file object, the current Fastq entry information, and
        the current Q score value after conversion.
        """

        self.solValues = {-5: 1, -4: 1, -3: 2, -2: 2, -1: 3, 0: 3, 1: 4, 2: 4, 3: 5, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9,
                          9: 10, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19,
                          20: 20, 21: 21, 22: 22, 23: 23, 24: 24, 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30,
                          31: 31, 32: 32, 33: 33, 34: 34, 35: 35, 36: 36, 37: 37, 38: 38, 39: 39, 40: 40}
        self.filename = filename
        self.tempList = [[], [], [], []]   #stores each line in a FASTQ entry when reading one entry at a time
        self.QScore = ''

    def fastqReading(self):
        """
        Parses each FASTQ entry (4 lines), eliminates incorrect entries, and corrects invalid base calls (filters entry).
        """
        file1 = open(self.filename)
        counter = 0
        for line in file1:   #iterates through each line in the given file
            counter += 1
            if ((line.startswith('@')) and (counter == 1)):
                header = line.upper().rstrip()
                self.tempList[0].append(header)    #stores the header if it is correct
            elif counter == 2:
                seq = line.rstrip().replace('*', 'N').replace('.', 'N').replace('n', 'N')
                seq = seq.upper()
                self.tempList[1].append(seq)  #stores the sequence (after capitalizing and making all invalid bases "N"

            elif ((line.startswith('+')) and (counter == 3)):
                plus = line.rstrip()
                self.tempList[2].append(plus)  #stores the 3rd line of the entry (a "+" sign)

            elif ((counter == 4) and (self.tempList[0]) and (self.tempList[1]) and (self.tempList[2])):
                quality = line.rstrip()
                self.tempList[3].append(quality)  #stores quality line
                if (len(quality) == len(seq)):   #checks to make sure line 2 (sequence) and line 4 (quality) are equal
                    for item in self.tempList:
                        yield (item[0])  #gives current stored line data
                    self.tempList = [[], [], [], []]   #reset
                    header = ''
                    seq = ''
                    plus = ''
                    quality = ''
                    counter = 0
                else:
                    self.tempList = [[], [], [], []]  #reset
                    header = ''
                    seq = ''
                    plus = ''
                    quality = ''
                    counter = 0
            else:
                self.tempList = [[], [], [], []]  #reset
                header = ''
                seq = ''
                plus = ''
                quality = ''
                counter = 0

    def ill15ToIll(self):
        """
        Converts Fastq file in Illumina1.5 (PhredB+64) to Illumina 1.3 (Phred+64).
        """
        count = 0
        for line in self.fastqReading():  #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:  #iterates through each character in the quality line
                    if (qual == 'B'):
                        qual = '@'      #Phred+64 encoding
                        self.QScore += qual
                    else:
                        newQual = chr((ord(qual)-64)+64)
                        self.QScore += newQual
                count = 0
            yield (self.QScore)  #gives current line information
            self.QScore = ''  #reset

    def ill15ToSanger(self):
        """
        Converts Fastq file in Illumina1.5 (PhredB+64) to Sanger (Phred+33).
        """
        count = 0
        for line in self.fastqReading(): #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:   #iterates through each character in the quality line
                    if (qual == 'B'):
                        qual = '!'
                        self.QScore += qual
                    else:
                        newQual = chr((ord(qual)-64)+33)
                        self.QScore += newQual
                count = 0
            yield (self.QScore)
            self.QScore = ''

    def solToIll(self):
        """
        Converts Fastq file in Solexa (Phred+64 Solexa) to Illumina 1.3 (Phred+64).
        """
        count = 0
        for line in self.fastqReading(): #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:   #iterates through each character in the quality line
                    newQual = (ord(qual)-64)
                    newQual2 = self.solValues[newQual]    #uses solexa dictionary for conversion
                    qual = chr((newQual2)+64)
                    self.QScore += qual
                count = 0
            yield (self.QScore)
            self.QScore = ''

    def solToSanger(self):
        """
        Converts Fastq file in Solexa (Phred+64 Solexa) to Sanger (Phred+33).
        """
        count = 0
        for line in self.fastqReading(): #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:   #iterates through each character in the quality line
                    newQual = (ord(qual)-64)
                    newQual2 = self.solValues[newQual]   #uses solexa dictionary for conversion
                    qual = chr((newQual2)+33)
                    self.QScore += qual
                count = 0
            yield (self.QScore)
            self.QScore = ''

    def sangerToIll(self):
        """
        Converts Fastq file in Sanger (Phred+33) to Illumina 1.3 (Phred+64).
        """
        count = 0
        for line in self.fastqReading(): #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:    #iterates through each character in the quality line
                    newQual = chr((ord(qual)-33)+64)
                    self.QScore += newQual
                count = 0
            yield (self.QScore)
            self.QScore = ''

    def illToSanger(self):
        """
        Converts Fastq file in Illumina 1.3 (Phred+64) to Sanger (Phred+33).
        """
        count = 0
        for line in self.fastqReading(): #iterates through each line of the parsed file
            if ((count == 0) or (count == 1) or (count == 2)):
                self.QScore = line
                count += 1
            else:
                for qual in line:   #iterates through each character in the quality line
                    newQual = chr((ord(qual)-64)+33)
                    self.QScore += newQual
                count = 0
            yield (self.QScore)
            self.QScore = ''

    def sameType(self):
        """
        Returns the same FASTQ file format back to the user if specified to do so.
        """
        for line in self.fastqReading(): #iterates through each line of the parsed file
            self.QScore = line
            yield (self.QScore)
            self.QScore = ''

def main(inCL=None):
    '''
    Parse the given std in file, use commandline arguments to choose which conversion method to use, converts the Fastq
    file to the specified format, redirects the new translated information to a std out file.
    '''
    if inCL is None:  # if no parameters are entered on command line
        myCommandLine = CommandLine()
    else:
        myCommandLine = CommandLine(inCL)

    filename = sys.stdin.fileno()   #uses std in
    myFastq = FastQTranslator(filename)   #creates a myFastq object using std in file

    if myCommandLine.args.PHRED33input is True:  # Phred33 to Phred64 or Phred33 (no format change)
        if myCommandLine.args.PHRED64output is True:
            for item in myFastq.sangerToIll():
                print(item)
        else:
            for item in myFastq.sameType():
                print(item)

    if myCommandLine.args.PHRED64input is True:  # Phred64 to Phred33 or Phred64 (no format change)
        if myCommandLine.args.PHRED33output is True:
            for item in myFastq.illToSanger():
                print(item)
        else:
            for item in myFastq.sameType():
                print(item)

    if myCommandLine.args.PHRED64withBoffsetinqualityvalues is True:  # Phred64B to Phred33 or Phred64
        if myCommandLine.args.PHRED64output is True:
            for item in myFastq.ill15ToIll():
                print(item)
        else:
            for item in myFastq.ill15ToSanger():
                print(item)

    if myCommandLine.args.PHRED64withSOLEXAinterpretationsofQscore is True:  # Phred64 (Solexa) to Phred33 or Phred64
        if myCommandLine.args.PHRED64output is True:
            for item in myFastq.solToIll():
                print(item)
        else:
            for item in myFastq.solToSanger():
                print(item)

if __name__ == "__main__":
    main()  # uses std in


arr = [1, 2, 3, 3, 3, 5, 8, 11, 16]
target = 3

left = 0
right = len(arr) - 1
min_idx = len(arr) # 최솟값을 답으로 출력해야 하므로, 답이 될 수 있는 값보다 더 큰 값으로 우선 설정

while left <= right:
    mid = (left + right) // 2

    if arr[mid] > target:
        right = mid - 1 # 왼쪽에 조건을 만족하는 숫자가 더 있을 가능성 있으므로, right를 mid - 1로 변환
        min_idx = min(min_idx, mid) # 큰 값들의 위치 중 최솟값 계속 갱신

    else:
        left = mid + 1 # 같거나 작은 경우라면 left값 바꿔줌

print(min_idx) # 조건을 만족하는 최소 index 값 반환


#이진 탐색 알고리즘을 사용하여 정렬된 리스트에서 특정값 찾기!
def find_my_num(list, value):

    start, end = 0, len(list)-1
    #start =0;
    #end = len(list)-1
    while start <= end:
        #검색범위가 남아있는 동안 반복한다
        mid = (start + end) // 2
        #현재 검색 범위의 중간 인덱스를 계산
        if value < list[mid]:
            end = mid - 1
        elif value > list[mid]:
            start = mid + 1
        else:
            return mid
    return -1
    #찾고자하는 값이 없을 때는 -1

print(find_my_num([1,2,3,4,5,6,7,8], 5))


"""
Project Name: NationalMappingForestAttributes
Authors: Giona Matasci (giona.matasci@gmail.com), Geordie Hobart (ghobart@nrcan.gc.ca)
File Name: exportTimeSeries_CAN_YAI_1984_2012.py
Objective: Export to PNG the time-series of some specified attributes of interest zoomed to a given bookmark
"""

# TO DO

# - che ck code with the addition of the landsat image
# - add difference between 2012 and 1984 and export it

## IMPORT MODULES ---------------------------------------------------------------

import arcpy, os, sys, glob
import numpy as np
from itertools import compress

sys.path.append(r'D:/Research/MyPythonModules')
from mybasemodule import*

## PARAMETERS  ------------------------------------------------

mxds_folder = r"D:\Research\ANALYSES\NationalMappingForestAttributes\WKG_DIR\MXDs"

root_dir = os.path.join(mxds_folder, "TimeSeries", "FireHarvest_CAN_timeseries_1984_2012")

out_folder = os.path.join(root_dir, r"PNGs")

# input_mxd = os.path.join(root_dir, r'empty.mxd')  ## path to empty mxd that has to have a scale bar (will adapt automatically) and bookmarks already set
input_mxd = os.path.join(root_dir, r'empty_nothing.mxd')  ## path to empty mxd that has to have a scale bar (will adapt automatically) and bookmarks already set

output_mxd = os.path.join(root_dir, r"FireHarvest_CAN_timeseries_1984_2012.mxd")  ## path to final mxd to save results

params = {}

params['build_MXD'] = True
# params['build_MXD'] = False

params['export_PNGs'] = True

# params['years'] = np.arange(1984, 2013, 1)
params['years'] = np.arange(1984, 1986, 1)

# params['targ_fact'] = {'elev_p95': "elev_p95", "cover_2m": 'percentage_first_returns_above_2m', "stem_volume": 'gross_stem_volume', "ag_biomass": 'total_biomass'}
params['targ_fact'] = {"stem_volume": 'gross_stem_volume', "ag_biomass": 'total_biomass'}

in_folder = r"E:\NTEMS\UTM_results\YAI_temporal_maps"

mask_file_base_name = "LC_Class_HMM_*.dat"  ## UTMzone in old filename by TX
landsat_image_base_name = "SRef_UTM*_1984_proxy_v2.dat"

# mapping_areas = {"11H": "11S", "11HH": "11S", "15F": "15S", "18H":"18S", "13F":"13S"}
mapping_areas = {"11H": "11S", "11HH": "11S", "13F":"13S"}

lyrs_dir = os.path.join(mxds_folder, "LYRs")
mask_lyr_path = os.path.join(lyrs_dir, r'Mask_4_TreedClasses.lyr')
landsat_lyr_path = os.path.join(lyrs_dir, r'Landsat_RGB543.lyr.lyr')
attr_lyr_srckey = os.path.join(lyrs_dir, '*_contin_*.lyr')

## START --------------------------------------------------------------------------

print('exportTimeSeries_CAN_YAI_1984_2012.py: started on %s' % time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime()))

start_time = tic()

arcpy.CheckOutExtension("Spatial")
arcpy.env.overwriteOutput = True

## Get MXD and dataframe
mxd = arcpy.mapping.MapDocument(input_mxd)
df = arcpy.mapping.ListDataFrames(mxd, 'Layers')[0]  ## assuming there is only 1 df (called Layer, the default)
mxd.activeView = df.name
mxd.title = df.name

## LOAD LAYERS AND APPLY SYMBOLOGY ----------------------------------------------

if params['build_MXD']:

    print('Loading layers and applying symbology...')

    for mapping_area, UTMzone in mapping_areas.iteritems():  ## iterate over mapping areas

        print('Area: '+mapping_area)

        in_dir_YAI = os.path.join(in_folder, mapping_area, "Results", "YAI_fitted")
        VLCE_dir = os.path.join(in_folder, mapping_area, "Results", "VLCE")
        landsat_dir = os.path.join(in_folder, mapping_area, "Results", "proxy_values")

        file_dirs = [in_dir_YAI, VLCE_dir, landsat_dir]

        for idx_dir, file_dir in enumerate(file_dirs):  ## iterate over the directories

            if file_dir == in_dir_YAI:
                files_to_add_path = []
                source_lyrs_dict = {}
                for targ, targ_long in params['targ_fact'].iteritems():
                    in_file_base_name_YAI = "UTM_%s_%s_YAI_*.dat" % (mapping_area, targ_long)
                    files_to_add_path.extend(glob.glob(os.path.join(file_dir, in_file_base_name_YAI)))
            elif file_dir == VLCE_dir:
                files_to_add_path = glob.glob(os.path.join(file_dir, mask_file_base_name))
            elif file_dir == landsat_dir:
                files_to_add_path = glob.glob(os.path.join(file_dir, landsat_image_base_name))

            for idx_file, file_to_add in enumerate(files_to_add_path):

                file = file_to_add

                if file_dir == VLCE_dir:  ## select forest mask layer file
                    if UTMzone in file_to_add:
                        file_path_new = file_to_add.replace(UTMzone, mapping_area)
                        arcpy.Rename_management(file_to_add, file_path_new)
                        file = file_path_new

                layer_to_add = arcpy.mapping.Layer(file)
                arcpy.mapping.AddLayer(df, layer_to_add, "TOP")

                if file_dir == VLCE_dir:  ## select forest mask layer file
                    source_lyr_path = mask_lyr_path
                elif file_dir == landsat_dir:
                    source_lyr_path = landsat_lyr_path
                elif file_dir == in_dir_YAI:  ## or select corresponding attribute layer file
                    logic_idx = [targ_long in layer_to_add.name for targ, targ_long in params['targ_fact'].iteritems()]
                    targ = list(compress(params['targ_fact'].values(), logic_idx))[0]
                    cand_lyr_path_list = glob.glob(attr_lyr_srckey)
                    source_lyr_path = [cand_lyr_path for cand_lyr_path in cand_lyr_path_list if targ in cand_lyr_path][0]

                source_lyr = arcpy.mapping.Layer(source_lyr_path)
                layer_to_update = arcpy.mapping.ListLayers(mxd, layer_to_add.name, df)[0]  ## redefine layer_to_update as an arcpy object
                arcpy.ApplySymbologyFromLayer_management(layer_to_update, source_lyr)  ## first apply the symbology with ApplySymbologyFromLayer_management (needs a path to the layer providing the symbology)
                arcpy.mapping.UpdateLayer(df, layer_to_update, source_lyr, True)  ## update symbology by using the one of source_lyr (has to be an arpy object and not just the path)

                arcpy.RefreshActiveView()
                arcpy.RefreshTOC()

    ## SAVE MXD -------------------------------------------------------

    print('Saving MXD...')

    mxd.saveACopy(output_mxd)

else:

    mxd = arcpy.mapping.MapDocument(output_mxd)
    df = arcpy.mapping.ListDataFrames(mxd, 'Layers')[0]  ## assuming there is only 1 df (called Layer, the default)
    mxd.activeView = df.name
    mxd.title = df.name

## ZOOM ON BOOKMARKS AND EXPORT PNGs --------------------------------------

if params['export_PNGs']:

    print('Exporting PNGs...')

    ## Turn of all layers in list
    for layer in arcpy.mapping.ListLayers(mxd, '', df):
        layer.visible = False
    arcpy.RefreshActiveView()

    ## Loop over the bookmarks
    for bkmk in arcpy.mapping.ListBookmarks(mxd):

        if bkmk.name[0:3] not in mapping_areas.keys():
            continue

        print('Area: %s' % bkmk.name)

        ## Set a projection system for the dataframe matching the UTM zone of the bookmark/mapping area
        df.spatialReference = arcpy.SpatialReference("NAD 1983 UTM Zone %sN" % bkmk.name[0:2])
        df.extent = bkmk.extent  ## set extent of dataframe to extent of bookmark

        ## Create directory for output .png files
        png_dir = os.path.join(out_folder, bkmk.name)
        if not os.path.exists(png_dir):
            os.makedirs(png_dir)

        search_key = "SRef_UTM%s_1984_proxy_v2.dat" % (bkmk.name.split('_')[0])
        try:
            landsat_layer = arcpy.mapping.ListLayers(mxd, search_key, df)[0]
        except:
            continue
        landsat_layer.visible = True
        arcpy.RefreshActiveView()
        png_name_out = "%s_Landsat543_1984.png" % (bkmk.name)  # build dynamic filename with the equivalent of sprintf
        arcpy.mapping.ExportToPNG(mxd, os.path.join(png_dir, png_name_out))  ## export mxd (zoomed on bookmark extent, and with only one layer available) to png
        landsat_layer.visible = False

        ## Loop over year of interest
        for yr in params['years']:

            search_key = 'LC_Class_HMM_%s_%d.dat' % (bkmk.name.split('_')[0], yr)
            try:
                mask_layer = arcpy.mapping.ListLayers(mxd, search_key, df)[0]
            except:
                continue

            placement = "TOP"
            mask_layer.visible = True

            for targ, targ_long in params['targ_fact'].iteritems():

                search_key = "UTM_%s_%s_YAI_%d.dat" % (bkmk.name.split('_')[0], targ_long, yr)
                try:
                    map_layer = arcpy.mapping.ListLayers(mxd, search_key, df)[0]
                except:
                    continue

                placement = "BOTTOM"
                map_layer.visible = True
                arcpy.RefreshActiveView()

                png_name_out = "%s_%s_%d.png" % (bkmk.name, targ, yr)  # build dynamic filename with the equivalent of sprintf
                arcpy.mapping.ExportToPNG(mxd, os.path.join(png_dir, png_name_out))  ## export mxd (zoomed on bookmark extent, and with only one layer available) to png
                map_layer.visible = False

            mask_layer.visible = False

print('Total ' + toc(start_time))


from IPython.display import display, Image
import PIL.Image
import numpy as np

import ImagePairsFormer

class Eyeballer:
    def __init__(self):
        pass
    # def __init__(self, type_of_image_pairs, minimum_index_similarity):
    #     self.MINIMUM_INDEX_SIMILARITY = minimum_index_similarity
    #     self.TYPE_OF_IMAGE_PAIRS = type_of_image_pairs

    # def obtain_image_pairs(self, list_of_images):
    #     IPF = ImagePairsFormer.ImagePairsFormer()
    #     if(self.TYPE_OF_IMAGE_PAIRS == 'exclusive'):
    #         return IPF.return_max_exclusive_image_pairs(list_of_images, self.MINIMUM_INDEX_SIMILARITY)
    #     elif(self.TYPE_OF_IMAGE_PAIRS == 'duplicate'):
    #         return IPF.return_max_duplicate_image_pairs(list_of_images)
    #     elif(self.TYPE_OF_IMAGE_PAIRS == 'munkres'):
    #         return IPF.return_munkres_pairs(list_of_images)

    def create_eyeball_file_name(self, storage_folder, name_of_images):
        return

    def form_eyeballs(self, list_of_images):
        # try:
        #     stimulus_file =
        return

    def forming_eyeballs(self, sim_value, storage_path, stimulus_image_files, distractor_image_files, stimulus_names, distractor_names):
        for i in range(len(stimulus_image_files)):
            try:
                stimulus_file = stimulus_image_files[i]
                distractor_file = distractor_image_files[i]

                eyeball_filename = str(storage_path)+str(sim_value[i])+"_"+str(stimulus_names[i].split("_")[0])+"_"+str(distractor_names[i].split("_")[0])
                list_im = [ stimulus_file, distractor_file ]
                imgs = [ PIL.Image.open(k) for k in list_im ]

        #         min_shape = sorted( [(np.sum(j.size), j.size) for j in imgs])[0][1]
        #         print(min_shape)
                imgs_comb = np.hstack( (np.asarray( j.resize((400,400)) ) for j in imgs ) )

                imgs_comb = PIL.Image.fromarray(imgs_comb)
                imgs_comb.save("%s.jpg" %eyeball_filename)
                print(eyeball_filename)
            except:
                print("Could not eyeball " + str(stimulus_file) + "_" + str(distractor_file))

    # forming_eyeballs(sim_value, stimulus_files, distractor_files, stimulus_names, distractor_names)


# -*- coding: utf-8 -*-
from faker.providers import BaseProvider

from .mimetypes import mime_types

class WebProvider(BaseProvider):
    """
    A Provider for web-related test data.

    >>> from faker import Faker
    >>> from faker_web import WebProvider
    >>> fake = Faker()
    >>> fake.add_provider(WebProvider)
    """
    all_mime_types = mime_types

    popular_mime_types = {
        'application/javascript': ['js'],
        'application/json': ['json'],
        'application/pdf': ['pdf'],
        'image/jpeg': ['jpeg', 'jpg', 'jpe'],
        'image/gif': ['gif'],
        'image/png': ['png'],
        'image/svg+xml': ['svg', 'svgz'],
        'text/css': ['css'],
        'text/html': ['html', 'htm'],
        'text/plain': ['txt', 'text', 'conf', 'def', 'list', 'log', 'in'],
    }

    web_servers = (
        'apache',
        'nginx',
        'iis',
        'varnish',
    )

    apache_versions = {
        '1.3': list(range(1, 42)),
        '2.0': list(range(35, 65)),
        '2.2': list(range(0, 32)),
        '2.4': list(range(1, 25)),
    }

    apache_distro = (
        'Amazon',
        'CentOS',
        'Debian',
        'Fedora',
        'Red Hat',
        'Ubuntu',
        'Unix',
    )

    nginx_versions = {
        '1.4': list(range(0, 7)),
        '1.5': list(range(0, 13)),
        '1.6': list(range(0, 3)),
        '1.7': list(range(0, 10)),
        '1.8': list(range(0, 1)),
        '1.9': list(range(0, 15)),
        '1.10': list(range(0, 3)),
        '1.11': list(range(0, 8)),
        '1.12': list(range(0, 0)),
    }

    iis_versions = (
        '1.0',
        '2.0',
        '3.0',
        '4.0',
        '5.0',
        '5.1',
        '6.0',
        '7.0',
        '7.5',
        '8.0',
    )

    def content_type(self):
        """
        Returns a mime-type from the list of types understood by the Apache
        http server.

        >>> fake.content_type()
        application/mxf

        :return: content-type
        :rtype: str
        """
        return self.random_element(self.all_mime_types.keys())

    def content_type_popular(self):
        """
        Returns a popular mime-type.

        >>> fake.content_type_popular()
        text/html

        :return: content-type/mime-type
        :rtype: str
        """
        return self.random_element(self.popular_mime_types.keys())

    def _web_server_version(self, choices):
        minor = self.random_element(choices.keys())
        patch = self.random_element(choices.get(minor))
        return '{minor}.{patch}'.format(**locals())

    def apache(self):
        version = self._web_server_version(self.apache_versions)
        os = self.random_element(self.apache_distro)
        return 'Apache/{version} ({os})'.format(**locals())

    def nginx(self):
        version = self._web_server_version(self.apache_versions)
        return 'nginx/' + version

    def iis(self):
        return 'Microsoft-IIS/' + self.random_element(self.iis_versions)

    def varnish(self):
        return 'Varnish'

    def server_token(self):
        """
        Returns a http web server response header, as per RFC-2616, section
        14.38
        https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.38

        >>> fake.server_token()
        Apache/2.4.9 (Unix)

        :return: web server signature.
        :rtype: str
        """
        return getattr(self, self.random_element(self.web_servers))()


import os
import discord
from dotenv import load_dotenv

path = os.path.abspath(__file__)
path = path[:-(len(__file__)+8)]

load_dotenv(dotenv_path = path + "configFiles/.env")
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')

intents = discord.Intents.default()
intents.members = True
intents.messages = True
client = discord.Client(intents=intents)

@client.event
async def on_ready():
    guild = discord.utils.get(client.guilds, name=GUILD)
    print(f'{client.user} has connected to Discord!')
    for member in guild.members:
        print(member.name)

@client.event
async def on_message(message):
    test()
    print(message.content)

def test():
    print("This is a test")

client.run(TOKEN)


'''
Find the first character that repeats in a String and return that character.

first_dup('tweet') => 't'
first_dup('like') => None
This is not the same as finding the character that repeats first. In that case, an input of 'tweet' would yield 'e'.
'''
def first_dup(s):
    new_s = ''
    for i in s:
        if s.count(i) == 1:
            new_s += i
            break
    if new_s == '':
        return None
    else:
        return new_s


# -*- coding: utf-8 -*-
"""
Created on Thu Apr 30 01:07:52 2020

@author: admin
"""

import seaborn as sns
sns.set()
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import csv
from sklearn.cluster import KMeans
data=pd.read_csv('Sentiments2.csv')

plt.scatter(data['neg'],data['pos'],marker='.')
plt.xlabel('Negative')
plt.ylabel('Posetive')
plt.show()

x=data[['neg','pos']].copy()
###########################################
kmeans=KMeans(3)
kmeans.fit(x)
clusters=x.copy()
list_comments=[]
clusters['cluster_pred']=kmeans.fit_predict(x)
for i in range(len(clusters['cluster_pred'])):
    #sentence=data.commentBody[i]
    dataframe ={}
    dataframe["Comment"] = data.Comment[i]
    dataframe["neg"] = data.neg[i]
    dataframe["pos"] = data.pos[i]
    val=clusters['cluster_pred'][i]
    if (val == 0):
            dataframe["cluster"] = "mixed"
    if (val == 1):
            dataframe["cluster"] = "mostly Positive"
    if (val == 2):
            dataframe["cluster"] = "revisit"
    list_comments.append(dataframe)
df = pd.DataFrame(list_comments)
df.to_csv("Kmeans2.csv")

plt.scatter(clusters['neg'],clusters['pos'],c=clusters['cluster_pred'],marker='.',cmap='spring')

plt.xlabel('Negative')
plt.ylabel('Positive')
plt.show()


# Sample Input 0

# 12
# insert 0 5
# insert 1 10
# insert 0 6
# print
# remove 6
# append 9
# append 1
# sort
# print
# pop
# reverse
# print
# Sample Output 0

# [6, 5, 10]
# [1, 5, 9, 10]
# [9, 5, 1]

class Command():
    def __init__(self, command_type, arguments_number):
        self.command_type = command_type
        self.arguments_number = arguments_number

commands_info = {
    "insert": Command("collection", 2),
    "remove": Command("collection", 1),
    "append": Command("collection", 1),
    "sort": Command("collection", 0),
    "pop": Command("collection", 0),
    "reverse": Command("collection", 0),
    "print": Command("runtime", 0)
}

def execute_command(command_text, collection):
    args = command_text.split()
    command_name = args[0]
    args.remove(command_name)
    command = commands_info[command_name]
    if command.command_type == "collection":
        fn = getattr(collection, command_name)
        fn(*map(int, args))
    else:
        print(collection)

if __name__ == '__main__':
    N = int(input())
    collection = []
    for _ in range(N):
        execute_command(input(), collection)


# 9단계 기본 수학2 직각삼각형
# 피타고라스의 정리에 대해 배우는 문제

while 1:
    p = sorted(list(map(int, input().split())))
    if p[0]: break

    # 직각 삼각형의 조건
    if p[2] ** 2 == p[0] ** 2 + p[1] ** 2:
        print('right')
    else:
        print('wrong')


from __future__ import print_function
import argparse as ap
import time
import sys
import pyric
import pyric.pyw as pyw
import pyric.utils.hardware as hw
from pyric.utils.channels import rf2ch

def execute(dev):
      print('setting up...')
      ifaces=pyw.interfaces()
      wifaces=pyw.winterfaces()

      if dev  not in ifaces:
        print("Device {0} is not valid, use one of {1}".format(dev, ifaces))
        return
      elif dev not in wifaces:
        print("Devise {0} is not wireless, use one of {1}".format(dev, wifaces))

      print("Regulatory Domain Currently: ", pyw.regget())
      dinfo =pyw.devinfo(dev)
      card =dinfo['card']
      pinfo = pyw.phyinfo(card)
      driver = hw.ifdriver(card.dev)
      chipset =hw.ifchipset(driver)
      msg = "Using {0} currently in mode: {1}\n".format(card,dinfo['mode'])
      msg += "\tDriver: {0} Chipset: {1}\n".format(driver,chipset)
      if dinfo['mode'] == 'managed':
        msg += "\tcurrently on channel {0} width {1}\n".format(rf2ch(dinfo['RF']),
                                                               dinfo['CHW'])
      msg += "\tSupports modes {0}\n".format(pinfo['modes'])
      msg += "\tSupports commands {0}".format(pinfo['commands'])
      msg += "\thw addr {0}".format(pyw.macget(card))
      print(msg)

      print ('Preparing pent0 for monitor mode')
      pdev='pent0'

      pcard = pyw.devadd(card, pdev, 'monitor')

      for iface in pyw.ifaces(card):
            if iface[0].dev !=pcard.dev:
                  print("deleting {0} in mode {1}".format(iface[0],iface[1]))
                  pyw.devdel(iface[0])
      pyw.up(pcard)
      print("using pcard")
      print("Setting channel to 6 NOHT")
      pyw.chset(pcard,6,None)
      msg = "Virtual interface {0} in monitor mode on ch 6".format(pcard)
      print(msg + ", using hwaddr: {0}".format(pyw.macget(pcard)))

      try:
          print('now ready to execute')
          print('hit Ctrl + C to quit and restore')
          while True: time.sleep(1)
      except KeyboardInterrupt:
          pass
#------

    #------
      print("restoring ", card, 'mode=', dinfo['mode'], 'mac=', dinfo['mac'])
      card =pyw.devadd(pcard, card.dev,dinfo['mode'])
      print('Deleting', pcard)
      pyw.devdel(pcard)
      pyw.up(card)
      print ("card ", card, " restored")

#------
if __name__ == '__main__':
    # create arg parser and parse command line args
    print("Wireless Pentest Environment using PyRIC v{0}".format(pyric.version))
    argp = ap.ArgumentParser(description="Wireless Pentest")
    argp.add_argument('-d','--dev',help="Pentesting Wireless Device")
    args = argp.parse_args()
    try:
        dname = args.dev
        if dname is None:
            print("usage: python pentest.py -d <dev>")
            sys.exit(0)
        else:
            execute(dname)
    except pyric.error as e:
        print(e)


import datetime
from django.http import response
from django.test import TestCase
from django.utils import timezone
from django.urls import reverse

from polls.models import Question

#! тесты для метода was_published_recently

class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)

    def test_was_published_recently_with_old_question(self):
        time = timezone.now() - datetime.timedelta(days=1, seconds=1)
        old_question = Question(pub_date=time)
        self.assertIs(old_question.was_published_recently(), False)

    def test_was_published_recently_with_recent_question(self):
        time = timezone.now() - datetime.timedelta(hours=59, minutes=59, seconds=59)
        recent_question = Question(pub_date=time)
        self.assertIs(recent_question.was_published_recently(), True)

#! тесты представления

def create_question(question_text, days):  #! функция для создания вопросов
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)

#! Проверить Questions с датами в прошлом и будущем

class QuestionIndexViewTests(TestCase):
    def test_no_question(self):
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        question = create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_future_question(self):
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])
        #! проверка, что 'latest_question_list' пустой

    def test_future_question_and_past_question(self):
        """
        Даже если существуют и прошлые, и будущие вопросы,
        только прошлые вопросы отображаются.
        """
        question = create_question(question_text="Past question.", days=-30)
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_two_past_questions(self):
        """
        Отражение нескольких вопросов на странице
        """
        question1 = create_question(question_text="Past question 1.", days=-30)
        question2 = create_question(question_text="Past question 2.", days=-5)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question2, question1],
        )

'''
Проверить, что Question, у которого pub_date находится в прошлом,
может отображаться, а вопрос с pub_date в будущем - нет'''

class QuestionDetailViewTests(TestCase):
    def test_future_question(self):
    #! возврат ошибки 404 not found
        future_question = create_question(question_text="Future question.", days=5)
        url = reverse('polls:detail', args=(future_question.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_past_question(self):
        past_question = create_question(question_text="Past question.", days=-5)
        url = reverse('polls:detail', args=(past_question.id,))
        response = self.client.get(url)
        self.assertEqual(response, past_question.question_text)