import os
from pymoo.mcdm.high_tradeoff import HighTradeoffPoints
from sklearn.preprocessing import MinMaxScaler
import pareto
import pandas as pd
from edbo.plus.optimizer_botorch import EDBOplus
from edbo.plus.optimizer import EDBOplus as EDBO
import torch
from botorch.utils.multi_objective.hypervolume import Hypervolume
from scipy.spatial.distance import euclidean
import copy
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

def is_pareto(objectives):
    """
    Find the pareto-efficient points.

    Parameters
    ----------
    objectives: array
        array containing all the objectives values.
    Returns
    -------
    is_efficient
        list of booleans, True: Pareto efficient and False: not Pareto efficient.

    """
    is_efficient = np.ones(objectives.shape[0], dtype=bool)
    for i, c in enumerate(objectives):
        is_efficient[i] = np.all(np.any(objectives[:i]>c, axis=1)) and np.all(np.any(objectives[i+1:]>c, axis=1))
    return is_efficient

class Benchmark():

    """
    Class for Benchmarking HTE datasets.
    """

    def __init__(self,
                 df_ground, index_column,
                 objective_names, objective_modes,
                 features_regression='all',
                 objective_thresholds=None,
                 filename='benchmark.csv',
                 acquisition_function='EHVI',
                 filename_results='benchmark_results.csv'):
        """

        Parameters
        ----------
        df_ground: Pandas dataframe.
            Pandas dataframe containing the features and objectives.
        index_column: string
            String with the name of the index column of the 'df_ground' Pandas dataframe.
        objective_names: list
            list of strings including the names of the columns that will be considered as objectives.
        objective_modes: list
            list of strings for deciding whether the objective has to be minimize ('min') or maximize ('max').
        features_regression: list
            list of strings containing the names of the columns that will be considered as features for the regression model.
        objective_thresholds: list
            list of floats containing the threshold values for each objective.
        acquisition_function: string
            name of the acquisition function to use (implemented are: 'EHVI', 'MOUCB', 'MOGreedy').
        filename: string
            name of the file to run the optimization (temporary file).
        filename_results:
            name of the file to store the results of the benchmark.
        """
        self.df_ground = df_ground
        self.objective_names = objective_names
        self.objective_modes = objective_modes
        self.objective_thresholds = objective_thresholds
        self.features_regressions = features_regression
        self.filename = filename
        self.filename_results = filename_results
        self.index_column = index_column
        self.acquisition_function = acquisition_function

        # Safe check. Check whether there are no duplicates in the regression domain.
        df_check = self.df_ground[self.features_regressions]
        msg = 'There are entries that are degenerate. Check your dataset.'
        assert len(df_check) == len(df_check.drop_duplicates()), msg

        # Calculate data for the ground truth function.
        self.objective_values_ground = self.get_objective_values(df=self.df_ground)
        self.pareto_ground, self.idx_pareto_ground = self.get_pareto_points(objective_values=self.objective_values_ground)
        self.tradeoff_ground = self.get_high_tradeoff_points(
                pareto_points=self.pareto_ground)
        print('High trade-off ground truth:', self.tradeoff_ground)

        # Fit scaler for a fair comparison between objectives.
        self.scaler_ground = MinMaxScaler()
        self.scaler_ground.fit(self.objective_values_ground)

        # Calculate Hypervolume using the ground scaler.
        self.hypervolume_ground = self.get_hypervolume(
                pareto_points=self.pareto_ground,
                thresholds=self.objective_thresholds)

        # Instanciate EDBOplus.
        if self.acquisition_function == 'EHVI':
            self.edbo = EDBOplus()
        else:
            self.edbo = EDBO()

        # Generate DataFrame for storing collected data and predictions.
        if not os.path.exists(filename):
            # Create first scope if filename is not found.
            df_edbo = self.df_ground.copy(deep=True)
            df_edbo = df_edbo.drop(columns=self.objective_names)
            df_edbo.to_csv(filename, index=False)

    def get_hypervolume(self, pareto_points, thresholds):
        """
        Calculate hypervolume using a reference point for each objective
        (if None it takes automatically the minimum of each objective in the ground truth).
        Note 1: It is always scaled w.r.t. the ground truth for a fair comparison between objectives.
        Note 2: Assumes maximization.
        """

        references = copy.deepcopy(thresholds)

        if references is None:
            references = [None] * len(self.objective_names)

        for i in range(0, len(references)):
            if references[i] is None:
                references[i] = np.min(self.objective_values_ground, axis=0)[i]

        references_scaled = self.scaler_ground.transform(np.array([references]))[0]
        pareto_points_scaled = self.scaler_ground.transform(pareto_points)

        pareto_torch = torch.Tensor(pareto_points_scaled)
        hv = Hypervolume(ref_point=torch.Tensor(references_scaled))
        hypervolume = hv.compute(pareto_Y=pareto_torch)

        return hypervolume

    def get_objective_values(self, df):  # Maximizing.
        """ Get a list of objective values from a given dataframe (for instance yields and cost)."""
        predata = []
        for obj in range(0, len(self.objective_names)):
            d = [float(i) for i in df[self.objective_names[obj]]]
            if self.objective_modes[obj] == 'min':
                d = -np.array(d)
            else:
                d = np.array(d)
            predata.append(d.flatten())
        objective_values = np.array(predata).T

        # Calculate also bounds (best and worst samples).
        max_bounds = []
        min_bounds = []
        for i in range(0, len(self.objective_names)):
            if self.objective_modes[i] == 'min':
                max_bounds.append(-np.max(self.df_ground[self.objective_names[i]]))
                min_bounds.append(-np.min(self.df_ground[self.objective_names[i]]))
            if self.objective_modes[i] == 'max':
                max_bounds.append(np.max(self.df_ground[self.objective_names[i]]))
                min_bounds.append(np.min(self.df_ground[self.objective_names[i]]))
        self.max_bounds = max_bounds
        self.min_bounds = min_bounds

        return objective_values

    def get_pareto_points(self, objective_values):
        """ Get pareto for the ground truth function.
        NOTE: Assumes maximization."""
        pareto_ground = pareto.eps_sort(tables=objective_values,
                                        objectives=np.arange(len(self.objective_names)),
                                        maximize_all=True)
        idx_pareto = is_pareto(objectives=-objective_values)
        return np.array(pareto_ground), idx_pareto

    def get_high_tradeoff_points(self, pareto_points):
        """ Pass a numpy array with the pareto points and returns a numpy
            array with the high tradeoff points."""

        scaler_pareto = MinMaxScaler()
        pareto_scaled = scaler_pareto.fit_transform(pareto_points)
        try:
            tradeoff = HighTradeoffPoints()

            tradeoff_args = tradeoff.do(-pareto_scaled)  # Always minimizing.
            tradeoff_points = pareto_points[tradeoff_args]
        except:
            tradeoff_points = []
            pass
        return tradeoff_points

    def get_distance_tradeoff_to_ground(self, set_of_points):
        """
        Max. minimum Euclidean distance between a set of points and
        the ground truth tradeoff point(s).
        """
        if len(self.tradeoff_ground) != 0:
            d_ij = []
            try:
                for tradeoff_point_ground in self.tradeoff_ground:
                    d_i = []
                    for point in set_of_points:
                        d_i.append(euclidean(point, tradeoff_point_ground))
                    d_ij.append(np.min(d_i))
            except:
                for tradeoff_point_ground in self.tradeoff_ground[0]:
                    d_i = []
                    for point in set_of_points:
                        d_i.append(euclidean(point, tradeoff_point_ground))
                    d_ij.append(np.min(d_i))
            return np.max(d_ij)
        else:
            return 'NA'

    def get_maximin_distance_pareto_to_ground(self, pareto_set):
        """
        Calculate maximin distance between a pareto set and the ground truth
        pareto. Also called Hausdorff
        """
        d_ij = []
        for pareto_point_ground in self.pareto_ground:
            d_i = []
            for point in pareto_set:
                d_i.append(euclidean(point, pareto_point_ground))
            d_ij.append(np.min(d_i))
        return np.max(d_ij)

    def get_predictions_errors(self):
        """
        Obtain errors in the predictions.
        """
        dict_pred_errors = {}
        df_ground = self.df_ground.copy(deep=True)

        if os.path.exists(f'pred_{self.filename}'):
            df_preds = pd.read_csv(f'pred_{self.filename}')
            df_preds = df_preds.sort_values(by=self.index_column)
            df_ground = df_ground.sort_values(by=self.index_column)

            # Collect information about the MAE, RMSE, ,
            for objective in self.objective_names:
                y_true = df_ground[objective].values
                y_pred = df_preds[f"{objective}_predicted_mean"].values

                mae = (np.sum(np.abs(y_pred - y_true))) / len(y_pred)
                rmse = np.sqrt((np.sum((y_pred - y_true)**2))/len(y_pred))

                from sklearn.metrics import r2_score

                r2 = r2_score(y_true=y_true, y_pred=y_pred)

                dict_pred_errors.update({
                    f"MAE_{objective}": mae,
                    f"RMSE_{objective}": rmse,
                    f"R2_{objective}": r2,
                    })
            print(dict_pred_errors)
        else:
            for objective in self.objective_names:
                dict_pred_errors.update({
                    f"MAE_{objective}": 'NaN',
                    f"RMSE_{objective}": 'NaN',
                    f"R2_{objective}": 'NaN',
                })

        return dict_pred_errors

    def _store_benchmark(self):
        for bt in range(self.batch):
            dict_i = {'step': self.step,
                      'init_method': self.init_method,
                      'init_sample': self.seed,
                      'batch': self.batch,
                      'n_experiments': self.n_experiments,
                      'thresholds': self.objective_thresholds,
                      'dmaximin_pareto': self.pareto_distance_ground_train,
                      'acquisition': self.acquisition_function,
                      'dmaximin_tradeoff': self.tradeoff_distance_ground_train,
                      'hypervolume_ground': self.hypervolume_ground,
                      'hypervolume_sampled': self.hypervolume_train,
                      'hypervolume completed (%)': (self.hypervolume_train/self.hypervolume_ground) * 100,
                      'sample_index': self.idx_next_samples[bt],
            }

            dict_i.update(self.predicted_errors)

            sample_vals = {}
            for kcol in self.collected_values.keys():
                sample_vals[kcol] = self.collected_values[kcol][bt]
            dict_i.update(sample_vals)
            best_samples_values = {}

            for i in range(0, len(self.objective_names)):
                best_i = self.best_values_found[i]
                best_samples_values.update({f"{self.objective_names[i]}_best": best_i})

            dict_i.update(best_samples_values)

            store_columns = list(dict_i.keys())

            if os.path.exists(self.filename_results):
                df_results = pd.read_csv(self.filename_results)
            else:
                df_results = pd.DataFrame(columns=store_columns)

            df_results = df_results.append(dict_i, ignore_index=True)
            df_results.to_csv(self.filename_results, index=False)

        return df_results

    def run(self, steps, batch, seed=0,
            init_method='seed',
            run_folder='./results', plot_ground=True,
            plot_train=False, plot_predictions=False,
            random_sampling=False):

        self.init_method=init_method
        self.seed = seed
        self.batch = batch
        self.run_folder = run_folder

        if not os.path.exists(run_folder):
            os.mkdir(run_folder)

        if plot_ground is True:
            if len(self.objective_names) == 2:
                self._plot_ground_2d()
            if len(self.objective_names) == 3:
                self._plot_ground_3d()

        for step in range(0, steps):
            self.step = step

            df_run = self.edbo.run(
                    filename=self.filename,
                    batch=batch,
                    columns_features=self.features_regressions,
                    objectives=self.objective_names,
                    objective_mode=self.objective_modes,
                    objective_thresholds=self.objective_thresholds,
                    acquisition_function=self.acquisition_function,
                    init_sampling_method=self.init_method,
                    seed=seed)

            df_next = df_run[df_run['priority'] >= 0.5]
            idx_next = df_next[self.index_column].values

            if len(idx_next) < batch:  # Add random if not enough.
                df_next = df_run[df_run['priority'] >= 0]
                idx_next_2 = df_next[self.index_column].values
                l_choice = np.arange(0, len(idx_next_2))
                r_choices = np.random.choice(l_choice, size=(batch-len(idx_next)))
                random_choice_idx = idx_next_2[r_choices]
                idx_next = np.append(idx_next, random_choice_idx)

            self.idx_next_samples = idx_next
            # Test performance of the model with large training data.
            # idx_next = np.random.choice(len(df_run), int(len(df_run)*0.2))
            if random_sampling is True:
                df_next = df_run[df_run['priority'] >= 0]
                idx_next = df_next[self.index_column].values
                choice_idx = idx_next[np.random.choice(np.arange(0, len(idx_next)), size=batch)]
                idx_next = choice_idx

            # Append solutions.
            self.collected_values = {}
            for id in idx_next:
                argwhere_idx_next_ground = np.argwhere(self.df_ground[self.index_column].values == id)[0][0]
                argwhere_dix_next_run = np.argwhere(df_run[self.index_column].values == id)[0][0]
                for obj in self.objective_names:
                    df_run[obj].values[argwhere_dix_next_run] = self.df_ground[obj].values[argwhere_idx_next_ground]
                    try:
                        self.collected_values[obj + "_collected_values"].append(self.df_ground[obj].values[argwhere_idx_next_ground])
                    except:
                        self.collected_values[obj + "_collected_values"] = [self.df_ground[obj].values[argwhere_idx_next_ground]]

            # Update the DataFrame with the new collected data.
            df_run.to_csv(self.filename, index=False)

            new_df = df_run.copy(deep=True)
            # Print best values for each objective and save sampled objectives.
            cumulative_train_y = []
            self.best_values_found = []
            for i in range(0, len(self.objective_names)):
                if self.objective_modes[i] == 'min':
                    best_value = pd.to_numeric(new_df[self.objective_names[i]], 'coerce').min()
                else:
                    best_value = pd.to_numeric(new_df[self.objective_names[i]], 'coerce').max()
                print(f"Best {self.objective_names[i]} found: {best_value}.")
                self.best_values_found.append(best_value)
                vals = pd.to_numeric(new_df[self.objective_names[i]], 'coerce').dropna().values
                if self.objective_modes[i] == 'min':
                    cumulative_train_y.append(-vals)
                else:
                    cumulative_train_y.append(vals)
            cumulative_train_y = np.reshape(cumulative_train_y, (len(cumulative_train_y), -1)).T

            self.pareto_train, self.idx_pareto_train = self.get_pareto_points(objective_values=cumulative_train_y)
            self.tradeoff_train = self.get_high_tradeoff_points(pareto_points=self.pareto_train)
            self.hypervolume_train = self.get_hypervolume(pareto_points=self.pareto_train,
                                                          thresholds=self.objective_thresholds)

            self.tradeoff_distance_ground_train = \
                self.get_distance_tradeoff_to_ground(
                        set_of_points=cumulative_train_y)
            self.pareto_distance_ground_train = \
                    self.get_maximin_distance_pareto_to_ground(
                            pareto_set=self.pareto_train)

            self.n_experiments = len(cumulative_train_y)

            print('Total number of experiments:', self.n_experiments)

            # Print collected samples.
            print('Collected samples \n', df_run[df_run['priority'] < 0])

            print(f"Hypervolume train (w.r.t to ground truth in %): "
                  f"{(self.hypervolume_train/self.hypervolume_ground) * 100}")

            print(f"Maximin distance any train to any ground truth "
                  f"Pareto: {self.pareto_distance_ground_train}")
            print(f"Maximin distance any train to ground truth "
                  f"Tradeoff: {self.tradeoff_distance_ground_train}")

            # Store all information.

            self.predicted_errors = self.get_predictions_errors()
            self._store_benchmark()
            print("\n \n")

            # Get plots.
            self.cumulative_train_y = cumulative_train_y

            if plot_train:
                if len(self.objective_names) == 2:
                    self._plot_train_pareto_2d()
                if len(self.objective_names) == 3:
                    self._plot_train_pareto_3d()

            if plot_predictions and os.path.exists(f"pred_{self.filename}"):
                self._plot_predictions()

    def _plot_predictions(self):

        df_preds = pd.read_csv(f'pred_{self.filename}')
        df_ground = self.df_ground.copy(deep=True)
        df_preds = df_preds.sort_values(by=self.index_column)
        df_ground = df_ground.sort_values(by=self.index_column)

        total_entries = len(df_preds)
        n_columns = 30
        n_rows = int(total_entries / n_columns) + 1

        for i in self.objective_names:
            ground = [np.nan] * n_columns * n_rows
            pred_mean = [np.nan] * n_columns * n_rows
            ei = [np.nan] * n_columns * n_rows
            ground[0:total_entries] = self.df_ground[i].values
            pred_mean[0:total_entries] = df_preds[f"{i}_predicted_mean"].values
            ei[0:total_entries] = df_preds[f"{i}_expected_improvement"].values
            ground = np.reshape(ground, (n_rows, n_columns))
            pred_mean = np.reshape(pred_mean, (n_rows, n_columns))
            ei = np.reshape(ei, (n_rows, n_columns))

            min_threshold = np.min(df_ground[i].values)
            max_threshold = np.max(df_ground[i].values)

            f, (ax1, ax2, ax3) = plt.subplots(
                1, 3,
                figsize=(n_columns, n_rows),
                gridspec_kw={
                  'width_ratios': [1, 1, 1]
                }
            )

            g1 = sns.heatmap(
                ground, cmap='Spectral_r', square=True,
                xticklabels=[], yticklabels=[],
                linewidths=0.7, cbar=False,
                cbar_kws=dict(use_gridspec=False, location="bottom"),
                vmin=min_threshold, vmax=max_threshold,
                ax=ax1
            )

            g2 = sns.heatmap(
                pred_mean, cmap='Spectral_r', square=True,
                xticklabels=[], yticklabels=[],
                linewidths=0.7, cbar=False,
                cbar_kws=dict(use_gridspec=False, location="bottom"),
                vmin=min_threshold, vmax=max_threshold,
                ax=ax2
            )

            g3 = sns.heatmap(
                ei,
                cmap='Blues', square=True,
                xticklabels=[], yticklabels=[],
                linewidths=0.7, cbar=False,
                cbar_kws=dict(use_gridspec=False, location="bottom"),
                vmin=np.min(df_preds[f"{i}_expected_improvement"].values),
                vmax=np.max(df_preds[f"{i}_expected_improvement"].values),
                ax=ax3
            )

            ax1.set_title(f"Ground truth ({i})")
            ax2.set_title(f"Predicted mean ({i})")
            ax3.set_title(f"Expected improvement ({i})")
            plt.tight_layout()
            plt.show()

    def _plot_ground_2d(self):

        fig, ax = plt.subplots(figsize=(10, 10))
        ax.scatter(self.objective_values_ground[:, 0],
                   self.objective_values_ground[:, 1], s=30, lw=1.,
                   edgecolors='black')
        ax.scatter(self.pareto_ground[:, 0], self.pareto_ground[:, 1],
                   s=100, c='orange', lw=1., edgecolors='black')

        import matplotlib.patches as patches
        ax.add_patch(
            patches.Rectangle(
                tuple(self.min_bounds),
                self.max_bounds[0],
                self.max_bounds[1],
                facecolor="red",
                alpha=0.1
            )
        )

        idx_pareto = np.argwhere(self.idx_pareto_ground)
        print('Indices pareto front (ground truth):', idx_pareto)
        for i in range(0, len(idx_pareto)):
            idxi = idx_pareto[i][0]
            ax.text(x=self.objective_values_ground[idxi][0] +0.,
                    y=self.objective_values_ground[idxi][1] +0.,
                    s=str(idxi),
                    )

        ax.set_xlabel(f"{self.objective_names[0]} ({self.objective_modes[0]})")
        ax.set_ylabel(f"{self.objective_names[1]} ({self.objective_modes[1]})")

        if not os.path.exists(f"{self.run_folder}_plots"):
            os.mkdir(f"{self.run_folder}_plots")
        plt.rc("axes.spines", top=False, right=False)
        plt.savefig(f"{self.run_folder}_plots/{self.filename_results}_ground.svg")
        plt.show()

    def _plot_ground_3d(self):

        plt.rcParams['grid.color'] = "lightgray"
        plt.rcParams['grid.linestyle'] = [6., 2., 6., 2.]
        plt.rcParams['grid.linewidth'] = 1.5

        # Scatter plots 3d.
        fig = plt.figure(figsize=(10, 10))
        ax = fig.add_subplot(projection='3d')

        # Plot properties.
        ax.view_init(elev=25, azim=290)
        fig.set_facecolor('white')
        ax.set_facecolor('white')

        ax.scatter(self.objective_values_ground[:, 0],
                   self.objective_values_ground[:, 1],
                   self.objective_values_ground[:, 2],
                   s=100, lw=1.,
                   color='C0',
                   zorder=1.,
                   edgecolors='gray'
                   )

        ax.scatter(self.pareto_ground[:, 0],
                   self.pareto_ground[:, 1],
                   self.pareto_ground[:, 2],
                   marker='o', s=100, c='C1', lw=1.,
                   alpha=0.8,
                   zorder=10.,
                   edgecolors='gray',
                   )

        xmin = np.min(self.objective_values_ground[:, 0])
        xmax = np.max(self.objective_values_ground[:, 0])
        ymin = np.min(self.objective_values_ground[:, 1])
        ymax = np.max(self.objective_values_ground[:, 1])
        zmin = np.min(self.objective_values_ground[:, 2])
        zmax = np.max(self.objective_values_ground[:, 2])

        ax.axes.set_xlim3d(xmin, xmax)
        ax.axes.set_ylim3d(ymin, ymax)
        ax.axes.set_zlim3d(zmin, zmax)

        ax.set_xlabel(f"{self.objective_names[0]} ({self.objective_modes[0]})")
        ax.set_ylabel(f"{self.objective_names[1]} ({self.objective_modes[1]})")
        ax.set_zlabel(f"{self.objective_names[2]} ({self.objective_modes[2]})")

        if not os.path.exists(f"{self.run_folder}_plots"):
            os.mkdir(f"{self.run_folder}_plots")

        plt.savefig(f"{self.run_folder}_plots/{self.filename_results}_ground.svg")

        plt.show()

    def _plot_train_pareto_2d(self):

        fig, ax = plt.subplots(figsize=(10, 10))
        ax.scatter(self.cumulative_train_y[:, 0],
                   self.cumulative_train_y[:, 1], s=30, lw=1.,
                   edgecolors='black')
        ax.scatter(self.pareto_train[:, 0], self.pareto_train[:, 1],
                   s=100, c='orange', lw=1., edgecolors='black')
        ax.scatter(self.pareto_ground[:, 0], self.pareto_ground[:, 1],
                   marker='x', s=100, c='black', lw=1.)

        ax.set_xlabel(f"{self.objective_names[0]} ({self.objective_modes[0]})")
        ax.set_ylabel(f"{self.objective_names[1]} ({self.objective_modes[1]})")

        if not os.path.exists(f"{self.run_folder}_plots"):
            os.mkdir(f"{self.run_folder}_plots")

        plt.savefig(f"{self.run_folder}_plots/{self.filename_results}_train_{self.step}.svg")

        plt.show()

    def _plot_train_pareto_3d(self):

        plt.rcParams['grid.color'] = "lightgray"
        plt.rcParams['grid.linestyle'] = [6., 2., 6., 2.]
        plt.rcParams['grid.linewidth'] = 1.5

        # Scatter plots 3d.
        fig = plt.figure(figsize=(10, 10))
        ax = fig.add_subplot(projection='3d')

        # Plot properties.
        ax.view_init(elev=25, azim=290)
        fig.set_facecolor('white')
        ax.set_facecolor('white')

        ax.scatter(self.cumulative_train_y[:, 0],
                   self.cumulative_train_y[:, 1],
                   self.cumulative_train_y[:, 2],
                   s=100, lw=1.,
                   color='C0',
                   zorder=1.,
                   edgecolors='gray'
                   )

        ax.scatter(self.pareto_ground[:, 0],
                   self.pareto_ground[:, 1],
                   self.pareto_ground[:, 2],
                   marker='o', s=100, c='C1', lw=1.,
                   alpha=0.8,
                   zorder=10.,
                   edgecolors='gray',
                   )

        xmin = np.min(self.objective_values_ground[:, 0])
        xmax = np.max(self.objective_values_ground[:, 0])
        ymin = np.min(self.objective_values_ground[:, 1])
        ymax = np.max(self.objective_values_ground[:, 1])
        zmin = np.min(self.objective_values_ground[:, 2])
        zmax = np.max(self.objective_values_ground[:, 2])

        ax.axes.set_xlim3d(xmin, xmax)
        ax.axes.set_ylim3d(ymin, ymax)
        ax.axes.set_zlim3d(zmin, zmax)

        ax.set_xlabel(f"{self.objective_names[0]} ({self.objective_modes[0]})")
        ax.set_ylabel(f"{self.objective_names[1]} ({self.objective_modes[1]})")
        ax.set_zlabel(f"{self.objective_names[2]} ({self.objective_modes[2]})")

        if not os.path.exists(f"{self.run_folder}_plots"):
            os.mkdir(f"{self.run_folder}_plots")

        plt.savefig(f"{self.run_folder}_plots/{self.filename_results}_train_{self.step}.svg")

        plt.show()


