#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Oct  4 07:33:11 2019

@author: vboas
"""

import numpy as np
from scipy.stats import multivariate_normal
import matplotlib.pyplot as plt
import itertools
import functools

class SigmoidalFeature(object):
    """
    Sigmoidal features

    1 / (1 + exp((m - x) @ c)
    """

    def __init__(self, mean, coef=1):
        """
        construct sigmoidal features

        Parameters
        ----------
        mean : (n_features, ndim) or (n_features,) ndarray
            center of sigmoid function
        coef : (ndim,) ndarray or int or float
            coefficient to be multplied with the distance
        """
        if mean.ndim == 1:
            mean = mean[:, None]
        else:
            assert mean.ndim == 2
        if isinstance(coef, int) or isinstance(coef, float):
            if np.size(mean, 1) == 1:
                coef = np.array([coef])
            else:
                raise ValueError("mismatch of dimension")
        else:
            assert coef.ndim == 1
            assert np.size(mean, 1) == len(coef)
        self.mean = mean
        self.coef = coef

    def _sigmoid(self, x, mean):
        return np.tanh((x - mean) @ self.coef * 0.5) * 0.5 + 0.5

    def transform(self, x):
        """
        transform input array with sigmoidal features

        Parameters
        ----------
        x : (sample_size, ndim) or (sample_size,) ndarray
            input array

        Returns
        -------
        output : (sample_size, n_features) ndarray
            sigmoidal features
        """
        if x.ndim == 1:
            x = x[:, None]
        else:
            assert x.ndim == 2
        assert np.size(x, 1) == np.size(self.mean, 1)
        basis = [np.ones(len(x))]
        for m in self.mean:
            basis.append(self._sigmoid(x, m))
        return np.asarray(basis).transpose()

class PolynomialFeature(object):
    """
    polynomial features

    transforms input array with polynomial features

    Example
    =======
    x =
    [[a, b],
    [c, d]]

    y = PolynomialFeatures(degree=2).transform(x)
    y =
    [[1, a, b, a^2, a * b, b^2],
    [1, c, d, c^2, c * d, d^2]]
    """

    def __init__(self, degree=2):
        """
        construct polynomial features

        Parameters
        ----------
        degree : int
            degree of polynomial
        """
        assert isinstance(degree, int)
        self.degree = degree

    def transform(self, x):
        """
        transforms input array with polynomial features

        Parameters
        ----------
        x : (sample_size, n) ndarray
            input array

        Returns
        -------
        output : (sample_size, 1 + nC1 + ... + nCd) ndarray
            polynomial features
        """
        if x.ndim == 1:
            x = x[:, None]
        x_t = x.transpose()
        features = [np.ones(len(x))]
        for degree in range(1, self.degree + 1):
            for items in itertools.combinations_with_replacement(x_t, degree):
                features.append(functools.reduce(lambda x, y: x * y, items))
        return np.asarray(features).transpose()

class GaussianFeature(object):
    """
    Gaussian feature

    gaussian function = exp(-0.5 * (x - m) / v)
    """

    def __init__(self, mean, var):
        """
        construct gaussian features

        Parameters
        ----------
        mean : (n_features, ndim) or (n_features,) ndarray
            places to locate gaussian function at
        var : float
            variance of the gaussian function
        """
        if mean.ndim == 1:
            mean = mean[:, None]
        else:
            assert mean.ndim == 2
        assert isinstance(var, float) or isinstance(var, int)
        self.mean = mean
        self.var = var

    def _gauss(self, x, mean):
        return np.exp(-0.5 * np.sum(np.square(x - mean), axis=-1) / self.var)

    def transform(self, x):
        """
        transform input array with gaussian features

        Parameters
        ----------
        x : (sample_size, ndim) or (sample_size,)
            input array

        Returns
        -------
        output : (sample_size, n_features)
            gaussian features
        """
        if x.ndim == 1:
            x = x[:, None]
        else:
            assert x.ndim == 2
        assert np.size(x, 1) == np.size(self.mean, 1)
        basis = [np.ones(len(x))]
        for m in self.mean:
            basis.append(self._gauss(x, m))
        return np.asarray(basis).transpose()

class Regression(object):
    """
    Base class for regressors
    """
    pass

class LinearRegression(Regression):
    """
    Linear regression model
    y = X @ w
    t ~ N(t|X @ w, var)
    """

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        perform least squares fitting

        Parameters
        ----------
        X : (N, D) np.ndarray
            training independent variable
        t : (N,) np.ndarray
            training dependent variable
        """
        self.w = np.linalg.pinv(X) @ t
        self.var = np.mean(np.square(X @ self.w - t))

    def predict(self, X:np.ndarray, return_std:bool=False):
        """
        make prediction given input

        Parameters
        ----------
        X : (N, D) np.ndarray
            samples to predict their output
        return_std : bool, optional
            returns standard deviation of each predition if True

        Returns
        -------
        y : (N,) np.ndarray
            prediction of each sample
        y_std : (N,) np.ndarray
            standard deviation of each predition
        """
        y = X @ self.w
        if return_std:
            y_std = np.sqrt(self.var) + np.zeros_like(y)
            return y, y_std
        return y

class RidgeRegression(Regression):
    """
    Ridge regression model

    w* = argmin |t - X @ w| + alpha * |w|_2^2
    """

    def __init__(self, alpha:float=1.):
        self.alpha = alpha

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        maximum a posteriori estimation of parameter

        Parameters
        ----------
        X : (N, D) np.ndarray
            training data independent variable
        t : (N,) np.ndarray
            training data dependent variable
        """

        eye = np.eye(np.size(X, 1))
        self.w = np.linalg.solve(self.alpha * eye + X.T @ X, X.T @ t)

    def predict(self, X:np.ndarray):
        """
        make prediction given input

        Parameters
        ----------
        X : (N, D) np.ndarray
            samples to predict their output

        Returns
        -------
        (N,) np.ndarray
            prediction of each input
        """
        return X @ self.w

class BayesianRegression(Regression):
    """
    Bayesian regression model

    w ~ N(w|0, alpha^(-1)I)
    y = X @ w
    t ~ N(t|X @ w, beta^(-1))
    """

    def __init__(self, alpha:float=1., beta:float=1.):
        self.alpha = alpha
        self.beta = beta
        self.w_mean = None
        self.w_precision = None

    def _is_prior_defined(self) -> bool:
        return self.w_mean is not None and self.w_precision is not None

    def _get_prior(self, ndim:int) -> tuple:
        if self._is_prior_defined():
            return self.w_mean, self.w_precision
        else:
            return np.zeros(ndim), self.alpha * np.eye(ndim)

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        bayesian update of parameters given training dataset

        Parameters
        ----------
        X : (N, n_features) np.ndarray
            training data independent variable
        t : (N,) np.ndarray
            training data dependent variable
        """

        mean_prev, precision_prev = self._get_prior(np.size(X, 1))

        w_precision = precision_prev + self.beta * X.T @ X
        w_mean = np.linalg.solve(
            w_precision,
            precision_prev @ mean_prev + self.beta * X.T @ t
        )
        self.w_mean = w_mean
        self.w_precision = w_precision
        self.w_cov = np.linalg.inv(self.w_precision)

    def predict(self, X:np.ndarray, return_std:bool=False, sample_size:int=None):
        """
        return mean (and standard deviation) of predictive distribution

        Parameters
        ----------
        X : (N, n_features) np.ndarray
            independent variable
        return_std : bool, optional
            flag to return standard deviation (the default is False)
        sample_size : int, optional
            number of samples to draw from the predictive distribution
            (the default is None, no sampling from the distribution)

        Returns
        -------
        y : (N,) np.ndarray
            mean of the predictive distribution
        y_std : (N,) np.ndarray
            standard deviation of the predictive distribution
        y_sample : (N, sample_size) np.ndarray
            samples from the predictive distribution
        """

        if sample_size is not None:
            w_sample = np.random.multivariate_normal(
                self.w_mean, self.w_cov, size=sample_size
            )
            y_sample = X @ w_sample.T
            return y_sample
        y = X @ self.w_mean
        if return_std:
            y_var = 1 / self.beta + np.sum(X @ self.w_cov * X, axis=1)
            y_std = np.sqrt(y_var)
            return y, y_std
        return y

class EmpiricalBayesRegression(BayesianRegression):
    """
    Empirical Bayes Regression model
    a.k.a.
    type 2 maximum likelihood,
    generalized maximum likelihood,
    evidence approximation

    w ~ N(w|0, alpha^(-1)I)
    y = X @ w
    t ~ N(t|X @ w, beta^(-1))
    evidence function p(t|X,alpha,beta) = S p(t|w;X,beta)p(w|0;alpha) dw
    """

    def __init__(self, alpha:float=1., beta:float=1.):
        super().__init__(alpha, beta)

    def fit(self, X:np.ndarray, t:np.ndarray, max_iter:int=100):
        """
        maximization of evidence function with respect to
        the hyperparameters alpha and beta given training dataset

        Parameters
        ----------
        X : (N, D) np.ndarray
            training independent variable
        t : (N,) np.ndarray
            training dependent variable
        max_iter : int
            maximum number of iteration
        """
        M = X.T @ X
        eigenvalues = np.linalg.eigvalsh(M)
        eye = np.eye(np.size(X, 1))
        N = len(t)
        for _ in range(max_iter):
            params = [self.alpha, self.beta]

            w_precision = self.alpha * eye + self.beta * X.T @ X
            w_mean = self.beta * np.linalg.solve(w_precision, X.T @ t)

            gamma = np.sum(eigenvalues / (self.alpha + eigenvalues))
            self.alpha = float(gamma / np.sum(w_mean ** 2).clip(min=1e-10))
            self.beta = float(
                (N - gamma) / np.sum(np.square(t - X @ w_mean))
            )
            if np.allclose(params, [self.alpha, self.beta]):
                break
        self.w_mean = w_mean
        self.w_precision = w_precision
        self.w_cov = np.linalg.inv(w_precision)

    def _log_prior(self, w):
        return -0.5 * self.alpha * np.sum(w ** 2)

    def _log_likelihood(self, X, t, w):
        return -0.5 * self.beta * np.square(t - X @ w).sum()

    def _log_posterior(self, X, t, w):
        return self._log_likelihood(X, t, w) + self._log_prior(w)

    def log_evidence(self, X:np.ndarray, t:np.ndarray):
        """
        logarithm or the evidence function

        Parameters
        ----------
        X : (N, D) np.ndarray
            indenpendent variable
        t : (N,) np.ndarray
            dependent variable
        Returns
        -------
        float
            log evidence
        """
        N = len(t)
        D = np.size(X, 1)
        return 0.5 * (
            D * np.log(self.alpha) + N * np.log(self.beta)
            - np.linalg.slogdet(self.w_precision)[1] - D * np.log(2 * np.pi)
        ) + self._log_posterior(X, t, self.w_mean)

# 3. Linear Models for Regression
np.random.seed(1234)

def create_toy_data(func, sample_size, std, domain=[0, 1]):
    x = np.linspace(domain[0], domain[1], sample_size)
    np.random.shuffle(x)
    t = func(x) + np.random.normal(scale=std, size=x.shape)
    return x, t

# 3.1 Linear Basis Function Models
x = np.linspace(-1, 1, 100)
X_polynomial = PolynomialFeature(11).transform(x[:, None])
X_gaussian = GaussianFeature(np.linspace(-1, 1, 11), 0.1).transform(x)
X_sigmoidal = SigmoidalFeature(np.linspace(-1, 1, 11), 10).transform(x)

plt.figure(figsize=(20, 5))
for i, X in enumerate([X_polynomial, X_gaussian, X_sigmoidal]):
    plt.subplot(1, 3, i + 1)
    for j in range(12):
        plt.plot(x, X[:, j])

# 3.1.1 Maximum likelihood and least squares
def sinusoidal(x):
    return np.sin(2 * np.pi * x)

x_train, y_train = create_toy_data(sinusoidal, 10, 0.25)
x_test = np.linspace(0, 1, 100)
y_test = sinusoidal(x_test)

# Pick one of the three features below
# feature = PolynomialFeature(8)
feature = GaussianFeature(np.linspace(0, 1, 8), 0.1)
# feature = SigmoidalFeature(np.linspace(0, 1, 8), 10)

X_train = feature.transform(x_train)
X_test = feature.transform(x_test)
model = LinearRegression()
model.fit(X_train, y_train)
y, y_std = model.predict(X_test, return_std=True)

plt.scatter(x_train, y_train, facecolor="none", edgecolor="b", s=50, label="training data")
plt.plot(x_test, y_test, label="$\sin(2\pi x)$")
plt.plot(x_test, y, label="prediction")
plt.fill_between(
    x_test, y - y_std, y + y_std,
    color="orange", alpha=0.5, label="std.")
plt.legend()
plt.show()

# 3.1.4 Regularized least squares
model = RidgeRegression(alpha=1e-3)
model.fit(X_train, y_train)
y = model.predict(X_test)

plt.scatter(x_train, y_train, facecolor="none", edgecolor="b", s=50, label="training data")
plt.plot(x_test, y_test, label="$\sin(2\pi x)$")
plt.plot(x_test, y, label="prediction")
plt.legend()
plt.show()

# 3.2 The Bias-Variance Decomposition
# feature = PolynomialFeature(24)
feature = GaussianFeature(np.linspace(0, 1, 24), 0.1)
# feature = SigmoidalFeature(np.linspace(0, 1, 24), 10)

for a in [1e2, 1., 1e-9]:
    y_list = []
    plt.figure(figsize=(20, 5))
    plt.subplot(1, 2, 1)
    for i in range(100):
        x_train, y_train = create_toy_data(sinusoidal, 25, 0.25)
        X_train = feature.transform(x_train)
        X_test = feature.transform(x_test)
        model = BayesianRegression(alpha=a, beta=1.)
        model.fit(X_train, y_train)
        y = model.predict(X_test)
        y_list.append(y)
        if i < 20:
            plt.plot(x_test, y, c="orange")
    plt.ylim(-1.5, 1.5)

    plt.subplot(1, 2, 2)
    plt.plot(x_test, y_test)
    plt.plot(x_test, np.asarray(y_list).mean(axis=0))
    plt.ylim(-1.5, 1.5)
    plt.show()


#!/usr/bin/python
from operator import itemgetter
import sys
import re
import errno

for line in sys.stdin:
    line = line.strip()
    line = line.split()
    num = line[1]
    num = int(num)

violations[plate] = violations.get(plate, 0) + num
violations[vYear] = violations.get(vYear, 0) + num
violations[vColor] = violations.get(vColor, 0) + num
violations[vtype] = violations.get(vtype, 0) + num
violations[violationTime] = violations.get(violationTime, 0) + num
violations[place] = violations.get(place, 0) + num

# question 1
sorted_time = sorted(violations[violationTime].items(), key=itemgetter(1), reverse=True)

for violationTime, freq in sorted_time[0:20]:
    print(violationTime, freq)

# question 2

sorted_years = sorted(violations[vYear].items(), key=itemgetter(1), reverse=True)
sorted_types = sorted(violations[vType].items(), key=itemgetter(1), reverse=True)

for vYear, freq in sorted_years[0:20]:
    print(vYear, freq)

for vType, freq in sorted_types[0:20]:
    print(vType, freq)

# question 3

sorted_place = sorted(violations[place].items(), key=itemgetter(1), reverse=True)

for place, freq in sorted_place[0:20]:
    print(place, freq)

# question 4

sorted_color = sorted(violations[vColor].items(), key=itemgetter(1), reverse=True)

for vColor, freq in sorted_color[0:20]:
    print(vColor, freq)


# -*- coding: utf-8 -*-
"""
Created on Fri Nov 27 17:04:58 2020

@author: abhay
"""

import numpy as np
import pandas as pd
import numpy.random as rand
import shutil
import os
# COST Function we will use the given cst calculator
from Farm_Evaluator_Vec_copy import AEP, binWindResourceData, loadPowerCurve
import matplotlib.pyplot as plt

# MAIN CLASS PARTICLES
# Each particle is a wind farm layout of lenght 4000x4000 dimensions
# Each windmill in the particle is bounded between (50,3950)
# The distance between each windmill should be at a distance 400 m

class Particle:
    def __init__(self,n_turbines = 50):
        # ABout thte particle
        self.length = 4000
        self.boundary = 50
        self.separation = 400
        self.n_turbines = n_turbines

        # fitness of the particle
        self.fitness = 0

        # personal best
        self.p_best_x = np.zeros(50)
        self.p_best_y = np.zeros(50)

        self.best_aep = 0
        self.best_fitness = None

        #Initially we will assign random coordinates to the turbines
        #self.position_x = np.ones(n_turbines)*self.boundary + rand.uniform(size = n_turbines) * (self.length - 2* self.boundary)
        #self.position_y = np.ones(n_turbines)*self.boundary + rand.uniform(size = n_turbines) * (self.length - 2* self.boundary)
        self.position_x = np.random.uniform(50,3950,50)
        self.position_y = np.random.uniform(50,3950,50)
        self.position_x,self.position_y = self.calc_postion(np.zeros(self.n_turbines), np.zeros(self.n_turbines),
                                                            np.zeros(self.n_turbines), np.zeros(self.n_turbines))

    def calc_postion(self, v1,v2, g_best_x, g_best_y):
        new_pos_x = self.position_x + np.multiply(v1[0], (g_best_x - self.position_x)) + np.multiply(v2[0], (self.p_best_x - self.position_x))
        new_pos_y = self.position_y + np.multiply(v1[1], (g_best_y - self.position_y)) + np.multiply(v2[1], (self.p_best_y - self.position_y))
        for i in range(len(new_pos_x)):
            for j in range(len(new_pos_x)):
                if (i == j):
                    continue

                x_1, y_1 = new_pos_x[i],new_pos_y[i]
                x_2, y_2 = new_pos_x[j],new_pos_y[j]
                dist = np.sqrt((x_1 - x_2)** 2 + (y_1 - y_2)** 2)
                if (dist < self.separation):
                    radius = (self.separation - dist) / 2
                    angle = np.arctan((y_2 - y_1) / (x_2 - x_1 + 1e-3))
                    # turn = np.random.uniform(low = -1.57, high = 1.57)
                    turn = 0
                    c=(x_2 * y_1 - x_1 * y_2) / (x_2 - x_1 + 1e-3)

                    s_x_1 = x_1
                    s_y_1 = y_1 + c
                    s_x_2 = x_2
                    s_y_2 = y_2 + c

                    r_x_1 = s_x_1 * np.cos(angle) + s_y_1 * np.sin(angle) + radius*np.cos(turn)
                    r_y_1 = s_y_1 * np.cos(angle) - s_x_1 * np.sin(angle) + radius*np.sin(turn)
                    r_x_2 = s_x_2 * np.cos(angle) + s_y_2 * np.sin(angle) - radius*np.cos(turn)
                    r_y_2 = s_y_2 * np.cos(angle) - s_x_2 * np.sin(angle) - radius * np.sin(turn)

                    [new_pos_x[i],new_pos_y[i]] = [r_x_1 * np.cos(angle) - r_y_1 * np.sin(angle), r_x_1 * np.sin(angle) + r_y_1 * np.cos(angle) - c]
                    [new_pos_x[j],new_pos_y[j]] = [r_x_2 * np.cos(angle) - r_y_2 * np.sin(angle), r_x_2 * np.sin(angle) + r_y_2 * np.cos(angle) - c]

            new_pos_x[i] = min(new_pos_x[i], self.length - self.boundary)
            new_pos_y[i] = min(new_pos_y[i], self.length - self.boundary)
            new_pos_x[i] = max(self.boundary, new_pos_x[i])
            new_pos_y[i] = max(self.boundary, new_pos_y[i])

        return new_pos_x,new_pos_y

    def calc_violation(self,position_x,position_y):
        cost = 0
        for i in range(self.n_turbines) :
            x1, y1 = position_x[i],position_y[i]
            # Check boundary constraints
            if x1 < self.boundary :
                cost = cost + (self.boundary - x1)**2
            if y1 < self.boundary :
                cost = cost + (self.boundary - y1)**2
            if x1 > self.length - self.boundary :
                cost = cost + (self.length - self.boundary - x1)**2
            if y1 > self.length - self.boundary :
                cost = cost + (self.length - self.boundary - y1)**2

            for j in range(self.n_turbines) :
                if i == j :
                    continue
                x2 , y2 = position_x[j],position_y[j]
                dist = np.sqrt((x1 - x2)**2 + (y1 - y2)**2)
                if dist < self.separation:
                    cost =cost + self.separation - dist
        return cost

# THe SWARM CLASS

class PSO:
    def __init__(self, n_turbines = 50,n_particles = 100, iterations = 50):
        # Will will load the power curve of the turbine and the wind data
        self.power_curve = loadPowerCurve(r'Shell_Hackathon Dataset/power_curve.csv')
        self.wind_data = binWindResourceData(r'Shell_Hackathon Dataset/Wind Data/wind_data_2017.csv')

        self.total_iterations = iterations
        self.n_particles = n_particles
        self.n_turbines = n_turbines

        self.g_best_x = []
        self.g_best_y = []

        self.g_best_aep = 0
        self.best_aep = []# for logging the aeps to graph
        self.g_best_fitness = None
        self.counter = 0
        #Loading The particles to the swarm
        self.particles = [Particle() for i in range(n_particles)]

    def calc_AEP(self, position_x, position_y):
        return AEP(position_x, position_y, self.power_curve, self.wind_data)

    def calc_fitness(self, aep, violation_cost):
        if violation_cost != 0:
            return -violation_cost
        else:
            return aep

    def log_best_plots(self,g_best_x,g_best_y,count):
        if count < 1:
            shutil.rmtree("globalbest")
            os.mkdir("globalbest")
        data = pd.DataFrame()
        data['x'] = g_best_x
        data['y'] = g_best_y
        data.to_csv("globalbest/iteration_"+str(count) + ".csv",index = False)

    def iterate(self):
        for i in range(self.n_particles):
            v1 = np.random.uniform(low = 0, high = 1, size = [2,self.n_turbines])
            v2 = np.random.uniform(low = 0, high = 1, size = [2,self.n_turbines])
            new_pos_x,new_pos_y = self.particles[i].calc_postion(v1,v2,self.g_best_x, self.g_best_y)

            violation_cost = self.particles[i].calc_violation(
                self.particles[i].position_x, self.particles[i].position_y)

            new_aep = self.calc_AEP(new_pos_x, new_pos_y)
            new_fitness = self.calc_fitness(new_aep, violation_cost)
            # Update particle fitness
            if new_fitness > self.particles[i].best_fitness:
                self.particles[i].best_fitness = new_fitness
                self.particles[i].best_aep = new_aep
                self.particles[i].p_best_x = new_pos_x
                self.particles[i].p_best_y = new_pos_y
            # Update global fitness
            if (new_fitness > self.g_best_fitness) :
                self.g_best_fitness = new_fitness
                self.g_best_aep = new_aep
                self.g_best_x = new_pos_x
                self.g_best_y = new_pos_y

            self.particles[i].fitness = new_fitness

            #self.particles[i].pos_history.append(self.particles[i].pos) # check these and local bests also
            self.particles[i].position_x = new_pos_x
            self.particles[i].position_y = new_pos_y
        self.best_aep.append(new_aep)

    def run(self):
        #initializing the variables(iteration = 0)
        for particle in self.particles:
            violation_cost = particle.calc_violation(
                particle.position_x, particle.position_y)
            aep = self.calc_AEP(particle.position_x, particle.position_y)
            particle.fitness = self.calc_fitness(aep, violation_cost)
            # Updating the initial global best
            if self.g_best_fitness is None or particle.fitness > self.g_best_fitness:
                self.g_best_fitness = particle.fitness
                self.g_best_x = particle.position_x
                self.g_best_y = particle.position_y
                self.g_best_aep = aep
            particle.best_fitness = particle.fitness
            particle.best_aep = aep
            particle.p_best_x = particle.position_x
            particle.p_best_y = particle.position_y

        self.best_aep.append(aep)
        self.log_data()

        self.log_best_plots(self.g_best_x, self.g_best_y, self.counter)
        self.counter =self.counter + 1

        while self.counter < self.total_iterations:
            self.iterate()
            self.log_data()
            self.log_best_plots(self.g_best_x, self.g_best_y, self.counter)
            self.counter = self.counter + 1
        self.log_data()
        self.plotter(self.g_best_x, self.g_best_y, self.best_aep, self.total_iterations)

    def log_data(self):
        print("Iteration: ", self.counter, "Best Fitness: ", self.g_best_fitness, "Best AEP: ", self.g_best_aep)

    def plotter(self,x,y,aep,iterations):
        fig,ax = plt.subplots(1, 2, figsize=(10, 5))

        a = range(iterations)
        print(a,aep)
        ax[0].set_xlabel("X (m)")
        ax[0].set_ylabel("Y (m)")
        ax[0].axis(xmin=0,xmax=4000)
        ax[0].axis(ymin=0,ymax=4000)
        ax[0].axhline(y=3950, color='r', linestyle='-')
        ax[0].axhline(y=50, color='r', linestyle='-')
        ax[0].axvline(x=3950, color='r', linestyle='-')
        ax[0].axvline(x=50, color='r', linestyle='-')
        #ax[0].set_title('Iterations : ' + str(i))
        ax[0].scatter(x,y)

        ax[1].set_ylabel('No of iterations')
        ax[1].set_xlabel('Annual Energy Production')
        ax[1].plot(a,aep)

        fig.tight_layout()
        plt.show()


with open("input14.txt") as f:
    lines = [x.rstrip() for x in f.readlines()]
    template = ''
    rules = {}
    for i, line in enumerate(lines):
        if i == 0:
            template = line
        elif i == 1:
            continue
        else:
            sides = line.split(' -> ')
            rules[sides[0]] = sides[1]
    print(template)
    print(rules)

    """
    # works for part one
    for step in range(6):
        print(step, template, len(template))
        length = len(template)
        next = ''
        for i in range(length):
            first = template[i]
            if i + 1 > length - 1:
                next += first
            else:
                second = template[i+1]
                combined = first + second
                middle = rules[combined]
                next += first + middle
        template = next

    counts = {}
    for c in template:
        if c in counts:
            counts[c] += 1
        else:
            counts[c] = 1
    """

    import collections
    # part two
    counts = {}
    q = collections.deque()

    for i, c in enumerate(template):
        if c in counts:
            counts[c] += 1
        else:
            counts[c] = 1
        if i == len(template) - 1:
            break
        first_letter = template[i]
        second_letter = template[i + 1]
        combined = first_letter + second_letter
        q.appendleft(combined)

    # print(q)

    for step in range(40):
        print(step)
        next_queue = collections.deque()
        while len(q):
            current = q.pop()
            next = rules[current]
            if next in counts:
                counts[next] += 1
            else:
                counts[next] = 1
            next_queue.appendleft(current[0] + next)
            next_queue.appendleft(next + current[1])
        # print("next: ", next_queue)
        q = next_queue

    # l = 20
    # add = l - 1
    # for _ in range(40):
    #     l  += add
    #     add *= 2
    # print("L : ", l)

    # print(counts)
    sorted_counts = sorted(counts.values())
    print(sorted_counts[len(sorted_counts) - 1] - sorted_counts[0])


from collections import Counter
import string
import math
def array_int():
    return [int(i) for i in input().split()]
def vary(number_of_variables):
    if number_of_variables==1:
        return int(input())
    if number_of_variables>=2:
        return map(int,input().split())
def makedict(var):
    return dict(Counter(var))
mod=1000000007
p,x=vary(2)
ans=0
def find(b):
    global ans
    tt=((b*(pow(10,p-1,((10*x)-1))-x)))/((10*x)-1)
    #print(int(tt))
    if math.ceil(tt)==int(tt):
        if len(str(int(tt)))==p-1:
            ans=int(tt)
            return 1
        else:
            return 0
    else:
        return 0
for i in range(1,10):
    if find(i):
        print(ans*10+i)
        break
else:
    print('Impossible')


import pandas
from pandas import DataFrame
import traceback

from LazyLuna.Tables.Table import *
from LazyLuna.loading_functions import *
from LazyLuna.Metrics import *

class LAX_CC_Metrics_Table(Table):
    def calculate(self, view, cc, contname, fixed_phase_first_reader=False, pretty=True):
        """Presents table of Metric values for a Case_Comparison

        Args:
            view (LazyLuna.Views.View): a view for the analysis
            cc (LazyLuna.Containers.Case_Comparison): contains two comparable cases
            contname (str): contour type to analyze
            fixed_phase_first_reader (bool): if True: forces phase for comparisons to the first reader's phase
            pretty (bool): if True casts metric values to strings with two decimal places
        """
        dsc_m, hd_m, areadiff_m = DiceMetric(), HausdorffMetric(), AreaDiffMetric()
        case1, case2 = cc.case1, cc.case2
        cats1, cats2 = view.get_categories(case1, contname), view.get_categories(case2, contname)
        cols, row = [], []
        for cat1, cat2 in zip(cats1, cats2):
            try:
                p1, p2 = (cat1.phase, cat2.phase) if not fixed_phase_first_reader else (cat1.phase, cat1.phase)
                dcm = cat1.get_dcm(0, p1)
                anno1, anno2 = cat1.get_anno(0, p1), cat2.get_anno(0, p2)
                cont1, cont2 = anno1.get_contour(contname), anno2.get_contour(contname)
                area_diff = areadiff_m.get_val(cont1, cont2, dcm, string=pretty)
                dsc       = dsc_m.get_val(cont1, cont2, dcm, string=pretty)
                hd        = hd_m.get_val(cont1, cont2, dcm, string=pretty)
                has_cont1, has_cont2 = anno1.has_contour(contname), anno2.has_contour(contname)
                row.extend([area_diff, dsc, hd, has_cont1, has_cont2])
            except Exception as e: row.extend([np.nan, np.nan, np.nan, np.nan, np.nan]); print(traceback.format_exc())
            cols.extend([cat1.name+' Area Diff', cat1.name+' DSC', cat1.name+' HD', cat1.name+' hascont1', cat1.name+' hascont2'])
        self.df = DataFrame([row], columns=cols)


from helper import FlaskBaseTestCase
import clientapp
import helper
from flask import url_for
from clientapp.helpers.client_handler import ClientHandler
from unittest.mock import MagicMock, patch

class TestRegisterEndpoint(FlaskBaseTestCase):

    def test_if_app_has_register_endpoint(self):
        self.assertIn(
            'register',
            helper.app_endpoints(clientapp.create_app())
        )

    def test_if_endpoint_accepts_post(self):
        methods = None
        for rule in self.app.url_map.iter_rules('register'):
            methods = rule.methods
        self.assertIn(
            'POST',
            methods
        )

    # def test_init_should_call_discover_once(self):
    #     ClientHandler.discover = MagicMock(name='discover')
    #     ClientHandler.discover.return_value = helper.OP_DATA_DICT_RESPONSE
    #     ClientHandler.discover.assert_called_once()

    def test_endpoint_should_return_valid_req(self):
        self.assertIn(
            self.client.post(url_for('register')).status_code,
            range(100, 511),
            '/register returned invalid requisition'
        )

    @patch('clientapp.helpers.client_handler.ClientHandler.__init__', MagicMock(return_value=None))
    def test_endpoint_should_init_client_handler(self):
        self.client.post(url_for('register'), json={
            'op_url': 'https://test.com',
            'redirect_uris': ['https://clienttoberegistered.com/oidc_callback']
        })
        ClientHandler.__init__.assert_called_once()

    @patch('clientapp.helpers.client_handler.ClientHandler.__init__', MagicMock(return_value=None))
    def test_endpoint_should_accept_2_params(self):
        first_value = 'https://op'
        second_value = ['https://client.com.br/oidc_callback']

        self.client.post(url_for('register'), json={
            'op_url': first_value,
            'redirect_uris': second_value
        })
        ClientHandler.__init__.assert_called_once_with(first_value, second_value, {})

    @patch('clientapp.helpers.client_handler.ClientHandler.__init__', MagicMock(return_value=None))
    def test_endpoint_should_accept_3_params(self):
        first_value = 'https://op'
        second_value = ['https://client.com.br/oidc_callback']
        third_value = {'scope': 'openid email profile'}

        self.client.post(url_for('register'), json={
            'op_url': first_value,
            'redirect_uris': second_value,
            'additional_params': third_value
        })

        ClientHandler.__init__.assert_called_once_with(first_value, second_value, third_value)

    def test_endpoint_should_return_error_code_400_if_no_data_sent(self):
        self.assertEqual(
            self.client.post(url_for('register')).status_code,
            400,
            'status_code for empty request is NOT 400'
        )

    def test_should_return_400_error_if_no_needed_keys_provided(self):
        self.assertEqual(
            self.client.post(url_for('register'), json={
                'other_key': 'othervalue',
                'another_key': 'another_value'
            }).status_code,
            400,
            'not returning 400 code if no needed keys provided'
        )

    def test_should_return_400_if_values_are_not_valid_urls(self):
        self.assertEqual(
            self.client.post(url_for('register'), json={
                'op_url': 'not_valid_url',
                'redirect_uris': ['https://clienttoberegistered.com/oidc_callback']
            }).status_code,
            400,
            'not returning status 400 if values are not valid urls'
        )

    @patch('clientapp.helpers.client_handler.ClientHandler.get_client_dict', MagicMock(return_value=None))
    def test_valid_post_should_should_call_get_client_dict_once(self):
        op_url = 'https://op.com.br'
        self.client.post(url_for('register'), json={
            'op_url': op_url,
            'redirect_uris': ['https://clienttoberegistered.com/oidc_callback']
        })
        ClientHandler.get_client_dict.assert_called_once()

    def test_should_should_return_200_if_registered(self):
        op_url = 'https://op.com.br'
        test_client_id = '1234-5678-9ten11'
        test_client_secret = 'mysuperprotectedsecret'
        with patch.object(ClientHandler, 'get_client_dict', return_value={
            'op_metadata_url': '%s/.well-known/open-id-configuration' % op_url,
            'client_id': test_client_id,
            'client_secret': test_client_secret
        }) as get_client_dict:
            response = self.client.post(url_for('register'), json={
                'op_url': op_url,
                'redirect_uris': ['https://clienttoberegistered.com/oidc_callback']
            })
            self.assertEqual(response.status_code, 200)
            get_client_dict.reset()

    def test_should_return_expected_keys(self):
        op_url = 'https://op.com.br'
        redirect_uris = ['https://client.com.br/oidc_calback']
        test_client_id = '1234-5678-9ten11'
        test_client_secret = 'mysuperprotectedsecret'
        additional_params = {'param1': 'value1'}

        expected_keys = {'op_metadata_url', 'client_id', 'client_secret'}

        with patch.object(ClientHandler, 'get_client_dict', return_value={
            'op_metadata_url': '%s/.well-known/open-id-configuration' % op_url,
            'client_id': test_client_id,
            'client_secret': test_client_secret
        }) as get_client_dict:
            response = self.client.post(url_for('register'), json={
                'op_url': op_url,
                'redirect_uris': redirect_uris,
                'additional_params': additional_params
            })
            print(response)
            assert expected_keys <= response.json.keys(), response.json

            get_client_dict.reset()


import swisseph as swe

# These are present in http://www.astro.com/swisseph/swephprg.htm#_Toc471829094 but not in the swe python module.
import jyotisha
from indic_transliteration import sanscript
from jyotisha.custom_transliteration import tr
from jyotisha.panchaanga.temporal.names.init_names_auto import init_names_auto

def get_ayanaamsha_name(ayanaamsha_id):
  return swe.get_ayanamsa_name(ayanaamsha_id)

def get_ekaadashii_name(paksha, lmonth):
  """Return the name of an ekaadashii
  """
  if paksha == "shukla":
    if lmonth == int(lmonth):
      return "%s-EkAdazI" % NAMES["SHUKLA_EKADASHI_NAMES"]["sa"][sanscript.roman.HK_DRAVIDIAN][lmonth]
    else:
      # adhika mAsam
      return "%s-EkAdazI" % NAMES["SHUKLA_EKADASHI_NAMES"]["sa"][sanscript.roman.HK_DRAVIDIAN][13]
  elif paksha == "krishna":
    if lmonth == int(lmonth):
      return "%s-EkAdazI" % NAMES["KRISHNA_EKADASHI_NAMES"]["sa"][sanscript.roman.HK_DRAVIDIAN][lmonth]
    else:
      # adhika mAsam
      return "%s-EkAdazI" % NAMES["KRISHNA_EKADASHI_NAMES"]["sa"][sanscript.roman.HK_DRAVIDIAN][13]

def get_chandra_masa(month, script, visarga=True):
  if visarga:
    if month == int(month):
      return NAMES["CHANDRA_MASA_NAMES"]["sa"][script][int(month)]
    else:
      return "%s-%s" % (tr("adhika", script, titled=False), NAMES["CHANDRA_MASA_NAMES"]["sa"][script][int(month) + 1])
  else:
    if month == int(month):
      return NAMES["CHANDRA_MASA_NAMES"]["sa"][script][int(month)][:-1]
    else:
      return "%s-%s" % (tr("adhika", script, titled=False), NAMES["CHANDRA_MASA_NAMES"]["sa"][script][int(month) + 1][:-1])

def get_month_name_en(month_number, month_type, script=sanscript.ISO):
  from jyotisha.panchaanga.temporal.festival.rules import RulesRepo
  if month_number == 0:
    return "every"
  if month_type == RulesRepo.LUNAR_MONTH_DIR:
    return get_chandra_masa(month_number, script)
  elif month_type == RulesRepo.SIDEREAL_SOLAR_MONTH_DIR:
    return NAMES['RASHI_NAMES']['sa'][script][month_number]
  elif month_type == RulesRepo.TROPICAL_MONTH_DIR:
    return NAMES['RTU_MASA_NAMES_SHORT']['sa'][script][month_number]
  elif month_type == RulesRepo.GREGORIAN_MONTH_DIR:
    return month_map[month_number]

def get_samvatsara_name(offset_from_1987, samvatsara_index_1987=1):
  from jyotisha.panchaanga.temporal import Anga
  from jyotisha.panchaanga.temporal import AngaType
  samvatsara = offset_from_1987 + Anga(index=samvatsara_index_1987, anga_type_id=AngaType.SAMVATSARA)
  return samvatsara.get_name()

NAMES = init_names_auto()
month_map = {1: "January", 2: "February", 3: "March", 4: "April",
             5: "May", 6: "June", 7: "July", 8: "August", 9: "September",
             10: "October", 11: "November", 12: "December"}
weekday_short_map = {0: "Sun", 1: "Mon", 2: "Tue",
                     3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat"}
weekday_map = {0: "Sunday", 1: "Monday", 2: "Tuesday", 3: "Wednesday", 4: "Thursday", 5: "Friday", 6: "Saturday"}
SHULAM = NAMES["SHUULAM"]["sa"]
python_to_devanaagarii = {
  "braahma": "ब्राह्मं मुहूर्तम्",
  "praatah": "प्रातः",
  "aparaahna": "अपराह्णः",
  "aparaahna3": "अपराह्णः~(त्रेधा)",
  "saangava": "साङ्गवः",
  "madhyaahna": "मध्याह्नः",
  "madhyaahna3": "मध्याह्नः~(त्रेधा)",
  "saayaahna": "सायाह्नः",
  "pradosha": "प्रदोषः",
  "saayam_sandhyaa": "सायंसन्ध्यावन्दनकालः",
  "praatas_sandhyaa": "प्रातःसन्ध्यावन्दनकालः",
  "madhyaraatri": "मध्यरात्रिः",
  "nishiitha": "निशीथः",
  "raahu": "राहुकालः",
  "gulika": "गुलिककालः",
  "raatri_gulika": "रात्रौ गुलिककालः",
  "yama": "यमघण्टः",
  "raatri_yama": "रात्रौ यमघण्टः",
  "raatri_yaama": "रात्रौ यामाः",
  "raatri_yaama_1": "रात्रौ यामः १",
  "raatri_yaama_2": "रात्रौ यामः २",
  "raatri_yaama_3": "रात्रौ यामः ३",
  "raatri_yaama_4": "रात्रौ यामः ४",
  "ahar_yaama": "अह्नि यामाः",
  "ahar_yaama_1": "अह्नि यामः १",
  "ahar_yaama_2": "अह्नि यामः २",
  "ahar_yaama_3": "अह्नि यामः ३",
  "ahar_yaama_4": "अह्नि यामः ४",
  "shraadhaarambha_mukhya": "श्राद्धारम्भ-कालः (मुख्यः)",
  "shraadhaarambha_gauna": "श्राद्धारम्भ-कालः (गौणः)",
  "shraadha_kaala": "श्राद्ध-कालः",
  "shayana": "शयनकालः",
  "dinaanta": "दिनान्तम्",
  "preceding_arunodaya": "प्राक्तनारुणोदयः",
  "maadhyaahnika_sandhyaa": "माध्याह्निकसन्ध्यावन्दनकालः",
  "puurvaahna": "पूर्वाह्णः",
  "puurvaahna3": "पूर्वाह्णः~(त्रेधा)",
  "raatrimaana": "रात्रिमानम्",
  "dinamaana": "दिनमानम्",
  "sunrise": "सूर्योदयः",
  "sunset": "सूर्यास्तमयः",
  "moonrise": "चन्द्रोदयः",
  "raudra" : "रौद्रः",
  "chaitra" : "चैत्रः",
  "maitra" : "मैत्रः",
  "saalakata" : "सालकटः",
  "saavitra" : "सावित्रः",
  "jayanta" : "जयन्तः",
  "gaandharva" : "गान्धर्वः",
  "kutapa" : "कुतपः",
  "rauhina" : "रौहिणः",
  "virinchi" : "विरिञ्चिः",
  "vijaya" : "विजयः",
  "nairrita" : "नैर्‌ऋतः",
  "mahendra" : "महेन्द्रः",
  "varuna" : "वरुणः",
  "bodha" : "बोधः",
  "shankara" : "शङ्करः",
  "ajapaat" : "अजपात्",
  "ahirbudhnya" : "अहिर्बुध्न्यः",
  "puushaka" : "पूषकः",
  "aashvina" : "आश्विनः",
  "yaamyava" : "याम्यः",
  "aahneya" : "आह्नेयः",
  "vaidhaatra" : "वैधात्रः",
  "chaandra" : "चान्द्रः",
  "aaditeya" : "आदितेयः",
  "jaiva" : "जैवः",
  "vaishnava" : "वैष्णवः",
  "saura" : "सौरः",
  "succeeding_braahma" : "ब्राह्मः",
  "naabhasvata" : "नाभस्वतः",
  "durmuhurta1" : "दुर्मुहूर्तः १",
  "durmuhurta2" : "दुर्मुहूर्तः २",
}

devanaagarii_to_python = {python_to_devanaagarii[x]: x for x in python_to_devanaagarii }

sa_to_tamil = dict(**NAMES["SA_TO_TAMIL"], **{sanscript.transliterate(x, sanscript.DEVANAGARI, sanscript.roman.HK_DRAVIDIAN):NAMES["SA_TO_TAMIL"][x] for x  in NAMES["SA_TO_TAMIL"]})

def translate_or_transliterate(text, script, source_script=sanscript.roman.HK_DRAVIDIAN):
  if script == "tamil":
    if text in sa_to_tamil:
      return sa_to_tamil[text]
    else:
      return jyotisha.custom_transliteration.tr(text, script, source_script=source_script)
  else:
    return jyotisha.custom_transliteration.tr(text, script, source_script=source_script)

def get_tipu_month_str(month):
  """

  Reference: https://toshkhana.wordpress.com/2014/09/19/dawn-of-a-new-era-tipu-sultan-and-his-mauludi-calendar/
  :param month:
  :return:
  """
  if month == int(month):
    month_str = " / ".join([NAMES["TIPU_ABJAD_MONTH_NAMES"]["fa"][int(month) - 1], NAMES["TIPU_ABTATH_MONTH_NAMES"]["fa"][int(month) - 1]])
    return month_str
  else:
    month_str = " / ".join([NAMES["TIPU_ABJAD_MONTH_NAMES"]["fa"][int(month)], NAMES["TIPU_ABTATH_MONTH_NAMES"]["fa"][int(month)]])
    return "%s (adhika)" % (month_str)


import unittest
from collections import namedtuple
from ripe.atlas.tools.renderers.aggregate_ping import Renderer
from ripe.atlas.sagan import Result

from ..base import capture_sys_output

class TestAggregatePing(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.results = [
            {u'af': 4, u'prb_id': 11421, u'result': [{u'rtt': 42.342895}, {u'rtt': 42.220215}, {u'rtt': 42.40614}], u'ttl': 53, u'avg': 42.3230833333, u'size': 48, u'from': u'178.11.85.39', u'proto': u'ICMP', u'timestamp': 1446146495, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 42.40614, u'step': 240, u'src_addr': u'192.168.2.101', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 3, u'dst_name': u'194.88.241.228', u'min': 42.220215, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 11779, u'result': [{u'rtt': 76.61127}, {u'rtt': 76.38997}, {u'rtt': 76.47354}], u'ttl': 51, u'avg': 76.4915933333, u'size': 48, u'from': u'79.106.99.242', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 76.61127, u'step': 240, u'src_addr': u'192.168.1.110', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 127, u'dst_name': u'194.88.241.228', u'min': 76.38997, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 17854, u'result': [{u'rtt': 154.118}, {u'rtt': 154.197}, {u'rtt': 154.845}], u'ttl': 55, u'avg': 154.3866666667, u'size': 48, u'from': u'134.202.20.3', u'proto': u'ICMP', u'timestamp': 1446146493, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4700, u'max': 154.845, u'step': 240, u'src_addr': u'134.202.20.3', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 1, u'dst_name': u'194.88.241.228', u'min': 154.118, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 3183, u'result': [{u'rtt': 42.263816}, {u'rtt': 42.196233}, {u'rtt': 42.342921}], u'ttl': 56, u'avg': 42.2676566667, u'size': 48, u'from': u'212.122.42.107', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 42.342921, u'step': 240, u'src_addr': u'192.168.189.1', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 3, u'dst_name': u'194.88.241.228', u'min': 42.196233, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 3207, u'result': [{u'rtt': 218.077484}, {u'rtt': 36.921608}, {u'rtt': 38.99444}], u'ttl': 49, u'avg': 97.997844, u'size': 48, u'from': u'134.3.245.244', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 218.077484, u'step': 240, u'src_addr': u'10.30.0.4', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 70, u'dst_name': u'194.88.241.228', u'min': 36.921608, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'}
        ]
        cls.sagans = [
            Result.get(
                result,
                on_error=Result.ACTION_IGNORE,
                on_warning=Result.ACTION_IGNORE
            ) for result in cls.results
        ]

    def test_additional(self):
        """Tests whole functionality of additional unit."""
        expected_output = (
            "-- 194.88.241.228 ping statistics ---\n"
            "15 packets transmitted, 15 received, 0.0% loss\n"
            "rtt min/med/avg/max = 36.921608/42.406/82.693/218.077484 ms\n\n"
        )

        self.assertEquals(Renderer().additional(self.sagans), expected_output)

    def test_collect_stats(self):
        """Tests collect stats function."""

        renderer = Renderer()
        renderer.collect_stats(self.sagans)
        self.assertEquals(
            renderer.rtts,
            [
                42.343, 42.22, 42.406, 76.611, 76.39, 76.474, 154.118, 154.197,
                154.845, 42.264, 42.196, 42.343, 218.077, 36.922, 38.994
            ]
        )
        self.assertEquals(renderer.target, "194.88.241.228")
        self.assertEquals(renderer.sent_packets, 15)
        self.assertEquals(renderer.received_packets, 15)
        self.assertEquals(
            renderer.rtts_min,
            [42.220215, 76.38997, 154.118, 42.196233, 36.921608]
        )
        self.assertEquals(
            renderer.rtts_max,
            [42.40614, 76.61127, 154.845, 42.342921, 218.077484]
        )

    def test_collect_min_max_rtts(self):
        """Test use cases for collecting min max rtts."""
        renderer = Renderer()
        renderer.collect_min_max_rtts("min", 3)
        self.assertEquals(renderer.rtts_min, [3])
        renderer.collect_min_max_rtts("min", None)
        self.assertEquals(renderer.rtts_min, [3, 0])

        renderer.collect_min_max_rtts("max", 3)
        self.assertEquals(renderer.rtts_max, [3])
        renderer.collect_min_max_rtts("max", None)
        self.assertEquals(renderer.rtts_max, [3, 0])

    def test_collect_packets_rtt(self):
        """Test use cases for collecting rtts."""
        Packet = namedtuple("Packet", "rtt")
        packets = [Packet(rtt=2), Packet(rtt=3.2), Packet(rtt=5.0)]
        renderer = Renderer()
        renderer.collect_packets_rtt(packets)
        self.assertEquals(renderer.rtts, [2, 3.2, 5.0])

        packets = [Packet(rtt=None), Packet(rtt=3.2), Packet(rtt=5.0)]
        renderer = Renderer()
        renderer.collect_packets_rtt(packets)
        self.assertEquals(renderer.rtts, [0, 3.2, 5.0])

    def test_set_target(self):
        """Tests setting the target."""
        Sagan = namedtuple("Sagan", "destination_name")
        renderer = Renderer()
        sagan = Sagan(destination_name="1")
        renderer.set_target(sagan)
        self.assertEquals(renderer.target, "1")
        sagan = Sagan(destination_name="2")
        renderer.set_target(sagan)
        self.assertEquals(renderer.target, "1")

    def test_calculate_loss(self):
        """Test use cases for calculating loss."""
        renderer = Renderer()
        renderer.sent_packets = 10
        renderer.received_packets = 9
        self.assertEquals(renderer.calculate_loss(), 9.999999999999998)
        renderer.sent_packets = 0
        self.assertEquals(renderer.calculate_loss(), 0)
        renderer.received_packets = 0
        renderer.sent_packets = 10
        self.assertEquals(renderer.calculate_loss(), 100)
        renderer.received_packets = 5
        self.assertEquals(renderer.calculate_loss(), 50)

    def test_mean(self):
        """Test use cases for calculating mean."""
        renderer = Renderer()
        renderer.rtts = [0, 2.0, 5.0, 20]
        self.assertEquals(renderer.mean(), 6.75)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20]
        self.assertEquals(renderer.mean(), 6.9)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20, 50]
        self.assertEquals(renderer.mean(), 14.083)

    def test_median(self):
        """Test use cases for calculating median."""
        renderer = Renderer()
        renderer.rtts = [0, 2.0, 5.0, 20]
        self.assertEquals(renderer.median(), 3.5)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20]
        self.assertEquals(renderer.median(), 5)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20, 50]
        self.assertEquals(renderer.median(), 6.25)


