from __future__ import print_function
import simpy
import random
from statistics import mean
from pifo_wrapper import SkipListWrapper

def test(env):
    NUM_SKIP_LISTS = 6
    PERIOD = 1
    MAX_NODES = 512
    OUTREG_WIDTH = 16
    ENQ_FIFO_DEPTH = 16
    CLK_FREQ = 200 # MHz
    PKT_RATE = 14.8*4 # MPkts/sec
    PKT_INTERVAL = int(CLK_FREQ/PKT_RATE)
    NumRuns = 1
    NumOps = 128
    enq_nclks_list = []
    deq_nclks_list = []

    enq_in_pipe  = simpy.Store(env)
    enq_out_pipe = simpy.Store(env)
    deq_in_pipe  = simpy.Store(env)
    deq_out_pipe = simpy.Store(env)

    print ('@ {:04d} - starting skip list init'.format(env.now))

    slw = SkipListWrapper(env, enq_in_pipe, enq_out_pipe, deq_in_pipe, deq_out_pipe, num_sl=NUM_SKIP_LISTS, period=PERIOD, size=MAX_NODES, outreg_width=OUTREG_WIDTH, enq_fifo_depth=ENQ_FIFO_DEPTH, rd_latency=1, wr_latency=1)

    for i in range(NUM_SKIP_LISTS):
        while slw.sl[i].busy == 1:
            yield env.timeout(PERIOD)

    print ('@ {:04d} - done skip list init'.format(env.now))

    for j in range(NumRuns):
        print ("Run:", j)
        # Enqueue some values and print skip list
        for i in range (NumOps):
            val = random.randint(0,100)
            hsp = mdp = -1
            t1 = env.now
            slw.enq_in_pipe.put((val, hsp, mdp))
            yield slw.enq_out_pipe.get()
            enq_nclks = env.now - t1
            enq_nclks_list.append(enq_nclks)
            print ('enq: {} - {} clks'.format(val, enq_nclks))
            yield env.timeout(PKT_INTERVAL)

        for i in range(NUM_SKIP_LISTS):
            while slw.sl[i].enq_fifo.fill_level() != 0 or slw.sl[i].busy == 1:
                yield env.timeout(PERIOD)

        # Dequeue all values and print skip list
        while slw.num_entries > 0:
            t1 = env.now
            slw.deq_in_pipe.put(True)
            (val, hsp, mdp, deq_nclks) = yield slw.deq_out_pipe.get()
            deq_nclks = env.now - t1
            print ('deq: {} - {} clks'.format(val, deq_nclks))
            deq_nclks_list.append(deq_nclks)
            yield env.timeout(PKT_INTERVAL)

    # Wait until skip lists are done
    for i in range(NUM_SKIP_LISTS):
        while slw.sl[i].busy == 1:
            yield env.timeout(PERIOD)
        # Stop deq_sl processes
        slw.sl[i].enq_sl_proc.interrupt('Done')
        slw.sl[i].deq_sl_proc.interrupt('Done')

    print ("Time measurements (min, avg, max) for {} runs of {} enq/deq ops".format(NumRuns, NumOps))
    print ("Enq: {:5.2f} {:5.2f} {:5.2f}".format(min(enq_nclks_list), mean(enq_nclks_list), max(enq_nclks_list)))
    print ("Deq: {:5.2f} {:5.2f} {:5.2f}".format(min(deq_nclks_list), mean(deq_nclks_list), max(deq_nclks_list)))

# Main
env = simpy.Environment()
env.process(test(env))
env.run()


#Huffman Coding
class node:
    def __init__(self, freq, symbol, left=None, right=None):
        # frequency of symbol
        self.freq = freq

        # symbol name (charecter)
        self.symbol = symbol

        # node left of current node
        self.left = left

        # node right of current node
        self.right = right

        # tree direction (0/1)
        self.huff = ''

# utility function to print huffman
# codes for all symbols in the newly
# created Huffman tree

def printNodes(node, val=''):
    # huffman code for current node
    newVal = val + str(node.huff)

    # if node is not an edge node
    # then traverse inside it
    if(node.left):
        printNodes(node.left, newVal)
    if(node.right):
        printNodes(node.right, newVal)

        # if node is edge node then
        # display its huffman code
    if(not node.left and not node.right):
        print(f"{node.symbol} -> {newVal}")

#taking input
# charecters for huffman tree
chars = list(map(str,input("enter the number of characters:").rstrip().split()))

# frequency of charecters
freq = list(map(int, input("enter the frequency of each character you entered:").rstrip().split()))
# list containing unused nodes
nodes = []

# converting ccharecters and frequencies
# into huffman tree nodes
for x in range(len(chars)):
    nodes.append(node(freq[x], chars[x]))

while len(nodes) > 1:
    # sort all the nodes in ascending order
    # based on theri frequency
    nodes = sorted(nodes, key=lambda x: x.freq)

    # pick 2 smallest nodes
    left = nodes[0]
    right = nodes[1]

    # assign directional value to these nodes
    left.huff = 0
    right.huff = 1

    # combine the 2 smallest nodes to create
    # new node as their parent
    newNode = node(left.freq+right.freq, left.symbol+right.symbol, left, right)

    # remove the 2 nodes and add their
    # parent as new node among others
    nodes.remove(left)
    nodes.remove(right)
    nodes.append(newNode)

# Huffman Tree is ready!
printNodes(nodes[0])

# Python code for run length encoding
from collections import OrderedDict
def runLengthEncoding(string):
    count = 0
    chatacter = ''
    previous_char = string[0]
    result = ''
    length = len(string)

    i = 0
    while (i != length ):
        chatacter = string[i]

        if previous_char == chatacter :
            count = count + 1
        else :
            result = result + str(count) + previous_char
            count = 1
        #print(str(i) + str(chatacter) + str(previous_char) + "          " + str(result))
        previous_char = chatacter
        i = i + 1

    return result + str(count) + str(previous_char)

# taking input
string = str(input("enter the string:"))
print (runLengthEncoding(string))

#Develop KNN algo
from math import sqrt

# calculate the Euclidean distance between two vectors
def euclidean_distance(row1, row2):
	distance = 0.0
	for i in range(len(row1)-1):
		distance += (row1[i] - row2[i])**2
	return sqrt(distance)
# Locate the most similar neighbors
def get_neighbors(train, test_row, num_neighbors):
	distances = list()
	for train_row in train:
		dist = euclidean_distance(test_row, train_row)
		distances.append((train_row, dist))
	distances.sort(key=lambda tup: tup[1])
	neighbors = list()
	for i in range(num_neighbors):
		neighbors.append(distances[i][0])
	return neighbors
# Make a classification prediction with neighbors
def predict_classification(train, test_row, num_neighbors):
	neighbors = get_neighbors(train, test_row, num_neighbors)
	output_values = [row[-1] for row in neighbors]
	prediction = max(set(output_values), key=output_values.count)
	return prediction

# Test distance function
dataset = [[2.7810836,2.550537003,0],
	[1.465489372,2.362125076,0],
	[3.396561688,4.400293529,0],
	[1.38807019,1.850220317,0],
	[3.06407232,3.005305973,0],
	[7.627531214,2.759262235,1],
	[5.332441248,2.088626775,1],
	[6.922596716,1.77106367,1],
	[8.675418651,-0.242068655,1],
	[7.673756466,3.508563011,1]]
row0 = dataset[0]
for row in dataset:
	distance = euclidean_distance(row0, row)
	print(distance)


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

# In[47]:

#Load the dataset into the tool.
import pandas as pd

data = pd.read_csv('housing.csv')

# In[48]:

# Univariate analysis
import matplotlib.pyplot as plt

# Histogram
plt.hist(data['price'], bins=20)
plt.xlabel('Price')
plt.ylabel('Area')
plt.title('Price VS Area')
plt.show()

# Bar plot
data['bedrooms'].value_counts().plot(kind='bar')
plt.xlabel('Bedrooms')
plt.ylabel('Stories')
plt.title('Bedrooms VS Stories')
plt.show()

# In[11]:

# Bivariate analysis
import seaborn as sns

# Scatter plot
sns.scatterplot(x='area', y='price', data=data)
plt.xlabel('Area')
plt.ylabel('Price')
plt.title('Price vs. Area')
plt.show()

# Box plot
sns.boxplot(x='parking', y='price', data=data)
plt.xlabel('Parking')
plt.ylabel('Price')
plt.title('Parking vs Price')
plt.show()

# In[12]:

# Multivariate analysis
# Correlation matrix
corr_matrix = data.corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
plt.title('Correlation Matrix')
plt.show()

# Pair plot
sns.pairplot(data)
plt.show()

# In[13]:

# Descriptive statistics
statistics = data.describe()
print(statistics)

# In[15]:

# Check for missing values
missing_values = data.isnull().sum()
print(missing_values)
data = data.dropna()

# In[17]:

#detecting outliers
import numpy as np
def detect_outliers_zscore(data, threshold=3):
    z_scores = np.abs((data - data.mean()) / data.std())
    outliers = data[z_scores > threshold]
    return outliers
numerical_columns = ['price', 'area', 'bedrooms', 'bathrooms','stories','parking']
for column in numerical_columns:
    outliers = detect_outliers_zscore(data[column])
    print(f"Outliers in {column}:")
    print(outliers)

# In[18]:

#replacing outliers
def replace_outliers(data, column, method='median', threshold=3):
    z_scores = np.abs((data[column] - data[column].mean()) / data[column].std())
    outliers = data[z_scores > threshold]

    if method == 'median':
        replacement_value = data[column].median()
    elif method == 'mean':
        replacement_value = data[column].mean()
    else:
        raise ValueError("Invalid replacement method. Choose 'median' or 'mean'.")

    data.loc[z_scores > threshold, column] = replacement_value

    return data

numerical_columns = ['price', 'area', 'bedrooms', 'bathrooms','stories','parking']
for column in numerical_columns:
    data = replace_outliers(data, column, method='median')
data.to_csv('housing_without_outliers.csv', index=False)

# In[35]:

# Check for categorical columns
categorical_columns = data.select_dtypes(include=['object']).columns

# Perform one-hot encoding
data_encoded = pd.get_dummies(data, columns=categorical_columns)

# In[36]:

# Split into dependent and independent variables
X = data.drop('price', axis=1)  # Independent variables
y = data['price']  # Dependent variable

# In[37]:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# In[46]:

# Split the data into training and testing
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# In[45]:

# Build the model
from sklearn.linear_model import LinearRegression

model = LinearRegression()

# In[44]:

# Train the model
model.fit(X_train, y_train)

# In[41]:

# Test the model
y_pred = model.predict(X_test)

# In[43]:

# Measure performance
from sklearn.metrics import mean_squared_error, r2_score

rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)

print("RMSE:", rmse)
print("R-squared:", r2)


import os.path
from collections import deque

def formar_menu_acciones() -> str:
    """
    esta funcion retorna el menu de acciones para que pueda ser printeado
    """
    linea_1 = '[1] Mostrar tablero'
    linea_2 = '[2] Validar bombas y tortugas'
    linea_3 = '[3] Solucionar tablero'
    linea_4 = '[4] Validar solucion'
    linea_5 = '[0] Salir del DCCeldas'
    return f'\n**MENU DE ACCIONES**\n\n{linea_1}\n{linea_2}\n{linea_3}\n{linea_4}\n{linea_5}'

"""
las cuatro funciones siguientes son para checkear el valor arriba, abajo y a los lados
de una posicion especifica en una matriz, retorna True si son iguales a T, False en los otros casos
"""