class Solution:
    """https://leetcode.com/problems/longest-substring-without-repeating-characters/"""
    @staticmethod
    def v1_length_of_longest_substring(s: str) -> int:
        """
        Time complexity: O(n) 59ms beats 78.60%
        Space complexity: 0(n) 16.48mb beats 44.51%
        """
        res = 0
        char_set = set()
        left = 0

        for right in range(len(s)):
            while s[right] in char_set:
                char_set.remove(s[left])
                left += 1
            char_set.add(s[right])
            res = max(res, right - left + 1)
        return res

    @staticmethod
    def v2_length_of_longest_substring(s: str) -> int:
        """
        Time complexity: O(n) 41ms beats 99.73%
        Space complexity: 0(n) 16.36mb beats 77.38%
        """
        start = 0
        result = 0
        lookup = {}

        for i, c in enumerate(s):
            if c in lookup and start <= lookup[c]:
                start = lookup[c] + 1
            else:
                result = max(result, i-start+1)
            lookup[c] = i
        return result


import numpy as np
import os

np_dir=r'\\hydro-nas\Team\Projects\5635_SFEI Carbon and GHG\Accretion\20211223'

#Import template array

temp_np_nam="MTL"
temp_np=np.load(os.path.join(np_dir,temp_np_nam+".npy"))

