#import sys
import os
import argparse
from pathlib import Path
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
import io
import re
from tqdm import tqdm

def pdfparser(data):

    fp = open(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = io.StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, laparams=laparams) #codec=codec
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    return data

def main(inpath, outpath):
    for filename in tqdm(Path(inpath).glob("*.pdf")):

        base=os.path.splitext(os.path.basename(filename))[0]
        ID = re.search(r'#[0-9]+', base)

        # some of them do not have an ID
        try:
            paperID = ID.group() + "_paper.txt"

            text = pdfparser(os.path.join(f"{filename}"))

            with open(os.path.join(outpath, paperID), "w") as text_file:
                text_file.write(text)

        except AttributeError:
            pass

if __name__ == '__main__':
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--inpath", required=True, type=str, help="path to folder with input files (pdfs)")
    ap.add_argument("-o", "--outpath", required=True, type=str, help='path to folder for saving output files')
    args = vars(ap.parse_args())

    main(inpath = args['inpath'], outpath = args['outpath'])


import base64
from io import BytesIO

import dash
import dash_core_components as dcc
import dash_html_components as html
import matplotlib.pyplot as plt
from pickle import load
from dash.dependencies import Output, Input

from mg_nmf.nmf import NMFGeneSetEnrichment
from mg_nmf import nmf as visualise, nmf as selection

"""
Attempt at a multipage app to
* View heatmaps summarising the model
* View a PCA-RGB map of the model
* Enrichment analysis and gene breakdown
"""

# Load some results to look at
with open('/home/hal/Dropbox/PHD/FunctionalAbundance/nmf/data/metatranscriptome_k6.enrich', 'rb') as f:
    analysis: NMFGeneSetEnrichment = load(f)

MODEL_RES = '/home/hal/Dropbox/PHD/FunctionalAbundance/nmf/data/metatranscriptome_k6.model'
res = selection.NMFModelSelectionResults.load_model(MODEL_RES)

# Methods to generate some plots
def heatmap_image(results):
    fig = visualise.heatmap_plot(res, axes=[0], return_fig=True, log=False)
    pic_bytes = BytesIO()
    plt.savefig(pic_bytes, format='png')
    pic_bytes.seek(0)
    pic_hash = base64.b64encode(pic_bytes.read()).decode("ascii").replace("\n", "")
    img = html.Img(src="data:image/png;base64,{}".format(pic_hash))
    return img

def enrichment_plot(enrichment):
    return dcc.Graph(
        id='enrichment-heatmap',
        figure=enrichment.plot_enrichment(enrichment.results(significance=0.05), group='namespace', label='name',
                                          width=None, height=None),
        style=dict(height='100%'),
        config=dict(displayModeBar=False)
    )

app = dash.Dash(__name__)

heatmap_page = html.Div([
    html.H1('Hi'),
    heatmap_image(res)
])

enrichment_page = html.Div([
        html.Div([
            enrichment_plot(enrichment=analysis),
        ], style=dict(flex=1)),
        html.Div([], id='enrichment-term-plots', style=dict(flex=1, overflowY='auto'))
    ], style=dict(display='flex', height='100%'))

navigation_buttons = html.Div([
        html.Button('Model Heatmap', id='button-heatmap'),
        html.Button('Enrichment', id='button-enrichment'),
        html.Button('Map', id='button-map')
    ], style=dict(display='flex'),
)

layout_index = html.Div([
    navigation_buttons,
    html.Div([], id='content-div', style=dict(height='90vh'))
])

app.layout = layout_index

# Button callbacks
@app.callback(
    Output('content-div', 'children'),
    Input('button-heatmap', 'n_clicks'),
    Input('button-enrichment', 'n_clicks'),
    Input('button-map', 'n_clicks')
)
def button_event(btn1, btn2, btn3):
    ctx = dash.callback_context
    if ctx is None:
        return heatmap_image(res)
    # Find which button triggered the callback
    btn_trigger = ctx.triggered[0]['prop_id'].split('.')[0]
    if btn_trigger == 'button-heatmap':
        return heatmap_image(res)
    if btn_trigger == 'button-enrichment':
        return enrichment_page
    return []

# Heatmap page callbacks

# Enrichment page callbacks
@app.callback(
    Output('enrichment-term-plots', 'children'),
    Input('enrichment-heatmap', 'clickData'))
def display_click_data(clickData):
    # Extract the GO Term from this
    if clickData is None:
        return html.Div()
    go = clickData['points'][0]['y'].split("GO:")[1][:-1]
    go = 'GO:' + go
    component = clickData['points'][0]['x']
    return dcc.Graph(
        id='enrichment-correlation',
        figure=analysis.plot_geneset_correlation(component=component, gene_set_id=go, cols=3, vspace=0.03)
    )

if __name__ == '__main__':
    app.run_server(debug=True)


from lmfit import Parameters, Parameter
from liboptpy.lib.mechanism_model import mechanism
from liboptpy.policy import Policy, PolicyLab, PolicyDDPG
from liboptpy.gradients.bayesian_network import bayesian_network, bayesian_network_posterior
from liboptpy.gradients.BN_gradient import BN_gradient
import liboptpy.constr_solvers._proj_gd as cs
import liboptpy.step_size as ss
import numpy as np
import pandas as pd
from liboptpy.simulator.bio_env import fermentation_env, fermentation_env2, two_unit_operations_env
from liboptpy.lib.compute_reward import compute_avg_reward
from liboptpy.simulator.bioprocess_2stages import fermentation_purification_simulator

feed_profile = [0.000000e+00, 3.131863e-05, 8.332656e-04, 3.641692e-03, 9.661720e-03, 7.794840e-03, 7.359495e-03,
                5.043735e-03, 5.347406e-03, 2.486022e-03, 2.385212e-03, 2.301092e-03, 1.724154e-03, 6.246971e-04,np.log(40), np.log(60)]
# feed_profile = [0.0000000000, 0.0003131863, 0.0041663280, 0.0098325692, 0.0087833820, 0.0077948404, 0.0056611497,
#                 0.0038797959, 0.0041133889, 0.0019123248, 0.0015901411, 0.0015340615, 0.0011494357, 0.0004164647]

#
# feed_profile = [0.0000000000,
#                 0.0003624999,
#                 0.0048485723,
#                 0.0119220315,
#                 0.0102440275,
#                 0.0086513113,
#                 0.0061447560,
#                 0.0039552809,
#                 0.0048855832,
#                 0.0020873176,
#                 0.0017531639,
#                 0.0015830354,
#                 0.0010269718,
#                 0.0004710181,
#                 np.log(40), np.log(60)]
# feed_profile = [0.0000000000, 0.0003131863, 0.0041663280, 0.0098325692, 0.0087833820, 0.0077948404, 0.0056611497,
#                 0.0038797959, 0.0041133889, 0.0019123248, 0.0015901411, 0.0015340615, 0.0011494357, 0.0004164647,
#                 np.log(40), np.log(60)]

# feed_profile = [0, 4.440000e-19, 0.002515011, 0.004502748, 0.005973753, 0.007297723, 0.006291863,  5.175258e-03, 0.0025989402, 0.001611073, 0.001167248, 0.001135921, 0.0010017584, 0.0001669597]
# feed_profile = [0.000000e+00,  0.000000e+00,  2.801345e-03,  6.500561e-03,  7.838870e-03,  7.379049e-03,  5.426248e-03, -4.236836e-05,
#  1.575191e-02,  1.355505e-03, -1.190099e-03,  1.957627e-03,  9.760737e-04,  1.626789e-04]
real_measurement = [0.0, 5.0, 10.0, 23.0, 28.0, 34.0, 47.5, 55.0, 72.0, 80.0, 95.0, 102.0, 120.0, 140.0]

