from math import sqrt
from copy import deepcopy

def linreg(X, Y):
    """
    Summary
        Linear regression of y = ax + b
    Usage
        real, real, real = linreg(list, list)
    Returns coefficients to the regression line "y=ax+b" from x[] and y[], and R^2 Value
    """
    if len(X) != len(Y):
        raise ValueError('unequal length')

	# Handles the horizontal 2-point line case
    if len(Y) == 2 and Y[0] == Y[1] :
        return 0, Y[0], 1
    #/////////////////////////////////////////

    N = len(X)
    Sx = Sy = Sxx = Syy = Sxy = 0.0
    for x, y in zip(X, Y):
        Sx = Sx + x
        Sy = Sy + y
        Sxx = Sxx + x*x
        Syy = Syy + y*y
        Sxy = Sxy + x*y
    det = Sxx * N - Sx * Sx
    a, b = (Sxy * N - Sy * Sx)/det, (Sxx * Sy - Sx * Sxy)/det
    meanerror = residual = 0.0
    for x, y in zip(X, Y):
        meanerror = meanerror + (y - Sy/N)**2
        residual = residual + (y - a * x - b)**2
    RR = 1 - residual/meanerror
    return a, b, RR

def partialreg(X, Y, threshold, backwards = "no", cutoff_size_input = 10, cutoff_size_in_percent = "yes") :
    """
    Summary
        Linear regression of y = ax + b
        Cuts away parts of X and Y if RR is inferior to  the threshold
    Usage
        [real, real, real], int, int = partialreg(list, list, real, optional str, opttional int, optional string)
    Return coefficients to the regression line "y=ax+b" from x[] and y[], R^2 value,
    the length of X and Y treated by the function, and the cutoff size.

    If the backwards flag is set to "backwards", the cutoff is operated at the beginning of the lists ("backwards")
    cutoff_size determines the portion of the list that is cut off is the regression fails to meet the threshold
    The cutoff_size_in_percent flag determines if cutoff_size is to be treated as an integer or a percentage ("no")
    """

    # Flags manipulation
    bk = 0
    cpct = 1
    cutoff_size = cutoff_size_input
    if backwards == "backwards" :
        bk = 1
    if cutoff_size_in_percent == "no" :
        cpct = 0
    #///////////////////

    new_X = deepcopy(X)
    new_Y = deepcopy(Y)
    cutoff_return = 0

    reg_results = linreg(new_X,new_Y)
    # While R squared < threshold, keep cutting the lists
    while reg_results[2] < threshold :
        # If the cuttof becomes too small / large, set it back to 1 (integer)
        if (len(new_X) - int(cutoff_size * (1 + cpct * (len(new_X)/100 - 1)))) < 3 or int(cutoff_size * (1 + cpct * (len(new_X)/100 - 1))) < 1:
            cpct = 0
            cutoff_size = 1
        # Cutoff data
        del new_X[(bk - 1) * int(cutoff_size * (1 + cpct * (len(new_X)/100 - 1))):(1 - bk) * len(new_X) + bk * int(cutoff_size * (1 + cpct * (len(new_X)/100 - 1)))]
        del new_Y[(bk - 1) * int(cutoff_size * (1 + cpct * (len(new_Y)/100 - 1))):(1 - bk) * len(new_Y) + bk * int(cutoff_size * (1 + cpct * (len(new_Y)/100 - 1)))]
        cutoff_return += 1
        reg_results = linreg(new_X, new_Y)

    return reg_results, len(new_X), cutoff_return


import csv
import math
from decimal import *

from django.core.management.base import BaseCommand, CommandError
from api.models import IPLocation

class Command(BaseCommand):
    help = 'Deletes existing ip locations and re-imports all ip locations from the provided CSV file.'

    def add_arguments(self, parser):
        parser.add_argument('file_name', nargs='?', default='ipv4_locations.csv')
        parser.add_argument('batch_size', nargs='?', default=10000)

    def handle(self, *args, **options):
        # Delete all existing IP Locations
        IPLocation.objects.all().delete()

        # List of IPLocation objects to be bulk saved
        ip_locations = []

        # Open CSV File
        with open(options['file_name'], 'r', newline='') as csvfile:
            ip_location_reader = csv.reader(csvfile, delimiter=',')

            # Use enumerate for built-in counter
            for counter, ip_location in enumerate(ip_location_reader):

                # Retrieve IP network and location data with checks for data validity
                network = ip_location[0]
                if network == 'network' or not network:
                    print(f"Row { counter } doesn't have an associated network")
                    continue

                if ip_location[7]:
                    ip_latitude = Decimal(ip_location[7])
                else:
                    print(f"{ network } does not have an associated latitude")
                    continue

                if ip_location[8]:
                    ip_longitude = Decimal(ip_location[8])
                else:
                    print(f"{ network } does not have an associated longitude")
                    continue

                if ip_latitude < -90 or ip_latitude > 90 or ip_longitude < -180 or ip_longitude > 180:
                    print(f"{ network } does not have possible latitude/longitude values")

                # Append IPLocation object instance to ip_locations list.
                # Note: This does not save the IPLocation object
                ip_locations.append(IPLocation(
                    ip_network = network,
                    latitude = ip_latitude,
                    longitude = ip_longitude
                ))

                # Uses counter to calculate current batch size of ip_locations (as opposed to checking length of ip_locations)
                # Bulk saves all IPLocation objects in ip_locations
                # Flushes ip_locations
                if counter % int(options['batch_size']) == 0:
                    IPLocation.objects.bulk_create(ip_locations)
                    ip_locations = []

            # Bulk save IPLocation objects remaining if number of rows in CSV isn't evenly divisible by batch_size
            IPLocation.objects.bulk_create(ip_locations)


#%% Import the required libraries

import os
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer

#%% Load the data and show some statistics
data = pd.read_csv('HAM10000_metadata.csv')
print(data.head())

print(data.isnull().sum())

#%% Previous command shows us that age has some missing data

null = data.age.isnull().values
print(type(null))
result = np.where(null == True)
print(len(result))

# we found the values where age is null.
# Let's impute the nan values
y = data['dx']
X = np.array(data.drop(['dx'], 1))
age = np.array(data['age'])
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
X_norm = imp_mean.fit_transform(X)
# print(age_norm.shape)
# print(y.shape)

# encoder = OneHotEncoder(handle_unknown='ignore')
# X_encoded = encoder.fit_transform(X)
# print(X_encoded[0:5])
#
# y = data['dx']

#%% PCA
Ncomponents=2
pca = PCA()

X_reduced = pca.fit_transform(X)

print(X_reduced.shape)


import warnings

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import ticker, colors as mcolors, dates as mdates
from matplotlib.collections import LineCollection

from ._utils import prepare_wide_data