#Import array to be fixed
tbf_np_nam="SLR_1_1"
tbf_np=np.load(os.path.join(np_dir,tbf_np_nam+".npy"))

tbf_np[np.isnan(temp_np)]=np.nan

np.save(os.path.join(np_dir,tbf_np_nam+'_fix.npy'),tbf_np)


import sqlite3 as sqlite
import const

def is_in_base(user_id):
    db = sqlite.connect("clientbase.db")
    cur = db.cursor()
    cur.execute("SELECT * FROM users WHERE user_id = (?)", (user_id,))
    if cur.fetchone():
        return True
    return False

def create_table():
    db = sqlite.connect("clientbase.db")
    cur = db.cursor()
    try:
        cur.execute("CREATE TABLE users (id, user_id)")
        db.commit()
        db.close()
    except Exception as e:
        print("Failed while creating " + str(e))

def drop_table():
    db = sqlite.connect("clientbase.db")
    cur = db.cursor()
    try:
        cur.execute("DROP TABLE IF EXISTS users;")
        db.commit()
        db.close()
    except Exception as e:
        print("Failed while dropping" + str(e))

def add_user(user_id):
    db = sqlite.connect("clientbase.db")
    cur = db.cursor()
    try:
        cur.execute("INSERT INTO users (id, user_id) VALUES (?,?)",
                    (const.counter+1,
                     user_id))
        db.commit()
        db.close()
        const.counter += 1
        return const.counter
    except:
        return -1


# Create a hash table (using a dictionary) that maps a number in an array
#to True, to show that it is present

# new_dictionary = {key:value for(key:value) in old_dict (if conditional)}

# Create an empty list to hold all missing numbers

# For each number in the range between low and high,
#check the value in the map:

# If the number exists as a key in the dictionary, then the number is present
# If the number does not exist as a key in the dictionary, then the number is missing
# Append it to our list that holds all missing numbers

def get_missing_numbers_in_range(array, num_low, num_high):
    num_dict = {num: True for num in array}
    missing_nums = []

    for num in range(num_low, num_high):
        if num in num_dict:
            num +=1
        else:
            missing_nums.append(num)
            num +=1
    return missing_nums

answer = get_missing_numbers_in_range([10, 12, 11, 15], 10, 15)
print(answer)

# Create a hash table that maps every pair's first item to its second item
# Create an empty list to hold all symmetric pairs
# Iterate over the pair list again to ensure we process pairs in order:
# Check the hash table if the symmetric pair exists:
# Take the current second item, and use it as a key in the hash table
# Look up the value of the current second item in the hash table, and
# check whether its value is equal to the current key (current first item)
# If it's equal, then there's a symmetric pair!
# Append it to our list of symmetric pairs
# Remove the current pair from the hash table so that it can't
# be matched by the symmetric pair when we reach it in the list.

def get_symmetric_pairs(list):
    '''
    input: list of pairs, with sublists that each have two items
    output: list of symetric pairs: a list with sublists of pairs;
    A pair is only listed once; its symmetric pair is not also listed.
    '''
    # Create a hash table that maps every pair's first item to its second item
    dict_of_pairs = {couple[0] : couple[1] for couple in list}
    # dict_of_pairs = {}
    # for couple in list:
    #     dict_of_pairs[couple[0]]= couple[1]

    # Create an empty list to hold all symmetric pair
    symmetric_pairs  = []
    #Iterate over the pair list again to ensure we process pairs in order:
    # Check the hash table if the symmetric pair exists:
    for couple in list:
        if couple[0] in dict_of_pairs:
            if couple[1] in dict_of_pairs:
                new_key = couple[1]
                if dict_of_pairs[new_key] == couple[0]:
                    symmetric_pairs.append(couple)
                    del dict_of_pairs[couple[0]]
    return symmetric_pairs

    # Take the current second item, and use it as a key in the hash table
    # Look up the value of the current second item in the hash table, and
    # check whether its value is equal to the current key (current first item)
    # If it's equal, then there's a symmetric pair!
    # Append it to our list of symmetric pairs

answer = get_symmetric_pairs([[11, 20], [30, 40], [5, 10], [40, 30], [10, 5]])
print(answer) # expect [[30, 40], [5, 10]]

def get_intersection(list_1, list_2):
    dict = {list_1[i]: False for i in range(len(list_1))}
    dict = {list_2[i]: True for i in range(len(list_2)) if list_2[i] in dict}
    intersection_list = []
    for num in dict:
        if dict[num] == True:
            intersection_list.append(num)
    return intersection_list

result = get_intersection([50, 43, 25, 72],[25, 36, 43, 50, 80]
)
print(set(result)) # 25,43,50 in set

# alternate solutions:
def get_intersection(red, blue):
    frequency_hash = {}

    for list in [red, blue]:
        for item in list:
            if item in frequency_hash:
                frequency_hash[item] += 1
            else:
                frequency_hash[item] = 1

    intersections = []
    for item, quantity in frequency_hash.items():
        if quantity > 1:
            intersections.append(item)

    return intersections

def is_permutation(str_1, str_2):
    str_1_hash = {}
    for char in str_1:
        if char in str_1_hash:
            str_1_hash[char] += 1
        else:
            str_1_hash[char] = 1
    # print(str_1_hash)
    str_2_hash = {}
    for char in str_2:
        if char in str_2_hash:
            str_2_hash[char] += 1
        else:
            str_2_hash[char] = 1
    # print(str_2_hash)
    if str_1_hash == str_2_hash:
        return True
    else:
        return False

# With helper function:
def populate_frequency_map(text):
    frequency_hash = {}
    for char in text:
        if char in frequency_hash:
            frequency_hash[char] += 1
        else:
            frequency_hash[char] = 1
    return frequency_hash

def is_permutation(red, blue):
    red_frequency_hash = populate_frequency_map(red)
    blue_frequency_hash = populate_frequency_map(blue)

    return red_frequency_hash == blue_frequency_hash

def is_palindrome_permutation(string):
    '''
    input: str
    output: True or False; True if letters could be re-arranged as a palindrome
    '''
    char_freq_hash = {}

    for letter in string:
        if letter in char_freq_hash:
            char_freq_hash[letter] += 1
        else:
            char_freq_hash[letter] = 1
    print(char_freq_hash)

    odd_frequencies = 0
    for value in char_freq_hash.values():
        if value % 2 != 0:
            odd_frequencies += 1
    # if len(string) % 2 == 0 and odd_frequencies > 0:
    #     return False
    if odd_frequencies > 1:
        return False
    else:
        return True

answer = is_palindrome_permutation("string")
print(answer)

# alternate answer-- I don't understand the 'if frequency % 2' part
def is_palindrome_permutation(text):
    frequency_hash = {}
    for char in text:
        if char in frequency_hash:
            frequency_hash[char] += 1
        else:
            frequency_hash[char] = 1

    odd_matches_count = 0
    for frequency in frequency_hash.values():
        if frequency % 2: # This means,
            odd_matches_count += 1

    return odd_matches_count <= 1
result = is_palindrome_permutation('text')
print(result)


import scrollphathd

import threading

from argparse import ArgumentParser

try:
    from queue import Queue, Empty
except ImportError:
    from Queue import Queue, Empty

from .action import Action
from .stoppablethread import StoppableThread

try:
    import http.client as http_status
except ImportError:
    import httplib as http_status

from flask import Blueprint, render_template, abort, request, jsonify, Flask

scrollphathd_blueprint = Blueprint('scrollhat', __name__)
api_queue = Queue()

class AutoScroll():
    _is_enabled = False
    _interval = 0.1

    def config(self, is_enabled="False", interval=0.1):
        self._interval = interval

        if is_enabled == "True":
            if self._is_enabled is False:
                self._is_enabled = True
                self.run()
        else:
            self._is_enabled = False

    def run(self):
        if self._is_enabled is True:
            # Start a timer
            threading.Timer(self._interval, self.run).start()
            # Scroll the buffer content
            scrollphathd.scroll()
            # Show the buffer
            scrollphathd.show()

@scrollphathd_blueprint.route('/autoscroll', methods=["POST"])
def autoscroll():
    response = {"result": "success"}
    status_code = http_status.OK

    data = request.get_json()
    if data is None:
        data = request.form
    try:
        api_queue.put(Action("autoscroll", (data["is_enabled"], float(data["interval"]))))
    except KeyError:
        response = {"result": "KeyError", "error": "keys is_enabled and interval not posted."}
        status_code = http_status.UNPROCESSABLE_ENTITY
    except ValueError:
        response = {"result": "ValueError", "error": "invalid data type(s)."}
        status_code = http_status.UNPROCESSABLE_ENTITY

    return jsonify(response), status_code