def check_up(tablero, row, col):
    if row == 0:
        return False
    elif tablero[row - 1][col] == 'T':
        return True
    return False

def check_left(tablero, row, col):
    if col == 0:
        return False
    elif 'T' == tablero[row][col - 1]:
        return True
    return False

def check_right(tablero, row, col):
    if col == len(tablero) - 1:
        return False
    elif 'T' == tablero[row][col + 1]:
        return True
    return False

def check_down(tablero: list, row: int, col: int) -> bool:
    if row == len(tablero) - 1:
        return False
    elif tablero[row + 1][col] == 'T':
        return True
    return False

def contar_bloques(indice: int, fila: list) -> int:
    """
    esta funcion cuenta los espacios libres ('-') para cado lado de una posicion especifica en una
    fila retorna la cantidad de bloques vacios
    """
    left_check, right_check = True, True  # busca checkear para cada lado del indice
    counter, index_step_right, index_step_left = 0, 1, 1
    # counter cuenta las invalidas, index_step dice la distancia del indice que revisamos
    while left_check or right_check:
        if left_check is True:
            # si vamos a checkear fuera de la lista o si vamos a
            # checkear una tortuga, la revision de ese lado termina
            # en cualquier otro caso le sumamos uno al contador y uno a la distancia para checkear
            if indice - index_step_left < 0 or fila[indice - index_step_left] == 'T':
                left_check = False
            else:
                index_step_left, counter = index_step_left + 1, counter + 1
        if right_check is True:
            # misma logica que left check
            if indice + index_step_right > len(fila) - 1 or fila[indice + index_step_right] == 'T':
                right_check = False
            else:
                index_step_right, counter = 1 + index_step_right, 1 + counter
    return counter

def cargar_tablero(nombre_archivo: str) -> list:
    """
    esta funcion se usa para leer un archivo (el nombre que se entrega debe incluir extension) y
    retorna una lista de lista que representa al tablero
    """
    dir_archivo = os.path.join('Archivos', nombre_archivo)
    with open(dir_archivo, 'r') as info_archivo:
        info_tablero = deque(info_archivo.readline().split(','))
    square_size = int(info_tablero.popleft())
    tablero = [[] for i in range(square_size)]
    for row in tablero:
        for i in range(square_size):
            row.append(info_tablero.popleft())
    return tablero

def guardar_tablero(nombre_archivo: str, tablero: list) -> None:
    """
    esta funcion recibe el tablero de juego y un nombre de archivo (extension incluida), no retorna
    nada pero crea un archivo en el directorio relativo Archivos/ con el sufijo '_sol'
    antes de la extension
    """
    dir_archivo = os.path.join('Archivos', nombre_archivo)
    with open(dir_archivo, 'w') as archivo_sol:
        tablero_size = str(len(tablero))
        data_list = [tablero_size]
        for row in tablero:
            for entry in row:
                data_list.append(entry)
        print(','.join(data_list), file=archivo_sol)

def verificar_valor_bombas(tablero: list) -> int:
    """
    esta funcion verfica si el valor de las bombas en el tablero es valido, o sea si se encuentra
    entre 2 y 2n - 1 con n siendo la dimension de la matriz (tablero), recible el tablero de juego
    retorna la cantidad de bombas invalidas
    """
    max_size = 2 * len(tablero) - 1
    invalid = 0
    for row in tablero:
        for entry in row:
            if entry.isnumeric():
                if not 2 <= int(entry) <= max_size:
                    invalid += 1
    return invalid

def verificar_alcance_bomba(tablero: list, coordenada: tuple) -> int:
    """
    verifica que rango esta cubriendo una bomba, o sea, la cantidad de
    bloques que tapa su explosion, usa la funcion 'contar_bloques'
    retorna el rango de la bomba en forma de int
    """
    coord_x = coordenada[0]
    coord_y = coordenada[1]
    if tablero[coord_x][coord_y].isnumeric():
        fila_tablero = tablero[coord_x]
        col_tablero = list()
        for index in range(len(tablero)):
            col_tablero.append(tablero[index][coord_y])
        bloques_fila = contar_bloques(coord_y, fila_tablero)
        bloques_col = contar_bloques(coord_x, col_tablero)
        return bloques_fila + bloques_col + 1
    else:
        return 0

def regla_1(tablero: list) -> bool:
    """
    verifica si se cumple la regla 1, retorna True si es que se cumple, False en cualquier otro caso
    """
    final = True
    for row in range(len(tablero)):
        for col in range(len(tablero)):
            if tablero[row][col].isnumeric():
                if int(tablero[row][col]) != verificar_alcance_bomba(tablero, (row, col)):
                    final = False
    return final

def regla_3(tablero: list) -> bool:
    """
    verificas si se cumple la regla 3, retorna True si es que se cumple, False en otro caso
    """
    final = True
    for row in range(len(tablero)):
        for col in range(len(tablero)):
            if 'T' in tablero[row][col] and len(tablero[row][col]) > 1:
                final = False
    return final

def verificar_una_celda(tablero: list, coord: tuple) -> bool:
    """
    verifica si las celdas arriba, abajo o a los lados de una celda en especifico son iguales,
    retorna True si no la rodea ninguna igual, False si es que si
    """
    up = check_up(tablero, coord[0], coord[1])
    down = check_down(tablero, coord[0], coord[1])
    left = check_left(tablero, coord[0], coord[1])
    right = check_right(tablero, coord[0], coord[1])
    answers = [up, down, left, right]
    if True in answers:
        return False
    return True

def verificar_tortugas(tablero: list) -> int:
    """
    verifica la cantidad de tortugas invalidas en el tablero, o sea, tortugas directamente arriba, a
    bajo o a los lados de otra tortuga, recibe el tablero de juego
    y retorna la cantidad de tortugas invalidas
    """
    invalid = 0
    for row_num in range(len(tablero)):
        for col_num in range(len(tablero)):
            if tablero[row_num][col_num] == 'T':
                answer = verificar_una_celda(tablero, (row_num, col_num))
                if answer is False:
                    invalid += 1
    return invalid

def completado(tablero: list) -> bool:
    """
    esta funcion determina si se estan cumpliendo las 4 reglas, retorna True si es que
    se cumplen, False para otro caso
    """
    regla_1_l = regla_1(tablero)
    regla_2 = verificar_valor_bombas(tablero)
    regla_3_l = regla_3(tablero)
    regla_4 = verificar_tortugas(tablero)
    if [regla_1_l, regla_2, regla_3_l, regla_4] == [True, 0, True, 0]:
        return True
    return False

def coordenadas(tablero: list) -> list:
    """
    retorna las coordenadas (en tuplas de la forma (num row, num col))
    en una lista de todas las bombas del tablero
    """
    coords = []
    for row in range(len(tablero)):
        for col in range(len(tablero)):
            if tablero[row][col].isnumeric():
                coords.append((row, col))
    return coords

def is_inside(tablero: list, posicion: tuple) -> bool:
    """
    verifica si una posicion esta dentro o fuera de un tablero, retorna False
    si es que esta afuera, True si es que esta adentro
    """
    if posicion[0] < 0 or posicion[0] >= len(tablero):
        return False
    if posicion[1] < 0 or posicion[1] >= len(tablero[0]):
        return False
    return True

def validar_rangos(tablero: list, coord: tuple, coord_list: list) -> bool:
    """
    revisa como afecta el ingreso de una tortuga a los rangos de las bombas en
    la columna y fila afectada, retorna True si es que los rangos se mantienen
    mayores o iguales al numero de las bombas, False si alguna bomba queda
    con menos rango de lo que deberia
    """
    new_tablero = [[item for item in tablero[i]] for i in range(len(tablero))]
    new_tablero[coord[0]][coord[1]] = 'T'
    for entry in coord_list:
        if entry[0] == coord[0]:
            if verificar_alcance_bomba(tablero, entry) < int(tablero[entry[0]][entry[1]]):
                return False
        if entry[1] == coord[1]:
            if verificar_alcance_bomba(tablero, entry) < int(tablero[entry[0]][entry[1]]):
                return False
    return True

def validar_poner_tor(tablero: list, coord: tuple, coord_list: list) -> bool:
    """
    esta funcion verifica si es posible poner una tortuga en una celda especifica, basandose en las
    reglas definidas anteriormente.
    Retorna True si es posible poner la tortuga, False en otro caso
    """
    if is_inside(tablero, coord) is False:
        return False
    if tablero[coord[0]][coord[1]].isnumeric() or tablero[coord[0]][coord[1]] == 'T':
        return False
    if verificar_una_celda(tablero, coord) is False:
        return False
    if validar_rangos(tablero, coord, coord_list) is False:
        return False
    return True

def solucionar_tablero(tablero: list) -> list:
    """
    esta funcion soluciona el tablero mediante un algoritmo de backtracking ,
    retorna el tablero (lista de listas) resuelto con tortugas en lugares correctos
    """
    if completado(tablero) is True:
        return tablero
    bomb_coord_list = coordenadas(tablero)
    for row in range(len(tablero)):
        for col in range(len(tablero)):
            if tablero[row][col] == '-':
                if validar_poner_tor(tablero, (row, col), bomb_coord_list):
                    tablero[row][col] = 'T'
                    sol = solucionar_tablero(tablero)
                    if sol is not None:
                        return sol
                    tablero[row][col] = '-'


# Written by Cameron Haddock
# Written as a solution for Advent of Code 2015

# https://adventofcode.com/2015/day/2

sum_paper,sum_ribbon = 0,0
with open('2015/02/input.txt') as f:
    for line in f:
        dim = line.strip().split('x')
        dim = tuple(map(lambda x: int(x),dim))
        sum_paper += 2 * (dim[0]*dim[1] + dim[1]*dim[2] + dim[2]*dim[0]) + min(dim[0]*dim[1],dim[1]*dim[2],dim[2]*dim[0])
        sum_ribbon += 2* min(dim[0]+dim[1],dim[1]+dim[2],dim[2]+dim[0]) + dim[0]*dim[1]*dim[2]

print('The elves will need {} sq. feet of wrapping paper and {} feet of ribbon.'.format(sum_paper,sum_ribbon))


# Given an array nums of size n, return the majority element.

# The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.

# Example 1:

# Input: nums = [3,2,3]
# Output: 3
# Example 2:

# Input: nums = [2,2,1,1,1,2,2]
# Output: 2

# Constraints:

# n == nums.length
# 1 <= n <= 5 * 104
# -231 <= nums[i] <= 231 - 1
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        mp = {}
        for i in nums:
            if i not in mp.keys():
                mp[i] = 1
            else:
                mp[i] += 1
        return max(mp, key=mp.get)


import logging
from qt_core import *
from ..my_combobox import MYCombobox
config_logging(logging, logging.DEBUG)

class OrderCreationWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def create_order_type_widget(self):
        widget = QWidget(self)
        layout = QVBoxLayout(widget)

        btn_grp_buy_sell = QButtonGroup(self)

        radio_buy = QRadioButton("Buy")
        radio_buy.setStyleSheet("QRadioButton { color: #55AA69; }")
        radio_sell = QRadioButton("Sell")
        radio_sell.setStyleSheet("QRadioButton { color: #B93446; }")

        # Add buttons to button group
        btn_grp_buy_sell.addButton(radio_buy)
        btn_grp_buy_sell.addButton(radio_sell)

        radio_buy.setChecked(True)

        # Radio buttons for order type: Limit, Market, Stop
        radio_limit = QRadioButton("Limit")
        radio_market = QRadioButton("Market")
        radio_stop = QRadioButton("Stop")
        # setup radio buttons... (omitted for brevity)

        layout.addWidget(btn_buy)
        layout.addWidget(btn_sell)
        layout.addWidget(radio_limit)
        layout.addWidget(radio_market)
        layout.addWidget(radio_stop)

        combo = MYCombobox()
        combo.addItem("BTCUSDT")
        combo.addItem("ETHUSDT")
        layout.addWidget(combo)

        return widget, layout

    def init_ui(self):
        # Layout
        layout = QVBoxLayout()

        # 폰트 설정
        font = QFont()
        font.setPointSize(13)
        font.setBold(True)

        self.stacked_widget = QStackedWidget(self)
        # Create a Spot widget
        self.spot_widget = QWidget(self)
        self.spot_layout = QVBoxLayout(self.spot_widget)
        # Add additional Spot-specific UI elements to self.spot_layout if needed

        # Create a Futures widget
        self.futures_widget = QWidget(self)
        self.futures_layout = QVBoxLayout(self.futures_widget)
        # Add additional Futures-specific UI elements to self.futures_layout if needed

        # Add widgets to the stacked widget
        self.stacked_widget.addWidget(self.spot_widget)
        self.stacked_widget.addWidget(self.futures_widget)

        # Tab widget to switch between Spot and Futures
        self.tab_widget = QTabWidget(self)
        self.tab_widget.addTab(self.spot_widget, "Spot")
        self.tab_widget.addTab(self.futures_widget, "Futures")
        self.tab_widget.setStyleSheet("""
            QWidget {
            background-color: #343b48;
            color: #8a95aa;
            }
            QTabWidget::pane {
                background-color: #343b48;
            }
            QTabBar::tab {
                background-color: #4a5360;
                color: #8a95aa;
                width: 80px; /* Tab width */
                height: 30px; /* Tab height */
                font-size: 13px; /* Font size */
            }
            QTabBar::tab:selected {
                background-color: #343b48;
                color: #8a95aa;
            }
        """)

        # Combobox for choosing Ticker
        self.spot_combo = MYCombobox()
        self.futures_combo = MYCombobox()
        self.spot_combo.addItem("BTCUSDT")
        self.spot_combo.addItem("ETHUSDT")
        self.futures_combo.addItem("BTCUSDT")
        self.futures_combo.addItem("ETHUSDT")

        # Add comboboxes to the respective layouts
        self.spot_layout.addWidget(self.spot_combo)
        self.futures_layout.addWidget(self.futures_combo)

        # Horizontal layout for Spot radio button and combobox
        layout.addWidget(self.tab_widget)

        # Buy/Sell buttons with color toggle on press

        style_sheet_radio = """
        QRadioButton {
            font: bold 15px;
            color: #ffffff;
            padding: 10px;
        }
        QRadioButton::indicator {
            width: 20px;
            height: 20px;
            border-radius: 7px;
            background: #c3ccdf;
        }
        QRadioButton::indicator:checked {
            background-color: #0075FF;
        }
        """
        # 4.1.1 Buy 및 Sell 버튼 Here
        self.btn_grp_buy_sell = QButtonGroup(self)
        self.radio_buy = QRadioButton("Buy")
        self.radio_buy.setStyleSheet(style_sheet_radio)
        self.radio_sell = QRadioButton("Sell")
        self.radio_sell.setStyleSheet(style_sheet_radio)
        self.btn_grp_buy_sell.addButton(self.radio_buy)
        self.btn_grp_buy_sell.addButton(self.radio_sell)
        self.radio_buy.setChecked(True)
        # 4.1.2 Buy 및 Sell 버튼 Layout 추가
        self.hlayout_buy_sell = QHBoxLayout()
        self.hlayout_buy_sell.addWidget(self.radio_buy)
        self.hlayout_buy_sell.addWidget(self.radio_sell)
        self.futures_layout.addLayout(self.hlayout_buy_sell)

        # 4.2.1 Limit, Market, Stop 버튼 Here
        self.btn_grp_order = QButtonGroup(self)
        self.radio_limit = QRadioButton("Limit")
        self.radio_limit.setStyleSheet(style_sheet_radio)
        self.radio_market = QRadioButton("Market")
        self.radio_market.setStyleSheet(style_sheet_radio)
        self.radio_stop = QRadioButton("Stop")
        self.radio_stop.setStyleSheet(style_sheet_radio)
        self.btn_grp_order.addButton(self.radio_limit)
        self.btn_grp_order.addButton(self.radio_market)
        self.btn_grp_order.addButton(self.radio_stop)
        self.radio_limit.setChecked(True)
        # 4.2.2 Limit, Market, Stop 버튼 Layout 추가
        self.hlayout_limit_market_stop = QHBoxLayout()
        self.hlayout_limit_market_stop.addWidget(self.radio_limit)
        self.hlayout_limit_market_stop.addWidget(self.radio_market)
        self.hlayout_limit_market_stop.addWidget(self.radio_stop)
        self.futures_layout.addLayout(self.hlayout_limit_market_stop)

        # 4.3.1 입력필드 Here
        self.lbl_price = QLabel("Price:")
        self.input_price = QLineEdit(self)
        self.lbl_qty = QLabel("Quantity:")
        self.input_qty = QLineEdit(self)
        self.lbl_stop_price = QLabel("Stop Price:")
        self.input_stop_price = QLineEdit(self)
        # 4.3.2 슬라이더 입력 Here
        self.slider = QSlider(Qt.Horizontal)
        self.lbl_slider_value = QLabel("0%")
        self.slider.valueChanged.connect(lambda: self.lbl_slider_value.setText(f"{self.slider.value()}%"))
        # 4.3.3 Excute Order 버튼 Here
        self.btn_execute_order = QPushButton("Execute Order", self)
        self.btn_execute_order.clicked.connect(self.place_order)

        grid = QGridLayout()
        grid.addWidget(self.lbl_price, 0, 0)
        grid.addWidget(self.input_price, 0, 1)
        grid.addWidget(self.lbl_qty, 1, 0)
        grid.addWidget(self.input_qty, 1, 1)
        grid.addWidget(self.lbl_stop_price, 2, 0)
        grid.addWidget(self.input_stop_price, 2, 1)

        self.futures_layout.addLayout(grid)
        self.futures_layout.addWidget(self.slider)
        self.futures_layout.addWidget(self.lbl_slider_value)
        self.futures_layout.addWidget(self.btn_execute_order)

        # Frame for grouping
        frame = QFrame()
        frame.setLayout(layout)
        main_layout = QVBoxLayout(self)
        main_layout.addWidget(frame)

        # Events
        self.radio_limit.toggled.connect(self.update_input_fields_visibility)
        self.radio_market.toggled.connect(self.update_input_fields_visibility)
        self.radio_stop.toggled.connect(self.update_input_fields_visibility)
        self.update_input_fields_visibility()

        self.lbl_binance_input = QLabel("Binance Input Parameters:\n")

        self.futures_layout.addWidget(self.lbl_binance_input)

        # Connect signals to update lbl_binance_input
        self.radio_buy.toggled.connect(self.update_binance_input)
        self.radio_sell.toggled.connect(self.update_binance_input)
        self.radio_limit.toggled.connect(self.update_binance_input)
        self.radio_market.toggled.connect(self.update_binance_input)
        self.radio_stop.toggled.connect(self.update_binance_input)
        self.input_price.textChanged.connect(self.update_binance_input)
        self.input_qty.textChanged.connect(self.update_binance_input)
        self.input_stop_price.textChanged.connect(self.update_binance_input)

        # If you had some initial default values, you might want to call update_binance_input once at the end of your init to populate lbl_binance_input
        self.update_binance_input()

    def update_binance_input(self):
        symbol = "YOUR_SYMBOL_HERE"  # Replace this with your actual symbol
        side = "BUY" if self.radio_buy.isChecked() else "SELL"
        order_type = "LIMIT" if self.radio_limit.isChecked() else ("MARKET" if self.radio_market.isChecked() else "STOP")
        price = self.input_price.text()
        quantity = self.input_qty.text()
        stop_price = self.input_stop_price.text()
        binance_input = f"Symbol: {symbol}\nSide: {side}\nType: {order_type}\nPrice: {price}\nQuantity: {quantity}\nStop Price: {stop_price}"
        self.lbl_binance_input.setText(binance_input)

    def update_input_fields_visibility(self):
        """Hide/show input fields based on order type"""
        self.input_price.setVisible(self.radio_limit.isChecked() or self.radio_stop.isChecked())
        self.lbl_price.setVisible(self.radio_limit.isChecked() or self.radio_stop.isChecked())
        self.input_stop_price.setVisible(self.radio_stop.isChecked())
        self.lbl_stop_price.setVisible(self.radio_stop.isChecked())

    def place_order(self):
        if self.btn_buy.isChecked():
            order_type = "BUY"
        elif self.btn_sell.isChecked():
            order_type = "SELL"
        else:
            # Neither button selected, show an error or return without doing anything
            QMessageBox.warning(self, "Warning", "Please select either Buy or Sell!")
            return
        if self.sender() == self.btn_buy:
            order_type = "BUY"
        else:
            order_type = "SELL"

        if self.radio_limit.isChecked():
            order_method = "LIMIT"
        elif self.radio_market.isChecked():
            order_method = "MARKET"
        else:
            order_method = "STOP"

        # Collect common order parameters
        order_params = {
            "symbol": self.combo_ticker.currentText(),
            "side": order_type,
            "type": order_method,
            "quantity": float(self.input_qty.text()),
            "timeInForce": "GTC",
        }

        # Add price if relevant based on order method
        if self.input_price.isVisible():
            order_params["price"] = float(self.input_price.text())

        try:
            if self.tab_widget.currentIndex() == 1:  # If Futures tab is active
                # Place a futures order
                response = UMFutures.new_order(**order_params)
            else:  # Default to Spot if no tab or the first tab is active
                # Place a spot order
                response = Spot.new_order(**order_params)

            logging.info(response)

        except ClientError as error:
            logging.error(
                "Found error. status: {}, error code: {}, error message: {}".format(
                    error.status_code, error.error_code, error.error_message
                )
            )


"""
Tests for intensity combination.
"""

from __future__ import annotations

from unittest.mock import Mock

import pytest

from dxtbx.model import Crystal, Experiment

from dials.algorithms.scaling.combine_intensities import (
    MultiDatasetIntensityCombiner,
    SingleDatasetIntensityCombiner,
    combine_intensities,
)
from dials.algorithms.scaling.scaling_utilities import calculate_prescaling_correction
from dials.array_family import flex

@pytest.fixture(scope="module")
def test_exp_P1():
    """Create a mock experiments object."""
    exp = Experiment()
    exp_dict = {
        "__id__": "crystal",
        "real_space_a": [1.0, 0.0, 0.0],
        "real_space_b": [0.0, 1.0, 0.0],
        "real_space_c": [0.0, 0.0, 1.0],
        "space_group_hall_symbol": " P 1",
    }
    crystal = Crystal.from_dict(exp_dict)
    exp.crystal = crystal
    return exp