class _LineChartRace:

    def __init__(self, df, filename, orientation, sort, n_lines, fixed_max,
                 steps_per_period, period_length, interpolate_period, period_label,
                 period_fmt, period_summary_func, agg_line_func, figsize, cmap, title,
                 tick_label_size, shared_fontdict, scale, writer, fig, dpi,
                 line_kwargs, filter_column_colors):
        self.filename = filename
        self.extension = self.get_extension()
        self.orientation = orientation
        self.sort = sort
        self.n_lines = n_lines or df.shape[1]
        self.fixed_max = fixed_max
        self.steps_per_period = steps_per_period
        self.interpolate_period = interpolate_period
        self.period_label = self.get_period_label(period_label)
        self.period_fmt = period_fmt
        self.period_summary_func = period_summary_func
        self.agg_line_func = agg_line_func
        self.period_length = period_length
        self.figsize = figsize
        self.title = self.get_title(title)
        self.tick_label_size = tick_label_size
        self.orig_rcParams = self.set_shared_fontdict(shared_fontdict)
        self.scale = scale
        self.writer = self.get_writer(writer)
        self.fps = 1000 / self.period_length * steps_per_period
        self.filter_column_colors = filter_column_colors

        self.validate_params()
        self.line_kwargs = self.get_line_kwargs(line_kwargs)
        self.html = self.filename is None
        self.df_values = self.prepare_data(df)
        self.fig, self.ax = self.get_fig(fig, dpi)
        self.colors = self.get_colors(cmap)
        self.str_index = self.df_values.index.astype('str')

    def get_extension(self):
        if self.filename:
            return self.filename.split('.')[-1]

    def validate_params(self):
        if isinstance(self.filename, str):
            if '.' not in self.filename:
                raise ValueError('`filename` must have an extension')
        elif self.filename is not None:
            raise TypeError('`filename` must be None or a string')

        if self.sort not in ('asc', 'desc'):
            raise ValueError('`sort` must be "asc" or "desc"')

        if self.orientation not in ('h', 'v'):
            raise ValueError('`orientation` must be "h" or "v"')

    def get_line_kwargs(self, line_kwargs):
        line_kwargs = line_kwargs or {}
        if 'alpha' not in line_kwargs:
            line_kwargs['alpha'] = .8
        if 'ec' not in line_kwargs:
            line_kwargs['ec'] = 'white'
        return line_kwargs

    def get_period_label(self, period_label):
        if not period_label:
            return False
        elif period_label is True:
            period_label = {'size': 12}
            if self.orientation == 'h':
                period_label['x'] = .95
                period_label['y'] = .15 if self.sort == 'desc' else .85
                period_label['ha'] = 'right'
                period_label['va'] = 'center'
            else:
                period_label['x'] = .95 if self.sort == 'desc' else .05
                period_label['y'] = .85
                period_label['ha'] = 'right' if self.sort == 'desc' else 'left'
                period_label['va'] = 'center'
        else:
            if 'x' not in period_label or 'y' not in period_label:
                raise ValueError('`period_label` dictionary must have keys for "x" and "y"')
        return period_label

    def get_title(self, title):
        if isinstance(title, str):
            return {'label': title}
        elif isinstance(title, dict):
            if 'label' not in title:
                raise ValueError('You must use the key "label" in the `title` dictionary '
                                 'to supply the name of the title')
        elif title is None:
            title = {'label': None}
        else:
            raise TypeError('`title` must be either a string or dictionary')

        return title

    def set_shared_fontdict(self, shared_fontdict):
        orig_rcParams = plt.rcParams.copy()
        if shared_fontdict is None:
            return orig_rcParams
        for k, v in shared_fontdict.items():
            if k not in ['fontsize', 'size']:
                if k in ['cursive', 'family', 'fantasy', 'monospace', 'sans-serif', 'serif']:
                        if isinstance(v, str):
                            v = [v]
                if k == 'color':
                    plt.rcParams['text.color'] = v
                    plt.rcParams['xtick.color'] = v
                    plt.rcParams['ytick.color'] = v
                    continue
                try:
                    plt.rcParams[f'font.{k}'] = v
                except KeyError:
                    raise KeyError(f"{k} is not a valid key in `sharedfont_dict`"
                                    "It must be one of "
                                    "'cursive', 'family', 'fantasy', 'monospace',"
                                    "sans-serif', 'serif',"
                                    "'stretch', 'style', 'variant', 'weight'")
        return orig_rcParams

    def get_writer(self, writer):
        if writer is None:
            if self.extension == 'gif':
                writer = 'imagemagick'
            elif self.extension == 'html':
                writer = 'html'
            else:
                writer = plt.rcParams['animation.writer']
        return writer

    def prepare_data(self, df):
        compute_ranks = False
        return prepare_wide_data(df, self.orientation, self.sort, self.n_lines,
                                True, self.steps_per_period,
                                compute_ranks)

    def get_colors(self, cmap):
        if cmap is None:
            cmap = 'dark12'
            if self.df_values.shape[1] > 10:
                cmap = 'dark24'

        if isinstance(cmap, str):
            from ._colormaps import colormaps
            try:
                colors = colormaps[cmap.lower()]
            except KeyError:
                raise KeyError(f'Colormap {cmap} does not exist. Here are the '
                               f'possible colormaps: {colormaps.keys()}')
        elif isinstance(cmap, mcolors.Colormap):
            colors = cmap(range(cmap.N)).tolist()
        elif isinstance(cmap, list):
            colors = cmap
        elif isinstance(cmap, tuple):
            colors = list(cmap)
        elif hasattr(cmap, 'tolist'):
            colors = cmap.tolist()
        else:
            raise TypeError('`cmap` must be a string name of a colormap, a matplotlib colormap '
                            'instance, list, or tuple of colors')

        # colors is a list
        n = len(colors)
        if self.df_values.shape[1] > n:
            colors = colors * (self.df_values.shape[1] // n + 1)

        colors = mcolors.to_rgba_array(colors)
        colors = colors[:self.df_values.shape[1]]
        return colors

    def get_fig(self, fig, dpi):
        if fig is not None and not isinstance(fig, plt.Figure):
            raise TypeError('`fig` must be a matplotlib Figure instance')
        if fig is not None:
            if not fig.axes:
                raise ValueError('The figure passed to `fig` must have an axes')
            ax = fig.axes[0]
            self.figsize = fig.get_size_inches()
        else:
            fig, ax = self.create_figure(dpi)
        return fig, ax

    def create_figure(self, dpi):
        fig = plt.Figure(figsize=self.figsize, dpi=dpi)
        ax = fig.subplots()
        ax.set_title(**self.title)
        return fig, ax

    def init_func(self):
        self.ax.set_xlim(self.df_values.index[0], self.df_values.index[-1])
        self.ax.set_ylim(self.df_values.min().min(), self.df_values.max().max())
        xmin, xmax = self.ax.get_xlim()
        delta = (xmax - xmin) * .05
        self.ax.set_xlim(xmin - delta, xmax + delta)

        ymin, ymax = self.ax.get_ylim()
        delta = (ymax - ymin) * .05
        self.ax.set_ylim(ymin - delta, ymax + delta)

        for spine in self.ax.spines.values():
            spine.set_visible(False)

        self.ax.tick_params(length=0)
        self.ax.set_facecolor('.9')
        self.ax.grid(True, axis='y')
        self.ax.xaxis_date()
        self.ax.xaxis.set_major_formatter(mdates.DateFormatter('%-d'))

        df_cur = self.df_values.iloc[0]
        x, y = df_cur.name, df_cur.values
        x = mdates.date2num(x)
        for col, val, color in zip(self.df_values.columns, y, self.colors):
            self.ax.text(x, val, col, ha='center', va='bottom')
            self.ax.add_collection(LineCollection([[(x, val)]], colors=[color]))

    def anim_func(self, i):
        df_cur = self.df_values.iloc[i]
        x, y = df_cur.name, df_cur.values
        x = mdates.date2num(x)
        for collection, text, val, color in zip(self.ax.collections, self.ax.texts, y, self.colors):
            seg = collection.get_segments()
            last = seg[-1][-1]
            new_seg = np.row_stack((last, [x, val]))
            seg.append(new_seg)
            collection.set_segments(seg)
            color_arr = collection.get_colors()
            color_arr = np.append(color_arr, [color], axis=0)
            color_arr[:, -1] *= .97
            collection.set_color(color_arr)
            text.set_position((x, val))

    def make_animation(self):
        interval = self.period_length / self.steps_per_period
        anim = FuncAnimation(self.fig, self.anim_func, range(1, len(self.df_values)),
                             self.init_func, interval=interval)

        try:
            if self.html:
                ret_val = anim.to_html5_video()
                try:
                    from IPython.display import HTML
                    ret_val = HTML(ret_val)
                except ImportError:
                    pass
            else:
                ret_val = anim.save(self.filename, fps=self.fps, writer=self.writer)
        except Exception as e:
            message = str(e)
            raise Exception(message)
        finally:
            plt.rcParams = self.orig_rcParams

        return ret_val

def line_chart_race(df, filename=None, orientation='h', sort='desc', n_lines=None,
                    fixed_max=True, steps_per_period=10, period_length=500,
                    interpolate_period=False, period_label=True, period_fmt=None,
                    period_summary_func=None, agg_line_func=None, figsize=(6, 3.5),
                    cmap=None, title=None, tick_label_size=7, shared_fontdict=None,
                    scale='linear', writer=None, fig=None, dpi=144, line_kwargs=None,
                    filter_column_colors=False):
    lcr = _LineChartRace(df, filename, orientation, sort, n_lines, fixed_max,
                         steps_per_period, period_length, interpolate_period, period_label,
                         period_fmt, period_summary_func, agg_line_func, figsize, cmap, title,
                         tick_label_size, shared_fontdict, scale, writer, fig, dpi, line_kwargs,
                         filter_column_colors)
    return lcr.make_animation()


class Solution:

    def nextCell(self, board):
        for i in range(9):
            for j in range(9):
                if board[i][j] == ".":
                    return i, j
        return -1, -1

    def isValidSudoku(self, board):
        seen = set()
        return not any(x in seen or seen.add(x)
                       for i, row in enumerate(board)
                       for j, c in enumerate(row)
                       if c != "."
                       for x in ((c, i, j), (i // 3, j // 3, c)))

    def isValid(self, board, i, j, e):
        row_valid = not any(e == x for x in board[i])
        if row_valid:
            col_valid = not any(e == board[x][j] for x in range(9))
            if col_valid:
                sec_x, sec_y = 3 * (i // 3), 3 * (j // 3)
                return not any(e == board[x][y] for x in range(sec_x, sec_x + 3) for y in range(sec_y, sec_y + 3))
            return False
        return False

    def solveSudoku(self, board):
        i, j = self.nextCell(board)
        if i == -1:
            return True
        for e in range(1, 10):
            if self.isValid(board, i, j, str(e)):
                board[i][j] = str(e)
                if self.solveSudoku(board):
                    return True
            board[i][j] = "."
        return False

if __name__ == "__main__":
    board = [["5", "3", ".", ".", "7", ".", ".", ".", "."],
             ["6", ".", ".", "1", "9", "5", ".", ".", "."],
             [".", "9", "8", ".", ".", ".", ".", "6", "."],
             ["8", ".", ".", ".", "6", ".", ".", ".", "3"],
             ["4", ".", ".", "8", ".", "3", ".", ".", "1"],
             ["7", ".", ".", ".", "2", ".", ".", ".", "6"],
             [".", "6", ".", ".", ".", ".", "2", "8", "."],
             [".", ".", ".", "4", "1", "9", ".", ".", "5"],
             [".", ".", ".", ".", "8", ".", ".", "7", "9"]]
    Solution().solveSudoku(board)
    print(board)


"""
This module handles the functions that are used to visualize the
maps and other important features
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
from matplotlib.patches import Patch
from scipy.ndimage import gaussian_filter

from config import Config
import general
import generate_data

def plot_map(category_map, liquid, gas, pipe, u_gs_map, u_ls_map):
    """
    plot a map which contains the representation of a categorical map
    """
    # initialize the figure
    fig, axs = plt.subplots(figsize=(7, 7))

    # get the axis values
    x_ticks = u_gs_map[0, :]
    y_ticks = u_ls_map[:, 0]

    # get alpha values
    edges = generate_data.detect_edges(category_map)
    alphas = gaussian_filter(edges, sigma=1)
    # scale up to 1
    alphas = alphas / alphas.max()
    # scale min alpha
    min_alpha = 0.2
    alphas[alphas < min_alpha] = min_alpha

    # get the specific location of the supplied case
    u_gs = general.single_fluid_velocity(gas, pipe)
    u_ls = general.single_fluid_velocity(liquid, pipe)

    # get the legend
    legend_elements = []
    for category, value in Config.CATEGORIES.items():
        if np.any(category_map == value):
            color = list(Config.CMAP(value))
            color[-1] = min(min_alpha * 3, 1)
            legend_elements.append(Patch(facecolor=color, label=category))

    axs.pcolormesh(
        x_ticks,
        y_ticks,
        category_map,
        shading="gouraud",
        cmap=Config.CMAP,
        alpha=alphas,
    )

    # the current value marker
    axs.plot(u_gs, u_ls, marker="x", color="black", mew=2, markersize=10)
    legend_elements.append(
        mlines.Line2D(
            [],
            [],
            color="black",
            marker="x",
            mew=2,
            linestyle="None",
            markersize=10,
            label="This scenario",
        )
    )

    # plot the legend
    axs.legend(handles=legend_elements, bbox_to_anchor=(1.04, 1), loc="upper left")

    # set the ticks, label, title and scale
    axs.set_xticks(x_ticks)
    axs.set_yticks(y_ticks)
    axs.set_xscale("log")
    axs.set_yscale("log")
    axs.set_xlabel(r"$U_{Gs}$")
    axs.set_ylabel(r"$U_{Ls}$")
    axs.set_title(f"Inclination = ${pipe.inclination*180/np.pi:.1f}{{\degree}}$")
    plt.tight_layout()

    return fig, axs


import numpy as np

class sequence_alignment:
    def __init__(self, _s1: str, _s2: str, _gap_score: int, _match_score: int, _mismatch_score: int, _local: bool):
        self.s1 = _s1
        self.s2 = _s2
        self.gap_score = _gap_score
        self.match_score = _match_score
        self.mismatch_score = _mismatch_score
        self.local = _local
        self.T = self.init_matrix(len(self.s1), len(self.s2))
        self.num_paths = np.zeros(self.T.shape) - 1

    def init_matrix(self, n: int, m: int):
        # returns an n x m matrix with [:,0] and [0,:] initialized to reflect score_gap
        T = np.zeros((n + 1, m + 1))
        T[:, :] = np.NaN
        for i in range(n + 1):
            T[i, 0] = i * self.gap_score if not self.local else 0
        for i in range(m + 1):
            T[0, i] = i * self.gap_score if not self.local else 0
        return T

    def recursive_table_search(self, i: int, j: int):
        # recursively fill score table starting from i, j
        if not np.isnan(self.T[i, j]):
            # value has already been memoized, so return it
            return self.T[i, j]
        else:
            # value has not been memoized, so memoize it and write to T
            replace = self.recursive_table_search(i - 1, j - 1) + self.does_match(i, j)
            s1_miss = self.recursive_table_search(i - 1, j) + self.gap_score
            s2_miss = self.recursive_table_search(i, j - 1) + self.gap_score
            limit = 0 if self.local else float('-inf')
            self.T[i, j] = max(replace, s1_miss, s2_miss, limit)
            return self.T[i, j]

    def does_match(self, i: int, j: int):
        # helper function to return score of some (i, j) match attempt
        if self.s1[i - 1] == self.s2[j - 1]:
            return self.match_score
        else:
            return self.mismatch_score

    def get_all_alginments(self, i, j):
        alignments = []
        options = []
        if self.T[i - 1, j] + self.gap_score == self.T[i, j]:
            options.append(self.T[i - 1, j])
        if self.T[i - 1, j - 1] + self.match_score == self.T[i, j] or self.T[i - 1, j - 1] + self.mismatch_score == self.T[i, j]:
            options.append(self.T[i - 1, j - 1])
        if self.T[i, j - 1] + self.gap_score == self.T[i, j]:
            options.append(self.T[i, j - 1])
        if not options:
            return [([''], [''])]
        maxval = max(options)
        if j != 0 and self.T[i, j - 1] == maxval and self.T[i, j - 1] + self.gap_score == self.T[i, j]:
            # a gap in s1
            valid_seq = (self.get_all_alginments(i, j - 1))
            for path in valid_seq:
                path[0].append('-')
                path[1].append(self.s2[j - 1])
            alignments.extend(valid_seq)
        if i != 0 and self.T[i - 1, j] == maxval and self.T[i - 1, j] + self.gap_score == self.T[i, j]:
            # a gap in s1
            valid_seq = (self.get_all_alginments(i - 1, j))
            for path in valid_seq:
                path[0].append(self.s1[i - 1])
                path[1].append('-')
            alignments.extend(valid_seq)
        if (i != 0 and j != 0) and (self.T[i - 1, j - 1] == maxval) and (self.T[i - 1, j - 1] + self.match_score == self.T[i, j] or self.T[i - 1, j - 1] + self.mismatch_score == self.T[i, j]):
            # a match or missmatch valid
            valid_seq = self.get_all_alginments(i - 1, j - 1)
            for path in valid_seq:
                path[0].append(self.s1[i - 1])
                path[1].append(self.s2[j - 1])
            alignments.extend(valid_seq)
        return alignments


class RandomizedSet:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.nums = list()
        self.map = dict()

    def insert(self, val: int) -> bool:
        """
        Inserts a value to the set. Returns true if the set did not already contain the specified element.
        """
        if val in self.map:
            return False
        self.map[val] = len(self.nums)
        self.nums.append(val)
        return True

    def remove(self, val: int) -> bool:
        """
        Removes a value from the set. Returns true if the set contained the specified element.
        """
        if val not in self.map:
            return False
        last = len(self.nums) - 1
        self.map[self.nums[last]] = self.map[val]
        self.nums[self.map.pop(val)] = self.nums[last]
        self.nums.pop()
        return True

    def getRandom(self) -> int:
        """
        Get a random element from the set.
        """
        return self.nums[random.randint(0, len(self.nums) - 1)]

# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()


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

from pandas_datareader import data as web
import os
import math
import numpy as np
import pandas as pd
import traceback
import matplotlib.pyplot as plt

ticker = 'HSBC'
input_dir = r'../datasets'
ticker_file = os.path.join(input_dir, ticker + '_weekly_return_volatility.csv')

def main():
    try:
        # read file
        df = pd.read_csv(ticker_file)
        # get the data of year 2018 and year 2019
        df_2018 = df[(df['Year']) == 2018]
        df_2019 = df[(df['Year']) == 2019]

        plt.figure()
        # sub plot 1 for year 2018
        plt.subplot(211)
        # put each point on the plot
        plt.scatter(df_2018['mean_return'], df_2018['volatility'], c=df_2018['Label'], s=300)
        week = df_2018['Week_Number'].tolist()
        x = df_2018['mean_return'].tolist()
        y = df_2018['volatility'].tolist()
        # put the week id on each point
        for i in range(len(df_2018)):
            plt.annotate(week[i], xy=(x[i], y[i]))
        plt.title('2018')
        plt.xlabel('mean_return')
        plt.ylabel('volatility')
        # plt.show()
        # sub plot 2 for year 2019
        plt.subplot(212)
        plt.scatter(df_2019['mean_return'], df_2019['volatility'], c=df_2019['Label'], s=300)
        week = df_2019['Week_Number'].tolist()
        x = df_2019['mean_return'].tolist()
        y = df_2019['volatility'].tolist()
        for i in range(len(df_2019)):
            plt.annotate(week[i], xy=(x[i], y[i]))
        plt.title('2019')
        plt.xlabel('mean_return')
        plt.ylabel('volatility')
        plt.show()

    except Exception as e:
        print(e)
        print(traceback.format_exc())

main()


def song_decoder(song):
    """Return the words of the initial song that DJ used to make a dubsteb remix. Separate the words with a space.

    Args:
        song (string]): Upper case string e.g WUBWUBIWUBAMWUBWUBX
    Returns:
        string: Return the words of the initial song that DJ used to make a dubsteb remix. Separate the words with a space
    """
    song = song.upper()
    str = "WUB"

    if song.find(str) != -1:
        return " ".join(song.replace(str, " ").split())
    return song

remix = "WUBWEWUBAREWUBWUBTHEWUBCHAMPIONSWUBMYWUBFRIENDWUB"
output = "WE ARE THE CHAMPIONS MY FRIEND"

print(song_decoder(remix) == output)
print(song_decoder(remix))


import pytest
import yaml
import mock
import os
from puppetmanager.models import Node, Classification, Configuration
from puppetmanager.signals import configuration_update

# Node
def test_node_turns_into_string():
    node = Node(name="test node")
    assert str(node) == "test node"

@pytest.mark.django_db
def test_node_external_classify_format():
    expected_data = yaml.dump(
        {"classes": {}, "parameters": {}, "environment": "production"},
        default_flow_style=False,
        explicit_start=True,
    )

    node = Node(name="test node")
    node.save()

    yaml_data = node.external_classify()

    assert yaml_data == expected_data

@pytest.mark.django_db
def test_node_external_classify_lists_configurations_in_classification():
    expected_data = yaml.dump(
        {
            "classes": {"testconfiguration": {}, "testconfiguration2": {}},
            "parameters": {},
            "environment": "production",
        },
        default_flow_style=False,
        explicit_start=True,
    )

    configuration = Configuration(name="testconfiguration")
    configuration.save()

    configuration2 = Configuration(name="testconfiguration2")
    configuration2.save()

    classification = Classification()
    classification.save()
    classification.configurations.add(configuration)

    classification2 = Classification()
    classification2.save()
    classification2.configurations.add(configuration2)

    node = Node(name="test node")
    node.save()
    node.classifications.add(classification)
    node.classifications.add(classification2)

    yaml_data = node.external_classify()

    assert yaml_data == expected_data

@pytest.mark.django_db
def test_node_external_classify_doesnt_list_unrelated_configuration():
    expected_data = {
        "classes": {"testconfiguration": {}},
        "parameters": {},
        "environment": "production",
    }

    expected_data = yaml.dump(
        expected_data, default_flow_style=False, explicit_start=True
    )

    configuration = Configuration(name="testconfiguration")
    configuration.save()

    configuration2 = Configuration(name="testconfiguration2")
    configuration2.save()

    classification = Classification()
    classification.save()
    classification.configurations.add(configuration)

    classification2 = Classification()
    classification2.save()
    classification2.configurations.add(configuration2)

    node = Node(name="test node")
    node.save()
    node.classifications.add(classification)

    yaml_data = node.external_classify()

    assert yaml_data == expected_data

@pytest.mark.django_db
def test_node_update_increments_checkin_count():
    node = Node(name="test node")
    node.save()

    assert node.total_checkins == 0

    node.update()
    node.update()

    assert node.total_checkins == 2

# Configuration
def test_configuration_turns_into_string():
    configuration = Configuration(name="testconfiguration")
    assert str(configuration) == "testconfiguration"

def test_configuration_bake_data_to_file_writes_file():
    m_open = mock.mock_open()
    with mock.patch("builtins.open", m_open, create=True):
        with mock.patch("puppetmanager.models.os") as mock_os:
            mock_os.path.exists.return_value = False

            configuration = Configuration(name="TestConfig")
            configuration.data = "{}"

            configuration.bake_to_file("/etc/fingerpuppet")

            mock_os.makedirs.assert_called_with(
                "/etc/fingerpuppet/TestConfig/manifests"
            )
            m_open.assert_called_once_with(
                "/etc/fingerpuppet/TestConfig/manifests/init.pp", "w+"
            )
            m_open().write.assert_called_once_with("{}")

def test_configuration_signal_saves_only_when_path_set():
    mock_config = mock.Mock()
    configuration_update(None, mock_config)
    assert not mock_config.bake_to_file.called

    os.environ["PUPPET_MODULE_PATH"] = "/test"
    configuration_update(None, mock_config)
    mock_config.bake_to_file.assert_called_with("/test")

def test_configuration_restart_puppet_service_hack():
    configuration = Configuration(name="testconfiguration")
    with mock.patch("puppetmanager.models.subprocess") as mock_subp:
        configuration.restart_puppet()
        mock_subp.run.assert_called()

# Classification
def test_classification_turns_into_string():
    classification = Classification(name="testclassification")
    assert str(classification) == "testclassification"


from fastapi import FastAPI, File ,UploadFile
from os import system
import uvicorn
import numpy as np
from io import BytesIO
from PIL import Image
import tensorflow as tf
import requests

app = FastAPI()

# endpoint =  "http:localhost:8501/v1/models/potatoes_model:predict"
MODEL =tf.keras.models.load_model("saved_models/1")
CLASS_NAMES = ["Early Blight", "Late Blight", "Healthy"]

@app.get("/ping")
async def ping():
    return "Hello"

def read_file_as_file(data) -> np.ndarray:
    #converting pillow image into numpy array
    image = np.array(Image.open(BytesIO(data)))
    return image

@app.post("/predict")
async def predict(
    file: UploadFile = File(...)
):
    image =read_file_as_file( await file.read())
    img_batch = np.expand_dims(image , 0)
#    json_data = {
#        "instances": img_batch.tolist()
#   }

    # response = requests.post(endpoint, json=json_data)
#    prediction = np.array(response.json()["predictions"][0])
    predictions = MODEL.predict(img_batch)
    predicted_class = CLASS_NAMES[np.argmax(predictions[0])]
    confidence = np.max(predictions[0])

    return {
        "class": predicted_class,
        "confidence":float(confidence)
        }

if __name__ == "__main__":
    uvicorn.run(app, host='localhost', port = 8000)


from copy import deepcopy
from collections import deque
import sys
input = sys.stdin.readline

def bfs():
    queue = deque()
    queue.append((7, 0))

    count = 0

    while queue:
        queueLen = len(queue)

        # 벽이 밀릴때 마다 visited 리스트를 초기화 해준다.
        visited = [[False] * 8 for _ in range(8)]

        for _ in range(queueLen):
            x, y = queue.popleft()

            if arr[x][y] == '#':
                continue

            if (x, y) == (0, 7):
                return 1

            for i in directions:
                nx = x + i[0]
                ny = y + i[1]

                if nx < 0 or nx >= 8 or ny < 0 or ny >= 8:
                    continue

                if not visited[nx][ny] and arr[nx][ny] != '#':
                    visited[nx][ny] = True
                    queue.append((nx, ny))

        # 체스판 아래로 밀어내고 새로운 빈칸 제일 윗줄에 추가하기
        arr.pop()
        arr.appendleft(['.', '.', '.', '.', '.', '.', '.', '.'])

        count += 1

        # 9초 이후에는 벽이 모두 아래로 밀려났기 때문에
        # 무조건 도착지까지 도착 가능함
        if count == 9:
            return 1

    return 0

arr = deque(list(input().rstrip()) for _ in range(8))
directions = [(0, 0), (0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]

print(bfs())


""" the vhist module contains the definition of the vHist class. vHist is a class to
simplify the display of different kind of histograms. Meant to be used in conjunction
with the vImg class. By adding a single 3-tuple bool parameter (RGB) to indicate which
channels are active in the histogram, we can automatically calculate what type of histogram
to show information for. Therefore, initialization and show functionality may be standardized.
"""

import numpy as np
from matplotlib import pyplot as plt
# from typing import Tuple
# from .types import color_type, nd_or_none
# from itertools import compress
# from .vtools import eprint

####################################################################################################
######################################### Histogram Class ##########################################

class vHist(np.ndarray):
    """ vHist is a class to simplify the display of different kind of histograms. Meant to be used in conjunction
    with the vImg class. By adding a single 3-tuple bool parameter (RGB) to indicate which channels are active
    in the histogram, we can automatically calculate what type of histogram to show information for. Therefore,
    initialization and show functionality may be standardized.

    hist   : This is the image that we want to compute a histogram for. Wrap it as a list: [vHists] .
    channels : A list of indexes, where we specify the index of the channel we want to compute a histogram for.
               To compute a histogram of a grayscale image, the list would be [0] . To compute a histogram for all
               three red, green, and blue channels, the channels list would be [0, 1, 2] .
    mask     : Remember learning about masks in Section 1.4.8? Well, here we can supply a mask. If a mask is
               provided, a histogram will be computed for masked pixels only. If we do not have a mask or do not
               want to apply one, we can just provide a value  of None .
    histSize : This is the number of bins we want to use when computing a histogram. Again, this is a list, one
               for each channel we are computing a histogram for. The bin sizes do not all have to be the same.
               Here is an example of 32 bins for each channel: [32, 32, 32] .
    ranges   : The range of possible pixel values. Normally, this is [0, 256] (this is not a typo — the ending
               range of the cv2.calcHist  function is non-inclusive so you’ll want to provide a value of 256 rather
than 255) for each channel, but if you are using a color space other than RGB [such as HSV],
               the ranges might be different.)
    """

    _cDict = {'b': 'Blue', 'g': 'Green', 'r': 'Red',
              'L': 'Luminance', 'A': 'Alpha', 'B': 'Beta',
              'h': 'Hue', 's': 'Saturation', 'v': 'Value', 'k': 'Grayscale'}

    ####################################################################################################
    ####################################### vHist Dunder Methods #######################################

    def __new__(cls, hist, img_name: str, color_space: str = 'BGR', hist_type: str = '1D',
                channels=(False,) * 3):
        # Init assert statements. Make sure basic class parameter requirements are met.

        assert type is not None, "None check failed for type parameter."

        assert len(channels) == 3 and isinstance(channels, tuple), "Must provide a 3-tuple with True or False " \
            "elements for each value. True if that channel is included in calculated histogram, False if not."
        # Here is the meat for subclassed numpy ndarray types, this casts a new instance of
        # the passed parameter hist.
        assert issubclass(type(hist), np.ndarray), "[-] Error: hist must be subclass of ndarray."
        obj = np.asarray(hist).view(cls)
        obj.__image_name = img_name
        obj.__color_space = color_space
        obj.__type = hist_type
        obj.__channels = channels

        return obj

    # classmethod for alternative creation (beta)
    @classmethod
    def fromMultiHist(cls):
        # to be implemented later
        pass

    def __array_finalize__(self, obj):
        """ this is where we initialize most of the variables for the vHist class, due to the way
            numpy n-dimensional arrays work.
        """
        if obj is None: return
        self.__image_name = getattr(obj, '__image_name', None)
        self.__type = getattr(obj, '__type', None)
        self.__channels = getattr(obj, '__channels', (False, False, False))
        active_chans = sum(1 for e in self.channels if e is True)
        self.xlimit = (0, self.shape[0])
        self.shown = False

    def __array_wrap__(self, out_arr, context=None):
        """__array_wrap__ gets called at the end of numpy ufuncs and
        other numpy functions, to allow a subclass to set the type of
        the return value and update attributes and metadata"""
        out_arr.__image_name = self.__image_name
        out_arr.__type = self.type
        out_arr.__channels = self.channels
        out_arr.__image_name = self.image_name
        out_arr._multi = self._multi
        out_arr.shown = self.shown

        return np.ndarray.__array_wrap__(self, out_arr, context)

    def __eq__(self, other):
        return True if np.array_equal(self, other) else False

    def __truediv__(self, other):
        return super().__truediv__(self, other).view(vHist)

    ####################################################################################################
    ######################################### vHist Properties #########################################

    @property
    def image_name(self):
        return self.__image_name

    @image_name.setter
    def image_name(self, img_name: str):
        self.__image_name = img_name

    @property
    def channels(self):
        return self.__channels

    @channels.setter
    def channels(self, chans):
        if issubclass(type(chans), tuple) and len(chans) == 3 and all(type(e) == bool for e in chans):
            self.__channels = chans
        else:
            raise ValueError(f"[-] Fatal Error: Expected 3-tuple of bools, got ({type(chans)}).")

    @property
    def color_space(self):
        return self.__color_space

    @color_space.setter
    def color_space(self, cspace: str):
        cspace = cspace.upper()
        if cspace == 'RGB':
            self.__color_space = cspace[::-1]
        elif cspace in ('BGR', 'HSV', 'LAB'):
            self.__color_space = cspace
        else:
            raise ValueError(f"[-] Fatal Error: Expected 'RGB', 'BGR', 'HSV', or 'LAB' (case insensitive)")

    @property
    def type(self):
        return self.__type

    @type.setter
    def type(self, str_type: str):
        str_type = str_type.upper()
        TYPES = ('1D', '2D', '3D')
        if str_type in TYPES:
            self.__type = str_type
        else:
            raise ValueError(f"[-] Fatal Error: Expected '1D', '2D', or '3D', got {str_type}.")

    @property
    def bins(self):
        return self.shape[0]

    @property
    def xlimit(self):
        return self.__xlimit

    @xlimit.setter
    def xlimit(self, x_limit):
        if all(type(e) == int for e in x_limit):
            self.__xlimit = x_limit
        else:
            raise ValueError(f"[-] Fatal Error: x_limit argument must be an iterable made up of only int")

    ####################################################################################################
    ###################################### vHist Display Methods #######################################

    def show(self, title='', append: tuple = tuple(), x_title: str = '', y_title: str = '', legend: bool = True):
        """ The show method of the vHist class invokes the display (using matplotlib) of the histogram it
        represents. Since we handle black and white, RGB histograms, HSV histograms, and two dimensional
        color bar histograms, the function must use the type and color_space properties in order to determine
        the type of display to use. By default, flat histograms use a line plot and 2-D histograms use a
        colorbar plot.

        :param title   :
        :param append  :
        :param x_title :
        :param y_title :
        :return:
        """

        # Check if hist was shown before, if so, proceed with same arguments
        if self.shown is True:
            title, append, x_title, y_title, legend = self._show_cache
        else:
            # Create a cache of the first provided parameters to show function so you can repeat previous views easily
            self._show_cache = (title, append, x_title, y_title, legend)

        self._multi = len(append) > 0

        # If attempting to show a three dimensional histogram
        if self.type == '3D':
            # Print an error and return
            raise ValueError("[-] Error: 3D Histogram has no current visualization method.")

        # Determine color from self.color_space
        color_space = self.color_space.lower() if self.color_space != 'LAB' else 'LAB'

        # color_dict is used to quickly determine which color channel corresponds with the appended data
        # from vImg.histogram(display=True)
        color_dict = {
                      (True, True, True): color_space,
                      (True, True, False): color_space[:3],
                      (True, False, True): color_space[::2],
                      (True, False, False): color_space[0],
                      (False, True, True): color_space[1:],
                      (False, True, False): color_space[1],
                      (False, False, True): color_space[2],
                      (False, False, False): 'k'
        }

        # If the histogram is flattened (or '1D' as used here) we need to create a line graph histogram
        if self.type == '1D':
            if not self._multi:
                # Flat grayscale display code:
                fig, ax = plt.subplots()
                fig.suptitle(title)
                ax.set_xlabel(x_title)
                ax.set_ylabel(y_title)
                ax.set_xlim(self.xlimit)
                color = color_dict[self.channels][0]
                ax.plot(self, color, label=f"{self._cDict[color]} channel")
            else:
                # Flat color histogram at least one channel
                fig, ax = plt.subplots()
                fig.suptitle(title)
                ax.set_xlabel(x_title)
                ax.set_ylabel(y_title)
                color = color_dict[self.channels][0]
                ax.plot(self, color, label=f"{self._cDict[color]} channel")
                max_bin = self.bins
                for add_clr, add_hist in append:
                    ax.plot(add_hist, add_clr, label=f"{self._cDict[add_clr]} channel")
                    if add_hist.shape[0] > max_bin:
                        max_bin = add_hist.shape[0]
                ax.set_xlim(self.xlimit)

            if legend:
                handles, labels = ax.get_legend_handles_labels()
                ax.legend(handles, labels)

        if self.type == '2D':
            pass

        self.shown = True


SIZE_COL_1 = 11
SIZE_COL_2 = 21
LINE_SIZE = SIZE_COL_1+SIZE_COL_2+8
# 2000 - 10 is an overestimation to avoid problems
MAX_LINE = (2000 - 10) // LINE_SIZE

def get_message_line(key, info):
    return f'║ {key:<{SIZE_COL_1}.{SIZE_COL_1}} ║ {info:<{SIZE_COL_2}.{SIZE_COL_2}} ║\n'

def get_message(desc, info):
    # only one list allowed and in last position
    for i, k in enumerate(info.keys()):
        if type(info[k]) is list and not i == len(info.keys()) - 1:
            raise ValueError
    # create header
    output = '```'
    line_break = f'╠{"":═<{SIZE_COL_1+2}}╬{"":═<{SIZE_COL_2+2}}╣\n'
    output += f'╔{"":═<{SIZE_COL_1+SIZE_COL_2+5}}╗\n'
    output += f'║{desc:^{SIZE_COL_1+SIZE_COL_2+5}}║\n'
    output += f'╠{"":═<{SIZE_COL_1+2}}╦{"":═<{SIZE_COL_2+2}}╣\n'
    # count lines to avoid more than 2000 characters
    line_counter = 3
    # add line for each key of the dict
    for i, k in enumerate(info.keys()):
        # handle list
        if type(info[k]) is list:
            output += get_message_line(k, info[k][0])
            line_counter += 1
            for e in info[k][1:]:
                output += get_message_line('', e)
                line_counter += 1
                if line_counter+3 > MAX_LINE:
                    output += get_message_line('', 'and more...')
                    break
        elif type(info[k]) is str or type(info[k]) is int or type(info[k]) is float:
            output += get_message_line(k, str(info[k]))
            line_counter += 1
        else:
            raise NotImplementedError

        if i == len(info.keys()) - 1:
            output += f'╚{"":═<{SIZE_COL_1 + 2}}╩{"":═<{SIZE_COL_2 + 2}}╝\n'
            line_counter += 1
        else:
            output += line_break
            line_counter += 1

    # crop string to be 200 chars safe
    output = output[0:1997]
    output += '```'

    return output


# STANDARD IMPORTS
import json
from typing import List

# EXTERNAL IMPORTS
from mepho import DWApiTransport

# PROJECT IMPORTS
from src.domain.date_formatters.region.date_time.model import RegionStringDateTime
from src.domain.date_formatters.region.enum.date_format.enum import RegionDateFormat
from src.domain.date_formatters.region.enum.utc_offset.enum import ExchangeUtcOffset
from src.domain.earning.us.model import Earning
from src.domain.statement.us.request.model import TransactionRequest
from src.infrastructures.env_config import config
from src.transport.drive_wealth.base.transport import DwBaseTransport

class DwEarningsTransport(DwBaseTransport):

    transaction_url = config("DW_GET_ALL_TRANSACTIONS_URL")
    balance_url = config("DW_BALANCE_URL")

    @staticmethod
    def __build_earning_model(earning_transaction: dict) -> Earning:
        earning_model = Earning(
            symbol=earning_transaction.get("instrument", {}).get("symbol"),
            description=earning_transaction.get("instrument", {}).get("name"),
            amount_per_share=earning_transaction.get("dividend", {}).get(
                "amountPerShare"
            ),
            date=RegionStringDateTime(
                date=earning_transaction.get("tranWhen"),
                utc_offset=ExchangeUtcOffset.US_UTC_OFFSET,
                region_date_format=RegionDateFormat.US_DATE_FORMAT,
            ),
            amount=earning_transaction.get("accountAmount"),
        )

        return earning_model

    @staticmethod
    async def get_transaction_earnings(
        transaction_request: TransactionRequest,
    ) -> List[Earning]:
        earnings_transactions = await DwEarningsTransport.__get_transactions(
            transaction_request=transaction_request
        )
        earnings_model = [
            DwEarningsTransport.__build_earning_model(
                earning_transaction=earning_transaction
            )
            for earning_transaction in earnings_transactions
            if earning_transaction.get("dividend")
        ]

        return earnings_model

    @classmethod
    async def __get_transactions(cls, transaction_request: TransactionRequest) -> dict:
        query_params = transaction_request.get_query_params()
        account = transaction_request.get_account()
        url_formatted = DwEarningsTransport.transaction_url.format(account)

        response = await DWApiTransport.execute_get(
            url=url_formatted, query_params=query_params
        )
        body = await response.text()
        transactions = json.loads(body)

        cls._handle_dw_error_status_from_response(
            request=url_formatted, response=transactions
        )

        cls._handle_http_error_from_drive_wealth_request(
            request=url_formatted, response=response
        )
        return transactions


from collections import Counter

print("################################## Part - 1 #############################################")

class Employee:
    #Initializing the constructor
    emp_count = 0;
    emp_salaries = []
    def __init__(self,name, family, salary, department):
        self.emp_department_name = department
        self.emp_salary = salary
        self.emp_family = family
        Employee.emp_count +=1
        Employee.emp_salaries.append(salary)
        self.emp_name = name

    def get_salary(self):
        total_salaries=0;
        for s in Employee.emp_salaries:
            total_salaries = total_salaries + s
        return total_salaries/len(Employee.emp_salaries)

# Inheriting the Employee class to FullTimeEmployee Class

class FullTimeEmployee(Employee):
    def _init_(self, name, family, salary, department):
        Employee._init_(self, name, family, salary, department)

f1 = FullTimeEmployee("Pranu", "Mutha", 1200000, "CS")
f2 = FullTimeEmployee("Sirisha","Rella", 1200000, "CS")
f3 = FullTimeEmployee("Nikki","Pateel", 600000, "CS")
avg_salary = FullTimeEmployee.get_salary(Employee)
print("All the employees together has an average salary of",avg_salary)

print("################################## Part - 2 (Web Scraping) #############################################")
from bs4 import BeautifulSoup
import urllib.request
import requests

def web_scrap():
    html = requests.get("https://en.wikipedia.org/wiki/Deep_learning")   #Passing url to get the content of html
    soup = BeautifulSoup(html.content, "html.parser")                        #Parsing through soup parser
    print("Title of the web page is ",soup.title.string)

#returning the results with href and printing out with it
    # for r in soup.find_all('a'):
    #     print(r.get('href'))
web_scrap()

print("################################## Part - 3 (Numpy) #############################################")
import numpy as np

# temp = np.random.random_integers(0,20,15)
# a = np.random.randint(0,20,15)
a = np.array([5, 4, 12, 12, 2, 0, 5, 4, 6, 1])
print(a)
co = Counter(a)

for k, v in co.items():
    if v == max(co.values()):
        print(k)

# integers = np.array([5, 4, 12, 12, 2, 0, 5, 4, 6, 1])
# print("Input Array",integers)
# x = []
# temp = np.bincount(integers)
# x = np.argmax(temp)
# print(temp)
# print(x)

# print(np.argmax(np.bincount(integers)))

#r = np.random.randint(20,size=15)

# print("The most frequently repeated integer is:",np.bincount(r).argmax())


import sys

import pygame
from pygame.locals import *

pygame.init()

fps = 60
fpsClock = pygame.time.Clock()

width, height = 640, 480
screen = pygame.display.set_mode((width, height))

frame = 0
started = False

# Game loop.
while True:
  screen.fill((255, 255, 255))

  for event in pygame.event.get():
    if event.type == QUIT:
      pygame.quit()
      sys.exit()

  if frame >= 60 and frame < 120:
      if frame % 2 == 0:
          screen.fill((0, 0, 0))

  if pygame.key.get_pressed()[pygame.K_SPACE]:
      started = True
  if started:
      frame += 1

  pygame.display.flip()
  fpsClock.tick(fps)


"""Unit tests for functions in `spider.orb.orb_models`.
"""

import os
import unittest
from spider.orb.orb_models import *

__author__ = "Mike Ryu"
__copyright__ = "Copyright 2023, Mike Ryu"
__credits__ = ["Mike Ryu"]
__license__ = "MIT"
__email__ = "dongyub.ryu@gmail.com"

class OrbAgentTest(unittest.TestCase):
    def setUp(self):
        cwd = os.path.dirname(__file__)
        host_path = "./data"
        page_path = host_path + "/spider.orb_{:02d}.in.html"

        num_samples = 5
        sample_paths = [os.path.relpath(page_path.format(i), cwd) for i in range(num_samples)]

        self.host = os.path.relpath(host_path, cwd)
        self.uris = [OrbURI(sample_paths[i], dict()) for i in range(num_samples)]

        self.dummy_doc_db = OrbDocDB()
        self.dummy_uri_db = OrbUriDB()

        self.base_config = {
            "external": ["https://", "http://"],
            "encoding": "UTF-8",
            "parser": "html.parser",
            "debug": True
        }

    def test_crawl_io_error(self):
        config = dict(self.base_config)
        config["tags"] = {"p": {}}
        agent = OrbAgent(OrbURI("bad_uri.html (THIS ERROR MSG IS EXPECTED)"),
                         self.dummy_doc_db, self.dummy_uri_db, config)

        try:
            content, link = agent.crawl()
            self.assertEqual(0, len(list(content)))
            self.assertEqual(0, len(list(link)))
        except OSError as e:
            self.fail(f"OSError raised: {str(e)}")

    def test_crawl_0_empty_case(self):
        config = dict(self.base_config)
        config["tags"] = {"p": {}}
        agent = OrbAgent(self.uris[0], self.dummy_doc_db, self.dummy_uri_db, config)
        content, link = agent.crawl()

        with self.assertRaises(StopIteration):
            next_content = next(content)
            print(f"[{next_content}]")

        with self.assertRaises(StopIteration):
            next(link)

    def test_crawl_1_simple_case_content_only(self):
        config = dict(self.base_config)
        config["tags"] = {"h1": {}, "p": {}}
        agent = OrbAgent(self.uris[1], self.dummy_doc_db, self.dummy_uri_db, config)
        content, link = agent.crawl()

        try:
            self.assertEqual("Top-level Heading Paragraph content!", next(content).content)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(link)

    def test_crawl_2_simple_case_content_and_link(self):
        config = dict(self.base_config)
        config["tags"] = {"h2": {}, "p": {}}
        agent = OrbAgent(self.uris[2], self.dummy_doc_db, self.dummy_uri_db, config)
        content, link = agent.crawl()

        try:
            self.assertEqual("Subheading HTML links are defined with the <a> tag:", next(content).content)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(content)

        try:
            self.assertEqual("https://www.mikeryu.com", next(link).uri)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(link)

    def test_crawl_3_simple_case_content_and_links(self):
        config = dict(self.base_config)
        config["tags"] = {"p": {}}
        agent = OrbAgent(self.uris[3], self.dummy_doc_db, self.dummy_uri_db, config)
        content, link = agent.crawl()

        try:
            content_text = next(content).content
            self.assertTrue("Four score and seven years ago our fathers brought" in content_text)
            self.assertTrue("all men are created equal. Now we are engaged in a great civil war" in content_text)
            self.assertTrue("   The brave men, living and dead, who struggled here, have consecrated" in content_text)
            self.assertTrue("for the people, shall not perish from the earth" in content_text)
            self.assertFalse("Go to 01" in content_text)
            self.assertFalse("Go to 02" in content_text)
            self.assertFalse("Visit Mike's site!" in content_text)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(content)

        try:
            all_links = [_.uri for _ in link]
            self.assertTrue(f"{self.host}/spider.orb_01.in.html" in all_links)
            self.assertTrue(f"{self.host}/spider.orb_02.in.html" in all_links)
            self.assertTrue("https://www.mikeryu.com" in all_links)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(link)

    def test_crawl_4_realistic_case(self):
        config = dict(self.base_config)
        config["tags"] = {"dd": {}}
        agent = OrbAgent(self.uris[4], self.dummy_doc_db, self.dummy_uri_db, config)
        content, link = agent.crawl()

        try:
            content_text = next(content).content
            self.assertTrue("Then went Samson to Gaza, and saw there an harlot, and went in unto her." in content_text)
            self.assertTrue("Samson is come hither. And they compassed him in, and laid wait" in content_text)
            self.assertTrue("took hold of the two middle pillars upon which the" in content_text)
            self.assertTrue("And he said unto her, If they bind me fast" in content_text)
            self.assertFalse("Judges 15" in content_text)
            self.assertFalse("Index" in content_text)
            self.assertFalse("Judges 17" in content_text)
            self.assertFalse("Download Free Bible" in content_text)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(content)

        try:
            all_links = [_.uri for _ in link]
            self.assertTrue(f"{self.host}/index.htm" in all_links)
            self.assertTrue(f"{self.host}/07015.htm" in all_links)
            self.assertTrue(f"{self.host}/07017.htm" in all_links)
            self.assertTrue("http://www.truth.info/download/bible.htm" in all_links)
        except StopIteration:
            self.fail()

        with self.assertRaises(StopIteration):
            next(link)

    def test_crawl_5_handle_duplicates_with_dbs(self):
        config = dict(self.base_config)
        config["tags"] = {"dd": {}}
        docs, links = OrbAgent(self.uris[4], self.dummy_doc_db, self.dummy_uri_db, config).crawl()

        _ = [doc for doc in docs]
        _ = [uri for uri in links]

        agent = OrbAgent(self.uris[4], self.dummy_doc_db, self.dummy_uri_db, config)
        docs, links = agent.crawl()

        with self.assertRaises(StopIteration):
            next(docs)

        with self.assertRaises(StopIteration):
            next(links)

class OrbUriFrontierTest(unittest.TestCase):
    def setUp(self):
        cwd = os.path.dirname(__file__)
        num_samples = 5

        sample_paths = [os.path.relpath("./data/spider.orb_{:02d}.in.html".format(i), cwd) for i in range(num_samples)]
        self.uris = [OrbURI(sample_paths[i], dict()) for i in range(num_samples)]

    def test_constructor_bool_and_len(self):
        with self.assertRaises(ValueError):
            OrbUriFrontier(list())

        frontier = OrbUriFrontier(self.uris)
        self.assertTrue(frontier)
        self.assertEqual(5, len(frontier))
        self.assertEqual(self.uris[0], frontier.peek())

    def test_str(self):
        frontier = OrbUriFrontier(self.uris)
        self.assertTrue(frontier)
        self.assertEqual(
            "Size: {:d}\nNext: {}".format(5, self.uris[0]),
            str(frontier)
        )

    def test_push_peek_and_pop(self):
        frontier = OrbUriFrontier(self.uris[:1])
        self.assertEqual(self.uris[0], frontier.peek())

        frontier.pop()
        self.assertFalse(bool(frontier))
        self.assertEqual(0, len(frontier))

        for i in range(len(self.uris)):
            frontier.push(self.uris[i])
            self.assertTrue(bool(frontier))
            self.assertEqual(i + 1, len(frontier))
            self.assertEqual(self.uris[0], frontier.peek())

        init_len = len(frontier)
        for j in range(init_len):
            self.assertEqual(self.uris[j], frontier.peek())
            self.assertEqual(self.uris[j], frontier.pop())
            self.assertEqual(init_len - j - 1, len(frontier))

        self.assertFalse(frontier)


from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('order/', include('order.urls', namespace='order'),),
    path('', include('mainpage.urls', namespace='mainpage'),),
    path('main/', include('main.urls', namespace='main')),
    path('booth/', include('booth.urls', namespace='booth')),
    path('visitor/', include('visitor.urls', namespace='visitor')),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


# Write a program that accepts a sentence and calculate the number of upper case letters and lower case letters.

#i/p: Hello world!
# UPPER CASE 1
# LOWER CASE 9

from collections import Counter

UPPER_CASE = LOWER_CASE = 0
raw_input = input("enter the sentence ")
input_dict = Counter(raw_input)
for k,v in input_dict.items():
  if k.islower():
    LOWER_CASE += v
  elif k.isupper():
    UPPER_CASE += v

print(f"UPPER CASE {UPPER_CASE} \n LOWER CASE {LOWER_CASE}")


"""
The output data from the first script is used in this code which is run
in Abaqus to create the muscles.
Both scripts need to be located in the same folder. Use this folder as
the work directory in Abaqus.
"""

from abaqus import *
from abaqusConstants import *
import __main__

import section
import regionToolset
import displayGroupMdbToolset as dgm
import part
import material
import assembly
import step
import interaction
import load
import mesh
import optimization
import job
import sketch
import visualization
import xyPlot
import displayGroupOdbToolset as dgo
import connectorBehavior

#------------------------------------------------------------------------------------------------------------
#--- HIERARCHICAL LEVEL 5 - MUSCLE --------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------------

#------ OUTPUT OF FIRST SCRIPT ------------------------------------------------------------------------------

"""
From the first script, read the output data of the two text files where the names
of all text files for (1) the input variables and (2) the vertice coordinates
are saved.
"""

all_txt_input="all_txt_input.txt"
all_txt_coordinates="all_txt_coordinates.txt"

txt_input = open(all_txt_input,'r')
txt_coordinates = open(all_txt_coordinates,'r')

input_entries = txt_input.read().splitlines()
coordinates_entries = txt_coordinates.read().splitlines()

txt_input.close
txt_coordinates.close

#------ GENERATION OF THE STRUCTURES ------------------------------------------------------------------------

# loop to create all structures
for i_structure in range(len(input_entries)):

    # read the input values from each structure of the first script
    input_entry = open(input_entries[i_structure],'r')
    read_input_entry = input_entry.readlines()
    number_fascicles = float(read_input_entry[0])
    r_muscle = float(read_input_entry[1])
    r_muscle_inner = float(read_input_entry[2])
    l_muscle = float(read_input_entry[3])
    thickness_fascia = float(read_input_entry[4])
    thickness_epimysium = float(read_input_entry[5])
    input_entry.close()

    # read the polygon vertice-coordinates created by the first script
    v_x = []
    v_y = []
    coordinates_entry = open(coordinates_entries[i_structure],'r')
    read_coordinates_entry = coordinates_entry.readlines()
    coordinates_entry.close()

    #------ GEOMETRY NAME -----------------------------------------------------------------------------------

    # prepare a newly named model and delete the default model
    model = mdb.Model(name='muscle')
    assembly = model.rootAssembly
    if mdb.Model(name='Model-1'):
        del mdb.models['Model-1']

    #--------- FASCICLES ------------------------------------------------------------------------------------

    """
    Fascicles are generated by connecting the input coordinates polygon by
    polygon with lines. This is done by saving the x- and y-coordinates of the
    vertices of one polygon in separate lists and immediately creating this
    polygon. Afterwards, the same procedure is done with the next polygon etc.
    """

    sketch_fascicles = model.ConstrainedSketch(name='sketch_fascicles', sheetSize=r_muscle*2)

    a = 0
    count = 0
    # iterate over all vertice-coordinates
    for line in read_coordinates_entry:
        # the x- and y-vertice-coordinates are saved in separate lists
        if line != '\n':
            v_string = line.split(' ')
            v_x.append(round(float(v_string[0]),7))
            v_y.append(round(float(v_string[1]),7))

        # the fascicle polygons are created by connecting the vertices with lines
        else:
            count -= 1
            for i in range(a,count+1,1):
                if i < count:
                    sketch_fascicles.Spline(points=((v_x[i], v_y[i]), (v_x[i+1], v_y[i+1])))
                else:
                    sketch_fascicles.Spline(points=((v_x[count], v_y[count]), (v_x[a], v_y[a])))
            a = count+1
        count += 1

    fascicles = model.Part(dimensionality=THREE_D, name='fascicles', type=DEFORMABLE_BODY)
    fascicles.BaseSolidExtrude(depth=l_muscle, sketch=sketch_fascicles)
    assembly.Instance(name='fascicles', part=fascicles, dependent=ON)

    #--------- PERIMYSIUM -----------------------------------------------------------------------------------

    """
    Perimysium is generated by using the fascicle sketch.
    """

    sketch_perimysium = model.ConstrainedSketch(name='sketch_perimysium', sheetSize=r_muscle*1.5)
    sketch_perimysium.CircleByCenterPerimeter(center=(0, 0), point1=(r_muscle*2, 0))
    sketch_perimysium.retrieveSketch(sketch=model.sketches['sketch_fascicles'])

    perimysium = model.Part(dimensionality=THREE_D, name='perimysium', type=DEFORMABLE_BODY)
    perimysium.BaseSolidExtrude(depth=l_muscle, sketch=sketch_perimysium)
    assembly.Instance(name='perimysium', part=perimysium, dependent=ON)

    #------ CUT BOTH COMPONENTS TO MUSCLE RADIUS ------------------------------------------------------------

    """
    Fascicle and perimysium are cut out to obtain the final circular shape and
    the outer perimysium edge is added to the muscle. Here, an additional plane
    and an axis is needed to cut areas and add the outer perimysium edge.
    """

    for i in range(2):
        if i == 0:
            component = model.parts['fascicles']
        else:
            component = model.parts['perimysium']

        # create one xy-plane (d1[2]) and one axis (d1[5]) through two points (d1[3] and d1[4])
        d1 = component.datums
        component.DatumPlaneByPrincipalPlane(principalPlane=XYPLANE, offset=l_muscle)
        component.DatumPointByCoordinate(coords=(0, 0, l_muscle))
        component.DatumPointByCoordinate(coords=(1, 1, l_muscle))
        component.DatumAxisByTwoPoint(point1=d1[3], point2=d1[4])

        # cut out fascicle and perimysium
        t = component.MakeSketchTransform(sketchPlane=d1[2], sketchUpEdge=d1[5],
            sketchPlaneSide=SIDE1, sketchOrientation=RIGHT, origin=(0.0, 0.0, l_muscle))
        sketch_cut = model.ConstrainedSketch(name='__profile__',
            sheetSize=r_muscle*2, gridSpacing=r_muscle/50, transform=t)
        sketch_cut.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle_inner, 0.0))
        sketch_cut.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle*2, 0.0))
        component.CutExtrude(sketchPlane=d1[2], sketchUpEdge=d1[5], sketchPlaneSide=SIDE1,
            sketchOrientation=RIGHT, sketch=sketch_cut, flipExtrudeDirection=OFF)

        if i == 1:
            # generate outer perimysium edge
            sketch_outer_perimysium = model.ConstrainedSketch(name='__profile__',
                sheetSize=r_muscle*2, gridSpacing=r_muscle/50, transform=t)
            sketch_outer_perimysium.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle_inner, 0.0))
            sketch_outer_perimysium.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle, 0.0))
            component.SolidExtrude(sketchPlane=d1[2], sketchUpEdge=d1[5], sketchPlaneSide=SIDE1,
                sketchOrientation=RIGHT, sketch=sketch_outer_perimysium, depth=l_muscle, flipExtrudeDirection=ON)

    #--------- EPIMYSIUM ------------------------------------------------------------------------------------

    """
    Epimysium is placed as a thin hollow cylinder on the outer perimysium edge.
    """

    sketch_epimysium = model.ConstrainedSketch(name='sketch_epimysium', sheetSize=r_muscle*2)
    sketch_epimysium.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle, 0.0))
    sketch_epimysium.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle+thickness_epimysium, 0.0))

    epimysium = model.Part(name='epimysium', dimensionality=THREE_D, type=DEFORMABLE_BODY)
    epimysium.BaseSolidExtrude(sketch=sketch_epimysium, depth=l_muscle)
    assembly.Instance(name='epimysium', part=epimysium, dependent=ON)

    #--------- FASCIA ---------------------------------------------------------------------------------------

    """
    Fascia is placed as a thin hollow cylinder on the epimysium structure.
    """

    sketch_fascia = model.ConstrainedSketch(name='sketch_fascia', sheetSize=r_muscle*2)
    sketch_fascia.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle+thickness_epimysium, 0.0))
    sketch_fascia.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(r_muscle+thickness_epimysium+thickness_fascia, 0.0))

    fascia = model.Part(name='fascia', dimensionality=THREE_D, type=DEFORMABLE_BODY)
    fascia.BaseSolidExtrude(sketch=sketch_fascia, depth=l_muscle)
    assembly.Instance(name='fascia', part=fascia, dependent=ON)

    #--------- MERGE TO ONE INSTANCE ------------------------------------------------------------------------

    # merge the different instances of the muscle to one instance
    all_instances = assembly.instances.keys()
    assembly.InstanceFromBooleanMerge(name='muscle', instances=([assembly.instances[all_instances[i]]
        for i in range(len(assembly.instances))] ), keepIntersections=ON, originalInstances=SUPPRESS, domain=GEOMETRY)
    assembly.features.changeKey(fromName='muscle-1', toName='muscle')

    #--------- SAVE MODEL AS CAE-FILE -----------------------------------------------------------------------

    file_ending=input_entries[i_structure].replace('input_values_muscle','')
    file_ending=file_ending.replace('.txt','')

    file='muscle'+str(file_ending)
    mdb.saveAs(str(file)+'.cae')


import copy
import logging
import os
from collections.abc import Callable
from typing import TypeAlias

from .models import AudioFormat
from .models import Download
from .models import DownloadInput
from .models import DownloadState
from .models import DownloadStatus
from .models import VideoFormat
from .ytdlp import PostprocessorHookInfo
from .ytdlp import ProgressHookInfo
from .ytdlp import YoutubeDLParams

logger = logging.getLogger('ydcore')

StatusHook: TypeAlias = Callable[[Download], None]

# Default params used with yt-dlp. These may be overriden by our download
# options.
# Note: if a default isnt provided then the yt-dlp default will be used.
DEFAULT_YTDLP_PARAMS: YoutubeDLParams = {
    'quiet': True,
    'retries': 5,
    'verbose': False,
    'noprogress': True,
}

class DownloadConfig:
    def __init__(
        self,
        download: DownloadInput,
        output_directory: str,
        *,
        output_file_readable_name: bool = False,
    ) -> None:
        self.download = Download(
            **download.model_dump(),
            status=DownloadStatus(
                state=DownloadState.WAITING,
            ),
        )
        self._output_directory = output_directory
        self._output_file_readable_name = output_file_readable_name
        self._status_hooks: list[StatusHook] = []
        self._overrides: YoutubeDLParams = {}

    def add_status_hook(self, hook: StatusHook) -> None:
        self._status_hooks.append(hook)

    def on_status_update(self, status: DownloadStatus) -> None:
        self._handle_status_update(status)

    def add_ytdlp_params_overrides(self, params: YoutubeDLParams) -> None:
        self._overrides = params

    @property
    def filename(self) -> str:
        return f'{self.download.video.id}.{self.download.options.format.value}'

    @property
    def path(self) -> str:
        return os.path.join(self._output_directory, self.filename)

    @property
    def _is_audio_download(self) -> bool:
        return self.download.options.format in AudioFormat

    @property
    def _is_video_download(self) -> bool:
        return self.download.options.format in VideoFormat

    @property
    def as_ytdlp_params(self) -> YoutubeDLParams:
        postprocessors: list[dict[str, str | bool | int]] = []
        # Only append audio postprocessor if we are downloading audio format.
        if self._is_audio_download:
            postprocessors.append({
                'key': 'FFmpegExtractAudio',
                'preferredcodec': self.download.options.format.value,
                'preferredquality': '192',
            })
        # Only append video postprocessor if we are downloading video format.
        if self._is_video_download:
            postprocessors.append(
                {
                    'key': 'FFmpegVideoConvertor',
                    'preferedformat': self.download.options.format.value,
                },
            )
        # Only append metadata to the video if enabled by user
        if self.download.options.embed_metadata:
            postprocessors.append({'key': 'FFmpegMetadata'})
        # Only append thumbnail embedding if enabled by user
        if self.download.options.embed_thumbnail:
            postprocessors.append({
                'key': 'EmbedThumbnail',
                'already_have_thumbnail': False,
            })
            self._overrides['writethumbnail'] = True
        if self.download.options.embed_subtitles:
            postprocessors.append({
                'key': 'FFmpegEmbedSubtitle',
                'already_have_subtitle': False,
            })
            self._overrides['writesubtitles'] = True
            self._overrides['subtitlesformat'] = 'best'

        filename = self.download.video.id
        if self._output_file_readable_name:
            filename = str(self.download.video)

        params: YoutubeDLParams = {
            **DEFAULT_YTDLP_PARAMS,
            **self._overrides,
            'format': self._ytdlp_format,
            'progress_hooks': [self._progress_hook],
            'postprocessor_hooks': [self._postprocessor_hook],
            'post_hooks': [self._post_hook],
            'outtmpl': f'{self._output_directory}/{filename}.%(ext)s',
            'postprocessors': postprocessors,
        }

        logger.debug(
            f'Downloading {self.download.video.url} with params: {params}.',
        )

        return params

    @property
    def _ytdlp_format(self) -> str:
        options = self.download.options
        quality = options.quality.value
        extension = options.format.value
        # bestvideo*[ext=X]+bestaudio/bestvideo*+bestaudio/best or
        # worstvideo*[ext=X]+worstaudio/worstvideo*+worstaudio/worst
        if self._is_video_download:
            proper_ext = f'{quality}video*[ext={extension}]+{quality}audio'
            return f'{proper_ext}/{quality}video*+{quality}audio/{quality}'
        # bestaudio[ext=X]/bestaudio/best or worstaudio[ext=X]/worstaudio/worst
        elif self._is_audio_download:
            return f'{quality}audio[ext={extension}]/{quality}audio/{quality}'
        # Default to returning the quality (ie 'best' or 'worst')
        return quality

    def _progress_hook(self, info: ProgressHookInfo) -> None:
        url = self.download.video.url
        status = info.get('status')
        if status == 'downloading':
            logger.debug(f'Download status update DOWNLOADING for: {url}.')
            downloaded_bytes = info.get('downloaded_bytes')
            total_bytes = info.get(
                'total_bytes', info.get('total_bytes_estimate'),
            )
            elapsed = info.get('elapsed')
            eta = info.get('eta')
            speed = info.get('speed')
            logger.debug(
                f'Downloading ({url}): ' +
                f'downloaded_bytes={downloaded_bytes}, ' +
                f'total_bytes={total_bytes}, ' +
                f'elapsed={elapsed}, eta={eta}, ' +
                f'speed={speed}.',
            )
            self._handle_status_update(
                DownloadStatus(
                    state=DownloadState.DOWNLOADING,
                    downloaded_bytes=downloaded_bytes,
                    total_bytes=total_bytes,
                    elapsed=elapsed,
                    eta=eta,
                    speed=speed,
                ),
            )
        elif status == 'error':
            logger.error(f'Download status update ERROR for: {url}.')
            self._handle_status_update(
                DownloadStatus(state=DownloadState.ERROR),
            )
        elif status == 'finished':
            logger.debug(f'Download status update FINISHED for: {url}.')
            self._handle_status_update(
                DownloadStatus(state=DownloadState.PROCESSING),
            )

    def _postprocessor_hook(self, info: PostprocessorHookInfo) -> None:
        url = self.download.video.url
        status = info.get('status')
        logger.debug(
            f'Postprocessor status update {str(status).upper()} for: {url}.',
        )
        postprocessor: str | None = None
        if status == 'started' or status == 'processing':
            postprocessor = info.get('postprocessor')
            logger.debug(
                f'Postprocessor {postprocessor} is {status.upper()}.',
            )
        elif status == 'finished':
            postprocessor = None
            logger.debug('Postprocessor is None.')
        self._handle_status_update(
            DownloadStatus(
                state=DownloadState.PROCESSING,
                postprocessor=postprocessor,
            ),
        )

    def _post_hook(self, filepath: str) -> None:
        logger.debug(
            f'Post status update for: {self.download.video.url}.',
        )
        state = DownloadState.DONE
        if not os.path.exists(filepath):
            logger.error(f'File does not exist: {filepath}.')
            state = DownloadState.ERROR
        self._handle_status_update(
            DownloadStatus(
                state=state,
            ),
        )

    def _handle_status_update(self, update: DownloadStatus) -> None:
        self.download.status = update
        # Call each hook with the update
        for h in self._status_hooks:
            h(copy.deepcopy(self.download))


import csv
import pandas

#pandas_data = pandas.read_csv("weather_data.csv")
#print(pandas_data)
#print(pandas_data["temp"])

#print(pandas_data["temp"].mean())
#print(pandas_data["temp"].max())

#print(pandas_data[pandas_data["day"] == "Wednesday"])
# or pandas_data[pandas_data.day == "Wednesday"]
#print(pandas_data[pandas_data.temp == pandas_data.temp.max()])

#monday = pandas_data[pandas_data.day == "Monday"]
#monday_temp_F = monday.temp * 9 / 5 + 32
#print(monday_temp_F)

#new_dict = {
   # "students": ["maxim", "ilon", "mona"],
    #"score": [100, 75, 25]
#}

#new_data = pandas.DataFrame(new_dict)
#print(new_data)
#new_data.to_csv("new_data.csv")

#maxim = new_data[new_data.students == "maxim"]
#print(maxim.score)

squirrel_data = pandas.read_csv("Squirrel_Data.csv")
squirrel_colors = squirrel_data["Primary Fur Color"]
black_squirrel = len(squirrel_data[squirrel_colors == "Black"])
cinnamon_squirrel = len(squirrel_data[squirrel_colors == "Cinnamon"])
gray_squirrel = len(squirrel_data[squirrel_colors == "Gray"])
undefined_squirrel_color = len(squirrel_data) - black_squirrel - cinnamon_squirrel - gray_squirrel

squirrel_dict = {
    "Color": ["Black", "Cinnamon", "Gray"],
    "Count": [black_squirrel, cinnamon_squirrel, gray_squirrel]
}

squirrel_color_data = pandas.DataFrame(squirrel_dict)
print(squirrel_color_data)


import re

import numpy as np
import pandas as pd
from abc import ABCMeta, abstractmethod
from typing import Optional, List, Tuple
from core.spider.errors.basics import Error

class BaseExtract(metaclass=ABCMeta):
    """爬虫类"""

    def __init__(self, paras_content: Tuple, context={}):
        self.tree, self.soup, self.content = paras_content
        self.context = context
        self.__data_dict = {}
        self.errors = {}

    @abstractmethod
    def analyze(self, request):
        """自定义规则"""
        ...

    def add_error(self, error):
        self.errors.update(error)

    def success(self) -> bool:
        return self.errors.__len__() == 0

    @property
    def data(self, ):
        #
        return self.__data_dict

    def extract_all_img(self):
        """解析所有图片"""
        try:
            base = self.context.get('url')
            from urllib.parse import urljoin
            self.__data_dict["imgList"] = [urljoin(base=base, url=img.get('src')) for img in self.soup.find_all('img')]
        except Exception as e:
            raise Error(msg='未发现图片')

    def extract_all_table(self):
        """后期做表格与图"""
        try:

            df = pd.read_html(self.content)

            for item in df:
                if item.size != 0:
                    df = item
                    break
            else:
                #  测试
                # self.__data_dict['table'] = {
                #     'columns': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
                #     'data': [120, 200, 150, 80, 70, 110, 130],
                # }
                raise Error(msg="未发现表格")
            # df = pd.DataFrame(data=[[120, 200, 150, 80, 70, 110, 130]],
            #                   columns=['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
            df.fillna(value='', inplace=True)
            col = []
            data = []
            # 创建列

            for i, v in enumerate(df.columns):
                if i == 0:
                    col.append({
                        'title': v,
                        'dataIndex': f'field{i}',
                        'key': i,
                        'fixed': 'left'
                    })
                else:
                    col.append({
                        'title': v,
                        'dataIndex': f'field{i}',
                        'key': i
                    })
            for i in range(df.shape[0]):
                d = df.iloc[i, :]
                dic = {'key': i, }
                for j in range(df.shape[1]):
                    dic.update({
                        f'field{j}': d[j]
                    })
                data.append(dic)
            self.__data_dict['table'] = {
                'columns': col,
                'data': data
            }
        except ValueError as e:
            raise Error(msg="未发现表格")

    def extract_all_text(self):
        # 文本关键提取
        self.__data_dict['text'] = ''.join(re.sub(r'\s+', ' ', self.soup.get_text()))

    def extract_all_chart(self):
        try:
            df = pd.read_html(self.content)
            for item in df:
                if item.size != 0:
                    df = item
                    break
            else:
                raise Error(msg='未发现图表')

            df.dropna(axis=1, inplace=True)
            pf = []
            for index, col in enumerate(df.columns):
                if df[col].dtype.type == np.float64 or index == 0:
                    pf.append(col)
            df = df.loc[:, pf].head(10)

            yData = df.iloc[:, 1:]
            self.__data_dict['chart'] = {
                'xData': df.iloc[:, 0].tolist(),
                'yData': [yData[i].tolist() for i in yData],
            }
        except ValueError as e:
            raise Error(msg='未发现图表')
            # self.__data_dict['chart'] = None

    def dispatch(self, opt_list: Optional[str or List[str]]):
        opt_map = {
            '图片': "img",
            '文本': "text",
            '表格': "table",
            '图表': "chart",
        }
        if isinstance(opt_list, str):
            opt_list = opt_list.split(',')
        for op in opt_list:
            opt = opt_map.get(op, '')
            if not hasattr(self, f'extract_all_{opt}'):
                self.add_error(
                    {'method error': "method not find"}
                )
                continue
            try:
                getattr(self, f'extract_all_{opt}')()
            except Error as e:
                self.add_error({
                    opt: e.msg
                })

if __name__ == '__main__':
    pass