@scrollphathd_blueprint.route('/scroll', methods=["POST"])
def scroll():
    response = {"result": "success"}
    status_code = http_status.OK

    data = request.get_json()
    if data is None:
        data = request.form
    try:
        api_queue.put(Action("scroll", (int(data["x"]), int(data["y"]))))
    except KeyError:
        response = {"result": "KeyError", "error": "keys x and y not posted."}
        status_code = http_status.UNPROCESSABLE_ENTITY
    except ValueError:
        response = {"result": "ValueError", "error": "invalid integer."}
        status_code = http_status.UNPROCESSABLE_ENTITY

    return jsonify(response), status_code

@scrollphathd_blueprint.route('/show', methods=["POST"])
def show():
    response = {"result": "success"}
    status_code = http_status.OK

    data = request.get_json()
    if data is None:
        data = request.form
    try:
        api_queue.put(Action("write", data["text"]))
    except KeyError:
        response = {"result": "KeyError", "error": "key 'text' not set"}
        status_code = http_status.UNPROCESSABLE_ENTITY

    return jsonify(response), status_code

@scrollphathd_blueprint.route('/clear', methods=["POST"])
def clear():
    response = {"result": "success"}
    status_code = http_status.OK

    api_queue.put(Action("clear", {}))
    return jsonify(response), status_code

@scrollphathd_blueprint.route('/flip', methods=["POST"])
def flip():
    response = {"result": "success"}
    status_code = http_status.OK

    data = request.get_json()
    if data is None:
        data = request.form
    try:
        api_queue.put(Action("flip", (bool(data["x"]), bool(data["y"]))))
    except TypeError:
        response = {"result": "TypeError", "error": "Could not cast data correctly. Both `x` and `y` must be set to true or false."}
        status_code = http_status.UNPROCESSABLE_ENTITY
    except KeyError:
        response = {"result": "KeyError", "error": "Could not cast data correctly. Both `x` and `y` must be in the posted json data."}
        status_code = http_status.UNPROCESSABLE_ENTITY

    return jsonify(response), status_code

def cleanup():
    # Reset the autoscroll
    autoscroll.config()
    # Clear the buffer before writing new text
    scrollphathd.clear()

def run():
    while True:
        action = api_queue.get(block=True)

        if action.action_type == "write":
            cleanup()
            scrollphathd.write_string(action.data)

        if action.action_type == "clear":
            cleanup()

        if action.action_type == "scroll":
            scrollphathd.scroll(action.data[0], action.data[1])

        if action.action_type == "flip":
            scrollphathd.flip(x=action.data[0], y=action.data[1])

        if action.action_type == "autoscroll":
            autoscroll.config(action.data[0], action.data[1])

        scrollphathd.show()

def start_background_thread():
    api_thread = StoppableThread(target=run)
    api_thread.start()

scrollphathd_blueprint.before_app_first_request(start_background_thread)

# Autoscroll handling
autoscroll = AutoScroll()

def main():
    # Parser handling
    parser = ArgumentParser()
    parser.add_argument("-p", "--port", type=int, help="HTTP port.", default=8080)
    parser.add_argument("-H", "--host", type=str, help="HTTP host.", default="0.0.0.0")
    args = parser.parse_args()

    # TODO Check
    scrollphathd.set_clear_on_exit(False)
    scrollphathd.write_string(str(args.port), x=1, y=1, brightness=0.1)
    scrollphathd.show()

    # Flash usage
    app = Flask(__name__)
    app.register_blueprint(scrollphathd_blueprint, url_prefix="/scrollphathd")
    app.run(port=args.port, host=args.host)

if __name__ == '__main__':
    main()


# imports
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import CubicSpline, interp1d
import os
import csv

plt.rcParams['figure.figsize'] = (12, 8)

delim = ' '
raw_points = []
points = []
x = []
y = []
cwd = os.getcwd()
Data_path = cwd + "/Letters_Data/Arabic/Data_converted/Ayn.csv"
with open(Data_path, 'r') as csvfile:
    coords = csv.reader(csvfile, delimiter=delim)
    for row in coords:
        if len(row) > 1:
            raw_points.append((float(row[0]), float(row[1])))
for i in range(0, len(raw_points), 5):
    x.append(raw_points[i][0])
    y.append(raw_points[i][1])

for i in range(len(x)):
    print(x[i], ", ", y[i])

# apply cubic spline interpolation
cs = CubicSpline(x, y)
# Apply Linear interpolation
linear_int = interp1d(x, y)

xs = np.arange(-10, 10)
ys = linear_int(xs)

# plot linear interpolation
plt.plot(x, y, 'o', label='data')
plt.plot(xs, ys, label="S", color='green')
plt.legend(loc='upper right', ncol=2)
plt.title('Linear Interpolation')
plt.show()

# plot cubic spline interpolation
plt.plot(x, y, 'o', label='data')
plt.plot(xs, 1 / (1 + (xs ** 2)), label='true')
plt.plot(xs, cs(xs), label="S")
plt.plot(xs, cs(xs, 1), label="S'")
plt.plot(xs, cs(xs, 2), label="S''")
plt.plot(xs, cs(xs, 3), label="S'''")
plt.ylim(-1.5, 1.5)
plt.legend(loc='upper right', ncol=2)
plt.title('Cubic Spline Interpolation')
plt.show()


# encoding=utf-8
import os
import csv
import numpy as np
import random
import re
from itertools import islice

# 生成开源SVM所需的格式
def read_data(file_path):
    data_matrix = []
    with open(file_path, 'r', encoding='gbk', newline="") as file:
        csv_reader = csv.reader(file)
        # 跳过第一行Head和第一列
        for line in islice(csv_reader, 3, None):
            row = []
            for item in islice(line, 1, None):
                value = re.findall('[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?', item)
                value = float(value[0])
                row.append(value)
            data_matrix.append(row)
    return np.array(data_matrix)

def event_split(data):
    feature = data[:, 0:-5]
    thirty_day_readmit = data[:, -5]
    thirty_day_readmit = thirty_day_readmit[:, np.newaxis]
    one_year_readmit = data[:, -4]
    one_year_readmit = one_year_readmit[:, np.newaxis]
    cardio_death = data[:, -3]
    cardio_death = cardio_death[:, np.newaxis]
    all_cause_death = data[:, -2]
    all_cause_death = all_cause_death[:, np.newaxis]

    thirty_day_readmit = np.concatenate([feature, thirty_day_readmit], axis=1)
    one_year_readmit = np.concatenate([feature, one_year_readmit], axis=1)
    cardio_death = np.concatenate([feature, cardio_death], axis=1)
    all_cause_death = np.concatenate([feature, all_cause_death], axis=1)
    return thirty_day_readmit, one_year_readmit, cardio_death, all_cause_death

def five_fold_split(data, skip_zero=False):
    # 数据规范，data是一个 M*N的矩阵，其中，M*(N-1)的部分是特征，最后一列是标签
    # 标签要求正标签为1，负标签为-1，无标签为0
    # 如果skip被设为True，则跳过无标签数据
    pos_data = list()
    neg_data = list()
    no_label_data = list()

    for item in data:
        if item[-1] == 1:
            pos_data.append(item)
        elif item[-1] == -1:
            neg_data.append(item)
        elif item[-1] == 0 and not skip_zero:
            no_label_data.append(item)
        elif item[-1] == 0 and skip_zero:
            pass
        else:
            raise ValueError("")

    # 随机化
    random.shuffle(pos_data)
    random.shuffle(neg_data)
    random.shuffle(no_label_data)

    five_fold = list()
    for i in range(5):
        pos_num = len(pos_data) // 5
        neg_num = len(neg_data) // 5
        no_num = len(no_label_data) // 5
        if i != 4:
            fold_pos = np.array(pos_data[i*pos_num:(i+1)*pos_num])
            fold_neg = np.array(neg_data[i*neg_num:(i+1)*neg_num])
            fold_no = np.array(no_label_data[i*no_num:(i+1)*no_num])
            if no_num != 0:
                five_fold.append(np.concatenate([fold_pos, fold_neg, fold_no], axis=0))
            else:
                five_fold.append(np.concatenate([fold_pos, fold_neg], axis=0))
        else:
            # 由于数据珍贵，不能丢弃任何一个数据
            fold_pos = np.array(pos_data[4*pos_num:])
            fold_neg = np.array(neg_data[4*neg_num:])
            fold_no = np.array(no_label_data[4*no_num:])
            if no_num != 0:
                five_fold.append(np.concatenate([fold_pos, fold_neg, fold_no], axis=0))
            else:
                five_fold.append(np.concatenate([fold_pos, fold_neg], axis=0))
    return five_fold

def data_generate(five_fold_data):
    reconstructed = list()
    for i in range(5):
        train = list()
        for j in range(5):
            if i == j:
                continue
            train.append(five_fold_data[j])
        train = np.concatenate([train[0], train[1], train[2], train[3]], axis=0)
        train_data = train[:, :-1]
        train_label = train[:, -1]

        test = []
        for item in five_fold_data[i]:
            if item[-1] != 0:
                test.append(item)
        test = np.array(test)
        test_label = test[:, -1]
        test_data = test[:, : -1]

        reconstructed.append([train_data, train_label, test_data, test_label])
    return reconstructed

def write_data(data, label, data_path, label_path):
    data_to_write = []
    for case in data:
        line_string = str()
        for index, item in enumerate(case):
            line_string += str(index+1)+':'+str(item)+" "
        line_string = line_string[:-1]+'\n'
        data_to_write.append(line_string)

    label_to_write = []
    for case in label:
        label_to_write.append(str(int(case))+"\n")

    with open(data_path, 'w', encoding='utf-8') as file:
        for item in data_to_write:
            file.write(item)
    with open(label_path, 'w', encoding='utf-8') as file:
        for item in label_to_write:
            file.write(item)

def semi_supervised_data_generate():
    source_data_path = os.path.abspath('..\\resource\\Data\\general_preprocessed.csv')
    data = read_data(source_data_path)
    thirty_day_readmit, one_year_readmit, cardio_death, all_cause_death = event_split(data)
    thirty_day_readmit_5_fold = five_fold_split(thirty_day_readmit)
    one_year_readmit_5_fold = five_fold_split(one_year_readmit)
    cardio_death_5_fold = five_fold_split(cardio_death)
    all_cause_death_5_fold = five_fold_split(all_cause_death)

    thirty_day_readmit_data = data_generate(thirty_day_readmit_5_fold)
    one_year_readmit_data = data_generate(one_year_readmit_5_fold)
    cardio_death_data = data_generate(cardio_death_5_fold)
    all_cause_death_data = data_generate(all_cause_death_5_fold)

    thirty_day_readmit_path = os.path.abspath('..\\resource\\Data\\svm_data\\30_day_readmit')
    one_year_readmit_path = os.path.abspath('..\\resource\\Data\\svm_data\\1_year_readmit')
    cardio_death_path = os.path.abspath('..\\resource\\Data\\svm_data\\cardio_death')
    all_cause_death_path = os.path.abspath('..\\resource\\Data\\svm_data\\all_cause_death')
    data_dict = {'30_day': [thirty_day_readmit_data, thirty_day_readmit_path],
                 '1_year': [one_year_readmit_data, one_year_readmit_path],
                 'all_cause': [all_cause_death_data, all_cause_death_path],
                 'cardio': [cardio_death_data,cardio_death_path]}

    for key in data_dict:
        data, path = data_dict[key]
        for i in range(5):
            train_data, train_label, test_data, test_label = data[i]
            train_data_path = os.path.join(path, str(i)+'trd')
            train_label_path = os.path.join(path, str(i) + 'trl')
            test_data_path = os.path.join(path, str(i) + 'ted')
            test_label_path = os.path.join(path, str(i) + 'tel')
            write_data(train_data, train_label, train_data_path, train_label_path)
            write_data(test_data, test_label, test_data_path, test_label_path)

    print('finish')

