import sys
import copy
import math
import torch
from torch import nn
from torch.nn import functional as F
from torch.nn import Conv1d, ConvTranspose1d, AvgPool1d, Conv2d
from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm

sys.path.append('../..')
import modules.commons as commons
import modules.modules as modules
import modules.attentions as attentions

from modules.commons import init_weights, get_padding

from modules.ddsp import mlp, gru, scale_function, remove_above_nyquist, upsample
from modules.ddsp import harmonic_synth, amp_to_impulse_response, fft_convolve
from modules.ddsp import resample
import utils

from modules.stft import TorchSTFT

import torch.distributions as D

from modules.losses import (
    generator_loss,
    discriminator_loss,
    feature_loss,
    kl_loss
)

LRELU_SLOPE = 0.1

class PostF0Decoder(nn.Module):
    def __init__(self, in_channels, filter_channels, kernel_size, p_dropout, spk_channels=0):
        super().__init__()

        self.in_channels = in_channels
        self.filter_channels = filter_channels
        self.kernel_size = kernel_size
        self.p_dropout = p_dropout
        self.gin_channels = spk_channels

        self.drop = nn.Dropout(p_dropout)
        self.conv_1 = nn.Conv1d(in_channels, filter_channels, kernel_size, padding=kernel_size // 2)
        self.norm_1 = modules.LayerNorm(filter_channels)
        self.conv_2 = nn.Conv1d(filter_channels, filter_channels, kernel_size, padding=kernel_size // 2)
        self.norm_2 = modules.LayerNorm(filter_channels)
        self.proj = nn.Conv1d(filter_channels, 1, 1)

        if spk_channels != 0:
            self.cond = nn.Conv1d(spk_channels, in_channels, 1)

    def forward(self, x, x_mask, g=None):
        x = torch.detach(x)
        if g is not None:
            g = torch.detach(g)
            x = x + self.cond(g)
        x = self.conv_1(x * x_mask)
        x = torch.relu(x)
        x = self.norm_1(x)
        x = self.drop(x)
        x = self.conv_2(x * x_mask)
        x = torch.relu(x)
        x = self.norm_2(x)
        x = self.drop(x)
        x = self.proj(x * x_mask)
        return x * x_mask

class TextEncoder(nn.Module):
    def __init__(self,
                 c_dim,
                 out_channels,
                 hidden_channels,
                 filter_channels,
                 n_heads,
                 n_layers,
                 kernel_size,
                 p_dropout):
        super().__init__()
        self.out_channels = out_channels
        self.hidden_channels = hidden_channels
        self.filter_channels = filter_channels
        self.n_heads = n_heads
        self.n_layers = n_layers
        self.kernel_size = kernel_size
        self.p_dropout = p_dropout

        self.pre_net = torch.nn.Linear(c_dim, hidden_channels)

        self.encoder = attentions.Encoder(
            hidden_channels,
            filter_channels,
            n_heads,
            n_layers,
            kernel_size,
            p_dropout)
        self.proj = nn.Conv1d(hidden_channels, out_channels, 1)

    def forward(self, x, x_lengths):
        x = x.transpose(1,-1)
        x = self.pre_net(x)
        x = torch.transpose(x, 1, -1)  # [b, h, t]
        x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype)
        x = self.encoder(x * x_mask, x_mask)
        x = self.proj(x) * x_mask
        return x, x_mask

def pad_v2(input_ele, mel_max_length=None):
    if mel_max_length:
        max_len = mel_max_length
    else:
        max_len = max([input_ele[i].size(0) for i in range(len(input_ele))])

    out_list = list()
    for i, batch in enumerate(input_ele):
        if len(batch.shape) == 1:
            one_batch_padded = F.pad(
                batch, (0, max_len - batch.size(0)), "constant", 0.0
            )
        elif len(batch.shape) == 2:
            one_batch_padded = F.pad(
                batch, (0, 0, 0, max_len - batch.size(0)), "constant", 0.0
            )
        out_list.append(one_batch_padded)
    out_padded = torch.stack(out_list)
    return out_padded

class LengthRegulator(nn.Module):
    """ Length Regulator """

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

    def LR(self, x, duration, max_len):
        x = torch.transpose(x, 1, 2)
        output = list()
        mel_len = list()
        for batch, expand_target in zip(x, duration):
            expanded = self.expand(batch, expand_target)
            output.append(expanded)
            mel_len.append(expanded.shape[0])

        if max_len is not None:
            output = pad_v2(output, max_len)
        else:
            output = pad_v2(output)
        output = torch.transpose(output, 1, 2)
        return output, torch.LongTensor(mel_len)

    def expand(self, batch, predicted):
        predicted = torch.squeeze(predicted)
        out = list()

        for i, vec in enumerate(batch):
            expand_size = predicted[i].item()
            state_info_index = torch.unsqueeze(torch.arange(0, expand_size), 1).float()
            state_info_length = torch.unsqueeze(torch.Tensor([expand_size] * expand_size), 1).float()
            state_info = torch.cat([state_info_index, state_info_length], 1).to(vec.device)
            new_vec = vec.expand(max(int(expand_size), 0), -1)
            new_vec = torch.cat([new_vec, state_info], 1)
            out.append(new_vec)
        out = torch.cat(out, 0)
        return out

    def forward(self, x, duration, max_len):
        output, mel_len = self.LR(x, duration, max_len)
        return output, mel_len

class PriorDecoder(nn.Module):
    def __init__(self,
                 out_bn_channels,
                 hidden_channels,
                 filter_channels,
                 n_heads,
                 n_layers,
                 kernel_size,
                 p_dropout,
                 n_speakers=0,
                 spk_channels=0):
        super().__init__()
        self.out_bn_channels = out_bn_channels
        self.hidden_channels = hidden_channels
        self.filter_channels = filter_channels
        self.n_heads = n_heads
        self.n_layers = n_layers
        self.kernel_size = kernel_size
        self.p_dropout = p_dropout
        self.spk_channels = spk_channels

        self.prenet = nn.Conv1d(hidden_channels , hidden_channels, 3, padding=1)
        self.decoder = attentions.FFT(
            hidden_channels,
            filter_channels,
            n_heads,
            n_layers,
            kernel_size,
            p_dropout)
        self.proj = nn.Conv1d(hidden_channels, out_bn_channels, 1)

        if n_speakers != 0:
            self.cond = nn.Conv1d(spk_channels, hidden_channels, 1)

    def forward(self, x, x_lengths, spk_emb=None):
        x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype)

        x = self.prenet(x) * x_mask

        if (spk_emb is not None):
            x = x + self.cond(spk_emb)

        x = self.decoder(x * x_mask, x_mask)

        bn = self.proj(x) * x_mask

        return bn, x_mask

class Decoder(nn.Module):
    def __init__(self,
                 out_channels,
                 hidden_channels,
                 filter_channels,
                 n_heads,
                 n_layers,
                 kernel_size,
                 p_dropout,
                 n_speakers=0,
                 spk_channels=0,
                 in_channels=None):
        super().__init__()
        self.out_channels = out_channels
        self.hidden_channels = hidden_channels
        self.filter_channels = filter_channels
        self.n_heads = n_heads
        self.n_layers = n_layers
        self.kernel_size = kernel_size
        self.p_dropout = p_dropout
        self.spk_channels = spk_channels

        self.prenet = nn.Conv1d(in_channels if in_channels is not None else hidden_channels, hidden_channels, 3, padding=1)
        self.decoder = attentions.FFT(
            hidden_channels,
            filter_channels,
            n_heads,
            n_layers,
            kernel_size,
            p_dropout)
        self.proj = nn.Conv1d(hidden_channels, out_channels, 1)

        if n_speakers != 0:
            self.cond = nn.Conv1d(spk_channels, hidden_channels, 1)

    def forward(self, x, x_lengths, spk_emb=None):
        x = torch.detach(x)
        x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype)

        x = self.prenet(x) * x_mask

        if (spk_emb is not None):
            x = x + self.cond(spk_emb)

        x = self.decoder(x * x_mask, x_mask)

        x = self.proj(x) * x_mask

        return x, x_mask

class F0Decoder(nn.Module):
    def __init__(self,
                 out_channels,
                 hidden_channels,
                 filter_channels,
                 n_heads,
                 n_layers,
                 kernel_size,
                 p_dropout,
                 n_speakers=0,
                 spk_channels=0,
                 in_channels=None):
        super().__init__()
        self.out_channels = out_channels
        self.hidden_channels = hidden_channels
        self.filter_channels = filter_channels
        self.n_heads = n_heads
        self.n_layers = n_layers
        self.kernel_size = kernel_size
        self.p_dropout = p_dropout
        self.spk_channels = spk_channels

        self.prenet = nn.Conv1d(in_channels if in_channels is not None else hidden_channels, hidden_channels, 3, padding=1)
        self.decoder = attentions.FFT(
            hidden_channels,
            filter_channels,
            n_heads,
            n_layers,
            kernel_size,
            p_dropout)
        self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
        self.f0_prenet = nn.Conv1d(1, hidden_channels , 3, padding=1)

        if n_speakers != 0:
            self.cond = nn.Conv1d(spk_channels, hidden_channels, 1)

    def forward(self, x, norm_f0, x_lengths, spk_emb=None):
        x = torch.detach(x)
        x += self.f0_prenet(norm_f0)
        x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype)

        x = self.prenet(x) * x_mask

        if (spk_emb is not None):
            x = x + self.cond(spk_emb)

        x = self.decoder(x * x_mask, x_mask)

        x = self.proj(x) * x_mask

        return x, x_mask

