class VotingSystem:
    def __init__(self, n_emulator, simulation, x_parameters, t_series_names,
                 normalize, drop_outliers):
        self.n_emulator = n_emulator
        self.simulation = simulation
        self.x_parameters = x_parameters
        self.t_series_names = t_series_names
        self.normalize = normalize
        self.drop_outliers = drop_outliers
        self.formater_emulator = Emulator(f'Emulator_formater',
                                          self.x_parameters,
                                          self.t_series_names, self.normalize,
                                          self.drop_outliers)
        self.x_signal, self.y_signal, self.x_min_max, self.y_min_max = self.formater_emulator.format_data(
            self.simulation)

    def start_training(self):
        self.emulators = dict()
        number_of_points = np.linspace(
            len(self.x_signal) / 6, len(self.x_signal),
            self.n_emulator).astype(int)

        number_of_rows = self.x_signal.shape[0]

        for i in range(self.n_emulator):
            print(number_of_points[i])
            print(number_of_rows)
            random_indices = np.random.choice(number_of_rows,
                                              size=number_of_points[i],
                                              replace=False)
            x_signal = self.x_signal[random_indices, :]
            y_signal = self.y_signal[random_indices, :]
            if self.x_min_max != None:
                x_min_max = self.x_min_max[random_indices, :]
                y_min_max = self.y_min_max[random_indices, :]
            else:
                x_min_max = None
                y_min_max = None

            print(f'training on emulator n° {i} : started ')
            # TODO dev other multi training methods

            emulator = Emulator(f'Emulator_{i}', self.x_parameters,
                                self.t_series_names, self.normalize,
                                self.drop_outliers)
            emulator.train(x_signal, y_signal, x_min_max, y_min_max)
            self.emulators[emulator.name] = emulator
            print(f'training on emulator n° {i} : done ')

    def predict(self, input_params):
        prediction = dict()
        for emulator_name in list(self.emulators.keys()):
            prediction[emulator_name] = self.emulators[emulator_name].predict(
                input_params)
        return prediction
def benchmark(number_of_iter, min_samples, max_samples, type='scorer'):
    number_of_point = np.linspace(min_samples, max_samples, number_of_iter)
    benchmark_data_frame = pd.DataFrame()
    descriptors = [
        "alpha", "beta", "delta", "gamma", "DefaultComp.predator",
        "DefaultComp.prey"
    ]
    # create vpop testing
    vpop_test = Vpop(
        f'vpop testing',
        descriptors,
        # fixed_parameters=dict({'pred_0': 1, 'prey_0': 1}),
        number_of_point=500,
        min_=0.1,
        max_=1,
        sampling_method='random')
    vpop_test.sample()

    # create model
    model = Model('model', type=type)

    testing_data_frame = model.run(vpop_test)

    emulator = Emulator('test formater',
                        x_parameters=descriptors,
                        normalize=False,
                        drop_outliers=False)
    intput_signal_model_test, output_signal_model_test, input_min_max_model_test, output_min_max_model_test = emulator.format_data(
        testing_data_frame)
    test_data_signal = (intput_signal_model_test, output_signal_model_test)
    test_data_min_max = (input_min_max_model_test, output_min_max_model_test)

    print(vpop_test.patients)
    for i in range(number_of_iter):
        print(f'iteration n°{i} : sampling...')

        # create training vpop
        vpop_train = Vpop(
            f'vpop n°{i}',
            descriptors=descriptors,
            # fixed_parameters=dict({'pred_0': 1, 'prey_0': 1}),
            number_of_point=int(number_of_point[i]),
            min_=0.1,
            max_=1)
        vpop_train.sample()

        # run model on vpop
        training_data_frame = model.run(vpop_train)

        # create emulator
        emulator = Emulator(f'emulator_n°{i}',
                            x_parameters=descriptors,
                            normalize=False,
                            drop_outliers=False)
        print(f'iteration n°{i} : sampling done, formating...')
        # format input
        intput_signal_model_train, output_signal_model_train, input_min_max_model_train, output_min_max_model_train = emulator.format_data(
            training_data_frame)

        print(f'iteration n°{i} : training...')

        emulator.train(
            intput_signal_model_train,  # train
            output_signal_model_train,
            input_min_max_model_train,
            output_min_max_model_train,
            test_data=True,
            test_data_signal=test_data_signal,
            test_data_min_max=test_data_min_max)

        prediction = emulator.predict(
            input_params=testing_data_frame[descriptors].values)
        true = testing_data_frame[emulator.t_series_names].values

        raw_mse = emulator.mse(prediction, true=true)
        raw_mse['training_set_size'] = vpop_train.number_of_point
        benchmark_data_frame = pd.concat([benchmark_data_frame, raw_mse],
                                         axis=0)

        benchmark_data_frame.to_json(f"benchmark/benchmark_scorer.json",
                                     orient='split',
                                     index=False)

    return benchmark_data_frame