def main():
    semi_supervised_data_generate()

if __name__ == "__main__":
    main()


import csv
import json
import pandas as pd

csv_data = "data.csv"

csvfile = open(csv_data, "r")

df = pd.read_csv(csv_data)

df = df.groupby('TIME')["Value"].agg("mean")

jsonfile = json.loads(df.to_json(orient="index"))

keys = list(jsonfile.keys())
values = list(jsonfile.values())

length_list = len(keys)

data = []
for i in range(length_list):
    set = []
    set.append(keys[i])
    set.append(values[i])
    data.append(set)

headers = ["Time", "Value"]

df = pd.DataFrame(data, columns=headers)

jsonfile = json.loads(df.to_json(orient="records"))

print(jsonfile)
with open('Week4data.json', 'w') as outfile:
    json.dump(jsonfile, outfile)


import numpy

def mean_median(election_results):
    """
    Computes the Mean-Median score for the given ElectionResults.
    A positive value indicates an advantage for the first party listed
    in the Election's parties_to_columns dictionary.
    """
    first_party = election_results.election.parties[0]
    data = election_results.percents(first_party)

    return numpy.median(data) - numpy.mean(data)

def mean_thirdian(election_results):
    """
    Computes the Mean-Median score for the given ElectionResults.
    A positive value indicates an advantage for the first party listed
    in the Election's parties_to_columns dictionary.

    The motivation for this score is that the minority party in many
    states struggles to win even a third of the seats.
    """
    first_party = election_results.election.parties[0]
    data = election_results.percents(first_party)

    thirdian_index = round(len(data) / 3)
    thirdian = sorted(data)[thirdian_index]

    return thirdian - numpy.mean(data)

def efficiency_gap(results):
    """
    Computes the efficiency gap for the given ElectionResults.
    A positive value indicates an advantage for the first party listed
    in the Election's parties_to_columns dictionary.
    """
    party1, party2 = [results.counts(party) for party in results.election.parties]
    wasted_votes_by_part = map(wasted_votes, party1, party2)
    total_votes = results.total_votes()
    numerator = sum(waste2 - waste1 for waste1, waste2 in wasted_votes_by_part)
    return numerator / total_votes

def wasted_votes(party1_votes, party2_votes):
    """
    Computes the wasted votes for each party in the given race.
    :party1_votes: the number of votes party1 received in the race
    :party2_votes: the number of votes party2 received in the race
    """
    total_votes = party1_votes + party2_votes
    if party1_votes > party2_votes:
        party1_waste = party1_votes - total_votes / 2
        party2_waste = party2_votes
    else:
        party2_waste = party2_votes - total_votes / 2
        party1_waste = party1_votes
    return party1_waste, party2_waste

def partisan_bias(election_results):
    """
    Computes the partisan bias for the given ElectionResults.
    The partisan bias is defined as the number of districts with above-mean
    vote share by the first party divided by the total number of districts,
    minus 1/2.
    """
    first_party = election_results.election.parties[0]
    party_shares = numpy.array(election_results.percents(first_party))
    mean_share = numpy.mean(party_shares)
    above_mean_districts = len(party_shares[party_shares > mean_share])
    return (above_mean_districts / len(party_shares)) - 0.5

def partisan_gini(election_results):
    """
    Computes the partisan Gini score for the given ElectionResults.
    The partisan Gini score is defined as the area between the seats-votes
    curve and its reflection about (.5, .5).
    """
    # For two parties, the Gini score is symmetric--it does not vary by party.
    party = election_results.election.parties[0]

    # To find seats as a function of votes, we assume uniform partisan swing.
    # That is, if the statewide popular vote share for a party swings by some
    # delta, the vote share for that party swings by that delta in each
    # district.
    # We calculate the necessary delta to shift the district with the highest
    # vote share for the party to a vote share of 0.5. This delta, subtracted
    # from the original popular vote share, gives the minimum popular vote
    # share that yields 1 seat to the party.
    # We repeat this process for the district with the second-highest vote
    # share, which gives the minimum popular vote share yielding 2 seats,
    # and so on.
    overall_result = election_results.percent(party)
    race_results = sorted(election_results.percents(party), reverse=True)
    seats_votes = [overall_result - r + 0.5 for r in race_results]

    # Apply reflection of seats-votes curve about (.5, .5)
    reflected_sv = reversed([1 - s for s in seats_votes])
    # Calculate the unscaled, unsigned area between the seats-votes curve
    # and its reflection. For each possible number of seats attained, we find
    # the area of a rectangle of unit height, with a width determined by the
    # horizontal distance between the curves at that number of seats.
    unscaled_area = sum(abs(s - r) for s, r in zip(seats_votes, reflected_sv))
    # We divide by area by the number of seats to obtain a partisan Gini score
    # between 0 and 1.
    return unscaled_area / len(race_results)


#
# cocos2d
# http://python.cocos2d.org
#

from __future__ import division, print_function, unicode_literals

# This code is so you can run the samples without installing the package
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
#

import cocos

class Ball(cocos.sprite.Sprite):

    def update(self):
        self.position = (self.position[0] + 1, self.position[1] + 1)

class GameWorld(cocos.layer.Layer):

    is_event_handler = True     #: enable pyglet's events

    def __init__(self):
        super(GameWorld, self).__init__()

        self.ball = Ball('ball.png')

        self.add(self.ball)
        self.schedule(self.update)

    def update(self, dt):
        self.ball.update()

if __name__ == "__main__":
    # director init takes the same arguments as pyglet.window
    cocos.director.director.init()

    # We create a new layer, an instance of GameWorld
    hello_layer = GameWorld()

    # A scene that contains the layer hello_layer
    main_scene = cocos.scene.Scene(hello_layer)

    # And now, start the application, starting with main_scene
    cocos.director.director.run(main_scene)

    # or you could have written, without so many comments:
    #      director.run( cocos.scene.Scene( GameWorld() ) )


class VariableElimination():
    @staticmethod
    def inference(factorList, queryVariables,
    orderedListOfHiddenVariables, evidenceList):
        #restrict factor related to evidence
        for ev in evidenceList:
            for i in range(len(factorList)):
                if ev in factorList[i].varList:
                    # restrict
                    factorList[i] = factorList[i].restrict(ev,evidenceList[ev])
        #multiply factor related to the variable
        for var in orderedListOfHiddenVariables:
            # factor related to the variable
            f_list = [f for f in factorList if var in f.varList]
            # error
            if not f_list:
                return None
            # multiply factor and then sumout
            g = f_list[0]
            for f in f_list[1:]:
                # multiply factor on var
                g = g.multiply(f)
            g = g.sumout(var)
            # remove factor f1, f2, f3...fn
            factorList = [factor for factor in factorList if factor not in f_list]
            # add factor g
            factorList.append(g)
        # print ("RESULT:")
        res = factorList[0]
        for factor in factorList[1:]:
            res = res.multiply(factor)
        total = sum(res.cpt.values())
        res.cpt = {k: v/total for k, v in res.cpt.items()}
        # res.printInf()
        return res.cpt
    @staticmethod
    def printFactors(factorList):
        for factor in factorList:
            factor.printInf()

class Node():
    def __init__(self, name, var_list):
        self.name = name
        self.varList = var_list
        self.cpt = {}
    def setCpt(self, cpt):
        self.cpt = cpt
    def printInf(self):
        print ("Name = " + self.name)
        print (" vars " + str(self.varList))
        for key in self.cpt:
            print ("   key: " + str(key) + " val : " , str(self.cpt[key]))
        print ("")
    def multiply(self, factor):
        """function that multiplies with another factor on variables"""
        def equal(key1, key2, indexs1, indexs2):
            for i in range(len(indexs1)):
                if key1[indexs1[i]] != key2[indexs2[i]]:
                    return False
            return True
        def get_new_key(key1, indexs1):
            new_key = [key1[i] for i in range(len(key1)) if i not in indexs1]
            new_key = tuple(new_key)
            return new_key

        variables = [var for var in self.varList if var in factor.varList]
        # variable location
        indexs1 = [self.varList.index(var) for var in variables]
        indexs2 = [factor.varList.index(var) for var in variables]
        # newList and new_cpt
        newList = [var for var in self.varList if var not in variables] + factor.varList
        new_cpt = {}
        for key1,val1 in self.cpt.items():
            for key2,val2 in factor.cpt.items():
                # the same value on variables, multiply
                if equal(key1, key2, indexs1, indexs2):
                    new_key = get_new_key(key1,indexs1)+ key2
                    new_cpt[new_key] = val1 * val2
        new_node = Node("f" + str(newList), newList)
        new_node.setCpt(new_cpt)
        return new_node
    def sumout(self, variable):
        """function that sums out a variable given a factor"""
        if len(self.varList) == 1:
            return None
        # variable location
        var_index = self.varList.index(variable)
        new_var_list = self.varList[:var_index] + self.varList[var_index+1:]
        new_cpt = {}
        new_keys = {key[:var_index] + key[var_index+1:] for key in self.cpt}
        values = {key[var_index] for key in self.cpt}
        for new_key in new_keys:
            probas = [self.cpt[new_key[:var_index]+(val,)+new_key[var_index:]] for val in values]
            # sumout
            new_cpt[new_key] = sum(probas)
        new_node = Node("f" + str(new_var_list), new_var_list)
        new_node.setCpt(new_cpt)
        return new_node
    def restrict(self, variable, value):
        """function that restricts a variable to some value
        in a given factor"""
        # variable location
        var_index = self.varList.index(variable)
        new_var_list = self.varList[:var_index] + self.varList[var_index+1:]
        new_cpt = {}
        for key,val in self.cpt.items():
            if key[var_index] == value:
                new_key = key[:var_index] + key[var_index+1:]
                # restrict
                new_cpt[new_key] = val
        new_node = Node("f" + str(new_var_list), new_var_list)
        new_node.setCpt(new_cpt)
        return new_node

# create nodes for Bayes Net
A = Node('A',['A'])
B = Node('B',['A','B'])
C = Node('C',['A','C'])
D = Node('D',['B','C','D'])
E = Node('E',['C','E'])
# Generate cpt for each node
A.setCpt({('1',):0.2,('0',):0.8})
B.setCpt({('1','1'):0.7,('1','0'):0.3,('0','1'):0.2,('0','0'):0.8})
C.setCpt({('1','1'):0.2,('1','0'):0.8,('0','1'):0.05,('0','0'):0.95})
D.setCpt({('1','1','1'):0.8,('1','1','0'):0.2,('1','0','1'):0.7,('1','0','0'):0.3,('0','1','1'):0.7,('0','1','0'):0.3,('0','0','1'):0.05,('0','0','0'):0.95})
E.setCpt({('1','1'):0.7,('1','0'):0.3,('0','1'):0.6,('0','0'):0.4})

Distribution = VariableElimination.inference([A,B,C,D,E],['A','B','C'],[],{'D':'0','E':'1'})
print(Distribution)

Distribution2 = VariableElimination.inference([A,B,C,D,E],['A',],['B','C'],{'D':'0','E':'1'})
print(Distribution2)


import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#get data
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)

#define layer
def add_layer(inputs,in_size,out_size,activation_function=None):
	weights = tf.Variable(tf.random_normal([in_size,out_size]))
	biases = tf.Variable(tf.zeros([1,out_size]) + 0.1)
	G = tf.matmul(inputs,weights) + biases
	if activation_function is None:
		outputs = G
	else:
		outputs = activation_function(G)
	return outputs

#define compute_accuracy
def compute_accuracy(images,labels):
	global prediction
	y_pre = sess.run(prediction,feed_dict={x_input:images})
	correct_prediction = tf.equal(tf.argmax(y_pre,1),tf.argmax(labels,1))
	accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
	result = sess.run(accuracy, feed_dict={x_input:images,y_input:labels})
	return result