class ConvReluNorm(nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels, kernel_size, n_layers, p_dropout):
        super().__init__()
        self.in_channels = in_channels
        self.hidden_channels = hidden_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.n_layers = n_layers
        self.p_dropout = p_dropout
        assert n_layers > 1, "Number of layers should be larger than 0."

        self.conv_layers = nn.ModuleList()
        self.norm_layers = nn.ModuleList()
        self.conv_layers.append(nn.Conv1d(in_channels, hidden_channels, kernel_size, padding=kernel_size // 2))
        self.norm_layers.append(LayerNorm(hidden_channels))
        self.relu_drop = nn.Sequential(
            nn.ReLU(),
            nn.Dropout(p_dropout))
        for _ in range(n_layers - 1):
            self.conv_layers.append(nn.Conv1d(hidden_channels, hidden_channels, kernel_size, padding=kernel_size // 2))
            self.norm_layers.append(LayerNorm(hidden_channels))
        self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
        self.proj.weight.data.zero_()
        self.proj.bias.data.zero_()

    def forward(self, x):
        x = self.conv_layers[0](x)
        x = self.norm_layers[0](x)
        x = self.relu_drop(x)

        for i in range(1, self.n_layers):
            x_ = self.conv_layers[i](x)
            x_ = self.norm_layers[i](x_)
            x_ = self.relu_drop(x_)
            x = (x + x_) / 2
        x = self.proj(x)
        return x

class PosteriorEncoder(nn.Module):
    def __init__(self,
                 hps,
                 in_channels,
                 out_channels,
                 hidden_channels,
                 kernel_size,
                 dilation_rate,
                 n_layers):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.hidden_channels = hidden_channels
        self.kernel_size = kernel_size
        self.dilation_rate = dilation_rate
        self.n_layers = n_layers

        self.pre = nn.Conv1d(in_channels, hidden_channels, 1)
        self.enc = modules.WN(hidden_channels, kernel_size, dilation_rate, n_layers, n_speakers=hps.data.n_speakers, spk_channels=hps.model.spk_channels)
        # self.enc = ConvReluNorm(hidden_channels,
        #                         hidden_channels,
        #                         hidden_channels,
        #                         kernel_size,
        #                         n_layers,
        #                         0.1)
        self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)

    def forward(self, x, x_lengths, g=None):
        x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype)
        x = self.pre(x) * x_mask
        x = self.enc(x, x_mask, g=g)
        stats = self.proj(x) * x_mask
        return stats, x_mask

class ResBlock3(torch.nn.Module):
    def __init__(self, channels, kernel_size=3, dilation=(1, 3)):
        super(ResBlock3, self).__init__()
        self.convs = nn.ModuleList([
            weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[0],
                               padding=get_padding(kernel_size, dilation[0])))
        ])
        self.convs.apply(init_weights)

    def forward(self, x, x_mask=None):
        for c in self.convs:
            xt = F.leaky_relu(x, LRELU_SLOPE)
            if x_mask is not None:
                xt = xt * x_mask
            xt = c(xt)
            x = xt + x
        if x_mask is not None:
            x = x * x_mask
        return x

    def remove_weight_norm(self):
        for l in self.convs:
            remove_weight_norm(l)

class Generator_Harm(torch.nn.Module):
    def __init__(self, hps):
        super(Generator_Harm, self).__init__()
        self.hps = hps

        self.prenet = Conv1d(hps.model.hidden_channels, hps.model.hidden_channels, 3, padding=1)

        self.net = ConvReluNorm(hps.model.hidden_channels,
                                hps.model.hidden_channels,
                                hps.model.hidden_channels,
                                hps.model.kernel_size,
                                8,
                                hps.model.p_dropout)

        # self.rnn = nn.LSTM(input_size=hps.model.hidden_channels,
        #    hidden_size=hps.model.hidden_channels,
        #    num_layers=1,
        #    bias=True,
        #    batch_first=True,
        #    dropout=0.5,
        #    bidirectional=True)
        self.postnet = Conv1d(hps.model.hidden_channels, hps.model.n_harmonic + 1, 3, padding=1)

    def forward(self, f0, harm, mask):
        pitch = f0.transpose(1, 2)
        harm = self.prenet(harm)

        harm = self.net(harm) * mask
        # harm = harm.transpose(1, 2)
        # harm, (hs, hc) = self.rnn(harm)
        # harm = harm.transpose(1, 2)

        harm = self.postnet(harm)
        harm = harm.transpose(1, 2)
        param = harm

        param = scale_function(param)
        total_amp = param[..., :1]
        amplitudes = param[..., 1:]
        amplitudes = remove_above_nyquist(
            amplitudes,
            pitch,
            self.hps.data.sampling_rate,
        )
        amplitudes /= amplitudes.sum(-1, keepdim=True)
        amplitudes *= total_amp

        amplitudes = upsample(amplitudes, self.hps.data.hop_length)
        pitch = upsample(pitch, self.hps.data.hop_length)

        n_harmonic = amplitudes.shape[-1]
        omega = torch.cumsum(2 * math.pi * pitch / self.hps.data.sampling_rate, 1)
        omegas = omega * torch.arange(1, n_harmonic + 1).to(omega)
        signal_harmonics = (torch.sin(omegas) * amplitudes)
        signal_harmonics = signal_harmonics.transpose(1, 2)
        return signal_harmonics