if __name__ == '__main__':

    params = Parameters()

    params.add('alpha_L', value=0.127275, min=0, max=0.5)
    params.add('c_max', value=130.901733, min=100, max=250)
    params.add('K_iN', value=0.12294103, min=0, max=5.064)
    params.add('K_iS', value=612.178130, min=300, max=700)
    params.add('K_iX', value=59.9737695, min=20, max=100)
    params.add('K_N', value=0.02000201, min=0, max=1)
    params.add('K_O', value=0.33085322, min=0, max=10)
    params.add('K_S', value=0.0430429, min=0, max=5)
    params.add('K_SL', value=0.02165744, min=0, max=1)
    params.add('m_s', value=0.02252332, min=0, max=2)
    params.add('r_L', value=0.47917813, min=0, max=1)
    params.add('V_evap', value=2.6 * 1e-03, min=0, max=10)
    params.add('Y_cs', value=0.682572, min=0, max=4)
    params.add('Y_ls', value=0.3574429, min=0, max=2)
    params.add('Y_xn', value=10.0, min=0, max=15)
    params.add('Y_xs', value=0.2385559, min=0, max=1)
    params.add('beta_LC_max', value=0.14255192, min=0, max=5)
    params.add('mu_max', value=0.3844627, min=0, max=2)
    params_copy = params.copy()

    beta_gibbs = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/beta_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    v2_gibbs = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/v2_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None,
                            dtype=np.float64)
    the_R = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/the_R_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    tau2_R = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/tau2_R_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    kap_R = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/kap_R_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    lam_R = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/lam_R_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    mu = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/mu_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    sd = pd.read_csv('/Users/hua.zheng/Research/PHD/project/BN-MDP/BN/sd_s5a1-R100-explore0.3-v1-modelrisk--ntime36-sigma10-2operations.txt', header=None, dtype=np.float64)
    bn_post = bayesian_network_posterior(the_R.to_numpy(), tau2_R.to_numpy(), kap_R.to_numpy(), lam_R.to_numpy(),
                                         mu.to_numpy().flatten(), 5, 1, 39, beta_gibbs, v2_gibbs)
    p_beta, p_v2, mu = bn_post.posterior_sample(5000, useFixed=False)
    beta = np.apply_along_axis(np.mean, 2, p_beta)
    v2 = np.apply_along_axis(np.mean, 1, p_v2)
    bn = bayesian_network(mu, beta, v2, 1, 5, 39, True, mu, sd.to_numpy().flatten())

    ''' set up with the constraints '''
    def projection(y):
        theta = y.reshape((bn.n_time - 1, bn.num_state, bn.num_action))
        theta[:bn.n_time - 1 - 2, 0, :] = np.clip(theta[:bn.n_time - 1 - 2, 0, :], 0, 0.6)
        theta[:bn.n_time - 1 - 2, 1, :] = np.clip(theta[:bn.n_time - 1 - 2, 0, :], 0, 0.6)
        theta[0, 2, :] = np.clip(theta[0, 2, :], -0.2, 0.2)
        theta[:bn.n_time - 1 - 2, 2, :] = np.clip(theta[:bn.n_time - 1 - 2, 2, :], -0.4, 0.4)
        theta[:bn.n_time - 1 - 2, 3, :] = np.clip(theta[:bn.n_time - 1 - 2, 3, :], -0.2, 0.04)
        theta[:bn.n_time - 1 - 2, 4, :] = np.clip(theta[:bn.n_time - 1 - 2, 4, :], -1.4, 1)

        theta[bn.n_time - 1 - 2, 0, :] = np.clip(theta[bn.n_time - 1 - 2, 0, :], -0.1, 0.02)
        theta[bn.n_time - 1 - 2, 1, :] = np.clip(theta[bn.n_time - 1 - 2, 0, :], -0.02, 0.1)

        theta[bn.n_time - 1 - 1, 0, :] = np.clip(theta[bn.n_time - 1 - 1, 0, :], -0.0, 0.1)
        theta[bn.n_time - 1 - 1, 1, :] = np.clip(theta[bn.n_time - 1 - 1, 0, :], -0.1, 0.0)

        theta[bn.n_time - 1 - 2:, 2, :] = 0
        theta[bn.n_time - 1 - 2:, 3, :] = 0
        theta[bn.n_time - 1 - 2:, 4, :] = 0
        return theta.flatten()

    ''' projected gradient accent with posterior sampling '''

    cumulative_rewards = []
    cumulative_profits =[]
    final_purity = []
    final_titer = []
    total_feeding = []
    feed_profiles = []
    conv_trajectories = []
    patient = 15
    window = 15
    max_iter = 100
    algorithm = 'PGA'
    fixedBN = False
    for id in range(30):
        feed_profile_ddpg = []
        np.random.seed(1 + id)

        time_interval = 140 / (bn.n_time - 3 - 1)
        time_measurement = [time_interval * i for i in range(bn.n_time -3)]
        flag_estimate_reward_fun = False
        m = [0] * (bn.n_time - 1) + [-15]  # $/g
        b = np.transpose(np.array([[-0.13363 * 1000 * time_interval] * (bn.n_time - 3) + [-0.05] * 2]))  # $/g
        c = np.zeros(shape=(bn.n_time, bn.num_state))
        c[bn.n_time - 1, 0] = 1.28739  # product revenue
        c[bn.n_time - 1, 1] = - 1  # purification cost

        gradient = BN_gradient(m, b, c, bn, time_measurement, flag_estimate_reward_fun)
        theta = np.random.uniform(low=0., high=0.3, size=(bn.n_time - 1, bn.num_state, bn.num_action))
        grad = lambda x: - gradient.grad_f(x)
        f = lambda x: - gradient.func(x)

        process_model = mechanism()
        bio_env = two_unit_operations_env(process_model, bn, time_measurement, real_measurement, m, b, c, params)
        if not fixedBN:
            methods = {"PGA": cs.ProjectedGDWithPosterior(f,
                                                          grad,
                                                          projection,
                                                          ss.Backtracking(rule_type="Armijo", rho=0.5, beta=0.1,
                                                                          init_alpha=0.001),
                                                          bn_post,
                                                          bio_env,
                                                          sd.to_numpy().flatten(),
                                                          256,
                                                          patient,
                                                          window)
                       }
        else:
            methods = {"PGA": cs.ProjectedBNPG(f,
                                               grad,
                                               projection,
                                               ss.Backtracking(rule_type="Armijo", rho=0.5, beta=0.1,
                                                               init_alpha=0.001),
                                               bn_post,
                                               bio_env,
                                               sd.to_numpy().flatten(),
                                               256,
                                               patient,
                                               window)
                       }

        tol = -1000  # 1e-25
        for m_name in methods:
            print("\t", m_name)
            x = methods[m_name].solve(x0=theta.flatten(), max_iter=max_iter, tol=tol, disp=2)
        # gradient.states
        # [f(x) for x in methods[m_name].get_convergence()]

        theta = x.reshape((bn.n_time - 1, bn.num_state, bn.num_action))
        policy = Policy(theta, True)
        '''bn
        simulate new policy and existing policy with true model (ODEs)
        '''
        B = 50
        x0 = bn.initial_state_full

        simulator = fermentation_purification_simulator(bn, time_measurement, policy, real_measurement)
        state = simulator.g(time_measurement, x0, params)
        state = state[-1, :]
        feed_profile_ddpg = list(simulator.feed.values())
        total_feed_MDP = np.sum(feed_profile_ddpg)
        ammonium_sulphate, downstream_state, result2 = simulator.purification_processes(state)

        conv_trajectories.append(methods[m_name].convergence_reward)

        cur_titer = np.exp(downstream_state[0])
        cur_purity = np.exp(downstream_state[0]) / (np.exp(downstream_state[1]) + np.exp(downstream_state[0]))
        final_titer.append(cur_titer)
        final_purity.append(cur_purity)
        feed_profiles.append(list(simulator.feed.values()))
        total_feeding.append(total_feed_MDP * (140 / (bn.n_time - 3 - 1)))
        # final_reward = -0.13363 * 1000 * total_feed_MDP + 1.28739 * state[-1, 1]
        final_reward = -15 - 0.13363 * 1000 * total_feed_MDP - b[-1][0] * sum(ammonium_sulphate) \
                       + c[bn.n_time - 1, 0] * downstream_state[0] + c[bn.n_time - 1, 1] * downstream_state[1]
        final_profit = -15 - 0.13363 * 1000 * total_feed_MDP - b[-1][0] * sum(np.exp(ammonium_sulphate)) \
                       + c[bn.n_time - 1, 0] * np.exp(downstream_state[0]) + c[bn.n_time - 1, 1] * np.exp(
            downstream_state[1])

        cumulative_rewards.append(final_reward)
        cumulative_profits.append(final_profit)
        print('--------------------------------------------------')
        print(id)
        # print(policy.theta)
        print("mean final titer = {}".format(np.exp(downstream_state[0])))
        print("mean final purity = {}".format(np.exp(downstream_state[0])/(np.exp(downstream_state[1]) + np.exp(downstream_state[0]))))
        print("mean reward = {}".format(final_reward))
        print("mean profit = {}".format(final_profit))

    print('---------------------Summary-------------------------')
    print(np.mean(final_titer), np.std(final_titer))
    print(np.mean(final_purity), np.std(final_purity))
    print(np.mean(cumulative_rewards), np.std(cumulative_rewards))
    print(np.mean(cumulative_profits), np.std(cumulative_profits))


"""
Based on: https://docs.tudat.space/en/latest/_src_getting_started/_src_examples/notebooks/propagation/perturbed_satellite_orbit.html?highlight=ground#Ground-track
"""

# Load standard modules
import numpy as np

import matplotlib
from matplotlib import pyplot as plt

# Load tudatpy modules
from tudatpy.kernel.interface import spice
from tudatpy.kernel import numerical_simulation
from tudatpy.kernel.numerical_simulation import environment_setup, propagation_setup
from tudatpy.kernel.astro import element_conversion
from tudatpy.kernel import constants
from tudatpy.util import result2array

import satellite

class tudat_environment:
    def __init__(self, epochstart: float = 0):
        self.initial_state = None
        self.time_hours = None
        self.dep_vars_array = None
        self.states_array = None
        self.propagator_settings = None
        self.acceleration_models = None
        self.dependent_variables_to_save = []
        self.initial_states_settings = None
        self.initial_states = None
        self.acceleration_settings = None
        self.central_bodies = None
        self.bodies_to_propagate = None

        # Load spice kernels
        spice.load_standard_kernels()

        # Set simulation start and end epochs
        self.simulation_start_epoch = epochstart   ## January 1 2035
        self.simulation_end_epoch = constants.JULIAN_DAY

        # Define string names for bodies to be created from default.
        self.bodies_to_create = ["Sun", "Earth", "Moon"] #"Mars", "Venus"

        # Use "Earth"/"J2000" as global frame origin and orientation.
        self.global_frame_origin = "Earth"
        self.global_frame_orientation = "J2000"

        # Create default body settings, usually from `spice`.
        self.body_settings = environment_setup.get_default_body_settings(
            self.bodies_to_create,
            self.global_frame_origin,
            self.global_frame_orientation)

        # Create system of selected celestial bodies
        self.bodies = environment_setup.create_system_of_bodies(self.body_settings)

    def create_sat(self, sat_object, name: str):
        # Create vehicle objects.
        self.bodies.create_empty_body(name)
        self.bodies.get(name).dry_mass = sat_object.dry_mass

    def set_up_aerodynamics(self,
                            sat: str,
                            reference_area: float, ## Initial vol
                            drag_coefficient: float  ## Initital drag coefficient
                            ):
        # Create aerodynamic coefficient interface settings, and add to vehicle
        aero_coefficient_settings = environment_setup.aerodynamic_coefficients.constant(
            reference_area, [drag_coefficient, 0, 0]
        )
        environment_setup.add_aerodynamic_coefficient_interface(
            self.bodies, sat, aero_coefficient_settings)

    def set_up_solar_pressure(self,
                              sat: str,
                              reference_area_radiation: float,
                              radiation_pressure_coefficient: float
                              ):
        # Create radiation pressure settings, and add to vehicle
        occulting_bodies = ["Earth"]
        radiation_pressure_settings = environment_setup.radiation_pressure.cannonball(
            "Sun", reference_area_radiation, radiation_pressure_coefficient, occulting_bodies
        )
        environment_setup.add_radiation_pressure_interface(
            self.bodies, sat, radiation_pressure_settings)

    def propagation_setup(self, sats: list):
        self.bodies_to_propagate = sats
        self.central_bodies = ["Earth"]

    def set_up_acceleration(self, sats: list):
        # Define accelerations acting on satellite by Sun and Earth.
        accelerations_settings = dict(
            #Sun=[
                #propagation_setup.acceleration.cannonball_radiation_pressure(),
            #    propagation_setup.acceleration.point_mass_gravity()
            #],
            Earth=[
                propagation_setup.acceleration.spherical_harmonic_gravity(1, 5),
                #propagation_setup.acceleration.aerodynamic()
            ]#,
            #Moon=[
            #    propagation_setup.acceleration.point_mass_gravity()
            #]#, ## Should be removed due to insignificance compared to the others:
            # Mars=[
            #     propagation_setup.acceleration.point_mass_gravity()
            # ],
            # Venus=[
            #     propagation_setup.acceleration.point_mass_gravity()
            # ]
        )

        # Create global accelerations settings dictionary.
        self.acceleration_settings = {}
        for sat in sats:
            self.acceleration_settings[sat] = accelerations_settings

        # Create acceleration models.
        self.acceleration_models = propagation_setup.create_acceleration_models(
            self.bodies,
            self.acceleration_settings,
            self.bodies_to_propagate,
            self.central_bodies)

    def set_up_initial_states(self, sats: list):
        self.initial_states = np.empty((len(sats), 6))

    def set_initial_state(self, sat_object, sat: str, sats: list):
        # Set initial conditions for the satellite that will be
        # propagated in this simulation. The initial conditions are given in
        # Keplerian elements and later on converted to Cartesian elements
        earth_gravitational_parameter = self.bodies.get("Earth").gravitational_parameter

        self.initial_state = element_conversion.keplerian_to_cartesian_elementwise(
            gravitational_parameter=earth_gravitational_parameter,
            semi_major_axis=sat_object.a,
            eccentricity=sat_object.e,
            inclination=sat_object.i,
            argument_of_periapsis=sat_object.omega,
            longitude_of_ascending_node=sat_object.OMEGA,
            true_anomaly=sat_object.nu,
        )

        self.initial_states[np.where(sats == sat)] = self.initial_state

    def finalise_initial_states(self):
        self.initial_states_settings = np.concatenate(self.initial_states)

    def define_vars_to_store(self, sat: str):
        # Define list of dependent variables to save
        self.dependent_variables_to_save = [
            propagation_setup.dependent_variable.total_acceleration(sat),
            propagation_setup.dependent_variable.keplerian_state(sat, "Earth"),
            propagation_setup.dependent_variable.latitude(sat, "Earth"),
            propagation_setup.dependent_variable.longitude(sat, "Earth"),
            #propagation_setup.dependent_variable.single_acceleration_norm(
            #    propagation_setup.acceleration.point_mass_gravity_type, sat, "Sun"
            #),
            #propagation_setup.dependent_variable.single_acceleration_norm(
            #    propagation_setup.acceleration.point_mass_gravity_type, sat, "Moon"
            #),
            # propagation_setup.dependent_variable.single_acceleration_norm(
            #     propagation_setup.acceleration.point_mass_gravity_type, sat, "Mars"
            # ),
            # propagation_setup.dependent_variable.single_acceleration_norm(
            #     propagation_setup.acceleration.point_mass_gravity_type, sat, "Venus"
            # ),
            propagation_setup.dependent_variable.single_acceleration_norm(
                propagation_setup.acceleration.spherical_harmonic_gravity_type, sat, "Earth"
            )#,
            #propagation_setup.dependent_variable.single_acceleration_norm(
            #    propagation_setup.acceleration.aerodynamic_type, sat, "Earth"
            #)#,
            #propagation_setup.dependent_variable.single_acceleration_norm(
            #    propagation_setup.acceleration.cannonball_radiation_pressure_type, sat, "Sun"
            #)
        ]

    def define_propagator_settings(self):
        # Create termination settings
        termination_condition = propagation_setup.propagator.time_termination(self.simulation_end_epoch)

        # Create numerical integrator settings
        fixed_step_size = 1.0
        integrator_settings = propagation_setup.integrator.runge_kutta_4(fixed_step_size)

        # Create propagation settings
        self.propagator_settings = propagation_setup.propagator.translational(
            self.central_bodies,
            self.acceleration_models,
            self.bodies_to_propagate,
            self.initial_state,
            self.simulation_start_epoch,
            integrator_settings,
            termination_condition,
            output_variables=self.dependent_variables_to_save
        )

    def simulate(self):
        # Create simulation object and propagate the dynamics
        dynamics_simulator = numerical_simulation.create_dynamics_simulator(
            self.bodies, self.propagator_settings
        )

        # Extract the resulting state and dependent variable history and convert it to an ndarray
        states = dynamics_simulator.state_history
        self.states_array = result2array(states)
        dep_vars = dynamics_simulator.dependent_variable_history
        self.dep_vars_array = result2array(dep_vars)

        self.time_hours = self.dep_vars_array[:, 0]/3600

    def plot_ground_track(self, sat_objects: list | np.ndarray, show_plot: bool = True, subset: int | None = None):
        for sat in sat_objects:
            if subset is None:
                latitude = np.rad2deg(self.dep_vars_array[:, 10]) + np.rad2deg(sat.OMEGA)
                longitude = np.rad2deg(self.dep_vars_array[:, 11])
            else:
                latitude = np.rad2deg(self.dep_vars_array[:, 10])[:subset] + np.rad2deg(sat.OMEGA)
                longitude = np.rad2deg(self.dep_vars_array[:, 11])[:subset]

            plt.scatter(longitude, latitude, s=1)

        if show_plot:
            plt.show()

    def create_plot(self, hours: float | int | None = None):
        if hours is None:
            subset = None
        else:
            subset = int(len(self.time_hours) / 24 * hours)
        plt.figure(figsize=(9, 5))
        plt.title(f"Ground track of satellite over {hours} hours")
        plt.xlabel('Longitude [deg]')
        plt.ylabel('Latitude [deg]')

        plt.yticks(np.arange(-91, 91, step=45))
        plt.xlim([-180, 180])
        plt.grid()
        plt.tight_layout()

        return subset