# Analog PyGame clock

import pygame
import pygame_gui
from pygame_gui.elements.ui_image import UIImage

from math import pi, cos, sin
import datetime

DARK = 33, 41, 46
WHITE = 255, 255, 255
GRAY = 76, 80, 82
RED = 255, 0, 0

class SnakeAClock(pygame_gui.elements.UIWindow):
    DIMS = (300, 300)

    def __init__(self, pos, manager):
        super().__init__(
            pygame.Rect(pos, (self.DIMS[0] + 32, self.DIMS[1] + 60)),
            manager=manager,
            window_display_title="aclock",
            object_id="#aclock",
            resizable=True,
        )

        self.dsurf = UIImage(
            pygame.Rect((0, 0), self.DIMS),
            pygame.Surface(self.DIMS).convert(),
            manager=manager,
            container=self,
            parent_element=self,
        )
        self.draw_dial()
        self.clean_dial = self.dial.copy()
        self.manager = manager

    def process_event(self, event):
        super().process_event(event)
        r = super().get_abs_rect()
        if event.type == pygame.MOUSEBUTTONUP and (
            r.w != self.DIMS[0] + 32 or r.h != self.DIMS[1] + 60
        ):
            self.DIMS = r.w - 32, r.h - 60
            super().kill()
            self.__init__((r.left, r.top), self.manager)

    def update(self, delta):
        super().update(delta)
        self.dial = self.clean_dial.copy()
        self.draw_hands()
        self.dsurf.image.blit(self.dial, (0, 0))

    def clocksize(self):
        return int(0.95 * min(self.DIMS) / 2)

    def diam(self, x, r1, r2, r3, dx):
        x1, y1 = (
            r1 * self.clocksize() * sin(x * pi / 180),
            r1 * self.clocksize() * cos(x * pi / 180),
        )
        x2, y2 = (
            r2 * self.clocksize() * sin((x + dx) * pi / 180),
            r2 * self.clocksize() * cos((x + dx) * pi / 180),
        )
        x3, y3 = (
            r3 * self.clocksize() * sin(x * pi / 180),
            r3 * self.clocksize() * cos(x * pi / 180),
        )
        x4, y4 = (
            r2 * self.clocksize() * sin((x - dx) * pi / 180),
            r2 * self.clocksize() * cos((x - dx) * pi / 180),
        )
        p = [
            (int(x1 + self.DIMS[0] // 2), int(-y1 + self.DIMS[1] // 2)),
            (int(x2 + self.DIMS[0] // 2), int(-y2 + self.DIMS[1] // 2)),
            (int(x3 + self.DIMS[0] // 2), int(-y3 + self.DIMS[1] // 2)),
            (int(x4 + self.DIMS[0] // 2), int(-y4 + self.DIMS[1] // 2)),
        ]
        pygame.draw.polygon(self.dial, WHITE, p)

    def draw_dial(self):
        self.dial = pygame.Surface(self.DIMS)
        self.dial.fill(DARK)
        pygame.draw.circle(
            self.dial, WHITE, (self.DIMS[0] // 2, self.DIMS[1] // 2), self.clocksize()
        )
        pygame.draw.circle(
            self.dial,
            GRAY,
            (self.DIMS[0] // 2, self.DIMS[1] // 2),
            int(0.99 * self.clocksize()),
        )
        for x in range(60):
            if x % 5 == 0:
                continue
            x1, y1 = (
                0.95 * self.clocksize() * sin(6 * x * pi / 180),
                0.95 * self.clocksize() * cos(6 * x * pi / 180),
            )
            x2, y2 = (
                0.92 * self.clocksize() * sin(6 * x * pi / 180),
                0.92 * self.clocksize() * cos(6 * x * pi / 180),
            )
            pygame.draw.line(
                self.dial,
                WHITE,
                (int(x1 + self.DIMS[0] // 2), int(y1 + self.DIMS[1] // 2)),
                (int(x2 + self.DIMS[0] // 2), int(y2 + self.DIMS[1] // 2)),
                2,
            )
        for x in range(0, 360, 30):
            if x % 90 == 0:
                self.diam(x, 0.95, 0.88, 0.88, 2)
            else:
                self.diam(x, 0.95, 0.95, 0.87, 1)

    def draw_hands(self):
        # hour hand
        now = datetime.datetime.now()
        x = 30 * ((now.hour - 12) % 12) + now.minute / 2
        self.diam(x, 0.45, 0.08, -0.08, 30)

        # minute hand
        x = 6 * now.minute + now.second / 10
        self.diam(x, 0.75, 0.08, -0.08, 25)

        # second hand
        x = 6 * now.second
        x1, y1 = (
            0.8 * self.clocksize() * sin(x * pi / 180),
            0.8 * self.clocksize() * cos(x * pi / 180),
        )
        x2, y2 = 0, 0
        pygame.draw.line(
            self.dial,
            RED,
            (int(x1 + self.DIMS[0] // 2), int(-y1 + self.DIMS[1] // 2)),
            (int(x2 + self.DIMS[0] // 2), int(-y2 + self.DIMS[1] // 2)),
            3,
        )


# import os
# os.environ['CUDA_VISIBLE_DEVICES']='1'
import torch
import torch.nn as nn
import configs
import torch.nn.functional as nnf
from Moudules import *
from einops.layers.torch import Rearrange
from einops import rearrange
import torchvision

class Conv3dReLU(nn.Sequential):
    def __init__(
            self,
            in_channels,
            out_channels,
            kernel_size,
            padding=0,
            stride=1,
            use_batchnorm=True,
    ):
        conv = nn.Conv3d(
            in_channels,
            out_channels,
            kernel_size,
            stride=stride,
            padding=padding,
            bias=False,
        )
        relu = nn.LeakyReLU(inplace=True)
        if not use_batchnorm:
            nm = nn.InstanceNorm3d(out_channels)
        else:
            nm = nn.BatchNorm3d(out_channels)

        super(Conv3dReLU, self).__init__(conv, nm, relu)

class DecoderBlock(nn.Module):
    def __init__(
            self,
            in_channels,
            out_channels,
            skip_channels=0,
            use_batchnorm=True,
    ):
        super().__init__()
        self.conv1 = Conv3dReLU(
            in_channels + skip_channels,
            out_channels,
            kernel_size=3,
            padding=1,
            use_batchnorm=use_batchnorm,
        )
        self.conv2 = Conv3dReLU(
            out_channels,
            out_channels,
            kernel_size=3,
            padding=1,
            use_batchnorm=use_batchnorm,
        )
        self.up = nn.Upsample(scale_factor=2, mode='trilinear', align_corners=False)

    def forward(self, x, skip=None):
        x = self.up(x)
        if skip is not None:
            x = torch.cat([x, skip], dim=1)
        x = self.conv1(x)
        x = self.conv2(x)
        return x

class RegistrationHead(nn.Sequential):
    def __init__(self, in_channels, out_channels, kernel_size=3, upsampling=1):
        conv3d = nn.Conv3d(in_channels, out_channels, kernel_size=kernel_size, padding=kernel_size // 2)
        conv3d.weight = nn.Parameter(Normal(0, 1e-5).sample(conv3d.weight.shape))
        conv3d.bias = nn.Parameter(torch.zeros(conv3d.bias.shape))
        super().__init__(conv3d)

class SpatialTransformer(nn.Module):
    """
    N-D Spatial Transformer
    Obtained from https://github.com/voxelmorph/voxelmorph
    """

    def __init__(self, size, mode='bilinear'):
        super().__init__()

        self.mode = mode

        vectors = [torch.arange(0, s) for s in size]
        grids = torch.meshgrid(vectors)
        grid = torch.stack(grids)
        grid = torch.unsqueeze(grid, 0)
        grid = grid.type(torch.FloatTensor)

        self.register_buffer('grid', grid)

    def forward(self, src, flow):

        new_locs = self.grid + flow
        shape = flow.shape[2:]

        for i in range(len(shape)):
            new_locs[:, i, ...] = 2 * (new_locs[:, i, ...] / (shape[i] - 1) - 0.5)

        if len(shape) == 2:
            new_locs = new_locs.permute(0, 2, 3, 1)
            new_locs = new_locs[..., [1, 0]]
        elif len(shape) == 3:
            new_locs = new_locs.permute(0, 2, 3, 4, 1)
            new_locs = new_locs[..., [2, 1, 0]]

        return nnf.grid_sample(src, new_locs, align_corners=True, mode=self.mode)

class PatchEmbed(nn.Module):
    """ Image to Patch Embedding
    Args:
        patch_size (int): Patch token size. Default: 4.
        in_chans (int): Number of input image channels. Default: 3.
        embed_dim (int): Number of linear projection output channels. Default: 96.
        norm_layer (nn.Module, optional): Normalization layer. Default: None
    """

    def __init__(self, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
        super().__init__()
        patch_size = to_3tuple(patch_size)
        self.patch_size = patch_size

        self.in_chans = in_chans
        self.embed_dim = embed_dim

        self.proj = nn.Conv3d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)
        if norm_layer is not None:
            self.norm = norm_layer(embed_dim)
        else:
            self.norm = None

    def forward(self, x):
        """Forward function."""

        _, _, H, W, T = x.size()
        if W % self.patch_size[1] != 0:
            x = nnf.pad(x, (0, self.patch_size[1] - W % self.patch_size[1]))
        if H % self.patch_size[0] != 0:
            x = nnf.pad(x, (0, 0, 0, self.patch_size[0] - H % self.patch_size[0]))
        if T % self.patch_size[0] != 0:
            x = nnf.pad(x, (0, 0, 0, 0, 0, self.patch_size[0] - T % self.patch_size[0]))

        x = self.proj(x)
        if self.norm is not None:
            Wh, Ww, Wt = x.size(2), x.size(3), x.size(4)
            x = x.flatten(2).transpose(1, 2)
            x = self.norm(x)
            x = x.transpose(1, 2).view(-1, self.embed_dim, Wh, Ww, Wt)

        return x

#
# class AttnWindowAttn(nn.Module):
#     def __init__(self, dim, factor=0.25):
#         """
#         """
#         super(AttnWindowAttn, self).__init__()
#         self.factor=factor
#         self.mlp = nn.Sequential(
#             nn.Linear(dim, dim * self.factor),
#             nn.ReLU(),
#             nn.Linear(dim * self.factor, dim)
#         )
#         self.sigmoid = nn.Sigmoid()
#
#     def forward(self, x):
#         """
#
#         :param x: [B L C]
#         :return:
#         """
#
#         y = torch.mean(x, dim=1, keepdim=True)
#         y = self.mlp(y)
#         y = self.sigmoid(y)
#         y = y.expand_as(x)
#         attn_window = y * x
#
#         return attn_window

class HeadTrans(nn.Sequential):
    def __init__(self, shape):
        super(HeadTrans, self).__init__()
        self.shape = shape
        self.patch_emb = nn.Sequential(
            nn.Conv3d(2, 16, 3, 1, 1),
            nn.LeakyReLU(0.2),
            nn.Conv3d(16, 32, 3, 2, 1),
            nn.LeakyReLU(0.2),
            nn.Conv3d(32, 96, 3, 2, 1),
            nn.LeakyReLU(0.2),
            Rearrange('B C D H W -> B (D H W) C'),
            nn.LayerNorm(96),
            Rearrange('B (D H W) C -> B C D H W', D=shape[0] // 4, H=shape[1] // 4, W=shape[2] // 4)
        )

    def forward(self, x):
        y = self.patch_emb(x)
        return y

class SwinNet(nn.Module):
    def __init__(self, config):
        '''
        TransMorph Model
        '''
        super(SwinNet, self).__init__()

        if_convskip = config.if_convskip
        self.if_convskip = if_convskip
        if_transskip = config.if_transskip
        self.if_transskip = if_transskip
        embed_dim = config.embed_dim

        self.transformer = SwinTransformerHigh(patch_size=config.patch_size,
                                               in_chans=config.in_chans,
                                               embed_dim=config.embed_dim,
                                               depths=config.depths,
                                               num_heads=config.num_heads,
                                               window_size=config.window_size,
                                               mlp_ratio=config.mlp_ratio,
                                               qkv_bias=config.qkv_bias,
                                               drop_rate=config.drop_rate,
                                               drop_path_rate=config.drop_path_rate,
                                               ape=config.ape,
                                               spe=config.spe,
                                               patch_norm=config.patch_norm,
                                               use_checkpoint=config.use_checkpoint,
                                               out_indices=config.out_indices,
                                               pat_merg_rf=config.pat_merg_rf,
                                               )

        self.transformer.patch_embed = nn.Sequential()

        self.transformer.patch_embed.add_module('new_patch_emb', HeadTrans(config.img_size))

        self.up0 = DecoderBlock(embed_dim * 8, embed_dim * 4, skip_channels=embed_dim * 4 if if_transskip else 0,
                                use_batchnorm=False)
        self.up1 = DecoderBlock(embed_dim * 4, embed_dim * 2, skip_channels=embed_dim * 2 if if_transskip else 0,
                                use_batchnorm=False)
        self.up2 = DecoderBlock(embed_dim * 2, embed_dim, skip_channels=embed_dim if if_transskip else 0,
                                use_batchnorm=False)
        self.up3 = DecoderBlock(embed_dim, embed_dim // 2, skip_channels=embed_dim // 2 if if_convskip else 0,
                                use_batchnorm=False)
        self.up4 = DecoderBlock(embed_dim // 2, config.reg_head_chan,
                                skip_channels=config.reg_head_chan if if_convskip else 0,
                                use_batchnorm=False)
        self.c1 = Conv3dReLU(2, embed_dim // 2, 3, 1, use_batchnorm=False)
        self.c2 = Conv3dReLU(2, config.reg_head_chan, 3, 1, use_batchnorm=False)
        self.reg_head = RegistrationHead(
            in_channels=config.reg_head_chan,
            out_channels=3,
            kernel_size=3,
        )

        self.spatial_trans = SpatialTransformer(config.img_size)

    def forward(self, x):
        source = x[:, 0:1, :, :]

        out_feats = self.transformer(x)

        f1 = out_feats[-2]
        f2 = out_feats[-3]
        f3 = out_feats[-4]
        f4 = out_feats[-5]
        f5 = out_feats[-6]

        x = self.up0(out_feats[-1], f1)
        x = self.up1(x, f2)
        x = self.up2(x, f3)
        x = self.up3(x, f4)
        x = self.up4(x, f5)
        flow = self.reg_head(x)
        out = self.spatial_trans(source, flow)
        return out, flow

class PatchExpanding(nn.Module):
    def __init__(self, dim, scale_factor=8, bias=False):
        """
        Expand operation in decoder.
        :param dim: input token channels for expanding.
        :param scale_factor: the expanding scale for token channels.
        """
        super(PatchExpanding, self).__init__()
        self.dim = dim

        self.expander = nn.Sequential(
            Rearrange('B C D H W -> B D H W C'),
            nn.Linear(self.dim, scale_factor * self.dim, bias=bias),
            Rearrange('b D H W (h d w c) -> b (D d) (H h) (W w) c', d=2, h=2, w=2, c=self.dim // 2),

        )
        self.norm = nn.Sequential(
            nn.LayerNorm(self.dim // 2, eps=1e-6),
            Rearrange('B D H W C -> B C D H W')
        )

    def forward(self, x):
        """
        Run forward pass.
        :param x: torch.Tensor
            Input tokens.
        :return: x: torch.Tensor
            Output expanded tokens.
        """
        y = self.norm(self.expander(x))

        return y

CONFIGS = {
    'RFRANet': configs.RFRANet()}


# https://www.acmicpc.net/problem/1010

import sys

input = sys.stdin.readline

def factorial(num) :
    result = 1
    while num != 0 :
        result *= num
        num -= 1
    return result

def combination(a, b) :
    return factorial(a) // (factorial(b) * factorial(a - b))

T = int(input())

for _ in range(T) :
    N, M = map(int, input().split())
    print(combination(M, N))


import numpy as np
import time

#使用字典来存储数据
data = []
num = int(input('输入节点数'))
jiedian = int((num*(num-1)/2))
for n in range(1,jiedian+1):
    dict = {'导纳':'','l':'','r':''}
    G = int(input('导纳值电导'))
    B = int(input('导纳值电纳'))
    image = 1j
    dict['导纳'] = G + B*image
    dict['l'] = int(input('左节点'))
    dict['r'] = int(input('右节点'))
    data.append(dict)

def zero():
    #创建全0矩阵
    zarray = np.zeros((num,num),dtype=complex)
    return zarray

def buding(l,r,Y):
    zarray = zero()
    #单个元件的不定导纳矩阵
    zarray[l-1,l-1] = Y
    zarray[r-1,r-1] = Y
    zarray[l-1,r-1] = -Y
    zarray[r-1,l-1] = -Y
    # print(zarray,'\n')
    return zarray

def sum():
    #矩阵的相加

    sum = zero()
    for dict in data:
        array = buding(dict['l'],dict['r'],dict['导纳'])
        sum += array
    # print('求和矩阵')
    # print(sum)
    return sum

def result():
    #得到不定导纳矩阵
    budingjuzhen = sum()
    tmp1 = np.delete(budingjuzhen,0,axis=1)
    tmp2 = np.delete(tmp1,0,axis=0)
    budingjuzhen = tmp2
    # print('不定导纳矩阵\n')
    return budingjuzhen

def Zarray():
    #Z矩阵
    Z = np.linalg.pinv(result())  # 逆矩阵就是Z矩阵
    # print('逆矩阵\n', Z)
    return Z

time.sleep(2)
print('\n----开始----')

print('单个元件的导纳矩阵和\n',sum())
print('不定导纳矩阵\n',result())
print('逆矩阵\n', Zarray())

time.sleep(2)
print('\n----结束----')


from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from base64 import urlsafe_b64encode, urlsafe_b64decode
import os

def encrypt(plaintext, key):
    backend = default_backend()

    # Генерация случайного IV (Initialization Vector)
    iv = os.urandom(16)

    RawKey = padding.PKCS7(128).padder()
    Key_data = RawKey.update(key.encode()) + RawKey.finalize()

    cipher = Cipher(algorithms.AES(Key_data), modes.CFB(iv), backend=backend)
    encryptor = cipher.encryptor()

    # Добавление дополнения для обработки текстов с переменной длиной
    padder = padding.PKCS7(128).padder()
    padded_data = padder.update(plaintext.encode()) + padder.finalize()

    # Шифрование данных
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()

    # Кодирование IV и шифртекста в URL-безопасной Base64
    encrypted_message = urlsafe_b64encode(iv + ciphertext)

    return encrypted_message

def decrypt(encrypted_message, key):
    backend = default_backend()

    # Декодирование URL-безопасной Base64
    encrypted_message = urlsafe_b64decode(encrypted_message)

    # Извлечение IV из зашифрованных данных
    iv = encrypted_message[:16]
    ciphertext = encrypted_message[16:]

    cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=backend)
    decryptor = cipher.decryptor()

    # Расшифрование данных
    padded_data = decryptor.update(ciphertext) + decryptor.finalize()

    # Удаление дополнения
    unpadder = padding.PKCS7(128).unpadder()
    plaintext = unpadder.update(padded_data) + unpadder.finalize()

    return plaintext.decode()


peso_payaso = 112
peso_barbie = 75

cantidad_payasos = input("Cuantos payasos vendimos este mes? ")
cantidad_barbies = input("Cuantas muñecas vendimos este mes? ")

total_payasos = peso_payaso * int(cantidad_payasos)
total_barbies = peso_barbie * int(cantidad_barbies)
pedido_total = total_payasos+total_barbies

print("Este mes vendimos " + cantidad_payasos +" de payasos y " + cantidad_barbies + " de muñecas. Y el peso total del envío fue de " + str(pedido_total) + "gr")


from itertools import combinations
import math
def decimal(num):
    for i in range(2, int(math.sqrt(num))+1):
        if num%i == 0 :
            return False
    return True

def solution(nums):
    cnt = 0
    combs = combinations(nums, 3)
    for comb in combs:
        if decimal(sum(comb)):
            cnt += 1
    return cnt

nums = [1,2,3,4]
print(solution(nums))
#result = 1

nums = [1,2,7,6,4]
print(solution(nums))
#result = 4


#! /usr/bin/python3

import re

def get_input():
    content = ""
    with open('codeit.au3', 'r') as f:
        content = f.read()
    return content

def set_output(content):
    with open('codeit_deobfuscated.au3', 'w') as f:
        f.write(content)

def remove_numbers_definitions(content):
    definition_pattern = re.compile(r'''((Global )?(\$[A-Za-z]+) = (Number\(" (\d+) "\))(,\s*)?)''')

    for definition_match in re.findall(definition_pattern, content):
        whole_match = re.escape(definition_match[0])
        global_match = re.escape(definition_match[1])
        variable_match = re.escape(definition_match[2])
        number_obj = re.escape(definition_match[3])
        integer_value = definition_match[4]
        separator = re.escape(definition_match[5])

        content = re.sub(whole_match, "" , content)
        content = re.sub(variable_match, integer_value, content)
    return content

def remove_empty_lines(content):
    content = re.sub(r'''\n{2,}''', r'''\n\n''', content)
    return content

def concat_multiline_concats(content):
    definition_with_pattern = re.compile(r'''((Local\s*|Global\s*)?(\$[A-Za-z]+)(\s*=\s*")(.+)("\s*\n+\s*)(\$[A-Za-z]+)(\s*&=))''')

    for definition_match in re.findall(definition_with_pattern, content):

        variable_name_definion = re.escape(definition_match[2])
        variable_name_usage = re.escape(definition_match[6])
        if variable_name_definion != variable_name_usage:
            continue

        whole_definition_match = re.escape(definition_match[0])
        variable_param = definition_match[1]
        variable_initial_value = definition_match[4]
        new_variable_definition = variable_param + ' ' + definition_match[2] + ' = "' + variable_initial_value

        variable_usage_pattern = re.compile('(('+variable_name_definion+')(\s*&=\s*")([\$\w\d]+)("\n\t*))')
        for usage_match in re.findall(variable_usage_pattern, content):
            whole_usage_match = re.escape(usage_match[0])
            variable_concated_value = usage_match[3]
            new_variable_definition += variable_concated_value
            content = re.sub(whole_usage_match, '', content)
        new_variable_definition += '"'

        definition_pattern = re.compile(r'''((Local\s*|Global\s*)?('''+variable_name_definion+''')(\s*=\s*")(.+)("))''')
        content = re.sub(definition_pattern, new_variable_definition, content)

    return content

def unroll_arrays(content):
    string_split_pattern = re.compile(r'''((Local\s*|Global\s*)?(\$[A-Za-z]+)(\s*=\s*StringSplit\()(\$[A-Za-z]+)(,\s*")([\$\w\d]+)(",\s*)(\d)(\s*\)))''')
    for string_split_match in re.findall(string_split_pattern, content):
        separator = string_split_match[6]
        array_visibility = string_split_match[1]
        array_name = string_split_match[2]
        variable_name_to_split = string_split_match[4]
        variable_to_split_match = re.findall(r'''((Local\s*|Global\s*)?('''+re.escape(variable_name_to_split)+''')(\s*=\s*")(.+)("))''', content)[0]
        value_to_split = variable_to_split_match[4]
        content = re.sub(re.compile(re.escape(variable_to_split_match[0])), '', content)

        new_variable_definition = array_visibility + array_name + ';'
        i = 1
        for element in re.split(re.escape(separator), value_to_split):
            new_variable_definition += '\n' + array_name + '[' + str(i) + '] = "' + element + '"'
            i += 1

        old_variable_definition_pattern = re.compile(re.escape(string_split_match[0]))
        content = re.sub(old_variable_definition_pattern, new_variable_definition, content)

    return content

def remove_array(content, array_name):
    for i in range(1, 256):
        array_element_name = "\$" + array_name + "\[" + str(i) + "\]"
        array_element_definiton = '((' + array_element_name +')' + r'''\s*=\s*("[\w\d]*")''' + ')'
        array_element_definiton_pattern = re.compile(array_element_definiton)
        for array_element_definiton_match in re.findall(array_element_definiton_pattern, content):
            array_element_definiton_instance = array_element_definiton_match[0]
            array_element_usage = array_element_definiton_match[1]
            array_element_value = array_element_definiton_match[2]
            content = re.sub(re.escape(array_element_definiton_instance), '', content)
            content = re.sub(re.escape(array_element_usage), array_element_value, content)

    return content

def remove_character_encoding(content, encoder_name):
    encoder_usage_pattern = re.compile('(('+encoder_name+')' + r'''\("([\w\d]*)"\))''')
    for encoder_usage_match in re.findall(encoder_usage_pattern, content):
        encoder_usage = encoder_usage_match[0]
        encoded_string = encoder_usage_match[2]
        decoded_string = bytes.fromhex(encoded_string).decode("utf-8")
        content = re.sub(re.escape(encoder_usage), '"'+decoded_string+'"', content)
    return content

def remove_function(content, function_name):
    function_definition_pattern = re.compile(r'Func\s'+re.escape(function_name)+r'''[\w\d\&\$=\(\)\-\<\>\+.,_;\n\t\s]+?EndFunc''')
    for function_definition_match in re.findall(function_definition_pattern, content):
        content = re.sub(re.escape(function_definition_match), '', content)
    return content

def main():
    content = get_input()

    content = remove_numbers_definitions(content)
    content = concat_multiline_concats(content)
    content = remove_empty_lines(content)
    content = unroll_arrays(content)
    content = remove_array(content, 'os')
    content = remove_empty_lines(content)
    content = remove_character_encoding(content, 'arehdidxrgk')
    content = remove_function(content, 'areihnvapwn')
    content = remove_function(content, 'arehdidxrgk')
    content = remove_empty_lines(content)

    set_output(content)

if __name__ == "__main__":
    main()


from pico2d import *

TUK_WIDTH, TUK_HEIGHT = 1280, 1024

def handle_events():
    global running
    global x_dir, y_dir
    global sprite_num

    events = get_events()

    for event in events:
        if event.type == SDL_QUIT:
            running = False

        elif event.type == SDL_KEYDOWN:
            if event.key == SDLK_RIGHT:
                x_dir += 1
                y_dir = 0
                sprite_num = 1

            elif event.key == SDLK_LEFT:
                x_dir -= 1
                y_dir = 0
                sprite_num = 0

            elif event.key == SDLK_UP:
                x_dir = 0
                y_dir += 1

            elif event.key == SDLK_DOWN:
                x_dir = 0
                y_dir -= 1

            elif event.key == SDLK_ESCAPE:
                running = False

            elif event.type == SDL_KEYUP:
                if event.key == SDLK_RIGHT:
                    x_dir -= 1

                elif event.key == SDLK_LEFT:
                    x_dir += 1

                elif event.key == SDLK_UP:
                    y_dir -= 1

                elif event.key == SDLK_DOWN:
                    y_dir += 1

open_canvas(TUK_WIDTH, TUK_HEIGHT)
tuk_ground = load_image('TUK_GROUND.png')
character = load_image('animation_sheet.png')

running = True
x = TUK_WIDTH // 2
y = TUK_HEIGHT // 2
frame = 0
x_dir = 0
y_dir = 0
sprite_num = 1

while running:
    clear_canvas()
    tuk_ground.draw(TUK_WIDTH // 2, TUK_HEIGHT // 2)
    character.clip_draw(frame * 100, 100 * sprite_num, 100, 100, x, y)
    update_canvas()

    handle_events()
    frame = (frame + 1) % 8
    x += x_dir * 5
    y += y_dir * 5

    if x <= 20:
        x = 20

    elif x >= 1250:
        x = 1250

    elif y <= 20:
        y = 20

    elif y >= 1000:
        y = 1000

    delay(0.01)

close_canvas()


"""
game.py - base file for the tetris game
author : Benjamin Blundell
email : oni@section9.co.uk

"""

import tetris, argparse, time, sys, socket

class Game:

  ''' A game class that controls the timing and viewing of the game state
  This class also communicates with the server side '''

  def __init__(self, game, fps=2, local=True, server_address="192.168.1.1", port=9001, pygame=False):
    self.fps = fps;
    self.interval = 1 / fps;
    self.game = game
    self.pygame = pygame
    self.server_address = server_address
    self.port = port
    self.local = local

    self.buffer_palette = {"I" : 1, "J" : 2, "L" : 3, "O" : 4, "Z" : 5, "S" : 6 , "T" : 7 }

    if self.pygame:
      self.pygame.init()

    if not local:
      self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

  def bufferToServer(self):
    ''' send the game buffer to the server via udp.
    We prepare the buffer by converting down into numnbers 0-8.'''

    send_buffer = []

    for item in self.game.getLinearBufferReversed():
      if item in self.buffer_palette.keys():
        send_buffer.append( int(self.buffer_palette[item]) )
      else:
        send_buffer.append(int(0))

    msg = ''.join(chr(x) for x in send_buffer)

    try:
      self.socket.sendto(msg, (self.server_address, self.port))
      # TODO - dont break on all exceptions! Its a bit naff

    except:
      import traceback
      print("Error connecting to server: " + self.server_address + ":" + str(self.port))
      print(traceback.print_exc())

  def loop(self):
    start_time = time.time()
    self.running = True

    while self.running:

      # Cx pygame - kill it but keep the game running
      if self.pygame:
        if self.pygame.running:
          self.pygame.frame()
        else:
          self.pygame.cleanup()
          self.pygame = False

      now = time.time()
      dt = now - start_time
      if dt >= self.interval:

        self.game.frame(self.fps)
        #print("---")
        #self.game.prettyPrint()
        start_time = now
        if not self.local:
          self.bufferToServer()

  def quit(self):
    print("Quitting...")
    if self.pygame:
      self.pygame.cleanup()

    self.running = False
    sys.exit()

if __name__ == "__main__" :

  import signal

  def signal_handler(sig, frame):
    print("")
    game.quit()
    sys.exit(0)

  signal.signal(signal.SIGINT, signal_handler)
  print ('Launching Tetris...')
  print ('Press Ctrl+C to exit')

  parser = argparse.ArgumentParser(description='Process some integers.')
  parser.add_argument('--fps', metavar='N', type=float, help='overall framerate.')
  parser.add_argument('--pygame', help='launch a pygame window.', action='store_true')
  parser.add_argument('--server', metavar='ip address', help='server string.')
  parser.add_argument('--port', metavar='N', type=int, help='port to connect to.')
  parser.add_argument('--local',  help='run locally with no server.', action='store_true')
  parser.add_argument('--message', metavar='scroll message', help='scroll a message then quit.')
  parser.add_argument('--file', metavar='filename', help='load a file and go on repeat.')
  parser.add_argument('--scrollspeed', metavar='N', type=float, help='How man steps a second for the scolling message.')
  parser.add_argument('--width', metavar='N', type=int, help='buffer width.')
  parser.add_argument('--height', metavar='N', type=int, help='buffer height.')

  argz = vars(parser.parse_args())

  # Basic options - defaults
  fps = 1
  address = "localhost"
  port = 9001
  local = False

  width = 14
  height = 13

  # Parse arguments
  if argz["fps"]:
    fps = argz["fps"]

  if argz["server"]:
    address = argz["server"]

  if argz["port"]:
    port = argz["port"]

  if argz["local"]:
    local = True

  if argz["width"]:
    width = argz["width"]

  if argz["height"]:
    height = argz["height"]

  # game choice options
  if argz["pygame"]:

    tetris = tetris.Tetris(width, height)
    import pygame_wrapper, pygame
    wrapper = pygame_wrapper.Wrapper(tetris.buffer, tetris.boardX, tetris.boardY)
    game = Game(tetris,fps,local,address,port,wrapper)

    # Bind pygame keyboard events to tetris game logic
    wrapper.register_event( pygame.KEYDOWN, pygame.K_LEFT, tetris.goLeft )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_RIGHT, tetris.goRight )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_SPACE, tetris.goRotate )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_DOWN, tetris.goDown )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_SPACE, tetris.goStart )

    # Makey Makey bindings on the mac
    wrapper.register_event( pygame.KEYDOWN, pygame.K_b, tetris.goDown )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_n, tetris.goLeft )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_v, tetris.goRight )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_m, tetris.goStart )
    wrapper.register_event( pygame.KEYDOWN, pygame.K_m, tetris.goRotate )

    # TODO makey makey on the RI machine. Is it the same as above?

    game.loop()

  elif argz["file"]:
    # Display contents from one of our files
    import pygame_wrapper, pygame, screensaver

    crashburn = screensaver.FileToBuffer(width, height, argz["file"])
    wrapper = pygame_wrapper.Wrapper(crashburn.buffer, crashburn.boardX, crashburn.boardY)
    game = Game(crashburn,fps,local,address,port,wrapper)

    game.loop()

  elif argz["message"]:
    # Show messages
    import pygame_wrapper, pygame, message

    scrollspeed = 1
    if argz["scrollspeed"]:
      scrollspeed = argz["scrollspeed"]

    messenger = message.MessageWriter(width, height, "glyphs.txt", argz["message"],scrollspeed)
    wrapper = pygame_wrapper.Wrapper(messenger.buffer, messenger.boardX, messenger.boardY)
    game = Game(messenger,fps,local,address,port,wrapper)

    game.loop()

  else:
    tetris = tetris.Tetris(width, height)
    game = Game(tetris,fps,local,address,port)
    game.loop()


import numpy as np
import pandas as pd

import h5py
import json

from dev_link import *
from util import *

from icecream import ic

class VibExportIms:
    """ Handles reading IMS dataset feature extraction output in CSV (by previous project)
    and exporting to h5py data record,
    with the following properties: RMS_time, Range_time, Kurtosis, Skewness, Range_freq, Peak_freq, Mean_freq, Peak_amp

    .. note:: The 1st test has 2 dimension for each of the 4 bearings
    .. note:: The 4th test is defined test 3

    .. note:: The 1st row in the feature domain intentionally removed was included for export

    Split into 4 partitions with names: [test1/ch1/, test1/ch2/, test2/, test3/]
    """
    FEAT_CSV_NMS = dict(
        rms_time='RMS',
        range_time='p2p',
        kurtosis='kurtosis',
        skewness='skew',
        rms_freq='rmsFeq',
        mean_freq='meanFeq',
        peak_freq='peakFeq',
        rot_amp='peakAmp'
    )

    ENC_FEAT_STOR = dict(  # Dictionary on storage encoding of properties
        rms_time=0,
        range_time=1,
        kurtosis=2,
        skewness=3,
        rms_freq=4,
        mean_freq=5,
        peak_freq=6,
        rot_amp=7
    )

    def get_test_feature_series(self, idx_tst, feat='rms_time'):
        """ Feature across all channels available """
        fl_nm = f'{FEAT_PATH_IMS}test{idx_tst+1}_{self.FEAT_CSV_NMS[feat]}.csv'
        df = pd.read_csv(fl_nm, header=None)
        return df.to_numpy().T

    def get_feature_series(self, idx_tst, idx_brg, feat='rms_time', ch=None):
        """
        :param idx_tst: The test number index in [0, 2] for 3 tests
        :param idx_brg: The bearing index in [0, 3] for 4 bearings
        :param feat: Feature/Property
        :param ch: Which channel of bearing vibration, integer in [0, 1], only an option for test 1
        """
        idx = idx_brg if idx_tst != 0 else (idx_brg * 2 + ch)
        fl_nm = f'{FEAT_PATH_IMS}test{idx_tst+1}_{self.FEAT_CSV_NMS[feat]}.csv'
        df = pd.read_csv(fl_nm, header=None)
        return df[idx].to_numpy()

    def export(self, fl_nm='ims_features'):
        fl_nm = f'data/{fl_nm}.hdf5'
        open(fl_nm, 'a').close()  # Create file in OS
        fl = h5py.File(fl_nm, 'w')
        fl.attrs['feat_stor_idxs'] = json.dumps(self.ENC_FEAT_STOR)
        fl.attrs['nums_msr'] = json.dumps(config('ims.num_measurements'))
        tst_nms = []
        for (idx_tst, tst_nm) in [(0, '/ch1'), (1, '/ch2'), (2, ''), (3, '')]:
            i_tst = max(idx_tst - 1, 0)  # To be compatible with `get_feature_series`
            tst_nm = f'test{i_tst+1}{tst_nm}'
            tst_nms.append(tst_nm)
            group = fl.create_group(tst_nm)
            idxs_brg = list(range(config('ims.num_bearings')))
            # if idx_tst == 0:
            #     idxs_brg = [i * 2 for i in idxs_brg]
            # elif idx_tst == 1:
            #     idxs_brg = [i * 2 + 1 for i in idxs_brg]
            for idx_brg in idxs_brg:
                dset = np.stack([
                    self.get_feature_series(i_tst, idx_brg, feat=f, ch=idx_tst) for f in self.FEAT_CSV_NMS
                ])
                group.create_dataset(f'bearing{idx_brg+1}', data=dset)
        fl.attrs['tst_nms'] = json.dumps(tst_nms)  # 4 tests
        print(f'Metadata attributes created: {list(fl.attrs.keys())}')
        print(f'Features extracted: {[nm for nm in fl]}')


# coding=utf-8
import torch
from torch.nn import functional as F
from torch.nn.modules import Module

class PrototypicalLoss(Module):
    '''
    Loss class deriving from Module for the prototypical loss function defined below
    '''
    def __init__(self, n_support):
        super(PrototypicalLoss, self).__init__()
        self.n_support = n_support

    def forward(self, input, target):
        return prototypical_loss(input, target, self.n_support)

def euclidean_dist(x, y):
    '''
    Compute euclidean distance between two tensors
    '''
    # x: N x D
    # y: M x D
    n = x.size(0)
    m = y.size(0)
    d = x.size(1)
    if d != y.size(1):
        raise Exception

    x = x.unsqueeze(1).expand(n, m, d)
    y = y.unsqueeze(0).expand(n, m, d)

    return torch.pow(x - y, 2).sum(2)

def prototypical_eval(input, target, prototypes):
    target_cpu = target.to('cpu')
    input_cpu = input.to('cpu')
    dists = euclidean_dist(input_cpu, prototypes)
    #print(dists.size(), input_cpu.size(), prototypes.size())
    log_p_y = F.log_softmax(-dists, dim=1)
    #print(log_p_y.size())
    _, y_hat = log_p_y.max(1)
    #print(y_hat.size(), target_cpu.size())
    acc_val = y_hat.eq(target_cpu).float().mean()
    return acc_val, y_hat


from perfis import views
from django.urls import path
from django.contrib.auth import views as v
from usuarios.views import RegistrarUsuarioView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
	path('', views.index, name='index'),
	path('perfil/<int:perfil_id>', views.exibir_perfil, name='exibir'),
	path('perfil/<int:perfil_id>/convidar', views.convidar, name='convidar'),
	path('perfil/<int:perfil_id>/desfazer', views.desfazer, name='desfazer'),
	path('convite/<int:convite_id>/aceitar', views.aceitar, name='aceitar'),
	path('convite/<int:convite_id>/recusar', views.recusar, name='recusar'),
	path('login/', v.LoginView.as_view(template_name='usuarios/login.html'), name='login'),
	path('logout/', v.LogoutView.as_view(template_name='usuarios/login.html'), name="logout"),
	path('registrar/', RegistrarUsuarioView.as_view(), name='registrar'),
	path('password/', views.change_password, name='change_password'),
	path('feed/', views.feed, name='feed'),
	path('promover/<int:perfil_id>', views.promover, name='promover'),
	path('desativar/',views.desativar, name='desativar'),
	path('reativar/',views.reativar, name='reativar'),
	path('bloquear/<int:perfil_id>',views.bloquear,name='bloquear'),
	path('desbloquear/<int:perfil_id>',views.desbloquear, name='desbloquear'),
	path('search', views.search, name='search'),
	path('updatefoto',views.updatefoto, name='updatefoto'),
	path('perfil_list', views.perfil_list, name='perfil_list'),
]
if settings.DEBUG:
	urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


 # -*- coding: utf-8 -*-
"""
Created on Thurs July 02 2020

@author: xcxg109
"""

import pandas as pd

from gamut_ORIGINAL_query import GamutQuery
from queries_PIM import gamut_attr_query, gamut_attr_values
import settings
import time

gamut = GamutQuery()

def data_in(directory_name):
    uom_group = input('Input UOM Group ID or hit ENTER to read from file: ')

    if uom_group != "":
        uom_group = [uom_group]
        return uom_group

    else:
        file_data = settings.get_file_data()

        uom_group = [int(row[0]) for row in file_data[1:]]
        return uom_group

gamut_df = pd.DataFrame()
all_vals = pd.DataFrame()

uom_data = data_in(settings.directory_name)

start_time = time.time()
print('working...')

for k in uom_data:
    print('\nUOM group = ', k)
    gamut_df = gamut.gamut_q(gamut_attr_query, 'tax_att."unitGroupId"', k)

    if gamut_df.empty == False:
        atts = gamut_df['Gamut_Attr_ID'].to_list()

        for attribute in atts:
            temp_df = gamut.gamut_q(gamut_attr_values, 'tax_att.id', attribute)
            temp_df['Count'] = 1

            if temp_df.empty == False:
                vals = pd.DataFrame(temp_df.groupby(['Gamut_Attr_ID', 'Gamut_Attribute_Name', 'Normalized Unit'])['Count'].sum())
                vals = vals.reset_index()
#                vals = vals.sort_values(by=['Count'], ascending=[False])

                temp_df['UOMs Present'] = '; '.join(item for item in vals['Normalized Unit'] if item)

                all_vals = pd.concat([all_vals, temp_df], axis=0)

        if all_vals.empty == False:
            all_vals = all_vals[['Gamut_Attr_ID', 'UOMs Present']]
            all_vals = all_vals.drop_duplicates(subset=['Gamut_Attr_ID'])

            gamut_df = pd.merge(gamut_df, all_vals, on=['Gamut_Attr_ID'])

        columnsTitles = ['Gamut_PIM_Path', 'Gamut_Category_ID', 'Gamut_Category_Name', 'Gamut_Node_ID', \
                         'Gamut_Node_Name', 'Gamut_Attr_ID', 'Gamut_Attribute_Name', 'Gamut_Attribute_Definition', \
                         'Unit_Group_ID', 'UOM_Kind', 'UOMs Present']
        gamut_df = gamut_df.reindex(columns=columnsTitles)

        filename= 'F:\CGabriel\Grainger_Shorties\OUTPUT\gamut_UOM_group_' + str(k) + '.xlsx'

        gamut_df.to_excel(filename)
    else:
        print('\nEMPTY DATAFRAME\n')

    print("--- {} seconds ---".format(round(time.time() - start_time, 2)))


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ['CUDA_VISIBLE_DEVICES'] = ''

import numpy as np

import warnings
warnings.filterwarnings("ignore")

import config as cfg

# Import TFLite from runtrime or Tensorflow;
# import Keras if protobuf model;
# NOTE: we have to use TFLite if we want to use
# the metadata model or want to extract embeddings
try:
    import tflite_runtime.interpreter as tflite
except ModuleNotFoundError:
    from tensorflow import lite as tflite
if not cfg.MODEL_PATH.endswith('.tflite'):
   from tensorflow import keras

INTERPRETER = None
M_INTERPRETER = None
PBMODEL = None

def loadModel(class_output=True):

    global PBMODEL
    global INTERPRETER
    global INPUT_LAYER_INDEX
    global OUTPUT_LAYER_INDEX

    # Do we have to load the tflite or protobuf model?
    if cfg.MODEL_PATH.endswith('.tflite'):

        # Load TFLite model and allocate tensors.
        INTERPRETER = tflite.Interpreter(model_path=cfg.MODEL_PATH, num_threads=cfg.TFLITE_THREADS)
        INTERPRETER.allocate_tensors()

        # Get input and output tensors.
        input_details = INTERPRETER.get_input_details()
        output_details = INTERPRETER.get_output_details()

        # Get input tensor index
        INPUT_LAYER_INDEX = input_details[0]['index']

        # Get classification output or feature embeddings
        if class_output:
            OUTPUT_LAYER_INDEX = output_details[0]['index']
        else:
            OUTPUT_LAYER_INDEX = output_details[0]['index'] - 1

    else:

        # Load protobuf model
        # Note: This will throw a bunch of warnings about custom gradients
        # which we will ignore until TF lets us block them
        PBMODEL = keras.models.load_model(cfg.MODEL_PATH, compile=False)

def loadMetaModel():

    global M_INTERPRETER
    global M_INPUT_LAYER_INDEX
    global M_OUTPUT_LAYER_INDEX

    # Load TFLite model and allocate tensors.
    M_INTERPRETER = tflite.Interpreter(model_path=cfg.MDATA_MODEL_PATH, num_threads=cfg.TFLITE_THREADS)
    M_INTERPRETER.allocate_tensors()

    # Get input and output tensors.
    input_details = M_INTERPRETER.get_input_details()
    output_details = M_INTERPRETER.get_output_details()

    # Get input tensor index
    M_INPUT_LAYER_INDEX = input_details[0]['index']
    M_OUTPUT_LAYER_INDEX = output_details[0]['index']

def predictFilter(lat, lon, week):

    global M_INTERPRETER

    # Does interpreter exist?
    if M_INTERPRETER == None:
        loadMetaModel()

    # Prepare mdata as sample
    sample = np.expand_dims(np.array([lat, lon, week], dtype='float32'), 0)

    # Run inference
    M_INTERPRETER.set_tensor(M_INPUT_LAYER_INDEX, sample)
    M_INTERPRETER.invoke()

    return M_INTERPRETER.get_tensor(M_OUTPUT_LAYER_INDEX)[0]

def explore(lat, lon, week):

    # Make filter prediction
    l_filter = predictFilter(lat, lon, week)

    # Apply threshold
    l_filter = np.where(l_filter >= cfg.LOCATION_FILTER_THRESHOLD, l_filter, 0)

    # Zip with labels
    l_filter = list(zip(l_filter, cfg.LABELS))

    # Sort by filter value
    l_filter = sorted(l_filter, key=lambda x: x[0], reverse=True)

    return l_filter

def flat_sigmoid(x, sensitivity=-1):
    return 1 / (1.0 + np.exp(sensitivity * np.clip(x, -15, 15)))

def predict(sample):

    global INTERPRETER

    # Does interpreter or keras model exist?
    if INTERPRETER == None and PBMODEL == None:
        loadModel()

    if PBMODEL == None:

        # Reshape input tensor
        INTERPRETER.resize_tensor_input(INPUT_LAYER_INDEX, [len(sample), *sample[0].shape])
        INTERPRETER.allocate_tensors()

        # Make a prediction (Audio only for now)
        INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample, dtype='float32'))
        INTERPRETER.invoke()
        prediction = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)

        return prediction

    else:

        # Make a prediction (Audio only for now)
        prediction = PBMODEL.predict(sample)

        return prediction

def embeddings(sample):

    global INTERPRETER

    # Does interpreter exist?
    if INTERPRETER == None:
        loadModel(False)

    # Reshape input tensor
    INTERPRETER.resize_tensor_input(INPUT_LAYER_INDEX, [len(sample), *sample[0].shape])
    INTERPRETER.allocate_tensors()

    # Extract feature embeddings
    INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample, dtype='float32'))
    INTERPRETER.invoke()
    features = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)

    return features