def generate_simple_table(prf=True):
    """Generate a reflection table for testing intensity combination.
    The numbers are contrived to make sum intensities agree well at high
    intensity but terribly at low and vice versa for profile intensities."""
    reflections = flex.reflection_table()
    reflections["miller_index"] = flex.miller_index(
        [
            (0, 0, 1),
            (0, 0, 1),
            (0, 0, 1),
            (0, 0, 1),
            (0, 0, 1),
            (0, 0, 2),
            (0, 0, 2),
            (0, 0, 2),
            (0, 0, 2),
            (0, 0, 2),
            (0, 0, 3),
            (0, 0, 3),
            (0, 0, 3),
            (0, 0, 3),
            (0, 0, 3),
            (0, 0, 4),
            (0, 0, 4),
            (0, 0, 4),
            (0, 0, 4),
            (0, 0, 4),
            (0, 0, 5),
            (0, 0, 5),
            (0, 0, 5),
            (0, 0, 5),
            (0, 0, 5),
        ]
    )
    reflections["inverse_scale_factor"] = flex.double(25, 1.0)
    # Contrive an example that should give the best cc12 when combined.
    # make sum intensities agree well at high intensity but terribly at low
    # and vice versa for profile intensities.
    # profile less consistent at high intensity here

    # sumless consistent at low intensity here
    reflections["intensity.sum.value"] = flex.double(
        [
            10000.0,
            11000.0,
            9000.0,
            8000.0,
            12000.0,
            500.0,
            5600.0,
            5500.0,
            2000.0,
            6000.0,
            100.0,
            50.0,
            150.0,
            75.0,
            125.0,
            30.0,
            10.0,
            2.0,
            35.0,
            79.0,
            1.0,
            10.0,
            20.0,
            10.0,
            5.0,
        ]
    )
    reflections["intensity.sum.variance"] = flex.double(
        [10000] * 5 + [5000] * 5 + [100] * 5 + [30] * 5 + [10] * 5
    )
    reflections.set_flags(flex.bool(25, False), reflections.flags.outlier_in_scaling)
    reflections.set_flags(flex.bool(25, True), reflections.flags.integrated)
    reflections["lp"] = flex.double(25, 0.5)
    if prf:
        reflections["intensity.prf.value"] = flex.double(
            [
                10000.0,
                16000.0,
                12000.0,
                6000.0,
                9000.0,
                5000.0,
                2000.0,
                1500.0,
                1300.0,
                9000.0,
                100.0,
                80.0,
                120.0,
                90.0,
                100.0,
                30.0,
                40.0,
                50.0,
                30.0,
                30.0,
                10.0,
                12.0,
                9.0,
                8.0,
                10.0,
            ]
        )
        reflections["intensity.prf.variance"] = flex.double(
            [1000] * 5 + [500] * 5 + [10] * 5 + [3] * 5 + [1] * 5
        )
    reflections = calculate_prescaling_correction(reflections)
    return reflections

def test_combine_intensities_prf_sum(test_exp_P1):
    reflections = flex.reflection_table()

    reflections["intensity.sum.value"] = flex.double([100.0, 100.0, 100.0, 100.0])
    reflections["intensity.prf.value"] = flex.double([200.0, 200.0, 200.0, 200.0])
    reflections["intensity.sum.variance"] = flex.double(4, 100)
    reflections["intensity.prf.variance"] = flex.double(4, 200)
    reflections["prescaling_correction"] = flex.double(4, 1.0)
    reflections.set_flags(
        flex.bool([False, False, True, True]), reflections.flags.integrated_prf
    )
    reflections.set_flags(
        flex.bool([True, False, False, True]), reflections.flags.integrated_sum
    )

    intensities, _ = combine_intensities(reflections, Imid=100.0)
    # if prf not successful - set as sum. Only last refl should be combined here.
    assert list(intensities) == [100.0, 100.0, 200.0, 150.0]

def test_combine_intensities(test_exp_P1):
    """Test the combine intensities function for a single dataset"""
    reflections = generate_simple_table()
    scaler = Mock()
    scaler.reflection_table = reflections
    scaler.suitable_refl_for_scaling_sel = flex.bool(reflections.size(), True)
    scaler.outliers = flex.bool(reflections.size(), False)
    scaler.free_set_selection = flex.bool(reflections.size(), False)
    scaler.experiment = test_exp_P1
    scaler.params.reflection_selection.combine.Imid = None

    combiner = SingleDatasetIntensityCombiner(scaler)
    Imid = combiner.max_key
    intensity, variance = combiner.calculate_suitable_combined_intensities()

    # Imid being 1200.0 should be best for this contrived example
    assert Imid == 1200.0

    # Due to nature of crossover, just require 2% tolerance for this example
    assert list(intensity[0:5]) == pytest.approx(
        list(
            reflections["intensity.sum.value"][0:5]
            * reflections["prescaling_correction"][0:5]
        ),
        rel=2e-2,
    )
    assert list(intensity[20:25]) == pytest.approx(
        list(
            reflections["intensity.prf.value"][20:25]
            * reflections["prescaling_correction"][20:25]
        ),
        rel=2e-2,
    )

    assert list(variance[0:5]) == pytest.approx(
        list(
            reflections["intensity.sum.variance"][0:5]
            * flex.pow2(reflections["prescaling_correction"][0:5])
        ),
        rel=2e-2,
    )
    assert list(variance[20:25]) == pytest.approx(
        list(
            reflections["intensity.prf.variance"][20:25]
            * flex.pow2(reflections["prescaling_correction"][20:25])
        ),
        rel=2e-2,
    )

    combiner.max_key = 0  # prf
    intensity, variance = combiner.calculate_suitable_combined_intensities()
    assert list(intensity) == pytest.approx(
        list(reflections["intensity.prf.value"] * reflections["prescaling_correction"]),
        rel=2e-2,
    )
    assert list(variance) == pytest.approx(
        list(
            reflections["intensity.prf.variance"]
            * flex.pow2(reflections["prescaling_correction"])
        ),
        rel=2e-2,
    )

    combiner.max_key = 1  # sum
    intensity, variance = combiner.calculate_suitable_combined_intensities()
    assert list(intensity) == pytest.approx(
        list(reflections["intensity.sum.value"] * reflections["prescaling_correction"]),
        rel=2e-2,
    )
    assert list(variance) == pytest.approx(
        list(
            reflections["intensity.sum.variance"]
            * flex.pow2(reflections["prescaling_correction"])
        ),
        rel=2e-2,
    )

def test_combine_intensities_multi_dataset(test_exp_P1):
    """Test the combine intensities function for multiple datasets"""
    r1 = generate_simple_table()
    r1["partiality"] = flex.double(25, 1.0)
    r2 = generate_simple_table(prf=False)
    scaler1 = Mock()
    scaler1.reflection_table = r1
    scaler1.suitable_refl_for_scaling_sel = flex.bool(r1.size(), True)
    scaler1.outliers = flex.bool(r1.size(), False)
    scaler1.free_set_selection = flex.bool(r1.size(), False)
    scaler1.experiment = test_exp_P1
    scaler1.params.reflection_selection.combine.Imid = None
    scaler2 = Mock()
    scaler2.reflection_table = r2
    scaler2.suitable_refl_for_scaling_sel = flex.bool(r2.size(), True)
    scaler2.outliers = flex.bool(r2.size(), False)
    scaler2.free_set_selection = flex.bool(r2.size(), False)
    scaler2.experiment = test_exp_P1
    scaler2.params.reflection_selection.combine.Imid = None

    multiscaler = Mock()
    multiscaler.active_scalers = [scaler1, scaler2]
    multiscaler.experiment = test_exp_P1
    multiscaler.params.reflection_selection.combine.Imid = None

    combiner = MultiDatasetIntensityCombiner(multiscaler)
    Imid = combiner.max_key

    assert pytest.approx(Imid) == 1200.0


#importing modules

import wikipedia
#first you have to install wikipedia module as it is not in-built
import warnings
#warning is in-built module
#this module in not important for this program
#this module hide warning from module, if occurs

# initializing a function
def WikipediaSearch(a):

    #try and except hideing errors, if occurs
    try:
        warnings.filterwarnings("ignore")
        result = wikipedia.summary(a, sentences = 3)
        return(result)

    except Exception as e:
        print(a,"is unable to find easily.There are many ",a,"which one do you want to find...")
        return(e)


'''
AP Poker, written in Python.
'''
from skeleton.actions import FoldAction, CallAction, CheckAction, RaiseAction, AssignAction
from skeleton.states import GameState, TerminalState, RoundState, BoardState
from skeleton.states import NUM_ROUNDS, STARTING_STACK, BIG_BLIND, SMALL_BLIND, NUM_BOARDS
from skeleton.bot import Bot
from skeleton.runner import parse_args, run_bot

import eval7
import random

