# pip install xlrd
import xlrd
# pip install requests
import requests
import xlsxwriter
# pip install beautifulsoup4
# pip install lxml
from bs4 import BeautifulSoup

def download_xls():
    """
    Downlaods a .xls file containing data for State Population.
    :param: None
    :return: None
    """
    # URL
    url = "http://mospi.nic.in/statistical-year-book-india/2015/171"
    html_page = requests.get(url).text
    soup = BeautifulSoup(html_page, 'lxml')
    # Get table content
    table_links = []
    page_table = soup.find_all(name="table", class_="views-table")
    for content in page_table:
        table_links = content.find_all(name="a")
    # Try: Check if required_doc exists in table
    try:
        required_doc = "Mid Year Population"
        state_population_href = [link['href'] for link in table_links if required_doc in link.text][0]
        response = requests.get(state_population_href)
        # Open file with filename and write bytes
        filename = "state_population_data.xls"
        with open(filename, 'wb') as xls:
            xls.write(response.content)
            xls.close()
        print("File Downloaded!")
    except Exception as e:
        print("No Data Found!", e)

def modify_xls(quiet=True):
    """
    Modify .xls file to required format.
    :param quiet: (default: True) - Set verbosity of the function.
    :return years: (defualt: []) - A list of years extracted from the .xls file
    :return state_population_dict: (default: {}) - A dictionary of State Names (keys) and their population data (values)
    """
    book = xlrd.open_workbook("state_population_data.xls", on_demand=True)
    sh = book.sheet_by_index(0)
    state_population_dict = {}
    years = []
    for rows in range(sh.nrows):
        cell_values = [text.value for text in sh.row(rows)]
        useful_cell_values = []
        for value in cell_values:
            if value == '':
                continue
            useful_cell_values.append(str(value).strip())
        if len(useful_cell_values) == 0:
            continue
        if "State/" in useful_cell_values[0]:
            years = sorted([int(float(value)) for value in list(set(useful_cell_values[1:]))])
        if len(useful_cell_values) == 9:
            state_population_dict[useful_cell_values[0]] = [int(float(value)) for value in useful_cell_values[1:]]
    book.release_resources()
    del book
    if not quiet:
        print(f"Years: {years}")
        print(f"State Population Data: {state_population_dict}")
    return years, state_population_dict

def write_xlsx(year_list, population_dict):
    """
    Create a new .xlsx file to write required data in required format
    :param year_list: A list of years
    :param population_dict: A dictionary of "State_Name":[Yearly_Population_data_list] pair of key:value
    :return:
    """
    filename = "Yearly_State_Population.xlsx"
    book = xlsxwriter.Workbook(filename)
    sh = book.add_worksheet()
    row = 0
    col = 0
    for index, year in enumerate(year_list, start=1):
        sh.write(row, col + index, year)
    col = 0
    keys = population_dict.keys()
    for key in keys:
        row += 1
        sh.write(row, col, key)
        for index, item in enumerate(population_dict[key], start=1):
            sh.write(row, col + index, item)
    book.close()
    print(f"Sucessfully written file: {filename}")

if __name__ == "__main__":
    download_xls()
    year_list_data, population_data = modify_xls(quiet=True)
    write_xlsx(year_list=year_list_data, population_dict=population_data)


with open("day2_input.txt") as file:
    lines = file.readlines()

x = 0
y = 0
aim = 0

for line in lines:
    line_split = line.split()
    direction = line_split[0]
    amount = line_split[1]
    if direction == "forward":
        x += int(amount)
        y += int(amount) * aim
    elif direction == "up":
        aim -= int(amount)
    elif direction == "down":
        aim += int(amount)
    else:
        continue

print(f"{x} * {y} = {x*y}")


def wrap_kawahara_processRN(filen, filemask, fitsout):
    # OEGP method
    import astropy.io.fits as pyf
    import numpy as np
    from pyird import readnoise as rn
    from pyird import large_scaled

    hdulist = pyf.open(filemask)
    hdu = hdulist[0]
    header = hdu.header
    mask = np.array(hdu.data)
    mask[mask == 0] = 0
    mask[mask > 0] = 1
    mask = np.array(mask, dtype=np.bool)
    # input img
    hdulist = pyf.open(filen)
    hdu = hdulist[0]
    header = hdu.header
    img = np.array(hdu.data)
    imgorig = np.copy(img)
    # print("# of Masked pix is "+str(len(img[mask])))
    img[mask] = None

    # Large Scale Distribution
    check = large_scaled.check_mask_filling(mask, Ncor=64)
    if check:
        LSD = large_scaled.get_LSD(img, gpscale=1024, Ncor=64, sigma=0.001)
    else:
        sys.exit('exit')
    ###############################
    img = img-LSD
    recimg = rn.RNestimate_OEGP(img)
    ###############################

    cimg = imgorig-recimg-LSD

    hdu = pyf.PrimaryHDU(cimg, header)
    hdulist = pyf.HDUList([hdu])
    hdulist.writeto(fitsout, overwrite=True)


from Node import Node

class Game:

    """ Creates a Cannibals and Missionaries game

    Attributes:
        initial_node: The starting node of the problem, with all characters and boat on the left-hand side of the river

    """

    def __init__(self):
        """Initialises first node with starting positions"""
        self.initial_node = Node(missionaries_wrong_side=3, cannibals_wrong_side=3, boat_wrong_side=1)

    def breadth_first_search(self):
        """BFS algorithm that explores until goal node is found"""
        if self.initial_node.is_goal_state():
            return self.initial_node
        frontier = []
        explored = set()
        frontier.append(self.initial_node)

        while frontier:
            node = frontier.pop(0)
            print("Exploring node " + str(node.state))
            explored.add(node)
            children = node.get_child_nodes()
            for child in children:
                if (child not in frontier) and (child not in explored):
                    if child.is_goal_state():
                        return child
                    frontier.append(child)

        return None


"""
Sets up and runs advanced benchmarking tests for developers.

It is designed to submit many jobs simultaneously on an HPC system.
Please see the README.md file for more information.
"""

import os
import pandas as pd
import shutil
import json
import subprocess
import numpy as np

def set_up_calcs(basedir, env, testfile="test.py"):
    """
    Set up calculations by creating directories and preparing files.

    Parameters
    ----------
    basedir : str
        The base directory where calculations will be set up.
    env : str
        The environment variable to be used in the calculations.
    testfile : str, optional
        The name of the test file to use for calculations.

    Returns
    -------
    None
    """
    if os.path.exists(basedir):
        user_input = (
            input(
                f"The directory {basedir} already exists."
                + "Are you sure you want to continue? (yes/no): "
            )
            .strip()
            .lower()
        )
        if user_input != "yes":
            print("Operation cancelled.")
            return

    # Read the CSV file
    df = pd.read_csv("pressure_benchmarks.csv")

    # Loop through the rows of the dataframe
    for index, row in df.iterrows():
        species = row["species"]
        rho = row["rho"]
        rho_round = round(rho, 3)
        temp = row["temp"]
        temp_round = round(temp, 3)

        # Create the sub-folder
        subdir = os.path.join(basedir, f"{species}/rho_{rho_round}/T_{temp_round}")
        os.makedirs(subdir, exist_ok=True)

        # Read the original submit.slurm file
        with open("submit.slurm", "r") as file:
            filedata = file.read()

        # Replace the target string
        filedata = filedata.replace("env={ENV}", f"env={env}")

        # Write the modified submit.slurm file to the new location
        with open(subdir + "/submit.slurm", "w") as file:
            file.write(filedata)

        # same for python script
        shutil.copy(testfile, subdir + "/test.py")

        # Make a JSON file containing all the information from the row
        row_dict = row.to_dict()
        with open(os.path.join(subdir, "input.json"), "w") as f:
            json.dump(row_dict, f, indent=4)

    print("Setup complete.")

def run_calcs(basedir):
    """
    Run calculations by submitting jobs to an HPC system.

    Parameters
    ----------
    basedir : str
        The base directory where calculations are set up.

    Returns
    -------
    None
    """
    # Read the CSV file
    df = pd.read_csv("pressure_benchmarks.csv")

    # Loop through the rows of the dataframe
    for index, row in df.iterrows():
        species = row["species"]
        rho = row["rho"]
        rho_round = round(rho, 3)
        temp = row["temp"]
        temp_round = round(temp, 3)

        # Define the sub-folder
        subdir = os.path.join(basedir, f"{species}/rho_{rho_round}/T_{temp_round}")

        # Check if the directory exists
        if not os.path.exists(subdir):
            print(f"Directory does not exist: {subdir}")
            continue

        # Check if submit.slurm exists in the directory
        if not os.path.exists(os.path.join(subdir, "submit.slurm")):
            print(f"submit.slurm does not exist in: {subdir}")
            continue

        # Execute sbatch submit.slurm
        try:
            subprocess.run(["sbatch", "submit.slurm"], check=True, cwd=subdir)
            print(f"Job submitted for {species}, rho_{rho}, T_{temp}")
        except subprocess.CalledProcessError as e:
            print(f"Failed to submit job for {species}, rho_{rho}, T_{temp}: {e}")

# Function to check if the values are close
def check_close(input_val, output_val, atol=1e-9, rtol=1e-2):
    """
    Check if two values are close to each other within a tolerance.

    By default it checks for a relative tolerance of 1%.
    Absolute tolerance is not considered.

    Parameters
    ----------
    input_val : float
        The first value to compare.
    output_val : float
        The second value to compare.
    atol : float, optional
        The absolute tolerance parameter.
    rtol : float, optional
        The relative tolerance parameter.

    Returns
    -------
    bool
        True if the values are close within the specified tolerances, False otherwise.
    """
    return np.isclose(input_val, output_val, atol=atol, rtol=rtol)

# Function to calculate the percentage error
def calculate_percentage_error(value1, value2):
    """
    Calculate the percentage error between two values.

    Parameters
    ----------
    value1 : float
        The first value (reference value).
    value2 : float
        The second value (value to compare).

    Returns
    -------
    float
        The percentage error between the two values.
    """
    if value1 == 0 and value2 == 0:
        return 0  # Avoid division by zero if both values are zero
    try:
        return round(abs((value1 - value2) / value1) * 100, 3)
    except ZeroDivisionError:
        return np.inf  # Return infinity if value1 is zero