#define placeholder for inputs to network [None,748]: None is unknown amount of sample, 784 pixels for one pic
x_input = tf.placeholder(tf.float32,[None,784])
y_input = tf.placeholder(tf.float32,[None,10])

#add output layer
prediction = add_layer(x_input, 784,10,activation_function=tf.nn.softmax)

#loss
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_input * tf.log(prediction),
								reduction_indices=[1]))

train = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.Session()
sess.run(tf.initialize_all_variables())

for i in range(1000):
	#train part of the data sample each time -> reduce training time
	batch_x,batch_y = mnist.train.next_batch(100)
	sess.run(train,feed_dict={x_input:batch_x,y_input:batch_y})
	if i % 50 == 0:
		print(compute_accuracy(mnist.test.images, mnist.test.labels))


import PIL.Image
import torchvision.transforms
import torch.nn

import pywebio
from io import BytesIO

from data.myModel_import2 import *

@pywebio.config(title="卷积神经网络Demo", description="基于CIFAR10数据集的图像分类")
def page1():
    train_set_classes = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
    graph_img = PIL.Image.open("./data/net_graph.png")

    def show_info():
        pywebio.output.put_markdown("# 基于CIFAR10数据集的图像分类")
        pywebio.output.put_html("
")
        pywebio.output.put_table([
            [pywebio.output.span('数据集', row=1), pywebio.output.span('支持类别', col=2)],
            ['CIFAR10', train_set_classes]
        ])
        pywebio.output.put_html("
")

    show_net = [pywebio.output.put_text('net'),
                pywebio.output.put_image(graph_img)]

    def popup_window(title, content):
        pywebio.output.popup(title=title, content=content)

    show_info()
    pywebio.output.put_buttons(['查看网络结构'], [lambda: popup_window("网络结构", show_net)])
    # pywebio.output.put_buttons(['点击查看网络结构'], [popup_window])
    pywebio.input.actions("", [{'label': "上传图片", 'value': "", 'color': 'success', }])
    inpic = pywebio.input.file_upload(label="上传图片 please upload a image")
    pywebio.output.popup("加载中", [
        pywebio.output.put_loading(),
    ])

    # img_path = "./pic2/102.png"
    img = PIL.Image.open(BytesIO(inpic['content']))
    # pywebio.output.put_image(inpic['content'])
    img = img.convert("RGB")
    # print(img.size)
    transform01 = torchvision.transforms.Compose([
        torchvision.transforms.Resize((32, 32)),
        torchvision.transforms.ToTensor()
    ])
    img = transform01(img)
    img = torch.reshape(img, (1, 3, 32, 32))
    # print(img.shape)

    model = torch.load("data/myModel_46.pth", map_location=torch.device('cpu'))
    # print(model)

    # model.eval()
    with torch.no_grad():
        output = model(img)
    # print(output)
    # print(output.argmax(1))
    # print(train_set.classes[output.argmax(1).item()])
    # pywebio.output.put_text(train_set.classes[output.argmax(1).item()])
    pywebio.output.popup(title='识别结果',
                         content=[
                             pywebio.output.put_markdown("分类结果：\n # " + train_set_classes[output.argmax(1).item()]),
                             pywebio.output.put_image(None if not inpic else inpic['content'])])

    # img = torch.reshape(img, (3, 32, 32))
    # transform2 = torchvision.transforms.Compose([
    #     torchvision.transforms.Resize((160, 160)),
    #     torchvision.transforms.ToPILImage()
    # ])
    # img = transform2(img)
    #
    # img_bytes = BytesIO()
    # img.save(img_bytes, format="JPEG")
    # img = img_bytes.getvalue()
    # pywebio.output.put_image(img, height="512", width="512")
    # pywebio.output.put_image(inpic['content'], height="512", width="512")
    # pywebio.output.put_image(inpic['content'])
    del model, inpic, img

if __name__ == "__main__":
    # page1()
    pywebio.start_server(
        applications=[page1, ],
        debug=True,
        cdn=False,
        auto_open_webbrowser=False,
        remote_access=False,
        port=6006
    )


import dlib
import uuid
import numpy as np

class TrackState:
    TENTATIVE = 1
    CONFIRMED = 2
    OCCLUDED = 3
    DELETED = 4

class Track(object):
    def __init__(self,
                 rgb_image,
                 detection,
                 n_init,
                 max_disappeared,
                 max_age,
                 use_correlation_tracker=True,
                 feature=None):

        self.uuid = str(uuid.uuid4())

        self.bbox = dlib.rectangle(int(detection.bbox.left()),
                                   int(detection.bbox.top()),
                                   int(detection.bbox.right()),
                                   int(detection.bbox.bottom()))

        self.class_label = detection.class_label

        self.k_past = dlib.rectangles()

        if use_correlation_tracker is True:
            self.tracker = dlib.correlation_tracker()
            self.tracker.start_track(rgb_image, self.bbox)
        else:
            self.tracker = None

        self.state = TrackState.TENTATIVE

        self.n_init = n_init
        self.max_disappeared = max_disappeared
        self.max_age = max_age

        self.translation = None
        self.rotation = None

        if feature is not None:
            self.feature = np.asarray(feature, dtype=np.float32)
        else:
            self.feature = None

        self.missed = 0
        self.age = 1
        self.hits = 1
        self.since_update = 1

    def update(self, rgb_image, detection):
        if self.tracker is not None:
            self.tracker.update(rgb_image, detection.bbox)
            self.bbox = self.tracker.get_position()
        else:
            self.bbox = detection.bbox
        self.class_label = detection.class_label
        self.hits += 1
        self.age = 0
        self.since_update = 0
        if self.state == TrackState.TENTATIVE and self.hits >= self.n_init:
            self.state = TrackState.CONFIRMED
        if self.state == TrackState.OCCLUDED:
            self.state = TrackState.CONFIRMED

    def predict(self, rgb_image):
        if self.age > self.max_age:
            self.mark_missed()
        else:
            if self.tracker is not None:
                self.tracker.update(rgb_image)
                self.bbox = self.tracker.get_position()
            else:
                pass
            self.age += 1
            self.since_update = 0

    def mark_missed(self):
        self.since_update += 1
        if self.state == TrackState.TENTATIVE:
            if self.since_update > self.max_disappeared:
                self.state = TrackState.DELETED
        if self.state == TrackState.CONFIRMED:
            if self.since_update > self.max_disappeared:
                self.state = TrackState.OCCLUDED
        elif self.state == TrackState.OCCLUDED:
            if self.since_update > self.max_age:
                self.state = TrackState.DELETED

    def is_perceived(self):
        if not self.is_deleted():
            return self.state != TrackState.OCCLUDED
        else:
            return False

    def is_confirmed(self):
        return self.state == TrackState.CONFIRMED or self.state == TrackState.OCCLUDED

    def is_deleted(self):
        return self.state == TrackState.DELETED

    def __str__(self):
        return "rect : {} for class : {}".format(self.bbox, self.class_label)


from keras import Input, Model
from keras.layers import Conv2D, LeakyReLU, BatchNormalization, Dense

class Discriminator:
    def __init__(self, input_image_h, input_image_w, image_channels, no_filters):
        self.input_image_h = input_image_h
        self.input_image_w = input_image_w
        self.image_channels = image_channels
        self.input_image_shape = (self.input_image_h, self.input_image_w, self.image_channels)

        self.no_filters = no_filters

        self.model = self.create_discriminator_net()
        self.model.trainable = False

    def get_discriminator_model(self):
        return self.model

    def discriminator_block(self, input, no_filters, strides=1, add_batch_norm=True):
        conv2d = Conv2D(no_filters, kernel_size=3, strides=strides, padding='same')(input)
                                # name="discriminator_block_conv2d"
        leaky_relu = LeakyReLU(alpha=0.2)(conv2d)
                                # name="discriminator_block_leaky_relu"

        if add_batch_norm:
            batch_norm = BatchNormalization(momentum=0.8)(leaky_relu)
                                # name="discriminator_block_batch_norm"

            return batch_norm

        return leaky_relu

    def create_discriminator_net(self):
        input_img = Input(shape=self.input_image_shape, name="create_discr_input")

        discr_1 = self.discriminator_block(input_img, self.no_filters, add_batch_norm=False)
        discr_2 = self.discriminator_block(discr_1, self.no_filters, strides=2)
        discr_3 = self.discriminator_block(discr_2, self.no_filters * 2)
        discr_4 = self.discriminator_block(discr_3, self.no_filters * 2, strides=2)
        discr_5 = self.discriminator_block(discr_4, self.no_filters * 4)
        discr_6 = self.discriminator_block(discr_5, self.no_filters * 4, strides=2)
        discr_7 = self.discriminator_block(discr_6, self.no_filters * 8)
        discr_8 = self.discriminator_block(discr_7, self.no_filters * 8, strides=2)

        dense_1 = Dense(self.no_filters * 16)(discr_8)
        leaky_relu = LeakyReLU(alpha=0.2)(dense_1)
        dense_2 = Dense(1, activation='sigmoid')(leaky_relu)

        return Model(input_img, dense_2)


import networkx as nx
import argparse
import dgl
from dgl.data import register_data_args, load_data

import graph_io

def main(args):
    data = load_data(args)
    g = data.graph
    if isinstance(g, dgl.DGLGraph):
        csr = g.adjacency_matrix_scipy(transpose=True)
    else:
        csr = nx.to_scipy_sparse_matrix(g, weight=None, format='csr')

    graph_io.save_graph(args.out, csr)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-o', '--out', type=str, help='Output file name')
    register_data_args(parser)
    args = parser.parse_args()
    print(args)
    main(args)


from django.test import TestCase

from api.apps.problems.models import Category
from api.apps.problems.tests.api.api_helper import ApiHelper
from api.apps.problems.urls import ProblemsAppUrls

class CategoriesTestCase(TestCase):
    def setUp(self) -> None:
        self.api_helper = ApiHelper()

    def test_no_categories_saved_empty_list_should_be_returned(self):
        response = self.client.get(ProblemsAppUrls.categories_list_url())

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.data), 0)

    def test_categories_exist_all_categories_should_be_returned(self):
        algebra = self.api_helper.create_category("Algebra")
        geometry = self.api_helper.create_category("Geometry")

        response = self.client.get(ProblemsAppUrls.categories_list_url())
        algebra_from_response = self.__find_category_in_response(response, algebra.name)
        geometry_from_response = self.__find_category_in_response(response, geometry.name)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.data), 2)
        self.assertIsNotNone(algebra_from_response)
        self.assertIsNotNone(geometry_from_response)

    def test_find_by_not_existing_category_should_return_404(self):
        response = self.client.get(ProblemsAppUrls.category_details_url(0))

        self.assertEqual(response.status_code, 404)

    def test_find_by_existing_category_should_return_single_category(self):
        algebra = self.api_helper.create_category("Algebra")

        response = self.client.get(ProblemsAppUrls.category_details_url(algebra.id))
        algebra_from_response = Category(**response.json())

        self.assertEqual(response.status_code, 200)
        self.assertEqual(algebra_from_response.name, algebra.name)

    def __find_category_in_response(self, response, name):
        return Category(**[category for category in response.json() if category["name"] == name][0])


#!/usr/bin/python3
# -*- coding: utf-8 -*-
#拉格朗日插值法

def Lagrange(lPoints):
	iLen = len(lPoints)
	def innerLagrange(x):
		value = 0.0
		for idx in range(iLen):
			xi, yi = lPoints[idx]
			top, bottom = 1.0, 1.0
			for i in range(iLen):
				if idx == i:
					continue
				yi = yi * (x - lPoints[i][0])
				yi = yi / (xi - lPoints[i][0])
			value += yi
		return value
	return innerLagrange