def set_up_and_run_tudat(sat_objects):
    sat1 = sat_objects[0]
    tudat_env = tudat_environment()
    tudat_env.create_sat(sat1, sat1.name)
    tudat_env.set_up_aerodynamics(sat1.name, sat1.reference_area, sat1.drag_coefficient)
    tudat_env.set_up_solar_pressure(sat1.name, sat1.radiation_reference_area, sat1.solar_pressure_coefficient)
    tudat_env.propagation_setup([sat1.name])
    tudat_env.set_up_acceleration([sat1.name])
    tudat_env.set_up_initial_states([sat1.name])
    tudat_env.set_initial_state(sat1, sat1.name, [sat1.name])
    tudat_env.finalise_initial_states()
    tudat_env.define_vars_to_store(sat1.name)
    tudat_env.define_propagator_settings()
    tudat_env.simulate()
    return tudat_env

if __name__ == "__main__":
    sat = satellite.load_sat(1)
    sat.reference_area = 2
    sat.drag_coefficient = 1
    sat.radiation_reference_area = 3
    sat.solar_pressure_coefficient = 0.5
    sat.mass = 1000
    print(sat.__dict__)
    tudat_env = set_up_and_run_tudat([sat])


import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# Parameters
w = 1
mu = 1
a = 1

x_base = 1
y_base = 1
r_base = np.sqrt(x_base ** 2 + y_base ** 2)

e = 0

# Initial conditions
x0 = 0
y0 = 2 * a

# Potential function
def get_numeric_potential(t, x1, x3, r_base):
    # Calculate potential using provided equation
    potential = mu / r_base ** 3 - w ** 2 + e * np.sin(f * t)
    return potential

# ODE system
# x1 = x
# x2 = x_dot
# x3 = y
# x4 = y_dot
def odes(t, z):
    # Unpack state
    x1, x2, x3, x4 = z

    # Get potential
    U = get_numeric_potential(t, x1, x3, r_base)

    # Calculate derivatives
    dxdt = [
        x2,
        2 * w * x4 - U * x1,
        x4,
        -2 * w * x2 - U * x3
    ]

    return dxdt

# Initial state
omega1 = -w - np.sqrt(mu / r_base ** 3)
x_dot0 = -2 * a * omega1
y_dot0 = 0
omega3 = -w + np.sqrt(mu / r_base ** 3)
f = omega3
z0 = [x0, x_dot0, y0, y_dot0]

# Specify time points
t = np.linspace(0, 10, 1000)

# Solve
sol = solve_ivp(odes, [0, 10], z0, t_eval=t)

# Plot
plt.plot(sol.t, sol.y[0], label='x(t)')
plt.plot(sol.t, sol.y[2], label='y(t)')
plt.xlabel('t')
plt.legend()
plt.show()

# Get x and y solution vectors
x = sol.y[0]
y = sol.y[2]

# Plot
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('x vs y')
plt.show()


import random
import sys

from line_profiler import LineProfiler
class SingleNode(object):
    """单链表的结点"""
    def __init__(self,item):
        self.item = item
        self.next = None

class SingleLinkList(object):
    """单链表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        return self._head == None

    def length(self):
        """链表长度"""
        cur = self._head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self._head
        while cur != None:
            print(cur.item , end=" ")
            cur = cur.next
        print("\n")

    def add(self, item):
        """头部添加元素"""
        node = SingleNode(item)
        node.next = self._head
        self._head = node

    def append(self, item):
        """尾部添加元素"""
        node = SingleNode(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def get(self, pos):
        """获取指定位置的元素"""
        if pos <= 0:
            return self._head
        cur = self._head
        count = 0
        while count < pos:
            count += 1
            cur = cur.next
        return cur

    def insert(self, pos, item):
        """指定位置添加元素"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = SingleNode(item)
            cur = self.get(pos - 1)
            node.next = cur.next
            cur.next = node

    def remove(self, pos):
        """删除节点"""
        if pos <= 0:
            self._head = self._head.next
        elif pos > (self.length() - 1):
            pass
        else:
            cur = self.get(pos - 1)
            cur.next = cur.next.next

    def search(self, item):
        """查找节点是否存在"""
        cur = self._head
        while cur != None:
            if cur.item == item:
                return True
            cur = cur.next
        return False
    '''
    单链表反转有两种办法
    1. 递归
    2. 非递归
    '''
    def reverse2(self):
        """反转链表 非递归"""
        cur = self._head
        pre = None
        while cur != None:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        self._head = pre

    def reverse1(self):
        """反转链表 递归"""
        self._reverse(self._head)

    def _reverse(self, head):
        """反转链表 递归"""
        if head==None or head.next == None :
            return head
        else:
            new_head = self._reverse(head.next)
            head.next.next = head
            head.next = None
            return new_head

    def sort(self):
        """排序"""
        if self.is_empty():
            return
        self._sort(self._head)

    def _sort(self, head):
        pass
        """排序
        if head==None or head.next == None:
            return head
        else:
            cur = head
            while cur.next != None:
                if cur.item > cur.next.item:
                    cur.item, cur.next.item = cur.next.item, cur.item
                cur = cur.next
            self._sort(head)
        """

if __name__ == "__main__":
    ll = SingleLinkList()
    lp = LineProfiler()
    #lp_wrapper = lp(ll.add)
    #lp_wrapper(1)
    #lp.print_stats()
    #ll.add(1)
    for i in range(10):
        ll.add(random.randint(0,1000))
    #ll.travel()
    ll.sort()
    ll.travel()

'''
    lp.add_function(ll.reverse2)
    lp.add_function(ll.reverse1)
    lp.enable()
    ll.reverse1()
    ll.reverse2()
    lp.disable()
    lp.print_stats(sys.stdout)

   '''

   # print ll.search(3)
   # print ll.search(5)
   # ll.remove(1)
   # print "length:",ll.length()
   # ll.travel()


import torch
import torch.nn as nn

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def vog_calc(trainloader, model,dataset_name):
    vog = {}
    for idx, batch in enumerate(trainloader):
        if idx >= 10:
            print(idx)
            break
        X,y = batch
        X, y = X.to(device), y.to(device)
        grad_X = X
        grad_Y = y
        grad_X.requires_grad = True
        logits = model(grad_X)
        celoss = nn.CrossEntropyLoss()
        loss = celoss(logits, grad_Y)
        loss.backward()
        sumMatrix = torch.sum(grad_X.grad, dim=0)

    sumMatrix /= grad_X.grad.shape[0] * len(trainloader)
    covMatrix = [torch.pow(covMatric - sumMatrix, 2) for covMatric in grad_X]
    covMatrix = sum(covMatrix)
    covMatrix /= len(trainloader)
    meanMatrix = torch.mean(covMatrix)
    print("Dataset_ {}: {}".format(dataset_name, meanMatrix.item()))

    # print(covGrad)

import torch.nn as nn
import torchvision
class MyResNet(nn.Module):

    def __init__(self, in_channels=1):
        super(MyResNet, self).__init__()

        # bring resnet
        self.model = torchvision.models.resnet18(pretrained=True)

        # original definition of the first layer on the renset class
        # self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)

        # your case
        self.model.conv1 = nn.Conv2d(in_channels, 64, kernel_size=7, stride=2, padding=3, bias=False)

    def forward(self, x):
        return self.model(x)

model = MyResNet()
model_rgb = torchvision.models.resnet18(pretrained=True)
import torch

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.MNIST(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)