# Function to gather benchmark results and save to a new file
def gather_benchmark_results(basedir, new_filename):
    """
    Gather benchmark results from JSON files and save them to a new CSV file.

    Parameters
    ----------
    basedir : str
        The base directory where the benchmark results are stored.
    new_filename : str
        The name of the new CSV file to save the results.

    Returns
    -------
    None
    """
    # Read the existing dataframe
    df = pd.read_csv("pressure_benchmarks.csv")

    # Prepare a list to hold the new data
    new_data = []

    # Loop through the rows of the dataframe
    for index, row in df.iterrows():
        species = row["species"]
        rho = row["rho"]
        temp = row["temp"]

        # Define the sub-folder
        subdir = os.path.join(
            basedir, f"{species}/rho_{round(rho, 3)}/T_{round(temp, 3)}"
        )

        # Initialize the outcome and percentage errors
        outcome = "fail"
        pc_err_st = pc_err_vir = pc_err_id = time_s = None

        # Read input.json and output.json files
        try:
            with open(os.path.join(subdir, "input.json"), "r") as f:
                input_data = json.load(f)

            with open(os.path.join(subdir, "output.json"), "r") as f:
                output_data = json.load(f)

            # Extract the relevant values
            P_st_rr_input = input_data["P_st_rr"]
            P_vir_nocorr_input = input_data["P_vir_nocorr"]
            P_id_input = input_data["P_id"]

            P_st_rr_output = output_data["P_st_rr"]
            P_vir_nocorr_output = output_data["P_vir_nocorr"]
            P_id_output = output_data["P_id"]
            time_s = round(output_data["time"], 2)

            # Calculate percentage errors
            pc_err_st = calculate_percentage_error(P_st_rr_input, P_st_rr_output)
            pc_err_vir = calculate_percentage_error(
                P_vir_nocorr_input, P_vir_nocorr_output
            )
            pc_err_id = calculate_percentage_error(P_id_input, P_id_output)

            # Check if the values are close within the specified relative tolerance
            # The original calculations were converged to 1%
            rtol = 1e-2  # 1%
            if (
                np.isclose(P_st_rr_input, P_st_rr_output, rtol=rtol)
                and np.isclose(P_vir_nocorr_input, P_vir_nocorr_output, rtol=rtol)
                and np.isclose(P_id_input, P_id_output, rtol=rtol)
            ):
                outcome = "pass"

        except Exception as e:
            print(f"Error reading files for {species}, rho_{rho}, T_{temp}: {e}")
            outcome = "fail"

        # Append the new row to the data list
        new_data.append(
            [species, rho, temp, outcome, pc_err_st, pc_err_vir, pc_err_id, time_s]
        )

    # Create the new dataframe with additional columns for percentage errors
    new_df_columns = [
        "species",
        "rho",
        "temp",
        "outcome",
        "pc_err_st",
        "pc_err_vir",
        "pc_err_id",
        "time_s",
    ]
    new_df = pd.DataFrame(new_data, columns=new_df_columns)

    # Save the new dataframe to the specified CSV file
    new_df.to_csv(new_filename, index=False)
    print(f"Results saved to {new_filename}")

def analyze_benchmark_results(csv_file):
    """
    Read benchmark results from a CSV file and analyzes the data.

    Parameters
    ----------
    csv_file : str
        The path to the CSV file containing benchmark results

    Returns
    -------
    None
    """
    # Read the CSV file into a DataFrame
    df = pd.read_csv(csv_file)

    # Calculate the number of tests passed
    total_tests = len(df)
    passed_tests = len(df[df["outcome"] == "pass"])
    pass_fraction = passed_tests / total_tests

    # Calculate median and max for error columns
    err_st_stats = {"median": df["pc_err_st"].median(), "max": df["pc_err_st"].max()}
    err_vir_stats = {
        "median": df["pc_err_vir"].median(),
        "max": df["pc_err_vir"].max(),
    }
    err_id_stats = {"median": df["pc_err_id"].median(), "max": df["pc_err_id"].max()}

    # Calculate mean, median, quartiles, and max for time column
    time_stats = {
        "mean": df["time_s"].mean(),
        "median": df["time_s"].median(),
        "q1": df["time_s"].quantile(0.25),
        "q3": df["time_s"].quantile(0.75),
        "max": df["time_s"].max(),
    }

    # Format the table
    table = f"""
    Benchmarking Results Analysis
    -----------------------------
    Tests passed: {passed_tests} / {total_tests} ({pass_fraction:.2%})

    Error Statistics
    -----------------------------------------
    | Error Type  | Median     | Max        |
    |-------------|------------|------------|
    | pc_err_st   | {err_st_stats['median']:10.2f} | {err_st_stats['max']:10.2f} |
    | pc_err_vir  | {err_vir_stats['median']:10.2f} | {err_vir_stats['max']:10.2f} |
    | pc_err_id   | {err_id_stats['median']:10.2f} | {err_id_stats['max']:10.2f} |

    Time Statistics (s)
    ------------------------
    | Statistic |   Value  |
    |-----------|----------|
    | Mean      | {time_stats['mean']:8.2f} |
    | Median    | {time_stats['median']:8.2f} |
    | Q1        | {time_stats['q1']:8.2f} |
    | Q3        | {time_stats['q3']:8.2f} |
    | Max       | {time_stats['max']:8.2f} |
    """
    print(table)

def calc_time_diff(csv_ref, csv_new):
    """
    Calculate the average percentage difference in timings between two atoMEC versions.

    Parameters
    ----------
    csv_ref : str
        Filepath to the reference CSV file.
    csv_new : str
        Filepath to the new CSV file to compare against the reference.

    Returns
    -------
    float
        The average absolute percentage difference of the 'time_s' column
        between the reference and new datasets.

    Notes
    -----
    The percentage difference is calculated using the formula:
    100 * abs(time_new - time_ref) / time_ref
    This formula gives the average of the absolute relative differences
    from the reference to the new values.
    """
    # Read the time_s column from each CSV into a DataFrame
    df_ref = pd.read_csv(csv_ref)["time_s"]
    df_new = pd.read_csv(csv_new)["time_s"]

    # Calculate the absolute percentage difference
    time_diff_pc = 100 * (df_ref - df_new) / df_ref

    # Return the mean of these percentage differences, rounded to 2 decimal places
    return round(time_diff_pc.mean(), 2)

def comp_benchmark_results(csv_ref, csv_new):
    """
    Compare benchmark results between a reference CSV file and a new CSV file.

    Prints individual test and timings results, and finally does a row-by-row
    percentage difference of timings.

    Parameters
    ----------
    csv_ref : str
        Filepath to the reference CSV file containing benchmark results.
    csv_new : str
        Filepath to the new CSV file containing benchmark results to be compared.

    Returns
    -------
    None
    """
    # Print results from the reference CSV
    print("\nResults from reference csv")
    print("--------------------------")
    analyze_benchmark_results(csv_ref)

    # Print results from the new CSV
    print("\nResults from new csv")
    print("--------------------------")
    analyze_benchmark_results(csv_new)

    # Calculate and print the average time percentage difference
    avg_time_diff = calc_time_diff(csv_ref, csv_new)
    print("\n-------------------------------------")
    print(f" Average time % difference = {avg_time_diff}% ")
    print("-------------------------------------")


import os
import random
import torch
from scipy.sparse import csr_matrix
import numpy as np
import time
from collections import defaultdict