from debile.utils.xmlrpc import get_proxy
from debile.utils.xmlrpc import DebileSafeTransport

import xmlrpclib
import unittest

class UtilsXMLRPCTestCase(unittest.TestCase):
    def test_get_proxy_without_xml(self):
        self.assertRaises(Exception, get_proxy, dict(), 'simple')

    def test_get_proxy_simple_auth(self):
        data = dict(xmlrpc = dict(host='localhost', port='22017'))

        proxy = get_proxy(data, 'simple')

        self.assertEquals(proxy.__dict__['_ServerProxy__host'],
                'localhost:22017')
        self.assertTrue(proxy.__dict__['_ServerProxy__allow_none'])

    def test_get_proxy_ssl_auth(self):
        data = dict(xmlrpc = dict(host='localhost', port='22017',
            keyfile='~/keyfile.key', certfile='~/certfile.crt'))

        proxy = get_proxy(data, 'ssl')

        self.assertEquals(proxy.__dict__['_ServerProxy__host'],
                'localhost:22017')
        self.assertTrue(proxy.__dict__['_ServerProxy__allow_none'])
        self.assertIsInstance(proxy.__dict__['_ServerProxy__transport'],
                DebileSafeTransport)


from typing import Optional, Tuple

import requests
from youtube_dl import YoutubeDL

from ..classes import Song

def search_youtube_video(
    search: str,
) -> Tuple[str, Optional[str], str, str, Optional[str]]:
    """
    Gets the first youtube video from a search, returns a tuple of (title, artist, url, youtube_url, duration)
    If the top url found is a video it will get the video, if it is a playlist it will turn the playlist into a single track
    """
    if not isinstance(search, str):
        raise TypeError(f"Searchs must be a str, not a {type(search)}")
    with YoutubeDL(
        {
            "format": "bestaudio",
            "noplaylist": True,
            "logtostderr": False,
            "quiet": True,
            "no_warnings": True,
            "source_address": "0.0.0.0",
        }
    ) as ydl:
        try:
            requests.get(search)
        except:
            info = ydl.extract_info(f"ytsearch:{search}", download=False)["entries"][0]
        else:
            info = ydl.extract_info(search, download=False)
    return (
        info["title"],
        info["uploader"],
        info["formats"][0]["url"],
        info["webpage_url"],
        info["duration"],
    )

def get_song_youtube(search) -> Song:
    title, artist, url, youtube_url, duration = search_youtube_video(search)
    return Song(title, artist, url, youtube_url, duration)


# Crie um programa para receber uma sequência de inteiros e mostrar ao inverso
def soma_elementos():
    n = 0
    lista = []
    n = int(input('Digite um número: '))
    while n > 0:
        lista.append(n)
        n = int(input('Digite um número: '))
    return lista[::-1]

def inverte_elementos():
    lista = soma_elementos()
    for i in range(len(lista)):
        print(lista[i])

inverte_elementos()


"""Write a function students_credits which receives a different number of strings.
Each string will be in the format: "{course name}-{credits}-{max test points}-{diyan's points}".
Your task is to calculate the credits Diyan manages to get from all courses.
The credits he gets are proportional to his points on the test. For example, if the credits of a course are 25, and
Diyan achieved to get 50 of 100 max test points, he will get 12.5 credits for the course.
Also, you need to keep track of each course and Diyan's credits and sort them in descending order by Diyan's credits.
Finally, return a string on multiple lines containing:
•	Diyan's achievement message:
o	If the sum of all of Diyan's credits is more than or equal to 240, return:
"Diyan gets a diploma with {total credits} credits."
o	Otherwise, return: "Diyan needs {credits needed} credits more for a diploma."
•	Information for each course and Diyan's credits:
o	"{course name} - {diyan's credits}"
o	Note: Each course data should be on a new line.
•	All credits must be formatted to the first decimal place.

Note: Submit only the function in the judge system
Input
•	There will be no input, just any number of strings with courses data passed to your function
Output
•	The function should return a string in the format described above:
Constraints:
•	There will always be at least one course.
•	There will not be two or more courses with the same name.
•	All points and all credits will be whole numbers
"""

def students_credits(*args):
    total_credits = 0
    courses_taken_credits = {}
    result = []

    for course_info in args:
        course_info = course_info.split("-")
        course_name = course_info[0]
        course_credits, max_test_points, student_points = [int(i) for i in course_info[1:]]
        percent_taken = (student_points * 100) / max_test_points
        credits_taken = (percent_taken / 100) * course_credits
        total_credits += credits_taken
        courses_taken_credits[course_name] = credits_taken

    if total_credits >= 240:
        result.append(f"Diyan gets a diploma with {total_credits:.1f} credits.")
    else:
        result.append(f"Diyan needs {(240 - total_credits):.1f} credits more for a diploma.")

    courses_taken_credits_sorted = sorted(courses_taken_credits.items(), key=lambda x: -x[1])
    courses_results = [f"{name} - {value:.1f}" for name, value in courses_taken_credits_sorted]

    result.extend(courses_results)
    return "\n".join(result)

# print(
#     students_credits(
#         "Computer Science-12-300-250",
#         "Basic Algebra-15-400-200",
#         "Algorithms-25-500-490"
#     )
# )

# print(
#     students_credits(
#         "Discrete Maths-40-500-450",
#         "AI Development-20-400-400",
#         "Algorithms Advanced-50-700-630",
#         "Python Development-15-200-200",
#         "JavaScript Development-12-500-480",
#         "C++ Development-30-500-405",
#         "Game Engine Development-70-100-70",
#         "Mobile Development-25-250-225",
#         "QA-20-300-300",
#     )
# )

# print(
#     students_credits(
#         "Python Development-15-200-200",
#         "JavaScript Development-12-500-480",
#         "C++ Development-30-500-405",
#         "Java Development-10-300-150"
#     )
# )


from rlscore.learner import RLS
from rlscore.measure import auc
from rlscore.utilities.reader import read_svmlight

def train_rls():
    X_train, Y_train, foo = read_svmlight("a1a.t")
    X_test, Y_test, foo = read_svmlight("a1a", X_train.shape[1])
    learner = RLS(X_train, Y_train)
    best_regparam = None
    best_auc = 0.
    #exponential grid of possible regparam values
    log_regparams = range(-15, 16)
    for log_regparam in log_regparams:
        regparam = 2.**log_regparam
        #RLS is re-trained with the new regparam, this
        #is very fast due to computational short-cut
        learner.solve(regparam)
        #Leave-one-out cross-validation predictions, this is fast due to
        #computational short-cut
        P_loo = learner.leave_one_out()
        acc = auc(Y_train, P_loo)
        print("regparam 2**%d, loo-auc %f" %(log_regparam, acc))
        if acc > best_auc:
            best_auc = acc
            best_regparam = regparam
    learner.solve(best_regparam)
    P_test = learner.predict(X_test)
    print("best regparam %f with loo-auc %f" %(best_regparam, best_auc))
    print("test set auc %f" %auc(Y_test, P_test))

if __name__=="__main__":
    train_rls()


datafiles = ["pyqtgraph", "pyqtgraph_100points", "matplot", "matplot_100points"]
for program_type in datafiles:
    with open("/home/r/TIMEPIX/data_%s.txt" % (program_type), "r") as f:
        line = f.readline().strip("\n")
        total = float(line)
        counter = 1.0
        while line:
            total += float(line)
            counter += 1.0
            line = f.readline().strip("\n")
        print("Average time required to run %s %f" % (program_type, total/counter))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Feb  3 16:48:02 2023