testset = datasets.MNIST(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

model.to(device)
model = nn.DataParallel(model)
model.eval()

model_rgb.to(device)
model_rgb = nn.DataParallel(model_rgb)
model_rgb.eval()

vog = vog_calc(trainloader, model, "MNIST")

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.KMNIST(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model, "KMNIST")

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.FashionMNIST(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model, "FashionMNIST")
print(vog)

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.CIFAR10(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model_rgb, "CIFAR10")
print(vog)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import gridspec

import tensorflow as tf
# import tensorflow_probability as tfp

# conda install -c conda-forge bayesian-optimization
from bayes_opt import BayesianOptimization, UtilityFunction

# from IPython.display import clear_output
# import time

# Baysian Optimization : Exploitation / Exploration
def target(x):      # real_function
    return np.exp(-(x-2)**2) + np.exp(-(x-6)**2/10) + 1 / (x**2+1)

x_lp = np.linspace(-2, 10, 10000).reshape(-1,1)
y_lp = target(x_lp)

plt.plot(x_lp, y_lp)
plt.show()

# x_lp[np.argmax(y_lp)]

bayes_opt = BayesianOptimization(f=target, pbounds={'x': (-2,10)}, random_state=27)
# ?BayesianOptimization
# BayesianOptimization(f, pbounds, random_state=None, verbose=2)

bayes_opt.maximize(init_points=2, n_iter=12, acq='ucb', kappa=5)
# acq: acquisition_function('ucb...')이 내부적으로 돌아가서 최대가 되는 지점을 찾아줌
# kappa: Exploration 정도 지정      # ucb = mean + kappa * std
    # kappa ↑ → Exploration에 집중하겠다
# ?BayesianOptimization.maximize
# bayes_opt.maximize(
#     init_points=5,
#     n_iter=25,
#     acq='ucb',
#     kappa=2.576,
#     xi=0.0,
#     **gp_params,
# )

# dir(bayes_opt)
bayes_opt.max           # max_point (best_case)
bayes_opt._gp           # setting parameter
bayes_opt.res           # history
len(bayes_opt.space)    # iter횟수

x_res = np.array([res['params']['x'] for res in bayes_opt.res])
y_res = np.array([res['target'] for res in bayes_opt.res])

plt.plot(x_lp, y_lp, label='target')
plt.plot(x_res, y_res, 'r--', marker='D', alpha=0.5, label='Observations')
plt.show()

fitted = bayes_opt._gp.fit(x_res[...,np.newaxis], y_res)
fitted
bayes_opt._gp.predict(x_lp, return_std=True)

def posterior(optimizer, x_obs, y_obs, grid):
    optimizer._gp.fit(x_obs, y_obs)

    mu, sigma = optimizer._gp.predict(grid, return_std=True)
    return mu, sigma

def plot_gp(optimizer, x, y):
    fig = plt.figure(figsize=(16, 10))
    steps = len(optimizer.space)    # 현재 몇번 iteration 했는지?
    fig.suptitle(f'Gaussian Process and Utility Function After {steps} steps')

    gs = gridspec.GridSpec(2, 1, height_ratios=[3,1])
    axis = plt.subplot(gs[0])
    acq = plt.subplot(gs[1])

    # bayesian optimization으로 현재까지 관측된 x, y값
    x_obs = np.array([[res['params']['x']] for res in optimizer.res])
    y_obs = np.array([res['target'] for res in optimizer.res])

    mu, sigma = posterior(optimizer, x_obs, y_obs, x)

    # plot function
    axis.plot(x, y, linewidth=3, label='target')        # 실제 함수
    axis.plot(x_obs.flatten(), y_obs, 'D', markersize=8, label='Observations', color='r')   # 현재 관측된 값 ◆
    axis.plot(x, mu, '--', color='k', label='Prediction')
    axis.fill(np.concatenate([x, x[::-1]]),
            np.concatenate([mu - 1.9600 * sigma, (mu + 1.9600 * sigma)[::-1]]),
            alpha=0.6, fc='c', ec='None', label='95% confidence interval'
        )
    axis.set_xlim((-2, 10))
    axis.set_ylim((None, None))
    axis.set_xlabel('x', fontdict={'size':20})
    axis.set_ylabel('f(x)', fontdict={'size':20})
    axis.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)

    # acquition function
    util_func = UtilityFunction(kind='ucb', kappa=5, xi=0)
    utility = util_func.utility(x=x, gp=optimizer._gp, y_max=0)
    acq.plot(x, utility, color='purple', label='Utility Function')
    acq.plot(x[np.argmax(utility)], np.max(utility), '*',
        markersize=15, markerfacecolor='gold',
        markeredgecolor='k', markeredgewidth=1, label='NExt Best Gauess')
    acq.set_xlim((-2,10))
    acq.set_ylim((0, np.max(utility)+0.5))
    acq.set_xlabel('x', fontdict={'size': 20})
    acq.set_ylabel('Utility', fontdict={'size': 20})
    acq.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)
    plt.show()

bayes_opt = BayesianOptimization(f=target, pbounds={'x': (-2,10)}, random_state=27)
bayes_opt.maximize(init_points=0, n_iter=1, acq='ucb', kappa=5)
plot_gp(bayes_opt, x_lp, y_lp)

# Cifar10 Data에 HyperParameter Optimize
(x_trainval, y_trainval), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
print(x_trainval.shape, y_trainval.shape, x_test.shape, y_test.shape)

x_trainval = x_trainval.astype('float32')/255.0
x_test = x_test.astype('float32')/255.0

y_trainval = tf.one_hot(y_trainval.squeeze(), 10)
y_test = tf.one_hot(y_test.squeeze(), 10)
print(x_trainval.shape, y_trainval.shape, x_test.shape, y_test.shape)

x_train = x_trainval[:1000]
y_train = y_trainval[:1000]

x_valid = x_trainval[49000:]
y_valid = y_trainval[49000:]

print(x_train.shape, y_train.shape, x_valid.shape, y_valid.shape, x_test.shape, y_test.shape)

train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(2000)
# valid_dataset = tf.data.Dataset.from_tensor_slices((x_valid, y_valid)).batch(2000)
# test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(2000)

def build_network(num_layers_conv,
                num_layers_dense,
                num_channels_cnn,
                num_nodes_dense):
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Input(shape=(32,32,3)))

    # Conv_layers
    for i in range(num_layers_conv):
        model.add(tf.keras.layers.Conv2D(num_channels_cnn, kernel_size=(3,3),
                strides=1, padding='same', activation='relu'))
    model.add(tf.keras.layers.Flatten())

    # Dense_layers
    for i in range(num_layers_dense):
        model.add(tf.keras.layers.Dense(num_nodes_dense, activation='relu'))

    # output_layers
    model.add(tf.keras.layers.Dense(10))
    return model

def build_and_optimize(num_layers_conv,
                num_layers_dense,
                num_channels_cnn,
                num_nodes_dense,
                log_learning_rate):
    num_layers_conv = int(num_layers_conv)
    num_layers_dense = int(num_layers_dense)
    num_channels_cnn = int(num_channels_cnn)
    num_nodes_dense = int(num_nodes_dense)
    learning_rate = np.exp(log_learning_rate)

    # print(f'num_layers_conv: {num_layers_conv}')
    # print(f'num_layers_dense: {num_layers_dense}')
    # print(f'num_channels_cnn: {num_channels_cnn}')
    # print(f'num_nodes_dense: {num_nodes_dense}')
    # print(f'learning_rate: {learning_rate}')

    model = build_network(num_layers_conv, num_layers_dense,
                num_channels_cnn, num_nodes_dense)
    model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate),
                loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
    model.fit(train_dataset, epochs=10, verbose=0)
    loss, accuracy = model.evaluate(x_valid, y_valid, verbose=0)
    # print(f'accuracy: {accuracy}')
    return accuracy

bound = {'num_layers_conv': (2, 5.9),
        'num_layers_dense': (2, 4.9),
        'num_channels_cnn': (32, 128.9),
        'num_nodes_dense': (32, 256.9),
        'log_learning_rate': (-5,-1)}

bayes_optimizer = BayesianOptimization(f=build_and_optimize, pbounds=bound, random_state=7)
bayes_optimizer.maximize(init_points=2, n_iter=10, kappa=5)

bayes_optimizer.max # best_case

acc_frame = pd.Series([res['target'] for res in bayes_optimizer.res], name='accuracy').to_frame()
params_frame = pd.DataFrame([res['params'] for res in bayes_optimizer.res])
bayesian_frame = pd.concat([acc_frame, params_frame], axis=1)
bayesian_frame

# models = build_network(2, 4, 3, 3)
# models.compile(optimizer=tf.keras.optimizers.SGD(0.001),
#                 loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
#                 metrics=['accuracy'])
# models.fit(train_dataset, epochs=10, verbose=2)
# models.evaluate(x_valid, y_valid)

52_Deep_Learning/[POSTECH AI] DeepLearning (Tensorflow)/200917_p18_AutoML (Bayesian_Optimization).py


"""Basis functionality that should always be present."""
import re
import pytest
import requests
from playwright.sync_api import expect

FOOTER_TEXT_EN = "Internet.nl is an initiative of the Internet community and the Dutch"
FOOTER_TEXT_NL = "Internet.nl is een initiatief van de internetgemeenschap en de Nederlandse"

SECURITY_TXT_TEXT = "Policy: https://internet.nl/disclosure/"

ROBOTS_TXT_TEXT = "Disallow: /site/"

def test_index_http_ok(page, app_url_subdomain):
    response = page.request.get(app_url_subdomain)
    expect(response).to_be_ok()

@pytest.mark.parametrize(
    ("app_url", "footer_text"),
    [("https://en.internet.test", FOOTER_TEXT_EN), ("https://nl.internet.test", FOOTER_TEXT_NL)],
)
def test_index_footer_text_present(page, app_url, footer_text):
    page.goto(app_url)
    footer = page.locator("#footer")

    assert footer_text in footer.text_content()

def test_security_txt(page, app_url_subdomain):
    page.goto(app_url_subdomain + "/.well-known/security.txt")

    assert SECURITY_TXT_TEXT in page.content()

def test_robots_txt(page, app_url_subdomain):
    page.goto(app_url_subdomain + "/robots.txt")

    assert ROBOTS_TXT_TEXT in page.content()

def test_favicon_ico(page, app_url_subdomain):
    response = page.request.get(app_url_subdomain + "/favicon.ico")
    expect(response).to_be_ok()

def test_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/logo_en.png", verify=False)
    response.raise_for_status()

def test_generated_css_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/css/style-min.css", verify=False)
    response.raise_for_status()
    assert "@font-face" in response.text
    assert "expires" in response.headers

def test_generated_js_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/js/menu-min.js", verify=False)
    response.raise_for_status()
    assert "hideMenuButton" in response.text
    assert "expires" in response.headers

@pytest.mark.parametrize(
    "path",
    ["/grafana", "/prometheus", "/prometheus/targets"],
)
def test_monitoring_auth(page, app_url, path):
    """Monitoring endpoints must be behind basic auth."""

    response = requests.get(app_url + path, verify=False)
    assert response.status_code == 401

    # MONITORING_AUTH provided in docker/test.env
    auth = ("test", "test")

    response = requests.get(app_url + path, auth=auth, verify=False)
    response.raise_for_status()