class Player(Bot):
    '''
    A pokerbot.
    '''

    def __init__(self):
        '''
        Called when a new game starts. Called exactly once.

        Arguments:
        Nothing.

        Returns:
        Nothing.
        '''
        self.allocations = [[], [], []]
        self.hole_strengths = [0, 0, 0]
        self.MONTE_CARLO_ITERS = 100 # the number of Monte Carlo samples we will use

    def rank_to_numeric(self, rank):
        if rank.isnumeric(): # 2-9
            return int(rank)
        elif rank == 'T': # 10 is T, so we need to specify it here
            return 10
        elif rank == 'J': # Face cards for the rest of them
            return 11
        elif rank == 'Q':
            return 12
        elif rank == 'K':
            return 13
        else: # Ace (A) is the only one left
            return 14

    def sort_cards_by_rank(self, cards):
        return sorted(cards, reverse = True, key = lambda x: self.rank_to_numeric(x[0])) # we want it in descending order

    def calculate_strength(self, hole, iters):
        '''
        A Monte Carlo method meant to estimate the win probability of a pair of
        hole cards. Simlulates 'iters' games and determines the win rates of our cards

        Arguments:
        hole: a list of our two hole cards
        iters: a integer that determines how many Monte Carlo samples to take

        Returns: win probability, expressed as a float between 0 and 1
        '''

        deck = eval7.Deck() # eval7 object!
        hole_cards = [eval7.Card(card) for card in hole] # card objects, used to evaliate hands

        for card in hole_cards: # remove cards that we know about! they shouldn't come up in simulations
            deck.cards.remove(card)

        score = 0

        for _ in range(iters): # take 'iters' samples
            deck.shuffle() # make sure our samples are random

            _COMM = 5 # the number of cards we need to draw
            _OPP = 2

            draw = deck.peek(_COMM + _OPP)

            opp_hole = draw[: _OPP]
            community = draw[_OPP: ]

            our_hand = hole_cards + community # the two showdown hands
            opp_hand = opp_hole + community

            our_hand_value = eval7.evaluate(our_hand) # the ranks of our hands (only useful for comparisons)
            opp_hand_value = eval7.evaluate(opp_hand)

            if our_hand_value > opp_hand_value: # we win!
                score += 2

            elif our_hand_value == opp_hand_value: # we tie.
                score += 1

            else: # we lost...
                score += 0

        hand_strength = score / (2 * iters) #this is our win probability!

        return hand_strength

    def allocate_cards(self, my_cards):
        '''
        Allocates cards by mutating passing in self.allocations as my_cards and mutating it

        Strategy: Allocate pairs together and assign to biggest board; next pair suits of singles
            otherwise, and sort any remaining singles by rank.

        Arguments:
        my_cards

        Returns:
        Nothing.
        '''

        ranks = {}
        suits = {}

        for card in my_cards:
            card_rank = card[0]
            card_suit = card[1]

            if card_rank in ranks: # if card with same rank already seen
                ranks[card_rank].append(card)

            else: # map card_rank to new list containing current card
                ranks[card_rank] = [card]

            if card_suit in suits:
                suits[card_suit].append(card)

            else:
                suits[card_suit] = [card]

        singles = []
        pairs = []
        thirds = []

        for rank in ranks:
            cards = ranks[rank]

            if len(cards) == 2:
                pairs += cards

            elif len(cards) == 3: # TODO sort by number of suit repetitions
                suit_drawn = []
                suit_undrawn = []

                for card in cards:
                    if len(suits[card[1]]) > 1:
                        suit_drawn.append(card)
                    else:
                        suit_undrawn.append(card)

                ordered_cards = suit_drawn + suit_undrawn
                thirds.append(ordered_cards[0]) # set aside to put at lowest board
                pairs += ordered_cards[1], ordered_cards[2]

            elif len(cards) == 4: # TODO sort by number of suit repetitions
                suit_drawn = []
                suit_undrawn = []

                for card in cards:
                    if len(suits[card[1]]) > 1:
                        suit_drawn.append(card)
                    else:
                        suit_undrawn.append(card)

                pairs += suit_drawn + suit_undrawn # if suit drawn, less prob of a flush so put first

            else: # single
                singles += cards

        ordered_ranks = sorted([card[0] for card in singles])
        ordered_singles = thirds # copy thirds at beginning of list

        while singles:
            for i in range(len(singles)):
                if singles[i][0] == ordered_ranks[0]:
                    ordered_ranks.pop(0)
                    ordered_singles.append(singles.pop(i)) # remove from list and append to ordered_singles
                    break # stop looping, otherwise will raise IndexError because of pop

        if len(pairs) > 0:
            self.strong_hole = True

        combined_allocation = ordered_singles + pairs # strongest hands at end

        for i in range(NUM_BOARDS):
            hand = [combined_allocation[2*i], combined_allocation[2*i + 1]]
            self.allocations[i] = hand

    def assign_holes(self, hole_cards):

        holes_and_strengths = [] # keep track of holes and their strengths

        for hole in hole_cards:
            strength = self.calculate_strength(hole, self.MONTE_CARLO_ITERS) # use our monte carlo sim!
            holes_and_strengths.append((hole, strength))

        holes_and_strengths = sorted(holes_and_strengths, key=lambda x: x[1]) # sort them by strength

        if random.random() < 0.15: # swap strongest with second, makes our strategy non-deterministic! TODO calculate Nash?
            temp = holes_and_strengths[2]
            holes_and_strengths[2] = holes_and_strengths[1]
            holes_and_strengths[1] = temp

        if random.random() < 0.15: # swap second with last, makes us even more random
            temp = holes_and_strengths[1]
            holes_and_strengths[1] = holes_and_strengths[0]
            holes_and_strengths[0] = temp

        for i in range(NUM_BOARDS): # we have our final board allocations!
            self.allocations[i] = holes_and_strengths[i][0]
            self.hole_strengths[i] = holes_and_strengths[i][1]

    def handle_new_round(self, game_state, round_state, active):
        '''
        Called when a new round starts. Called NUM_ROUNDS times.

        Arguments:
        game_state: the GameState object.
        round_state: the RoundState object.
        active: your player's index.

        Returns:
        Nothing.
        '''
        my_bankroll = game_state.bankroll  # the total number of chips you've gained or lost from the beginning of the game to the start of this round
        opp_bankroll = game_state.opp_bankroll # ^but for your opponent
        game_clock = game_state.game_clock  # the total number of seconds your bot has left to play this game
        round_num = game_state.round_num  # the round number from 1 to NUM_ROUNDS
        my_cards = round_state.hands[active]  # your six cards at teh start of the round
        big_blind = bool(active)  # True if you are the big blind

        allocated_holes = self.allocate_cards(my_cards)
        self.allocate_cards(my_cards)

    def handle_round_over(self, game_state, terminal_state, active):
        '''
        Called when a round ends. Called NUM_ROUNDS times.

        Arguments:
        game_state: the GameState object.
        terminal_state: the TerminalState object.
        active: your player's index.

        Returns:
        Nothing.
        '''
        my_delta = terminal_state.deltas[active]  # your bankroll change from this round
        opp_delta = terminal_state.deltas[1-active] # your opponent's bankroll change from this round
        previous_state = terminal_state.previous_state  # RoundState before payoffs
        street = previous_state.street  # 0, 3, 4, or 5 representing when this round ended
        for terminal_board_state in previous_state.board_states:
            previous_board_state = terminal_board_state.previous_state
            my_cards = previous_board_state.hands[active]  # your cards
            opp_cards = previous_board_state.hands[1-active]  # opponent's cards or [] if not revealed

        self.allocations = [[], [], []]
        self.strong_hole = False

        game_clock = game_state.game_clock # check how much time we have remaining at the end of a game
        round_num = game_state.round_num # Monte Carlo takes a lot of time, we use this to adjust!
        if round_num == NUM_ROUNDS:
            print(game_clock)

    def get_actions(self, game_state, round_state, active):
        '''
        Where the magic happens - your code should implement this function.
        Called any time the engine needs a triplet of actions from your bot.

        Arguments:
        game_state: the GameState object.
        round_state: the RoundState object.
        active: your player's index.

        Returns:
        Your actions.
        '''
        legal_actions = round_state.legal_actions()  # the actions you are allowed to take
        street = round_state.street  # 0, 3, 4, or 5 representing pre-flop, flop, turn, or river respectively
        my_cards = round_state.hands[active]  # your cards across all boards
        board_cards = [board_state.deck if isinstance(board_state, BoardState) else board_state.previous_state.deck for board_state in round_state.board_states] # the board cards
        my_pips = [board_state.pips[active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips you have contributed to the pot on each board this round of betting
        opp_pips = [board_state.pips[1-active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips your opponent has contributed to the pot on each board this round of betting
        continue_cost = [opp_pips[i] - my_pips[i] for i in range(NUM_BOARDS)] #the number of chips needed to stay in each board's pot
        my_stack = round_state.stacks[active]  # the number of chips you have remaining
        opp_stack = round_state.stacks[1-active]  # the number of chips your opponent has remaining
        stacks = [my_stack, opp_stack]
        net_upper_raise_bound = round_state.raise_bounds()[1] # max raise across 3 boards
        net_cost = 0 # keep track of the net additional amount you are spending across boards this round

        my_actions = [None] * NUM_BOARDS # initializing [None, None, None]
        for i in range(NUM_BOARDS):
            if AssignAction in legal_actions[i]:
                cards = self.allocations[i] # assign our cards that we made earlier
                my_actions[i] = AssignAction(cards) # add to our actions

            elif isinstance(round_state.board_states[i], TerminalState): #make sure the game isn't over at this board
                my_actions[i] = CheckAction() #check if it is

            else: #do we add more resources?
                board_cont_cost = continue_cost[i] #we need to pay this to keep playing
                board_total = round_state.board_states[i].pot #amount before we started betting
                pot_total = my_pips[i] + opp_pips[i] + board_total #total money in the pot right now
                min_raise, max_raise = round_state.board_states[i].raise_bounds(active, round_state.stacks)
                strength = self.hole_strengths[i]

                if street < 3: #pre-flop
                    raise_ammount = int(my_pips[i] + board_cont_cost + 0.4 * (pot_total + board_cont_cost)) #play a little conservatively pre-flop
                else:
                    raise_ammount = int(my_pips[i] + board_cont_cost + 0.75 * (pot_total + board_cont_cost)) #raise the stakes deeper into the game

                raise_ammount = max([min_raise, raise_ammount]) #make sure we have a valid raise
                raise_ammount = min([max_raise, raise_ammount])

                raise_cost = raise_ammount - my_pips[i] #how much it costs to make that raise

                if RaiseAction in legal_actions[i] and (raise_cost <= my_stack - net_cost): #raise if we can and if we can afford it
                    commit_action = RaiseAction(raise_ammount)
                    commit_cost = raise_cost

                elif CallAction in legal_actions[i] and (board_cont_cost <= my_stack - net_cost): #call if we can afford it!
                    commit_action = CallAction()
                    commit_cost = board_cont_cost #the cost to call is board_cont_cost

                elif CheckAction in legal_actions[i]: #try to check if we can
                    commit_action = CheckAction()
                    commit_cost = 0

                else: #we have to fold
                    commit_action = FoldAction()
                    commit_cost = 0

                if board_cont_cost > 0: #our opp raised!!! we must respond

                    if board_cont_cost > 5: #<--- parameters to tweak.
                        _INTIMIDATION = 0.15
                        strength = max([0, strength - _INTIMIDATION]) #if our opp raises a lot, be cautious!

                    pot_odds = board_cont_cost / (pot_total + board_cont_cost)

                    if strength >= pot_odds: #Positive Expected Value!! at least call!!

                        if strength > 0.5 and random.random() < strength: #raise sometimes, more likely if our hand is strong
                            my_actions[i] = commit_action
                            net_cost += commit_cost

                        else: # try to call if we don't raise
                            if (board_cont_cost <= my_stack - net_cost): #we call because we can afford it and it's +EV
                                my_actions[i] = CallAction()
                                net_cost += board_cont_cost

                            else: #we can't afford to call :(  should have managed our stack better
                                my_actions[i] = FoldAction()
                                net_cost += 0

                    else: #Negative Expected Value!!! FOLD!!!
                        my_actions[i] = FoldAction()
                        net_cost += 0

                else: #board_cont_cost == 0, we control the action

                    if random.random() < strength: #raise sometimes, more likely if our hand is strong
                        my_actions[i] = commit_action
                        net_cost += commit_cost

                    else: #just check otherwise
                        my_actions[i] = CheckAction()
                        net_cost += 0

        return my_actions

if __name__ == '__main__':
    run_bot(Player(), parse_args())


#coding:utf-8
import numpy as np
import matplotlib.pyplot as plt

def plot1():
    xData = np.arange(0, 10, 1)
    yData1 = xData.__pow__(2.0)
    yData2 = np.arange(15, 61, 5)
    plt.figure(num=1, figsize=(8, 6))
    plt.title('Plot 1', size=14)
    plt.xlabel('x-axis', size=14)
    plt.ylabel('y-axis', size=14)
    plt.plot(xData, yData1, color='b', linestyle='--', marker='o', label='y1 data')
    plt.plot(xData, yData2, color='r', linestyle='-', label='y2 data')
    plt.legend(loc='upper left')
    # plt.savefig('plot1.png', format='png')
    plt.show()

def plot2():
    mu = 0.0
    sigma = 2.0
    samples = np.random.normal(loc=mu, scale=sigma, size=1000)
    plt.figure(num=1, figsize=(8, 6))
    plt.title('Plot 2', size=14)
    plt.xlabel('value', size=14)
    plt.ylabel('counts', size=14)
    plt.hist(samples, bins=40, range=(-10, 10))
    plt.text(-9, 100, r'$\mu$ = 0.0, $\sigma$ = 2.0', size=16)
    # plt.savefig('images/plot2.png', format='png')
    plt.show();

def plot3():
    data = [33, 25, 20, 12, 10]
    plt.figure(num=1, figsize=(6, 6))
    plt.axes(aspect=1)
    plt.title('Plot 3', size=14)
    plt.pie(data, labels=('Group 1', 'Group 2', 'Group 3', 'Group 4', 'Group 5'))
    # plt.savefig('images/plot3.png', format='png')
    plt.show()

def align_yaxis(ax1, v1, ax2, v2):
    """adjust ax2 ylimit so that v2 in ax2 is aligned to v1 in ax1"""
    _, y1 = ax1.transData.transform((0, v1))
    _, y2 = ax2.transData.transform((0, v2))
    inv = ax2.transData.inverted()
    _, dy = inv.transform((0, 0)) - inv.transform((0, y1 - y2))
    miny, maxy = ax2.get_ylim()
    ax2.set_ylim(miny + dy, maxy + dy)

def plot4():
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax2 = ax1.twinx()
    x = np.linspace(0, 1, 100)
    y1 = np.sin(10 * x)
    y2 = x ** 2 - 0.5
    ax1.plot(x, y1, "r", lw=2)
    ax2.plot(x, y2, "g", lw=2)
    align_yaxis(ax1, 0, ax2, 0)
    plt.title(u'中文抬头')
    plt.xlabel(u'X坐标')
    plt.ylabel(u'Y坐标')
    #plt.ylabel(u'Y1坐标')
    plt.show()

def main():
    plot4()

if __name__ == '__main__':
    main()


data_points = [
    (-2, -3),
    (-1, -1),
    (1, 2),
    (4, 3),
]

def get_y_hat(x):
    return (41 / 42 * x) - (5 / 21)

def get_y_mean(data_points):
    l = len(data_points)
    total = 0
    for point in data_points:
        total += point[1]
    return total / l

def squared_error(y, y_hat):
    return (y - y_hat)**2

def squared_from_y_mean(y, y_mean):
    return (y - y_mean)**2

def get_r_squared(sq_e, sq_m):
    # First find the total percentage of the variation not described by the
    # y_hat slope
    perc_total_var_not = sq_e / sq_m
    # Return 1 minus that
    return 1 - perc_total_var_not

print("")
y_mean = get_y_mean(data_points)
total_sq_e = 0
total_sq_m = 0
for x, y in data_points:
    y_hat = get_y_hat(x)
    sq_e = squared_error(y, y_hat)
    sq_m = squared_from_y_mean(y, y_mean)
    total_sq_e += sq_e
    total_sq_m += sq_m
    print("(", x, y, sq_e, sq_m, ")")

print("\ntotal squared error", total_sq_e)
print("y mean", y_mean)
print("total squared variation", total_sq_m)
print("r^2 is", get_r_squared(total_sq_e, total_sq_m))
print("")


import numpy

def expandJ(a):
    """
    Expands an array by one row, averaging the data to the middle columns and
    extrapolating for the first and last rows. Needed for shifting coordinates
    from centers to corners.
    """
    nj, ni = a.shape
    b = numpy.zeros((nj + 1, ni))
    b[1:-1, :] = 0.5 * (a[:-1, :] + a[1:, :])
    b[0, :] = a[0, :] + 0.5 * (a[0, :] - a[1, :])
    b[-1, :] = a[-1, :] + 0.5 * (a[-1, :] - a[-2, :])
    return b


def majority_element(nums):
    """
    Problem:
    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in
    linear time and in O(1) space.

    :type nums: List[int]
    :rtype: List[int]

    Solution:
    There are at most two such elements. We implement a version of the Boyer-Moore majority vote algorithm with two
    candidates and two counts to do this in O(n) time and O(1) space. The first pass finds two candidate values, then
    we verify the candidates actually occurred at least the required number of times.
    """

    if not nums:
        return []

    count1, count2, candidate1, candidate2 = 0, 0, 0, 1

    for num in nums:
        if num == candidate1:
            count1 += 1
        elif num == candidate2:
            count2 += 1
        elif count1 == 0:
            candidate1 = num
            count1 = 1
        elif count2 == 0:
            candidate2 = num
            count2 = 1
        else:
            count1 -= 1
            count2 -= 1

    return [n for n in (candidate1, candidate2) if nums.count(n) > len(nums) // 3]


from tensorflow.python.keras.applications import ResNet50
from tensorflow.python.keras.layers import Dense, Flatten, BatchNormalization, Conv2D, Activation, add, ZeroPadding2D, GlobalAveragePooling2D, GlobalMaxPooling2D, MaxPooling2D
from tensorflow.python.keras.regularizers import l2
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.optimizers import Adam
from tensorflow.python.keras.backend import image_data_format

from collections import namedtuple

JW2MK_parameters = namedtuple('parameters',
                              'main_name, '
                              'base_path,'
                              'test_image_path,'
                              'test_result_path,'
                              'checkpoint_path,'
                              'batch_size,'
                              'learning_rate,'
                              'epochs,'
                              'num_threads,')

def resnet50(params):
    model = Sequential()
    resnet = ResNet50(include_top=False, pooling='avg', weights='imagenet', input_shape=(256, 256, 3))
    model.add(resnet)
    model.add(Flatten())
    model.add(BatchNormalization())

    model.add(Dense(2048, activation=None))
    model.add(BatchNormalization())
    model.add(Activation('relu'))

    model.add(Dense(1024, activation=None))
    model.add(BatchNormalization())
    model.add(Activation('relu'))

    model.add(Dense(512, activation=None))
    model.add(BatchNormalization())
    model.add(Activation('relu'))

    model.add(Dense(7, activation=None))
    model.add(BatchNormalization())
    model.add(Activation('softmax'))

    opt = Adam(lr=params.learning_rate, decay=params.learning_rate/params.epochs)
    model.compile(loss='categorical_crossentropy',
                  optimizer=opt,
                  metrics=['accuracy'])

    return model


#!/usr/bin/env python
import os
import pyesdoc
import pyesdoc.ontologies.cim as cim

gfdl_url = pyesdoc.create(cim.v2.OnlineResource)
gfdl_url.linkage = "www.gfdl.noaa.gov"
gfdl_url.name = "GFDL web page"
gfdl_url.protocol = "http"

person = pyesdoc.create(cim.v2.Party)
person.name = u"Chris Blanton"
person.address = u"201 Forrestal Rd, Princeton, NJ, USA"
person.email = u"chris.blanton@noaa.gov"
person.organisation = 0

org = pyesdoc.create(cim.v2.Party)
org.address = u"201 Forrestal Road, Princeton, NJ, USA"
org.name = "Geophysical Fluid Dynamics Laboratory"
org.organisation = 1
org.url = gfdl_url

person.meta.version = 1
org.meta.version = 1

dir = os.environ['HOME'] + "/esdoc-testing/pyesdoc/responsible_party"
os.system("mkdir -p " + dir)
pyesdoc.write(person, dir)
pyesdoc.write(org, dir)


import torch

from ...parameters import division_epsilon
from ..line_tensor.procedures import calculate_canonical_coordinates

def unit_energy(self, pixel_coords, division_epsilon=division_epsilon):
    r"""

    Parameters
    ----------
    pixel_coords : torch.Tensor
        of shape [spatial_dims_n, pixels_n]
    division_epsilon

    Returns
    -------
    energies : torch.Tensor
        of shape [patches_n, primitives_n, pixels_n]
    """
    spatial_dims_n, pixels_n = pixel_coords.shape
    patches_n = self.patches_n
    primitives_n = self.primitives_n

    if self._segments_p1 is None:
        # 1. Find good split for each curve
        # TODO maybe adaptively
        t = torch.linspace(0, 1, steps=10, dtype=self.dtype, device=self.device).reshape(-1, 1, 1)

        # 2. Split each curve into line segments
        segments_n = len(t) - 1
        spatial_dim_i = 2
        endpoints = self.get_points(t)  # [segments_n + 1, patches_n, spatial_dims_n, primitives_n]
        del t
        p1 = endpoints[:segments_n]
        dir = endpoints[1:] - p1
        del endpoints
        length = dir.norm(dim=spatial_dim_i, keepdim=True)
        dir = dir / (length + division_epsilon)
        length = length.data  # we don't want to optimize length here

        self._segments_p1 = p1
        self._segments_dir = dir
        self._segments_length = length
    else:
        p1 = self._segments_p1
        dir = self._segments_dir
        length = self._segments_length
        segments_n = len(p1)

    if self.pos_fixed:
        p1 = p1.data
        dir = dir.data

    # 3. Calculate segment-to-pixel energies
    p1 = p1.reshape(-1, spatial_dims_n, primitives_n)
    dir = dir.reshape(-1, spatial_dims_n, primitives_n)
    canonical_x, canonical_y = calculate_canonical_coordinates(pixel_coords, p1, dir)
    del p1, dir
    canonical_x = canonical_x.reshape(segments_n, patches_n, primitives_n, pixels_n)
    canonical_y = canonical_y.reshape(segments_n, patches_n, primitives_n, pixels_n)

    halfwidth = self.width.reshape(1, patches_n, primitives_n, 1) / 2
    length = length.reshape(segments_n, patches_n, primitives_n, 1)
    energies = self.energy_procedures.unit_energy_line_to_canonical_point(halfwidth, length, canonical_x, canonical_y)
    del length, canonical_x, canonical_y

    # 4. Sum over segments
    segments_dim_i = 0
    energies = energies.sum(segments_dim_i)

    # 5. Inject dependency on p2-p1 and p2-p3 lengths using a trick
    if not self.size_fixed:
        segments_n = 2
        p1 = torch.stack([self.p1.data, self.p3.data])
        dir = torch.stack([self.p2_to_p1, self.p2_to_p3])
        length = torch.stack([self.p2_to_p1_len - self.p2_to_p1_len.data, self.p2_to_p3_len - self.p2_to_p3_len.data])

        p1 = p1.reshape(-1, spatial_dims_n, primitives_n)
        dir = dir.reshape(-1, spatial_dims_n, primitives_n)
        canonical_x, canonical_y = calculate_canonical_coordinates(pixel_coords, p1, dir)
        del p1, dir
        canonical_x = canonical_x.reshape(segments_n, patches_n, primitives_n, pixels_n)
        canonical_y = canonical_y.reshape(segments_n, patches_n, primitives_n, pixels_n)

        length = length.reshape(segments_n, patches_n, primitives_n, 1)
        halfwidth = halfwidth.data
        len_dependent_terms = self.energy_procedures.unit_energy_line_to_canonical_point(
            halfwidth, length, canonical_x, canonical_y)
        del canonical_x, canonical_y, length

        segments_dim_i = 0
        energies = energies + len_dependent_terms.sum(segments_dim_i)
    del halfwidth

    # # 6. Add curvature penalty
    # if not self.pos_fixed:
    #     # # dtheta in [-pi, pi]
    #     # dtheta = torch.remainder(self.theta2 - self.theta1 + np.pi, np.pi * 2) - np.pi
    #     #
    #     # beta = 1 / (15 * np.pi / 180) ** 2
    #     # amplitude = 1e6
    #     # curvature_penalty = torch.exp(-dtheta.pow(2) * beta) * amplitude
    #     # del dtheta, beta
    #
    #     # dtheta in [-pi, pi]
    #     dtheta = torch.remainder(self.theta2 - self.theta1.data + np.pi, np.pi * 2) - np.pi
    #
    #     beta = 1 / (15 * np.pi / 180) ** 2
    #     amplitude = 1e6
    #     curvature_penalty = torch.exp(-dtheta.pow(2) * beta) * amplitude
    #     del dtheta, beta
    #
    #     curvature_penalty.reshape(patches_n, primitives_n, 1)
    #     energies = energies + curvature_penalty
    #     del curvature_penalty

    # # draw for debugging
    # import numpy as np
    # _ = energies
    # _ = _[:, 0].detach().cpu()
    #
    # h = int(np.sqrt(pixels_n))
    # assert pixels_n % h == 0
    # w = pixels_n // h
    # _ = _.reshape(patches_n, h, w)
    # self.debug_ax.imshow(np.vstack(_))

    return energies


import re
# 路径配置。
import pandas as pd
from urllib.request import urlretrieve
import zipfile

class Config:
    #pattern = r'\d+\.(?:\d+\.)*\w+'
    pattern = r'\d+(\.|\_|\-)(?:\w+(\.|\_|\-))*\d+'   # 数字 + 连接符(._-) + 符号 组成 结尾最好也是数字，否则会把文件名连接符也算进去，但是会损失类似'beta''final'结尾
    s_path = '../vsrc/undertow-core-1.4.9.Final-sources'  # 源码包地址
    ver = re.search(pattern, s_path).group(0)
    s_name = 'undertow'  # 软件名
    github_url = 'https://github.com/undertow-io/undertow'  # 软件github地址
    repo_path = '../repo/' + s_name  # repo存储地址(默认)
   # file_his_url = '../file_his/' + s_name + '_all_file_his.json'  # file_his存储地址(默认)
    file_his_url = '../file_his/'   # file_his存储地址(默认)

def id_to_name():
    df = pd.read_csv('C:/Users/c50021559/Desktop/dataset/open_source_software.csv')
    df = df.drop([index for index in range(df.shape[0]) if df.loc[index,'blackhole_type']!='MAVEN'])
    df.reset_index(drop=True, inplace=True)
    id2name = dict()
    id2url = dict()
    for index in range(df.shape[0]):
        id = df.loc[index,'id']
        name = df.loc[index,'name']
        url = df.loc[index,'http_url']
        id2name[id]=name
        id2url[id] = url
    return id2name, id2url
class ConfigTest:

    def __init__(self):
        self.load_file = 'pkg_repo_cmt.csv'  # 文件
        self.pattern = r'\d+(\.|\_|\-)(?:\w+(\.|\_|\-))*\d+'
        self.df = pd.read_csv(self.load_file) # dataflow
        self.ver = 0   # version
        self.s_path = str # source path
        self.github_url = str  # github url
        self.s_name = str  # software name
        self.id2name, _= id_to_name()
        self.file_his_url = '../file_his/'

    def get_path(self,index):
        self.ver = self.df.loc[index,'version']
        self.name = self.df.loc[index,'name']  # NAME
        self.pkg_name = self.df.loc[index,'pkg_name']   # download pag name
        download = self.df.loc[index,'pkg_url']    # download url
        self.dirname = '../download/'+self.pkg_name   # download dir
        self.s_path = '../download/'+self.pkg_name.replace('.jar','')   # unzip url
        urlretrieve(download , self.dirname)   # download
        with zipfile.ZipFile(self.dirname, 'r') as zip:   #unzip
            zip.extractall(self.s_path)
        self.github_url = self.df.loc[index,'github_url']
        self.s_name = str(self.id2name[self.df.loc[index,'id']])
        self.repo_path = '../repo/' + self.s_name


from django.db import models
from django.utils import timezone

from sabzi_mandi.models import CustomFloatField
from shops.models import Shop, Item
from clients.models import Client
from suppliers.models import Supplier
from payments.models import ClientPayment

class ClientBill(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    created_time = models.DateTimeField(default=timezone.now, editable=False)
    is_draft = models.BooleanField(default=False)
    bill_date = models.DateField()
    balance = CustomFloatField(default=0)
    billed_amount = CustomFloatField(default=0)
    payment = models.ForeignKey(ClientPayment, blank=True, null=True, on_delete=models.CASCADE)

    class Meta:
        db_table  = "client_bill"

class BillDetail(models.Model):
    bill = models.ForeignKey(ClientBill, on_delete=models.CASCADE)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    unit = models.CharField(max_length=1, choices=[("k", "KG"), ("i", "Count")])
    rate = CustomFloatField()
    item_count = CustomFloatField()

    class Meta:
        db_table = "client_bill_detail"

class SupplierBill(models.Model):
    supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
    created_time = models.DateTimeField(default=timezone.now, editable=False)
    is_draft = models.BooleanField(default=False)
    bill_date = models.DateField()
    balance = CustomFloatField(default=0)
    billed_amount = CustomFloatField(default=0)
    other_expence = models.JSONField(default=dict)
    cash = CustomFloatField(default=0)

    class Meta:
        db_table  = "supplier_bill"

class SupplierBillDetail(models.Model):
    bill = models.ForeignKey(SupplierBill, on_delete=models.CASCADE)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    unit = models.CharField(max_length=1, choices=[("k", "KG"), ("i", "Count")])
    rate = CustomFloatField()
    item_count = CustomFloatField()
    weight = CustomFloatField(null=True, blank=True)

    class Meta:
        db_table = "supplier_bill_detail"


import re
import copy
import fileinput
import inspect

from GoogleDriveApi import *
from VideoStatusRecord import *
from core import *
from StatusComparisonResult import *
from MongoDBApi import *

class VideoFile:
    def __init__(self, *args, **dargs):
        self.statusRecord = None
        self.__isCompleted = False

        if not isEmpty(args):
            if isinstance(args[0], VideoStatusRecord):
                self.statusRecord = copy.deepcopy(args[0].statusRecord)
            elif isinstance(args[0], str) or isinstance(args[0], dict):
                self.statusRecord = VideoStatusRecord(args[0])
        else:
            self.statusRecord = VideoStatusRecord(args, dargs)
        trace("Created a videoFile object: " + self.statusRecord.stringify())

    def process(self):
        trace("Start video processing...")
        if not self.__hasValidStatus():
            self.__setInitialStatus()
        if not self.__isFinished():
            pStatus = self.__getPreviousStatus()
            self.__transitTo(pStatus)
        if self.__hasValidFinalStatus():
            self.__completeProcess()
            return

        self.__isCompleted = False
        eRecord = self.__getExistingRecord()
        nStatus = self.__getNextStatus(eRecord)
        while not isEmpty(nStatus):
            self.__transitTo(nStatus)
            if self.__isProcessCompleted():
                return
            nStatus = self.__getNextStatus(eRecord)

    def __setInitialStatus(self):
        self.statusRecord.initStatus()

    def __hasValidStatus(self):
        return not isEmpty(self.statusRecord.getStatus())

    def __hasValidFinalStatus(self):
        return self.statusRecord.getStatus().isValidFinalStatus()

    def __isFinished(self):
        return self.statusRecord.isFinished()

    def __getNextStatus(self, eRecord):
        return self.statusRecord.getNextStatus(eRecord)

    def __getPreviousStatus(self):
        return self.statusRecord.getPreviousStatus()

    def __isProcessCompleted(self):
        return self.__isCompleted

    def __isProcessFailed(self):
        return self.statusRecord.getStatus().getState() == "failed"

    def __failProcess(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        self.statusRecord.getStatus().setOrKeepState("failed")
        self.__completeProcess()

    def __completeProcess(self):
        finalStatus = self.statusRecord.getStatus()
        trace("Complete video processing at " + finalStatus.stringify())
        assertWithMessage(finalStatus.isValidFinalStatus(), #or finalStatus.isInitialStatus(),
                          "(" + finalStatus.stringify() + ") is an invalid final status...")
        if finalStatus.getStage() == "delete":
            eRecord = self.__getExistingRecord()
            self.statusRecord.setOrKeepName(eRecord.getName()) # use existing video name
        self.statusRecord.writeToCompleteFile()
        self.__isCompleted = True

    def __setVideoStatusAndUpdateIncompleteFile(self, toStatus):
        self.statusRecord.setOrKeepStatus(toStatus)
        self.statusRecord.writeToIncompleteFile()

    def __getExistingRecord(self):
        return self.statusRecord.findRecordByFileIdIn(COMP_STATUS_FILE)

    def __transitTo(self, toStatus):
        fromStatus = self.statusRecord.getStatus()
        comparison = fromStatus.compareTo(toStatus)

        infoMessage(fromStatus.stringify() + " ====> " + toStatus.stringify())

        if self.__handleSelfTransition(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromFailed(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromProcessingToFinished(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromDeleteToInit(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromDownloadToInit(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromInitToDelete(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromInitToDownload(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromDownloadToInit(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromDownloadToEncode(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromEncodeToDownload(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromEncodeToPackage(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromPackageToEncode(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromPackageToChunk(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromChunkToPackage(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromChunkToPublish(fromStatus, toStatus, comparison):
            return
        elif self.__handleFromPublishToChunk(fromStatus, toStatus, comparison):
            return
        else:
            self.__handleIllegalTransition(fromStatus, toStatus)

    @trycatch
    def deleteVideoFromMongoDB(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        eRecord = self.__getExistingRecord()
        ndnNameprefix = VIDEO_NDN_NAMESPACE + "/" + eRecord.getNameWithoutFileExtension()
        mongo = MongoDBApi()
        ecode = mongo.purge(ndnNameprefix)
        self.__handleTryCatchError()

    @trycatch
    def download(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        drive = GoogleDriveApi()
        drive.connect()
        drive.downloadFileByFileId(self.statusRecord.getFileId())

    @trycatch
    def encode(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        runShellCommand(self.__generateEncodeCommand())
        self.__handleStderr()
        self.__handleTryCatchError()
    def __generateEncodeCommand(self):
        videoName = self.statusRecord.getName()
        outputDir = VIDEO_DIR
        return BASH + VIDEO_TRANSCODER + " " + VIDEO_DIR + "/" + videoName + " " + outputDir + " 2> " + STDERR

    @trycatch
    def package(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        runShellCommand(self.__generatePackageCommand())
        self.__handleStderr()
        self.__handleTryCatchError()
    def __generatePackageCommand(self):
        videoName = self.statusRecord.getNameWithoutFileExtension()
        inputDir = VIDEO_DIR
        outputDir = VIDEO_DIR + "/" + videoName + "/" + VIDEO_PACKAGING_PROTOCOL
        return BASH + VIDEO_PACKAGER + " " + inputDir + \
               " " + videoName + " " + outputDir + " " + VIDEO_PACKAGING_PROTOCOL + " 2> " + STDERR

    @trycatch
    def chunk(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        runShellCommand(self.__generateChunkCommand())
        self.__handleStderr()
        self.__handleTryCatchError()
    def __generateChunkCommand(self):
        videoName = self.statusRecord.getNameWithoutFileExtension()
        inputDir = VIDEO_DIR + "/" + videoName
        ndnVideoName = VIDEO_NDN_NAMESPACE + "/" + videoName
        return CHUNKER + ndnVideoName + " -i " + inputDir + " -s " + VIDEO_SEGMENT_SIZE +\
               " -e " + VIDEO_VERSION + " 2> " + STDERR

    @trycatch
    def publish(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        runShellCommand(self.__generatePublishCommand())
        self.__handleStderr()
        self.__handleTryCatchError()
    def __generatePublishCommand(self):
        videoName = self.statusRecord.getNameWithoutFileExtension()
        outputDir = HTML_DIR
        playlistUrl = VIDEO_NDN_NAMESPACE + "/" + videoName + "/" +\
                      VIDEO_PACKAGING_PROTOCOL + "/" + VIDEO_MAIN_PLAYLIST_NAME
        return BASH + VIDEO_PUBLISHER + " " + videoName + " " + playlistUrl + " " + outputDir + " 2> " + STDERR

    @trycatch
    def deleteVideoFromDisk(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        filepath = self.__getVideoFilePath()
        deleteFile(filepath)
        self.__handleTryCatchError()
    @trycatch
    def deleteEncodedFilesFromDisk(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        wildcard = self.__getWildcardPathToEncodedFiles
        deleteFiles(wildcard)
        self.__handleTryCatchError()
    @trycatch
    def deletePackagedFolderFromDisk(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        folderpath = self.__getFolderPathToPackagedFiles()
        deleteFolder(folderpath)
        self.__handleTryCatchError()
    @trycatch
    def deleteHtmlFile(self):
        trace("@" + inspect.currentframe().f_code.co_name + "()")
        htmlPath = self.__getHtmlFilePath()
        deleteFile(htmlPath)

    def __getVideoFilePath(self):
        return VIDEO_DIR + "/" + self.statusRecord.getName()
    def __getWildcardPathToEncodedFiles(self):
        videoName = self.statusRecord.getNameWithoutFileExtension()
        videoNameWildcard = videoName + "_h264*"
        return VIDEO_DIR + "/" + videoNameWildcard
    def __getFolderPathToPackagedFiles(self):
        videoName = self.statusRecord.getNameWithoutFileExtension()
        return  VIDEO_DIR + "/" + videoName
    def __getHtmlFilePath(self):
        return VIDEO_DIR + "/" + self.statusRecord.getNameWithoutFileExtension() + ".html"

    def __handleStderr(self):
        errorLineFound = False
        finput = fileinput.input(STDERR, inplace=False)
        for line in finput:
            if re.search("ECode:[1-5]", line):
                errorMessage(line)
                errorLineFound = True
        finput.close()
        if errorLineFound:
            self.__failProcess()
            return FAILURE
        return SUCCESS

    def __handleTryCatchError(self):
        if not isEmpty(tryCatchError) and re.search("ECode:6", tryCatchError):
            self.__failProcess()
            return FAILURE
        return SUCCESS

    # =========-------------------------========== #
    # ============ Tansition Handlers ============ #
    # =========-------------------------========== #
    def __handleSelfTransition(self, fromStatus, toStatus, comparison):
        if comparison.isNoDifference():
            warningMessage("A self transition on " + fromStatus.stringify())
            self__isCompleted = True
            return True
        return False
    def __handleFromFailed(self, fromStatus, toStatus, comparison):
        if fromStatus.getStage() == "failed":
            self.__isCompleted = True
            return True
        return False
    def __handleFromProcessingToFinished(self, fromStatus, toStatus, comparison):
        if comparison.state and comparison.stage and not comparison.step:
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            if toStatus.isValidFinalStatus():
                self.__completeProcess()
            return True
        return False
    def __handleFromDeleteToInit(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "delete" and toStatus.getStage() == "init":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            #self.__completeProcess()
            return True
        return False
    def __handleFromDownloadToInit(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "download" and toStatus.getStage() == "init":
            self.deleteVideoFromDisk()
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            #self.__completeProcess()
            return True
        return False
    def __handleFromInitToDelete(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "init" and toStatus.getStage() == "delete":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.deleteVideoFromMongoDB()
            return True
        return False
    def __handleFromInitToDownload(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "init" and toStatus.getStage() == "download":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.download()
            return True
        return False
    def __handleFromDownloadToEncode(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "download" and toStatus.getStage() == "encode":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.encode()
            return True
        return False
    def __handleFromEncodeToDownload(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "encode" and toStatus.getStage() == "download":
            self.deleteEncodedFilesFromDisk()
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            return True
        return False
    def __handleFromEncodeToPackage(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "encode" and toStatus.getStage() == "package":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.package()
            return True
        return False
    def __handleFromPackageToEncode(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "package" and toStatus.getStage() == "encode":
            self.deletePackagedFolderFromDisk()
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            return True
        return False
    def __handleFromPackageToChunk(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "package" and toStatus.getStage() == "chunk":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.chunk()
            return True
        return False
    def __handleFromChunkToPackage(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "chunk" and toStatus.getStage() == "package":
            self.deleteVideoFromMongoDB()
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            return True
        return False
    def __handleFromChunkToPublish(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "chunk" and toStatus.getStage() == "publish":
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            self.publish()
            return True
        return False
    def __handleFromPublishToChunk(self, fromStatus, toStatus, comparison):
        if comparison.state and fromStatus.getStage() == "publish" and toStatus.getStage() == "chunk":
            self.deleteHtmlFile()
            self.__setVideoStatusAndUpdateIncompleteFile(toStatus)
            return True
        return False
    def __handleIllegalTransition(self, fromStatus, toStatus):
        raise Exception("Illegal transition: " + \
                        fromStatus.stringify() + " => " + toStatus.stringify())


from circuitree.viz import plot_network
from datetime import date
import h5py
from matplotlib.ticker import FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path

from circuitree.models import SimpleNetworkGrammar
from tf_network import (
    autocorrelate,
    compute_lowest_minimum,
    binomial9_kernel,
)

grammar = SimpleNetworkGrammar(
    components=["A", "B", "C"], interactions=["activates", "inhibits"]
)

def has_motif(state: str, motif: str):
    interaction_code = state.split("::")[1]
    if not interaction_code:
        return False
    state_interactions = set(interaction_code.split("_"))

    for recoloring in grammar.get_interaction_recolorings(motif):
        motif_interactions = set(recoloring.split("_"))
        if motif_interactions.issubset(state_interactions):
            return True
    return False

def plot_network_quantity_and_acorr(
    genotype,
    t,
    y_t,
    acorr,
    corr_time,
    minimum_val,
    plot_dir,
    save,
    dpi,
    fmt,
    figsize=(2.5, 2.5),
    annotate_acf_min=True,
    # plot_motifs=(),
    suptitle=None,
    suffix="",
    **kwargs,
):
    n_species, nt = y_t.shape
    half_nt = nt // 2
    t_mins = t / 60.0

    fig1, ax = plt.subplots(1, 1, figsize=(figsize[0] * 0.6, figsize[1] * 0.6))
    plt.sca(ax)
    plot_network(
        *grammar.parse_genotype(genotype, nonterminal_ok=True), ax=ax, **kwargs
    )
    if save:
        today = date.today().strftime("%y%m%d")
        fname = f"{today}_network_diagram{suffix}.{fmt}"
        fpath = plot_dir.joinpath(fname).resolve().absolute()
        print("Writing to:", fpath)
        plt.savefig(fpath, dpi=dpi, transparent=True)

    fig2, (ax1, ax2) = plt.subplots(2, 1, figsize=figsize)

    plt.sca(ax1)
    for j in range(n_species):
        ax1.plot(t_mins, y_t[j], lw=1)

    # if plot_motifs:
    #     x = 0.98
    #     y = 0.95
    #     ax.text(
    #         x, y, "Motifs:", ha="left", va="top", transform=ax.transAxes, size=8
    #     )
    #     y -= 0.1
    #     for motif, s in plot_motifs:
    #         if has_motif(state, motif):
    #             ax.text(x, y, s, ha="left", va="top", transform=ax.transAxes, size=8)
    #             y -= 0.1

    ax1.set_ylabel("TF Quantity")
    ax1.ticklabel_format(axis="y", style="sci", scilimits=(3, 3))
    plt.locator_params(axis="y", tight=True, nbins=3)

    ax1.spines["top"].set_visible(False)
    ax1.spines["right"].set_visible(False)

    plt.sca(ax2)
    for j in range(n_species):
        ax2.plot(t_mins[:-half_nt], acorr[j, :], lw=1)
    corr_time_mins = corr_time / 60.0
    # ax3.scatter(corr_time_mins, minimum_val, marker="x", s=50, c="r", zorder=100)
    if annotate_acf_min:
        ax2.annotate(
            rf"$\mathrm{{ACF}}_\mathrm{{min}}={{{minimum_val:.2f}}}$",
            (corr_time_mins, minimum_val),
            (corr_time_mins + 0.1 * t_mins.max(), -1.3),
            arrowprops=dict(arrowstyle="->"),
            # ha="left",
            # va="bottom",
            size=10,
        )
    ax2.set_xlabel("Time (mins)")
    ax2.set_ylabel("Autocorrelation")
    ax2.set_ylim(-1.5, 1.0)
    ax2.yaxis.set_major_formatter(FormatStrFormatter("%.0f"))
    ax2.spines["top"].set_visible(False)
    ax2.spines["right"].set_visible(False)

    if suptitle is not None:
        plt.suptitle(suptitle, size=14)
    plt.tight_layout()

    if save:
        today = date.today().strftime("%y%m%d")
        fname = f"{today}_copynum_and_acf_example{suffix}.{fmt}"
        fpath = Path(plot_dir).joinpath(fname).resolve().absolute()
        print("Writing to:", fpath)
        plt.savefig(fpath, dpi=dpi, transparent=True)

def main(
    genotype,
    data_fpath,
    plot_dir,
    which_plot=0,
    save=False,
    dpi=300,
    fmt="png",
    suffix="",
    network_kwargs={},
):
    with h5py.File(data_fpath, "r") as f:
        t = f["t"][...]
        y_t = f["y_t"][which_plot]
        state = f["states"][0]

    # plot_motifs = [
    #     ("*ABC::ABa_BAi", "A-I"),
    #     ("*ABC::ABi_BCi_CAi", "I-I-I"),
    #     ("*ABC::ABi_BAi", "Toggle"),
    # ]

    # Before autocorrelation, we filter the data with a 9-point binomial filter
    filtered9 = np.apply_along_axis(binomial9_kernel, -1, y_t)[:, 4:-4]
    acorrs_f9 = np.apply_along_axis(autocorrelate, -1, filtered9)
    t_f9 = t[4:-4]
    all_minima_idx, all_minima = zip(*[compute_lowest_minimum(a) for a in acorrs_f9])
    which_lowest = np.argmin(all_minima)
    where_minimum = all_minima_idx[which_lowest]
    minimum_val = all_minima[which_lowest]
    corr_time = t_f9[where_minimum]

    if not suffix:
        gen_str = genotype.split(":")[-1]
        suffix = f"_{gen_str}_{which_plot}"

    plot_network_quantity_and_acorr(
        # suptitle=r"Highest reward - Copy number vs $t$ (mins)",
        genotype=genotype,
        t=t_f9,
        y_t=filtered9,
        acorr=acorrs_f9,
        corr_time=corr_time,
        minimum_val=minimum_val,
        plot_dir=plot_dir,
        save=save,
        dpi=dpi,
        fmt=fmt,
        # plot_motifs=plot_motifs,
        suffix=suffix,
        **network_kwargs,
    )

    ...

if __name__ == "__main__":
    data_fpath = Path(
        "data/oscillation/bfs_230710_hpc/top_oscillating_runs_ABC::AAa_ABa_BAi_CBi.hdf5"
    )
    # data_fpath = Path("data/oscillation/bfs_230710_hpc/top_oscillating_states.hdf5")
    # data_fpath = Path("data/oscillation/bfs_230710_hpc/top_oscillating_runs.hdf5")
    plot_dir = Path("figures/oscillation")

    network_kwargs = dict(
        fontsize=12,
        padding=0.5,
        lw=1,
        node_shrink=0.7,
        offset=0.8,
        auto_shrink=0.9,
        width=0.005,
    )

    main(
        genotype="ABC::AAa_ABa_BAi_CBi",
        data_fpath=data_fpath,
        plot_dir=plot_dir,
        which_plot=0,
        network_kwargs=network_kwargs,
        save=True,
        fmt="eps",
    )