@author: johnmorgan
"""

# O(n) time complexity, auxiliary lists

def rearrange(lst):
    neg_lst, pos_lst = [],[]
    for elem in lst:
        if elem >= 0:
            pos_lst += [elem]
        else:
            neg_lst += [elem]
    return(neg_lst + pos_lst)

# Swap with leftmost positive element O(n)

# Pythonic, also O(n), loops over twice

def rearrange(lst):
    return [i for i in lst if i < 0] + [i for i in lst if i >= 0]

input_list = [10,-1,20,4,5,-9,-6]
print(rearrange(input_list))


class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        n = len(coins)

        @lru_cache(None)
        def dp(idx = n - 1, total = amount):

            if total == 0:
                return 0

            if idx == 0:
                remainder = total
                if remainder % coins[idx] == 0:
                    return remainder // coins[idx]
                return float('inf')

            not_take = dp(idx - 1, total)
            take = float('inf')

            if total >= coins[idx]:
                take = 1 + dp(idx, total - coins[idx])

            return min(take, not_take)

        ans = dp()
        return ans if ans != float('inf') else -1


import jwt
import os
from flask import request, g
from functools import wraps
from werkzeug.exceptions import Unauthorized

def auth_token():
    """Authenticate token and store user_id in g"""

    def _auth_token(func):
        @wraps(func)
        def __auth_token(*args, **kwargs):
            token = (
                request.headers.get("Authorization", "")
                .replace("Bearer ", "")
                .strip()
            )
            try:
                payload = jwt.decode(
                    token, os.environ["SECRET_KEY"], algorithms=["HS256"]
                )
            except jwt.exceptions.DecodeError:
                raise Unauthorized()
            g.user_id = payload.get("user_id")

            return func(*args, **kwargs)

        return __auth_token

    return _auth_token


# Example:
# python -u h5_downsample.py -i 0_human_instance_seg_pred.h5 -o 0_human_instance_seg_pred_v2.h5

import h5py
import numpy as np
import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input", required=True, help="Input h5 file")
parser.add_argument("-o", "--output", required=True, help="Output h5 downsample file")
parser.add_argument("-d", "--down", help="[z,y,x] downsampling to be applied", default=[1,2,2])
args = parser.parse_args()

# Load H5 file
h5f = h5py.File(args.input, 'r')
k = list(h5f.keys())

# Change the key accordingly
print("Keys: {}".format(k))
data = np.array(h5f[k[0]])
print("Loaded data shape: {}".format(data.shape))

data = data[::args.down[0],::args.down[1],::args.down[2]]
print("Downsampled data shape: {}".format(data.shape))

out_dir = os.path.dirname(args.output)
os.makedirs(out_dir, exist_ok=True)

# Create the h5 file (using lzf compression to save space)
h5f = h5py.File(args.output, 'w')
h5f.create_dataset('main', data=data, compression="lzf")
h5f.close()
print("File saved in {}".format(args.output))


""" Compares different experience replay sampling methods. """
from functools import partial
from collections import OrderedDict

import torch
from torch.nn import functional as F
import pandas as pd

import gym_fast_envs  # pylint: disable=unused-import
from liftoff.config import read_config, config_to_string

from utils import create_paths, configure_experiment, get_ground_truth

def learn(estimator, transition, loss_fn, optimizer, gamma):
    """ Computes the TD Error and optimises the model.

    Args:
        model (torch.nn.Module): An ensemble model.
        loss_fn (function): The loss functions.
        optimizer (torch.optim.Optim): An optimizer.
        transition (list): A s, a, r_, s_, d_, meta tuple.
        gamma (float): The discount factor.

    Returns:
        torch.tensor: The TD Error.
    """
    state, action, reward, state_, mask, _ = transition

    with torch.no_grad():
        q_targets = estimator(state_)

    qsa = estimator(state).gather(1, action)

    qsa_target = torch.zeros_like(qsa)
    qsa_target[mask] = q_targets.max(1, keepdim=True)[0][mask]

    qsa_target = (qsa_target * gamma) + reward
    loss = loss_fn(qsa, qsa_target)
    loss.backward()

    optimizer.step()
    optimizer.zero_grad()
    return loss

def learn_ensemble(ensemble, transition, learner, mem):
    """A wrapper over the `learn` function for optimizing an ensemble of
    estimators (`model`).
    """

    if mem.shuffle:
        transition[5]["boot_mask"] = mask = mem.sample_mask()
    else:
        mask = transition[5]["boot_mask"]

    mids = [mid for mid, m in enumerate(mask) if m != 0]
    for mid in mids:
        # optim.step() is called on all the parameters of the
        # ensemble when we learn a single component of the
        # ensemble. therefore we delete the gradients of all the
        # other estimators to avoid unnecessary operations in
        # optim.step().
        for i, estimator in enumerate(ensemble):
            if i != mid:
                estimator.weight.grad = None

        ensemble_ = partial(ensemble, mid=mid)
        learner(ensemble_, transition)

    return ensemble.var(transition[0], transition[1][0].item())

def train(mem, model, learner, tester, update_cb=None):
    """ The training sequence.
    """
    has_converged = False
    step_cnt = 0

    while not has_converged:
        batch = mem.sample()

        # we are not doing mini-batch learning
        for transition in batch:

            priority = learner(model, transition)

            # update priorities
            if update_cb:
                update_cb(mem, transition, priority)

            step_cnt += 1

            # check for convergence
            has_converged = tester(step_cnt)

            if has_converged:
                break

class Logger:
    def __init__(self, metrics):
        self.__df = pd.DataFrame(columns=metrics)
        self.__idx = 0

    def update(self, loss, step, with_vote=0):
        self.__df.loc[self.__idx] = [step, loss, with_vote]
        self.__idx += 1

    def get_results(self):
        return self.__df

class ConvergenceTester:
    """ Checks for convergence on one or two metrics.
    """

    def __init__(self, model, mdp_size, metrics, log=None, threshold=0.001):
        self.__model = model
        self.__threshold = threshold
        gamma = 1 - 1 / mdp_size
        test_states, optim_q_vals = get_ground_truth(mdp_size, gamma)
        self.__test_states, self.__optim_q_vals = test_states, optim_q_vals
        self.__converged = OrderedDict(
            {metric: {"converged": False, "step_cnt": 0} for metric in metrics}
        )
        if log:
            self.__log = log

    def get_results(self):
        steps = [metric["step_cnt"] for metric in self.__converged.values()]
        return steps, self.__log.get_results()

    def __call__(self, step_cnt):
        return self.__has_converged(step_cnt)

    def __has_converged(self, step_cnt):
        losses = []
        with torch.no_grad():
            y = self.__model(self.__test_states)
            if isinstance(y, tuple):
                for yi in y:
                    losses.append(F.mse_loss(yi, self.__optim_q_vals).item())
            else:
                losses.append(F.mse_loss(y, self.__optim_q_vals).item())

        for i, (k, metric) in enumerate(self.__converged.items()):
            if not metric["converged"]:
                self.__converged[k]["converged"] = losses[i] < self.__threshold
                self.__converged[k]["step_cnt"] = step_cnt

        if self.__log is not None:
            if step_cnt % 100 == 0:
                for i, loss in enumerate(losses):
                    self.__log.update(loss, step_cnt, i)

        return all([m["converged"] for m in self.__converged.values()])

def run(opt):
    """ Experiment trial. """
    lr = 0.25
    learners = [learn, learn_ensemble]

    mem, cb, model, learner, tag = configure_experiment(opt, lr, learners)
    n, mem_size = opt.mdp_size, len(mem)

    # configure tester @ logger
    metrics = ["optim_steps"]
    log_metrics = ["step", "loss", "vote"]
    try:
        if opt.experience_replay.bayesian:
            metrics = ["optim_steps", "vote_optim_steps"]
    except AttributeError:
        pass

    log = Logger(log_metrics)
    tester = ConvergenceTester(model, n, metrics, log=log)

    # run training
    train(mem, model, learner, tester, update_cb=cb)

    # do reporting
    pd.set_option("precision", 4)
    # retrieve logged metrics (optims steps and loss curves)
    optim_steps, results_df = tester.get_results()
    loss = opt.loss if "loss" in opt.__dict__ else "mse"

    # add columns to the loss dataframe curves
    additional_cols = [
        *metrics,
        "N",
        "mem",
        "trial",
        "sampling_type",
        "loss_fn",
    ]
    row_vals = [*optim_steps, n, mem_size, opt.run_id, tag, loss]
    for col, val in zip(additional_cols, row_vals):
        results_df[col] = val

    # save panda
    results_df.to_msgpack(f"./{opt.out_dir}/results.msgpack")

    # log results
    print(config_to_string(opt), flush=True)
    header = f"N={n}, tag={tag}, trial={opt.run_id} results:"
    print("-" * (len(header) + 2))
    print(header, flush=True)
    print("-" * (len(header) + 2))
    print(results_df.head(3), flush=True)

def main():
    """ Entry point. """
    opt = read_config()
    opt = create_paths(opt)
    run(opt)

if __name__ == "__main__":
    main()


import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph([(1, 2), (1, 3), (1, 5), (3, 4), (4, 5)])

num_nodes = G.number_of_nodes()
print('Number of Nodes {}'.format(num_nodes))
num_edges = G.number_of_edges()
print('Number of Edges {}'.format(num_edges))

subax1 = plt.subplot(121)
nx.draw(G, with_labels=True, font_weight='bold')

degree_c = nx.degree_centrality(G)
print('Degrees of Centrality is {}'.format(degree_c))

closeness_c = nx.closeness_centrality(G)
print('Closeness of Centrality is {}'.format(closeness_c))

# compute centrality
betweenness_centrality = nx.betweenness_centrality(G)
print('Betweenness of Centrality is {}'.format(betweenness_centrality))

plt.show()


import cv2
import numpy as np
import matplotlib as plt

img=cv2.imread('cat.jpg',0)
cv2.imshow('yuantu',img)

img2=cv2.Canny(img,200,300)
cv2.imshow('Canny',img2)

ret,img3=cv2.threshold(img,125,255,cv2.THRESH_BINARY)
c,h=cv2.findContours(img3,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

print('轮廓:',c)
print('轮廓类型:',type(c))
print('轮廓数:',len(c))
print('层次',h)
print('层次类型:',type(h))

# img4 = np.zeros_like(img) + 255
# for n in (range(len(c))):
# 	cv2.polylines(img4,[c[n]],True,(255,0,0),2)
# cv2.imshow('%s'%n,img4)

img5=np.zeros(img.shape,np.uint8)+255
img5=cv2.drawContours(img3,c,-1,(0,0,255),2)
cv2.imshow('Contours',img5)

for n in range(len(c)):
	m=cv2.moments(c[n])
	print('轮廓%s的矩：'%n,m)
	print('轮廓%s的面积：' % n, m['m00'])

img=cv2.imread('cat.jpg')#读取图像
cv2.imshow('original',img)#显示原图像
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#将其转化为灰度图像
ret,img2=cv2.threshold(gray,125,255,cv2.THRESH_BINARY)#二值化阈值处理
c,h=cv2.findContours(img2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#查找轮廓

img3=np.zeros(img.shape,np.uint8)+255
img3=cv2.drawContours(img3,c,-1,(0,0,255),2)
cv2.imshow('Counters',img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.waitKey(0)
cv2.destroyAllWindows()


"""
Problem Statement: Intersecting Wires

This problem is taken from a recent code.google.com/codejam contest. Although not required at the
time the problem specifications were given, we have modified a few of the constraints so you will (most
likely) need to implement an efficient divide-and-conquer algorithm to pass the CS320 harder data set.
An intranet company wants to connect two buildings with many wires, each connecting a port on the
first building to a port on the second building. Wires are straight segments connecting a vertical position
on the left building to a vertical position on the right building. No two wires share the same endpoint
on a building. However, from our side viewpoint, some of the wires intersect midway. We also noticed
that due to different tensions of the wires exactly two wires meet at any given intersection point.

Sample Input:
2
3
1 10
5 5
7 7
2
1 1
2 2

Sample Output (longest wires):
Case #1: 1
Case #2: 1 2

We have two problems. The first problem checks if you can read the input and compute a list of wires
that are the longest in length. With x being the case number, output a single line containing “Case
#x: ” followed by a single white-space separated list in increasing order of wires (starting at index 1).

"""

def compare(v1, v2):
    if(int(v1) > int(v2)):
        value = int(v1)-int(v2)
    else:
        value = int(v2) - int(v1)

    return value

n = 0
loop = int(input())

while(n < loop):

    inputNum = int(input())
    largeValue = 0
    lvList = []
    lvDict = {}
    for i in range(1, inputNum+1):
        wire = input().split()
        lvDict[i] = wire
        value = compare(wire[0], wire[1])

        if(len(lvList) > 0):
            if(value > largeValue):
                largeValue = value
                lvList = [i]
            elif(value == largeValue):
                lvList += [i]
        else:
            largeValue = value
            lvList = [i]

        #print(lvList, 'lvList')
    #print(lvDict, 'lvDict')

    output = str(lvList[0])
    for j in range(1, len(lvList)):
        output += " "+ str(lvList[j])

    n += 1
    print("Case #"+ str(n)+ ": "+ str(output))


import random

from russian import words

words_already_named = ['лл']
pre_word = ''
happy_msg = (
    'Отлично, такое слово есть!',
    'Вау, у нас тут знаток слов!',
    'Может быть хватит!? Отгадывать мои слова :)',
    'О как великолепно, когда слово есть!:)',
    'И-и-и-и.....',
    'Барабанная дробь *_*_*_ и:',
    'Н-у-у-у, это правильное слово!',
    'Угадайка-отгадайка!',
    'Белиссимо-словисимо! Правильно :)',
    'Ты-ы-ы-ы просто чудо!^)'
)

def happy_say(word: str, words=words) -> str:
    '''Сообщения для пользователя'''
    player_word = word.rstrip().lower()
    if words.get(player_word):
        return random.choice(happy_msg)

def check_word(word: str, words=words) -> str:
    '''Игра в слова'''
    player_word = word.rstrip().lower()
    if words.get(player_word):
        if player_word[-1] in ('ь', 'ъ') and len(player_word) > 3:
            if player_word not in words_already_named:
                words_already_named.append(player_word)
                words_already_named.append(player_word[:-1])
                last_letter = player_word.upper()[-2]
                return 'Следующее слово должно начинаться на ' + '"' + last_letter + '"'
        if words_already_named and player_word[-1] not in ('ь', 'ъ'):
            if player_word[0] != words_already_named[-1][-1]:
                return 'Но-но, по-легче! Слово должно начинаться букву "{0}"!'.format(words_already_named[-1][-1].upper())
            else:
                if player_word not in words_already_named:
                    words_already_named.append(player_word)
                    last_letter = player_word.upper()[-1]
                    return 'Следующее слово должно начинаться на ' + '"' + last_letter + '"'
                else:
                    return 'Слово уже было. Повторите попытку'
    else:
        return (
            f'Сам ты "{player_word.upper()}".'
            f'Такого слова нет в моем словаре, придумай другое!')


# Faça um programa que leia três números e mostre qual é  maior e qual é o menor.

num1 = float(input('Digite um número: '))
num2 = float(input('Digite outro número: '))
num3 = float(input('Digite mais um número: '))

menor = num1
if num2 < num1 and num2 < num3:
    menor = num2
if num3 < num2 and num3 < num2:
    menor = num3

maior = num1
if num2 > num1 and num2 > num3:
    maior = num2
if num3 > num2 and num3 > num2:
    maior = num3

print('O menor valor digitado foi {} e o maior valor foi {}'.format(menor, maior))

# Resolução da aula

# a = float(input('Primeiro valor: '))
# b = float(input('Segundo valor: '))
# c = float(input('Terceiro valor: '))
# menor = a
# if b < a and b < c:
#     menor = b
# if c < a and c < b:
#     menor = c
# maior = a
# if b > a and b > c:
#     maior = num2
# if c > b and c > b:
#     maior = c
# print('O menor valor digitado foi {}'.format(menor))
# print('O maior valor foi {}'.format(maior))