def test_monitoring_auth_raw(page, app_url):
    """Monitoring endpoints must be behind basic auth."""
    path = "/grafana"

    response = requests.get(app_url + path, verify=False)
    assert response.status_code == 401

    # MONITORING_AUTH_RAW provided in docker/test.env
    auth = ("test_raw", "test_raw")

    response = requests.get(app_url + path, auth=auth, verify=False)
    response.raise_for_status()

def test_no_server_banner(page, app_url_subdomain):
    response = requests.get(app_url_subdomain, verify=False)
    assert response.headers["server"] == "nginx"

def test_http_redirect_https(page, app_url_subdomain):
    response = requests.get(app_url_subdomain.replace("https", "http"), allow_redirects=False)
    assert response.status_code == 301
    assert re.match(app_url_subdomain, response.headers["location"])

def test_nowww_class_b(page, app_domain, app_url):
    response = requests.get(f"https://www.{app_domain}", allow_redirects=False, verify=False)
    assert response.status_code == 301
    assert response.headers["location"] == f"{app_url}/"

def test_additional_redirect_domains(page, app_url):
    """Additional configured redirect subdomains should redirect to the frontpage."""
    response = requests.get("https://platforminternet.test", allow_redirects=False, verify=False)
    assert response.status_code == 301
    assert response.headers["location"] == f"{app_url}/"

def test_default_sni_none(app_domain):
    """Default vhost should 404 on any non explicitly configured domain. #894"""

    not_configured_domain = "telefax.test"

    # make a https request to the webserver's adres but request a vhost that is not configured
    response = requests.get(
        f"https://{app_domain}", headers={"Host": not_configured_domain}, verify=False, allow_redirects=False
    )
    assert response.status_code == 404

def test_conn_over_https_no_hsts(app_domain):
    """Serving conn. over HTTPS should disable HSTS and downgrade to HTTP. #894"""

    # make a https request to the webserver's adres but request a vhost that is not configured
    response = requests.get(f"https://conn.{app_domain}", verify=False, allow_redirects=False)
    assert response.status_code == 301
    assert response.headers["Strict-Transport-Security"] == "max-age=0;"
    assert response.headers["location"] == f"http://conn.{app_domain}"

@pytest.mark.parametrize(
    ("from_language", "to_language", "footer_text"),
    [("nl", "en", FOOTER_TEXT_EN), ("en", "nl", FOOTER_TEXT_NL)],
)
def test_change_language(page, app_domain, from_language, to_language, footer_text):
    """Test clicking the language change button."""

    page.goto(f"https://{from_language}.{app_domain}")
    page.locator("#language-switch-header-container button:not(:disabled)").click()
    page.wait_for_url(f"https://{to_language}.internet.test/")

    footer = page.locator("#footer")
    assert footer_text in footer.text_content()

@pytest.mark.parametrize(
    ("language", "footer_text"),
    [("en", FOOTER_TEXT_EN), ("nl", FOOTER_TEXT_NL)],
)
def test_accept_language_header(page, app_domain, language, footer_text):
    """Browser preferred language should be respected."""

    page.set_extra_http_headers({"Accept-Language": language})
    page.goto(f"https://{app_domain}")

    footer = page.locator("#footer")
    assert footer_text in footer.text_content()


from functools import reduce
from operator import add
from flask import Flask, render_template, url_for, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from wtforms import Form, BooleanField, StringField, validators, IntegerField
from wtforms.fields.core import Field, FieldList, FormField, SelectField
from wtforms.ext.sqlalchemy.fields import QuerySelectField

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)

class Elo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    score = db.Column(db.Integer)
    name = db.Column(db.String(200), nullable=False)

    def __repr__(self):
        return self.name

class EloAddForm(Form):
    name = StringField('Name')
    score = IntegerField('Score')

class PlayerAddForm(Form):
    elos = Elo.query.order_by(-(Elo.score)).all()
    player = QuerySelectField(query_factory=lambda: Elo.query)

added_players = []

class PlaceForm(Form):
    place = SelectField('Place', coerce=int)

@app.route('/', methods=['POST', 'GET'])
def index():
    eloaddform = EloAddForm(request.form)
    playeraddform = PlayerAddForm()
    placeform = PlaceForm()
    placeform.place.choices = list(range(1, len(added_players)+1))

    if(request.method == 'POST'):
        elo_name = eloaddform.name.data
        elo_score = eloaddform.score.data
        new_elo = Elo(score = elo_score, name = elo_name )

        try:
            db.session.add(new_elo)
            db.session.commit()
            return redirect('/')
        except:
            return 'There was a problem adding your elo'

    else:
        all_elos = Elo.query.order_by(-(Elo.score)).all()
        return render_template('index.html', elos = all_elos, eloaddform = eloaddform, playeraddform = playeraddform, players = added_players, placeform = placeform)

@app.route('/delete/<int:id>')
def delete(id):
    elo_to_delete = Elo.query.get_or_404(id)

    try:
        db.session.delete(elo_to_delete)
        db.session.commit()
        return redirect('/')
    except:
        return 'There was a problem deleting this elo'

@app.route('/add_player/', methods=['POST', 'GET'])
def add_player():
    playeraddform = PlayerAddForm(request.form)

    if(request.method == 'POST'):
        added_players.append(playeraddform.player.data)
        return redirect('/')

@app.route('/calc_elo/', methods=['POST', 'GET'])
def calc_elo():
    placeform = PlaceForm(request.form)
    game_size = len(added_players)
    places = []
    if(request.method == 'POST'):
        places = list(map(int, request.form.getlist('place')))

        for i in range(game_size):
            elo_sum = 0
            for j in range(game_size):
                isWin = 0
                if j != i:
                    if places[i] < places[j]:
                        isWin = 1
                    expected = 1/(1 + pow(10, (added_players[j].score-added_players[i].score)/400))
                    elo_sum += added_players[i].score+32*(isWin - expected)

            Elo.query.filter_by(name=added_players[i].name).first().score = int(elo_sum/(game_size-1))

        db.session.commit()
        added_players.clear()

    return redirect('/')

if __name__ == "__main__":
    app.run(debug=True)


#!/usr/bin/env python
"""Load OBP chapter metadata into Thoth"""

import re
import logging

from bookloader import BookLoader
from chapterloader import ChapterLoader

class ObpChapterLoader(ChapterLoader):
    """OBP specific logic to ingest chapter metadata from CSV into Thoth"""
    publisher_name = "Open Book Publishers"
    contributors_limit = 1  # lookup not needed in this workflow
    institutions_limit = 1

    def run(self):
        """Process CSV and call Thoth to insert its data"""
        book_doi = self.data.at[0, 'doi'].strip().lower()[:-3]  # OBP chapter DOIs are book's + ".00"
        book_id = self.get_work_by_doi(book_doi)['workId']

        relation_ordinal = 1
        for row in self.data.index:
            work = self.get_work(row, self.imprint_id)
            logging.info(work)
            work_id = self.thoth.create_work(work)
            logging.info('Created chapter %s: %s (%s)' % (relation_ordinal, work['fullTitle'], work_id))
            self.create_languages(row, work_id)
            self.create_contributors(row, work_id)
            self.create_chapter_relation(book_id, work_id, relation_ordinal)
            relation_ordinal += 1

    def get_work(self, row, imprint_id):
        """Returns a dictionary with all attributes of a 'work'

        row: current row number

        imprint_id: previously obtained ID of this work's imprint
        """
        title = self.data.at[row, 'title']
        subtitle = self.data.at[row, 'subtitle']
        title = self.sanitise_title(title, subtitle)
        doi = self.data.at[row, 'doi'].strip().lower()

        cc_license = "https://creativecommons.org/licenses/{}/4.0/".format(self.data.at[row, 'license'].lower())

        # Produce landing page based on OBP's convention
        chapter_doi = doi.replace("https://doi.org/", "")
        book_doi = chapter_doi[:-3]
        landing_page = f"https://www.openbookpublishers.com/books/{book_doi}/chapters/{chapter_doi}"

        page_count = int(self.data.at[row, "page_count"]) \
            if self.data.at[row, "page_count"] else None
        first_page = str(self.data.at[row, "first_page"]) \
            if self.data.at[row, "first_page"] else None
        last_page = str(self.data.at[row, "last_page"]) \
            if self.data.at[row, "last_page"] else None
        page_interval = None
        if first_page and last_page:
            page_interval = "{}–{}".format(first_page, last_page)
        abstract = self.data.at[row, "long_abstract"].strip() \
            if self.data.at[row, "long_abstract"] else None

        work = {
            "workType": "BOOK_CHAPTER",
            "workStatus": "FORTHCOMING",
            "fullTitle": title["fullTitle"],
            "title": title["title"],
            "subtitle": title["subtitle"],
            "reference": None,
            "edition": None,
            "imprintId": imprint_id,
            "doi": doi,
            "publicationDate": None,
            "place": "Cambridge, UK",
            "width": None,
            "height": None,
            "pageCount": page_count,
            "pageBreakdown": None,
            "imageCount": None,
            "tableCount": None,
            "audioCount": None,
            "videoCount": None,
            "license": cc_license,
            "copyrightHolder": self.data.at[row, "copyright_holder"],
            "landingPage": landing_page,
            "lccn": None,
            "oclc": None,
            "shortAbstract": None,
            "longAbstract": abstract,
            "generalNote": None,
            "bibliographyNote": None,
            "toc": None,
            "coverUrl": None,
            "coverCaption": None,
            "firstPage": first_page,
            "lastPage": last_page,
            "pageInterval": page_interval
        }
        return work

    def create_languages(self, row, work_id):
        """Creates all languages associated with the current work

        row: current row number

        work_id: previously obtained ID of the current work
        """
        for index in range(1, 4):
            try:
                language = {
                    "workId": work_id,
                    "languageCode": self.data.at[row, f"language_code_{index}"],
                    "languageRelation": self.data.at[row, f"language_relation_{index}"].upper(),
                    "mainLanguage": "true" if self.data.at[row, f"main_language_{index}"] == "Yes" else "false",
                }
                language_id = self.thoth.create_language(language)
                logging.info(f"Language: {language_id}")
            except AttributeError:
                continue

    def create_contributors(self, row, work_id):
        """Creates all contributions associated with the current work

        row: current row number

        work_id: previously obtained ID of the current work
        """
        for index in range(1, 8):
            contributor_id = self.data.at[row, f"contributor_id_{index}"]
            if not contributor_id:
                continue
            contributor_id = contributor_id.strip()
            contribution_type = BookLoader.contribution_types[self.data.at[row, f"contribution_type_{index}"].strip()]
            main_contribution = "true" if self.data.at[row, f"main_contribution_{index}"].strip() == "Yes" else "false"
            biography = self.data.at[row, f"biography_{index}"].strip() if self.data.at[row, f"biography_{index}"] else None

            contributor = self.thoth.contributor(contributor_id)

            contribution = {
                "workId": work_id,
                "contributorId": contributor_id,
                "contributionType": contribution_type,
                "mainContribution": main_contribution,
                "biography": biography,
                "institution": None,
                "firstName": contributor['firstName'],
                "lastName": contributor['lastName'],
                "fullName": contributor['fullName'],
                "contributionOrdinal": index
            }
            contribution_id = self.thoth.create_contribution(contribution)
            logging.info(f"Contribution: {contribution_id}")

            # now create affiliations
            for affiliation_ordinal in range(1, 4):
                institution_id = self.data.at[row, f"institution_id_{index}_{affiliation_ordinal}"]
                if not institution_id:
                    continue
                institution_id = institution_id.strip()
                position = self.data.at[row, f"position_{index}_{affiliation_ordinal}"].strip()

                affiliation = {
                    "contributionId": contribution_id,
                    "institutionId": institution_id,
                    "position": position,
                    "affiliationOrdinal": affiliation_ordinal
                }
                affiliation_id = self.thoth.create_affiliation(affiliation)
                logging.info(f"Affiliation {affiliation_id}")