class DataLoader:
    def __init__(self, task_dir):
        self.task_dir = task_dir

        if  task_dir == 'data/Dis_5fold_user/' or task_dir == 'data/Dis_5fold_item/' or  task_dir == 'data/new_last-fm/'or  task_dir == 'data/new_amazon-book/'or  task_dir == 'data/new_alibaba-fashion/':
            self.all_cf = self.read_cf(self.task_dir + 'train_1.txt')  # all_cf  (np.array)
            self.test_cf = self.read_cf(self.task_dir + 'test_1.txt')
        else:
            self.all_cf = self.read_cf(self.task_dir + 'train.txt')
            self.test_cf = self.read_cf(self.task_dir + 'test.txt')

        self.n_users = max(max(self.all_cf[:,0]),max(self.test_cf[:,0])) + 1
        self.n_items = max(max(self.all_cf[:,1]),max(self.test_cf[:,1])) + 1
        self.known_user_set = self.cf_to_set(self.all_cf)
        self.test_user_set = self.cf_to_set(self.test_cf)

        n_all = self.all_cf.shape[0]
        rand_idx = np.random.permutation(n_all)
        self.all_cf = self.all_cf[rand_idx]

        self.triple = self.read_triples('kg.txt')

        self.arraytriple = np.asarray(self.triple)
        self.n_ent = max(max(self.arraytriple[:, 0]), max(self.arraytriple[:, 2])) + 1
        self.n_nodes = self.n_ent + self.n_users    # user + entity
        self.n_rel = max(self.arraytriple[:,1]) + 1

        if task_dir == 'data/Dis_5fold_item/'or  task_dir == 'data/new_last-fm/'or  task_dir == 'data/new_amazon-book/'or  task_dir == 'data/new_alibaba-fashion/':
            self.item_set = self.cf_to_item_set(self.all_cf)
            self.facts_cf, self.train_cf = self.generate_inductive_train(self.all_cf)
        else:
            self.facts_cf = self.all_cf[0:n_all*6//7]
            self.train_cf = self.all_cf[n_all*6//7:]

        self.fact_triple = self.cf_to_triple(self.facts_cf)
        self.train_triple = self.cf_to_triple(self.train_cf)
        self.test_triple = self.cf_to_triple(self.test_cf)

        # add inverse
        self.d_triple  = self.double_triple(self.triple)

        # add interact and user into triplets
        self.fact_data, self.known_data = self.interact_triple(self.d_triple)

        # use user-kg
        if  task_dir == 'data/Dis_5fold_user/' or task_dir == 'data/Dis_5fold_item/' :
            self.readukg = 1
            self.ukg = self.read_user_kg()
            self.n_rel += 1
            self.fact_data += self.ukg
            self.known_data += self.ukg
            print('load user kg')
        else:
            self.readukg = 0

        self.load_graph(self.fact_data)
        self.load_test_graph(self.known_data)

        self.train_q, self.train_a, self.train_w = self.load_train_query(self.train_triple)
        self.test_q,  self.test_a  = self.load_query(self.test_triple)

        self.n_train = len(self.train_q)
        self.n_test = len(self.test_q)

        print('n_facts:',len(self.facts_cf), 'n_test_cf:', len(self.test_cf), 'n_train:', self.n_train,  'n_test:', self.n_test)
        print('users:', self.n_users,'items:', self.n_items, 'other entities:', self.n_ent - self.n_items )

    def read_cf(self, file_name):
        inter_mat = list()
        lines = open(file_name, "r").readlines()
        for al in lines:
            tmps = al.strip()
            inters = [int(i) for i in tmps.split(" ")]

            u_id, pos_ids = inters[0], inters[1:]
            pos_ids = list(set(pos_ids))
            for i_id in pos_ids:
                inter_mat.append([u_id, i_id])

        return np.array(inter_mat)   #[[u1,i1],[u1,i2],……,[un,in]]

    def read_triples(self, filename):
        triples = []
        with open(os.path.join(self.task_dir, filename)) as f:
            for line in f:
                h, r, t = line.strip().split()
                h, r, t = int(h), int(r), int(t)

                triples.append([h,r,t])

        return triples

    def double_triple(self, triples):
        new_triples = []
        for triple in triples:
            h, r, t = triple
            new_triples.append([t, r+self.n_rel, h])

        return triples + new_triples

    def interact_triple(self, triples):
        # consider  additional relations  'interact' and 'in-interact'.
        copy_tri = triples.copy()
        for id, [h, r, t] in enumerate(copy_tri):
            copy_tri[id] = [h + self.n_users, r + 2, t + self.n_users]

        fact_user_triple = []

        for uitriple in self.fact_triple:
            u , i = uitriple[0], uitriple[2]

            fact_user_triple.append([u, 0, i])
            fact_user_triple.append([i, 1, u])

        train_user_triple = []
        for uitriple in self.train_triple:
            u , i = uitriple[0], uitriple[2]

            train_user_triple.append([u, 0, i])
            train_user_triple.append([i, 1, u])
        return copy_tri + fact_user_triple,   copy_tri + fact_user_triple + train_user_triple

    def cf_to_triple(self, cf):
        cf = list(cf)
        newtriple = []
        for [u,i] in cf :
            if u >= self.n_users:
                continue
            i = i + self.n_users
            newtriple.append([u, 0, i ])
        return newtriple

    def cf_to_set(self, cf):
        cf = list(cf)
        user_set = defaultdict(list)
        for [u, i] in cf :
            if u >= self.n_users:
                print("unexpected users")
                continue
            user_set[u].append(i + self.n_users)
        return user_set

    def read_user_kg(self):
        ukg = []
        with open(os.path.join(self.task_dir, 'ukg.txt')) as f:
            for line in f:
                h, r, t = line.strip().split()
                h, r, t = int(h), int(r), int(t)
                if h >= self.n_users or t >= self.n_users:
                    continue
                ukg.append([h, 2*self.n_rel + 2, t])
                ukg.append([t, 2*self.n_rel + 3, h])
        return ukg

    def cf_to_item_set(self, cf):  # item_set[i] = [u1, u3, u4……]
        cf = list(cf)
        item_set = defaultdict(list)
        for [u, i] in cf :
            if u >= self.n_users:
                print("unexpected users")
                continue
            item_set[i].append(u)
        return item_set

    def check_item_inkg(self, triple):    # return d(item) in kg
        it_inkg = np.zeros((self.n_items,1))
        for h,r,t in triple:
            if h < self.n_items:
                it_inkg[h] += 1
            if t < self.n_items:
                it_inkg[t] += 1
        return it_inkg

    def generate_inductive_train(self, cf):
        fcf = cf.tolist()
        n_train = 0
        train_cf = []
        ind_item = []
        while(n_train < len(cf) / 8):
            item = random.randint(0, self.n_items-1)
            if item in ind_item:
                continue
            for u in self.item_set[item]:
                train_cf.append([u,item])
                fcf.remove([u,item])      # as fact_cf
            ind_item.append(item)
            n_train += len(self.item_set[item])

        return np.array(fcf), np.array(train_cf)

    def load_graph(self, triples):
        idd = np.concatenate([np.expand_dims(np.arange(self.n_nodes),1), (2*self.n_rel+2)*np.ones((self.n_nodes, 1)), np.expand_dims(np.arange(self.n_nodes),1)], 1)

        self.KG = np.concatenate([np.array(triples), idd], 0)

        self.n_fact = len(self.KG)
        self.M_sub = csr_matrix((np.ones((self.n_fact,)), (np.arange(self.n_fact), self.KG[:,0])), shape=(self.n_fact, self.n_nodes))

    def load_test_graph(self, triples):
        idd = np.concatenate([np.expand_dims(np.arange(self.n_nodes),1), (2*self.n_rel+2)*np.ones((self.n_nodes, 1)), np.expand_dims(np.arange(self.n_nodes),1)], 1)

        self.tKG = np.concatenate([np.array(triples), idd], 0)

        self.tn_fact = len(self.tKG)
        self.tM_sub = csr_matrix((np.ones((self.tn_fact,)), (np.arange(self.tn_fact), self.tKG[:,0])), shape=(self.tn_fact, self.n_nodes))

    def load_train_query(self, triples):
        triples.sort(key=lambda x:(x[0], x[1]))
        pos_items = defaultdict(lambda:list())
        neg_items = defaultdict(list)

        for trip in triples:
            h, r, t = trip
            pos_items[(h,r)].append(t)
            while True:
                neg_item = np.random.randint(low=self.n_users, high=self.n_users + self.n_items, size=1)[0]  #重要修改！low=n_users
                if neg_item not in self.known_user_set[h]:
                    break
            neg_items[(h,r)].append(neg_item)

        queries = []
        answers = []
        wrongs = []
        for key in pos_items:
            queries.append(key)
            answers.append(np.array(pos_items[key]))
            wrongs.append(np.array(neg_items[key]))

        return queries, answers, wrongs

    def load_query(self, triples):
        triples.sort(key=lambda x:(x[0], x[1]))
        trip_hr = defaultdict(lambda:list())

        for trip in triples:
            h, r, t = trip
            trip_hr[(h,r)].append(t)

        queries = []
        answers = []
        for key in trip_hr:
            queries.append(key)
            answers.append(np.array(trip_hr[key]))
        return queries, answers

    def get_neighbors(self, nodes, mode='train'):

        if mode=='train':
            KG = self.KG
            M_sub = self.M_sub
        else:
            KG = self.tKG
            M_sub = self.tM_sub

        # nodes: n(node) x 2 with (batch_idx, node_idx)
        node_1hot = csr_matrix((np.ones(len(nodes)), (nodes[:,1], nodes[:,0])), shape=(self.n_nodes, nodes.shape[0]))
        edge_1hot = M_sub.dot(node_1hot)
        edges = np.nonzero(edge_1hot)
        sampled_edges = np.concatenate([np.expand_dims(edges[1],1), KG[edges[0]]], axis=1)     # (batch_idx, head, rela, tail)
        sampled_edges = torch.LongTensor(sampled_edges).cuda()

        # index to nodes
        head_nodes, head_index = torch.unique(sampled_edges[:,[0,1]], dim=0, sorted=True, return_inverse=True)
        tail_nodes, tail_index = torch.unique(sampled_edges[:,[0,3]], dim=0, sorted=True, return_inverse=True)

        sampled_edges = torch.cat([sampled_edges, head_index.unsqueeze(1), tail_index.unsqueeze(1)], 1)

        mask = sampled_edges[:,2] == (self.n_rel*2 + 2)
        _, old_idx = head_index[mask].sort()
        old_nodes_new_idx = tail_index[mask][old_idx]

        return tail_nodes, sampled_edges, old_nodes_new_idx

    def get_batch(self, batch_idx, steps=2, data='train'):
        if data=='train':
            query, answer, wrongs = np.array(self.train_q), self.train_a, self.train_w
        if data=='test':
            query, answer = np.array(self.test_q), np.array(self.test_a)

        subs = []
        rels = []
        objs = []
        pos = []
        neg =[]
        subs = query[batch_idx, 0]
        rels = query[batch_idx, 1]

        if data =='train':
            pos = answer[batch_idx[0]:batch_idx[-1]+1]
            neg = wrongs[batch_idx[0]:batch_idx[-1]+1]
            return subs, rels, pos, neg
        else :
            objs = np.zeros((len(batch_idx), self.n_nodes))
            for i in range(len(batch_idx)):
                objs[i][answer[batch_idx[i]]] = 1
            return subs, rels, objs

    def shuffle_train(self,):

        if self.task_dir == 'data/Dis_5fold_item/' :
            self.facts_cf, self.train_cf = self.generate_inductive_train(self.all_cf)
            self.fact_triple = self.cf_to_triple(self.facts_cf)
            self.train_triple = self.cf_to_triple(self.train_cf)

            self.fact_data,_ = self.interact_triple(self.d_triple)
            if self.readukg == 1:
                self.fact_data += self.ukg
            self.load_graph(self.fact_data)
            self.train_q, self.train_a, self.train_w = self.load_train_query(self.train_triple)
            self.n_train = len(self.train_q)
        elif self.task_dir == 'data/new_last-fm/'or  self.task_dir == 'data/new_amazon-book/'or  self.task_dir == 'data/new_alibaba-fashion/':
            self.train_triple = np.array(self.train_triple)
            n_all = len(self.train_triple)
            rand_idx = np.random.permutation(n_all)
            self.train_triple = self.train_triple[rand_idx].tolist()
            self.train_q, self.train_a, self.train_w = self.load_train_query(self.train_triple)
            self.n_train = len(self.train_q)
        else:
            fact_triple = np.array(self.fact_triple)
            train_triple = np.array(self.train_triple)
            all_ui_triple = np.concatenate([fact_triple, train_triple], axis=0)
            n_all = len(all_ui_triple)
            rand_idx = np.random.permutation(n_all)
            all_ui_triple = all_ui_triple[rand_idx]

            self.fact_triple = all_ui_triple[:n_all*6//7].tolist()
            self.train_triple = all_ui_triple[n_all*6//7:].tolist()

            self.fact_data,_ = self.interact_triple(self.d_triple)
            if self.readukg == 1:
                self.fact_data += self.ukg
            self.load_graph(self.fact_data)
            self.train_q, self.train_a, self.train_w = self.load_train_query(self.train_triple)
            self.n_train = len(self.train_q)


import sys

n, m, d = map(int, sys.stdin.readline().split())

board = []

for i in range(n):
    k = list(map(int, sys.stdin.readline().split()))
    board.append(k)

def aRange(a):
    x = a[0]
    y = a[1]
    a_atack = []
    for i in range(-1, -(d+1), -1):
        for j in range(-d+1, d-1+1):
            if 0 <= x+i < n and 0 <= y+j < m:
                value = abs(i) + abs(j)
                if value <= d:
                    a_atack.append([x+i, y+j])
    return a_atack

def play(a, b, c):
    global board

    a_Range = []
    count = 0

    tmp_board = [item[:] for item in board]

    for i in [a, b, c]:
        k = aRange(i)
        k.sort(key=lambda x: (abs(i[0]-x[0]) + abs(i[1]-x[1]), x[1]) )
        a_Range.append(k)
    t = True

    while t:

        for arc in a_Range:
            for a in arc:
                if tmp_board[a[0]][a[1]] == 1:
                    tmp_board[a[0]][a[1]] = 2
                    count += 1
                    break
                elif tmp_board[a[0]][a[1]] == 2:
                    break

        t = False

        for i in range(n):
            for j in range(m):
                if tmp_board[i][j] == 2:
                    tmp_board[i][j] = 0
                elif tmp_board[i][j] == 1:
                    t = True

        tmp_board = [[0] * m] + tmp_board
        tmp_board.pop()

    return count

visited = [0] * m
ac = []
mac = 0
def dfs(idx):
    global mac
    if len(ac) == 3:
        hhh = [[n, ac[0]], [n, ac[1]], [n, ac[2]]]
        ccc = play(hhh[0], hhh[1], hhh[2])
        if ccc > mac:
            mac = ccc
        return

    for i in range(idx, m):
        if not visited[i]:
            ac.append(i)
            visited[i] = 1
            dfs(i)
            visited[i] = 0
            ac.pop()

dfs(0)

print(mac)

# 7 6 2
# 0 1 1 0 1 0
# 1 1 0 1 0 0
# 1 0 1 0 0 1
# 0 1 0 0 1 0
# 1 0 0 1 0 1
# 0 0 1 0 1 1
# 0 1 0 1 1 0

알고리즘 분류/구현/캐슬 디펜스.py


import serial
from time import sleep
from serial import Serial

ser = serial.Serial("/dev/ttyS0",38400)

while True:
    ser.write(b'1')

    rd=ser.read().decode('utf-8')
    sleep(1)
    dl=ser.inWaiting()
    rd+=ser.read(dl)
    print(rd)


"""Implemenation of pixel map.

It is used for storing colors of image pixels and calculating their entropy.
"""
import numpy as np
from dataclasses import dataclass

@dataclass
class Pixel:
    """Data class representing single pixel of the image.

    Pixel consist of three RGB colors.
    """
    red: np.uint8
    green: np.uint8
    blue: np.uint8

    @property
    def color(self):
        """Whole color value of the pixel."""
        return (self.red << 16) + (self.green << 8) + self.blue

    def __sub__(self, other):
        return PixelDifference(
            clamp(np.int16(self.red) - np.int16(other.red), -32768, 32767),
            clamp(np.int16(self.green) - np.int16(other.green), -32768, 32767),
            clamp(np.int16(self.blue) - np.int16(other.blue), -32768, 32767)
        )

    def __add__(self, other):
        return Pixel(
            clamp(self.red + other.red, 0, 255),
            clamp(self.green + other.green, 0, 255),
            clamp(self.blue + other.blue, 0, 255)
        )

def get_pixel(pixel_difference):
    return Pixel(
        clamp(pixel_difference.red, 0, 255),
        clamp(pixel_difference.green, 0, 255),
        clamp(pixel_difference.blue, 0, 255),
    )

def clamp(number, minimum, maximum):
    if number > maximum:
        return maximum
    if number < minimum:
        return minimum
    return number

@dataclass
class PixelDifference:
    """Data class representing difference between two pixels.

    PixelDifference consist of three RGB color values. However they can be bigger than 255 and negative.
    """
    red: np.int16
    green: np.int16
    blue: np.int16

    def __add__(self, other):
        return PixelDifference(
            self.red + other.red,
            self.green + other.green,
            self.blue + other.blue
        )

    def __sub__(self, other):
        return PixelDifference(
            self.red - other.red,
            self.green - other.green,
            self.blue - other.blue
        )

class PixelMap:
    """Map wrapper of the image pixels.

    Pixel Map stores pixels of the image.
    """

    def __init__(self, height, width):
        """
        Initialize new instance of Pixel Map with a given height and width of an image.

        Args:
            height (int): height of the pixel table to create
            width (int): width of the pixel table to create
        """
        self.width = width
        self.height = height
        self.pixels = np.empty((height, width), dtype=Pixel)

    def __getitem__(self, idx):
        """Return pixel on the given idx coordinates.

        -- idx - tuple of (row, col)
        """
        row, col = idx
        return self.pixels[row, col]

    @classmethod
    def from_vector(cls, vector, height, width):
        assert vector.size == height * width
        new_pixel_map = cls(height, width)
        for row in range(height):
            for col in range(width):
                pixel = vector[row*width + col]
                new_pixel_map.new_pixel(row, col, pixel.red, pixel.green, pixel.blue)

        return new_pixel_map

    def new_pixel(self, row, col, red, green, blue):
        """Assign new pixel to (row, col) with given RGB color ingredients.

        -- row - pixel row, y-coordinate
        -- col - pixel col, x-coordinates
        -- red - red ingredient
        -- green - green ingredient
        -- blue - blue ingredient
        """
        assert row < self.height and col < self.width, f"Out of range: [{row}, {col}]"
        pixel = Pixel(red % 256, green % 256, blue % 256)
        self.pixels[row, col] = pixel

    @property
    def size(self):
        """Size of the pixel map, which is height * width."""
        return self.height * self.width

    def __str__(self):
        return str(self.pixels)

    def get_blocks(self, block_side):
        """Divide pixel table into blocks and return them as vectors.

        Blocks are squared size with side length of block_side. They are flattened into vectors.
        -- block_side - the length of blocks sides"""
        blocks = []
        for row_idx in range(0, self.height, block_side):
            for col_idx in range(0, self.width, block_side):
                blocks.append([(pixel.red, pixel.green, pixel.blue) for pixel in np.ndarray.flatten(self.pixels[row_idx:row_idx+block_side, col_idx:col_idx+block_side])])
        return np.array(blocks, dtype=np.uint8)


import turtle
import math
import random

#초기화 및 화면 설정
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("Collision Detection by @TokyoEdtech")
wn.tracer(0)

pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Score: 0", align="center", font=("Courier", 24, "normal"))

shapes = ["pacman.gif", "cherry.gif", "bar.gif", "ball.gif", "x.gif"]

for shape in shapes:
    wn.register_shape(shape)

class Sprite():
    def __init__(self, x, y, width, height, image):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = image

    def render(self, pen):
        pen.goto(self.x, self.y)
        pen.shape(self.image)
        pen.stamp()

    def is_distance_collision(self, other):
        distance = (((self.x - other.x) ** 2) + ((self.y - other.y) ** 2)) ** 0.5
        if distance < (self.width + other.width) / 2.0:
            return True
        else:
            return False

class Character(Sprite):
    def __init__(self, x, y, width, height, image):
        super().__init__(x, y, width, height, image)

    def move_up(self):
        self.y += 24

    def move_down(self):
        self.y -= 24

    def move_left(self):
        self.x -= 24

    def move_right(self):
        self.x += 24

class Cherry(Sprite):
    def __init__(self, x, y, width, height, image):
        super().__init__(x, y, width, height, image)

    def reset_position(self):
        self.x = random.randint(-200, 200)
        self.y = random.randint(-200, 200)

#팩맨 캐릭터 위치 지정 및 체리 생성
pacman = Character(-128, 0, 128, 128, "pacman.gif")
cherry1 = Cherry(random.randint(-200, 200), random.randint(-200, 200), 128, 128, "cherry.gif")
cherry2 = Cherry(random.randint(-200, 200), random.randint(-200, 200), 128, 128, "cherry.gif")
cherry3 = Cherry(random.randint(-200, 200), random.randint(-200, 200), 128, 128, "cherry.gif")
cherry4 = Cherry(random.randint(-200, 200), random.randint(-200, 200), 128, 128, "cherry.gif")
cherry5 = Cherry(random.randint(-200, 200), random.randint(-200, 200), 128, 128, "cherry.gif")

sprites = [pacman, cherry1, cherry2, cherry3, cherry4, cherry5]

def move_pacman_up():
    pacman.move_up()

def move_pacman_down():
    pacman.move_down()

def move_pacman_left():
    pacman.move_left()

def move_pacman_right():
    pacman.move_right()

def update_score(score):
    pen.clear()
    pen.write(f"Score: {score}", align="center", font=("Courier", 24, "normal"))

wn.listen()
wn.onkeypress(move_pacman_up, "w")
wn.onkeypress(move_pacman_down, "s")
wn.onkeypress(move_pacman_left, "a")
wn.onkeypress(move_pacman_right, "d")

score = 0
game_over = False

while not game_over:
    for sprite in sprites:
        sprite.render(pen)

    if pacman.is_distance_collision(cherry1):
        cherry1.reset_position()
        score += 1
        update_score(score)

    if pacman.is_distance_collision(cherry2):
        cherry2.reset_position()
        score += 1
        update_score(score)

    if pacman.is_distance_collision(cherry3):
        cherry3.reset_position()
        score += 1
        update_score(score)

    if pacman.is_distance_collision(cherry4):
        cherry4.reset_position()
        score += 1
        update_score(score)

    if pacman.is_distance_collision(cherry5):
        cherry5.reset_position()
        score += 1
        update_score(score)

    wn.update()
    pen.clearstamps()


import random
from typing import Literal
from icecream import ic

CUADRILLA = {
    'Marion': 'Olivier',
    'Leire': 'Sergio',
    'Nora': 'Jon',
    'Naiara': 'Jorge',
    'Marta': 'Andrés',
    'Estela': 'Odei',
    'Idoia': 'Eneko',
}

LISTA_COLORES = [
    '#0da68c',
    '#24b568',
    '#6fc45c',
    '#ced42f',
    '#6c9600',
    '#26A69A',
    '#4CAF50',
    '#7CB342',
    '#C0CA33',
    '#FDD835',
    '#FFB300',
    '#FF9800',
    '#FB8C00',
    '#F4511E',
]
LISTA_COLORES_AVATAR = [
    '#263238',
    '#37474F',
    '#455A64',
    '#546E7A',
    '#607D8B',
    '#5C6BC0',
    '#3949AB',
    '#283593',
    '#1A237E',
    '#880E4F',
    '#AD1457',
    '#C2185B',
    '#D81B60',
    '#E91E63',
]

async def lista_cuadrilla() -> list[str]:
    lista_nombres = []
    for item in CUADRILLA.items():
        lista_nombres.append(item[0])
        lista_nombres.append(item[1])
    return sorted(lista_nombres)

async def crear_dict_persona_color(tipo:Literal["avatar", "grafico"]='grafico') -> dict:
    lista = LISTA_COLORES if tipo == 'grafico' else LISTA_COLORES_AVATAR
    persona_color_dict = {}
    lista_nombres = await lista_cuadrilla()
    for nombre, color in zip(lista_nombres, lista):
        persona_color_dict[nombre] = color

    return persona_color_dict

#! No se usa
def generar_color_aleatorio():
    return '#{:02x}{:02x}{:02x}'.format(random.randint(100, 255),
                                       random.randint(100, 255),
                                       random.randint(100, 255))

async def get_color_async(nombre:str, tipo:Literal["avatar", "grafico"]='grafico') -> str:
    """Devuelve el color asociado a la persona

    Parameters
    ----------
    nombre : str
        _description_

    Returns
    -------
    str
        _description_
    """
    persona_color_dict = await crear_dict_persona_color(tipo)
    return persona_color_dict[nombre]

class Switch:
    def __init__(self, initial_state:bool=True) -> None:
        self.state = initial_state

    def accionar(self) -> None:
        self.state = not self.state


"""Add subscribe column to user table

Revision ID: 4e435ff8ba74
Revises: bbba2255e00
Create Date: 2015-02-09 10:36:45.935116

"""

# revision identifiers, used by Alembic.
revision = '4e435ff8ba74'
down_revision = 'bbba2255e00'

from alembic import op
import sqlalchemy as sa

def upgrade():
    op.add_column('user', sa.Column('subscribed', sa.Boolean, default=True))
    query = 'UPDATE "user" SET subscribed=true;'
    op.execute(query)

def downgrade():
    op.drop_column('user', 'subscribed')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Utilities to handle and manipulate AirQualityStationCollection objects
"""

import json
import logging
import warnings

from collections import defaultdict
from itertools import groupby

from itaqa.core.AirQualityStation import AirQualityStation
from itaqa.core.AirQualityStationCollection import AirQualityStationCollection
from itaqa.utils.AQS_utils import merge_AQS_data

logger = logging.getLogger(__name__)

def group_by_name(AQSC):
    """Return a dict with as key the name of the station and as value a list of AQS objects"""
    AQS_by_name = defaultdict(list)
    for k, g in groupby(AQSC.AQS_list, lambda x: x.name):
        for station in g:
            AQS_by_name[k].append(station)
    return AQS_by_name

def merge_by_group(AQSC, AQS_group):
    """Merge multiple groups of AQS and return a list of merged AQS objects"""
    for k in AQS_group:
        # Setup new resulting AQS
        new_AQS = AirQualityStation(k)
        new_AQS.set_address(region=AQS_group[k][0].region,
                            province=AQS_group[k][0].province,
                            comune=AQS_group[k][0].comune)
        # TODO: Compute geolocation and check if they are not so nearby
        new_AQS.metadata['premerge_history'] = {}
        frames = []

        for station in AQS_group[k]:
            frames.append(station.data.set_index('Timestamp'))
            # TODO: Refactor to handle stations with more than one pollutant before merge
            cols = station.data.columns.to_list()
            cols.remove('Timestamp')
            pollutant = cols[0]
            new_AQS.metadata['premerge_history'][pollutant] = {}
            new_AQS.metadata['premerge_history'][pollutant]['name'] = station.name
            new_AQS.metadata['premerge_history'][pollutant]['geolocation'] = station.geolocation

        # Take first frame and merge all the others
        merged_df = frames.pop()
        for frame in frames:
            merged_df = merged_df.merge(frame, how='outer', left_index=True, right_index=True)
        merged_df.reset_index(inplace=True)
        new_AQS.data = merged_df

        # Remove from AQSC the merged stations and add the new one
        AQSC.remove([AQS.uuid for AQS in AQS_group[k]])
        AQSC.add(new_AQS)

def remove_empty_stations(AQSC):
    """Remove AQS without any data inside"""
    empty_stations = [AQS.uuid for AQS in AQSC.AQS_list if AQS.data.size < 1]
    if empty_stations:
        AQSC.remove(empty_stations)

def merge_AQSC(AQSC1, AQSC2):
    """
    Merge the data of two AQSCs and return a new AQSC

    Given two AQSCs, check the amount of AQSs and merge them
    This function is to be used to merge AQSs containing data relative to different timestamps
    For example to merge two collections relative to different years
    """
    if len(AQSC1.AQS_list) != len(AQSC2.AQS_list):
        warning.warn("The AQSCs contain a different number of AQSs")

    new_AQSC = AirQualityStationCollection()

    AQSC1_names = [AQS.name for AQS in AQSC1.AQS_list]
    AQSC2_names = [AQS.name for AQS in AQSC2.AQS_list]

    AQS_names = list(set(AQSC1_names) & set(AQSC2_names))
    AQS_names.sort()

    for AQS_name in AQS_names:
        AQS1 = AQSC1.search(AQS_name)
        AQS2 = AQSC2.search(AQS_name)
        merged_AQS = merge_AQS_data([AQS1, AQS2])
        new_AQSC.add(merged_AQS)

    return new_AQSC

def merge_AQSC_multiple(AQSC_list):
    """
    Merge the data of multiple AQSCs and return a new AQSC

    Given a list of AQSC, check the amount of AQS contained in each and merge them
    This function is to be used to merge AQSs containing data relative to different timestamps
    For example to merge two collections relative to different years
    """
    new_AQSC = AirQualityStationCollection()

    all_names = list()
    for AQSC in AQSC_list:
        all_names.append([AQS.name for AQS in AQSC.AQS_list])

    AQS_names = list(set().union(*all_names))
    AQS_names.sort()

    for AQS_name in AQS_names:
        AQSs_to_merge = list()
        for AQSC in AQSC_list:
            AQS = AQSC.search(AQS_name)
            AQSs_to_merge.append(AQS)
        merged_AQS = merge_AQS_data(AQSs_to_merge)
        new_AQSC.add(merged_AQS)

    return new_AQSC


import datetime
import time
from typing import Optional

from nornir.core.exceptions import NornirSubTaskError
from nornir.core.task import MultiResult
from nornir_napalm.plugins.tasks import napalm_cli, napalm_get
from nornir_netmiko.tasks import netmiko_send_command

from cnaas_nms.db.device import Device, DeviceType
from cnaas_nms.db.job import Job
from cnaas_nms.db.session import redis_session, sqla_session
from cnaas_nms.devicehandler.nornir_helper import NornirJobResult, cnaas_init, inventory_selector
from cnaas_nms.devicehandler.sync_history import add_sync_event
from cnaas_nms.scheduler.thread_data import set_thread_data
from cnaas_nms.scheduler.wrapper import job_wrapper
from cnaas_nms.tools.log import get_logger

class FirmwareAlreadyActiveException(Exception):
    pass

def arista_pre_flight_check(task, job_id: Optional[int] = None) -> str:
    """
    NorNir task to do some basic checks before attempting to upgrade a switch.

    Args:
        task: NorNir task

    Returns:
        String, describing the result

    """
    set_thread_data(job_id)
    logger = get_logger()
    with sqla_session() as session:
        if Job.check_job_abort_status(session, job_id):
            return "Pre-flight aborted"

    flash_diskspace = "bash timeout 5 df /mnt/flash | awk '{print $4}'"
    flash_cleanup = 'bash timeout 30 ls -t /mnt/flash/*.swi | tail -n +2 | grep -v `cut -d"/" -f2 /mnt/flash/boot-config` | xargs rm -f'

    # Get amount of free disk space
    res = task.run(napalm_cli, commands=[flash_diskspace])
    if not isinstance(res, MultiResult) or len(res.result.keys()) != 1:
        raise Exception("Could not check free space")

    # Remove old firmware images if needed
    free_bytes = next(iter(res.result.values())).split("\n")[1]
    if int(free_bytes) < 2500000:
        logger.info("Cleaning up old firmware images on {}".format(task.host.name))
        res = task.run(napalm_cli, commands=[flash_cleanup])
    else:
        logger.info("Enough free space ({}b), no cleanup".format(free_bytes))

    return "Pre-flight check done."

def arista_post_flight_check(task, post_waittime: int, scheduled_by: str, job_id: Optional[int] = None) -> str:
    """
    NorNir task to update device facts after a switch have been upgraded

    Args:
        task: NorNir task
        post_waittime: Time to wait before trying to gather facts
        scheduled_by: Who scheduled the job
        job_id: Job ID

    Returns:
        String, describing the result

    """
    set_thread_data(job_id)
    logger = get_logger()
    time.sleep(int(post_waittime))
    logger.info("Post-flight check wait ({}s) complete, starting check for {}".format(post_waittime, task.host.name))
    with sqla_session() as session:
        if Job.check_job_abort_status(session, job_id):
            return "Post-flight aborted"

    try:
        res = task.run(napalm_get, getters=["facts"])
        os_version = res[0].result["facts"]["os_version"]

        with sqla_session() as session:
            dev: Device = session.query(Device).filter(Device.hostname == task.host.name).one()
            prev_os_version = dev.os_version
            dev.os_version = os_version
            if prev_os_version == os_version:
                logger.error("OS version did not change, activation failed on {}".format(task.host.name))
                raise Exception("OS version did not change, activation failed")
            else:
                dev.confhash = None
                dev.synchronized = False
                add_sync_event(task.host.name, "firmware_upgrade", scheduled_by, job_id)
                dev.last_seen = datetime.datetime.utcnow()
    except Exception as e:
        logger.exception("Could not update OS version on device {}: {}".format(task.host.name, str(e)))
        return "Post-flight failed, could not update OS version: {}".format(str(e))

    return "Post-flight, OS version updated from {} to {}.".format(prev_os_version, os_version)

def arista_firmware_download(task, filename: str, httpd_url: str, job_id: Optional[int] = None) -> str:
    """
    NorNir task to download firmware image from the HTTP server.

    Args:
        task: NorNir task
        filename: Name of the file to download
        httpd_url: Base URL to the HTTP server
        job_id: Job ID

    Returns:
        String, describing the result

    """
    set_thread_data(job_id)
    logger = get_logger()
    with sqla_session() as session:
        if Job.check_job_abort_status(session, job_id):
            return "Firmware download aborted"

    url = httpd_url + "/" + filename

    try:
        with sqla_session() as session:
            dev: Device = session.query(Device).filter(Device.hostname == task.host.name).one_or_none()
            device_type = dev.device_type

        if device_type == DeviceType.ACCESS:
            firmware_download_cmd = "copy {} flash:".format(url)
        else:
            firmware_download_cmd = "copy {} vrf MGMT flash:".format(url)

        res = task.run(
            netmiko_send_command, command_string=firmware_download_cmd.replace("//", "/"), enable=True, read_timeout=500
        )

        if "Copy completed successfully" in res.result:
            return "Firmware download done."
        else:
            logger.debug(
                "Firmware download failed on {} ('{}'): {}".format(task.host.name, firmware_download_cmd, res.result)
            )
            raise Exception(
                "Copy command did not complete successfully: {}".format(
                    ", ".join(filter(lambda x: x.startswith("get:"), res.result.splitlines()))
                )
            )

    except NornirSubTaskError as e:
        subtask_result = e.result[0]
        logger.error("{} failed to download firmware: {}".format(task.host.name, subtask_result))
        logger.debug("{} download subtask result: {}".format(task.host.name, subtask_result.result))
        raise Exception("Failed to download firmware: {}".format(subtask_result))
    except Exception as e:
        logger.error("{} failed to download firmware: {}".format(task.host.name, e))
        raise Exception("Failed to download firmware: {}".format(e))

    return "Firmware download done."

def arista_firmware_activate(task, filename: str, job_id: Optional[int] = None) -> str:
    """
    NorNir task to modify the boot config for new firmwares.

    Args:
        task: NorNir task
        filename: Name of the new firmware image
        job_id: Job ID

    Returns:
        String, describing the result

    """
    set_thread_data(job_id)
    logger = get_logger()
    with sqla_session() as session:
        if Job.check_job_abort_status(session, job_id):
            return "Firmware activate aborted"

    try:
        boot_file_cmd = "boot system flash:{}".format(filename)

        res = task.run(netmiko_send_command, command_string="enable", expect_string=".*#")

        res = task.run(netmiko_send_command, command_string='show boot-config | grep -o "\\w*{}\\w*"'.format(filename))
        if res.result == filename:
            raise FirmwareAlreadyActiveException(
                "Firmware already activated in boot-config on {}".format(task.host.name)
            )

        res = task.run(netmiko_send_command, command_string="conf t", expect_string=".*config.*#")

        res = task.run(netmiko_send_command, command_string=boot_file_cmd, read_timeout=120)

        res = task.run(netmiko_send_command, command_string="end", expect_string=".*#")

        res = task.run(netmiko_send_command, command_string='show boot-config | grep -o "\\w*{}\\w*"'.format(filename))

        if not isinstance(res, MultiResult):
            raise Exception("Could not check boot-config on {}".format(task.host.name))

        if res.result != filename:
            raise Exception("Firmware not activated properly on {}".format(task.host.name))
    except FirmwareAlreadyActiveException as e:
        raise e
    except Exception as e:
        logger.exception("Failed to activate firmware on {}: {}".format(task.host.name, str(e)))
        raise Exception("Failed to activate firmware")

    return "Firmware activate done."

def arista_device_reboot(task, job_id: Optional[int] = None) -> str:
    """
    NorNir task to reboot a single device.

    Args:
        task: NorNir task.
        job_id: Job ID

    Returns:
        String, describing the result

    """
    set_thread_data(job_id)
    logger = get_logger()
    with sqla_session() as session:
        if Job.check_job_abort_status(session, job_id):
            return "Reboot aborted"

    try:
        task.run(netmiko_send_command, command_string="enable", expect_string=".*#")

        task.run(netmiko_send_command, command_string="write", expect_string=".*#")

        task.run(netmiko_send_command, command_string="reload force", max_loops=2, expect_string=".*")
    except Exception as e:  # noqa: S110
        logger.exception("Failed to reboot switch {}: {}".format(task.host.name, str(e)))
        raise e

    return "Device reboot done."

def device_upgrade_task(
    task,
    job_id: int,
    scheduled_by: str,
    filename: str,
    url: str,
    reboot: Optional[bool] = False,
    download: Optional[bool] = False,
    pre_flight: Optional[bool] = False,
    post_flight: Optional[bool] = False,
    post_waittime: Optional[int] = 0,
    activate: Optional[bool] = False,
) -> NornirJobResult:

    # If pre-flight is selected, execute the pre-flight task which
    # will verify the amount of disk space and so on.
    set_thread_data(job_id)
    logger = get_logger()
    if pre_flight:
        logger.info("Running pre-flight check on {}".format(task.host.name))
        try:
            res = task.run(task=arista_pre_flight_check, job_id=job_id)
        except Exception as e:
            logger.exception("Exception while doing pre-flight check: {}".format(str(e)))
            raise Exception("Pre-flight check failed")
        else:
            if res.failed:
                logger.exception("Pre-flight check failed for: {}".format(" ".join(res.failed_hosts.keys())))
                raise

    # If download is true, go ahead and download the firmware
    if download:
        # Download the firmware from the HTTP container.
        logger.info("Downloading firmware {} on {}".format(filename, task.host.name))
        try:
            res = task.run(task=arista_firmware_download, filename=filename, httpd_url=url, job_id=job_id)
        except Exception as e:
            logger.exception("Exception while downloading firmware: {}".format(str(e)))
            raise e

    # If download_only is false, continue to activate the newly downloaded
    # firmware and verify that it if present in the boot-config.
    already_active = False
    if activate:
        logger.info("Activating firmware {} on {}".format(filename, task.host.name))
        try:
            res = task.run(task=arista_firmware_activate, filename=filename, job_id=job_id)
        except NornirSubTaskError as e:
            subtask_result = e.result[0]
            logger.debug("Exception while activating firmware for {}: {}".format(task.host.name, subtask_result))
            if subtask_result.exception:
                if isinstance(subtask_result.exception, FirmwareAlreadyActiveException):
                    already_active = True
                    logger.info(
                        "Firmware already active, skipping reboot and post_flight: {}".format(subtask_result.exception)
                    )
                else:
                    logger.exception(
                        "Firmware activate subtask exception for {}: {}".format(
                            task.host.name, str(subtask_result.exception)
                        )
                    )
                    raise e
            else:
                logger.error("Activate subtask result for {}: {}".format(task.host.name, subtask_result.result))
                raise e
        except Exception as e:
            logger.exception("Exception while activating firmware for {}: {}".format(task.host.name, str(e)))
            raise e

    # Reboot the device if needed, we will then lose the connection.
    if reboot and not already_active:
        logger.info("Rebooting {}".format(task.host.name))
        try:
            res = task.run(task=arista_device_reboot, job_id=job_id)
        except Exception:  # noqa: S110
            pass

    # If post-flight is selected, execute the post-flight task which
    # will update device facts for the selected devices
    if post_flight and not already_active:
        logger.info("Running post-flight check on {}, delay start by {}s".format(task.host.name, post_waittime))
        try:
            res = task.run(
                task=arista_post_flight_check, post_waittime=post_waittime, scheduled_by=scheduled_by, job_id=job_id
            )
        except Exception as e:
            logger.exception("Failed to run post-flight check: {}".format(str(e)))
        else:
            if res.failed:
                logger.error("Post-flight check failed for: {}".format(" ".join(res.failed_hosts.keys())))

    if job_id:
        with redis_session() as db:
            db.lpush("finished_devices_" + str(job_id), task.host.name)

@job_wrapper
def device_upgrade(
    download: Optional[bool] = False,
    activate: Optional[bool] = False,
    filename: Optional[bool] = None,
    group: Optional[str] = None,
    hostname: Optional[str] = None,
    url: Optional[str] = None,
    job_id: Optional[int] = None,
    pre_flight: Optional[bool] = False,
    post_flight: Optional[bool] = False,
    post_waittime: Optional[int] = 600,
    reboot: Optional[bool] = False,
    scheduled_by: Optional[str] = None,
) -> NornirJobResult:

    logger = get_logger()
    nr = cnaas_init()
    if hostname:
        nr_filtered, dev_count, _ = inventory_selector(nr, hostname=hostname)
    elif group:
        nr_filtered, dev_count, _ = inventory_selector(nr, group=group)
    else:
        raise ValueError("Neither hostname nor group specified for device_upgrade")

    device_list = list(nr_filtered.inventory.hosts.keys())
    logger.info("Device(s) selected for firmware upgrade ({}): {}".format(dev_count, ", ".join(device_list)))
    logger.info(
        f"Upgrade tasks selected: pre_flight = {pre_flight}, download = {download}, "
        + f"activate = {activate}, reboot = {reboot}, post_flight = {post_flight}"
    )

    # Make sure we only upgrade Arista access switches
    for device in device_list:
        with sqla_session() as session:
            dev: Device = session.query(Device).filter(Device.hostname == device).one_or_none()
            if not dev:
                raise Exception("Could not find device: {}".format(device))
            if dev.platform != "eos":
                raise Exception('Invalid device platform "{}" for device: {}'.format(dev.platform, device))

    # Start tasks to take care of the upgrade
    try:
        nrresult = nr_filtered.run(
            task=device_upgrade_task,
            job_id=job_id,
            scheduled_by=scheduled_by,
            download=download,
            filename=filename,
            url=url,
            pre_flight=pre_flight,
            post_flight=post_flight,
            post_waittime=post_waittime,
            reboot=reboot,
            activate=activate,
        )
    except Exception as e:
        logger.exception("Exception while upgrading devices: {}".format(str(e)))
        return NornirJobResult(nrresult=nrresult)

    failed_hosts = list(nrresult.failed_hosts.keys())
    for hostname in failed_hosts:
        logger.error("Firmware upgrade of device '{}' failed".format(hostname))

    if nrresult.failed:
        logger.error("Not all devices were successfully upgraded")

    return NornirJobResult(nrresult=nrresult)


# import the necessary packages
# 导入必要的包
import numpy as np
import csv

class Searcher:
	def __init__(self, indexPath):
		# store the index path
		# 存储索引路径
		self.indexPath = indexPath

	def search(self, queryFeatures, limit = 10):
		# initialize the dictionary of results
		# 初始化结果字典
		results = {}

		# open the index file for reading
		# 打开索引文件进行读取
		with open(self.indexPath) as f:
			# initialize the CSV reader
			# 初始化CSV读取器
			reader = csv.reader(f)

			# loop over the rows in the index
			# 循环索引中的行
			for row in reader:
				# parse out the image ID and features, then compute the chi-squared distance between the features in our index and our query features
				# 解析图像ID和特征，然后计算索引中的特征和查询特征之间的卡方距离
				features = [float(x) for x in row[1:]]
				d = self.chi2_distance(features, queryFeatures)

				# now that we have the distance between the two feature vectors, we can udpate the results dictionary -- the key is the current image ID in the index and the value is the distance we just computed, representing how 'similar' the image in the index is to our query
				# 现在我们已经得到了两个特征向量之间的距离，我们可以创建结果字典——关键是索引中的当前图像ID，值是我们刚刚计算的距离，表示索引中的图像与查询的“相似”程度
				results[row[0]] = d

			# close the reader
			# 关闭读卡器
			f.close()

		# sort our results, so that the smaller distances (i.e. the more relevant images are at the front of the list)
		# 对结果进行排序，以便距离越小（即列表前面的相关图像越多）
		results = sorted([(v, k) for (k, v) in results.items()])

		# return our (limited) results
		# 返回我们（有限）的结果
		return results[:limit]

	def chi2_distance(self, histA, histB, eps = 1e-10):
		# compute the chi-squared distance
		# 计算卡方距离
		d = 0.5 * np.sum([((a - b) ** 2) / (a + b + eps)
			for (a, b) in zip(histA, histB)])

		# return the chi-squared distance
		# 返回卡方距离
		return d


#!/usr/bin/env python

## \file run_verification_study.py
#  \brief Python script for performing a verification study.
#  \author J. Mukhopadhaya
#
#  This script runs a set of simulations for a verification study.
#  It requires a config file as a command line input.
#  It uses all the mesh files found in the working directory as a mesh
#  family. Mesh files should have the level (L5, L4, ... etc) in its
#  name.
#
#  Currently, this verfication study runs SA, and SST turbulence models
#  with the GG, and WLSQ numerical gradient methods, and with Least
#  Squares, and 2nd order flux reconstructions. This can be changed by
#  altering the options in the run set up section.

from optparse import OptionParser
import os, sys, shutil, copy, os.path
sys.path.append(os.environ['SU2_RUN'])
import SU2
from SU2.io import redirect_folder, redirect_output

def main():
# Command Line Options
    parser = OptionParser()
    parser.add_option("-f", "--file", dest="filename",
                      help="read config from FILE", metavar="FILE")

    (options, args)=parser.parse_args()

    # Config parsing
    config = SU2.io.Config(options.filename)
    state  = SU2.io.State()

    # Assumption: All .su2 meshes in family are present in current directory
    files = [f for f in os.listdir(os.getcwd()) if os.path.isfile(os.path.join(os.getcwd(), f))]
    mesh_files = [f for f in files if '.su2' in f]

    # Run set up
    mesh_folders = ['L5','L4','L3','L2','L1']
    models = ['SA', 'SST']
    grads = {'gg' : 'GREEN_GAUSS', 'wlsq' : 'WEIGHTED_LEAST_SQUARES'}
    recon_grads = ['ls','2nd_order']
    diverged_cases = []
    num_cores = {'L5': 1, 'L4' : 2, 'L3' : 8, 'L2' : 32, 'L1' : 128}

    for model in models:
        print('Running mesh convergence study for the ' + model + ' turbulence model: ')
        for grad_folder,grad in grads.items():
            print('\tUsing NUM_METHOD_GRAD = ' + grad)
            for recon in recon_grads:
                if 'ls' in recon:
                    print('\t\tUsing NUM_METHOD_GRAD_RECON = LEAST_SQUARES')
                else:
                    print('\t\tUsing second order reconstructions')
                for level in mesh_folders:
                    curr_mesh = ''
                    for mesh in mesh_files:
                        if level in mesh:
                            curr_mesh = mesh
                            break
                    print('\t\t\tRunning ' + level + ' mesh level using ' + curr_mesh)
                    run_folder = '{}/{}/{}/{}/'.format(model,grad_folder,recon,level)

                    # make copies
                    konfig = copy.deepcopy(config)
                    ztate  = copy.deepcopy(state)

                    # update options
                    konfig.KIND_TURB_MODEL= model
                    konfig.NUM_METHOD_GRAD= grad
                    if 'ls' in recon:
                        konfig.NUM_METHOD_GRAD_RECON= 'LEAST_SQUARES'
                    konfig.MESH_FILENAME= curr_mesh
                    konfig.NUMBER_PART = num_cores[level]

                    ztate.find_files(konfig)

                    link = []
                    link.append(ztate.FILES['MESH'])

                    with redirect_folder(run_folder,[],link, force=False) as push:
                        with redirect_output('log.out'):
                            try:
                                print("running")
                                info = SU2.run.CFD(konfig)
                                ztate.update(info)
                            except:
                                print("The solver stopped unexpectedly")
                                diverged_cases.append(run_folder)
                                print("Continuing... ")

                    print("Following cases diverged: ")
                    print(diverged_cases)

if __name__ == "__main__":
    main()


# third party and local imports
import tkinter as tk
from tkinter import filedialog,font, messagebox
import subprocess
from module_dic import challenges

file_path = '' # globalis the path file to use when click run the code in the created IDE

class ChallengeCodeEditor(tk.Frame):
    """
    Class definition for the ChallengeCodeEditor class
    """
    def __init__(self, master,challenge_selected , user, return_challenge):
        super().__init__(master)
        self.master = master
        self.challenge_selected = challenge_selected
        self.user = user
        self.return_challenge = return_challenge

        """
        Constructor for the AdminForumPage class,
        :param master: tkinter frame
        :param user: inherited from User class
        :param challenge_selected: string
        :param return_challeng: frame
        """
        self.scroll_bar = tk.Scrollbar(self)
        self.scroll_bar.pack(side= tk.RIGHT, fill= tk.Y)

        self.hoz_scroll = tk.Scrollbar(self)
        self.hoz_scroll.pack(side= tk.BOTTOM, fill= tk.Y)

        # create the text widget for code editor
        self.code_editor = tk.Text(self, yscrollcommand= self.scroll_bar.set,xscrollcommand= self.hoz_scroll.set)
        self.code_editor.pack()

        # create console for output of the code
        self.code_output =tk.Text(self, height= 10)
        self.code_output.pack()

        # Create the toolbar menu
        my_menu= tk.Menu(self)
        self.master.config(menu= my_menu)

        # The toolbar menu include Save, New, Open, Save As tools
        file_menu = tk.Menu(my_menu, tearoff= False)
        my_menu.add_cascade(label= "File", menu = file_menu)
        file_menu.add_command(label= "New", command= self.new_file)
        file_menu.add_command(label= "Open", command= self.open_file)
        file_menu.add_command(label= "Save", command= self.save_as)
        file_menu.add_command(label= "Save As", command= self.save_as)

        # Create toolbar to run the code
        run_bar = tk.Menu(my_menu, tearoff= False)
        my_menu.add_cascade(label= "Run", menu = run_bar)
        run_bar.add_command(label= 'Run', command=self.run)

        # Display status of the file
        self.status_bar = tk.Label(self, text ="Ready", anchor= tk.E)
        self.status_bar.pack(fill= tk.X, side = tk.BOTTOM, ipady= 5)

        # Create run code button
        run_button=  tk.Button(self,text = 'Run', command= self.run)
        run_button.pack()

        # Create Submit Code Button
        submit_button = tk.Button(self, text ="Submit Code", command =lambda m= f"{challenge_selected}":self.submit_code(m))
        submit_button.pack()

        #Create Return Button
        return_button = tk.Button(self,text ="Return", command=self.return_to_last_page)
        return_button.pack()

    # This method is used to run the code editor when 'Run' button is clicked on command
    def run(self):
        if file_path == '': #If the there is no file path, prompt user to save the file
            messagebox.showinfo(title= None, message= "Please save your code")
            return
        command = f'python3.10 {file_path}' # the command line to execute the code on the console
        process = subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
        output, error =process.communicate()
        self.code_output.insert('1.0',output)
        self.code_output.insert('1.0',error)

    def new_file(self):
        self.code_editor.delete("1.0",tk.END)
        self.master.title('New File')
        self.status_bar.config(text= "New File")

    def open_file(self):
        path = filedialog.askopenfilename(title= "Open File", filetypes=[("Python Files",'*.py')])
        with open(path,'r') as file:
            code = file.read()
            self.code_editor.delete('1.0',tk.END)
            self.code_editor.insert('1.0', code)
            self.set_file_path(path)

    def save_as(self):
        if file_path =='':
            path = filedialog.asksaveasfilename(title= "Save File", filetypes=[("Python Files","*.py")])
        else:
            path = file_path
        with open(path,'w') as file:
            code = self.code_editor.get("1.0", tk.END)
            file.write(code)
            self.set_file_path(path)

    def set_file_path(self, path):
        global file_path
        file_path =path

    def return_to_last_page(self):
        self.place_forget()
        self.return_challenge.place(relx=.5, rely=.5, anchor= tk.CENTER)

    def submit_code(self, challenge_selected):
        print(challenge_selected)
        my_code =str(self.code_editor.get(1.0, tk.END))
        for challenge in range(1,len(challenges)+1):
            if challenge_selected == f"Challenge {challenge}":
                with open ("data/code_submission.txt","a") as file:
                    file.write(f"Code Submission from {self.user.get_username()}: Challenge {challenge_selected}: {my_code}\n")
        messagebox.showinfo(title= None, message="Sucessfully submitted")


import os

def setup_interface(directory: str) -> str:
    result = "%module roypy\n%{\n"
    files = []
    for r, w, f in os.walk(directory, followlinks=True):
        for file in f:
            if file.endswith('.hpp'):
                files.append(file)

    for f in files:
        result += '#include "{}"\n'.format(f)

    result += "%}\n\n"

    for f in files:
        result += '%include "{}"\n'.format(f)

    return result

if __name__ == "__main__":
    file = setup_interface(input("Where would you like to search for headers? "))
    print(file)
    with open(input("Where would you like to store this? "), 'w+') as f:
        f.write(file)
    print("Write complete!")


from tkinter import *
from tkinter import filedialog
import string
from errors import errorCodes, error
import math
import numpy as np
import matplotlib.pyplot as plt

class seventhLab():
    def __init__(self, window):
        super().__init__()
        self.window = window    # родительское окно в методе
        self.method = "1"
        self.coefficients = []
        self.inputs = []
        self.initUI()
        self.Y = []
        self.X = []
        self.matrix_length = 3

    def initUI(self):
        self.window.title("Сплайны #7")

        mainMenu = Menu(self.window, tearoff=0)  # создаём вкладку в меню
        self.window.config(menu=mainMenu)
        fileMenu = Menu(mainMenu, tearoff=0)  # вкладываем туда кнопки
        fileMenu.add_command(label="Открыть", command=self.on_open)
        mainMenu.add_cascade(label="Файл", menu=fileMenu)

        buttons_frame = Frame(master=self.window, padx=10, pady=5)
        self.clear_button = Button(text="Очистить", master=buttons_frame, width=10, command=self.clear)
        self.clear_button.pack(side=LEFT)
        self.start_button = Button(text="Рассчитать", master=buttons_frame, width=10, command=self.calculate)
        self.start_button.pack(side=LEFT)
        buttons_frame.pack(side=TOP)

        main_frame_x = Frame(master=self.window)
        Label(master=main_frame_x, text="x: ").pack(side=LEFT)
        input1 = Entry(master=main_frame_x, width=10)
        input2 = Entry(master=main_frame_x, width=10)
        input3 = Entry(master=main_frame_x, width=10)
        input4 = Entry(master=main_frame_x, width=10)
        input5 = Entry(master=main_frame_x, width=10)
        input1.pack(side=LEFT)
        input2.pack(side=LEFT)
        input3.pack(side=LEFT)
        input4.pack(side=LEFT)
        input5.pack(side=LEFT)

        main_frame_x.pack(side=TOP, padx=10)

        main_frame_y = Frame(master=self.window)
        Label(master=main_frame_y, text="y: ").pack(side=LEFT)
        input6 = Entry(master=main_frame_y, width=10)
        input7 = Entry(master=main_frame_y, width=10)
        input8 = Entry(master=main_frame_y, width=10)
        input9 = Entry(master=main_frame_y, width=10)
        input10 = Entry(master=main_frame_y, width=10)
        input5.pack(side=LEFT)
        input6.pack(side=LEFT)
        input7.pack(side=LEFT)
        input8.pack(side=LEFT)
        input9.pack(side=LEFT)
        input10.pack(side=LEFT)
        main_frame_y.pack(side=TOP, padx=10)

        sub_frame = Frame(master=self.window)
        Label(master=sub_frame, text="Рассчитать от x:").pack(side=LEFT)
        input11 = Entry(master=sub_frame, width=10)
        input11.pack(side=LEFT)
        sub_frame.pack(side=TOP)

        self.inputs = [input1, input2, input3, input4, input5, input6, input7, input8, input9, input10, input11]

        result_frame = Frame(master=self.window)
        result_frame.pack(side=TOP)
        self.result_label = Label(master=result_frame, font="Courier 16", pady=10)
        self.result_label.pack(side=TOP)

    def get_coef(self):
        coefs = []
        for input in self.inputs:
            coefs.append(float(input.get()))
        return coefs

    def print_result(self, result):
        self.result_label.config(text="y = " + result)

        window = plt.subplots()
        x = np.arange(self.X[0], self.X[-1], 1)
        y = []
        for i in range(len(x)):
            y.append(self.calculate_digit(x[i]))
        plt.plot(x, y)
        plt.show()

    def sortMatrix(self, matrix):
        # сортировка строк по убыванию (пузырёк)
        rowMaxElem = 0
        for i in range(self.matrix_length):
            for j in range(i + 1, self.matrix_length):
                # сравнение строк матрицы
                column = 0
                while matrix[i][column] == matrix[j][column]:
                    column += 1
                    if column == self.matrix_length + 1:
                        error(errorCodes.IDENTIAL_LINES)
                        return
                if abs(matrix[i][column]) < abs(matrix[j][column]):  # по убыванию
                    matrix[i], matrix[j] = matrix[j], matrix[i]

    def calculate_gaus(self, matrix):

        self.sortMatrix(matrix)

        # зануляем всё что ниже диагонали
        for step in range(self.matrix_length - 1):
            for row in range(step + 1, self.matrix_length):
                if(matrix[step][step] == 0):
                    continue
                coefficient = matrix[row][step] / -matrix[step][step]
                for column in range(self.matrix_length + 1):
                    matrix[row][column] += round(coefficient * matrix[step][column], 10)
            self.sortMatrix(matrix)

        # находим неизвестные
        step = 0
        results = []
        for row in range(self.matrix_length - 1, -1, -1):
            count = 0
            for column in range(self.matrix_length - 1, self.matrix_length - step - 1, -1):
                matrix[row][self.matrix_length] -= matrix[row][column] * results[count]
                count += 1
            results.append(matrix[row][self.matrix_length] / matrix[row][self.matrix_length - step - 1])
            step += 1

        results.reverse()

        return np.array([[results[0]], [results[1]], [results[2]]])

    def get_step_x(self, i):
        return self.X[i + 1] - self.X[i]

    def get_step_x2(self, i):
        return self.X[i] - self.X[i - 1]

    def get_step_y(self, i):
        return self.Y[i + 1] - self.Y[i]

    def calculate(self):
        self.coefficients = self.get_coef()
        result = self.calculate_digit(self.coefficients[10])
        self.print_result(str(result))

    def calculate_digit(self, x):
        self.X = np.array(self.coefficients[0:5])
        self.Y = np.array(self.coefficients[5:10])

        C = np.empty((3, 3))
        for i in range(3):
            for j in range(3):
                if i == j:
                    C[i][j] = (self.get_step_x(i) + self.get_step_x(i + 1)) / 3
                elif i == j - 1:
                    C[i][j] = self.get_step_x(i + 1) / 6
                elif i == j + 1:
                    C[i][j] = self.get_step_x(i) / 6
                else:
                    C[i][j] = 0

        D = np.empty((3, 1))
        for i in range(3):
            D[i][0] = self.get_step_y(i + 1) / self.get_step_x(i + 1) - self.get_step_y(i) / self.get_step_x(i)

        CD = np.hstack((C, D))

        M = np.round(np.array(self.calculate_gaus(CD)), 2)
        M = np.vstack((0, M, 0))

        i = 0
        while x > self.X[i]:
            i += 1

        result = 0
        result += M[i - 1][0] * (self.X[i] - x) ** 3 / 6 / self.get_step_x2(i)
        result += M[i][0] * (x - self.X[i - 1]) ** 3 / 6 / self.get_step_x2(i)
        result += (self.Y[i - 1] - M[i - 1][0] * self.get_step_x2(i) ** 2 / 6) * (self.X[i] - x) / self.get_step_x2(i)
        result += (self.Y[i] - M[i][0] * self.get_step_x2(i) ** 2 / 6) * (x - self.X[i - 1]) / self.get_step_x2(i)

        return result

    def clear(self):
        for input in self.inputs:
            input.delete(0, END)
        self.result_label.config(text="")

    def on_open(self):
        ftypes = [('Текстовые файлы', '*.txt'), ('Все файлы', '*')]
        fold = filedialog.askopenfilename(filetypes=ftypes)
        try:
            text = self.read_file(fold)
        except FileNotFoundError:
            error(errorCodes.FILE_NOT_FOUND)
            return

        self.coefficients = text.split(" ")
        for index, input in enumerate(self.inputs):
            input.delete(0, END)
            input.insert(0, self.coefficients[index])

    def read_file(self, filename):
        with open(filename, "r") as f:
            text = f.read()
        return text

def startLab7():
    window = Tk()
    app = seventhLab(window)
    window.mainloop()


#!/usr/bin/env python
#

"""General logging interface for the application."""

import logging
import logging.handlers
import settings

class Logger():
    """Provides a general logging interface for the application."""
    __instance = None

    class FileLogger():
        """Provides an interface to log in files."""
        log = None

        def __init__(self):
            """ Logger's initialisation based on settings parameters. """
            self.log = logging.getLogger(settings.APPLICATION_NAME)
            logging.NOLOG = 60
            logging.addLevelName(logging.NOLOG, 'NOLOG')
            #SYSLOG LEVEL
            if settings.LOG_LEVEL == 'CRITICAL':
                self.log.setLevel(logging.CRITICAL)
            elif settings.LOG_LEVEL == 'ERROR':
                self.log.setLevel(logging.ERROR)
            elif settings.LOG_LEVEL == 'WARNING':
                self.log.setLevel(logging.WARNING)
            elif settings.LOG_LEVEL == 'INFO':
                self.log.setLevel(logging.INFO)
            elif settings.LOG_LEVEL == 'DEBUG':
                self.log.setLevel(logging.DEBUG)
            else:
                #Superior than CRITICAL
                self.log.setLevel(logging.NOLOG)

            #File handler
            filelog = logging.handlers.RotatingFileHandler(
                        settings.LOG_FILENAME,
                        maxBytes=settings.LOG_FILESIZE,
                        backupCount=settings.LOG_NBLOGFILES
                      )

            #Formatter
            if len(settings.LOG_FORMATTER) == 0:
                formatter = logging._defaultFormatter
            else:
                formatter = logging.Formatter(settings.LOG_FORMATTER)

            filelog.setFormatter(formatter)
            self.log.addHandler(filelog)

    def __init__(self):
        """Create instance of Syslog logger if doesn't exists."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()

    def warn(self,message):
        """Produce log message with WARNING level."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        Logger.__instance.log.warn(message)

    def debug(self,message):
        """Produce log message with DEBUG level."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        Logger.__instance.log.debug(message)

    def info(self,message):
        """Produce log message with INFO level."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        Logger.__instance.log.info(message)

    def error(self,message):
        """Produce log message with ERROR level."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        Logger.__instance.log.error(message)

    def critical(self,message):
        """Produce log message with CRITICAL level."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        Logger.__instance.log.critical(message)

    def __new__(Logger):
        """Create and return instance of Syslog logger if doesn't exists."""
        if not Logger.__instance :
            Logger.__instance = Logger.FileLogger()
        return Logger.__instance

logger = Logger()

def warn(message):
    """Produce log message with WARNING level."""
    logger.warn(message)

def debug(message):
    """Produce log message with DEBUG level."""
    logger.debug(message)

def info(message):
    """Produce log message with INFO level."""
    logger.info(message)

def error(message):
    """Produce log message with ERROR level."""
    logger.error(message)

def critical(message):
    """Produce log message with CRITICAL level."""
    logger.critical(message)


from uuid import UUID

import numpy as np
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import ModelCheckpoint

class Model:
    def __init__(self, vocab_len, sample_len, **hyper_params):
        """
        Create Python Language Model.
        :param vocab_len: int, length of vocabulary
        :param sample_len: int, length of a single sample for training/seeding
        :param hyper_params: Not Implemented yet.
        """
        self.vocab_len = vocab_len
        self.sample_len = sample_len
        self.model = None
        self.init_model()

    def init_model(self):
        """
        Initialize self.model
        :return: None
        """
        self.model = Sequential()
        self.model.add(Embedding(self.vocab_len, 512))
        self.model.add(Bidirectional(LSTM(512, return_sequences=True)))
        self.model.add(Bidirectional(LSTM(512, return_sequences=True)))
        self.model.add(Bidirectional(LSTM(512, return_sequences=True)))
        self.model.add(Bidirectional(LSTM(420)))
        self.model.add(Dense(self.vocab_len, activation='softmax'))

        optimizer = Adam()
        self.model.compile(loss='categorical_crossentropy',
                           optimizer=optimizer,
                           metrics=['accuracy'])

    def train(self, x, y, test_data, epochs=1, mini_batch_size=128):
        """
        train model on given data
        :param x: np.array, training inputs, dims (#samples, sample_len)
        :param y: np.array, training labels, dims (#samples, vocab_len)
        :param test_data: iterable, validation data in a tuple with same form as x & y
        :param epochs: int, number of iterations to train on data
        :param mini_batch_size: int, size of mini batches
        :return: None
        """
        assert x.shape[1] == self.sample_len, 'Incorrect sample length. Given: {}, Expecting: {}'.format(
            x.shape[1], self.sample_len)
        checkpoint = ModelCheckpoint("../resources/best_model",
                                     monitor='val_loss',
                                     save_best_only=True,
                                     save_freq=1)

        if test_data:
            self.model.fit(x, y, mini_batch_size, epochs, verbose=1, callbacks=[checkpoint],
                           validation_data=test_data)
        else:
            self.model.fit(x, y, mini_batch_size, epochs, verbose=1, callbacks=[checkpoint])

    def generate_script(self, seed, temp=0.5, **stop):
        """
        generate a script of certain length or until a token idx is reached.
        :param seed: np.array, input into model to generate sample from, dims (1, sample_len)
        :param temp: float, softmax temperature, amount of entropy to include in sample
        :param stop: kwargs, either len (int), number of new tokens to generate; or token (int) idx of token to stop at
        :return: list, full sequence generated as list of token indices (includes seed)
        """
        assert seed.shape[1] == self.sample_len, 'Incorrect sample length. Given: {}, Expecting: {}'.format(
            seed.shape[1], self.sample_len)
        generated_sequence = list(seed[0])

        while True:
            pred = self.model.predict(seed, verbose=0)[0]
            next_idx = self.sample_next_token(pred, temp)
            generated_sequence.append(next_idx)
            if stop.get('len', -1) == len(generated_sequence) - self.sample_len or stop.get('token', -1) == next_idx:
                break
            seed[0] = Model.np_shift(seed[0], -1)
            seed[0, -1] = next_idx

        return generated_sequence

    @staticmethod
    def sample_next_token(seed, temp):
        """
        sample next token given model's output sequence.
        :param seed: np.array, output from model used to pick next token
        :param temp: float, amount of randomness to use when sampling next token
        :return: int, index of sampled token
        """
        preds = np.asarray(seed).astype('float64')
        preds = np.log(preds) / temp
        exp_preds = np.exp(preds)
        probs = np.random.multinomial(1, exp_preds / np.sum(exp_preds), 1)
        return np.argmax(probs)

    @staticmethod
    def np_shift(xs, n):
        if n >= 0:
            return np.concatenate((np.full(n, np.nan), xs[:-n]))
        else:
            return np.concatenate((xs[-n:], np.full(-n, np.nan)))


# import libraries
from dataframe_maker.dataframe_maker import DFGuns
from plot_maker.plot_maker import PlotMaker
from dash import Dash
import dash_table
import dash_html_components as html
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output

# initialise Dash app
app = Dash(__name__,
           external_stylesheets=[dbc.themes.COSMO])

# generate dataframe
df = DFGuns().return_dataframe()

# generate charts
charts = PlotMaker(df)

app.layout = dbc.Container([
    dbc.Row(children=[  # header
        dbc.Row(className='jumbotron',

                children=[
                    html.H1('Firearms & Gun Homicide statistics Dashboard.'),
                    html.P('Data has been provided where it exists. Median values provided where numeric data absent.')
                ])]),
    dbc.Row([
        dbc.Col(children=[
            dbc.Label('Chunk size',
                      style={'color': 'pink'}),
            dbc.FormGroup(dbc.RadioItems(id='main_chart_dd_viewby',
                                         options=[{'label': 'Country', 'value': 'country'},
                                                  {'label': 'Region', 'value': 'region'},
                                                  {'label': 'Sub-Region', 'value': 'sub_region'}],
                                         value='country')),
            dbc.Label('X-Axis',
                      style={'color': 'pink'}),
            dbc.FormGroup(dbc.RadioItems(id='main_chart_x',
                                         options=[{'label': 'Population', 'value': 'pop_2017'},
                                                  {'label': 'Civilian Firearms',
                                                   'value': 'firearms_owned_civilians'},
                                                  {'label': 'Registered Firearms',
                                                   'value': 'registered_firearms'},
                                                  {'label': 'Unregistered Firearms',
                                                   'value': 'Unregistered firearms'},
                                                  {'label': 'Firearms per 100 people',
                                                   'value': 'firearms_per_100_persons'},
                                                  {'label': 'Murder Rate per 100,000', 'value': 'Rate'}],
                                         value='pop_2017')),
            dbc.Label('Y-Axis',
                      style={'color': 'pink'}),
            dbc.FormGroup(dbc.RadioItems(id='main_chart_y',
                                         options=[{'label': 'Population', 'value': 'pop_2017'},
                                                  {'label': 'Civilian Firearms',
                                                   'value': 'firearms_owned_civilians'},
                                                  {'label': 'Registered Firearms',
                                                   'value': 'registered_firearms'},
                                                  {'label': 'Unregistered Firearms',
                                                   'value': 'Unregistered firearms'},
                                                  {'label': 'Firearms per 100 people',
                                                   'value': 'firearms_per_100_persons'},
                                                  {'label': 'Murder Rate per 100,000', 'value': 'Rate'}],
                                         value='firearms_owned_civilians')),
            dbc.Label('Marker Size',
                      style={'color': 'pink'}),
            dbc.FormGroup(dbc.RadioItems(id='main_chart_z',
                                         options=[{'label': 'Population', 'value': 'pop_2017'},
                                                  {'label': 'Civilian Firearms',
                                                   'value': 'firearms_owned_civilians'},
                                                  {'label': 'Registered Firearms',
                                                   'value': 'registered_firearms'},
                                                  {'label': 'Unregistered Firearms',
                                                   'value': 'Unregistered firearms'},
                                                  {'label': 'Firearms per 100 people',
                                                   'value': 'firearms_per_100_persons'},
                                                  {'label': 'Murder Rate per 100,000', 'value': 'Rate'}],
                                         value='Rate'))
        ]),
        dcc.Graph(id='main_chart')
    ]),
    dash_table.DataTable(
        id='table-dark',
        columns=[{'name': 'Country', 'id': 'country'},
                 {'name': 'Region', 'id': 'region'},
                 {'name': 'Sub Region', 'id': 'sub_region'},
                 {'name': 'Population', 'id': 'pop_2017'},
                 {'name': 'Civilian Firearms', 'id': 'firearms_owned_civilians'},
                 {'name': 'Registered Firearms', 'id': 'registered_firearms'},
                 {'name': 'Unregistered Firearms', 'id': 'Unregistered firearms'},
                 {'name': 'Firearms per 100 people', 'id': 'firearms_per_100_persons'},
                 {'name': 'Murder Rate per 100,000', 'id': 'Rate'}],
        data=charts.df.to_dict('records'),
        sort_action='native',
        style_table={'width': '98%',
                     'align': 'center'}
    )
])

# callback for main_chart
@app.callback(output=Output(component_id='main_chart',
                            component_property='figure'),
              inputs=[Input(component_id='main_chart_dd_viewby',
                            component_property='value'),
                      Input(component_id='main_chart_x',
                            component_property='value'),
                      Input(component_id='main_chart_y',
                            component_property='value'),
                      Input(component_id='main_chart_z',
                            component_property='value')
                      ])
def callback(selector_region, x_axis, y_axis, z_axis):
    return charts.main_scatter(value_selection=selector_region,
                               x_axis=x_axis,
                               y_axis=y_axis,
                               z_axis=z_axis)

# run app
if __name__ == '__main__':
    app.run_server(debug=False,
                   port=5000)