class Generator(torch.nn.Module):
    def __init__(self, hps, initial_channel, resblock, resblock_kernel_sizes, resblock_dilation_sizes, upsample_rates,
                 upsample_initial_channel, upsample_kernel_sizes, n_speakers=0, spk_channels=0):
        super(Generator, self).__init__()
        self.num_kernels = len(resblock_kernel_sizes)
        self.num_upsamples = len(upsample_rates)
        self.conv_pre = Conv1d(initial_channel, upsample_initial_channel, 7, 1, padding=3)
        self.upsample_rates = upsample_rates
        self.n_speakers = n_speakers

        resblock = modules.ResBlock1 if resblock == '1' else modules.R

        self.downs = nn.ModuleList()
        for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
            i = len(upsample_rates) - 1 - i
            u = upsample_rates[i]
            k = upsample_kernel_sizes[i]
            # print("down: ",upsample_initial_channel//(2**(i+1))," -> ", upsample_initial_channel//(2**i))
            self.downs.append(weight_norm(
                Conv1d(hps.model.n_harmonic + 2, hps.model.n_harmonic + 2,
                       k, u, padding=k // 2)))

        self.resblocks_downs = nn.ModuleList()
        for i in range(len(self.downs)):
            j = len(upsample_rates) - 1 - i
            self.resblocks_downs.append(ResBlock3(hps.model.n_harmonic + 2, 3, (1, 3)))

        self.concat_pre = Conv1d(upsample_initial_channel + hps.model.n_harmonic + 2, upsample_initial_channel, 3, 1,
                                 padding=1)
        self.concat_conv = nn.ModuleList()
        for i in range(len(upsample_rates)):
            ch = upsample_initial_channel // (2 ** (i + 1))
            self.concat_conv.append(Conv1d(ch + hps.model.n_harmonic + 2, ch, 3, 1, padding=1, bias=False))

        self.ups = nn.ModuleList()
        for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
            self.ups.append(weight_norm(
                ConvTranspose1d(upsample_initial_channel // (2 ** i), upsample_initial_channel // (2 ** (i + 1)),
                                k, u, padding=(k - u) // 2)))

        self.resblocks = nn.ModuleList()
        for i in range(len(self.ups)):
            ch = upsample_initial_channel // (2 ** (i + 1))
            for j, (k, d) in enumerate(zip(resblock_kernel_sizes, resblock_dilation_sizes)):
                self.resblocks.append(resblock(ch, k, d))

        self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
        self.ups.apply(init_weights)

        if self.n_speakers != 0:
            self.cond = nn.Conv1d(spk_channels, upsample_initial_channel, 1)

    def forward(self, x, ddsp, g=None):

        x = self.conv_pre(x)

        if g is not None:
            x = x + self.cond(g)

        se = ddsp
        res_features = [se]
        for i in range(self.num_upsamples):
            in_size = se.size(2)
            se = self.downs[i](se)
            se = self.resblocks_downs[i](se)
            up_rate = self.upsample_rates[self.num_upsamples - 1 - i]
            se = se[:, :, : in_size // up_rate]
            res_features.append(se)

        x = torch.cat([x, se], 1)
        x = self.concat_pre(x)

        for i in range(self.num_upsamples):
            x = F.leaky_relu(x, modules.LRELU_SLOPE)
            in_size = x.size(2)
            x = self.ups[i](x)
            # 保证维度正确，丢掉多余通道
            x = x[:, :, : in_size * self.upsample_rates[i]]

            x = torch.cat([x, res_features[self.num_upsamples - 1 - i]], 1)
            x = self.concat_conv[i](x)

            xs = None
            for j in range(self.num_kernels):
                if xs is None:
                    xs = self.resblocks[i * self.num_kernels + j](x)
                else:
                    xs += self.resblocks[i * self.num_kernels + j](x)
            x = xs / self.num_kernels

        x = F.leaky_relu(x)
        x = self.conv_post(x)
        x = torch.tanh(x)

        return x

    def remove_weight_norm(self):
        print('Removing weight norm...')
        for l in self.ups:
            remove_weight_norm(l)
        for l in self.resblocks:
            l.remove_weight_norm()

class Generator_Noise(torch.nn.Module):
    def __init__(self, hps):
        super(Generator_Noise, self).__init__()
        self.hps = hps
        self.win_size = hps.data.win_size
        self.hop_size = hps.data.hop_length
        self.fft_size = hps.data.n_fft
        self.istft_pre = Conv1d(hps.model.hidden_channels, hps.model.hidden_channels, 3, padding=1)

        self.net = ConvReluNorm(hps.model.hidden_channels,
                                hps.model.hidden_channels,
                                hps.model.hidden_channels,
                                hps.model.kernel_size,
                                8,
                                hps.model.p_dropout)

        self.istft_amplitude = torch.nn.Conv1d(hps.model.hidden_channels, self.fft_size // 2 + 1, 1, 1)
        self.window = torch.hann_window(self.win_size)

    def forward(self, x, mask):
        istft_x = x
        istft_x = self.istft_pre(istft_x)

        istft_x = self.net(istft_x) * mask

        amp = self.istft_amplitude(istft_x).unsqueeze(-1)
        phase = (torch.rand(amp.shape) * 2 * 3.14 - 3.14).to(amp)

        real = amp * torch.cos(phase)
        imag = amp * torch.sin(phase)
        spec = torch.cat([real, imag], 3)
        istft_x = torch.istft(spec, self.fft_size, self.hop_size, self.win_size, self.window.to(amp), True,
                              length=x.shape[2] * self.hop_size, return_complex=False)

        return istft_x.unsqueeze(1)

class LayerNorm(nn.Module):
    def __init__(self, channels, eps=1e-5):
        super().__init__()
        self.channels = channels
        self.eps = eps

        self.gamma = nn.Parameter(torch.ones(channels))
        self.beta = nn.Parameter(torch.zeros(channels))

    def forward(self, x):
        x = x.transpose(1, -1)
        x = F.layer_norm(x, (self.channels,), self.gamma, self.beta, self.eps)
        return x.transpose(1, -1)

class DiscriminatorP(torch.nn.Module):
    def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False):
        super(DiscriminatorP, self).__init__()
        self.period = period
        self.use_spectral_norm = use_spectral_norm
        norm_f = weight_norm if use_spectral_norm == False else spectral_norm
        self.convs = nn.ModuleList([
            norm_f(Conv2d(1, 32, (kernel_size, 1), (stride, 1), padding=(get_padding(kernel_size, 1), 0))),
            norm_f(Conv2d(32, 128, (kernel_size, 1), (stride, 1), padding=(get_padding(kernel_size, 1), 0))),
            norm_f(Conv2d(128, 512, (kernel_size, 1), (stride, 1), padding=(get_padding(kernel_size, 1), 0))),
            norm_f(Conv2d(512, 1024, (kernel_size, 1), (stride, 1), padding=(get_padding(kernel_size, 1), 0))),
            norm_f(Conv2d(1024, 1024, (kernel_size, 1), 1, padding=(get_padding(kernel_size, 1), 0))),
        ])
        self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0)))

    def forward(self, x):
        fmap = []

        # 1d to 2d
        b, c, t = x.shape
        if t % self.period != 0:  # pad first
            n_pad = self.period - (t % self.period)
            x = F.pad(x, (0, n_pad), "reflect")
            t = t + n_pad
        x = x.view(b, c, t // self.period, self.period)

        for l in self.convs:
            x = l(x)
            x = F.leaky_relu(x, modules.LRELU_SLOPE)
            fmap.append(x)
        x = self.conv_post(x)
        fmap.append(x)
        x = torch.flatten(x, 1, -1)

        return x, fmap

class DiscriminatorS(torch.nn.Module):
    def __init__(self, use_spectral_norm=False):
        super(DiscriminatorS, self).__init__()
        norm_f = weight_norm if use_spectral_norm == False else spectral_norm
        self.convs = nn.ModuleList([
            norm_f(Conv1d(1, 16, 15, 1, padding=7)),
            norm_f(Conv1d(16, 64, 41, 4, groups=4, padding=20)),
            norm_f(Conv1d(64, 256, 41, 4, groups=16, padding=20)),
            norm_f(Conv1d(256, 1024, 41, 4, groups=64, padding=20)),
            norm_f(Conv1d(1024, 1024, 41, 4, groups=256, padding=20)),
            norm_f(Conv1d(1024, 1024, 5, 1, padding=2)),
        ])
        self.conv_post = norm_f(Conv1d(1024, 1, 3, 1, padding=1))

    def forward(self, x):
        fmap = []

        for l in self.convs:
            x = l(x)
            x = F.leaky_relu(x, modules.LRELU_SLOPE)
            fmap.append(x)
        x = self.conv_post(x)
        fmap.append(x)
        x = torch.flatten(x, 1, -1)

        return x, fmap

class MultiFrequencyDiscriminator(nn.Module):
    def __init__(self,
                 hop_lengths=[128, 256, 512],
                 hidden_channels=[256, 512, 512],
                 domain='double', mel_scale=True):
        super(MultiFrequencyDiscriminator, self).__init__()

        self.stfts = nn.ModuleList([
            TorchSTFT(fft_size=x * 4, hop_size=x, win_size=x * 4,
                      normalized=True, domain=domain, mel_scale=mel_scale)
            for x in hop_lengths])

        self.domain = domain
        if domain == 'double':
            self.discriminators = nn.ModuleList([
                BaseFrequenceDiscriminator(2, c)
                for x, c in zip(hop_lengths, hidden_channels)])
        else:
            self.discriminators = nn.ModuleList([
                BaseFrequenceDiscriminator(1, c)
                for x, c in zip(hop_lengths, hidden_channels)])

    def forward(self, x):
        scores, feats = list(), list()
        for stft, layer in zip(self.stfts, self.discriminators):
            # print(stft)
            mag, phase = stft.transform(x.squeeze())
            if self.domain == 'double':
                mag = torch.stack(torch.chunk(mag, 2, dim=1), dim=1)
            else:
                mag = mag.unsqueeze(1)

            score, feat = layer(mag)
            scores.append(score)
            feats.append(feat)
        return scores, feats

class BaseFrequenceDiscriminator(nn.Module):
    def __init__(self, in_channels, hidden_channels=512):
        super(BaseFrequenceDiscriminator, self).__init__()

        self.discriminator = nn.ModuleList()
        self.discriminator += [
            nn.Sequential(
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    in_channels, hidden_channels // 32,
                    kernel_size=(3, 3), stride=(1, 1)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels // 32, hidden_channels // 16,
                    kernel_size=(3, 3), stride=(2, 2)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels // 16, hidden_channels // 8,
                    kernel_size=(3, 3), stride=(1, 1)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels // 8, hidden_channels // 4,
                    kernel_size=(3, 3), stride=(2, 2)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels // 4, hidden_channels // 2,
                    kernel_size=(3, 3), stride=(1, 1)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels // 2, hidden_channels,
                    kernel_size=(3, 3), stride=(2, 2)))
            ),
            nn.Sequential(
                nn.LeakyReLU(0.2, True),
                nn.ReflectionPad2d((1, 1, 1, 1)),
                nn.utils.weight_norm(nn.Conv2d(
                    hidden_channels, 1,
                    kernel_size=(3, 3), stride=(1, 1)))
            )
        ]

    def forward(self, x):
        hiddens = []
        for layer in self.discriminator:
            x = layer(x)
            hiddens.append(x)
        return x, hiddens[-1]

class Discriminator(torch.nn.Module):
    def __init__(self, hps, use_spectral_norm=False):
        super(Discriminator, self).__init__()
        periods = [2, 3, 5, 7, 11]

        discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
        discs = discs + [DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods]
        self.discriminators = nn.ModuleList(discs)
        # self.disc_multfrequency = MultiFrequencyDiscriminator(hop_lengths=[int(hps.data.sampling_rate * 2.5 / 1000),
        #                                                                    int(hps.data.sampling_rate * 5 / 1000),
        #                                                                    int(hps.data.sampling_rate * 7.5 / 1000),
        #                                                                    int(hps.data.sampling_rate * 10 / 1000),
        #                                                                    int(hps.data.sampling_rate * 12.5 / 1000),
        #                                                                    int(hps.data.sampling_rate * 15 / 1000)],
        #                                                       hidden_channels=[256, 256, 256, 256, 256])

    def forward(self, y, y_hat):
        y_d_rs = []
        y_d_gs = []
        fmap_rs = []
        fmap_gs = []
        for i, d in enumerate(self.discriminators):
            y_d_r, fmap_r = d(y)
            y_d_g, fmap_g = d(y_hat)
            y_d_rs.append(y_d_r)
            y_d_gs.append(y_d_g)
            fmap_rs.append(fmap_r)
            fmap_gs.append(fmap_g)
        # scores_r, fmaps_r = self.disc_multfrequency(y)
        # scores_g, fmaps_g = self.disc_multfrequency(y_hat)
        # for i in range(len(scores_r)):
        #     y_d_rs.append(scores_r[i])
        #     y_d_gs.append(scores_g[i])
        #     fmap_rs.append(fmaps_r[i])
        #     fmap_gs.append(fmaps_g[i])
        return y_d_rs, y_d_gs, fmap_rs, fmap_gs

class SynthesizerTrn(nn.Module):
    """
    Model
    """

    def __init__(self, hps):
        super().__init__()
        self.hps = hps

        self.text_encoder = TextEncoder(
            hps.data.c_dim,
            hps.model.prior_hidden_channels,
            hps.model.prior_hidden_channels,
            hps.model.prior_filter_channels,
            hps.model.prior_n_heads,
            hps.model.prior_n_layers,
            hps.model.prior_kernel_size,
            hps.model.prior_p_dropout)

        self.decoder = PriorDecoder(
            hps.model.hidden_channels * 2,
            hps.model.prior_hidden_channels,
            hps.model.prior_filter_channels,
            hps.model.prior_n_heads,
            hps.model.prior_n_layers,
            hps.model.prior_kernel_size,
            hps.model.prior_p_dropout,
            n_speakers=hps.data.n_speakers,
            spk_channels=hps.model.spk_channels
        )

        self.f0_decoder = F0Decoder(
            1,
            hps.model.prior_hidden_channels,
            hps.model.prior_filter_channels,
            hps.model.prior_n_heads,
            hps.model.prior_n_layers,
            hps.model.prior_kernel_size,
            hps.model.prior_p_dropout,
            n_speakers=hps.data.n_speakers,
            spk_channels=hps.model.spk_channels
        )

        self.mel_decoder = Decoder(
            hps.data.acoustic_dim,
            hps.model.prior_hidden_channels,
            hps.model.prior_filter_channels,
            hps.model.prior_n_heads,
            hps.model.prior_n_layers,
            hps.model.prior_kernel_size,
            hps.model.prior_p_dropout,
            n_speakers=hps.data.n_speakers,
            spk_channels=hps.model.spk_channels
        )

        self.posterior_encoder = PosteriorEncoder(
            hps,
            hps.data.acoustic_dim,
            hps.model.hidden_channels,
            hps.model.hidden_channels, 3, 1, 8)

        self.dropout = nn.Dropout(0.2)

        self.LR = LengthRegulator()

        self.dec = Generator(hps,
                             hps.model.hidden_channels,
                             hps.model.resblock,
                             hps.model.resblock_kernel_sizes,
                             hps.model.resblock_dilation_sizes,
                             hps.model.upsample_rates,
                             hps.model.upsample_initial_channel,
                             hps.model.upsample_kernel_sizes,
                             n_speakers=hps.data.n_speakers,
                             spk_channels=hps.model.spk_channels)

        self.dec_harm = Generator_Harm(hps)

        self.dec_noise = Generator_Noise(hps)

        self.f0_prenet = nn.Conv1d(1, hps.model.prior_hidden_channels , 3, padding=1)
        self.energy_prenet = nn.Conv1d(1, hps.model.prior_hidden_channels , 3, padding=1)
        self.mel_prenet = nn.Conv1d(hps.data.acoustic_dim, hps.model.prior_hidden_channels , 3, padding=1)

        if hps.data.n_speakers > 0:
            self.emb_spk = nn.Embedding(hps.data.n_speakers, hps.model.spk_channels)
        self.flow = modules.ResidualCouplingBlock(hps.model.prior_hidden_channels, hps.model.hidden_channels, 5, 1, 4,n_speakers=hps.data.n_speakers, gin_channels=hps.model.spk_channels)

    def forward(self, c, c_lengths, F0, uv, mel, bn_lengths, spk_id=None):
        if self.hps.data.n_speakers > 0:
            g = self.emb_spk(spk_id).unsqueeze(-1)  # [b, h, 1]
        else:
            g = None

        # Encoder
        decoder_input, x_mask = self.text_encoder(c, c_lengths)

        LF0 = 2595. * torch.log10(1. + F0 / 700.)
        LF0 = LF0 / 500
        norm_f0 = utils.normalize_f0(LF0,x_mask, uv.squeeze(1),random_scale=True)
        pred_lf0, predict_bn_mask = self.f0_decoder(decoder_input, norm_f0, bn_lengths, spk_emb=g)
        # print(pred_lf0)
        loss_f0 = F.mse_loss(pred_lf0, LF0)

        # aam
        predict_mel, predict_bn_mask = self.mel_decoder(decoder_input + self.f0_prenet(LF0), bn_lengths, spk_emb=g)

        predict_energy = predict_mel.detach().sum(1).unsqueeze(1) / self.hps.data.acoustic_dim

        decoder_input = decoder_input + \
                        self.f0_prenet(LF0) + \
                        self.energy_prenet(predict_energy) + \
                        self.mel_prenet(predict_mel.detach())
        decoder_output, predict_bn_mask = self.decoder(decoder_input, bn_lengths, spk_emb=g)

        prior_info = decoder_output
        m_p = prior_info[:, :self.hps.model.hidden_channels, :]
        logs_p = prior_info[:, self.hps.model.hidden_channels:, :]

        # posterior
        posterior, y_mask = self.posterior_encoder(mel, bn_lengths,g=g)

        m_q = posterior[:, :self.hps.model.hidden_channels, :]
        logs_q = posterior[:, self.hps.model.hidden_channels:, :]
        z = (m_q + torch.randn_like(m_q) * torch.exp(logs_q)) * y_mask
        z_p = self.flow(z, y_mask, g=g)

        # kl loss
        loss_kl = kl_loss(z_p, logs_q, m_p, logs_p, y_mask)

        p_z = z
        p_z = self.dropout(p_z)

        pitch = upsample(F0.transpose(1, 2), self.hps.data.hop_length)
        omega = torch.cumsum(2 * math.pi * pitch / self.hps.data.sampling_rate, 1)
        sin = torch.sin(omega).transpose(1, 2)

        # dsp synthesize
        noise_x = self.dec_noise(p_z, y_mask)
        harm_x = self.dec_harm(F0, p_z, y_mask)

        # dsp waveform
        dsp_o = torch.cat([harm_x, noise_x], axis=1)

        decoder_condition = torch.cat([harm_x, noise_x, sin], axis=1)

        # dsp based HiFiGAN vocoder
        x_slice, ids_slice = commons.rand_slice_segments(p_z, bn_lengths,
                                                         self.hps.train.segment_size // self.hps.data.hop_length)
        F0_slice = commons.slice_segments(F0, ids_slice, self.hps.train.segment_size // self.hps.data.hop_length)
        dsp_slice = commons.slice_segments(dsp_o, ids_slice * self.hps.data.hop_length, self.hps.train.segment_size)
        condition_slice = commons.slice_segments(decoder_condition, ids_slice * self.hps.data.hop_length,
                                                 self.hps.train.segment_size)
        o = self.dec(x_slice, condition_slice.detach(), g=g)

        return o, ids_slice, LF0 * predict_bn_mask, dsp_slice.sum(1), loss_kl, \
               predict_mel, predict_bn_mask, pred_lf0, loss_f0, norm_f0

    def infer(self, c, g=None, f0=None,uv=None, predict_f0=False, noice_scale=0.3):
        if len(g.shape) == 2:
            g = g.squeeze(0)
        if len(f0.shape) == 2:
            f0 = f0.unsqueeze(0)
        g = self.emb_spk(g).unsqueeze(-1)  # [b, h, 1]

        c_lengths = (torch.ones(c.size(0)) * c.size(-1)).to(c.device)

        # Encoder
        decoder_input, x_mask = self.text_encoder(c, c_lengths)
        y_lengths = c_lengths

        LF0 = 2595. * torch.log10(1. + f0 / 700.)
        LF0 = LF0 / 500

        if predict_f0:
            norm_f0 = utils.normalize_f0(LF0, x_mask, uv.squeeze(1))
            pred_lf0, predict_bn_mask = self.f0_decoder(decoder_input, norm_f0, y_lengths, spk_emb=g)
            pred_f0 = 700 * ( torch.pow(10, pred_lf0 * 500 / 2595) - 1)
            f0 = pred_f0
            LF0 = pred_lf0

        # aam
        predict_mel, predict_bn_mask = self.mel_decoder(decoder_input + self.f0_prenet(LF0), y_lengths, spk_emb=g)
        predict_energy = predict_mel.sum(1).unsqueeze(1) / self.hps.data.acoustic_dim

        decoder_input = decoder_input + \
                        self.f0_prenet(LF0) + \
                        self.energy_prenet(predict_energy) + \
                        self.mel_prenet(predict_mel)
        decoder_output, y_mask = self.decoder(decoder_input, y_lengths, spk_emb=g)

        prior_info = decoder_output

        m_p = prior_info[:, :self.hps.model.hidden_channels, :]
        logs_p = prior_info[:, self.hps.model.hidden_channels:, :]
        z_p = m_p + torch.randn_like(m_p) * torch.exp(logs_p) * noice_scale
        z = self.flow(z_p, y_mask, g=g, reverse=True)

        prior_z = z

        noise_x = self.dec_noise(prior_z, y_mask)

        harm_x = self.dec_harm(f0, prior_z, y_mask)

        pitch = upsample(f0.transpose(1, 2), self.hps.data.hop_length)
        omega = torch.cumsum(2 * math.pi * pitch / self.hps.data.sampling_rate, 1)
        sin = torch.sin(omega).transpose(1, 2)

        decoder_condition = torch.cat([harm_x, noise_x, sin], axis=1)

        # dsp based HiFiGAN vocoder
        o = self.dec(prior_z, decoder_condition, g=g)

        return o, harm_x.sum(1).unsqueeze(1), noise_x, f0


class Node:
    def __init__(self, data):
        self.data = data
        self.right_child = None
        self.left_child = None
        self.height = 0

class AVL:
    def __init__(self):
        self.root = None

    def insert(self, data):
        self.root = self.insert_node(data, self.root)

    def traverse(self):
        self.traverse_in_order(self.root)

    def traverse_in_order(self, node):
        if node.left_child:
            self.traverse_in_order(node.left_child)
        print("%s" % node.data)
        if node.right_child:
            self.traverse_in_order(node.right_child)

    def insert_node(self, data, node):
        if not node:
            return Node(data)

        if data < node.data:
            node.left_child = self.insert_node(data, node.left_child)
        else:
            node.right_child = self.insert_node(data, node.right_child)

        node.height = max(self.calculate_height(node.left_child),
                          self.calculate_height(node.right_child)) + 1
        return self.settle_violations(data, node)

    def delete(self, data):
        if self.root:
            self.root = self.delete_node(data, self.root)

    def delete_node(self, data, node):
        if not node:
            return node

        if data < node.data:
            node.left_child = self.delete_node(data, node.left_child)
        elif data > node.data:
            node.right_child = self.delete_node(data, node.right_child)
        else:
            # node is leaf node
            if node.left_child is None and node.right_child is None:
                print("Removing leaf node")
                del(node)
                return None
            # node has right child
            if not node.right_child:
                print("Removing node with left child")
                temp_node = node.left_child
                del(node)
                return temp_node
            # node has left child
            if not node.left_child:
                print("Removing node with right child")
                temp_node = node.right_child
                del(node)
                return temp_node
            # node has two children
            else:
                print("Removing node with two children")
                temp_node = self.get_predecessor(self, node.left_child)
                node.data = temp_node.data
                node.left_child = self.delete_node(temp_node.data,
                                                   node.left_child)

        if not node:
            return node

        node.height = max(self.calculate_height(node.left_child),
                          self.calculate_height(node.right_child)) + 1
        balance = self.check_balance(node)

        # left-left heavy situation
        if balance < 1 and self.check_balance(node.left_child) >= 0:
            return self.rotate_right(node)
        if balance < 1 and self.check_balance(node.left_child) < 0:
            node.left_child = self.rotate_left(node.left_child)
            return self.rotate_right(node)
        if balance > 1 and self.check_balance(node.right_child) <= 0:
            return self.rotate_left(node)
        if balance > 1 and self.check_balance(node.right_child) > 0:
            node.left_child = self.rotate_right(node.left_child)
            return self.rotate_left(node)

        return node

    def get_predecessor(self, node):
        if node.right_child:
            return self.get_predecessor(node.right)
        else:
            return node

    def settle_violations(self, data, node):
        balance = self.check_balance(node)

        # case 1 -> left-left heavy situation
        if balance > 1 and data < node.left_child.data:
            print("left-left heavy situtation...")
            return self.rotate_right(node)
        # case2 -> right-right heavy situation
        if balance < -1 and data > node.right_child.data:
            print("right-right heavy situtation...")
            return self.rotate_left(node)
        # case 3 -> left right heavy situation
        if balance > 1 and data > node.left_child.data:
            print("left right heavy situation...")
            node.left_child = self.rotate_left(node.left_child)
            return self.rotate_right(node)
        # case 4 -> right left heavy situation
        if balance < -1 and data < node.right_child.data:
            print("right left heavy situation")
            node.right_child = self.rotate_right(node.right_child)
            return self.rotate_left(node)

        return node

    def calculate_height(self, node):
        if not node:
            return -1
        return node.height

    # if difference value > 1 it means it is left heavy situation
    # if difference value < -1 it means it is a right heavy situation
    def check_balance(self, node):
        if not node:
            return 0

        return self.calculate_height(node.left_child) - \
            self.calculate_height(node.right_child)

    def rotate_right(self, node):
        print("rotating to the right with the node ", node.data)
        temp_left = node.left_child
        in_pred = temp_left.right_child

        temp_left.right_child = node
        node.left_child = in_pred

        node.height = max(self.calculate_height(node.left_child),
                          self.calculate_height(node.right_child)) + 1
        temp_left.height = max(self.calculate_height(temp_left.left_child),
                               self.calculate_height(temp_left.right_child)
                               ) + 1

        return temp_left

    def rotate_left(self, node):
        print("rotating to the right with the node ", node.data)
        temp_right = node.right_child
        in_suc = temp_right.left_child

        temp_right.left_child = node
        node.right_child = in_suc

        node.height = max(self.calculate_height(node.left_child),
                          self.calculate_height(node.right_child)) + 1
        temp_right.height = max(self.calculate_height(temp_right.left_child),
                                self.calculate_height(temp_right.right_child)
                                ) + 1

        return temp_right

avl = AVL()
avl.insert(1)
avl.insert(2)
avl.insert(3)

avl.traverse()


import logging
import socket
import threading

from src import (
    parse_args,
    TestObject,
    TestCase,
    TEST_CASE_TO_TEST,
    OBJECTS,
)

def perform_calculations(test_object, test_case):
    test = TEST_CASE_TO_TEST[test_case]()
    test.run(OBJECTS[TestObject(test_object)])
    return str(test.report)

def handle_client_request(args, server_socket, client_address, data):
    try:
        logging.debug(f"Установлено соединение с клиентом {client_address}")
        command = data.split()
        logging.debug(command)

        assert "/get_result" == command[0]
        assert command[1] in [obj.value for obj in TestObject]
        for c in command[2:]:
            if c == "all":
                continue
            assert c in [case.value for case in TestCase]

        tests = (
            [item for item in TestCase]
            if "all" in command[2:]
            else [TestCase(item) for item in command[2:]]
        )

        if TestCase(args.format) not in tests:
            server_socket.sendto("".encode("utf-8"), client_address)
            return
        tests = [TestCase(args.format)]
        logging.info(args.format)

        logging.debug(tests)
        result = []
        for test in tests:
            res = perform_calculations(command[1], test)
            result.append(res)
            logging.debug(res)

        server_socket.sendto("\n".join(result).encode("utf-8"), client_address)

    except Exception as e:
        server_socket.sendto(str(e).encode("utf-8"), client_address)

def start_server(args):
    logging.basicConfig(
        level=logging.INFO,
        format="%(message)s",
    )
    host = f"server-{args.format}"
    server_address = (host, 2924)
    logging.debug(server_address)
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind(server_address)
    logging.debug(f"Сервер запущен на {server_address[0]}:{server_address[1]}")

    while True:
        data, client_address = server_socket.recvfrom(1024)
        data = data.decode()
        logging.debug(client_address)
        handle_client_request(args, server_socket, client_address, data)
    server_socket.close()


from flask import Flask, jsonify, request
import json
import numpy as np
from datetime import datetime

app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def filtering_api():
    if request.method == 'GET':
        with open('data.txt', 'r') as f:
            data = f.read().splitlines()
        data = [json.loads(item) for item in data]
        return jsonify({"response": data}), 200
    elif request.method == 'POST':
         if request.is_json:
            data = json.loads(request.data)
            main, input = data.get('main'), data.get('input')
            x1, y1 = main["x"], main["y"]
            x2 , y2 = x1 + main["width"], y1 + main["height"]
            out_file = open("data.txt", "a")
            for candid in input:
                x, y, w, h = candid["x"], candid["y"], candid["width"], candid["height"]

                if ((1 + np.min([x2, x+w])) - np.max([x1, x]) > 0) and ((1 + np.min([y2,y+h]) - np.max([y1, y])) > 0) :
                    candid["time"] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    out_file.write(json.dumps(candid)+"\n")

            out_file.close()
            return jsonify({"status": "saved"}), 201
         else:
             return "Content type is not supported. It must be json.", 415

if __name__ == '__main__':
    # app.run(debug=True)
    # To make the Flask app accessible from outside the container, you need to modify the app to listen on 0.0.0.0.
    app.run(host='0.0.0.0', debug=True)


from multiprocessing.managers import BaseManager
import random
import time
import queue

BaseManager.register('get_task_queue')
BaseManager.register('get_result_queue')

server_addr = '127.0.0.1'
manager = BaseManager(address=(server_addr,5000),authkey=b'abc')

manager.connect()

task = manager.get_task_queue()
result = manager.get_result_queue()

for i in range(10):
    try:
        temp = task.get(timeout=1)
        ans = temp * 2
        print("%s *2 = %s" % (temp,ans))
        time.sleep(1)
        result.put(ans)
    except queue.Queue().empty():
        print("task is empty")
print("Test Done....")


import openai

openai.api_key = "Fill your API key here"

days = 4
place = "Paris"

prompt = f"Make me a travel plan for {days} days to {place}"

response = openai.Completion.create(
    engine="text-davinci-002",
    prompt=prompt,
    max_tokens=4000,
    temperature=0.6,
    n=1,
    stop=None
)

print(str(response["choices"][0]["text"]))


"""
Driver for PES-Learn
"""
import timeit
import sys
import os
import json
from six.moves import input
from collections import OrderedDict
import peslearn
import numpy as np
import pandas as pd

with open('input.dat', 'r') as f:
    input_string = f.read()

input_obj = peslearn.InputProcessor(input_string)

if input_obj.keywords['mode'] == None:
    text = input("Do you want to 'generate' data, 'parse' data, or 'learn'?")
    text = text.strip()

else:
    text = input_obj.keywords['mode']

start = timeit.default_timer()

if text == 'generate' or text == 'g':
    mol = peslearn.datagen.Molecule(input_obj.zmat_string)
    config = peslearn.datagen.ConfigurationSpace(mol, input_obj)
    template_obj = peslearn.datagen.Template("./template.dat")
    config.generate_PES(template_obj)
    print("Data generation finished in {} seconds".format(round((timeit.default_timer() - start),2)))

if text == 'parse' or text == 'p':
    mol = peslearn.datagen.Molecule(input_obj.zmat_string)
    peslearn.utils.parsing_helper.parse(input_obj, mol)

if text == 'learn' or text == 'l':
    if input_obj.keywords['use_pips'] == 'true':
        mol = peslearn.datagen.Molecule(input_obj.zmat_string)
    if input_obj.keywords["ml_model"] == 'gp':
        if input_obj.keywords['use_pips'] == 'true':
            gp = peslearn.ml.GaussianProcess(input_obj.keywords["pes_name"], input_obj, molecule_type=mol.molecule_type)
        else:
            gp = peslearn.ml.GaussianProcess(input_obj.keywords["pes_name"], input_obj)
        gp.optimize_model()

    if input_obj.keywords["ml_model"] == 'nn':
        if input_obj.keywords['use_pips'] == 'true':
            nn = peslearn.ml.NeuralNetwork(input_obj.keywords["pes_name"], input_obj, molecule_type=mol.molecule_type)
        else:
            nn = peslearn.ml.NeuralNetwork(input_obj.keywords["pes_name"], input_obj)
        nn.optimize_model()

stop = timeit.default_timer()
print("Total run time: {} seconds".format(round(stop - start,2)))


#This file will need to use the DataManager,FlightSearch, FlightData, NotificationManager classes to achieve the program requirements.
from data_manager import DataManager
from flight_search import FlightSearch
from flight_data import FlightData
from notification_manager import NotificationManager
from users import User

def extract_stopovers(flight_dict):
    return_flag_list =  [flight["return"] for flight in flight_dict["route"]]
    num_stopovers = (return_flag_list.count(0) -1 , return_flag_list.count(1) -1)
    flights_out = [flight for flight in flight_dict["route"] if flight["return"] == 0]
    so_out = [flight["flyTo"] for flight in flights_out[:-1]]
    flights_in = [flight for flight in flight_dict["route"] if flight["return"] == 1]
    so_in = [flight["flyTo"] for flight in flights_in[:-1]]

    return num_stopovers, so_out, so_in

def main():

    #1. Ściągnij wszystkie dane z sheety z klasy
    sheety_data_manager = DataManager()
    sheety_data = sheety_data_manager.get_sheety_data()
    flight_search_manager = FlightSearch()
    flight_data_manager = FlightData()
    twilio_manager = NotificationManager()
    user_manager = User()
    user_info = user_manager.users_info()

    #2. Dla każdego rzędu w danych:
    for row in sheety_data:
    #a. czy ma iata code
        if row["iataCode"] == '':
    #b. jeśli nie znajdź code
            code = flight_search_manager.get_IATA_code(row['city'])
    #c. wstaw code do sheety
            row["iataCode"] = code
            sheety_data_manager.set_IATA_code(row["id"], code)
    print(sheety_data)

    for row in sheety_data:
        current_stopovers = 0
        flights = []
        while current_stopovers<= 2 and len(flights) < 1:
            flights = flight_data_manager.search_flights(row["iataCode"], row["lowestPrice"], max_stopovers=current_stopovers*2)
            print(f'{len(flights)} under {row["lowestPrice"]} to {row["city"]} found with {current_stopovers} stopovers.')
            current_stopovers += 1
        if len(flights) > 0:
            best_flight = flights[0]
            print(best_flight)

            num_stopovers, so_out, so_in = extract_stopovers(best_flight)

            flight_info = {
                "price": best_flight["price"] ,
                "departure_city_name":best_flight["cityFrom"] ,
                "departure_airport_iata_code":best_flight["cityCodeFrom"] ,
                "arrival_city_name":best_flight["cityTo"] ,
                "arrival_airport_iata_code":best_flight["cityCodeTo"] ,
                "outbound_date":str(best_flight["route"][0]["local_departure"]).split("T")[0] ,
                "inbound_date":str(best_flight["route"][-1]["local_departure"]).split("T")[0] ,
                "num_stopovers": num_stopovers, # tuple(stopoveroutbound, stopoversin inbound)
                "stopovers_out": so_out, # lista kodow
                "stopovers_in": so_in #lista kodow
            }
            print(flight_info)

            for row in user_info:

                user_phone_number = row["phoneNumber"]
                twilio_manager.send_SMS(flight_info=flight_info, phone_number=user_phone_number)

if __name__=="__main__":
    main()


# -*- coding: utf-8 -*-
from flask import Flask, render_template, request
from webapp.forms import db, ModelPosts, ModelComments, ModelTags
from read_db import *

# импорт семантического анализа
from semantic import semantic_res

def f_toxic_vals(v0, v1, v2):
    # processing results function for provide into web-page
    # функция предназначена для передачи данных в index.html в виде частей кода с целью отризовки круговых диаграмм
    # эмециональности

    toxic_rslts = [[], [], []]

    v0 = round(v0)
    v1 = round(v1)
    v2 = round(v2)

    over50 = 'progress-circle over50 p'
    under50 = 'progress-circle p'
    toxic_rslts[0] = [v0, over50 + str(v0) if v0 >= 50 else under50 + str(v0)]
    toxic_rslts[1] = [v1, over50 + str(v1) if v1 >= 50 else under50 + str(v1)]
    toxic_rslts[2] = [v2, over50 + str(v2) if v2 >= 50 else under50 + str(v2)]

    return toxic_rslts

def create_app():  # фабрика Flask

    app = Flask(__name__)
    app.config.from_pyfile('config.py')
    db.init_app(app)

    @app.route('/', methods=['POST', 'GET'])
    def index():

        # временные текстовые константы для страницы:
        v0, v1, v2 = 5, 10, 50

        title = 'Введите запрос'
        flag = False
        result = ''
        if request.method == 'POST':
            answer = request.form['text']
            answer = answer.lower()
            # information about answer
            #
            print('#'*100)
            print(type(answer))
            print(answer)
            print('#' * 100)

            result = '----- no answer -----'
            # флаг для вызова отображения результатов на странице html
            flag = True
            try:
                # function for getting data by input value
                # вызов функции для извлечениия и предобработки данных для предоставления ее в семантический анализатор
                result = get_data(answer)

            except:         # использовать без параметров не реккомендуется, но тут для красоты сделано исключение
                result = '----- no answer -----'
            finally:
                flag = True
                # печать результатов в стадии отладки приложения
                # for r in result:
                #     print(type(r))
                #     print(r)

                result_in_digits = semantic_res(result)

                v0 = result_in_digits['neg']
                v1 = result_in_digits['neu']
                v2 = result_in_digits['pos']

                # v0 = 10
                # v1 = 20
                # v2 = 30

        if request.method == 'GET':
            return render_template('index.html', title=title, answer='', flag=flag, toxic_vals=f_toxic_vals(v0, v1, v2))

        return render_template('index.html', title=title, answer=result, flag=flag, toxic_vals=f_toxic_vals(v0, v1, v2))

    return app

############################
if __name__ == '__main__':
    create_app().run(port='5000', debug=True)

#export FLASK_APP=webapp_f && export FLASK_ENV=development && flask run
#-h 172.19.65.99


import os
import copy
import logging
import numpy as np
import json_tricks
from gym import spaces

import nni
from nni.tuner import Tuner
from nni.utils import OptimizeMode, extract_scalar_reward

from .model import Model
from .util import set_global_seeds
from .policy import build_lstm_policy

logger = logging.getLogger('ppo_tuner_AutoML')

def constfn(val):
    """wrap as function"""
    def f(_):
        return val
    return f

class ModelConfig:
    """
    Configurations of the PPO model
    """
    def __init__(self):
        self.observation_space = None
        self.action_space = None
        self.num_envs = 0
        self.nsteps = 0

        self.ent_coef = 0.0
        self.lr = 3e-4
        self.vf_coef = 0.5
        self.max_grad_norm = 0.5
        self.gamma = 0.99
        self.lam = 0.95
        self.cliprange = 0.2
        self.embedding_size = None  # the embedding is for each action

        self.noptepochs = 4         # number of training epochs per update
        self.total_timesteps = 5000 # number of timesteps (i.e. number of actions taken in the environment)
        self.nminibatches = 4       # number of training minibatches per update. For recurrent policies,
                                    # should be smaller or equal than number of environments run in parallel.

class TrialsInfo:
    """
    Informations of each trial from one model inference
    """
    def __init__(self, obs, actions, values, neglogpacs, dones, last_value, inf_batch_size):
        self.iter = 0
        self.obs = obs
        self.actions = actions
        self.values = values
        self.neglogpacs = neglogpacs
        self.dones = dones
        self.last_value = last_value

        self.rewards = None
        self.returns = None

        self.inf_batch_size = inf_batch_size
        #self.states = None

    def get_next(self):
        """
        get actions of the next trial
        """
        if self.iter >= self.inf_batch_size:
            return None, None
        actions = []
        for step in self.actions:
            actions.append(step[self.iter])
        self.iter += 1
        return self.iter - 1, actions

    def update_rewards(self, rewards, returns):
        """
        after the trial is finished, reward and return of this trial is updated
        """
        self.rewards = rewards
        self.returns = returns

    def convert_shape(self):
        """
        convert shape
        """
        def sf01(arr):
            """
            swap and then flatten axes 0 and 1
            """
            s = arr.shape
            return arr.swapaxes(0, 1).reshape(s[0] * s[1], *s[2:])
        self.obs = sf01(self.obs)
        self.returns = sf01(self.returns)
        self.dones = sf01(self.dones)
        self.actions = sf01(self.actions)
        self.values = sf01(self.values)
        self.neglogpacs = sf01(self.neglogpacs)

class PPOModel:
    """
    PPO Model
    """
    def __init__(self, model_config, mask):
        self.model_config = model_config
        self.states = None    # initial state of lstm in policy/value network
        self.nupdates = None  # the number of func train is invoked, used to tune lr and cliprange
        self.cur_update = 1   # record the current update
        self.np_mask = mask   # record the mask of each action within one trial

        set_global_seeds(None)
        assert isinstance(self.model_config.lr, float)
        self.lr = constfn(self.model_config.lr)
        assert isinstance(self.model_config.cliprange, float)
        self.cliprange = constfn(self.model_config.cliprange)

        # build lstm policy network, value share the same network
        policy = build_lstm_policy(model_config)

        # Get the nb of env
        nenvs = model_config.num_envs

        # Calculate the batch_size
        self.nbatch = nbatch = nenvs * model_config.nsteps # num of record per update
        nbatch_train = nbatch // model_config.nminibatches # get batch size
        # self.nupdates is used to tune lr and cliprange
        self.nupdates = self.model_config.total_timesteps // self.nbatch

        # Instantiate the model object (that creates act_model and train_model)
        self.model = Model(policy=policy, nbatch_act=nenvs, nbatch_train=nbatch_train,
                           nsteps=model_config.nsteps, ent_coef=model_config.ent_coef, vf_coef=model_config.vf_coef,
                           max_grad_norm=model_config.max_grad_norm, np_mask=self.np_mask)

        self.states = self.model.initial_state

        logger.info('=== finished PPOModel initialization')

    def inference(self, num):
        """
        generate actions along with related info from policy network.
        observation is the action of the last step.

        Parameters:
        ----------
        num:             the number of trials to generate
        """
        # Here, we init the lists that will contain the mb of experiences
        mb_obs, mb_actions, mb_values, mb_dones, mb_neglogpacs = [], [], [], [], []
        # initial observation
        # use the (n+1)th embedding to represent the first step action
        first_step_ob = self.model_config.action_space.n
        obs = [first_step_ob for _ in range(num)]
        dones = [True for _ in range(num)]
        states = self.states
        # For n in range number of steps
        for cur_step in range(self.model_config.nsteps):
            # Given observations, get action value and neglopacs
            # We already have self.obs because Runner superclass run self.obs[:] = env.reset() on init
            actions, values, states, neglogpacs = self.model.step(cur_step, obs, S=states, M=dones)
            mb_obs.append(obs.copy())
            mb_actions.append(actions)
            mb_values.append(values)
            mb_neglogpacs.append(neglogpacs)
            mb_dones.append(dones)

            # Take actions in env and look the results
            # Infos contains a ton of useful informations
            obs[:] = actions
            if cur_step == self.model_config.nsteps - 1:
                dones = [True for _ in range(num)]
            else:
                dones = [False for _ in range(num)]

        #batch of steps to batch of rollouts
        np_obs = np.asarray(obs)
        mb_obs = np.asarray(mb_obs, dtype=np_obs.dtype)
        mb_actions = np.asarray(mb_actions)
        mb_values = np.asarray(mb_values, dtype=np.float32)
        mb_neglogpacs = np.asarray(mb_neglogpacs, dtype=np.float32)
        mb_dones = np.asarray(mb_dones, dtype=np.bool)
        last_values = self.model.value(np_obs, S=states, M=dones)

        return mb_obs, mb_actions, mb_values, mb_neglogpacs, mb_dones, last_values

    def compute_rewards(self, trials_info, trials_result):
        """
        compute the rewards of the trials in trials_info based on trials_result,
        and update the rewards in trials_info

        Parameters:
        ----------
        trials_info:             info of the generated trials
        trials_result:           final results (e.g., acc) of the generated trials
        """
        mb_rewards = np.asarray([trials_result for _ in trials_info.actions], dtype=np.float32)
        # discount/bootstrap off value fn
        mb_returns = np.zeros_like(mb_rewards)
        mb_advs = np.zeros_like(mb_rewards)
        lastgaelam = 0
        last_dones = np.asarray([True for _ in trials_result], dtype=np.bool) # ugly
        for t in reversed(range(self.model_config.nsteps)):
            if t == self.model_config.nsteps - 1:
                nextnonterminal = 1.0 - last_dones
                nextvalues = trials_info.last_value
            else:
                nextnonterminal = 1.0 - trials_info.dones[t+1]
                nextvalues = trials_info.values[t+1]
            delta = mb_rewards[t] + self.model_config.gamma * nextvalues * nextnonterminal - trials_info.values[t]
            mb_advs[t] = lastgaelam = delta + self.model_config.gamma * self.model_config.lam * nextnonterminal * lastgaelam
        mb_returns = mb_advs + trials_info.values

        trials_info.update_rewards(mb_rewards, mb_returns)
        trials_info.convert_shape()

    def train(self, trials_info, nenvs):
        """
        train the policy/value network using trials_info

        Parameters:
        ----------
        trials_info:             complete info of the generated trials from the previous inference
        nenvs:                   the batch size of the (previous) inference
        """
        # keep frac decay for future optimization
        if self.cur_update <= self.nupdates:
            frac = 1.0 - (self.cur_update - 1.0) / self.nupdates
        else:
            logger.warning('current update (self.cur_update) %d has exceeded total updates (self.nupdates) %d',
                           self.cur_update, self.nupdates)
            frac = 1.0 - (self.nupdates - 1.0) / self.nupdates
        lrnow = self.lr(frac)
        cliprangenow = self.cliprange(frac)
        self.cur_update += 1

        states = self.states

        assert states is not None # recurrent version
        assert nenvs % self.model_config.nminibatches == 0
        envsperbatch = nenvs // self.model_config.nminibatches
        envinds = np.arange(nenvs)
        flatinds = np.arange(nenvs * self.model_config.nsteps).reshape(nenvs, self.model_config.nsteps)
        for _ in range(self.model_config.noptepochs):
            np.random.shuffle(envinds)
            for start in range(0, nenvs, envsperbatch):
                end = start + envsperbatch
                mbenvinds = envinds[start:end]
                mbflatinds = flatinds[mbenvinds].ravel()
                slices = (arr[mbflatinds] for arr in (trials_info.obs, trials_info.returns, trials_info.dones,
                                                      trials_info.actions, trials_info.values, trials_info.neglogpacs))
                mbstates = states[mbenvinds]
                self.model.train(lrnow, cliprangenow, *slices, mbstates)

class PPOTuner(Tuner):
    """
    PPOTuner
    """

    def __init__(self, optimize_mode, trials_per_update=20, epochs_per_update=4, minibatch_size=4,
                 ent_coef=0.0, lr=3e-4, vf_coef=0.5, max_grad_norm=0.5, gamma=0.99, lam=0.95, cliprange=0.2):
        """
        initialization, PPO model is not initialized here as search space is not received yet.

        Parameters:
        ----------
        optimize_mode:         maximize or minimize
        trials_per_update:     number of trials to have for each model update
        epochs_per_update:     number of epochs to run for each model update
        minibatch_size:        minibatch size (number of trials) for the update
        ent_coef:              policy entropy coefficient in the optimization objective
        lr:                    learning rate of the model (lstm network), constant
        vf_coef:               value function loss coefficient in the optimization objective
        max_grad_norm:         gradient norm clipping coefficient
        gamma:                 discounting factor
        lam:                   advantage estimation discounting factor (lambda in the paper)
        cliprange:             cliprange in the PPO algorithm, constant
        """
        self.optimize_mode = OptimizeMode(optimize_mode)
        self.model_config = ModelConfig()
        self.model = None
        self.search_space = None
        self.running_trials = {}                  # key: parameter_id, value: actions/states/etc.
        self.inf_batch_size = trials_per_update   # number of trials to generate in one inference
        self.first_inf = True                     # indicate whether it is the first time to inference new trials
        self.trials_result = [None for _ in range(self.inf_batch_size)] # results of finished trials

        self.credit = 0 # record the unsatisfied trial requests
        self.param_ids = []
        self.finished_trials = 0
        self.chosen_arch_template = {}

        self.actions_spaces = None
        self.actions_to_config = None
        self.full_act_space = None
        self.trials_info = None

        self.all_trials = {} # used to dedup the same trial, key: config, value: final result

        self.model_config.num_envs = self.inf_batch_size
        self.model_config.noptepochs = epochs_per_update
        self.model_config.nminibatches = minibatch_size

        self.send_trial_callback = None
        logger.info('=== finished PPOTuner initialization')

    def _process_one_nas_space(self, block_name, block_space):
        """
        process nas space to determine observation space and action space

        Parameters:
        ----------
        block_name:              the name of the mutable block
        block_space:             search space of this mutable block

        Returns:
        ----------
        actions_spaces:          list of the space of each action
        actions_to_config:       the mapping from action to generated configuration
        """
        actions_spaces = []
        actions_to_config = []

        block_arch_temp = {}
        for l_name, layer in block_space.items():
            chosen_layer_temp = {}

            if len(layer['layer_choice']) > 1:
                actions_spaces.append(layer['layer_choice'])
                actions_to_config.append((block_name, l_name, 'chosen_layer'))
                chosen_layer_temp['chosen_layer'] = None
            else:
                assert len(layer['layer_choice']) == 1
                chosen_layer_temp['chosen_layer'] = layer['layer_choice'][0]

            if layer['optional_input_size'] not in [0, 1, [0, 1]]:
                raise ValueError('Optional_input_size can only be 0, 1, or [0, 1], but the pecified one is %s'
                                 % (layer['optional_input_size']))
            if isinstance(layer['optional_input_size'], list):
                actions_spaces.append(["None", *layer['optional_inputs']])
                actions_to_config.append((block_name, l_name, 'chosen_inputs'))
                chosen_layer_temp['chosen_inputs'] = None
            elif layer['optional_input_size'] == 1:
                actions_spaces.append(layer['optional_inputs'])
                actions_to_config.append((block_name, l_name, 'chosen_inputs'))
                chosen_layer_temp['chosen_inputs'] = None
            elif layer['optional_input_size'] == 0:
                chosen_layer_temp['chosen_inputs'] = []
            else:
                raise ValueError('invalid type and value of optional_input_size')

            block_arch_temp[l_name] = chosen_layer_temp

        self.chosen_arch_template[block_name] = block_arch_temp

        return actions_spaces, actions_to_config

    def _process_nas_space(self, search_space):
        """
        process nas search space to get action/observation space
        """
        actions_spaces = []
        actions_to_config = []
        for b_name, block in search_space.items():
            if block['_type'] != 'mutable_layer':
                raise ValueError('PPOTuner only accept mutable_layer type in search space, but the current one is %s'%(block['_type']))
            block = block['_value']
            act, act_map = self._process_one_nas_space(b_name, block)
            actions_spaces.extend(act)
            actions_to_config.extend(act_map)

        # calculate observation space
        dedup = {}
        for step in actions_spaces:
            for action in step:
                dedup[action] = 1
        full_act_space = [act for act, _ in dedup.items()]
        assert len(full_act_space) == len(dedup)
        observation_space = len(full_act_space)

        nsteps = len(actions_spaces)

        return actions_spaces, actions_to_config, full_act_space, observation_space, nsteps

    def _generate_action_mask(self):
        """
        different step could have different action space. to deal with this case, we merge all the
        possible actions into one action space, and use mask to indicate available actions for each step
        """
        two_masks = []

        mask = []
        for acts in self.actions_spaces:
            one_mask = [0 for _ in range(len(self.full_act_space))]
            for act in acts:
                idx = self.full_act_space.index(act)
                one_mask[idx] = 1
            mask.append(one_mask)
        two_masks.append(mask)

        mask = []
        for acts in self.actions_spaces:
            one_mask = [-np.inf for _ in range(len(self.full_act_space))]
            for act in acts:
                idx = self.full_act_space.index(act)
                one_mask[idx] = 0
            mask.append(one_mask)
        two_masks.append(mask)

        return np.asarray(two_masks, dtype=np.float32)

    def update_search_space(self, search_space):
        """
        get search space, currently the space only includes that for NAS

        Parameters:
        ----------
        search_space:                  search space for NAS

        Returns:
        -------
        no return
        """
        logger.info('=== update search space %s', search_space)
        assert self.search_space is None
        self.search_space = search_space

        assert self.model_config.observation_space is None
        assert self.model_config.action_space is None

        self.actions_spaces, self.actions_to_config, self.full_act_space, obs_space, nsteps = self._process_nas_space(search_space)

        self.model_config.observation_space = spaces.Discrete(obs_space)
        self.model_config.action_space = spaces.Discrete(obs_space)
        self.model_config.nsteps = nsteps

        # generate mask in numpy
        mask = self._generate_action_mask()

        assert self.model is None
        self.model = PPOModel(self.model_config, mask)

    def _actions_to_config(self, actions):
        """
        given actions, to generate the corresponding trial configuration
        """
        chosen_arch = copy.deepcopy(self.chosen_arch_template)
        for cnt, act in enumerate(actions):
            act_name = self.full_act_space[act]
            (block_name, layer_name, key) = self.actions_to_config[cnt]
            if key == 'chosen_inputs':
                if act_name == 'None':
                    chosen_arch[block_name][layer_name][key] = []
                else:
                    chosen_arch[block_name][layer_name][key] = [act_name]
            elif key == 'chosen_layer':
                chosen_arch[block_name][layer_name][key] = act_name
            else:
                raise ValueError('unrecognized key: {0}'.format(key))
        return chosen_arch

    def generate_multiple_parameters(self, parameter_id_list, **kwargs):
        """
        Returns multiple sets of trial (hyper-)parameters, as iterable of serializable objects.
        """
        result = []
        self.send_trial_callback = kwargs['st_callback']
        for parameter_id in parameter_id_list:
            had_exception = False
            try:
                logger.debug("generating param for %s", parameter_id)
                res = self.generate_parameters(parameter_id, **kwargs)
            except nni.NoMoreTrialError:
                had_exception = True
            if not had_exception:
                result.append(res)
        return result

    def generate_parameters(self, parameter_id, **kwargs):
        """
        generate parameters, if no trial configration for now, self.credit plus 1 to send the config later
        """
        if self.first_inf:
            self.trials_result = [None for _ in range(self.inf_batch_size)]
            mb_obs, mb_actions, mb_values, mb_neglogpacs, mb_dones, last_values = self.model.inference(self.inf_batch_size)
            self.trials_info = TrialsInfo(mb_obs, mb_actions, mb_values, mb_neglogpacs,
                                          mb_dones, last_values, self.inf_batch_size)
            self.first_inf = False

        trial_info_idx, actions = self.trials_info.get_next()
        if trial_info_idx is None:
            self.credit += 1
            self.param_ids.append(parameter_id)
            raise nni.NoMoreTrialError('no more parameters now.')

        self.running_trials[parameter_id] = trial_info_idx
        new_config = self._actions_to_config(actions)
        return new_config

    def _next_round_inference(self):
        """
        """
        self.finished_trials = 0
        self.model.compute_rewards(self.trials_info, self.trials_result)
        self.model.train(self.trials_info, self.inf_batch_size)
        self.running_trials = {}
        # generate new trials
        self.trials_result = [None for _ in range(self.inf_batch_size)]
        mb_obs, mb_actions, mb_values, mb_neglogpacs, mb_dones, last_values = self.model.inference(self.inf_batch_size)
        self.trials_info = TrialsInfo(mb_obs, mb_actions, mb_values, mb_neglogpacs,
                                        mb_dones, last_values, self.inf_batch_size)
        # check credit and submit new trials
        for _ in range(self.credit):
            trial_info_idx, actions = self.trials_info.get_next()
            if trial_info_idx is None:
                logger.warning('No enough trial config, trials_per_update is suggested to be larger than trialConcurrency')
                break
            assert self.param_ids
            param_id = self.param_ids.pop()
            self.running_trials[param_id] = trial_info_idx
            new_config = self._actions_to_config(actions)
            self.send_trial_callback(param_id, new_config)
            self.credit -= 1

    def receive_trial_result(self, parameter_id, parameters, value, **kwargs):
        """
        receive trial's result. if the number of finished trials equals self.inf_batch_size, start the next update to
        train the model
        """
        trial_info_idx = self.running_trials.pop(parameter_id, None)
        assert trial_info_idx is not None

        value = extract_scalar_reward(value)
        if self.optimize_mode == OptimizeMode.Minimize:
            value = -value

        self.trials_result[trial_info_idx] = value
        self.finished_trials += 1

        if self.finished_trials == self.inf_batch_size:
            self._next_round_inference()

    def trial_end(self, parameter_id, success, **kwargs):
        """
        to deal with trial failure
        """
        if not success:
            if parameter_id not in self.running_trials:
                logger.warning('The trial is failed, but self.running_trial does not have this trial')
                return
            trial_info_idx = self.running_trials.pop(parameter_id, None)
            assert trial_info_idx is not None
            # use mean of finished trials as the result of this failed trial
            values = [val for val in self.trials_result if val is not None]
            logger.warning('zql values: {0}'.format(values))
            self.trials_result[trial_info_idx] = (sum(values) / len(values)) if len(values) > 0 else 0
            self.finished_trials += 1
            if self.finished_trials == self.inf_batch_size:
                self._next_round_inference()

    def import_data(self, data):
        """
        Import additional data for tuning

        Parameters
        ----------
        data:               a list of dictionarys, each of which has at least two keys, 'parameter' and 'value'
        """
        logger.warning('PPOTuner cannot leverage imported data.')


from aiogram import Bot, Dispatcher,executor,types
from token_auth import token
from script import get_user_info,get_user_subs,get_friends_user,get_user_photo
import json

def telegram_bot(token):
    bot  = Bot(token=token,parse_mode=types.ParseMode.HTML)
    dp = Dispatcher(bot=bot)

    #@dp.message_handler(content_types=["text"])
    async def echo(message: types.Message):
        await message.answer("[ 🔧 ] Бот на разработке, но он обязательно оживёт ")
        await message.answer("🧑💻")
        print(f"[+] LOGGING: '{message.text}' от {message.from_user.full_name} ({message.from_user.id})")

    @dp.message_handler(commands=['start'])
    async def send_message(message: types.Message):
        await message.answer("Важная информация: данный бот находится в разработке, поэтому я жду от Вас фидбэк по работе бота в лс @gifgufgaf")
        await message.answer("Вкратце о боте: данный бот берёт данные исключительно из открытых источников (VK, Instagram(пока не добавлено)), поэтому важно, чтобы цели бота были открытыми профилями.")
        print(f"[+] LOGGING: '{message.text}' от {message.from_user.full_name} ({message.from_user.id})")

    @dp.message_handler(commands=['help'])
    async def send_message(message: types.Message):
        await message.answer("Вводи в любом формате (числовой или буквенный) \n\nНе нагружай бота страницами с 500> фото, а то ему станет плохо🥹 ")
        print(f"[+] LOGGING: '{message.text}' от {message.from_user.full_name} ({message.from_user.id})")

    @dp.message_handler(content_types=["text"])

    async def echo(message: types.Message):
        try:
            print(f"[+] LOGGING: '{message.text}' от {message.from_user.full_name} ({message.from_user.id})")
            user_id = message.text
            await message.answer(f"Информация, найденная по айди: {message.text}")
            get_user_info(user_id)
            with open("account_info.json", "r") as read_file:
                data = json.load(read_file)
                first_name = data["first_name"]
                second_name = data["second_name"]
                birth_date = data["birth_date"]
                interests = data["interests"]
                home_town = data["home_town"]
                city = data["city"]
                mobile_phone = data["mobile_phone"]
            read_file.close()

            await message.answer(f"Вот что удалось найти: \n \t 📋 Имя Фамилия: {first_name} {second_name} \n \t 🎉 День рождения: {birth_date} \n \t 😍 Интересы: {interests} \n \t 🏠 Родной город: {home_town} \n \t 🏙 Город: {city} \n \t 📱 Мобильный телефон: {mobile_phone} \n Подробная информация файлами ниже.")
            await message.answer_document(open('account_info.json', 'rb'))
            get_user_subs(user_id)
            await message.answer_document(open('account_subs.json', 'rb'))
            get_friends_user(user_id)
            await message.answer_document(open('account_friends.json', 'rb'))
            await message.answer(f"Раздел с фотографиями на доработке")
            #get_user_photo(user_id)
            #await message.answer_document(open('account_photos.zip', 'rb'))
            #await message.answer_video(open('success.mp4','rb'))
        except:
            await message.answer("Чёт пошло не так, но это обязательно пофиксится, надо просто подождать, правда ведь? ")
            await message.answer("🥺")
            print(f"[!] WARNING: '{message.text}' от {message.from_user.full_name} ({message.from_user.id})")
    executor.start_polling(dispatcher = dp)
if __name__ == "__main__":
    telegram_bot(token)


#!/usr/bin/python3
# -*- coding: utf-8 -*-

import urllib.request
url="http://google.cn/"
response=urllib.request.urlopen(url)
page=response.read()
#print(page)
f = open('index.html', "wb+")
f.write(page)  #用readlines()方法写入文件
f.close()


'''
Created on Jul 17, 2014

@author: c3h3
'''

class EdxUrls(object):
    edx_site_dict = {"edx":"https://courses.edx.org",
                     "stanford":"https://class.stanford.edu",
                     }

    def __init__(self, edx_site="edx"):
        assert edx_site in self.edx_site_dict.keys()

        self.base = self.edx_site_dict[edx_site]
        self.login_ajax = self.base + "/login_ajax"
        self.dashboard = self.base + "/dashboard"


import numpy as np
import matplotlib.pyplot as plt

# Color
# https://matplotlib.org/stable/gallery/color/named_colors.html

#https://www.yutaka-note.com/entry/matplotlib_subplots

x = np.linspace(-3,3)
y1 = x**2
y2 = x
fig, ax = plt.subplots(1, 2, squeeze=False,figsize=(8,3),tight_layout=True)
ax[0,0].plot(x, y1,"SteelBlue", linewidth=2)
ax[0,0].plot(x, y2,"LightSteelBlue")
ax[0,0].set_title("A")
ax[0,0].legend(["test1","test2"])
ax[0,0].set_xlabel("x-label")
ax[0,0].set_ylabel("y-label")

ax[0,1].plot(x, y2)
ax[0,1].set_title("B")
ax[0,1].legend(["test2"])
ax[0,1].set_xticks(list(range(-3,8,2)))
ax[0,1].set_xlim(-3, 10)

fig.autofmt_xdate()
plt.show()


import sqlite3, datetime
from EmployeeEdit import randserial
from Login import clear
from Inventory import unique
conn = sqlite3.connect('MarksHardware.db')
cursor = conn.cursor()

def uniquesales(ID): #ensures unique Ids
  for id in conn.execute("SELECT SALESID FROM SALES"):
    if id[0] == ID:
      return False
    return True

def addsales(USERID): #Adds sales uses current date time and Id from who logged on to categorize sales
  clear()
  try:
    cashier = conn.execute(f"SELECT NAME from COMPANY where ID = {USERID}").fetchall()[0][0]
    while True:
      SALESID = randserial(6)
      if uniquesales(SALESID):
        break
    for row in conn.execute("SELECT ID, NAME from INVENTORY"):
      print(f'ID: {row[0]} || Name: {row[1]} ')

    while True:
      print('Sales ID:', SALESID)
      print('Cashier:', cashier)
      Sale = int(input('Enter serial #. Enter 0 to cancel: ')) # getsinventory id of item
      if Sale == 0:
        input('Cancel. \nPress ente to continue...')
        return
      if unique(Sale) == False: # decides if the serial number provided is valid
        print("Found!")
        Name = conn.execute(f"SELECT NAME FROM INVENTORY WHERE ID = {Sale}").fetchone()[0] # gets the product namewith the id from the inventory
        date = datetime.datetime.now().date() # Gets date of sale
        unitsleft2 = conn.execute(f"SELECT STOCK FROM INVENTORY WHERE ID={Sale}").fetchone()[0] # gets units left in stock of item
        print('There are', unitsleft2, 'left in stock')
        while True: # loop asks for unts being sold and if the input is invalid loop it
          sold = int(input('Input number of units being sold: '))
          if unitsleft2 >= sold: # checks to see if there is enough in stock to sell requested amount
            break
          else:
            print('Invalid. Not enough stock.')
            continue
        salval = (SALESID, Sale, Name, sold, date, cashier)
        conn.execute("INSERT INTO SALES VALUES (?,?,?,?,?,?)", salval)
        conn.execute(f"UPDATE INVENTORY SET STOCK = {unitsleft2 - sold} where ID = {Sale}")
        conn.commit()
        input('Success. \nPress enter to continue...')
        return
      else:  # if serial Id does not match any in the inventory asks for id again
          input("Serial # does not exist. \nPress enter to continue...")
          continue
  except:
    input('Invalid. \nPress enter to continue...')

def viewsales(): #This function prints out all the past sales
  for row in conn.execute("SELECT * FROM SALES").fetchall():
    print(f'Sale ID: {row[0]} || Item ID: {row[1]}\nItem: {row[2]} || # of items sold: {row[3]}\nDate: {row[4]} || Cashier: {row[5]}\n')
  input('Press enter to continue...')

def main(id): #This function gives you choices to choose from to continue
  while True:
    clear()
    choice = input("""
  -------Sales information-------
  Please choose:
  1 - View Sales
  2 - Add Sales
  3 - Return
  ----------------------------------
  """)
    if choice == "1":
      viewsales()
    elif choice == "2":
      addsales(id)
    elif choice == "3":
      return
    else:
      input("Invalid.\nPress enter to continue:...")


with open("2021/03/input.txt", "r") as f:
    binaryTable = []
    for line in f:
        l = [*line]
        l.pop()
        binaryTable.append(l)

def rating(table, i, type):
    bitAtIndex = []
    output = []
    for j in table:
        bitAtIndex.append(j[i])

    for j in table:
        if type == "oxygen":
            if bitAtIndex.count("1") >= bitAtIndex.count("0"):
                if j[i] == "1":
                    output.append(j)
            else :
                if j[i] == "0":
                    output.append(j)
        if type == "co2":
            if bitAtIndex.count("1") < bitAtIndex.count("0"):
                if j[i] == "1":
                    output.append(j)
            else :
                if j[i] == "0":
                    output.append(j)

    if (len(output) == 1 or i == len(table[0])):
        return "".join(output[0])
    else:
        return rating(output, i + 1, type)

gamma = ""
epsilon = ""
for i in range(len(binaryTable[0])):
    bitAtIndex = []
    for j in binaryTable:
        bitAtIndex.append(j[i])
    if bitAtIndex.count("1") > bitAtIndex.count("0"):
        gamma += "1"
        epsilon += "0"
    else :
        gamma += "0"
        epsilon += "1"
print("consumption:", int(gamma, 2) * int(epsilon, 2))

oxygen = rating(binaryTable, 0, "oxygen")
co2 = rating(binaryTable, 0, "co2")

print("life support:", int(oxygen, 2) * int(co2, 2))


from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
import PyPDF2
import os

files=Tk()
files.title('Easy Files')
files.geometry(f'400x600')
files.resizable(False,False)
# Add a frame to set the size of the window
frame= Frame(files, relief= 'sunken')
frame.pack(fill= BOTH, expand= True, padx= 10, pady=0)

def browseFiles():
    global filename
    filename = filedialog.askopenfilename(initialdir="/",
                                          title="Select a File",
                                          filetypes=(("Pdf files",
                                                      "*.pdf*"),
                                                     ("all files",
                                                      "*.*")))
    label_file_explorer.config(text=os.path.split(filename)[1])

def convert_pdf():
    global filename
    global name
    name = name_entry.get()
    start=int(Entry2.get())
    end=int(Entry3.get())
    with open(filename, mode='rb') as f:
        reader = PyPDF2.PdfFileReader(f)
        doc_path = os.path.expanduser("~\Desktop") +'\\'+ name + '.doc'
        print(doc_path)
        # Open a file with access mode 'a'
        file_object = open(doc_path, 'a')
        for i in range(start-1,end):
            page = reader.getPage(i)
            # Append page content at the end of file
            file_object.write(page.extractText())
            # Close the file
        file_object.close()

        return messagebox.showinfo('Success', f'File saved in desktop as {name}.doc')

        #Print success
        label_success.pack()

#Create heading
label = Label(
    frame,
    font = "Helvetica 40 bold",
    foreground = "grey", text = "Welcome")
label.pack(pady=30)

#Create a File Explorer button
button1 = Button(frame, text="Browse file", command=browseFiles)
button1.pack(pady=1)

# Create a File Explorer label
label_file_explorer = Label(frame,
                            text="Upload pdf",
                            width=100, height=4,
                            fg="grey")
label_file_explorer.pack(pady=1)

#Frame 2
frame2=Frame(files)
frame2.pack(fill= BOTH, expand= True, padx= 10, pady=0)
#Page Range
Label2 = Label(frame2,width=25)
Label2.configure(text='''                           Enter page range ''')
Label2.grid(row=0,column=0)

Entry2 = Entry(frame2,width=3)
Entry2.grid(row=0,column=1)

Entry3 = Entry(frame2,width=3)
Entry3.grid(row=0,column=3)

Label3 = Label(frame2)
Label3.configure(text='''-''')
Label3.grid(row=0,column=2)

#Frame3
frame3=Frame(files)
frame3.pack(fill= BOTH, expand= True, padx= 10, pady=0)
#Enter name of new file
name_label = Label(frame3, text = 'New file name', font=('calibre',10, 'bold'))
name_label.pack()
name_entry = Entry(frame3, font=('calibre',10,'normal'))
name_entry.pack()

#Create a File Converter button
button2 = Button(frame3, text="Convert File",height=5,bg='grey',fg='white', command= convert_pdf)
button2.pack(pady=50)

# Create a Message label
label_success = Label(frame3,
                            text='Success!!',
                            fg='green',
                            font=("Arial", 15),
                            width=100, height=4)

#   close window after 3 seconds
#files.after(3000, lambda: files.destroy())

files.mainloop()


import sys
from collections import deque
input = sys.stdin.readline
# bfs와 이분탐색 활용문제
# 처음에는 다리무게를 활용하여 도착지에 갈 수 있는 최소 무게를 탐색
# 나중에는 이분탐색을 활용해 도달할 수 있는 무게의 최대값을 탐색

def bfs(w):
    q = deque()
    q.append(S)
    visited = [0] * (N+1)
    visited[S] = 1
    while q:
        A = q.popleft()
        for B, C in G[A]:
            if not visited[B] and w <= C:
                visited[B] = 1
                q.append(B)
    if visited[E]:
        return True
    return False

N, M = map(int, input().split())
G = [[] for _ in range(N+1)]
for _ in range(M):
    A, B, C = map(int, input().split())
    G[A].append((B, C))
    G[B].append((A, C))
S, E = map(int, input().split())
minW = 1
maxW = 1000000000
ans = 0
while minW <= maxW:
    midW = (maxW + minW) // 2
    if bfs(midW):
        ans = midW
        minW = midW + 1
    else:
        maxW = midW - 1
print(ans)


def nodeDepthsRecursive(root, depth = 0):
	if root is None:
		return 0
	return depth + nodeDepthsRecursive(root.left, depth + 1) + nodeDepthsRecursive(root.right, depth + 1)

def nodeDepthsIterative(root):
    # Write your code here.
	answer = 0
	stack = [{"node": root, "depth": 0}]
	while len(stack) > 0:
		temp = stack.pop()
		node, depth = temp["node"], temp["depth"]
		if node is None:
			continue
		answer += depth
		stack.append({"node": node.left, "depth": depth+1})
		stack.append({"node": node.right, "depth": depth+1})
	return answer

# This is the class of the input binary tree.
class BinaryTree:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None