import numpy as np
import scipy.stats
import scikit_posthocs as sp
import matplotlib.pyplot as plt

cmap = ['1', '#fb6a4a', 'mediumseagreen', 'limegreen', 'palegreen']
heatmap_args = {'cmap':cmap, 'linewidths': 0.5, 'linecolor': '0.3', 'clip_on': False, 'square': True, 'cbar_ax_bbox': [0.80, 0.35, 0.04, 0.3]}

# Verification of statistical tests with known distributions
# x = np.array([np.random.normal(loc=00.0, scale=1.0, size=30),
              # np.random.normal(loc=19.5, scale=1.0, size=30),
              # np.random.normal(loc=20.0, scale=1.0, size=30)])
# print(np.shape(x))
# fr_test = scipy.stats.friedmanchisquare(*x)
# print(fr_test)
# nm_posthoc = sp.posthoc_nemenyi_friedman(x.T)
# print(nm_posthoc)
# sp.sign_plot(nm_posthoc, **heatmap_args)
# exit()

function_evals = [i * 100 for i in range(1,101)] + [11000 + i * 1000 for i in range(90)]
function_evals_of_interest = [1e3, 1e4, 1e5]
evals_mask = [eval in function_evals_of_interest for eval in function_evals]

for system_order in ['finite', 'infinite']:
    print(system_order.upper())

    for eval in range(len(function_evals_of_interest)):
        algorithms_at_fes = []
        for algorithm in ['sa', 'acfsa', 'pso', 'aiwpso', 'acor', 'baacor']:
            print(algorithm)
            # Load test costs of a given metaheuristic for a given system, considering some number of objective function evaluations
            base_filename   = './results/' + algorithm + '_' + system_order
            test_costs_mat  = np.load(base_filename + '_test_costs.npy')
            test_costs_of_interest = test_costs_mat[:, evals_mask]
            costs_fe = test_costs_of_interest[:, eval]

            algorithms_at_fes.append(list(costs_fe))
            print(str(function_evals_of_interest[eval]) + ':  \t' + str(np.mean(costs_fe)))

        algorithms_at_fes = np.array(algorithms_at_fes)
        print('\n Statistical significance')
        print(np.shape(algorithms_at_fes))
        print('Friedman p-val = ' + str(scipy.stats.friedmanchisquare(*algorithms_at_fes)[1]) + '\n\n')
        nm_posthoc = sp.posthoc_nemenyi_friedman(algorithms_at_fes.T)
        plt.figure()
        sp.sign_plot(nm_posthoc, **heatmap_args)
        plt.show()
        print('\n')


import numpy as np
import matplotlib.pyplot as plt

cool = np.loadtxt('Cool_Down.txt')
time_cool = cool[:,0]
time_cool-=time_cool[0]
temp_cool = cool[:,1]
time_cool_clipped = time_cool[time_cool>23]
temp_cool = temp_cool[time_cool>23]
time_cool_clipped-=time_cool_clipped[0]

plt.figure()

###Initial Guess
residual_optimal = 1e200

###Time Constant
Ta = -8.44
T0 = 26.5
time_cool_sim = np.linspace(0,time_cool_clipped[-1],1000)
for TsC in np.linspace(1,1000,100):
    plt.cla()

    #TsC = 720-t0
    tauC = TsC/4.0

    ##Plot raw data
    plt.plot(time_cool_clipped,temp_cool,'b*',label='Measured Data')

    ##Clean up
    plt.grid()
    plt.xlabel('Time (sec)')
    plt.ylabel('Temperature (C)')

    temp_cool_sim = (Ta-T0)*(1-np.exp(-(1/tauC)*time_cool_sim)) + T0

    temp_cool_interpolate = (Ta-T0)*(1-np.exp(-(1/tauC)*time_cool_clipped)) + T0

    residuals = (temp_cool_interpolate - temp_cool)**2

    print(TsC,np.sum(residuals))

    if np.sum(residuals) < residual_optimal:
        residual_optimal = np.sum(residuals)
        print('New Optimum found')
        tauOpt = tauC
        temp_cool_opt = (Ta-T0)*(1-np.exp(-(1/tauOpt)*time_cool_sim)) + T0

    plt.plot(time_cool_sim,temp_cool_sim,'r-',label='Fitted Data')
    plt.plot(time_cool_sim,temp_cool_sim,'rs',label='Interpolated Data')

    ##plot the optimal solution in green
    plt.plot(time_cool_sim,temp_cool_opt,'y-',label='Optimal Solution')

    ###Least Square Regression
    ### cost function = J = residuals
    ### Minimizes J
    ### Spits out the solution to minimizing res
    ### Compute r^2 OR minimize res

    plt.legend()
    plt.pause(0.0001)

print('Optimal tau =',tauOpt)
plt.show()


#!/usr/bin/env python3

# Script Name:                  ops401d8-day37
# Author:                       Jonathan McMullin
# Date of latest revision:      08/29/2023
# Purpose:                      Cookie Capture Tool

# Credit: Utilized syntax from Code Fellows Demo and ChatGPT to develop this script

# Note: You will need to have Firefox and the Geckodriver

import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

targetsite = input("Enter target site url: ")
response = requests.get(targetsite)
cookie = response.cookies

def bringforthcookiemonster(): # Because why not!
    print('''

              .---. .---.
             :     : o   :    me want cookie!
         _..-:   o :     :-.._    /
     .-''  '  `---' `---' "   ``-.
   .'   "   '  "  .    "  . '  "  `.
  :   '.---.,,.,...,.,.,.,..---.  ' ;
  `. " `.                     .' " .'
   `.  '`.                   .' ' .'
    `.    `-._           _.-' "  .'  .----.
      `. "    '"--...--"'  . ' .'  .'  o   `.

        ''')

def save_html_response(response_text):
    with open('response.html', 'w', encoding='utf-8') as f:
        f.write(response_text)

def open_html_with_firefox():
    options = Options()
    options.headless = True  # Set to False if you want to run Firefox in GUI mode
    driver = webdriver.Firefox(options=options)
    driver.get('file://' + 'response.html')

bringforthcookiemonster()
print("Target site is " + targetsite)
print(cookie)

# Send the cookie back to the site and receive an HTTP response
response_with_cookie = requests.get(targetsite, cookies=cookie)

# Generate a .html file to capture the contents of the HTTP response
save_html_response(response_with_cookie.text)

# Open it with Firefox
open_html_with_firefox()

# End


"""Translate english to chinese via a dict."""
import copy
from typing import List, Union

# from word_tr import word_tr
from .json_de2zh import json_de2zh

# fmt: off
def de2zh(
        text: Union[str, List[List[str]]],
) -> List[str]:
    # fmt: on
    """Translate english to chinese via a dict.

    Args
        text: to translate, list of list of str

    Returns
        res: list of str
    """
    res = copy.deepcopy(text)
    if isinstance(text, str):
        res = [text.split()]

    # if res and isinstance(res[0], str):
        # res = [line.lower().split() for line in res]

    res = ["".join([json_de2zh(word) for word in line]) for line in res]

    return res


from flask import Flask, abort, Response, request
from socket import *

app = Flask(__name__)

@app.route('/')
def initialize():
    return "You should visit /fibonacci with several parameters to obtain the IP address"

@app.route('/register', methods=["PUT"], endpoint="register")
def register():
    data = request.json
    hostname = data.get("hostname")
    ip = data.get("ip")
    as_ip = data.get("as_ip")
    as_port = data.get("as_port")

    if not all((hostname, ip, as_ip, as_port)):
        abort(400, "Missing Parameters!")

    dns_Message = f"TYPE=A\nNAME={hostname}\nVALUE={ip}\nTTL=10"
    address = (as_ip, int(as_port))

    fibonacciSocket = socket(AF_INET, SOCK_DGRAM)
    fibonacciSocket.sendto(dns_Message.encode(), address)

    response, addr = fibonacciSocket.recvfrom(2048)
    print(response.decode())

    return Response("Registration Finished!", status=201)

@app.route('/fibonacci', methods=["GET"], endpoint="fibonacci")
def fibonacci():
    num = request.args.get("number")

    if not num:
        abort(400, "Missing Parameters")
    elif not num.isdigit():
        abort(400, "Wrong Parameter Type")

    num = int(num)

    def fib(n):
        a, b = 1, 1
        for i in range(n - 1):
            a, b = b, a + b
        return a

    return str(fib(num))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9090, debug=True)


from core.generics.generic import BaseAkModel
from django.db import models
from django.utils.translation import gettext as _
from evaluation.nom_types import (APP_LABEL, GROUP_TYPES,
    GROUP_TYPES_DEFAULT, GROUP_STATES, GROUP_STATES_DEFAULT)
from study_plan.models import (AcademicYear, SchoolPeriod,
                               StudyPlanOrganization, SubjectVersion, SubjectType)
from planning.models import Course
from core.models import EducationType, StructureActivityType, EducationLevelType

from structure.models import EducativeCenter, OrganizatinalUnit, SpecialityModality
from .mdl_study_group import StudyGroup

class SchoolGroup(BaseAkModel):
    """
        It gathers school groups that are created in an educational center and
        where students are enrolled according to their study plan.
    """
    educative_center = models.ForeignKey(
        EducativeCenter,
        on_delete=models.CASCADE,
        db_column='id_centro_educacional',
        verbose_name=_('Educative center')
    )

    organizational_unit = models.ForeignKey(
        OrganizatinalUnit,
        on_delete=models.CASCADE,
        db_column='id_unidad_organizativa',
        verbose_name=_('Organizational unit')
    )

    subject_version = models.ForeignKey(
        SubjectVersion,
        on_delete=models.CASCADE,
        db_column='id_version_asignatura',
        verbose_name=_('Subject version')
    )

    subject_type = models.ForeignKey(
        SubjectType,
        on_delete=models.CASCADE,
        db_column='id_tipo_asignatura',
        verbose_name=_('Subject type')
    )

    study_plan_organization = models.ForeignKey(
        StudyPlanOrganization,
        on_delete=models.CASCADE,
        db_column='id_organizacion_plan_estudio',
        verbose_name=_('Study plan organization')
    )

    academic_year = models.ForeignKey(
        AcademicYear,
        on_delete=models.CASCADE,
        db_column='id_anno_academico',
        verbose_name=_('Academic year')
    )

    school_period = models.ForeignKey(
        SchoolPeriod,
        on_delete=models.CASCADE,
        db_column='id_periodo_lectivo',
        verbose_name=_('School period')
    )

    study_group = models.ForeignKey(
        StudyGroup,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        default=None,
        db_column='id_grupo_estudio',
        verbose_name=_('Study Group')
    )

    course = models.ForeignKey(
        Course,
        on_delete=models.CASCADE,
        db_column='id_curso',
        verbose_name=_('Course')
    )

    group_type = models.CharField(
        max_length=100,
        default=GROUP_TYPES_DEFAULT,
        choices=GROUP_TYPES,
        db_column='tipo_grupo',
        verbose_name=_('Group type')
    )

    group_state = models.CharField(
        max_length=100,
        default=GROUP_STATES_DEFAULT,
        choices=GROUP_STATES,
        db_column='estado_grupo',
        verbose_name=_('Group state')
    )

