import torch
import torch.nn as nn
import torch.nn.functional as F

class StochasticBinaryLinear(nn.Linear):
    def __init__(self, input_size, output_size):
        super().__init__()
        self.lin = nn.Linear(input_size, output_size)

    def forward(self, x, q):
        a_0 = self.lin(x)
        a = a_0[:, :, None] - 2 * self.lin.weight[None] * x[:, None]

        probs = torch.sigmoid(a_0)
        with torch.no_grad():
            b = torch.bernoulli(probs)
            new_x = 2 * b - 1

        delta_0 = -new_x * probs
        delta = -new_x[:, :, None] * torch.sigmoid(a)

        new_q = delta_0 + q[:, None].mul(delta - delta_0[:, :, None]).sum(dim=-1)
        return new_x, new_q

class StochasticBinaryLinear_2(nn.Module):
    def __init__(self, input_size, output_size, fast=False, t=0.):
        super().__init__()
        self.lin = nn.Linear(input_size, output_size)
        self.fast = fast
        self.t = t
        self._t = torch.tensor([t])
        self._reset_parameters()

    def _reset_parameters(self):
        gain = torch.nn.init.calculate_gain('sigmoid')
        torch.nn.init.xavier_uniform_(self.lin.weight, gain=gain)

    def forward(self, x, q):
        if self.fast:
            return self._fast_forward(x, q)
        else:
            return self._norm_forward(x, q)

    def _fast_forward(self, x, q):
        a_0 = self.lin(x)
        a = a_0.unsqueeze(-1) - 2 * torch.einsum('ji,bi->bji', (self.lin.weight, x))
        #probs = torch.sigmoid(a_0)

        if self.t == 0.:
            probs = torch.sigmoid(a_0)
        else:
            probs = (F.softplus(a_0 + self.t) - F.softplus(a_0 - self.t)) / (2 * self.t)
            probs = probs.clamp_(0., 1.)
        with torch.no_grad():
            b = torch.bernoulli(probs)
            new_x = 2 * b - 1

        probs_ = probs.detach()

        ###########################################################################################
        #delta_0 = -new_x * probs # delta_0.shape = B x O
        #delta = torch.einsum('bj,bji->bji', (-new_x, torch.sigmoid(a)))

        p0 = torch.sigmoid(a_0)
        p = torch.sigmoid(a)
        if self._t.device != a.device:
            self._t = self._t.to(a.device)

        if self.t == 0.:
            delta_0 = -new_x * p0
            delta = torch.einsum('bj,bji->bji', (-new_x, p))
        else:
            delta_0 = -0.5 * new_x * p0 + F.softplus(a_0 + self.t * new_x) / (2 * self.t)
            b = torch.min(torch.max(a - a_0.unsqueeze(-1), -self._t), self._t)
            pi = b / (2 * self.t) - new_x.unsqueeze(-1) / 2
            delta = pi * p + (F.softplus(a_0 + self.t * new_x).unsqueeze(-1) - F.softplus(a_0.unsqueeze(-1) + b)) / (2 * self.t)

        ###########################################################################################
        #new_q = delta_0.mul(1 - q.sum(dim=1, keepdim=True)) + torch.einsum('bi,bji->bj', (q, delta))
        new_q = b + delta_0.mul(1 - q.sum(dim=1, keepdim=True)) + torch.einsum('bi,bji->bj', (q, delta))
        return new_x, new_q

    def _norm_forward(self, x, q):
        a_0 = self.lin(x)
        a_0_ = a_0.detach()
        a = a_0.unsqueeze(-1) - 2 * torch.einsum('ji,bi->bji', (self.lin.weight, x))

        if self.t == 0.:
            probs = torch.sigmoid(a_0)
        else:
            probs = (F.softplus(a_0 + self.t) - F.softplus(a_0 - self.t)) / (2 * self.t)
            probs = probs.clamp_(0., 1.)
        probs_ = probs.detach()

        with torch.no_grad():
            b = torch.bernoulli(probs)
            new_x = 2 * b - 1

        pi = probs_ * b + (1 - probs_) * (1 - b)

        #delta_0 = -new_x * (probs - probs_) # delta_0.shape = B x O
        #delta = torch.einsum('bj,bji->bji', (-new_x, (torch.sigmoid(a) - probs_.unsqueeze(2))))
        delta_0, delta = self._compute_delta(new_x, a_0, a, t=self.t)
        new_q = delta_0.mul(1 - q.sum(dim=1, keepdim=True)) + torch.einsum('bi,bji->bj', (q, delta))
        new_q = new_q / pi
        return new_x, new_q

    def _compute_delta(self, new_x, a0, a, t=0.):
        p0 = torch.sigmoid(a0)
        p = torch.sigmoid(a)
        if self._t.device != a.device:
            self._t = self._t.to(a.device)

        _t = self._t
        a0_, p0_ = a0.detach(), p0.detach()

        if t == 0.:
            delta_0 = -new_x * (p0 - p0_)
            delta = torch.einsum('bj,bji->bji', (-new_x, (p - p0_.unsqueeze(2))))
        else:
            delta_0 = -0.5 * new_x * p0 + (F.softplus(a0_ + t * new_x) - F.softplus(a0_)) / (2 * t)
            b = torch.min(torch.max(a - a0_.unsqueeze(-1), -_t), _t)
            pi = b / (2 * t) - new_x.unsqueeze(-1) / 2
            delta = pi * p + (F.softplus(a0_ + t * new_x).unsqueeze(-1) - F.softplus(a0_.unsqueeze(-1) + b)) / (2 * t)

        return delta_0, delta

#class StochasticBinaryFullyConnected(nn.Module):
#    def __init__(self, args):
#        super().__init__()
#        self.fc_layers, self.output_layer = self._make_layers(args)
#        self.input_size = args.input_size
#
#
#    def _make_layers(self, args):
#        layers = []
#        input_size = args.input_size
#
#        for _ in range(args.n_layers):
#            layers.append(StochasticBinaryLinear(input_size, args.hidden_size))
#            input_size = args.hidden_size
#
#        mask = [torch.ones(input_size)]
#        for i in range(input_size):
#            m = torch.ones(input_size)
#            m[i] = -1
#            mask.append(m)
#        self.mask = torch.stack(mask, dim=0)
#
#        output_layer = nn.Linear(input_size, args.n_classes)
#        return nn.ModuleList(layers), output_layer
#
#
#    def forward(self, x):
#        if x.device != self.mask.device:
#            self.mask = self.mask.to(x.device)
#
#        z = x.view(-1, self.input_size)
#        q = torch.zeros([x.shape[0], self.input_size], device=z.device)
#        for layer in self.fc_layers:
#            z, q = layer(z, q)
#
#        batch_size, size = z.shape
#        inps = torch.stack([z for _ in range(size + 1)], dim=0) # inps.shape = O + 1 x B x O
#        inps = inps.mul(self.mask[:, None, :]).view(-1, size)
#        f = self.output_layer(inps).view(size + 1, batch_size, -1) # O x B x D
#        out = f[0] + (f[1:] - f[:1]).mul(q.t()[:, :, None]).sum(dim=0)
#        return out
#
#class StochasticBinaryFullyConnected_2(nn.Module):
#    def __init__(self, args):
#        super().__init__()
#        self.fc_layers, self.output_layer = self._make_layers(args)
#        self.input_size = args.input_size
#        self.n_classes = args.n_classes
#        self.expect_pred = args.expect_pred
#        self.expect_probs = args.expect_probs
#
#
#    def _make_layers(self, args):
#        layers = []
#        input_size = args.input_size
#
#        for _ in range(args.n_layers):
#            layers.append(StochasticBinaryLinear_2(input_size, args.hidden_size, fast=args.fast, t=args.t))
#            input_size = args.hidden_size
#
#        mask = [torch.ones(input_size)]
#        for i in range(input_size):
#            m = torch.ones(input_size)
#            m[i] = -1
#            mask.append(m)
#        self.mask = torch.stack(mask, dim=0)
#
#        output_layer = nn.Linear(input_size, args.n_classes)
#        return nn.ModuleList(layers), output_layer
#
#
#    def forward(self, x):
#        if x.device != self.mask.device:
#            self.mask = self.mask.to(x.device)
#
#        z = x.view(-1, self.input_size)
#        q = torch.zeros_like(z).to(z)
#
#        for i, layer in enumerate(self.fc_layers):
#            z, q = layer(z, q)
#
#        out = z, q
#        return out
#
#
#    def expectation(self, z, q, y):
#        batch_size, size = z.shape
#        inps = torch.stack([z for _ in range(size + 1)], dim=0) # inps.shape = O + 1 x B x O
#        inps = torch.einsum('abo,ao->abo', (inps, self.mask)).view(-1, size)
#        pred = self.output_layer(inps)
#
#        if self.expect_pred:
#            pred_ = pred.view(size + 1, batch_size, -1) # O x B x D
#            pred_ = pred_[0] + (pred_[1:] - pred_[:1]).mul(q.t()[:, :, None]).sum(dim=0)
#            y = y.view(size + 1, -1)[0]
#            return F.cross_entropy(pred_, y), pred_
#        elif self.expect_probs:
#            pred_ = pred.view(size + 1, batch_size, -1) # O x B x D
#            probs = F.softmax(pred_, dim=2)
#            probs = probs[0] + (probs[1:] - probs[:1]).mul(q.t()[:, :, None]).sum(dim=0)
#            y = y.view(size + 1, -1)[0]
#            return F.nll_loss(probs.add(1e-6).log(), y), probs
#        else:
#            pred_ = pred.view(size + 1, batch_size, -1)[0]
#            f = F.cross_entropy(pred, y, reduction='none').view(size + 1, batch_size)
#            out = f[0].mul(1 - q.sum(dim=1, keepdim=True)) + torch.einsum('ob,bo->b', (f[1:], q))
#            #print(F.cross_entropy(pred_, y.view(size + 1, -1)[0]).item(), f[0].mean().item(), out.mean().item())
#            return out.mean(), pred_

class StochasticBinaryConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, padding=1, stride=1, t=0.):
        super().__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, padding=padding, stride=1)
        self.t = t
        self._t = torch.tensor([t])
        self._reset_parameters()

        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.in_channels = in_channels
        self.out_channels = out_channels
        self._init = False

    def _reset_parameters(self):
        gain = torch.nn.init.calculate_gain('sigmoid')
        torch.nn.init.xavier_uniform_(self.conv.weight, gain=gain)

    def _compute_conv_diffs(self, x, a0):
        k = self.kernel_size
        pad = 2 * (k // 2) - self.padding

        batch_size, out_channels, out_h, out_w = a0.shape
        _, in_channels, in_h, in_w = x.shape

        K_flip = torch.flip(self.conv.weight, [2, 3])

        a = torch.zeros([k, k, batch_size, out_channels, in_channels, in_h, in_w]).to(a0)
        a0_ = torch.zeros([batch_size, out_channels, in_h + k - 1, in_w + k - 1]).to(a0)
        a0_[:, :, pad:-pad, pad:-pad] = a0

        for l1 in range(k):
            for l2 in range(k):
                val = a0_[:, :, None, l1:l1 + in_h, l2:l2 + in_w] - 2 * x[:, None] * K_flip[None, :, :, l1, l2, None, None]
                a[l1, l2] = val

        return a

    def _compute_delta_sum(self, new_x, p, p0, q):
        k = self.kernel_size
        pad = 2 * (k // 2) - self.padding

        batch_size, out_channels, out_h, out_w = p0.shape
        _, in_channels, in_h, in_w = q.shape

        delta_q = torch.zeros([batch_size, out_channels, in_h + k - 1, in_w + k - 1]).to(p0)

        p0_ = torch.zeros([batch_size, out_channels, in_h + k - 1, in_w + k - 1]).to(p0)
        p0_[:, :, pad:-pad, pad:-pad] = p0
        #self.p0_[:, :, pad:-pad, pad:-pad] = p0

        y_ = torch.zeros([batch_size, out_channels, in_h + k - 1, in_w + k - 1]).to(p0)
        y_[:, :, pad:-pad, pad:-pad] = new_x
        #self.y_[:, :, pad:-pad, pad:-pad] = new_x

        for l1 in range(k):
            for l2 in range(k):
                add = p[l1, l2].sub(p0_[:, :, None, l1:l1 + in_h, l2:l2 + in_w]).mul(q[:, None]).sum(dim=2).mul(-y_[:, :, l1:l1 + in_h, l2:l2 + in_w])
                delta_q[:, :, l1:l1 + in_h, l2:l2 + in_w] += add

        return delta_q[:, :, pad:-pad, pad:-pad]

    def _norm_forward(self, x, q):
        a0 = self.conv(x)
        p0 = torch.sigmoid(a0)
        a = self._compute_conv_diffs(x, a0)
        p = torch.sigmoid(a)

        new_x = 2 * p0.bernoulli() - 1

        delta_0 = -new_x * (p0 - p0.detach())
        delta_q = self._compute_delta_sum(new_x, p, p0, q)

        qs = q.sum(dim=3, keepdim=True)
        qs = qs.sum(dim=2, keepdim=True)
        qs = qs.sum(dim=1, keepdim=True)

        new_q = delta_0.mul(1 - qs) + delta_q
        return new_x, new_q

    def forward(self, x, q):
        new_x, new_q = self._norm_forward(x, q)
        new_x = new_x[:, :, ::self.stride, ::self.stride].contiguous()
        new_q = new_q[:, :, ::self.stride, ::self.stride].contiguous()
        return new_x, new_q

class StochasticBinaryLinearSoftmax(nn.Linear):
    def __init__(self, in_features, out_features):
        super().__init__(in_features, out_features)
        mask_size = in_features
        mask = [torch.ones(mask_size)]
        for i in range(mask_size):
            m = torch.ones(mask_size)
            m[i] = -1
            mask.append(m)
        self.mask = torch.stack(mask, dim=0)

    def forward(self, x, q):
        if x.device != self.mask.device:
            self.mask = self.mask.to(x.device)

        batch_size, size = x.shape
        inps = torch.stack([x for _ in range(size + 1)], dim=0) # inps.shape = O + 1 x B x O
        inps = torch.einsum('abo,ao->abo', (inps, self.mask)).view(-1, size)
        pred = super().forward(inps)

        pred_ = pred.view(size + 1, batch_size, -1) # O x B x D
        probs = F.softmax(pred_, dim=2)
        probs = probs[0] + (probs[1:] - probs[:1]).mul(q.t()[:, :, None]).sum(dim=0)
        return probs.add(1e-6).log()

class StochasticBinaryArchMixin:
    def _get_linear(self, *args):
        return StochasticBinaryLinear_2(*args)

    def _get_conv(self, *args, **kwargs):
        return StochasticBinaryConv2d(*args, **kwargs)

    def _get_first_conv(self, *args, **kwargs):
        return StochasticBinaryConv2d(*args, **kwargs)

    def _get_output_layer(self, *args, **kwargs):
        return StochasticBinaryLinearSoftmax(*args, **kwargs)

    def _get_input(self, x):
        q = torch.zeros_like(x).to(x)
        return x, q

    def _apply_layer(self, layer, *args):
        z, q = args[:2]
        return layer(z, q)

#class StochasticBinaryLeNet5(nn.Module):
#    def __init__(self, args):
#        super().__init__()
#        self.conv_layers = nn.ModuleList([
#            StochasticBinaryConv2d(1, 6, kernel_size=5, padding=2, stride=2),
#            StochasticBinaryConv2d(6, 16, kernel_size=5, padding=0, stride=2)
#        ])
#
#        self.fc_layers = nn.ModuleList([
#            StochasticBinaryLinear_2(400, 120),
#            StochasticBinaryLinear_2(120, 84),
#        ])
#
#        self.output_layer = nn.Linear(84, 10)
#
#
#    def forward(self, x):
#        z = x
#        q = torch.zeros_like(z).to(z)
#
#        for layer in self.conv_layers:
#            z, q = layer(z, q)
#
#        z = z.view(z.shape[0], -1)
#        q = q.view(q.shape[0], -1)
#
#        for layer in self.fc_layers:
#            z, q = layer(z, q)
#
#        out = z, q
#        return out


import numpy as np
from numba import njit,float64
from numba.pycc import CC

cc = CC('model_precompiled_functions')
cc.verbose = True

## Inner product function
@njit(float64(float64[:],float64[:]))
def innerproduct(v1,v2):
    x=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]
    return x
## Inner matrix product function
@njit(float64(float64[:,:],float64[:,:]))
def inner_matrix_product(A1,A2):
    x=0.0
    for i in range(3):
        for j in range(3):
            x+=A1[i,j]*A2[i,j]
    return x
## Centrifugal forces and stiffness matrix
#
# Inputs:
#  ndofs             int32
#  jcol_nonzero_irow int32[:,:]
#  ijsym             int32[:,:]
#  m_drcg_dqi        float64[:,:]
#  m_ddrcg_dqidqj    float64[:,:]
#  Abase_i           float64[:,:,:]
#  Abase1_ij         float64[:,:,:]
#  Abase2_ij         float64[:,:,:]
#  R0Tddr0           float64[:]
#  R0TddR0           float64[:,:]
#  R0TdR0            float64[:,:]
#
# Outputs
#  Fc          float64[:]
#  Gc          float64[:,:]
#  Kc          float64[:,:]
#
#
@cc.export('compute_local_centrifugal_forces_and_matrix','(i4,i4[:,:],i4[:,:],f8[:,:],f8[:,:],f8[:,:,:],f8[:,:,:],f8[:,:,:],f8[:],f8[:,:],f8[:,:])')
def compute_local_centrifugal_forces_and_matrix(ndofs,jcol_nonzero_irow,ijsym,m_drcg_dqi,m_ddrcg_dqidqj,Abase_i,Abase1_ij,Abase2_ij,R0Tddr0,R0TddR0,R0TdR0):
    ddR0TR0=R0TddR0.T
    Fc=np.zeros(ndofs)
    Gc=np.zeros((ndofs,ndofs))
    Kc=np.zeros((ndofs,ndofs))
    for i in range(ndofs):
        Fc[i]= innerproduct(R0Tddr0,m_drcg_dqi[:,i]) \
              +inner_matrix_product(ddR0TR0,Abase_i[:,:,i])
        for j in range(jcol_nonzero_irow[0,i],jcol_nonzero_irow[1,i]):
            # Upper triangle
            Gc[i,j]= inner_matrix_product(R0TdR0,Abase1_ij[:,:,ijsym[i,j]])
            Kc[i,j]= innerproduct(R0Tddr0,m_ddrcg_dqidqj[:,ijsym[i,j]]) \
                    +inner_matrix_product(R0TddR0,Abase1_ij[:,:,ijsym[i,j]]) \
                    +inner_matrix_product(ddR0TR0,Abase2_ij[:,:,ijsym[i,j]])
            # Lower triangle
            if j!=i:
                Gc[i,j]= inner_matrix_product(R0TdR0,Abase1_ij[:,:,ijsym[i,j]].T)
                Kc[j,i]= innerproduct(R0Tddr0,m_ddrcg_dqidqj[:,ijsym[i,j]]) \
                        +inner_matrix_product(R0TddR0,Abase1_ij[:,:,ijsym[i,j]].T) \
                        +inner_matrix_product(ddR0TR0,Abase2_ij[:,:,ijsym[i,j]])

    return Fc,Gc,Kc

#===============================================================================================
# Compilation
#===============================================================================================
if __name__ == "__main__":
    cc.compile()


import random

import pygame

pygame.init()
vec = pygame.math.Vector2

class Item(pygame.sprite.Sprite):
    def __init__(self, attributes, inventory):
        super().__init__()
        self.attributes = attributes
        self.inventory = inventory

        self.is_item = True

        self.surf = pygame.Surface((20, 20))
        self.surf.fill((20, 120, 30))
        self.rect = self.surf.get_rect(topleft=(random.randint(100, 500), random.randint(100, 500)))

        self.overworld_pos = self.rect.topleft

    def picked_up(self):
        if not self.inventory.inventory[len(self.inventory.inventory) - 1]:
            self.inventory.pick_up(self)
            self.kill()

    def update(self):
        pass

class Weapon(Item):
    def __init__(self, attributes, inventory):
        super().__init__(attributes, inventory)


from diffusers import StableDiffusionPipeline
import torch

# model_path = "path_to_saved_model"
model_path="./sd-pokemon-model/"
pipe = StableDiffusionPipeline.from_pretrained(model_path, torch_dtype=torch.float16)
pipe.to("cuda")

image = pipe(prompt="yoda").images[0]
image.save("generation/yoda-pokemon.png")


# Initialize models
vectorizer = CountVectorizer(min_df=1)
pca = RandomizedPCA(n_components=50, whiten=True)
km = KMeans(n_clusters=2, init='random', n_init=1, verbose=1)

# Fit models
X = vectorizer.fit_transform(sentences)
X2 = pca.fit_transform(X)
km.fit(X2)

# Predict with models
X_new = vectorizer.transform(["hello world"])
X2_new = pca.transform(X_new)
km.predict(X2_new)


import os, sys, datetime, random
from timeit import default_timer as timer
import pandas as pd
import numpy as np

from openalea.vmango.simulation.fruitmodel.fruit_model_main import growth_main
from openalea.vmango.simulation.fruitmodel.fruitmodel import initialize_input
from openalea.vmango.simulation.fruitmodel.fruitmodel_error import FruitModelValueError

verbose = False
result = pd.DataFrame({
    'run': [],
    'bloom_date': [],
    'nb_fruits': [],
    'nb_leaves': [],
    'DM_fruit_0': [],
    'sunlit_bs_sample': [],
    'time_r': [],
    'time_py': [],
    'ripe': [],
    'model_error': [],
    'result': []
})

absdir = os.path.dirname(os.path.abspath(__file__))
os.chdir(os.path.join(absdir, '..'))

weather_hourly_file_path = os.path.join(absdir, '../../../../../../../share/environment/weather_hourly_stpierre_2002.csv')
weather_daily_file_path = os.path.join(absdir, '../../../../../../../share/environment/weather_daily_stpierre_2002.csv')
sunlit_fractions_file_path = os.path.join(absdir, '../../../../../../../share/environment/sunlit_fractions.csv')
params_file_path = os.path.join(absdir, '../../../../../../../share/parameters/fruitmodel/cogshall.toml')

input_hourly, input_daily, sunlit_fractions, params = initialize_input(
            weather_hourly_file_path, weather_daily_file_path, sunlit_fractions_file_path, params_file_path)

if sys.platform == 'win32':
    R_HOME = os.environ['R_HOME']
    exe = os.path.join(R_HOME, 'bin', 'Rscript.exe')
    assert os.path.exists(exe)
else:
    exe = 'Rscript'

def run_r(bloom_date, nb_fruits, nb_leaves, verbose, DM_fruit_0, light_envir_sample, weather_fname="stpierre_2002"):
    os.system(f'"{exe}" r_vs_py/run.r {os.getcwd()} {bloom_date} {nb_fruits} {nb_leaves} {verbose} {DM_fruit_0} {light_envir_sample} {weather_fname}')

times = []

for i in range(100):

    time_r = 0
    time_py = 0

    if os.path.exists('tmp/r.csv'):
        os.remove('tmp/r.csv')
    if os.path.exists ('tmp/py.csv'):
        os.remove('tmp/py.csv')

    bloom_date = '01/11/2002'
    nb_fruits = random.randrange(1, 4)
    nb_leaves = random.randrange(10, 20)
    weight_1 = params.main.fruitDM0_weight_1
    mu_1 = params.main.fruitDM0_mu_1
    sigma_1 = params.main.fruitDM0_sigma_1
    weight_2 = params.main.fruitDM0_weight_2
    mu_2 = params.main.fruitDM0_mu_2
    sigma_2 = params.main.fruitDM0_sigma_2

    DM_fruit_0 = weight_1 * np.random.normal(mu_1, sigma_1) + weight_2 * np.random.normal(mu_2, sigma_2)
    sunlit_bs_sample = random.randrange(0, 5)
    sunlit_bs = sunlit_fractions.iloc[:,sunlit_bs_sample].to_numpy()
    model_error = ''
    ripe = False

    try:
        start = timer()
        run_r(bloom_date, nb_fruits, nb_leaves, verbose, DM_fruit_0, sunlit_bs_sample + 1)
        end = timer()
        time_r = end - start

        start = timer()
        bloom_date_ = np.datetime64(datetime.datetime.strptime(bloom_date, '%d/%m/%Y'), 'D')
        res = growth_main(
            bloom_date_,
            nb_fruits,
            nb_leaves,
            sunlit_bs,
            input_daily,
            input_hourly,
            params,
            DM_fruit_0,
            DM_fruit_ini=np.nan,
            sim_date_ini=None,
            dd_thresh=np.nan,
            stop_sim_ddcum=np.nan,
            verbose=verbose
        )
        res.to_csv('tmp/py.csv', na_rep='nan', index=False)

        end = timer()
        time_py = end - start

        times.append([time_r, time_py])

    except FruitModelValueError as e:
        end = timer()
        time_py = end - start
        print(e)
        model_error = str(e)
        pass
    finally:
        if os.path.exists('tmp/r.csv') and os.path.exists('tmp/py.csv'):
            df_r = pd.read_csv('tmp/r.csv', sep=',').fillna(-99999).round(4)
            ripe = df_r.loc[df_r.shape[0] - 2, 'sucrose'] >= 0.04 if not model_error else False
            df_py = pd.read_csv('tmp/py.csv', sep=',').fillna(-99999).round(4)
            eq = df_r.eq(df_py)
            is_eq = eq[eq == False].count().sum() == 0
            if is_eq:
                print(i, bloom_date, nb_fruits, nb_leaves, DM_fruit_0, sunlit_bs_sample, time_r, time_py, ripe, model_error, is_eq)
            else:
                print(i, bloom_date, nb_fruits, nb_leaves, DM_fruit_0, sunlit_bs_sample, time_r, time_py, ripe, model_error, is_eq)
                df_r.to_csv('r_vs_py/df_r.csv', index=False)
                df_py.to_csv('r_vs_py/df_py.csv', index=False)
                df_diff = df_r.loc[:, 'FM_fruit':] - df_py.loc[:, 'FM_fruit':]
                flat_diff = df_diff[abs(df_diff) > 0.001].values.flatten()
                if len(flat_diff[~np.isnan(flat_diff)]) > 0:
                    df_diff.to_csv('r_vs_py/df_py_diff.csv', index=False)
                    pd.options.display.max_rows = None
                    pd.options.display.max_columns = None
                    print(df_diff)
                    pd.options.display.max_rows = 10
                    pd.options.display.max_columns = 10
                    break
        else:
            is_eq = False

        result.loc[len(result)] = [i, bloom_date, nb_fruits, nb_leaves, DM_fruit_0, sunlit_bs_sample, time_r, time_py, ripe, model_error, is_eq]

result.to_csv('r_vs_py/r_vs_py.csv', na_rep='nan', index=False)

print('py/r', np.mean([t[1]/t[0] for t in times]))


import sys
import cv2
import os

# encoder (for mp4)
fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
# output file name, encoder , fps, size (fit to image size)
num = 0
while True:
    filename = f'minmax_vel{num}.mp4'
    if os.path.exists(os.path.join(os.getcwd(),filename)):
        num += 1
    else:
        break
video = cv2.VideoWriter(os.path.join(os.getcwd(),filename), fourcc, 50, (1920,1080))
print('video path -->', os.path.join(os.getcwd(),filename))

if not video.isOpened():
    print('cannot open')
    sys.exit()

pic_num = 3000
pic_file = '0'
pic_path = os.path.join(os.getcwd(),pic_file)
for i in range(0, pic_num):
    img = cv2.imread(os.path.join(pic_path,f'{i}.png'))
    if img is None:
        print('cannot read')
        break

    # add
    video.write(img)
print('generating videos....')
video.release()


import math

def rank(arr):
    lastIndex = len(arr) - 1
    while lastIndex > 0:

        for i in range(lastIndex):
            if arr[i + 1] < arr[i]:
                tmp = arr[i + 1]
                arr[i + 1] = arr[i]
                arr[i] = tmp

        lastIndex = lastIndex - 1

    return arr

def half_search(arr, N, startIndex, endIndex):
    if startIndex == endIndex:
        if arr[startIndex] > N:
            return startIndex
        else:
            return -1

    if endIndex - startIndex == 1:

        if arr[startIndex] > N:
            return startIndex
        else:

            if arr[endIndex] <= N:
                return -1

            return endIndex

    m = (startIndex + endIndex) % 2

    if m == 1:
        # 偶数 2,5 => 3,4
        s1 = int((startIndex + endIndex - 1) / 2)
        s2 = s1 + 1
        value1 = arr[s1]

        if N < value1:
            return half_search(arr, N, startIndex, s2)
        else:
            return half_search(arr, N, s1, endIndex)
    else:
        # 奇数 3,6 => 5
        #
        midIndex = int((startIndex + endIndex + 1) / 2)
        midValue = arr[midIndex]

        if midValue > N:
            return half_search(arr, N, startIndex, midIndex)
        else:
            return half_search(arr, N, midIndex, endIndex)

def calculate(arr):
    if len(arr) < 3:
        return 0

    index = len(arr) - 1
    result = 0
    while index - 2 >= 0:

        s1 = arr[index] # 最大的值

        secondIndex = index - 1

        while secondIndex - 1 >= 0:

            s2 = arr[secondIndex]

            left = arr[:secondIndex]

            dirrerence = math.fabs(s2 - s1)
            t = half_search(left, dirrerence, 0, len(left) - 1)
            res = 0
            if t >= 0:
                res = len(left) - t
            result = result + res

            secondIndex = secondIndex - 1
        index = index - 1

    return result

N = input()
S = list(input().split(' '))
S = list(map(int, S))

arr = rank(S)
result = calculate(arr)
print(result)


from collections import OrderedDict

import torch
import torch.nn as nn
from torchvision import models
import torch.nn.functional as F

class UpSample(nn.Sequential):
    def __init__(self, skip_input, output_features):
        super(UpSample, self).__init__()
        self.convA = nn.Conv2d(skip_input, output_features, kernel_size=3, stride=1, padding=1)
        self.leakyreluA = nn.LeakyReLU(0.2)
        self.convB = nn.Conv2d(output_features, output_features, kernel_size=3, stride=1, padding=1)
        self.leakyreluB = nn.LeakyReLU(0.2)

    def forward(self, x, concat_with):
        up_x = F.interpolate(x, size=[concat_with.size(2), concat_with.size(3)], mode='bilinear', align_corners=True)
        up_x = self.convA(torch.cat([up_x, concat_with], dim=1))
        up_x = self.leakyreluA(up_x)
        up_x = self.convB(up_x)
        up_x = self.leakyreluB(up_x)
        return up_x

class Decoder(nn.Module):
    def __init__(self, num_features=1664, decoder_width=1.0):
        super(Decoder, self).__init__()
        features = int(num_features * decoder_width)

        self.conv2 = nn.Conv2d(num_features, features, kernel_size=1, stride=1, padding=0)

        self.up1 = UpSample(skip_input=features // 1 + 256, output_features=features // 2)
        self.up2 = UpSample(skip_input=features // 2 + 128, output_features=features // 4)
        self.up3 = UpSample(skip_input=features // 4 + 64, output_features=features // 8)
        self.up4 = UpSample(skip_input=features // 8 + 64, output_features=features // 16)

        self.conv3 = nn.Conv2d(features // 16, 1, kernel_size=3, stride=1, padding=1)

    def forward(self, input, skip_features):
        x_d0 = self.conv2(F.relu(skip_features['norm5']))
        x_d1 = self.up1(x_d0, skip_features['transition2'])
        x_d2 = self.up2(x_d1, skip_features['transition1'])
        x_d3 = self.up3(x_d2, skip_features['pool0'])
        x_d4 = self.up4(x_d3, skip_features['relu0'])
        return self.conv3(x_d4)

class Encoder(nn.Module):
    def __init__(self, pretrained=True):
        super(Encoder, self).__init__()
        print(f"Loading densenet pretrained={pretrained}")
        self.densenet = models.densenet169(pretrained=pretrained).features
        self.densenet_features = OrderedDict()
        self.fhooks = []
        self.output_layers = ['norm5', 'transition2', 'transition1', 'pool0', 'relu0']

        for i, l in enumerate(list(self.densenet._modules.keys())):
            if l in self.output_layers:
                self.fhooks.append(getattr(self.densenet, l).register_forward_hook(self.forward_hook(l)))

    def to(self, *args, **kwargs):
        self = super().to(*args, **kwargs)
        self.densenet = self.densenet.to(*args, **kwargs)
        print(f"densenet sent to {args}")
        return self

    def forward_hook(self, layer_name):
        def hook(module, input, output):
            self.densenet_features[layer_name] = output

        return hook

    def forward(self, x):
        output = self.densenet(x)
        return output, self.densenet_features

class Model(nn.Module):
    def __init__(self, pretrained_encoder=True):
        super(Model, self).__init__()
        self.encoder = Encoder(pretrained_encoder)
        self.decoder = Decoder()

    def to(self, *args, **kwargs):
        self = super().to(*args, **kwargs)
        self.encoder = self.encoder.to(*args, **kwargs)
        self.decoder = self.decoder.to(*args, **kwargs)
        return self

    def forward(self, x):
        x, skip_features = self.encoder(x)
        x = self.decoder(x, skip_features)
        return x


import time
import math
import asyncio

import aiohttp
import requests

from .errors import ApiError

URL_TEMPLATE = "https://qrng.anu.edu.au/wp-content/plugins/colours-plugin/get_block_binary.php?_={tsm}"
BLOCK_SIZE = 128

class AsyncClientFree:
    async def _get_random_block(self, tsm):
        url = URL_TEMPLATE.format(tsm=tsm)

        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                if resp.status == 200:
                    data = await resp.text()
                    return int(data, 2).to_bytes(BLOCK_SIZE, byteorder='big')
                else:
                    raise ApiError(await resp.text())

    async def get_random_bytes(self, size):
        ts = time.time()
        tsm = int(ts * 1000)
        coro_list = [
            self._get_random_block(tsm + i)
            for i in range(math.ceil(size / BLOCK_SIZE))
        ]
        block_list = await asyncio.gather(*coro_list)
        return b''.join(map(bytes, block_list))[:size]

class SyncClientFree:
    def _get_random_block(self, tsm):
        url = URL_TEMPLATE.format(tsm=tsm)

        with requests.get(url) as resp:
            if resp.status_code == 200:
                return int(resp.text, 2).to_bytes(BLOCK_SIZE, byteorder='big')
            else:
                raise ApiError(resp.text)

    def get_random_bytes(self, size):
        ts = time.time()
        tsm = int(ts * 1000)
        block_list = []
        for i in range(math.ceil(size / BLOCK_SIZE)):
            block = self._get_random_block(tsm + i)
            block_list.append(block)
        return b''.join(map(bytes, block_list))[:size]


import matplotlib.pyplot as plt
import os
import funcs

colors = list('rgbcm')

# getting all commits
all_commits = os.popen('git log --pretty=oneline --all').readlines()
all_commits = [commit.split()[0] for commit in all_commits]

# creating dictionary that assigns a uniqe index for each commit
all_commits_dict = funcs.create_commits_dict(all_commits)

# getting master branch commits
master_commits = funcs.get_master_branch_commits()

# getting the name of all exsiting branchs
branches = funcs.get_branches()

# assgning a uniqe index for each branch
branches_dict = funcs.assign_axis_to_branches(branches)

# creating a dictionary that adds every commit to each related branch
# and plots them at the same time
commit_branch_rel = {}
for branch in branches:
    commits = funcs.get_commits_of_branch(branch)
    commit_branch_rel[branch] = commits
    for commit in commits:
        plt.scatter(all_commits_dict[commit], branches_dict[branch], color=colors[0],zorder=2,s=500)
    first_color = colors[0]
    colors.remove(colors[0])
    colors.append(first_color)
commit_branch_rel['master'] = master_commits

# drawing master branch commits
for commit in master_commits:
    plt.scatter(all_commits_dict[commit], branches_dict['master'], color='y',zorder=2, s=500)

# draw lines between related commits
for commit in all_commits:
    parents = funcs.get_parents_of_commit(commit)
    for parent in parents:
        parent_branch = funcs.get_branch_name_of_commit_from_dictionary(parent, commit_branch_rel)
        commit_branch = funcs.get_branch_name_of_commit_from_dictionary(commit, commit_branch_rel)
        plt.plot([all_commits_dict[parent],all_commits_dict[commit]], [branches_dict[parent_branch],branches_dict[commit_branch]], color='black',
                 zorder=1,
                 linewidth=1)

plt.show()


# Testing if we can read from Wikibase

import pywikibot
from SPARQLWrapper import SPARQLWrapper, JSON

wikibase = pywikibot.Site("my", "my")
wikibase_repo = wikibase.data_repository()
wikibase_repo.login()

item = pywikibot.ItemPage(wikibase_repo, "Q1")
item.get()
print(item.labels['en']) # should print "Semantic Interoperability Community"

fr_label = "Communauté d'interopérabilité sémantique"
new_label_data = {'fr': fr_label}
item.editLabels(new_label_data, summary=u'Added French label')


# pyright: reportMissingImports=false

import sys
import fontforge
import psMat
import util
import properties as const

if len(sys.argv) != 3:
    raise ValueError("Invalid argument")

FONT_FILE = sys.argv[1]
BUILD_FILE = sys.argv[2]

def main() -> None:
    font = fontforge.open(FONT_FILE)

    # Remove kerning info
    for lookup in font.gpos_lookups:
        if lookup.startswith("'halt'") or \
           lookup.startswith("'vhal'") or \
           lookup.startswith("'palt'") or \
           lookup.startswith("'vpal'") or \
           lookup.startswith("'kern'") or \
           lookup.startswith("'vkrn'"):
            font.removeLookup(lookup)

    # Remove vertical fonts
    font.removeLookup("'vert' Vertical Alternates lookup 18")
    font.removeLookup("'vrt2' Vertical Rotation & Alternates lookup 19")
    for glyph in font.glyphs():
        if glyph.unicode != -1:
            continue
        name = glyph.glyphname
        if name.endswith(".rotat"):
            util.font_clear_glyph(font, name)

    # Use Hack glyph
    util.font_clear_glyph(font, 0x20, 0x2002)    # number, alphabet, etc
    util.font_clear_glyph(font, 0x2004, 0x2044)  # ← skipping 0x2003 (EM SPACE)
    util.font_clear_glyph(font, 0x20ac)          # €
    util.font_clear_glyph(font, 0x2190, 0x21f5)  # arrow
    util.font_clear_glyph(font, 0x2200, 0x22A5)  # math symbol
    util.font_clear_glyph(font, 0x2116)          # №
    util.font_clear_glyph(font, 0x2122)          # ™
    util.font_clear_glyph(font, 0x23a7, 0x23ad)  # curly bracket
    util.font_clear_glyph(font, 0x2500, 0x2595)  # border symbol
    util.font_clear_glyph(font, 0x25a0, 0x25ef)  # block symbol

    util.font_set_em(font, const.ASCENT, const.DESCENT, const.EM)

    # Shrink to 1:2
    util.glyph_riseze_width(font[0x2103], const.EM // 2)  # ℃
    util.glyph_riseze_width(font[0x2109], const.EM // 2)  # ℉
    util.glyph_riseze_width(font[0x2121], const.EM // 2)  # ℡
    util.glyph_riseze_width(font[0x212B], const.EM // 2)  # Å
    util.glyph_riseze_width(font[0xfb01], const.EM // 2)  # ﬁ
    util.glyph_riseze_width(font[0xfb02], const.EM // 2)  # ﬂ

    # Fix width (Note that I don't know the meaning of the following glyphs)
    # unkown scale: 1257 name: section
    # unkown scale: 1187 name: dagger.prop
    # unkown scale: 1187 name: daggerdbl.prop
    # unkown scale: 1396 name: paragraph
    # unkown scale: 2799 name: perthousand.full
    # unkown scale: 1003 name: degree
    # unkown scale: 1290 name: plusminus
    # unkown scale: 1290 name: multiply
    # unkown scale: 1290 name: divide
    # unkown scale: 1290 name: zero.zero
    # unkown scale: 2052 name: uni51F0
    # unkown scale: 1245 name: a.alt01
    # unkown scale: 1245 name: g.alt01
    # unkown scale: 1142 name: g.alt02
    # unkown scale: 1290 name: zero.alt01
    # unkown scale: 1228 name: minus
    for name in ("section", "dagger.prop", "daggerdbl.prop", "paragraph",
                 "degree", "plusminus", "multiply",
                 "divide", "zero.zero", "uni51F0", "a.alt01", "g.alt01",
                 "g.alt02", "zero.alt01", "minus"):
        util.glyph_riseze_width(font[name], const.EM // 2)
    for name in ("perthousand.full", "uni51F0"):
        util.glyph_riseze_width(font[name], const.EM)

    modify_whitespace(font)
    resize_all_scale(font)

    util.fix_all_glyph_points(font, round=True)
    util.font_into_file(font, BUILD_FILE)
    util.log("Modified:", FONT_FILE, "->", BUILD_FILE)

def resize_all_scale(font) -> None:
    scale = 0.82
    x_to_center = const.EM * (1 - scale) / 2

    scale_mat = [psMat.scale(scale) for _ in range(2)]
    trans_mat = [psMat.translate(x) for x in (x_to_center, x_to_center / 2)]
    mat = [psMat.compose(scale_mat[i], trans_mat[i]) for i in range(2)]

    for glyph in font.glyphs():
        width = glyph.width
        if width == const.EM:
            glyph.transform(mat[0])
            glyph.width = const.EM
        elif width == const.EM // 2:
            glyph.transform(mat[1])
            glyph.width = const.EM // 2
        else:
            name = glyph.glyphname
            util.log(f"unkown scale: {width} name: {name}")

def modify_whitespace(font) -> None:
    # NOTE: if modify 0x3000, it also apply to 0x2003 (EM SPACE)
    pen = font[0x3000].glyphPen(replace=False)

    # draw square frame
    util.draw_square(pen,
                     (const.EM // 2, (const.EM - const.DESCENT) // 2),
                     round(const.EM * 0.8), round(const.EM * 0.8))
    util.draw_square(pen,
                     (const.EM // 2, (const.EM - const.DESCENT) // 2),
                     round(const.EM * 0.7), round(const.EM * 0.7),
                     clockwise=False)

    util.draw_square(pen,
                     (const.EM // 2, (const.EM - const.DESCENT) // 2),
                     round(const.EM * 0.35), round(const.EM * 2))
    util.draw_square(pen,
                     (0, (const.EM - const.DESCENT) // 2),
                     round(const.EM * 0.5), round(const.EM * 0.35))
    util.draw_square(pen,
                     (const.EM, (const.EM - const.DESCENT) // 2),
                     round(const.EM * 0.5), round(const.EM * 0.35))
    pen = None

    font.selection.select(0x3000)
    font.intersect()
    font.selection.none()

if __name__ == "__main__":
    main()


from utils import *
def criar_arquivo(nome):
    arquivo = open(nome, "w")
    linhas = arquivo.readlines()
    arquivo.close()
    return linhas

def abrir_arquivo(nome):
    arquivo = open(nome)
    linhas = arquivo.readlines()
    arquivo.close()
    return linhas

def abrir_ou_criar(nome):
    try:
        arquivo = open(nome)
    except:
        arquivo = open(nome, "w")
    linhas = arquivo.readlines()
    arquivo.close()
    return linhas

def gravar_em_arquivo(linhas, nome):
    out = open(nome, 'w')

    for i in range(len(linhas)):
        out.write(formatar_para_arquivo(linhas[i]))

    out.close()

def importar_celulares(nome_arquivo):
    linhas = abrir_arquivo(nome_arquivo)

    qtd_celulares = len(linhas)
    matriz_celulares = criar_matriz(qtd_celulares, 7)

    for i in range(len(linhas)):
        matriz_celulares[i] = linhas[i].strip().split('#')
    return matriz_celulares


# -*- coding: utf-8 -*-
"""
Created on Tue Nov  5 19:05:42 2019

@author: smouz

"Military Expenditure and GDP Web App"

"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objs as go
import plotly.express as px

pd.options.display.max_columns = 30
pd.options.display.max_rows = 50
pd.options.display.width = 100

def clean_data():
    # LOAD DATA
    df = pd.read_csv('data/Military Expenditure.csv')
    gdp_df = pd.read_csv('data/API_NY.GDP.MKTP.CD_DS2_en_csv_v2_422026.csv',
                         skiprows=4)

    #                               GDP: MELT
    gdp_years = gdp_df.columns[gdp_df.columns.str.isnumeric()].tolist()
    gdp_ids = gdp_df.iloc[:, :4].columns

    gdp_df = pd.melt(gdp_df, id_vars=gdp_ids, value_vars=gdp_years,
                     var_name='year', value_name='gdp')
    gdp_df['year'] = gdp_df['year'].astype('datetime64').dt.year

    # 'amount' -> float
    gdp_df['gdp'] = gdp_df['gdp'].astype('float')

    # GDP: RENAME
    gdp_df = gdp_df.rename(columns={'Country Name': 'country',
                                    'Country Code': 'country_code'})

    # GDP: LOWERCASE
    lower_cols = ['country', 'country_code']
    gdp_df[lower_cols] = gdp_df[lower_cols].applymap(str.lower)

    # GDP: DROP COLS
    gdp_df.drop(['Indicator Name', 'Indicator Code'], axis=1, inplace=True)

    #                   MILITARY EXPENDITURES
    # MELT
    # transform data such that all years are in one column

    # extract all 'years' from columns, and ids to unpivot on
    all_years = df.columns[df.columns.str.isnumeric()].tolist()
    ids = df.iloc[:, :4].columns

    # unpivot using melt()
    df = pd.melt(df, id_vars=ids, value_vars=all_years,
                 var_name='year', value_name='amount')

    # CONVERT DATA TYPES
    # 'year' -> datetime, year
    df['year'] = df['year'].astype('datetime64').dt.year

    # 'amount' -> float
    df['amount'] = df['amount'].astype('float')

    # RENAME COLUMNS
    df = df.rename(columns={'Name': 'country', 'Indicator Name': 'indicator'})

    # contents of columns to lwoercase
    cols_to_lower = ['country', 'Code', 'Type', 'indicator']
    df[cols_to_lower] = df[cols_to_lower].applymap(str.lower)
    df.columns = df.columns.str.lower()

    # MISSING VALUES
    # drop rows with missing values
    df = df.dropna(subset=['amount'], axis=0).reset_index(drop=True)
    df.drop(['indicator'], axis=1, inplace=True)

    # EXTRACT COUNTRIES
    # exract only countries
    df = df[df['type'] == 'country']

    #                              MERGE DATAFRAMES
    # bring together into one DF
    countries_df = pd.merge(df, gdp_df,
                            left_on=['country', 'year'],
                            right_on=['country', 'year'])

    countries_df = countries_df.dropna(subset=['gdp'], axis=0)
    countries_df = countries_df.drop(['code', 'type'], axis=1).reset_index(drop=True)

    countries_df['country'].nunique()
    countries_df = countries_df.rename(columns={'amount': 'military_expend'})

    # MILITARY VS GDP
    # compute percent of GDP
    countries_df['percent'] = countries_df['military_expend'] / countries_df['gdp'] * 100

    # extract countries with higher GDP
    df_2 = df[df['amount'] > df['amount'].mean()]
    top_countries = df_2['country'].unique().tolist()

    clean_df = countries_df[countries_df['country'].isin(top_countries)]
    clean_df.reset_index(drop=True, inplace=True)

    return clean_df

def filter_data(clean_data):
    # FILTER COUNTRIES BY TOP 10
    # groupby Country and compute mean
    agg_gdp = clean_data.groupby(['country'])['military_expend','gdp','percent'].agg(['mean'])

    # TOP 10: Military Expenditure to GDP Ratio
    mil_10 = agg_gdp.sort_values(('military_expend', 'mean'), ascending=False)[:10].index.tolist()
    top_military_df = clean_data[clean_data['country'].isin(mil_10)]

    # TOP 10: Highest GDP
    gdp_10 = agg_gdp.sort_values(('gdp', 'mean'), ascending=False)[:10].index.tolist()
    top_gdp_df = clean_data[clean_data['country'].isin(gdp_10)]

    # TOP 10: Highest Military Expenditure
    percent_10 = agg_gdp.sort_values(('percent', 'mean'), ascending=False)[:10].index.tolist()
    top_ratio_df = clean_data[clean_data['country'].isin(percent_10)]

    return top_military_df, top_gdp_df, top_ratio_df

def return_figures():

    df = clean_data()

    # define list of countries and initialize empty list
    country_ls = df['country'].unique().tolist()
    graph_one = []

    # iterate over countries to define y-values
    for country in country_ls:
        # define x and y
        # x=years, y=GDP
        x_val = df[df['country'] == country].year.tolist()
        y_val =  df[df['country'] == country].gdp.tolist()
        mark_size = df[df['country'] == country].percent*10

        graph_one.append(
                go.Scatter(
                        x=x_val,
                        y=y_val,
                        mode='markers',
                        marker=dict(size=mark_size),
                        name=country
                        )
                )
    # define layout; title, x-axis, y-axis
    layout_one = dict(title='Change in GDP between 1960 and 2019',
                      xaxis=dict(title='Year',
                                 autotick=True,
                                 tick0=1960,
                                 dtick=5
                                 ),
                      yaxis=dict(title='GDP (current USD)')
                      )
    figures = [
            dict(data=graph_one, layout=layout_one),

            ]

    # PLOTLY EXPRESS
    # Plot 1: Military Expense
    data = filter_data(clean_data())[0]
    fig_one = px.line(data,
                      x="year",
                      y="military_expend",
                      title='Military Expenditure 1960 - 2019',
                      color="country",
                      line_group="country_code",
                      labels={'military_expend': 'Military Expenditure',
                              'year': 'Year'
                              }
                      )
    # Plot 2: GDP of nations
    data_1 = filter_data(clean_data())[1]
    fig_two = px.line(data_1,
                      x="year",
                      y="gdp",
                      title='GDP between 1960 and 2019',
                      color="country",
                      line_group="country_code",
                      labels={'gdp': 'Gross Domestic Product (GDP)',
                              'year': 'Year'
                              }
                      )

    # Plot 3: ratio of Military Expense to GDP
    data_2 = filter_data(clean_data())[2]
    fig_three = px.line(data_2,
                        x="year",
                        y="percent",
                        title='Military Expenditure to GDP ratio 1960 - 2019',
                        color="country",
                        line_group="country_code",
                        labels={'percent': 'Military Expenditure to GDP Ratio',
                              'year': 'Year'
                              }
                        )
    # Plot 4: Scatter ratio of Military Expense to GDP
    data_2_scat = filter_data(clean_data())[2]
    # create new column for size of marker
#    data_2_scat['marker_size'] = data_2_scat['percent']
    fig_four = px.scatter(data_2_scat,
                          x="year",
                          y="gdp",
                          log_y=True,
                          title='Military Expenditure to GDP ratio 1960 - 2019',
                          color="country",
                          hover_data=['country', 'percent', 'gdp'],
                          size='percent',
                          size_max=75,
                          opacity=0.3,
                          labels={'percent': 'Military Expenditure to GDP Ratio',
                                  'year': 'Year'
                                  }
                          )

    # append all data into list
    fig_ls = []
    for item in [fig_one.to_dict(), fig_two.to_dict(),
                 fig_three.to_dict(), fig_four.to_dict()]:
        fig_ls.append(item)

    return fig_ls


n = 5
roots = [[1,2,3], [1,3,6], [2,4,5], [3,4,8], [3,5,1], [4,5,2]]

# n: 총 노드의 수
# roots: 간선 정보들 - [노드A, 노드B, 비용]

INF = int(1e9)
graph = [ [INF] * (n+1) for _ in range(n+1) ]

# INF: 무한대 값
# graph: 최단 거리를 담는 표 (최단 거리 = graph[출발지][도착지])

# 재귀적 간선(노드A -> 노드A)은 없으므로 0으로 초기화
for i in range(1, n+1):
    graph[i][i] = 0

# 간선 정보를 표에 삽입
# 양방향으로 이동 가능하므로, '노드A -> 노드B', '노드B -> 노드A', 이렇게 2번 삽입
for arr in roots:
    graph[ arr[0] ][ arr[1] ] = arr[2]
    graph[ arr[1] ][ arr[0] ] = arr[2]

for z in range(1, n+1):
    for a in range(1, n+1):
        for b in range(1, n+1):
            # z: 경유지
            # a: 출발지
            # b: 도착지
            # 경유점을 거쳐 가는 값이 더 작으면 더 작은 값으로 대체
            graph[a][b] = min(graph[a][b], graph[a][z] + graph[z][b])

# 모든 최단 거리 출력
for x in range(1, n+1):
    for y in range(1, n+1):
        if graph[x][y] == INF:
            print('N', end='  ')
        else:
            print(graph[x][y], end='  ')

    print()


"""
Set Matrix Zeros - #73 Leetcode.com

Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0's, and return the matrix.
You must do it in place.
"""

class Solution(object):
      def setZeroes(self, matrix):
            """
            :type matrix: List[List[int]]
            :rtype: None Do not return anything, modify matrix in-place instead.
            """
            rows = []
            cols = []
            for i in range(len(matrix)):
                  for j in range(len(matrix[0])):
                        if matrix[i][j] == 0:
                              rows.append(i)
                              cols.append(j)
            for row in rows:
                  # Add 0's the length of the column
                  matrix[row] = [0] * len(matrix[0])
            for col in cols:
                  for row in range(len(matrix)):
                        matrix[row][col] = 0
if __name__ == "__main__":
      import numpy as np
      sol = Solution()
      the_matrix = [[1, 1, 1], [1, 0, 1], [1, 1, 1]]
      expected = [[1, 0, 1], [0, 0, 0], [1, 0, 1]]
      print(f' Your Input: \n{np.matrix(the_matrix)}')
      sol.setZeroes(the_matrix)
      if the_matrix == expected:
            print(f'Expected:\n{np.matrix(expected)}\nOutput:\n{np.matrix(the_matrix)}\nStatus: PASSED')
      else:
            print("Testcase failed.")


import functools

def mycmp(x, y):
    return int(x) - int(y)

def resolve(l):
    l = list(map(int, l))
    return max(l[0] * l[1] * l[-1], l[-1] * l[-2] * l[-3])

num = int(input())
for i in range(num):
    people = int(input())
    l = input().split(" ")
    print(resolve(sorted(l, key=functools.cmp_to_key(mycmp))))


import argparse
import json

from pymongo import MongoClient

from nyan.util import get_current_ts

def main(
    output_path,
    mongo_config,
    clid_start,
    clid_end,
    batch_size
):
    with open(mongo_config) as r:
        config = json.load(r)

    client = MongoClient(**config["client"])
    database_name = config["database_name"]
    clusters_collection_name = config["clusters_collection_name"]
    collection = client[database_name][clusters_collection_name]

    if not clid_start:
        first_cluster = collection.find_one(sort=[("clid", 1)])
        clid_start = first_cluster["clid"]
    if not clid_end:
        last_cluster = collection.find_one(sort=[("clid", -1)])
        clid_end = last_cluster["clid"] + 1
    print(f"Start clid: {clid_start}")
    print(f"End clid: {clid_end}")

    current_clid_start = clid_start
    with open(output_path, "w") as w:
        while current_clid_start < clid_end:
            print(clid_end - current_clid_start)
            current_clid_end = current_clid_start + batch_size
            clusters = list(collection.find({"clid": {"$gte": current_clid_start, "$lt": current_clid_end}}))
            clusters.sort(key=lambda x: x["annotation_doc"]["pub_time"])
            for cluster in clusters:
                cluster.pop("_id")
                cluster["annotation_doc"].pop("embedding", None)
                cluster["annotation_doc"].pop("embedded_images", None)
                w.write(json.dumps(cluster, ensure_ascii=False) + "\n")
            current_clid_start = current_clid_end

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--output-path", type=str, default="data/clusters.jsonl")
    parser.add_argument("--mongo-config", type=str, default="configs/mongo_config.json")
    parser.add_argument("--clid-start", type=int, default=None)
    parser.add_argument("--clid-end", type=int, default=None)
    parser.add_argument("--batch-size", type=int, default=1000)
    args = parser.parse_args()
    main(**vars(args))


# pylint: disable=invalid-name, missing-docstring

from __future__ import print_function

import sys

with open(sys.argv[1]) as fh:
    for line in fh:
        words = line.strip().split(' ')
        words = sorted(words, key = lambda w: len(w), reverse = True)

        print(words[0])


"""JokePostLike Model."""

from devgag_api.database import Column, PkModel, db

class JokePostLike(PkModel):
    """A JokePostLike."""

    __tablename__ = "jokepost_likes"
    __table_args__ = (
        db.UniqueConstraint(  # A user can like/dislike, specific post only once. (Simply no multiple like for a post by same user)
            "user_id",
            "jokepost_id",
            name="UK__ALREADYEXIST__UserIdAndJokePostId",
        ),
    )

    # IMPORTANT NOTE : Below Field "db.CheckConstraint()" are not automatically added to "migrations" file. Make sure to add them manually if schema changed.

    user_id = Column(
        db.Integer(),
        db.ForeignKey("users.id"),
        nullable=False,
    )
    jokepost_id = Column(
        db.Integer(),
        db.ForeignKey("jokeposts.id"),
        nullable=False,
    )
    like = Column(
        db.Integer(),  # SIDENOTE: We are using "CheckConstraint" in here instead of "db.Enum(-1, 1)", Because SQLite don't support enum.
        db.CheckConstraint("like=1 OR like=-1", name="CK__InvalidType__Like"),
        nullable=False,
    )

    def __repr__(self):
        """Represent instance as a unique string."""
        return f"<JokePostLike ({self.like})>"


import os

def make_new_text_file():
    #if os.path.isfile('test.txt'):
     #   print("This file already exists.")
    #else:
        obj = open('test.txt', 'w')
        for i in range(-10000, 10000):
            text = str(i)
            obj.write("  ")
            obj.write(text)
            obj.write("  ")

def read_the_file():
    obj = open('test.txt', 'r')
    text = obj.read()
    print(text)

make_new_text_file()
read_the_file()


def partition(arr,l,h):
    if h > l:
        pivot = arr[l];
        i = l
        j = h
        while i<j:
            while arr[i] <= pivot and i<len(arr)-1:
                i+=1
            while arr[j] > pivot and j >= 0:
                j-=1
            if(i<j):
                temp = arr[i]
                arr[i] = arr[j]
                arr[j] = temp
        temp = arr[l]
        arr[l] = arr[j]
        arr[j] = temp
        return j

def quickSort(arr,low,high):

        print(f"form quick sort low={low} and high={high}")
        pi =partition(arr,low,high)
        quickSort(arr, low, pi-1)
        quickSort(arr, pi+1, high)

if __name__ == "__main__":
    t = int(input())
    for i in range(t):
        n= int(input())
        arr = list(map(int, input().strip().split()))
        quickSort(arr,0,len(arr)-1)
        for i in range(len(arr)):
            print(arr[i],end=" ")
        print()


import argparse
from datetime import datetime
import os
import pickle
import torch
import json
import tqdm
from my_utils.train_utils import BatchGen, predict_squda
from docQA.docQA_model import DocQA_Model
from my_utils.evaluate import my_evaluate

# 返回embedding矩阵 和 更新参数中三个词典的长度
def load_meta(opt, squda_meta_data_path):
    with open(squda_meta_data_path, 'rb') as f:
        meta_data = pickle.load(f)
    embedding = torch.Tensor(meta_data['embedding'])
    opt['vocab_size'] = len(meta_data['vocab'])
    opt['pos_vocab_size'] = len(meta_data['vocab_tag'])
    opt['ner_vocab_size'] = len(meta_data['vocab_ner'])
    return embedding, opt

def set_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--dev_data_path', default = 'F:\\0recentwork\\SQuDA\\data\\dev-v2.0.json')    # /home/caiyinqiong/squda/data/dev-v2.0.json
    parser.add_argument('--squda_meta_data_path', default = 'output\\squda_v2.pick')   # /home/caiyinqiong/squda/output-SAN
    parser.add_argument('--train_propress_data_path', default='output\\train_preprocess.json')  # /home/caiyinqiong/squda/output-SAN
    parser.add_argument('--dev_propress_data_path', default='output\\dev_preprocess.json')  # /home/caiyinqiong/squda/output-SAN
    # parser.add_argument('--elmo_config_path', default='F:\\0recentwork\\SQuDA\\data\\elmo_2x4096_512_2048cnn_2xhighway_5.5B_options.json')
    # parser.add_argument('--elmo_weight_path', default='F:\\0recentwork\\SQuDA\\data\\elmo_2x4096_512_2048cnn_2xhighway_5.5B_weights.hdf5')
    parser.add_argument('--out_model_dir', default='docQA_output\\model')   ## output/model

    parser.add_argument('--vocab_size', default=1000)
    parser.add_argument('--pos_vocab_size', default=10)
    parser.add_argument('--ner_vocab_size', default=10)

    # train
    parser.add_argument('--batch_size', default=32) ###### 原论文32
    parser.add_argument('--epochs', default=30)     #######################################
    parser.add_argument('--learning_rate', default=0.002)  #
    parser.add_argument('--embed_tune_partial', default=1000)  ## 只调整前1000个词的embedding
    parser.add_argument('--max_len', default=15)   # 原论文 15

    ## network
    parser.add_argument('--dropout_p', type=float, default=0.3)  ## 原文0.3  应用到embed 和 所有LSTM隐单元
    parser.add_argument('--pos_dim', default=8)  ## 词性标注的特征向量长度
    parser.add_argument('--ner_dim', default=8)    ## 实体的特征向量长度
    parser.add_argument('--prealign_hidden_size', default=128)    # 对齐网络中一层全连接层的隐单元数
    parser.add_argument('--contextual_hidden_size', default=128)   # 三层BiLSTM的隐单元数  原文是128
    parser.add_argument('--label_size', default=1)

    args = parser.parse_args()
    return args

def main():
    args = set_args()
    opt = vars(args)

    print('start load data...')
    embedding, opt = load_meta(opt, args.squda_meta_data_path)
    train_data = BatchGen(args.train_propress_data_path, args.batch_size, is_train=True)
    dev_data = BatchGen(args.dev_propress_data_path, args.batch_size, is_train=False)
    print('load data end!')

    ## model define
    # param = torch.load('/home/caiyinqiong/squda/docQA_1/output_model/model_chechpoint_epoch_0.pt')
    # opt = param['config']
    # embedding = param['state_dict']['network']['lexicon_encoder.embedding.weight']
    # model = DocQA_Model(opt, embedding)
    # model.network.load_state_dict = param['state_dict']['network']
    model = DocQA_Model(opt, embedding)
    print(model.network)
    model.setup_eval_embed(embedding)  #### DocReaderModel中的方法
    print('模型总参数量：' + str(model.total_param))

    for epoch in range(args.epochs):
        print('epoch ' + str(epoch))
        train_data.reset()   ####  BatchGen中的方法，打乱batch的顺序
        start = datetime.now()

        ## train
        print('第 ' + str(epoch) + ' 轮的训练开始......')
        for i, batch in enumerate(train_data):
            model.update(batch)  #### DocReaderModel中的方法
            #break  ########################################################### debug
            remain_time = str((datetime.now() - start) / (i + 1) * (len(train_data) - i - 1)).split('.')[0]
            print('loss = {}, remain_time = {}'.format(model.train_loss.avg, remain_time))
        print('第 ' + str(epoch) + ' 轮的训练结束！ train_loss = ' + str(model.train_loss.avg))

        ## save
        model_out_file_path = os.path.join(args.out_model_dir, 'model_chechpoint_epoch_{}.pt'.format(epoch))
        model.save(model_out_file_path)

        ## predict
        print('第 ' + str(epoch) + ' 轮的预测开始......')
        answer_pred_results = predict_squda(model, dev_data)   ## 预测的结果：{uid:answer_text}
        predict_out_path = os.path.join(args.out_model_dir, 'dev_predict_out_{}.json'.format(epoch))
        with open(predict_out_path, 'w') as f:
            json.dump(answer_pred_results, f)
        print('第 ' + str(epoch) + ' 轮的预测结束！')
        exact_score, f1_score = my_evaluate(opt['dev_data_path'], answer_pred_results)
        print('第 ' + str(epoch) + ' 轮得分：exact_score=' + str(exact_score) + ', f1_score=' + str(f1_score))

        print('epoch ' + str(epoch) + ' 结束！')
    print('train done!')

if __name__ == "__main__":
    main()


import os
import pandas as pd

# 4 steps of data work from beginning to end
import _01_input as d1
import _02_process as d2
import _03_analysis as d3
import _04_output as d4

# read in the datasets of interest and assign them to the appropriate variables
def data_prep():
    # Read in the PLACES (500 Cities: Census Tract-level) data and print out the dimension and a sample of the dataset
    df_places = d1.read_in_data('PLACES_2019.csv')
    # Read in the Toxics Release Inventory (TRI) data and print out the dimension and a sample of the dataset
    df_tri = d1.read_in_data('TRI_2019.csv')
    # Read in the NHGIS data for Race and Income as additional controls, then print out the dimension and a sample of the dataset
    df_control = d1.read_in_data('NHGIS_Race_Income_2015_2019.csv', encoding='latin1')

    return df_places, df_tri, df_control

# the main function that is run if this Python file is run
# ouput and full_output parameters used to set different mode of outputting depending on the situation
def main(output=False, full_output=False):
    df1,df2,df3 = data_prep()
    main_df = d2.lets_proceed(df1,df2,df3)
    result = d3.output_analysis(main_df)
    if output:
        d4.output(result, full=full_output)

    return [main_df, result]

if __name__ == "__main__":
    main(output=True, full_output=True)


'''
977. Squares of a Sorted Array
Easy

Given an integer array nums sorted in non-decreasing order, return an array
of the squares of each number sorted in non-decreasing order.

Example 1:
Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Explanation: After squaring, the array becomes [16,1,0,9,100].
After sorting, it becomes [0,1,9,16,100].

Example 2:
Input: nums = [-7,-3,2,3,11]
Output: [4,9,9,49,121]

Constraints:
1 <= nums.length <= 10**4
-10**4 <= nums[i] <= 10**4
nums is sorted in non-decreasing order.

Follow up: Squaring each element and sorting the new array is very trivial,
could you find an O(n) solution using a different approach?
'''

from typing import List

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        if nums[0] >= 0 or len(nums) == 1:
            return [x**2 for x in nums]

        left = 0
        right = len(nums) - 1
        result = []
        while left != right:
            if abs(nums[left]) >= abs(nums[right]):
                result.append(nums[left] ** 2)
                left += 1
            else:
                result.append(nums[right] ** 2)
                right -= 1

        result.append(nums[left] ** 2)
        return result[::-1]

sol = Solution()

assert sol.sortedSquares([0, 3, 10]) == [0, 9, 100]
assert sol.sortedSquares([-4, -1, 0, 3, 10]) == [0, 1, 9, 16, 100]
assert sol.sortedSquares([-7, -3, 2, 3, 11]) == [4, 9, 9, 49, 121]


from google_speech import Speech
from image_processing import *
from gpiozero import Button
from gtts import gTTS
import random
import os

def text_recognition():

    os.system("pkill mpg321")

    language = ''
    os.environ['OMP_THREAD_LIMIT'] = '1'
    IMAGE_PATH = "/home/pi/Desktop/output-1.jpg"
    os.system("mpg321 /home/pi/please_wait.mp3 &")

    print("pre-processing...")
    # Deskew the given image after the
    # Preprocessing stage is done
    modified_img = process_image(IMAGE_PATH)
    deskew('/home/pi/processed_image.jpg')

    print("pre-processing finished...")
    # Check the processed image for
    # Any text that is upside down

    osd = ''
    try:
        osd = pytesseract.image_to_osd('/home/pi/deskewed_image.jpg', config='--psm 0 -c min_characters_to_try=30')
        print(osd)
    except:
        pass

    index = osd.find("Script confidence:")
    script_confidence = float(index)
    script_confidence = int(script_confidence)

    script_confidence = float(osd[script_confidence+19:script_confidence+23])

    if "Script: Cyrillic" in osd and script_confidence > 0.50:
        language = 'bul'
    elif "Script: Latin" in osd and script_confidence > 0.50:
        language = 'eng'
    else:
        language = 'eng'
    # Dewarp code goes here...

    text = ''

    index = osd.find("Orientation confidence:")
    orientation_confidence = float(index)
    orientation_confidence = int(orientation_confidence)
    #print(orientation_confidence)
    #print(osd[orientation_confidence+24:orientation_confidence+28])
    orientation_confidence = float(osd[orientation_confidence+24:orientation_confidence+28])

    # Flip the image case
    if "Orientation in degrees: 180" in osd and orientation_confidence > 0.50:

        im = Image.open('/home/pi/deskewed_image.jpg')
        angle = 90
        out = im.rotate(angle)
        out.save("/home/pi/flipped_image.jpg")
        text = text_extraction('/home/pi/flipped_image.jpg', language)

    elif "Orientation in degrees: 90" in osd and orientation_confidence > 0.50:
        im = Image.open('/home/pi/deskewed_image.jpg')
        angle = 90
        out = im.rotate(angle)
        out.save("/home/pi/flipped_image.jpg")
        text = text_extraction('/home/pi/flipped_image.jpg', language)

    elif "Orientation in degrees: 270" in osd and orientation_confidence > 0.50:
        im = Image.open('/home/pi/deskewed_image.jpg')
        angle = 90
        out = im.rotate(angle)
        out.save("/home/pi/flipped_image.jpg")
        text = text_extraction('/home/pi/flipped_image.jpg', language)

    else:
        text = text_extraction('/home/pi/deskewed_image.jpg', language)

    text = mistake_removal(text)

    if 'bul' in language:
        language = 'bg'
    elif 'eng' in language:
        language = 'en'

    gtts_speak(str(text), language)

def kill_mpg():
    os.system("pkill mpg321")

def gtts_speak(text, language):

    if text != "":
        speech = Speech(text, language)
        speech.save("page.mp3")
        os.system('mpg321 page.mp3 &')

    else:
        errorMessages = ["ocr_error_1.mp3",
                         "ocr_error_2.mp3",
                         "ocr_error_3.mp3"]

        chosen_message = random.choice(errorMessages)
        print(chosen_message)

        os.system('mpg321 ' + '/home/pi/error_messages/' + chosen_message + ' &')

#text_recognition()


import json
import logging
import random
import threading
import time

import tweepy
from dotenv import dotenv_values

import Classes.countdown
import Classes.vote_processor
from Classes.worker_thread import WorkerThread
from Data_Dumps.scale_data import cybernetic_republic_scales
from Data_Dumps.vote_options import vote_options
from Utility_Tools.message_response import PoliticsMessageResponder
from Utility_Tools.message_response import generate_cybernetic_republic_message_response
from Utility_Tools.politics_logger import logger_launcher
from a2_Cybernetic_Republic.python_files.build_music_generator_objects import *
from a2_Cybernetic_Republic.python_files.send_to_sc_functions import *

class CyberneticRepublicMusicGen:
    def __init__(self, logger_object: logging.Logger, vote_processor_dat: dict,
                 num_cycles: int = 2, voting_period: int = 20, resting_period: int = 10) -> object:
        """
        Initializes Cybernetic Republic's music generator.
        :param logger_object: Logger to log as needed.
        :param vote_processor_dat: Dictionary of {String (Section): List (Keys to Music Generators)}
        :param num_cycles: Integer of number of sections to run through. (not an entire cycle through the sections).
        Currently, there are six sections, so num_cycles would need to be set to 6 to go through each different
        musical layer once.
        :param voting_period: Integer in seconds. The amount of time votes can be cast.
        :param resting_period: Integer in seconds. The amount of time that voting is closed and audience members
        can see the next vote options and listen.
        """
        # Data initialization
        self.logger = logger_object
        self.countdown = Classes.countdown.Countdown(voting_period, resting_period)
        self.section = 0
        self.introduction = True
        self.vote_option_keys = list(vote_processor_dat.keys())
        self.vote_processor_dat = vote_processor_dat
        self.vote_processor = self.build_vote_processor_options(0, self.vote_processor_dat)
        self.voters = {}

        # For thread safe handling of data
        self.worker_thread = None
        self.lock = threading.Lock()
        self.is_voting_period = False
        self.total_time = (voting_period + resting_period) * num_cycles

        # OSC UDP Clients
        self.sc_client = udp_client.SimpleUDPClient("127.0.0.1", 57120)
        self.gui_client = udp_client.SimpleUDPClient("127.0.0.1", 12000)

        # OSC Addresses
        self.vote_tally_address = "/vote_tally"
        self.update_vote_tally_address = "/update_vote_tally"
        self.count_address = "/count"
        self.selected_vote_address = "/selected_vote"
        self.end_section = "/end_section"
        self.end_address = "/end"

        # Musical Data
        self.arpeggiator = False

        self.variable_keys = {
            'bass': None,
            'progression': None,
            'middle-voices': None,
            'melody': None,
            'rhythm': None,
            'meter': None
        }

        # Message Responder
        config = dotenv_values()

        self.twitter_auth = tweepy.OAuth1UserHandler(config['TWITTER_CONSUMER_KEY'], config['TWITTER_CONSUMER_SECRET'],
                                                     config['TWITTER_ACCESS_TOKEN'], config['TWITTER_ACCESS_SECRET'])
        self.responder = PoliticsMessageResponder(config['TWILIO_ACCOUNT_SID'], config['TWILIO_AUTH_TOKEN'],
                                                  config['TWILIO_PHONE_NUMBER'], self.twitter_auth,
                                                  config['DISCORD_WEBHOOK'], config['DISCORD_TOKEN'])

        # run the countdown
        self.run_music()

    def on_data(self, data: dict):
        """
        Checks if a user has already submitted a vote. If not, via the vote processor, checks to see if an option has
        been voted for. If something has been voted for, it modifies the vote percentage tally and sends the returned
        vote string off to the GUI.
        :param data: Dictionary of data e.g. {'username': "voter", 'text': "I want a)"}
        :return: None
        """
        kwargs = {
            'vote': None,
            'already-voted': False,
            'no-option-selected': False,
            'voting-period': self.is_voting_period,
            'introduction': self.introduction,
            'first-option': self.vote_processor.candidates[0],
            'vote-text': data['text']
        }
        print(data)
        if self.is_voting_period:
            # If voting is open
            if self.voters.get(data['username']):
                # skip voter if they have already voted
                # Respond
                kwargs['already-voted'] = True
            else:
                # Update vote processor and get updated GUI string
                vote = self.vote_processor.on_message(data['text'])
                print(vote)
                if vote is None:
                    # If the voter submitted a message without a vote option.
                    # if the vote processor returns None, set voter to not having voted
                    self.voters[data['username']] = False
                    kwargs['no-option-selected'] = True
                else:
                    # If the voter submitted a message with a vote option
                    # the voter successfully voted
                    # Add voter to voters
                    self.voters[data['username']] = True
                    self.send_vote_message_to_gui(vote.splitlines(), update=True)
                    # Respond with sucessful vote
                    kwargs['vote'] = vote

        else:
            # If voting is not open
            # Respond and do nothing
            kwargs['voting-period'] = self.is_voting_period

        # Generate a response based on conditional logic
        generate_cybernetic_republic_message_response(self.responder, data=data, kwargs=kwargs)

    def run(self):
        """
        Runs the main program which spins off a subtask via self.worker_thread to count through the sections and update
        any values in a thread-safe manner.
        :return: None
        """
        # Start the GUI
        self.send_logic_to_gui("/start")
        # send initial section title to GUI
        self.send_section_title_to_gui(list(self.vote_processor_dat.keys())[self.section].upper())
        # Set initial GUI Vote options
        vote = self.vote_processor.display_current_results()
        self.send_vote_message_to_gui(vote.splitlines())
        # Start worker thread that counts through the sections
        if self.worker_thread is None:
            self.worker_thread = WorkerThread(target=self.run_counter, args=[self.total_time])
            self.worker_thread.start()

    def end(self):
        """
        Sends graceful shutdown messages and then runs shutdown on the python side.
        :return: None
        """
        msg = osc_message_builder.OscMessageBuilder(address=self.end_address)
        msg.add_arg(1, arg_type='i')
        msg = msg.build()
        self.sc_client.send(msg)
        self.gui_client.send(msg)
        self.shutdown()

    def shutdown(self):
        """
        Prints shutting down and ends the program.
        :return: None
        """
        print("shutting down")

    def run_counter(self, total_time: int):
        """
        This function runs the main logic of the cybernetic republic music generator. The counter handles the timing
        of section changeovers in a thread-safe manner.
        :param total_time: Integer of total time to run the movement.
        :return: None
        """
        total_count = 0
        while total_count <= total_time:
            if self.introduction and total_count == self.countdown.init_rest_period:
                self.start_introduction()
            # Set is voting period to match countdown
            self.is_voting_period = self.countdown.is_voting_period
            # Get message of count down as string
            count_msg = self.countdown.count()
            # Create osc message object
            msg = osc_message_builder.OscMessageBuilder(address=self.count_address)
            # Add count string to osc message
            msg.add_arg(count_msg, arg_type='s')
            # Build osc message
            msg = msg.build()
            self.gui_client.send(msg)
            # Increment aggregate count of time passed and sleep one second
            total_count += 1
            time.sleep(1)
            # On section change, generate new vote processor options/reset, flash
            if total_count % (self.countdown.init_rest_period + self.countdown.init_vote_period) == 0:
                self.lock.acquire()
                try:
                    # Send the music data to SC
                    section = self.vote_option_keys[self.section]
                    winning_key = self.vote_processor.get_winning_key()
                    self.variable_keys[section] = winning_key
                    # Turn on or off arpeggiator
                    if self.variable_keys['middle-voices'] == 'arpeggiated':
                        self.turn_arpeggiator_on_off(True)
                    else:
                        self.turn_arpeggiator_on_off(False)
                    # Send all data to SC
                    self.run_music()
                    # Send the winning key to the GUI
                    self.send_selected_vote_to_gui(self.vote_processor.get_winning_key_index())
                    # Update section
                    self.send_logic_to_gui(self.end_section)
                    self.section = (self.section + 1) % len(self.vote_option_keys)
                    self.vote_processor = self.build_vote_processor_options(self.section, self.vote_processor_dat)
                    vote = self.vote_processor.display_current_results()
                    if self.introduction:
                        self.introduction = False
                        self.end_introduction()
                    # Send New Section Title
                    self.send_section_title_to_gui(list(self.vote_processor_dat.keys())[self.section].upper())
                    # Send new vote options
                    self.send_vote_message_to_gui(vote.splitlines())
                    # reset voters
                    self.voters = {}
                finally:
                    self.lock.release()
        self.end()

    def build_vote_processor_options(self, section: str, dat: dict):
        """
        Gets a random selection of values (that then become keys for the sound synthesis side of the program) to present
        as votes.
        :param section: String of the passed section.
        :param dat: Dictionary constructed as {String: List}
        :return: VoteProcessor with the section values as the selectable options
        """
        section_vals = dat[self.vote_option_keys[section]]
        section_vals = random.sample(section_vals, 4)
        return Classes.vote_processor.VoteProcessor(*section_vals)

    def send_vote_message_to_gui(self, text_list: list, update: bool = False):
        """
        Helper function that updates the vote string on the GUI side.
        :param update: bool
        :param text_list: List of Strings from VoteProcessor object returned by a vote.
        :return: None
        """
        if update:
            msg = osc_message_builder.OscMessageBuilder(address=self.update_vote_tally_address)
        else:
            msg = osc_message_builder.OscMessageBuilder(address=self.vote_tally_address)
        for text in text_list:
            msg.add_arg(text, arg_type='s')
        msg = msg.build()
        self.gui_client.send(msg)

    def send_selected_vote_to_gui(self, selected_vote_index: int):
        """
        Sends the selected vote to the GUI.
        :param selected_vote_index: Integer of selected vote.
        :return: None
        """
        msg = osc_message_builder.OscMessageBuilder(address=self.selected_vote_address)
        msg.add_arg(selected_vote_index, arg_type='i')
        msg = msg.build()
        self.gui_client.send(msg)

    def send_logic_to_gui(self, address: str):
        """
        Sends logic to the GUI that requires no data (kind of like a bang, trigger, or gate) that simply flips a
        'switch' on receipt.
        :param address: String as OSC address.
        :return: None
        """
        msg = osc_message_builder.OscMessageBuilder(address=address)
        msg = msg.build()
        self.gui_client.send(msg)

    def send_section_title_to_gui(self, section_title, address='/section_title'):
        msg = osc_message_builder.OscMessageBuilder(address=address)
        msg.add_arg(section_title, arg_type='s')
        msg = msg.build()
        self.gui_client.send(msg)

    def start_introduction(self):
        self.send_logic_to_gui('/start_introduction')

    def end_introduction(self):
        self.send_logic_to_gui('/end_introduction')
        self.introduction = False

    @staticmethod
    def build_music_generators(meter_key=None, melody_key=None, bass_key=None,
                               middle_voices_key=None, rhythm_key=None, progression_key=None):
        """
        Builds various music generator objects by key. Some additional logic is added so that music starts from the
        beginning with some default options running.
        :param meter_key: String || None
        :param melody_key: String || None
        :param bass_key: String || None
        :param middle_voices_key: String || None
        :param rhythm_key: String || None
        :param progression_key: String || None
        :return: Dictionary of {String: Musical Generator Object}
        """
        if meter_key is None:
            meter_key = 'four'
        else:
            meter_key = meter_key

        if progression_key is None:
            progression_key = 'introduction'
        else:
            progression_key = progression_key

        hr = build_harmonic_rhythm(meter_key, progression_key)

        if bass_key is None:
            bass_key = 'introduction'
        else:
            bass_key = bass_key

        bass = build_bass(bass_key, hr, cybernetic_republic_scales['major'])

        if melody_key is None:
            melody = None
        else:
            melody = build_melody(melody_key, hr, cybernetic_republic_scales['major'])

        if middle_voices_key is None:
            middle_voices = None
        else:
            middle_voices = build_middle_voices(middle_voices_key, hr)

        if rhythm_key is None:
            rhythm_key = 'introduction'
        else:
            rhythm_key = rhythm_key

        rhythm = build_rhythm_section(rhythm_key, meter_key)

        return {'bass': bass, 'melody': melody, 'middle_voices': middle_voices, 'rhythm': rhythm}

    def send_musical_data_to_sc(self, data: dict):
        """
        Sends musical data to SuperCollider via OSC.
        :param data: Dictionary of {String: Musical Generator Object}
        :return:
        """
        # send rhythm data
        send_rhythm_to_sc(data['rhythm'], self.sc_client)
        # send middle voices data
        if data['middle_voices'] is not None:
            send_middle_voice_chords_to_sc(data['middle_voices'], self.sc_client)
            send_middle_voice_durations_to_sc(data['middle_voices'], self.sc_client)
        # send melody data
        if data['melody'] is not None:
            send_bass_or_melody_notes_to_sc(data['melody'], self.sc_client, '/melody_notes')
            send_bass_or_melody_durations_to_sc(data['melody'], self.sc_client, '/melody_durations')
        # send bass data
        send_bass_or_melody_notes_to_sc(data['bass'], self.sc_client, '/bass_notes')
        send_bass_or_melody_durations_to_sc(data['bass'], self.sc_client, '/bass_durations')

    def initialize_musical_data(self, data: dict, max_inst: int = 8, arppeggiator: bool = False):
        """
        Sends initialization command to SuperCollider via OSC.
        :param data: Dictionary of {String: Musical Generator Object}
        :param arppeggiator: Boolean of whether the arpeggiator is to be turned on or off
        :return: None
        """
        # Initialize everything
        send_rhythm_initialization_to_sc(self.sc_client)
        send_bass_or_melody_initialization_to_sc(random.randint(0, max_inst), self.sc_client, '/bass_init')
        if data['melody'] is not None:
            send_bass_or_melody_initialization_to_sc(random.randint(0, max_inst), self.sc_client, '/melody_init')
        if data['middle_voices'] is not None:
            send_middle_voice_initialization_to_sc(random.randint(0, max_inst), self.sc_client)
        # turn on or off arpeggiator
        if arppeggiator:
            send_arpeggiator_on_off_to_sc(self.sc_client, address='/arpeggiator')
        # Set Quantization after initialization
        send_quantization_update_to_sc(data['rhythm'].meter.num_beats, self.sc_client, address='/quantization')

    def run_music(self):
        """
        Runs the music generators based on the keys called.
        :return: None.
        """
        data = self.build_music_generators(self.variable_keys['meter'], self.variable_keys['melody'],
                                           self.variable_keys['bass'], self.variable_keys['middle-voices'],
                                           self.variable_keys['rhythm'], self.variable_keys['progression'])
        self.send_musical_data_to_sc(data)
        self.initialize_musical_data(data, arppeggiator=self.arpeggiator)

    def turn_arpeggiator_on_off(self, arpeggiator_on_off: bool):
        """
        Helper function that sets class variable self.arpeggiator.
        :param arpeggiator_on_off: Boolean. True = On, False = Off
        :return: None
        """
        self.arpeggiator = arpeggiator_on_off

if __name__ == "__main__":
    a = {'username': 'boop', 'text': '808'}
    b = {'username': 'lop', 'text': 'random'}
    logger = logger_launcher()
    music_gen = CyberneticRepublicMusicGen(logger, vote_options, num_cycles=20)
    music_gen.run()
    for i in range(9):
        music_gen.on_data(b)
        time.sleep(random.random() * 5)
    for i in range(5):
        music_gen.on_data(b)
        time.sleep(random.random() * 5)
    for i in range(40):
        music_gen.on_data(b)
        time.sleep(random.random() * 5)


from django.shortcuts import render, redirect
from .models import Blog
from django.contrib.auth.decorators import login_required
from django.forms import forms
from django_summernote.fields import SummernoteTextFormField
from django.http import Http404, HttpResponse, JsonResponse
from django.utils.text import slugify
from django.contrib import messages
from django.core.paginator import Paginator
import string
import random

from account.models import Notifications
from datetime import datetime

def random_string_generator(size = 10, chars = string.ascii_lowercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

def allBlogs(request) :
    if request.user.is_authenticated :
        blogs = Blog.objects.all().exclude(user=request.user).order_by('-created_on')
    else :
        blogs = Blog.objects.all().order_by('-created_on')

    cover = blogs.exclude(cover_image__exact="").exclude(cover_image__isnull=True)

    paginator = Paginator(blogs, 10)
    page = request.GET.get('page')
    paged_blogs = paginator.get_page(page)

    import random

    context = {
        "blogs" : paged_blogs,
        "cover" : random.choice(cover)
    }

    return render(request, 'pages/blogs.html', context)

class AddBlogForm(forms.Form) :
    body = SummernoteTextFormField()

@login_required(login_url='/account/login')
def addBlog(request) :
    if request.method == 'POST' :
        title = request.POST.get('title')
        slug = slugify(title)

        while Blog.objects.filter(slug_title=slug).exists() :
            randstr = random_string_generator(size=10)
            slug = "{}-{}".format(slug, randstr)

        description = request.POST.get('description')
        body = request.POST.get('body')
        cover_image = request.FILES.get('cover')
        from datetime import datetime
        created_on = datetime.now()
        try :
            blog = Blog(
                user = request.user,
                title = title,
                slug_title = slug,
                description = description,
                body = body,
                cover_image = cover_image,
                created_on = created_on,
                published = True
            )
            blog.save()
            messages.success(request, 'Blog posted successfully')
            return redirect('/blog/addblog')
        except Exception as e :
            messages.error(request, e)
            return render(request, 'pages/addblog.html', {"form" : AddBlogForm})
    else :
        return render(request, 'pages/addblog.html', {"form" : AddBlogForm})

def viewBlog(request, blog_id) :
    try :
        blog = Blog.objects.get(slug_title=blog_id)

        if blog is not None :
            return render(request, 'pages/viewblog.html', {"blog" : blog})
        else :
            raise Http404()
    except Exception as e :
        raise Http404()

@login_required(login_url='/account/login/')
def likeBlog(request) :
    if request.method == 'POST' :
        user = request.user
        blog_id = request.POST.get('blog_id')
        blog = Blog.objects.get(id=blog_id)
        if user in blog.likes.all() :
            blog.likes.remove(user)
            return JsonResponse({
                'message' : 'LIKE',
                'action' : 'DISLIKE',
                'likes' : blog.likes.count()
            })
        else :
            blog.likes.add(user)
            if user!=blog.user :
                Notifications.objects.create(user=blog.user, title='{} liked your blog'.format(user), time_created = datetime.now(), link="/blog/read/{}".format(blog.slug_title))
            return JsonResponse({
                'message' : 'DISLIKE',
                'action' : 'LIKE',
                'likes' : blog.likes.count()
            })
    else :
        messages.error(request, 'You need to be loggedin')
        return redirect('/account/login/')

@login_required(login_url='/account/login/')
def editBlog(request, blog_title) :
    if request.method == 'POST' :
        title = request.POST.get('title')
        description = request.POST.get('description')
        body = request.POST.get('body')

        from datetime import datetime
        created_on = datetime.now()

        Blog.objects.filter(slug_title=blog_title).update(title=title, description=description, created_on=created_on, body=body)

        messages.success(request, 'Blog updated successfully')
        return redirect('/blog/edit/{}/'.format(blog_title))

    else :
        blog = Blog.objects.get(slug_title__exact=blog_title)
        form = AddBlogForm(initial={'body' : blog.body})
        return render(
            request,
            'pages/editblog.html',
            {"blog" : blog, "form" : form}
        )

#   method view to delete a particular post of the user
@login_required(login_url = '/account/login/')
def deleteBlog(request, blog_title) :
    blog = Blog.objects.get(user=request.user, slug_title__exact = blog_title)
    blog.delete()
    return redirect('/@{}/'.format(request.user.username))

@login_required(login_url='/account/login/')
def bookmarkBlog(request) :
    pass


def spiralOrder(matrix):
    if not matrix:
        return []

    cds = [1, 0, -1, 0] # 列坐标步进方向
    rds = [0, 1, 0, -1] # 行坐标步进方向

    # 行列当前元素数量（步进数）
    rs, cs = len(matrix), len(matrix[0])
    turns = 0 # 拐弯次数
    r, c = 0, -1 # 当前元素坐标
    elem_num = rs * cs
    result = [0] * elem_num # 结果
    index = 0 # 当前结果下标

    while index < elem_num:
        di = turns % 4 # 步进方向下标

        # 每次拐弯，交替使用行和列的步进
        steps = cs if turns % 2 == 0 else rs
        for i in range(steps):
            r += rds[di]
            c += cds[di]
            result[index] = matrix[r][c]
            index += 1

        # 每两次拐弯，行列的步进数递减
        if turns % 2 == 0:
            cs -= 1
            rs -= 1

        turns += 1

    return result

t = int(input())
for ti in range(t):
    s = input()
    m = int(s.split(' ')[0])
    n = int(s.split(' ')[1])
    line = input().split(' ')
    #print(line)
    data =[]
    for i in range(m):
        temp = []
        for j in range(n):
            temp.append(line[i*n+j])
        data.append(temp)
    #data = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

    dat = spiralOrder(data)
    for i in dat:
        print(i,end=' ')
    print()


import math
def distance(x1,y1,x2,y2):
    x = pow(abs(x1-x2),2)
    y = pow(abs(y1-y2),2)
    return math.sqrt(x+y)

import itertools
# 順列生成
def permutation(list_):
    return list(itertools.permutations(list_))

def main():
    n = int(input())
    x,y = [0 for _ in range(n)],[0 for _ in range(n)]
    for i in range(n):
        x[i],y[i] = map(int,input().split())

    can = permutation(list(range(n)))

    all_path = 0
    for ls in can:
        path = 0
        for i in range(1,len(ls)):
            path += distance(x[ls[i-1]],y[ls[i-1]],x[ls[i]],y[ls[i]])
        all_path += path
    print(all_path/len(can))

if __name__=='__main__':
    main()


from stribog import stribog, x
from sha import sha256, sha512

from BitString import BitString
from random import randint
from pmf import pmf

size_block_for_h = {
    stribog: 512,
    sha256: 512,
    sha512: 1024
}

def hcam_sha(key: BitString, message: BitString, func) -> BitString:

    ipad = BitString('00110110' * (size_block_for_h[func] // 8))
    opad = BitString('01011100' * (size_block_for_h[func] // 8))

    return func((key + opad) // func((key + ipad) // message))

def hcam_stribog(key, message, func, func_key):

    ipad = '00110110' * (size_block_for_h[func] // 8)
    opad = '01011100' * (size_block_for_h[func] // 8)

    return func(x(key, opad) + func(x(key, ipad) + message, func_key), func_key)

def gen_key() -> BitString:
    key = BitString.mod_f_d_in_bit(pmf(randint(100, 300), 100), 0)

    return key

def format_key(key, func):
    zero_bit = BitString('0' * (size_block_for_h[func] - len(key)))
    key //= zero_bit

    return key

def get_key():
    name = input('\nВведите имя файла: ')
    with open(f'{name}.key', 'r') as file:
        key = file.read()

    return BitString(key)

def save_key(key):
    name = input('\nВведите имя файла: ')
    with open(f'{name}.key', 'w') as file:
        file.write(key)

def menu():
    print('Откуда будем кодировать?\n'
          '\t1) Сообщение из консоли\n'
          '\t2) Сообщение из файла')
    message_key = input()

    if message_key == '1':
        message = input('Введите соощение: ')
    else:
        path = input('Введите имя файла: ')
        with open(f'{path}.txt', 'r', encoding='utf-8') as file:
            message = file.read()

    key_menu = input('\nВыберите метод хеширования:\n'
                     '\t1) SHA-512;\n'
                     '\t2) SHA-256;\n'
                     '\t3) Stribog-512;\n'
                     '\t4) Stribog-256\n')

    menu_for_key = input('\nВыберите ключ:\n'
                         '\t1) Создать ключ;\n'
                         '\t2) Воспользоваться имеющимся\n')

    key = ''
    if menu_for_key == '1':
        key = gen_key()
        save_key(key.bits)
    elif menu_for_key == '2':
        key = get_key()

    message = BitString.mod_text_in_bit(message)

    if key_menu == '1':
        key = format_key(key, sha512)
        print(hcam_sha(key, message, sha512).mod_f_b_in_16())
    elif key_menu == '2':
        key = format_key(key, sha256)
        print(hcam_sha(key, message, sha256).mod_f_b_in_16())
    elif key_menu == '3':
        key = format_key(key, stribog)
        message = message.bits
        print(BitString(hcam_stribog(key.bits, message, stribog, '1')).mod_f_b_in_16())
    elif key_menu == '4':
        key = format_key(key, stribog)
        message = message.bits
        print(BitString(hcam_stribog(key.bits, message, stribog, '2')).mod_f_b_in_16())

if __name__ == '__main__':
    menu()


from pandas import DataFrame

class Enquadramento:
    def __init__(self) -> None:
        self.IsConfigured = False
        self.CodEnq = 0

    def parseFromDf(self, df: DataFrame, ind: int):
        self.NumOcorrencia = df['NumOcorrencia'][ind]
        self.CodEnq = int(df['CodEnq'][ind])

        self.IsConfigured = True

        return self


from sklearn import linear_model
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# sklearn是scikit-learn的简称，是一个基于Python的第三方模块。
# sklearn库集成了一些常用的机器学习方法，在进行机器学习任务时，并不需要实现算法，只需要简单的调用sklearn库中提供的模块就能完成大多数的机器学习任务。
# sklearn库是在Numpy、Scipy和matplotlib的基础上开发而成的，因此在sklearn的安装前，需要先安装这些依赖库。

path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
data.insert(0, 'Ones', 1)
cols = data.shape[1]
X = data.iloc[:, 0:cols-1]
y = data.iloc[:, cols-1:cols]

X = np.mat(X.values)
y = np.mat(y.values)
model = linear_model.LinearRegression()
model.fit(X, y)
x = np.array(X[:, 1].A1)
# X[:, 1]是在第一个维度里选取所有的元素，然后在第二个维度里选取第一个元素，返回仍是一个二维数据
# 而A1的作用是将任意二维数据平铺成一维
f = model.predict(X).flatten()
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()