#    education = models.ForeignKey(
#        EducationType,
#        on_delete=models.CASCADE,
#        null=True,
#        blank=True,
#        verbose_name=_('education_type'),
#        db_column='id_educacion')

#    activity = models.ForeignKey(
#        StructureActivityType,
#        on_delete=models.CASCADE,
#        null=True,
#        blank=True,
#        verbose_name=_('activity'),
#        db_column='id_actividad_estructura')

#    education_level_type = models.ForeignKey(
#        EducationLevelType,
#        on_delete=models.CASCADE,
#        null=True,
#        blank=True,
#        verbose_name=_('education_level_type'),
#        db_column='id_nivel_educativo')

#    speciality = models.ForeignKey(
#        SpecialityModality,
#        on_delete=models.CASCADE,
#        null=True,
#        blank=True,
#        verbose_name=_('speciality'),
#        db_column='id_especialidad')

    class Meta:
        verbose_name = _('School Group')
        verbose_name_plural = _('School Groups')
        db_table = f'{APP_LABEL.lower()}_tbd_grupo_docente'

    def __str__(self):
        return f'{self.name}'


# coding: utf-8
from PIL import Image
from torch.utils.data import Dataset
import torch
import pandas as pd

def age_class(age):
    if age<60:
        age=0
    if age<65 and age>=60:
        age=1
    if age<70 and age>=65:
        age=2
    if age<75 and age>=70:
        age=3
    return age
class MyDataset(Dataset):
    def __init__(self, txt_path, transform=None, target_transform=None):
        data = pd.read_csv(txt_path)
        imgs, age, gender, bmi = data['root'], data['age'], data['gender'], data['bmi']

        self.imgs = imgs
        self.age = age
        self.gender = gender
        self.bmi = bmi

        self.transform = transform
        self.target_transform = target_transform

    def __getitem__(self, index):
        fn, age, gender, bmi = self.imgs[index], self.age[index], self.gender[index], self.bmi[index]
        img = Image.open(fn).convert('RGB')  # 像素值 0~255，在transfrom.totensor会除以255，使像素值变成 0~1
        age=age_class(age)
        if self.transform is not None:
            img = self.transform(img)

        return img, torch.tensor(age, dtype=torch.int64), torch.tensor(gender, dtype=torch.int64), \
               torch.tensor(bmi, dtype=torch.float64)

    def __len__(self):
        return len(self.imgs)


from sklearn.datasets import load_files
from keras.utils import np_utils
import numpy as np
from keras.preprocessing import image
from tqdm import tqdm
from PIL import ImageFile
from numpy import save

num_classes = 2
img_width, img_height, channels = 48, 48, 3

def load_dataset(path, shuffle):
    data = load_files(path,shuffle=shuffle)
    condition_files = np.array(data['filenames'])
    print(len(condition_files))
    condition_targets = np_utils.to_categorical(np.array(data['target']), num_classes)
    return condition_files, condition_targets

def path_to_tensor(img_path):
    img = image.load_img(img_path, target_size=(img_width, img_height))
    x = image.img_to_array(img)
    return np.expand_dims(x, axis=0)

def paths_to_tensor(img_paths):
    list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
    return np.vstack(list_of_tensors)

# load train, test, and validation datasets
train_files, train_targets = load_dataset('training', True)
valid_files, valid_targets = load_dataset('validation', True)
test_files, test_targets = load_dataset('testing', True)

ImageFile.LOAD_TRUNCATED_IMAGES = True

train_tensors = paths_to_tensor(train_files).astype('float32')/255
valid_tensors = paths_to_tensor(valid_files).astype('float32')/255
test_tensors = paths_to_tensor(test_files).astype('float32')/255

save('train_data.npy', train_tensors)
save('train_targets.npy', train_targets)
save('test_data.npy', test_tensors)
save('test_targets.npy', test_targets)
save('valid_data.npy', valid_tensors)
save('valid_targets.npy', valid_targets)


#################################################################################
#
# pokemon.py
#
# A simple command line Python app to get information on your favourite Pokemons!
#
# Requirement: Please install the requests package by running
#   pip install requests
#
#################################################################################

import requests

# This function returns the Pokemon's information as a dictionary.
# Information is retrieved from the https://pokeapi.co/api/v2/pokemon/ endpoint.
def get_pokemon(name : str) -> dict:

  # Get Pokemon information.
  pokemon_url = "https://pokeapi.co/api/v2/pokemon/" + name
  pokemon_req = requests.get(pokemon_url)

  # Raise an exception if fetching data failed.
  if pokemon_req.status_code != 200:
    raise Exception("Request failed with status code: " + str(pokemon_req.status_code))

  # Retrieve available data from this request.
  pokemon = pokemon_req.json()
  output = {
    "name": pokemon["name"],
    "height": pokemon["height"],
    "types": [t["type"]["name"] for t in pokemon["types"]]
  }

  return {**output, **get_species(pokemon["species"]["name"], fetch_pokemons=False)}

# This function returns a Pokemon species' information as a dictionary.
# If the optional argument fetch_pokemons is true, the output dictionary will include
# a list of Pokemon varieties under this species group.
# Information is retrieved from the https://pokeapi.co/api/v2/pokemon-species/ endpoint.
def get_species(name : str, fetch_pokemons : bool = True) -> dict:

  # Get Pokemon species information.
  species_url = "https://pokeapi.co/api/v2/pokemon-species/" + name
  species_req = requests.get(species_url)

  # Raise an exception if fetching data failed.
  if species_req.status_code != 200:
    raise Exception("Request failed with status code: " + str(species_req.status_code))

  # Access the species resource for Pokemon description, habitat,
  # and legendary status.
  species = species_req.json()
  output = {}
  output["species_name"] = species["name"]
  output["is_legendary"] = species["is_legendary"]

  # Sometimes, a Pokemon species has no habitat (e.g. lucario).
  try:
    output["habitat"] = species["habitat"]["name"]
  except:
    output["habitat"] = "???"

  # Take first English-language flavour text as description.
  i = 0
  while species["flavor_text_entries"][i]["language"]["name"] != "en":
    i += 1
  output["description"] = species["flavor_text_entries"][i]["flavor_text"]\
    .replace("\n", " ").replace("\f", " ")

  if fetch_pokemons:
    output["varieties"] = [p["pokemon"]["name"] for p in species["varieties"]]

  return output

def main() -> None:

  print(
    "#######################",
    "\n\nWelcome to Pokemonpy!",
    "\n\nGet basic information on any Pokemon, or type 'exit' to quit!",
    "\n\n#######################\n"
  )

  exit = False
  while not exit:
    user_input = input("Enter a Pokemon name: ")

    if user_input == "exit":
      exit = True
      continue

    try:
      pokemon_info = get_pokemon(user_input)
      print()
    except Exception as e:
      print("\nFailed to retrieve Pokemon data!")
      print("Error:", e, "\n")
      print("Checking the api/v2/pokemon-species/ endpoint...")
      try:
        pokemon_info = get_species(user_input)
        print("Found species info! To get more details, enter one of the species' varieties.\n")
      except Exception as e1:
        print("Failed to retrieve Pokemon species data!")
        print("Error:", e1, "\n")
        continue

    for key, val in pokemon_info.items():
      print("" + key + ":", val)
    print()

  return None

if __name__ == '__main__':
  main()


import sys
from io import StringIO
import unittest

class TestClass(unittest.TestCase):
    def assertIO(self, input, output):
        stdout, stdin = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(input)
        resolve()
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, stdin
        self.assertEqual(out, output)

    # def test_Sample_Input_1(self):
    #     input = """2 1"""
    #     output = """4"""
    #     self.assertIO(input, output)

    def test_Sample_Input_2(self):
        input = """3 1"""
        output = """16"""
        self.assertIO(input, output)

    # def test_Sample_Input_2(self):
    #     input = """2525 -425"""
    #     output = """10314607400"""
    #     self.assertIO(input, output)

def resolve():
  N, K = map(int, input().split(" "))
  ans = 0
  for a in range(1, N+1):
    a_count = 0
    for b in range(1, N+1):
      for c in range(1, N+1):
        for d in range(1, N+1):
          if a+b-c-d == K:
            a_count += 1
            ans += 1
    # print(a, ":", a_count)
  print(ans)

if __name__ == "__main__":
  resolve()

if __name__ == "__main__":
    unittest.main()


import scrapy
import json
stop = {}

class CommentsSpider(scrapy.Spider):
    name = 'comments'
    all_comments = []

    def start_requests(self):
        global stop
        headers = {"Authorization": "Bearer 56edfc79ecf25922b98202dd79a291aa"}

        with open('designs.json') as f:
            designs = json.load(f)
        for design in designs:
            i = 1
            stop[design["id"]] = False
            print("**************************************"+str(design["id"]))
            while True:
                if stop[design["id"]] == True:
                    break;
                url = 'https://api.thingiverse.com/things/'+str(design["id"])+'/root-comments?page='+str(i)+'&per_page=20&t=1624296261833'
                yield scrapy.http.Request(url, headers=headers, cb_kwargs={"page":i,"design_id":design["id"]})
                i = i + 1

    def parse(self, response, page, design_id):
        print(page, design_id)
        parsed_data = json.loads(response.text)

        if len(parsed_data) == 0:
            stop[design_id] = True
        else:

            for comment in parsed_data:
                comment["design_id"] = design_id
                self.all_comments.append(comment)
            writefile = open('root_comment.json', 'w')

            json.dump(self.all_comments, writefile)
            writefile.close()


from requests import get
from requests.exceptions import RequestException
from contextlib import closing
from bs4 import BeautifulSoup

def simple_get(url):
    """
    Attempts to get the content at `url` by making an HTTP GET request.
    If the content-type of response is some kind of HTML/XML, return the
    text content, otherwise return None
    """
    try:
        with closing(get(url, stream=True)) as resp:
            if is_good_response(resp):
                return resp.content
            else:
                return None

    except RequestException as e:
        log_error('Error during requests to {0} : {1}'.format(url, str(e)))
        return None

def is_good_response(resp):
    """
    Returns true if the response seems to be HTML, false otherwise
    """
    content_type = resp.headers['Content-Type'].lower()
    return (resp.status_code == 200
            and content_type is not None
            and content_type.find('html') > -1)

def log_error(e):
    """
    It is always a good idea to log errors.
    This function just prints them, but you can
    make it do anything.
    """
    print(e)

def get_html_soup(url):
    raw_html = simple_get(url)
    return BeautifulSoup(raw_html, 'html.parser')

def get_ica_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("span", "ingredient"):
        amount = tag.get('data-amount')
        unit = tag.get('data-type')
        item = tag.string

        item = item.replace(amount, '').replace(unit, '')

        amount = amount.replace(',', '.')

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.replace("| Recept ICA.se", "").strip()
    return name, ingreds

def get_koket_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("span", "ingredient"):
        amount_unit = tag.contents[0].string
        item = tag.contents[1].string

        if amount_unit is None:
            amount = None
            unit = ""

        else:
            amount_unit_list = amount_unit.split()

            if len(amount_unit_list) > 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = amount_unit_list[1]

            elif len(amount_unit_list) == 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = ""

            else:
                amount = None
                unit = ""

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.replace("| Recept från Köket.se", "").strip()
    return name, ingreds

def get_coop_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("li", "Recipe-ingredient"):
        item = tag.find("span", "Recipe-ingredientType").string
        amount_unit = tag.find("span", "Recipe-ingredientAmount").string

        if amount_unit is None:
            amount = None
            unit = ""

        else:
            amount_unit_list = amount_unit.split()

            if len(amount_unit_list) > 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = amount_unit_list[1]

            elif len(amount_unit_list) == 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = ""

            else:
                amount = None
                unit = ""

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.strip()
    return name, ingreds

def parse_recipe_from_url(html_address):
    if "www.ica.se" in html_address:
        recipe_name, ingreds = get_ica_recipe(html_address)
    elif "www.coop.se" in html_address:
        recipe_name, ingreds = get_coop_recipe(html_address)
    elif "www.koket.se" in html_address:
        recipe_name, ingreds = get_koket_recipe(html_address)
    else:
        recipe_name = ""
        ingreds = ""

    if ingreds:
        parse_successful = True
    else:
        parse_successful = False

    return recipe_name, ingreds, parse_successful

if __name__ == "__main__":
    #from_url = 'https://www.ica.se/recept/fryst-cheesecake-med-saffran-722867/'
    #from_url = 'https://www.coop.se/Recept--mat/Recept/l/lax-med-chunky-pesto-och-tagliatelle/'
    from_url = 'https://www.koket.se/sara_begner/soppor_och_grytor/korv_och_chark/korv_stroganoff/'
    recipe_title, recipe_ingreds, success = parse_recipe_from_url(from_url)
    print("Success: ", success)
    print(recipe_title)
    print(recipe_ingreds)


from aiogram.filters import Filter
from aiogram.types import Message

from tools import remove_proto

class IpAddress(Filter):
    async def __call__(self, m: Message) -> bool:
        text = remove_proto(m.text)
        parts = text.split('.')
        if len(parts) != 4:
            return False

        for part in parts:
            if not (part.isnumeric() and int(part) in range(0, 256)):
                return False

        return True


#-*-coding:utf-8-*-
'''
DpCas-Light
||||      ||||       ||||         ||        ||||
||  ||    ||  ||   ||    ||      ||||     ||    ||
||    ||  ||   || ||      ||    ||  ||     ||
||    ||  ||  ||  ||           ||====||      ||||
||    ||  ||||    ||      ||  ||======||         ||
||  ||    ||       ||    ||  ||        ||  ||    ||
||||      ||         ||||   ||          ||   ||||

/------------------ Who You Want 2 See ------------------/
'''
# date:2020-12-12
# Author: Eric.Lee
# function: show clip video
import os
import cv2
import copy
import time

import threading
from threading import current_thread, Lock

import  psutil
import numpy as np
import random

lock = Lock()
def run_one_process(path,process_id,vis):

    lock.acquire()
    video_ = cv2.VideoCapture(path)
    lock.release()
    while True:
        ret, img_ = video_.read()

        if ret:
           #------------------------------------------------
            if vis:
                cv2.namedWindow('video_seg_{}'.format(process_id),0)
                cv2.resizeWindow('video_seg_{}'.format(process_id), 300, 210);
                cv2.moveWindow('video_seg_{}'.format(process_id), (process_id%6)*300+60,int(process_id/6)*230)
                cv2.imshow('video_seg_{}'.format(process_id),img_)
                if cv2.waitKey(300) == 27:
                    flag_break =True
                    break
        else:
            break
    if vis:
        cv2.waitKey(30000)
        cv2.destroyWindow('video_seg_{}'.format(process_id))

def run_show(path,vis):
    seg_num = len(os.listdir(path))

    videos_path = os.listdir(path)
    # #--------------------------------------
    st_ = time.time()
    process_list = []
    for i in range(0,seg_num):
        # print(video_list[i])
        t = threading.Thread(target=run_one_process, args=(path + videos_path[i],i,vis))
        process_list.append(t)

    for i in range(0,seg_num):
        process_list[i].start()

    print(' start run ~ ')

    for i in range(0,seg_num):
        process_list[i].join()# 设置主线程等待子线程结束

    del process_list
    et_ = time.time()

if __name__ == "__main__":
    path = './video/'
    vis = True

    run_show_hights(path,vis)
    #--------------------------------------


# -*- coding: utf-8 -*-
"""
Created on Fri Dec 23 16:31:15 2022

@author: Nikhiel
"""

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns

def pharray(df):

    num_sigs = len(df)
    m_adc = []
    timebin = []

    for i in range(30):

        s = np.concatenate((np.array(df.iloc[:, i]),
                             np.array(df.iloc[:, i+30]),
                             np.array(df.iloc[:, i+60])), axis=None).sum()
        m_adc.append(s/num_sigs)
        timebin.append(i)

    return timebin, m_adc

df = pd.read_csv("Clean_simsigs_50k.csv")

L = df.shape[0]

t = np.arange(0,30)

x = np.tile(t, df.shape[0])

sigs = df.iloc[:, :90].to_numpy()

ph_sigs = sigs.reshape(L, 3, 30).sum(axis=1)

edgey = np.arange(0, 300, 7)

H, xe, ye = np.histogram2d(x, ph_sigs.flatten(), bins=[t,edgey], range=[[0,30],[0,400]])

tavg, avg = pharray(df)

plt.figure(figsize=(12, 6))
#sns.heatmap(H, cmap='viridis')
plt.imshow(H.T, cmap='viridis', extent=[xe[0], xe[-1], ye[-1], ye[0]], aspect='auto')
plt.plot(tavg, avg, marker='.', color='red', linestyle='', label='Average')
plt.ylim(ye[0], ye[-1])
plt.colorbar()
plt.legend()
plt.title("Pulse Height Spectrum", fontsize=12)
plt.xlabel("Time bin (100ns)", fontsize=11)
plt.ylabel("ADC", fontsize=11)
plt.tight_layout()
plt.show()

from scipy.stats import chi2

def calc_chi(obs, exp):

    L = len(obs)
    vals = np.zeros(L)
    # get the length of the arrays

    # loop over each element in the arrays and compute the squared diff divided by the expected

    for i in range(L):
        vals[i] = ((obs[i] - exp[i])**2)/(exp[i])

    chisq = vals.sum()

    return chisq

dfs = pd.read_csv("Clean_simsigs_50k.csv")
dfr = pd.read_csv("Clean_realsigs_LHC22o.csv")

t_s, a_s = pharray(dfs)
t_r, a_r = pharray(dfr)

calc_chi(obs = a_s, exp=a_r)

chi = calc_chi(obs = a_s, exp=a_r)

crit_val = chi2.ppf(q=0.95, df=30)
p_val = 1 - chi2.cdf(x=chi, df=30)

print("Chi Squared value = ", chi)
print("\nCritical value = ", crit_val)
print("\nP-value = ", p_val)


import numpy as np
import cv2
from PIL import ImageGrab
import pyautogui
import pytesseract
import time
from pyfirmata import Arduino,util
import serial
result = 0;
result2 = result - 1;
x = 500
y = 2000
w = 100
h = 11007
cords = 0
thingy = True;
DeathsInGame = 0;
board = Arduino('COM3');

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
def test_Pytesseract():
    pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
    screenshot = pyautogui.screenshot();
    screenshot = np.array(screenshot);
    text = pytesseract.image_to_string(screenshot)
    cv2.imshow("img", screenshot)
    print(text);
    cv2.waitKey(0);

def screen_Capture():
    while True:
        screenshot = pyautogui.screenshot();
        screenshot = np.array(screenshot);
        text = pytesseract.image_to_string(screenshot)
        cv2.imshow('Computer Vision', screenshot)
        if cv2.waitKey(1) == ord('q'):
            break
    cv2.destroyAllWindows()
    print('Done');

# pyautogui.displayMousePosition()
def deezNuts():
    while(True):
        X = 1683;
        Y = 38;
        image = ImageGrab.grab(bbox=(1683,38,100,100))
        img_np = np.array(image)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)

def Trial_2():
    while True:
        img = ImageGrab.grab(bbox=(0, 200, 1920, 1200))  # x, y, w, h #                     #
        img_np = np.array(img)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
        cv2.imshow("frame", frame)
        if cv2.waitKey(1) & 0Xff == ord('q'):
            break
    cv2.destroyAllWindows()
def Trial_That_Works():
    time.sleep(2);
    print("ooooo");
    while True:
        screenshot = pyautogui.screenshot('screenshot.png', region = (1665,0, 100, 25));
        img_np = np.array(screenshot)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
        img = cv2.imread('screenshot.png');
        text = pytesseract.image_to_string(img)
        #cv2.imshow("frame", frame)
        try:
            ConversionToSomethingReadable = text.split('/');
            DeathsInGame = int(ConversionToSomethingReadable[1]);
            result = DeathsInGame
            result2 = result - 1
            YourAssIsGettingTazed();
        except IndexError:
            continue;
    print('Done');

def YourAssIsGettingTazed():
    #time.sleep(5)
    if (result == result2 + 1):
        # LEDpin = board.get_pin('d:13:p')
        board.digital[12].write(1);

        time.sleep(5)
        board.digital[12].write(0);
        print("Tazed");

def Take_ScreenShot():
    time.sleep(5);
    screenshot = pyautogui.screenshot('Screenshot.jpg', region = (850,1000, 100, 50));
    img_np = np.array(screenshot)
    frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
    img = cv2.imread(frame);
    text = pytesseract.image_to_string(img)
    print(text);
'''
Trial_That_Works()
img = cv2.imread('Screenshot.jpg');
#picture = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
text = pytesseract.image_to_string(img)
print(text);
'''
#Trial_That_Works()
#YourAssIsGettingTazed()
#cv2.destroyAllWindows()
#print('done');

# references to helpful code
'''
img = ImageGrab.grab(bbox=None)  # x, y, w, h
img_np = np.array(img) <--- use this for the *mat* error
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
'''
def Take_ScreenShotV2():
    #board.digital[13].write(1);
    time.sleep(5);
    while True:
        try:
            screenshot = pyautogui.screenshot('Screenshot.jpg', region=(850, 1000, 100, 50));
            img_np = np.array(screenshot)
            img = cv2.imread('Screenshot.jpg');
            text = pytesseract.image_to_string(img)
            SomeBullshit = text.split("/")
            Health = SomeBullshit[0];
            print("done");
            if Health == "0":
                YourAssIsGettingTazed()
        except IndexError:
            continue
#Take_ScreenShotV2();
#board.digital[13].write(0);

#YourAssIsGettingTazed();

'''
while True:
    Take_ScreenShotV2()
    img = cv2.imread('Screenshot.jpg');
    text = pytesseract.image_to_string(img)
    SomeBullshit = text.split("/")
    Health = int(SomeBullshit[0]);
    if Health == 0:
        YourAssIsGettingTazed()
print(Done);
'''