#!/usr/bin/env python2

from indices import WORD_INDEX

from apollocaffe.layers import *
from corpus import Scene, Bird # "Scene" and "Bird" refer to namedtuple data, e.g., `` Scene = namedtuple("Scene", ["image_id", "props", "description", "features"]) ´´
                               # Using "Scene" and "Bird" allows to distinguish data without the need for storing it in separate classes.
import numpy as np
from scipy.misc import logsumexp

N_PROP_TYPES = 8
N_PROP_OBJECTS = 35

class EuclideanScorer(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, l_query, ll_targets, labels):
        net = self.apollo_net

        batch_size, n_dims = net.blobs[l_query].shape
        n_targets = len(ll_targets)

        l_cat = "EuclideanScorer_%s_%s_cat" % (self.name, prefix)
        l_inv_query = "EuclideanScorer_%s_%s_inv_query" % (self.name, prefix)
        l_tile_query = "EuclideanScorer_%s_%s_tile_query" % (self.name, prefix)
        l_add_query = "EuclideanScorer_%s_%s_add_query" % (self.name, prefix)
        l_sq = "EuclideanScorer_%s_%s_sq" % (self.name, prefix)
        l_neg = "EuclideanScorer_%s_%s_neg" % (self.name, prefix)
        l_reduce = "EuclideanScorer_%s_%s_reduce" % (self.name, prefix)
        l_label = "EuclideanScorer_%s_%s_target" % (self.name, prefix)
        l_loss = "EuclideanScorer_%s_%s_loss" % (self.name, prefix)

        p_reduce = ["EuclideanScorer_reduce_weight",
                    "EuclideanScorer_reduce_bias"]

        for l_target in ll_targets:
            net.blobs[l_target].reshape((batch_size, n_dims, 1, 1))
        net.f(Concat(l_cat, axis=2, bottoms=ll_targets))
        net.f(Power(l_inv_query, scale=-1, bottoms=[l_query]))
        net.blobs[l_inv_query].reshape((batch_size, n_dims, 1, 1))
        net.f(Tile(l_tile_query, tiles=n_targets, axis=2, bottoms=[l_inv_query]))
        net.f(Eltwise(l_add_query, "SUM", bottoms=[l_tile_query, l_cat]))
        net.f(Power(l_sq, power=2, bottoms=[l_add_query]))
        net.f(Power(l_neg, scale=-1, bottoms=[l_sq]))
        net.f(Convolution(
            l_reduce, (1,1), 1, bottoms=[l_neg], param_names=p_reduce,
            param_lr_mults=[0,0], weight_filler=Filler("constant", 1),
            bias_filler=Filler("constant", 0)))
        net.blobs[l_reduce].reshape((batch_size, n_targets))
        net.f(NumpyData(l_label, labels))
        loss = net.f(SoftmaxWithLoss(l_loss, bottoms=[l_reduce, l_label]))
        denominators = logsumexp(net.blobs[l_reduce].data, axis=1)
        chosen_logprobs = net.blobs[l_reduce].data[range(batch_size), labels.astype(int)]
        chosen_logprobs -= denominators

        predictions = np.argmax(net.blobs[l_reduce].data, axis=1)
        acc = np.mean(predictions==labels)
        accs = predictions == labels

        return chosen_logprobs, accs

# Choice ranker R
#   The choice ranker takes a string encoding and a collection of referent encodings,
#   assigns a score to each (string, referent) pair, and then transforms these scores
#   into a distribution over referents.
class MlpScorer(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    #                         v--Corresponds to ``l_string_enc´´ in the caller.
    #                         v        v--Corresponds to ``ll_scenes´´ in the caller.
    #                         v        v           v--Array of zeros.
    def forward(self, prefix, l_query, ll_targets, labels):
        """
            l_query: Embedding of a description (i.e., caption) of shape torch.Size([100, 100])
            ll_targets: Embedding of Scenes (target and distractor). It is a list of tensors 2 tensors each of shape torch.Size([100, 100])
            prefix : Not used --> Passed to forward() only with an empty string.
        """
        net = self.apollo_net

        batch_size, n_dims = net.blobs[l_query].shape
        n_targets = len(ll_targets)

        l_cat = "MlpScorer_%s_%s_cat" % (self.name, prefix)
        l_tile_query = "MlpScorer_%s_%s_tile_query" % (self.name, prefix)
        l_sum = "MlpScorer_%s_%s_sum" % (self.name, prefix)
        l_relu = "MlpScorer_%s_%s_relu" % (self.name, prefix)
        l_ip = "MlpScorer_%s_%s_ip" % (self.name, prefix)
        l_label = "MlpScorer_%s_%s_label" % (self.name, prefix)
        l_loss = "MlpScorer_%s_%s_loss" % (self.name, prefix)

        p_ip = ["MlpScorer_%s_weight", "MlpScorer_%s_bias"]

        for l_target in ll_targets:
            net.blobs[l_target].reshape((batch_size, 1, n_dims))
        net.blobs[l_query].reshape((batch_size, 1, n_dims))
        net.f(Concat(l_cat, axis=1, bottoms=ll_targets)) # Put target and distractor scene ("referent") in same blob. Assumption: Horizontal concatenation.
        net.f(Tile(l_tile_query, tiles=n_targets, axis=1, bottoms=[l_query])) # Make the shape of the description embedding match the shape of the scenes embedding.
        net.f(Eltwise(l_sum, "SUM", bottoms=[l_tile_query, l_cat]))
        net.f(ReLU(l_relu, bottoms=[l_sum]))
        net.f(InnerProduct(l_ip, 1, bottoms=[l_relu], axis=2, param_names=p_ip)) # l_ip -> Inner Product.
        net.blobs[l_ip].reshape((batch_size, n_targets))
        net.f(NumpyData(l_label, labels))    #              v--Row vector with all values 0.
        loss = net.f(SoftmaxWithLoss(l_loss, bottoms=[l_ip, l_label]))

        denominators = logsumexp(net.blobs[l_ip].data, axis=1) # Denominator of equation (3).
        chosen_logprobs = net.blobs[l_ip].data[range(batch_size), labels.astype(int)]
        chosen_logprobs -= denominators

        predictions = np.argmax(net.blobs[l_ip].data, axis=1)
        accs = predictions == labels

        return chosen_logprobs, accs

# Referent encoder (section 3.2)
class LinearSceneEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        # What type of data do we have? Is it abstract scenes...?
        if isinstance(scenes[0], Scene):
            feature_data = np.zeros((len(scenes), N_PROP_TYPES * N_PROP_OBJECTS)) # For the final evaluation, this was an array of size ``100 x 280´´ (c.f.: section 4.4).
            #                                                                       Because 100 samples were used.
            for i_scene, scene in enumerate(scenes):
                for prop in scene.props:
                    #            v--0..99 v-- 0..7 (sky object s ... toy object t) v--35            v--specifies the exact object (=png image) of the given type.
                    feature_data[i_scene, prop.type_index *                        N_PROP_OBJECTS + prop.object_index] = 1
                    # INTERPRETATION:
                    #   The number of ones ``1´´ corresponds to the number of features used. The position of the ones ``1´´ corresponds to which exact feature (i.e., png-feature image) was used.
                    #   Thus, EACH scene or referent is represented as 1x280 row vector.  This IS the feature representation f(r) --> c.f. section 3.1 in the paper.
        else:
            # ...or rather birds?
            assert isinstance(scenes[0], Bird)
            feature_data = np.zeros((len(scenes), len(scenes[0].features)))
            for i_scene, scene in enumerate(scenes):
                feature_data[i_scene, :] = scenes[i_scene].features # "features" == feature representation f(r) of one referent (i.e., of one image).
                                                                    # --> Set during load_scenes() in corpus.py

        l_data = "LinearSceneEncoder%s_%s_data" % (self.name, prefix)
        l_drop = "LinearSceneEncoder%s_%s_drop" % (self.name, prefix)
        l_ip1 = "LinearSceneEncoder%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "LinearSceneEncoder%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "LinearSceneEncoder%s_%s_ip2" % (self.name, prefix)

        p_ip1 = ["LinearSceneEncoder%s_ip1_weight" % self.name,
                 "LinearSceneEncoder%s_ip1_bias" % self.name]
        p_ip2 = ["LinearSceneEncoder%s_ip2_weight" % self.name,
                 "LinearSceneEncoder%s_ip2_bias" % self.name]

        #               v-- name (passes a string as label)
        #               v       v-- the actual data
        net.f(NumpyData(l_data, feature_data))
        # ``InnerProduct´´ is a fully connected layer. ``nn.Linear´´ is the PyTorch equivalent. The following command creates the referent encoding E_r --> c.f. equation (1) in section 3.2
        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_data], # ``bottoms´´ is the input data to this layer.
                param_names=p_ip1))

        return l_ip1

# Description encoder (section 3.2)
class LinearStringEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        """
            scenes : Description, i.e., sentence, to be encoded.
        """
        net = self.apollo_net

        # For the final experiment, ``feature_data´´ takes the following format: 100 x 1063.
        #                        v--100     , v--1063
        feature_data = np.zeros((len(scenes), len(WORD_INDEX)))
        for i_scene, scene in enumerate(scenes):
            for word in scene.description:          # "description" attribute comes from the "Scenes" namedtuple from corpus.py
                feature_data[i_scene, word] += 1    # ``feature_data´´ contains integer numbers >= 0 (i.e., 0, 1, 2, ...)

        l_data = "LinearStringEncoder_%s_%s_data" % (self.name, prefix)
        l_ip = "LinearStringEncoder_%s_%s_ip" % (self.name, prefix)

        p_ip = ["LinearStringEncoder_%s_ip_weight" % self.name,
                "LinearStringEncoder_%s_ip_bias" % self.name]

        net.f(NumpyData(l_data, feature_data))
        net.f(InnerProduct(
                l_ip, self.config.hidden_size, bottoms=[l_data],
                param_names=p_ip))

        return l_ip

class BowSceneEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        max_props = max(len(scene.props) for scene in scenes)
        type_data = np.zeros((len(scenes), max_props))
        object_data = np.zeros((len(scenes), max_props))
        feature_data = np.zeros((len(scenes), max_props, 4))
        for i_scene, scene in enumerate(scenes):
            offset = max_props - len(scene.props)
            for i_prop, prop in enumerate(scene.props):
                type_data[i_scene, offset+i_prop] = prop.type_index
                object_data[i_scene, offset+i_prop] = prop.object_index
                feature_data[i_scene, offset+i_prop, :] = \
                        [prop.x, prop.y, prop.z, prop.flip]

        l_type = "BowSceneEncoder_%s_%s_type_%d"
        l_object = "BowSceneEncoder_%s_%s_object_%d"
        l_feature = "BowSceneEncoder_%s_%s_feature_%d"
        l_type_vec = "BowSceneEncoder_%s_%s_type_vec_%d"
        l_object_vec = "BowSceneEncoder_%s_%s_object_vec_%d"
        l_prop = "BowSceneEncoder_%s_%s_prop_%d"
        l_all_props = "BowSceneEncoder_%s_%s_all_props" % (self.name, prefix)
        l_drop = "BowSceneEncoder_%s_%s_drop" % (self.name, prefix)
        l_ip1 = "BowSceneEncoder_%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "BowSceneEncoder_%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "BowSceneEncoder_%s_%s_ip2" % (self.name, prefix)

        p_type_vec = ["BowSceneEncoder_%s_type_vec" % self.name]
        p_object_vec = ["BowSceneEncoder_%s_object_vec" % self.name]
        p_ip1 = ["BowSceneEncoder_%s_ip1_weight" % self.name,
                 "BowSceneEncoder_%s_ip1_bias" % self.name]
        p_ip2 = ["BowSceneEncoder_%s_ip2_weight" % self.name,
                 "BowSceneEncoder_%s_ip2_bias" % self.name]

        for i_step in range(max_props):
            l_type_i = l_type % (self.name, prefix, i_step)
            l_object_i = l_object % (self.name, prefix, i_step)
            l_feature_i = l_feature % (self.name, prefix, i_step)
            l_type_vec_i = l_type_vec % (self.name, prefix, i_step)
            l_object_vec_i = l_object_vec % (self.name, prefix, i_step)
            l_prop_i = l_prop % (self.name, prefix, i_step)

            net.f(NumpyData(l_type_i, type_data[:, i_step]))
            net.f(NumpyData(l_object_i, object_data[:, i_step]))
            net.f(NumpyData(l_feature_i, feature_data[:, i_step]))
            net.f(Wordvec(
                    l_type_vec_i, self.config.prop_embedding_size, N_PROP_TYPES,
                    bottoms=[l_type_i], param_names=p_type_vec))
            net.f(Wordvec(
                    l_object_vec_i, self.config.prop_embedding_size, N_PROP_OBJECTS,
                    bottoms=[l_object_i], param_names=p_object_vec))
            net.f(Concat(
                    l_prop_i,
                    bottoms=[l_type_vec_i, l_object_vec_i, l_feature_i]))

        net.f(Eltwise(
                l_all_props, "SUM",
                bottoms=[l_prop % (self.name, prefix, i_step)
                         for i_step in range(max_props)]))
        if dropout:
            net.f(Dropout(l_drop, 0.5, bottoms=[l_all_props]))
            l_p = l_drop
        else:
            l_p = l_all_props

        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_p],
                param_names=p_ip1))

        return l_ip1

class BowStringEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        word_data = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes):
            offset = max_words - len(scene.description)
            for i_word, word in enumerate(scene.description):
                word_data[i_scene, offset+i_word] = word

        l_word = "BowStringEncoder_%s_%s_word_%d"
        l_word_vec = "BowStringEncoder_%s_%s_word_vec_%d"
        l_all_words = "BowStringEncoder_%s_%s_all_words" % (self.name, prefix)
        l_drop = "BowStringEncoder_%s_%s_drop" % (self.name, prefix)
        l_ip1 = "BowStringEncoder_%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "BowStringEncoder_%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "BowStringEncoder_%s_%s_ip2" % (self.name, prefix)

        p_word_vec = ["BowStringEncoder_%s_word_vec" % self.name]
        p_ip1 = ["BowStringEncoder_%s_ip1_weight" % self.name,
                 "BowStringEncoder_%s_ip1_param" % self.name]
        p_ip2 = ["BowStringEncoder_%s_ip2_weight" % self.name,
                 "BowStringEncoder_%s_ip2_param" % self.name]

        for i_step in range(max_words):
            l_word_i = l_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)

            net.f(NumpyData(l_word_i, word_data[:, i_step]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_word_i], param_names=p_word_vec))

        net.f(Eltwise(
                l_all_words, "MAX",
                bottoms=[l_word_vec % (self.name, prefix, i_step)
                         for i_step in range(max_words)]))

        if dropout:
            net.f(Dropout(l_drop, 0.5, bottoms=[l_all_words]))
            l_r = l_drop
        else:
            l_r = l_all_words

        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_r],
                param_names=p_ip1))
        net.f(ReLU(l_relu1, bottoms=[l_ip1]))
        net.f(InnerProduct(
                l_ip2, self.config.hidden_size, bottoms=[l_relu1],
                param_names=p_ip2))

        return l_ip2

# The referent describer D takes an image encoding and outputs a description using a (feedforward) conditional neural language model.
class MlpStringDecoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, encoding, scenes, dropout):
        """
        encoding: Is the linear embedding tensor of the targets ``scenes´´ (equation (1)).
        scenes  : Target scenes.
        """
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        history_features = np.zeros((len(scenes), max_words, len(WORD_INDEX)))
        last_features = np.zeros((len(scenes), max_words, len(WORD_INDEX)))
        targets = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes): # For each scene, parse its description and...
            #                             v--Example: description=[1, 2, 248, 11, 295, 14]
            for i_word, word in enumerate(scene.description): # ...for every single word within the description...
                if word == 0:
                    continue #       v--Starting position always changes (by one index ahead).
                for ii_word in range(i_word + 1, len(scene.description)): #...look at vocabulary index of the words starting from the second till last position.
                #                                                          That is, we look at progressively smaller parts of the description as the index ii_word...
                #                                                          keeps moving further and further towards the right boundary of the description.
                    history_features[i_scene, ii_word, word] += 1
                last_features[i_scene, i_word, word] += 1
                targets[i_scene, i_word] = word

        l_history_data = "MlpStringDecoder_%s_%s_history_data_%d"
        l_last_data = "MlpStringDecoder_%s_%s_last_data_%d"
        l_cat_features = "MlpStringDecoder_%s_%s_cat_features_%d"
        l_ip1 = "MlpStringDecoder_%s_%s_ip1_%d"
        l_cat = "MlpStringDecoder_%s_%s_cat_%d"
        l_relu1 = "MlpStringDecoder_%s_%s_relu1_%d"
        l_ip2 = "MlpStringDecoder_%s_%s_ip2_%d"
        l_target = "MlpStringDecoder_%s_%s_target_%d"
        l_loss = "MlpStringDecoder_%s_%s_loss_%d"

        p_ip1 = ["MlpStringDecoder_%s_ip1_weight" % self.name,
                 "MlpStringDecoder_%s_ip1_bias" % self.name]
        p_ip2 = ["MlpStringDecoder_%s_ip2_weight" % self.name,
                 "MlpStringDecoder_%s_ip2_bias" % self.name]

        loss = 0
        for i_step in range(1, max_words):
            l_history_data_i = l_history_data % (self.name, prefix, i_step)
            l_last_data_i = l_last_data % (self.name, prefix, i_step)
            l_cat_features_i = l_cat_features % (self.name, prefix, i_step)
            l_ip1_i = l_ip1 % (self.name, prefix, i_step)
            l_cat_i = l_cat % (self.name, prefix, i_step)
            l_relu1_i = l_relu1 % (self.name, prefix, i_step)
            l_ip2_i = l_ip2 % (self.name, prefix, i_step)
            l_target_i = l_target % (self.name, prefix, i_step)
            l_loss_i = l_loss % (self.name, prefix, i_step)

            net.f(NumpyData(l_history_data_i, history_features[:,i_step-1,:]))
            net.f(NumpyData(l_last_data_i, last_features[:,i_step-1,:]))
            net.f(Concat(l_cat_features_i, bottoms=[l_history_data_i, l_last_data_i]))
            net.f(InnerProduct(l_ip1_i, self.config.hidden_size, bottoms=[l_cat_features_i], param_names=p_ip1)) # (W7 @ [dn, d<n, ei])
            net.f(Concat(l_cat_i, bottoms=[l_ip1_i, encoding])) # Taking the referent embedding of the target scene into account.
            net.f(ReLU(l_relu1_i, bottoms=[l_cat_i]))
            net.f(InnerProduct(l_ip2_i, len(WORD_INDEX), bottoms=[l_relu1_i],param_names=p_ip2))                 # W6 @ ReLU(...)
            net.f(NumpyData(l_target_i, targets[:,i_step]))     # This is the target...
            loss += net.f(SoftmaxWithLoss(                      # ...here, the loss of the prediction vs. target is computed!
                l_loss_i, bottoms=[l_ip2_i, l_target_i],
                ignore_label=0, normalize=False))

        return -np.asarray(loss)

    """
    Draws a sequence of words, i.e., samples d_1, ..., d_n ~ p_S0(.|r_i)

    Remark: The paper does not specify, how the sampling actually works.
            This seems to be an "implementational detail".
    """
    def sample(self, prefix, encoding, viterbi):
        """
        encoding: Encoding of abstract scene image, i.e., referent encoding.
        viterbi : Decoding scheme:
                    ``False´´ corresponds to greedy sampling: Randomly sample index of one word from the vocabulary.
                    ``True´´ corresponds to pure sampling (non-deterministic; truly random).
                    Note: Set to False in the pragmatic speaker S1 (SamplingSpeaker1).
        """
        net = self.apollo_net

        max_words = 20
        batch_size = net.blobs[encoding].shape[0]

        out_logprobs = np.zeros((batch_size,))
        samples = np.zeros((batch_size, max_words))
        history_features = np.zeros((batch_size, len(WORD_INDEX)))
        last_features = np.zeros((batch_size, len(WORD_INDEX)))
        samples[:,0] = WORD_INDEX["<s>"]
        last_features[:,WORD_INDEX["<s>"]] += 1

        l_history_data = "MlpStringDecoder_%s_%s_history_data_%d"
        l_last_data = "MlpStringDecoder_%s_%s_last_data_%d"
        l_cat_features = "MlpStringDecoder_%s_%s_cat_features_%d"
        l_ip1 = "MlpStringDecoder_%s_%s_ip1_%d"
        l_cat = "MlpStringDecoder_%s_%s_cat_%d"
        l_relu1 = "MlpStringDecoder_%s_%s_relu1_%d"
        l_ip2 = "MlpStringDecoder_%s_%s_ip2_%d"
        l_softmax = "MlpStringDecoder_%s_%s_softmax_%d"

        p_ip1 = ["MlpStringDecoder_%s_ip1_weight" % self.name,
                 "MlpStringDecoder_%s_ip1_bias" % self.name]
        p_ip2 = ["MlpStringDecoder_%s_ip2_weight" % self.name,
                 "MlpStringDecoder_%s_ip2_bias" % self.name]

        # Compute sampling distribution p_S0:
        for i_step in range(1, max_words):
            l_history_data_i = l_history_data % (self.name, prefix, i_step)
            l_last_data_i = l_last_data % (self.name, prefix, i_step)
            l_cat_features_i = l_cat_features % (self.name, prefix, i_step)
            l_ip1_i = l_ip1 % (self.name, prefix, i_step)
            l_cat_i = l_cat % (self.name, prefix, i_step)
            l_relu1_i = l_relu1 % (self.name, prefix, i_step)
            l_ip2_i = l_ip2 % (self.name, prefix, i_step)
            l_softmax_i = l_softmax % (self.name, prefix, i_step)

            net.f(DummyData(l_history_data_i, (1,1,1,1))) # Initialise tensor with random values.
            net.blobs[l_history_data_i].reshape(history_features.shape)
            net.f(DummyData(l_last_data_i, (1,1,1,1)))    # Initialise tensor with random values.
            net.blobs[l_last_data_i].reshape(last_features.shape)
            net.blobs[l_history_data_i].data[...] = history_features
            net.blobs[l_last_data_i].data[...] = last_features
            net.f(Concat(l_cat_features_i, bottoms=[l_history_data_i, l_last_data_i]))
            net.f(InnerProduct(
                l_ip1_i, self.config.hidden_size, bottoms=[l_cat_features_i],
                param_names=p_ip1))
            net.f(Concat(l_cat_i, bottoms=[l_ip1_i, encoding]))
            net.f(ReLU(l_relu1_i, bottoms=[l_cat_i]))
            net.f(InnerProduct(
                l_ip2_i, len(WORD_INDEX), bottoms=[l_relu1_i],
                param_names=p_ip2))
            net.f(Softmax(l_softmax_i, bottoms=[l_ip2_i]))

            # Draw samples (i.e., words d_i) from probability distribution p_S0:
            probs = net.blobs[l_softmax_i].data
            history_features += last_features
            last_features[...] = 0
            for i_datum in range(batch_size):
                d_probs = probs[i_datum,:].astype(float)
                d_probs /= d_probs.sum()
                if viterbi:
                    choice = d_probs.argmax() # Find index of largest word-probability.
                else:
                    choice = np.random.multinomial(1, d_probs).argmax() # Randomly draw one sample, i.e., get the index of one single word from the vocabulary.
                samples[i_datum, i_step] = choice
                last_features[i_datum, choice] += 1
                out_logprobs[i_datum] += np.log(d_probs[choice])

        # This creates a candidate caption / sentence / description of the image e_r.
        out_samples = []
        for i in range(samples.shape[0]):
            this_sample = []
            for j in range(samples.shape[1]):
                word = WORD_INDEX.get(samples[i,j])
                #this_sample.append(word)
                this_sample.append(samples[i,j])
                if word == "</s>":
                    break
            if this_sample[-1] != WORD_INDEX["</s>"]:
                this_sample.append(WORD_INDEX["</s>"])
            out_samples.append(this_sample)
        return out_logprobs, out_samples

class LstmStringDecoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, encoding, scenes, dropout):
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        word_data = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes):
            offset = max_words - len(scene.description)
            for i_word, word in enumerate(scene.description):
                #word_data[i_scene, offset+i_word] = word
                word_data[i_scene, i_word] = word

        l_seed = "LstmStringDecoder_%s_%s_seed" % (self.name, prefix)
        l_prev_word = "LstmStringDecoder_%s_%s_word_%d"
        l_word_vec = "LstmStringDecoder_%s_%s_word_vec_%d"
        l_drop_in = "LstmStringDecoder_%s_%s_drop_in_%d"
        l_concat = "LstmStringDecoder_%s_%s_concat_%d"
        l_lstm = "LstmStringDecoder_%s_%s_lstm_%d"
        l_hidden = "LstmStringDecoder_%s_%s_hidden_%d"
        l_mem = "LstmStringDecoder_%s_%s_mem_%d"
        l_drop_out = "LstmStringDecoder_%s_%s_drop_out_%d"
        l_output = "LstmStringDecoder_%s_%s_output_%d"
        l_target = "LstmStringDecoder_%s_%s_target_%d"
        l_loss = "LstmStringDecoder_%s_%s_loss_%d"

        p_word_vec = ["LstmStringDecoder_%s_word_vec" % self.name]
        p_lstm = ["LstmStringDecoder_%s_lstm_iv" % self.name,
                  "LstmStringDecoder_%s_lstm_ig" % self.name,
                  "LstmStringDecoder_%s_lstm_fg" % self.name,
                  "LstmStringDecoder_%s_lstm_og" % self.name]
        p_output = ["LstmStringDecoder_%s_output_weight" % self.name,
                    "LstmStringDecoder_%s_output_bias" % self.name]

        loss = 0
        net.f(NumpyData(
                l_seed, np.zeros((len(scenes), self.config.hidden_size))))
        for i_step in range(1, max_words):
            l_prev_word_i = l_prev_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)
            l_drop_in_i = l_drop_in % (self.name, prefix, i_step)
            l_concat_i = l_concat % (self.name, prefix, i_step)
            l_lstm_i = l_lstm % (self.name, prefix, i_step)
            l_hidden_i = l_hidden % (self.name, prefix, i_step)
            l_mem_i = l_mem % (self.name, prefix, i_step)
            l_drop_out_i = l_drop_out % (self.name, prefix, i_step)
            l_output_i = l_output % (self.name, prefix, i_step)
            l_target_i = l_target % (self.name, prefix, i_step)
            l_loss_i = l_loss % (self.name, prefix, i_step)

            if i_step == 1:
                prev_hidden = l_seed
                prev_mem = l_seed
            else:
                prev_hidden = l_hidden % (self.name, prefix, i_step - 1)
                prev_mem = l_mem % (self.name, prefix, i_step - 1)

            net.f(NumpyData(l_prev_word_i, word_data[:, i_step-1]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_prev_word_i],
                    param_names=p_word_vec))
            #if dropout:
            #    net.f(Dropout(l_drop_in_i, 0.5, bottoms=[l_word_vec_i]))
            #    l_wv = l_drop_in_i
            #else:
            #    l_wv = l_word_vec_i
            net.f(Concat(l_concat_i, bottoms=[prev_hidden, l_word_vec_i, encoding]))
            net.f(LstmUnit(
                    l_lstm_i, bottoms=[l_concat_i, prev_mem],
                    param_names=p_lstm, tops=[l_hidden_i, l_mem_i],
                    num_cells=self.config.hidden_size))
            net.f(NumpyData(l_target_i, word_data[:, i_step]))
            #if dropout:
            #    net.f(Dropout(l_drop_out_i, 0.5, bottoms=[l_hidden_i]))
            #    l_h = l_drop_out_i
            #else:
            #    l_h = l_hidden_i
            net.f(InnerProduct(
                    l_output_i, len(WORD_INDEX), bottoms=[l_hidden_i],
                    param_names=p_output))
            loss += net.f(SoftmaxWithLoss(
                    #l_loss_i, bottoms=[l_output_i, l_target_i]))
                    l_loss_i, ignore_label=0, bottoms=[l_output_i, l_target_i]))

        return np.asarray(loss)

    # TODO consolidate
    def sample(self, prefix, encoding, viterbi):
        net = self.apollo_net

        batch_size = net.blobs[encoding].shape[0]
        max_words = 20

        l_seed = "LstmStringDecoder_%s_%s_seed"
        l_prev_word = "LstmStringDecoder_%s_%s_word_%d"
        l_word_vec = "LstmStringDecoder_%s_%s_word_vec_%d"
        l_concat = "LstmStringDecoder_%s_%s_concat_%d"
        l_lstm = "LstmStringDecoder_%s_%s_lstm_%d"
        l_hidden = "LstmStringDecoder_%s_%s_hidden_%d"
        l_mem = "LstmStringDecoder_%s_%s_mem_%d"
        l_output = "LstmStringDecoder_%s_%s_output_%d"
        l_softmax = "LstmStringDecoder_%s_%s_softmax_%d"

        p_word_vec = ["LstmStringDecoder_%s_word_vec" % self.name]
        p_lstm = ["LstmStringDecoder_%s_lstm_iv" % self.name,
                  "LstmStringDecoder_%s_lstm_ig" % self.name,
                  "LstmStringDecoder_%s_lstm_fg" % self.name,
                  "LstmStringDecoder_%s_lstm_og" % self.name]
        p_output = ["LstmStringDecoder_%s_output_weight" % self.name,
                    "LstmStringDecoder_%s_output_bias" % self.name]

        samples = np.zeros((batch_size, max_words), dtype=int)
        samples[:,0] = WORD_INDEX["<s>"]

        net.f(NumpyData(
                l_seed, np.zeros((batch_size, self.config.hidden_size))))
        for i_step in range(1, max_words):
            l_prev_word_i = l_prev_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)
            l_concat_i = l_concat % (self.name, prefix, i_step)
            l_lstm_i = l_lstm % (self.name, prefix, i_step)
            l_hidden_i = l_hidden % (self.name, prefix, i_step)
            l_mem_i = l_mem % (self.name, prefix, i_step)
            l_output_i = l_output % (self.name, prefix, i_step)
            l_softmax_i = l_softmax % (self.name, prefix, i_step)

            if i_step == 1:
                prev_hidden = l_seed
                prev_mem = l_seed
            else:
                prev_hidden = l_hidden % (self.name, prefix, i_step - 1)
                prev_mem = l_mem % (self.name, prefix, i_step - 1)

            net.f(NumpyData(l_prev_word_i, samples[:, i_step-1]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_prev_word_i],
                    param_names=p_word_vec))
            net.f(Concat(
                    l_concat_i, bottoms=[prev_hidden, l_word_vec_i, encoding]))
            net.f(LstmUnit(
                    l_lstm_i, bottoms=[l_concat_i, prev_mem],
                    param_names=p_lstm, tops=[l_hidden_i, l_mem_i],
                    num_cells=self.config.hidden_size))
            net.f(InnerProduct(
                    l_output_i, len(WORD_INDEX), bottoms=[l_hidden_i],
                    param_names=p_output))
            net.f(Softmax(l_softmax_i, bottoms=[l_output_i]))

            choices = []
            for i in range(batch_size):
                probs = net.blobs[l_softmax_i].data[i,:].astype(np.float64)
                probs /= probs.sum()
                if viterbi:
                    choices.append(np.argmax(probs))
                else:
                    choices.append(np.random.choice(len(WORD_INDEX), p=probs))
            samples[:, i_step] = choices

        out_samples = []
        for i in range(samples.shape[0]):
            this_sample = []
            for j in range(samples.shape[1]):
                word = WORD_INDEX.get(samples[i,j])
                this_sample.append(samples[i,j])
                if word == "</s>":
                    break
            out_samples.append(this_sample)
        return out_samples


from scrapy.spiders import CrawlSpider
from scrapy.selector import HtmlXPathSelector
from scrapy import Request

from varys.items import VarysItem
from varys.src.urlParser import Parser

class CrawlSpider(CrawlSpider):
    name = "varys"
    allowed_domains = ["amazon.co.uk"]
    start_urls = (
        'https://www.amazon.co.uk/',
    )

    def parse(self, response):
      for newRequest in self.newRequests(response):
          yield newRequest
      for newItem in self.newItems(response):
          yield newItem

    def newRequests(self, response):
      array = []
      for link in response.xpath('//a/@href').extract():
        parsed = Parser(link).joinDomain(response.url)
        if (parsed.approved):
          array.append( Request(parsed.fullUrl(), callback=self.parse) )
      return array

    def newItems(self, response):
      array = []
      item = VarysItem()
      item["link"] = response.url
      item["title"] = response.xpath("//title/text()").extract()
      item["description"] = response.xpath("/html/head/meta[@name='description']/@content").extract()
      array.append(item)
      return array


from django.http import HttpResponse, JsonResponse
from django.contrib.auth import get_user_model
from django.db.models import Sum
from django.shortcuts import render, redirect
from django.utils import timezone
import re
from .models import *
from users.models import Subscriber, Moderator
from posts.models import *

def index(request, subreddit_title):

    try:
        subreddit = Subreddit.objects.get(title=subreddit_title)
    except:
        return HttpResponse("Subreddit Does Not Exist")

    num_subscribers = subscribersCount(subreddit)
    moderators = getModerators(subreddit)
    ismoderator = request.user in moderators or request.user.is_staff
    assignedmod = request.user in moderators
    if request.user.is_authenticated():
        subscribed = checkSubscribed(request.user, subreddit)
        posts = feed(subreddit, request.user)
        events = getEvents(subreddit, request.user)
    else:
        posts = feed(subreddit)
        events = getEvents(subreddit)
        subscribed = False

    return render(request, "subreddit.html", {"subreddit" : subreddit, "posts" : posts,
                                              "num_subscribers" : num_subscribers, "subscribed" : subscribed,
                                              "moderators" : moderators, "ismoderator" : ismoderator,
                                              "assignedmod" : assignedmod, "events" : events})

def popularSubreddits(num=5, user = None):

    subreddits = list(Subreddit.objects.all())
    if(user != None):
        subreddits = [subreddit for subreddit in subreddits if not checkSubscribed(user,subreddit)]
    return sorted(subreddits, key = lambda s: subscribersCount(s), reverse=True)[:num]

def feed(subreddit, user = None):

    posts = []

    for p in LinkPost.objects.filter(posted_in = subreddit, deleted=False).extra(select={'num_votes' : 0, 'num_comments' : 0, 'type' : '%s', 'vote' : 0},
                                    select_params=('link',)):
        posts.append(updatePostFeatures(p, user))

    for p in TextPost.objects.filter(posted_in = subreddit, deleted=False).extra(select = {'num_votes' : 0, 'num_comments' : 0, 'type' : '%s', 'vote' : 0},
                                    select_params = ('text',)):
        posts.append(updatePostFeatures(p, user))

    return sorted(posts, key = lambda p: p.num_votes, reverse=True)

def getEvents(subreddit, user=None):

    events = []

    for e in Event.objects.filter(posted_in=subreddit):
        if timezone.now() < e.time and not e.deleted:
            events.append(updatePostFeatures(e, user))

    return sorted(events, key=lambda e: e.time)

def subscribersCount(subreddit):

    return Subscriber.objects.filter(subreddit=subreddit).count()

def getModerators(subreddit):

    qs = Moderator.objects.filter(subreddit=subreddit)
    mods = []
    for m in qs:
        mods.append(m.redditer)
    return mods

def checkSubscribed(user, subreddit):
    if Subscriber.objects.filter(redditer=user, subreddit=subreddit).exists():
        return True
    else:
        return False

def addSubredditForm(request):
    if request.user.is_authenticated():
        return render(request, "newsubreddit.html")
    else:
        return HttpResponse("Login to post!")

def addSubreddit(request):

    if request.method == 'GET':
        return redirect('index')
    subreddit_title = request.POST['title']
    if not validate_title(subreddit_title):
        return JsonResponse({'success' : False, 'Error' : "Subreddit Title should contain only A-Za-z0-9_"})

    description = request.POST['description']

    if not request.user.is_authenticated() :
        return HttpResponse("Login to add a new subreddit!")

    # some conditions for allowing to make a new subreddit

    if Subreddit.objects.filter(title=subreddit_title).exists():
        return JsonResponse({'success' : False, 'Error' : "Subreddit Already Exists"})

    subreddit = Subreddit(title=subreddit_title, description=description)
    subreddit.save()

    mod = Moderator(redditer=request.user, subreddit=subreddit)
    mod.save()

    return JsonResponse({'success' : True, 'Message' : "Added Subreddit", "title" : subreddit.title})

def subscribe(request):

    if request.method == 'GET':
        return redirect('index')

    subreddit_title = request.POST['subreddit']

    if not request.user.is_authenticated():
        return HttpResponse("Login to subscribe!")

    try:
        subreddit = Subreddit.objects.get(title=subreddit_title)
    except:
        return JsonResponse({'success' : False, 'Error' : "Subreddit Does not exist"})

    qs = Subscriber.objects.filter(redditer = request.user, subreddit=subreddit)

    if qs.count() == 0:
        subs = Subscriber(redditer=request.user, subreddit=subreddit)
        subs.save()

    return JsonResponse({'success' : True})

def unsubscribe(request):

    if request.method == 'GET':
        return redirect('index')
    subreddit_title = request.POST['subreddit']
    if not request.user.is_authenticated():
        return JsonResponse({'success' : False, 'Error' : "Login to subscribe!"})

    try:
        subreddit = Subreddit.objects.get(title=subreddit_title)
    except:
        return JsonResponse({'success' : False, 'Error' : "Subreddit Does not exist"})

    qs = Subscriber.objects.filter(redditer = request.user, subreddit=subreddit)

    if qs.count() > 0:
        qs.delete()

    return JsonResponse({'success' : True})

def addModerator(request):
    if request.method == 'GET':
        return redirect('index')

    subreddit_title = request.POST['subreddit']
    newmod_username = request.POST['username']

    try:
        newmod = get_user_model().objects.get(username=newmod_username)
    except:
        return JsonResponse({'success' : False, 'Error' : "User does not exist"})

    try:
        subreddit = Subreddit.objects.get(title=subreddit_title)
    except:
        return JsonResponse({'success' : False, 'Error' : "Subreddit Does not exist"})

    moderators = getModerators(subreddit)

    if not request.user.is_authenticated():
        return JsonResponse({'success' : False, 'Error' : "Login to add!"})
    elif not request.user in moderators and not request.user.is_staff:
        return JsonResponse({'success' : False, 'Error' : "Only current mods can add a new mod!"})
    elif newmod in moderators:
        return JsonResponse({'success' : False, 'Error' : "Already a mod!"})

    m = Moderator(redditer=newmod, subreddit=subreddit)
    m.save()

    return JsonResponse({'success' : True})

def delModerator(request):
    if request.method == 'GET':
        return redirect('index')

    subreddit_title = request.POST['subreddit']

    try:
        subreddit = Subreddit.objects.get(title=subreddit_title)
    except:
        return JsonResponse({'success' : False, 'Error' : "Subreddit Does not exist"})

    moderators = getModerators(subreddit)

    if not request.user.is_authenticated():
        return JsonResponse({'success' : False, 'Error' : "Login to add!"})
    elif not request.user in moderators:
        return JsonResponse({'success' : False, 'Error' : "Not a Mod!"})

    if len(moderators) == 1:
        if(not assignNewModerator(subreddit, request.user)):
            return JsonResponse({'success': False, 'Error': "Only Subscriber can't leave!"})

    qs = Moderator.objects.get(redditer=request.user, subreddit=subreddit)
    qs.delete()

    return JsonResponse({'success' : True})

def getPostKarma(user, userPosts):
    karma = 0
    for p in userPosts:
        karma += p.num_votes
    return karma

def assignNewModerator(subreddit, resign_user):
    subscribers = Subscriber.objects.filter(subreddit=subreddit)
    subredditPosts = feed(subreddit)
    maxKarma = 0
    newmod = None
    for subs in subscribers:
        if subs.redditer != resign_user:
            userPosts = [p for p in subredditPosts if p.posted_by == subs.redditer]
            karma = getPostKarma(subs.redditer,userPosts)
            if(maxKarma < karma):
                newmod = subs.redditer
                maxKarma = karma
            if newmod is None:
                newmod = subs.redditer

    if newmod is None:
        return False
    else:
        m = Moderator(redditer=newmod, subreddit=subreddit)
        m.save()
    return True

def validate_title(username):
    return re.compile('[A-Za-z0-9_]+$').match(username)

def updatePostFeatures(post, user=None):

    post.num_votes = Vote.objects.filter(voted_on__id = post.id).aggregate(votes = Sum('value')).get('votes')

    post.num_comments = numComments(post)

    if post.num_votes == None:
        post.num_votes = 0

    if user is not None:

        qs = Vote.objects.filter(voted_on__id = post.id, voted_by = user)
        if len(qs) > 0:
            post.vote = qs[0].value

    return post

def numComments(post):

    num = 0
    qs = Comment.objects.filter(commented_on = post)
    num += qs.count()
    for c in qs:
        num += numComments(c)
    return num


from collections import deque

num, deleter = input().split()
deleter = int(deleter)
a=list(map(int,num))

#print(a)
#cnt=0
# for i in range(len(a)):
#     for j in range(i+1):
#         if a[j]<a[i]:
#             a.pop(j)
#             deleter-=1

i=0

while i<len(a):
    j = i-1
    while j>=0 and deleter>0:
        #print(a[j],a[i])
        if a[j]<a[i]:
            #print(j,i)
            a.pop(j)
            deleter-=1
            i-=1
            j-=1
            #print(a)
        else:
            j-=1
    i+=1

#print(a)
#print(deleter)
if deleter==0:
    for x in a:
        print(x,end='')
else:
    for x in a[:-deleter]:
        print(x,end='')

파이썬 알고리즘 문제풀이(코딩테스트 대비)/섹션 5/1. 가장 큰 수/AA.py


from flask import Blueprint, request, jsonify
from datetime import datetime
from sqlalchemy import and_

from app.event.models import Client, EventViews
from app.database import db

album_ajax = Blueprint('album_ajax', __name__, url_prefix='/album/ajax')

@album_ajax.route('/client', methods=('POST',))
def client():
    """Для идентификации клиента и фиксации просмртра

    :param fingerprint: Идентификатор клиента
    :type fingerprint: string

    :param event_id: Идентификатор события
    :type event_id: integer

    :return: message, status
    :rtype: jsonify
    """
    fingerprint = request.form.get('fingerprint')
    event_id = request.form.get('event_id')

    if fingerprint:
        fingerprint = fingerprint.strip()

        client_ = Client.query.filter_by(fingerprint=fingerprint).first()
        if not client_:
            client_ = Client(
                fingerprint=fingerprint,
                created_at=datetime.now(),
                updated_at=datetime.now()
            )

            db.session.add(client_)
            db.session.commit()

        if client_ and event_id:
            views_ = EventViews.query.filter(
                and_(EventViews.client_id.__eq__(client_.id),
                     EventViews.event_id.__eq__(event_id))).first()
            if not views_:
                views_ = EventViews(
                    client_id=client_.id,
                    event_id=event_id,
                    created_at=datetime.now(),
                    cnt=0,
                )

            views_.cnt += 1
            views_.updated_at = datetime.now()

            db.session.add(views_)
            db.session.commit()

    return jsonify(message='Ok'), 200


class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        cache = {}
        for idx, val in enumerate(nums):
            if val in cache:
                if idx - cache[val] <= k:
                    return True
            cache[val] = idx
        return False


io = None
def _snd(s):
  io.send(s)
def _sndl(s):
  io.sendline(s)
def _snda(a,s):
  io.sendafter(a,s)
def _sndla(a,s):
  io.sendlineafter(a,s)
def _rcvu(s):
  return io.recvuntil(s)
def _rcva():
  return io.recvall()
def _rcvn(n):
  return io.recv(n)
def _rcvl():
    return io.recvline()
from pwn import *
#context.log_level = 'error'

def connect():
    global io
    io = remote('mission.satellitesabove.me', 5023)
    ticket = 'ticket{uniform74490hotel:GK069N6YnYRpJm_7gz3qKTpgeFg16x7l-pegT6h2rgmnqbP0BIyuXtftd9r87CoqiA}'
    _sndla(':', ticket)

    _rcvu('so make note of your plan elsewhere.')

def disconnect():
    global io
    io.close()

from datetime import datetime, timedelta
from random import choice

modes = ['sun_point', 'imaging', 'data_downlink', 'wheel_desaturate']
date_format = "%Y-%m-%dT%H:%M:%SZ"

start_time = '2020-04-22T00:00:00Z'
start_time = datetime.strptime(start_time, date_format)

def send_plan(time, mode):
    _sndl(f'{time.strftime(date_format)} {mode}')

import ast
def get_telemetry():
    cdate = _rcvl()
    if cdate == b'2020-04-23T23:59:00Z\n':
        io.interactive()
        exit(0)

    if b'Failed' in cdate:
        raise Exception(b'Error: ' + cdate)

    data = _rcvl()
    mode_change = None
    sensors = None

    if b'Changing'  in data:
        mode_change = data
        sensors = ast.literal_eval(_rcvl().decode('utf-8'))
    else:
        sensors = ast.literal_eval(data.decode('utf-8'))

    collected = _rcvl()
    collected = float(collected.replace(b'Collected Data:', b'').replace(b'bytes', b'').strip())

    return (cdate, mode_change, sensors, collected)

def bruteforce_plan(i):
    send_plan(start_time, 'sun_point')

    send_plan(start_time + timedelta(minutes = i), 'imaging')
    send_plan(start_time + timedelta(minutes = i + 2), 'sun_point')

def run_plan():
    _sndl('run')
    _rcvu('Executing mission plan.\n')

def bruteforce_find(i):
    print (f'try for minute: {i}')
    connect()
    bruteforce_plan(i)
    run_plan()
    while True:
        try:
            info = get_telemetry()
            if info[3] != 0:
                print (f'[+] sucess at {i}')
        except Exception as e:
            print (f'failed for {i}: {e}')
            break
        #print (info[0], end=' ')
        #print (info[2]['adcs']['mode'], end=' ')
        #print (info[3], end=' ')
    disconnect()

#for i in range(180 + 120 * 4, 180 + 120 * 6):
#    bruteforce_find(i)

def good_plan():
    connect()
    send_plan(start_time, 'sun_point')

    send_plan(start_time + timedelta(hours=9, minutes=30), 'imaging')
    send_plan(start_time + timedelta(hours=9, minutes=37), 'sun_point')

    send_plan(start_time + timedelta(hours=10, minutes=47), 'data_downlink')
    send_plan(start_time + timedelta(hours=10, minutes=51), 'sun_point')

    send_plan(start_time + timedelta(hours = 20), 'wheel_desaturate')
    send_plan(start_time + timedelta(hours = 22), 'sun_point')

    send_plan(start_time + timedelta(days=1, hours=9, minutes=50), 'imaging')
    send_plan(start_time + timedelta(days=1, hours=9, minutes=57), 'sun_point')

    send_plan(start_time + timedelta(days=1, hours=11, minutes=10), 'data_downlink')
    send_plan(start_time + timedelta(days=1, hours=11, minutes=14), 'sun_point')

    run_plan()

    while True:
        try:
            info = get_telemetry()
        except Exception as e:
            print (e)
            break
        if True:
            print (info[0], end=' ')
            print (f'{info[2]["adcs"]["mode"]} cam temp: {info[2]["cam"]["temp"]:.2f} disk {info[2]["obc"]["disk"]:.2f} rpm 1: {info[2]["adcs"]["whl_rpm"][0]:.2f}', end = ' ')
            print (f'MiB to ground: {info[3]/1024/1024:.2f}', end=' ')
            print ()
    disconnect()

good_plan()


def nonblocking_readlines(f):
    """Generator which yields lines from F (a file object, used only for
       its fileno()) without blocking.  If there is no data, you get an
       endless stream of empty strings until there is data again (caller
       is expected to sleep for a while).
       Newlines are normalized to the Unix standard.
    """

    fd = f.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
    enc = locale.getpreferredencoding(False)

    buf = bytearray()
    while True:
        try:
            block = os.read(fd, 8192)
        except BlockingIOError:
            yield ""
            continue

        if not block:
            if buf:
                yield buf.decode(enc)
                buf.clear()
            break

        buf.extend(block)

        while True:
            r = buf.find(b'\r')
            n = buf.find(b'\n')
            if r == -1 and n == -1: break

            if r == -1 or r > n:
                yield buf[:(n+1)].decode(enc)
                buf = buf[(n+1):]
            elif n == -1 or n > r:
                yield buf[:r].decode(enc) + '\n'
                if n == r+1:
                    buf = buf[(r+2):]
                else:
                    buf = buf[(r+1):]


import numpy as np

from . import generator_base
from plotter.utils.gcode import *
from plotter.utils.helper import overrides

class ArcGenerator(generator_base.GeneratorBase):
    def __init__(self, args):
        generator_base.GeneratorBase.__init__(self, args)

    @classmethod
    def getName(cls):
        return "Arc"

    @classmethod
    def getHelp(cls):
        return "Generates images by drawing arcs."

    @classmethod
    def getInputType(cls):
        return "image"

    @classmethod
    def setupCustomParams(cls, subparser):
        subparser.add_argument(
            '--img-threshold-min', default=0, type=int, help="Min threshold for image.")
        subparser.add_argument(
            '--img-threshold-max', default=255, type=int, help="Max threshold for image.")
        subparser.add_argument('--img-threshold-inv', default=False,
                               action="store_true", help="Invert image thresholding.")
        subparser.add_argument('--dirs', default=[1], nargs="*", type=int, choices=[
                               1, 2, 3, 4], help="List of directions that should be used for drawing")
        subparser.add_argument('--arc_sampling', default=20,
                               type=int, help="Number of samples per arc.")

    @overrides(generator_base.GeneratorBase)
    def convert(self, img):

        if len(img.shape) == 3 and img.shape[2] > 1:
            img = img.mean(axis=2)

        gcode = [GCode_up(), GCode_home()]

        max_val = self.params["img_threshold_max"]
        min_val = self.params["img_threshold_min"]
        maxRadius = int(np.linalg.norm(img.shape))

        dirs_drawn = 0
        for d in self.params["dirs"]:
            pImg = np.array([0, 0])
            pScreen = self.px2Scr(pImg)

            if d == 1:
                offset = np.array([0, 0])
            elif d == 2:
                offset = np.array([img.shape[1]-1, 0])
            elif d == 3:
                offset = np.array([0, img.shape[0]-1])
            elif d == 4:
                offset = np.array([img.shape[1]-1, img.shape[0]-1])

            for r in range(1, maxRadius):
                gcode.append(GCode_up())
                drawing = False
                lastDrawPos = [0, 0]

                # Sample in such a way that each arc segment has the same length
                # arc_length = 2*pi*r*radians/(2*pi)
                # radians = arc_length/r
                sampling = self.params["arc_sampling"]/r
                # print(sampling)

                if d == 1:
                    angles = np.arange(0, 90, sampling)
                elif d == 2:
                    angles = np.arange(0, -90, -sampling)
                elif d == 3:
                    angles = np.arange(90, 180, sampling)
                elif d == 4:
                    angles = np.arange(-90, -180, -sampling)

                for a in angles:
                    pImg = np.array(
                        [r*np.sin(np.radians(a)), r*np.cos(np.radians(a))])
                    pImg = pImg + offset

                    if pImg[0] < -0.5 or pImg[1] < -0.5 or pImg[1] >= img.shape[0]-0.5 or pImg[0] >= img.shape[1]-0.5:
                        continue

                    pixel = img[int(pImg[1]), int(pImg[0])]

                    if self.params["img_threshold_inv"]:
                        pixel = 255 - pixel

                    if pixel >= min_val and pixel <= max_val and pixel - min_val <= float(max_val - min_val)/(dirs_drawn+1):
                        pScreen = self.px2Scr(pImg)
                        gcode.append(GCode_goTo(
                            pScreen, self.params["speed_nodraw"]))

                        if not drawing:
                            gcode.append(GCode_down())
                            drawing = True

                    else:
                        if drawing:
                            pScreen = self.px2Scr(lastDrawPos)
                            gcode.append(GCode_goTo(
                                pScreen, self.params["speed_draw"]))
                            gcode.append(GCode_up())
                            drawing = False

                    if drawing:
                        lastDrawPos = pImg

            dirs_drawn = dirs_drawn + 1

        return gcode


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

import subprocess

detModel = 38
recoVar = 43

executable = "/usera/sg568/ilcsoft_Mod_v01_17_07/PandoraAnalysis/bin/AnalysePerformance"
results = ''

# Detailed JER

results += '-----------------------------------------------------------------------------------------------------------------------------------\n'
results += 'Detector Model ' + str(recoVar) + '\n'
results += '-----------------------------------------------------------------------------------------------------------------------------------\n'

for pandoraSettings in ['Muon', 'Default', 'PerfectPhoton', 'PerfectPhotonNK0L', 'PerfectPFA']:
    results += pandoraSettings + '\n'

    for jetEnergy in ['30', '40', '50', '60', '70', '80', '91', '100', '110', '120', '130', '140', '150', '160', '170', '180', '190', '200', '220', '240', '260', '280', '300', '350', '400', '450', '500']:
        inputRootFileFolder = "/r06/lc/sg568/JERDetailed/RootFiles/Detector_Model_" + str(detModel) + "/Reco_Var_" + str(recoVar) + "/" + str(jetEnergy) + "GeV/"
        outputRootFileFolder = inputRootFileFolder
        inputRootFileFormat = "MarlinReco_MokkaSim_Detector_Model_" + str(detModel) + "_Z_uds_" + str(jetEnergy) + "GeV_*_" + pandoraSettings + ".root"
        outputRootFileName = "PfoAnalysisHistorgrams_Detector_Model_" + str(detModel) + "_Reco_Var_" + str(recoVar) + "_uds" + jetEnergy + "GeV_PandoraSettings" + pandoraSettings + ".root"

        argsString = executable + ' ' + inputRootFileFolder + inputRootFileFormat + ' ' + outputRootFileFolder + outputRootFileName
        args = argsString.split()
        popen = subprocess.Popen(args, stdout=subprocess.PIPE)
        popen.wait()
        output = popen.stdout.read()

        resultsLine = ''
        for line in output.splitlines():
            if 'fPFA_L7A' in line:
                resultsLine = line

        results += jetEnergy + ' GeV Di Jet Energy:' + resultsLine + '\n'
results += '\n'

resultsFile = open("Detector_Model_" + str(detModel) + "_Reco_Var_" + str(recoVar) + "Results.txt", "w")
resultsFile.write(results)
resultsFile.close()


import torch as t
import torch.nn as nn
import torch.nn.functional as F
from itertools import chain
import torch.optim as optim
import time
import random
import utils as U
import model_bilstm as model

class Model_No_Diagonal_Zero(model.Model_BCE_Adam):

  def zero_diagonal(self, mat):
    return mat

class Model(Model_No_Diagonal_Zero):
  def get_should_update(self):
    return chain(self.encoder.parameters(), self.minify_layer.parameters(), self.left_lstm.parameters(), self.right_lstm.parameters(), self.squeezed_layer.parameters(), self.query_layer.parameters())

  def init_hook(self):
    self.left_lstm = t.nn.LSTM(self.hidden_size, self.hidden_size) # Bi-Direction
    self.right_lstm = t.nn.LSTM(self.hidden_size, self.hidden_size) # Bi-Direction
    self.query_layer = t.nn.Linear(self.hidden_size * 2, self.hidden_size)
    self.squeezed_layer = t.nn.Linear(self.hidden_size, 1)
    self.BCE = t.nn.BCELoss(None, None, None, 'sum')

  def zero_input(self):
    return t.zeros(1,1,self.input_size)

  def get_scores(self, outs, embs):
    left_lstm = self.left_lstm
    right_lstm = self.right_lstm
    scores = []
    for index,query in enumerate(outs):
      left = embs[0: index] # (left_count, 1, input_size) && reversed
      right = embs[index:] # (right_count, 1, input_size)
      query = self.query_layer(query).view(1,1,-1)
      if len(left) > 0:
        left_out,_ = left_lstm(left.flip(0), (query, self.zero_input())) #  (left_count, 1, input_size)
        left_out = left_out.flip(0)
        left_squeezed = self.squeezed_layer(left_out) # (left_count, 1, 1)
        left_sigmoided = self.sigmoid(left_squeezed)
        # total_loss += self.multiple_pointer_loss(squeezed, left_label)
      if len(right) > 0:
        right_out,_ = right_lstm(right, (query, self.zero_input())) #  (left_count, 1, input_size)
        right_squeezed = self.squeezed_layer(right_out) # (left_count, 1, 1)
        # total_loss += self.multiple_pointer_loss(squeezed, right_out)
        right_sigmoided = self.sigmoid(right_squeezed)
      if len(left) > 0 and len(right) > 0:
        all_sigmoided = t.cat((left_sigmoided, right_sigmoided))
      elif len(left) > 0:
        all_sigmoided = left_sigmoided
      else:
        all_sigmoided = right_sigmoided
      scores.append(all_sigmoided)
    scores = t.cat(scores).view(len(embs), len(embs)) # (seq_len, seq_len)
    return scores


# coding=utf-8
"""
实现huffman算法的细节
"""
import heapq

class HuffNode():
    '''huffman节点'''
    def __init__(self,weight,char=None):
        self.weight = weight    # 权重
        self.char = char    # 节点元素数据(int)
        self.left = None    # 左节点
        self.right = None   # 右节点

    def __lt__(self, other):
        return self.weight < other.weight

class HuffTree():
    '''huffman树'''
    def __init__(self):
        self.root = None    # 根节点

    def _build_dictionary(self,cur,d,code=''):
            if not (cur.left or cur.right):
                # 左右为空,该节点为叶子节点
                d[cur.char] = code
                print(f'({cur.char}=>{code})')
            else:
                # 存在子树
                if cur.left:
                    self._build_dictionary(cur.left, d, code+'0') # 向左移动为0
                if cur.right:
                    self._build_dictionary(cur.right, d, code+'1') # 向右移动为1

    def build_dictionary(self):
        '''遍历huffman树,构造huffman字典'''
        d = {}
        self._build_dictionary(self.root, d)
        return d

    def build_huffman_tree(self,weight):
        '''
        根据权重列表,构建huffman树
        :weight: 权重列表
        '''
        w_size = len(weight)
        heap = [HuffNode(weight[i],i) for i in range(w_size)]   # 构建一组单节点的树
        heapq.heapify(heap) # 堆化

        for i in range(w_size-1):
            # 去两棵最小的树
            x = heapq.heappop(heap)
            y = heapq.heappop(heap)

            # 合并两棵树
            z = HuffNode(x.weight+y.weight)
            z.left = x
            z.right = y

            print(f'z.weight = {z.weight}')

            # 将合并后的树入堆
            heapq.heappush(heap, z)

        self.root = heap[0]
        print(f'tree root: {self.root.weight}, {self.root.char}')


from functools import partial
from models.vit import VisionTransformer, interpolate_pos_embed
from models.xbert import BertConfig, BertForMaskedLM, BertModel
from models.transformer import TransformerEncoder
from models.tokenization_bert import BertTokenizer

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

import numpy as np
import random

class SMF(nn.Module):
    def __init__(self,
                 text_encoder = None,
                 tokenizer = None,
                 fusion_encoder = None,
                 config = None,
                 temp = 0.07,
                 init_deit = True
                 ):
        super().__init__()

        self.tokenizer = tokenizer
        self.mlm_probability = config['mlm_probability']
        embed_dim = config['embed_dim']
        self.batch_size= config['batch_size']
        self.embed_dim= config['embed_dim']

        self.visual_encoder = VisionTransformer(
            img_size=config['image_res'], patch_size=16, embed_dim=768, depth=12, num_heads=12,
            mlp_ratio=4, qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6))

        if init_deit:
            checkpoint = torch.hub.load_state_dict_from_url(
                url="https://dl.fbaipublicfiles.com/deit/deit_base_patch16_224-b5f2ef4d.pth",
                map_location="cpu", check_hash=True) #检查点
            state_dict = checkpoint["model"]
            pos_embed_reshaped = interpolate_pos_embed(state_dict['pos_embed'], self.visual_encoder)
            state_dict['pos_embed'] = pos_embed_reshaped
            msg = self.visual_encoder.load_state_dict(state_dict,strict=False)
            print(msg)

        vision_width = config['vision_width']
        bert_config = BertConfig.from_json_file(config['bert_config'])
        # lou
        fusion_bert_config = BertConfig.from_json_file(config['fusion_bert_config'])

        self.text_encoder = BertModel.from_pretrained(text_encoder, config=bert_config, add_pooling_layer=False)
        self.fusion_encoder = BertForMaskedLM.from_pretrained(fusion_encoder, config=fusion_bert_config)

        text_width = self.text_encoder.config.hidden_size
        self.vision_proj = nn.Linear(vision_width, embed_dim)
        self.text_proj = nn.Linear(text_width, embed_dim)

        self.temp = nn.Parameter(torch.ones([]) * config['temp'])
        self.queue_size = config['queue_size']
        self.momentum = config['momentum']
        self.itm_head = nn.Linear(embed_dim, 2)

        # create the queue
        self.register_buffer("image_queue", torch.randn(embed_dim, self.queue_size))
        self.register_buffer("text_queue", torch.randn(embed_dim, self.queue_size))
        self.register_buffer("queue_ptr", torch.zeros(1, dtype=torch.long))

        self.image_queue = nn.functional.normalize(self.image_queue, dim=0)
        self.text_queue = nn.functional.normalize(self.text_queue, dim=0)

        self.conv1d_t = nn.Conv1d(text_width, self.embed_dim, kernel_size=1, padding=0, bias=False)
        self.conv1d_i = nn.Conv1d(vision_width, self.embed_dim, kernel_size=1, padding=0, bias=False)

        self.conv1d_t_m = nn.Conv1d(text_width, self.embed_dim, kernel_size=1, padding=0, bias=False)
        self.conv1d_i_m = nn.Conv1d(vision_width, self.embed_dim, kernel_size=1, padding=0, bias=False)

        num_heads = 16
        attn_dropout = 0.1
        relu_dropout = 0.1
        res_dropout = 0.1
        embed_dropout = 0.1
        attn_mask = 'store_false'
        layers = 4

        self.trans_iichange = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.trans_ttchange = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.ii_proj = nn.Linear(embed_dim, embed_dim)
        self.tt_proj = nn.Linear(embed_dim, embed_dim)

        # create momentum models
        self.visual_encoder_m = VisionTransformer(
            img_size=config['image_res'], patch_size=16, embed_dim=768, depth=12, num_heads=12,
            mlp_ratio=4, qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6))
        self.vision_proj_m = nn.Linear(vision_width, embed_dim)
        self.text_encoder_m = BertForMaskedLM.from_pretrained(text_encoder, config=bert_config)
        self.text_proj_m = nn.Linear(text_width, embed_dim)

        self.trans_iichange_m = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.trans_ttchange_m = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.ii_proj_m = nn.Linear(embed_dim, embed_dim)
        self.tt_proj_m = nn.Linear(embed_dim, embed_dim)

        self.trans_itchange = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.trans_tichange = TransformerEncoder(embed_dim=embed_dim,
                                                 num_heads=num_heads,
                                                 layers=layers,
                                                 attn_dropout=attn_dropout,
                                                 relu_dropout=relu_dropout,
                                                 res_dropout=res_dropout,
                                                 embed_dropout=embed_dropout,
                                                 attn_mask=attn_mask)
        self.it_proj = nn.Linear(embed_dim, embed_dim)
        self.ti_proj = nn.Linear(embed_dim, embed_dim)
        self.model_pairs = [[self.trans_iichange,self.trans_iichange_m],
                            [self.trans_ttchange,self.trans_ttchange_m],
                            [self.ii_proj,self.ii_proj_m],
                            [self.tt_proj,self.tt_proj_m],
                            [self.visual_encoder,self.visual_encoder_m],
                            [self.text_encoder,self.text_encoder_m],
                            [self.conv1d_t, self.conv1d_t_m],
                            [self.conv1d_i, self.conv1d_i_m]
                           ]

        self.copy_params()

    def forward(self, image, text, alpha=0):
        with torch.no_grad():
            self.temp.clamp_(0.001,0.5)

        image_embeds_old = self.visual_encoder(image)
        image_atts = torch.ones(image_embeds_old.size()[:-1],dtype=torch.long).to(image.device)

        text_output = self.text_encoder(text.input_ids, attention_mask = text.attention_mask, return_dict = True, mode = 'text')
        text_embeds_old = text_output.last_hidden_state

        # self-attention

        m_text_feat_tran = text_embeds_old.clone().transpose(1, 2)
        m_image_feat_tran = image_embeds_old.clone().transpose(1, 2)

        m_text_feat = self.conv1d_t(m_text_feat_tran).permute(2, 0, 1)
        m_image_feat = self.conv1d_i(m_image_feat_tran).permute(2, 0, 1)

        tt_embeds = self.trans_ttchange(m_text_feat, m_text_feat, m_text_feat).permute(1, 0, 2)
        ii_embeds = self.trans_iichange(m_image_feat, m_image_feat, m_image_feat).permute(1, 0, 2)
        text_feat = F.normalize(self.tt_proj(tt_embeds[:,0,:]),dim=-1)
        image_feat = F.normalize(self.ii_proj(ii_embeds[:,0,:]),dim=-1)

        i2t_embeds = self.trans_itchange(m_text_feat, m_image_feat, m_image_feat).permute(1, 0, 2)
        t2i_embeds = self.trans_tichange(m_image_feat, m_text_feat, m_text_feat).permute(1, 0, 2)
        i2t_feat = F.normalize(self.it_proj(i2t_embeds[:,0,:]),dim=-1)
        t2i_feat = F.normalize(self.ti_proj(t2i_embeds[:,0,:]),dim=-1)

        text_embeds = torch.cat((tt_embeds,t2i_embeds), 1)
        image_embeds = torch.cat((ii_embeds,i2t_embeds), 1)

        with torch.no_grad():
            self._momentum_update()

            image_embeds_m_old = self.visual_encoder_m(image)
            text_output_m = self.text_encoder_m.bert(text.input_ids, attention_mask = text.attention_mask,
                                                return_dict = True, mode = 'text')
            text_embeds_m_old = text_output_m.last_hidden_state

            m_text_feat_tran_m = text_embeds_m_old.clone().transpose(1, 2)
            m_image_feat_tran_m = image_embeds_m_old.clone().transpose(1, 2)

            m_text_feat_m = self.conv1d_t(m_text_feat_tran_m).permute(2, 0, 1)
            m_image_feat_m = self.conv1d_i(m_image_feat_tran_m).permute(2, 0, 1)

            # cross-modal attention
            image_embeds_m = self.trans_iichange_m(m_image_feat_m, m_image_feat_m, m_image_feat_m).permute(1, 0, 2)
            text_embeds_m = self.trans_ttchange_m(m_text_feat_m, m_text_feat_m, m_text_feat_m).permute(1, 0, 2)
            image_feat_m = F.normalize(self.ii_proj_m(image_embeds_m[:,0,:]),dim=-1)
            text_feat_m = F.normalize(self.tt_proj_m(text_embeds_m[:,0,:]),dim=-1)
            image_feat_all = torch.cat([image_feat_m .t(),self.image_queue.clone().detach()],dim=1)
            text_feat_all = torch.cat([text_feat_m.t(),self.text_queue.clone().detach()],dim=1)

            sim_i2t_m = image_feat_m @ text_feat_all / self.temp #p i2t
            sim_t2i_m = text_feat_m @ image_feat_all / self.temp #p t2i

            sim_targets = torch.zeros(sim_i2t_m.size()).to(image.device)
            sim_targets.fill_diagonal_(1)

            sim_i2t_targets = alpha * F.softmax(sim_i2t_m, dim=1) + (1 - alpha) * sim_targets
            sim_t2i_targets = alpha * F.softmax(sim_t2i_m, dim=1) + (1 - alpha) * sim_targets

        sim_i2t = image_feat @ text_feat_all / self.temp
        sim_t2i = text_feat @ image_feat_all / self.temp

        loss_i2t = -torch.sum(F.log_softmax(sim_i2t, dim=1)*sim_i2t_targets,dim=1).mean()
        loss_t2i = -torch.sum(F.log_softmax(sim_t2i, dim=1)*sim_t2i_targets,dim=1).mean()

        loss_ita = (loss_i2t+loss_t2i)/2 #L ita

        sim_i2t_c = i2t_feat @ text_feat_all / self.temp #p c
        sim_t2i_c = t2i_feat @ image_feat_all / self.temp #p c
        sim_targets_itc = torch.arange(0, self.batch_size).to(image.device)
        loss_i2t_c = F.cross_entropy(sim_i2t_c, sim_targets_itc)
        loss_t2i_c = F.cross_entropy(sim_t2i_c, sim_targets_itc)

        loss_itc = (loss_i2t_c+loss_t2i_c)/2 #L itc

        self._dequeue_and_enqueue(image_feat_m, text_feat_m)

        text_atts = torch.ones(text_embeds.size()[:-1],dtype=torch.long).to(image.device)
        image_atts = torch.ones(image_embeds.size()[:-1],dtype=torch.long).to(image.device)
        output_pos = self.fusion_encoder.bert(encoder_embeds = text_embeds,
                                       attention_mask = text_atts,
                                       encoder_hidden_states = image_embeds,
                                       encoder_attention_mask = image_atts,
                                       return_dict = True,
                                       mode = 'fusion',
                                      )

        with torch.no_grad():
            bs = image.size(0)
            weights_i2t = F.softmax(sim_i2t_m[:,:bs],dim=1)
            weights_t2i = F.softmax(sim_t2i_m[:,:bs],dim=1)
            weights_i2t.fill_diagonal_(0)
            weights_t2i.fill_diagonal_(0)

        image_embeds_neg = []
        for b in range(bs):
            neg_idx = torch.multinomial(weights_t2i[b], 1).item()
            image_embeds_neg.append(image_embeds[neg_idx])
        image_embeds_neg = torch.stack(image_embeds_neg,dim=0)

        text_embeds_neg = []
        text_atts_neg = []
        for b in range(bs):
            neg_idx = torch.multinomial(weights_i2t[b], 1).item()
            text_embeds_neg.append(text_embeds[neg_idx])
            text_atts_neg.append(text_atts[neg_idx])
        text_embeds_neg = torch.stack(text_embeds_neg,dim=0)
        text_atts_neg = torch.stack(text_atts_neg,dim=0)

        text_embeds_all = torch.cat([text_embeds, text_embeds_neg],dim=0)
        text_atts_all = torch.cat([text_atts, text_atts_neg],dim=0)

        image_embeds_all = torch.cat([image_embeds_neg,image_embeds],dim=0)
        image_atts_all = torch.cat([image_atts,image_atts],dim=0)

        output_neg = self.fusion_encoder.bert(encoder_embeds = text_embeds_all,
                                        attention_mask = text_atts_all,
                                        encoder_hidden_states = image_embeds_all,
                                        encoder_attention_mask = image_atts_all,
                                        return_dict = True,
                                        mode = 'fusion',
                                       )

        vl_embeddings = torch.cat([output_pos.last_hidden_state[:,0,:], output_neg.last_hidden_state[:,0,:]],dim=0)
        vl_output = self.itm_head(vl_embeddings)

        itm_labels = torch.cat([torch.ones(bs,dtype=torch.long),torch.zeros(2*bs,dtype=torch.long)],
                               dim=0).to(image.device)
        loss_itm = F.cross_entropy(vl_output, itm_labels)

        #MLM
        input_ids = text.input_ids.clone()
        labels = input_ids.clone()

        probability_matrix = torch.full(labels.shape, self.mlm_probability)
        input_ids, labels = self.mask(input_ids, self.fusion_encoder.config.vocab_size, image.device, targets=labels,
                                      probability_matrix = probability_matrix)

        with torch.no_grad():
            image_atts_m = torch.ones(image_embeds_m.size()[:-1],dtype=torch.long).to(image.device)
            logits_m = self.fusion_encoder(input_ids,
                                           attention_mask = text.attention_mask,
                                           encoder_hidden_states = image_embeds_m,
                                           encoder_attention_mask = image_atts_m,
                                           return_dict = True,
                                           return_logits = True,
                                          )
        logits_m = torch.clamp(logits_m, min=1e-7, max=1 - 1e-7)
        mlm_output = self.fusion_encoder(input_ids,
                                       attention_mask = text.attention_mask,
                                       encoder_hidden_states = image_embeds,
                                       encoder_attention_mask = image_atts,
                                       return_dict = True,
                                       labels = labels,
                                       soft_labels = F.softmax(logits_m,dim=-1),
                                       alpha = alpha
                                      )
        loss_mlm = mlm_output.loss

        ita_t = 1
        loss_ita = loss_ita * ita_t
        itc_t = 1
        loss_itc = loss_itc * itc_t

        te = torch.cat((text_feat,t2i_feat), 1)
        ie = torch.cat((image_feat,i2t_feat), 1)

        return loss_mlm, loss_ita, loss_itc, loss_itm,te,ie

    @torch.no_grad()
    def copy_params(self):
        for model_pair in self.model_pairs:
            for param, param_m in zip(model_pair[0].parameters(), model_pair[1].parameters()):
                param_m.data.copy_(param.data)  # initialize
                param_m.requires_grad = False  # not update by gradient

    @torch.no_grad()
    def _momentum_update(self):
        for model_pair in self.model_pairs:
            for param, param_m in zip(model_pair[0].parameters(), model_pair[1].parameters()):
                param_m.data = param_m.data * self.momentum + param.data * (1. - self.momentum)

    @torch.no_grad()
    def _dequeue_and_enqueue(self, image_feat, text_feat):
        # gather keys before updating queue
        image_feats = concat_all_gather(image_feat)
        text_feats = concat_all_gather(text_feat)

        batch_size = image_feats.shape[0]

        ptr = int(self.queue_ptr)
        assert self.queue_size % batch_size == 0  # for simplicity

        # replace the keys at ptr (dequeue and enqueue)
        self.image_queue[:, ptr:ptr + batch_size] = image_feats.T
        self.text_queue[:, ptr:ptr + batch_size] = text_feats.T
        ptr = (ptr + batch_size) % self.queue_size  # move pointer

        self.queue_ptr[0] = ptr

    def mask(self, input_ids, vocab_size, device, targets=None, masked_indices=None, probability_matrix=None):
        if masked_indices is None:
            masked_indices = torch.bernoulli(probability_matrix).bool()

        masked_indices[input_ids == self.tokenizer.pad_token_id] = False
        masked_indices[input_ids == self.tokenizer.cls_token_id] = False

        if targets is not None:
            targets[~masked_indices] = -100 # We only compute loss on masked tokens

        # 80% of the time, we replace masked input tokens with tokenizer.mask_token ([MASK])
        indices_replaced = torch.bernoulli(torch.full(input_ids.shape, 0.8)).bool() & masked_indices
        input_ids[indices_replaced] = self.tokenizer.mask_token_id

        # 10% of the time, we replace masked input tokens with random word
        indices_random = torch.bernoulli(torch.full(input_ids.shape, 0.5)).bool() & masked_indices & ~indices_replaced
        random_words = torch.randint(vocab_size, input_ids.shape, dtype=torch.long).to(device)
        input_ids[indices_random] = random_words[indices_random]
        # The rest of the time (10% of the time) we keep the masked input tokens unchanged

        if targets is not None:
            return input_ids, targets
        else:
            return input_ids

@torch.no_grad()
def concat_all_gather(tensor):
    """
    Performs all_gather operation on the provided tensors.
    *** Warning ***: torch.distributed.all_gather has no gradient.
    """
    tensors_gather = [torch.ones_like(tensor)
        for _ in range(torch.distributed.get_world_size())]
    torch.distributed.all_gather(tensors_gather, tensor, async_op=False)

    output = torch.cat(tensors_gather, dim=0)
    return output


from os import system as cmd
from time import sleep as wait

message = "Calculo de média"

print(len(message) * "=")
print(message)
print(len(message) * "=")
wait(3)
cmd('cls')

#coleta os dados
print('Utilize a escala de 0 a 100')
nome = input("Digite o nome do aluno: ")
nota1 = int(input("Insira a primeira nota: "))
nota2 = int(input("Insira a segunda nota: "))
nota3 = int(input("Insira a  terceira nota: "))
nota4 = int(input("Insira a quarta nota: "))
cmd('cls')
#calcula os dados
print('Arguarde alguns segundos . . .')
wait(3)

media = (nota1+nota2+nota3+nota4)/4
#verificação
if media > 50 :
    situação = 'aprovado'
else:
    situação = 'reprovado'
#retorna os resultados dos calculos para o usuário
print(f"A situação do aluno {nome} é {situação} pois sua média foi de {media}.")


from tkinter import *
window = Tk()
window.title("hand_gesture")
window.geometry('650x400')
lbl = Label(window, text="smart mirror show date time and news ")
lbl.grid(column=50, row=30)
def clicked():
    from subprocess import call
    call(["python", "circel.py"])

btn = Button(window, text="circle", command=clicked)
btn.grid(column=70, row=50)

def clicked():
    from subprocess import call
    call(["python", "star.py"])

btn1 = Button(window, text="star", command=clicked)
btn1.grid(column=90, row=70)

def clicked():
    from subprocess import call
    call(["python", "rectangle.py"])

btn1 = Button(window, text="rectangle", command=clicked)
btn1.grid(column=110, row=90)

def clicked():
    from subprocess import call
    call(["python", "triangle.py"])

btn1 = Button(window, text="triangle", command=clicked)
btn1.grid(column=130, row=110)

window.mainloop()


import json
import cython  # type: ignore
from collections import defaultdict, Counter

from typing import (
    DefaultDict,
    Counter as tCounter,
    Tuple,
    List,
    Dict
)
from .codfreq_types import (
    NAPos,
    NAChar,
    Profile,
    FragmentConfig,
    SequenceAssemblyConfig,
    NARegionConfig,
    RegionalConsensus
)
from .posnas import get_posnas_in_genome_region, PosNA

from .filename_helper import name_bamfile

GAP = ord(b'N')
ENCODING = 'UTF-8'

@cython.cfunc
@cython.inline
@cython.returns(dict)
def make_consensus(
    nacons_lookup: Dict[Tuple[NAPos, int], NAChar],
    region: NARegionConfig
) -> RegionalConsensus:
    refpos: NAPos
    idx: int

    name: str = region['name']
    refpos_start: NAPos = region['refStart']
    refpos_end: NAPos = region['refEnd']
    consarr: bytearray = bytearray()

    for refpos in range(refpos_start, refpos_end + 1):
        idx = 0
        while True:
            try:
                na = nacons_lookup[(refpos, idx)]
            except KeyError:
                if idx == 0:
                    consarr.append(GAP)
                break
            consarr.append(na)
            idx += 1
    return {
        'name': name,
        'refStart': refpos_start,
        'refEnd': refpos_end,
        'consensus': consarr.decode(ENCODING)
    }

def sam2consensus(
    sampath: str,
    region: NARegionConfig,
) -> RegionalConsensus:

    name: str
    refpos_start: NAPos
    refpos_end: NAPos
    consarr: bytearray
    posnas: List[PosNA]
    refpos: NAPos
    idx: int
    na: NAChar

    nafreqs: DefaultDict[
        Tuple[NAPos, int],
        tCounter[NAChar]
    ] = defaultdict(Counter)

    for _, posnas in get_posnas_in_genome_region(
        sampath,
        ref_name=region['fromFragment'],
        ref_start=region['refStart'],
        ref_end=region['refEnd']
    ):
        for refpos, idx, na, _ in posnas:
            nafreqs[(refpos, idx)][na] += 1

    nacons_with_count_lookup: Dict[Tuple[NAPos, int], Tuple[NAChar, int]] = {
        pos: nas.most_common(1)[0]
        for pos, nas in nafreqs.items()
    }
    nacons_lookup: Dict[Tuple[NAPos, int], NAChar] = {
        (pos, idx): na
        for (pos, idx), (na, count) in nacons_with_count_lookup.items()
        if idx == 0 or
        # insertion should only be kept when it's at least as 50% common as the
        # prior nucleotide
        count * 2 > nacons_with_count_lookup.get((pos, 0), ('.', 0))[1]
    }

    r: RegionalConsensus = make_consensus(nacons_lookup, region)
    return r

@cython.ccall
@cython.returns(cython.void)
def create_untrans_region_consensus(
    seqname: str,
    profile: Profile
) -> None:

    refname: str
    samfile: str
    fragment: FragmentConfig
    region: SequenceAssemblyConfig

    results: List[RegionalConsensus] = []
    for fragment in profile['fragmentConfig']:
        if 'fromFragment' in fragment:
            continue
        refname = fragment['fragmentName']
        samfile = name_bamfile(seqname, refname, is_trimmed=True)
        for region in profile['sequenceAssemblyConfig']:
            if region.get('fromFragment') != refname:
                continue
            if 'name' not in region or region['name'] is None:
                continue
            if 'fromFragment' not in region or region['fromFragment'] is None:
                continue
            if 'refStart' not in region or region['refStart'] is None:
                continue
            if 'refEnd' not in region or region['refEnd'] is None:
                continue

            results.append(sam2consensus(
                samfile,
                {
                    'name': region['name'],
                    'fromFragment': region['fromFragment'],
                    'refStart': region['refStart'],
                    'refEnd': region['refEnd']
                }
            ))
    with open('{}.untrans.json'.format(seqname), 'w') as fp:
        json.dump(results, fp)


import asyncio

from pyrogram import filters

# from NekoRobot import DRAGONS, pbot as app

import NekoRobot.modules.mongo.dalc_mongo as sql
from NekoRobot.modules.disable import (
    DisableAbleCommandHandler,
    DisableAbleMessageHandler,
)
from NekoRobot import pgram as app
from telegram.ext import CallbackContext, Filters, MessageHandler
from telegram import MessageEntity, Update
from NekoRobot.ex_plugins.dbfunctions import(
    alpha_to_int,
    get_karma,
    # get_karmas,
    int_to_alpha,
    update_karma,
)

from NekoRobot.pyro.errors import capture_err
from NekoRobot.utils.filter_groups import karma_negative_group, karma_positive_group

regex_upvote = r"^((?i)\+|\+\+|\+1|thx|thanx|thanks|pro|cool|good|pro|pero|op|nice|noice|best|uwu|owo|right|correct|peru|piro|👍|\+100)$"
regex_downvote = r"^(\-|\-\-|\-1|👎|noob|baka|idiot|chutiya|nub|noob|wrong|incorrect|chaprii|chapri|weak|\-100)$"

@app.on_message(
  filters.text
  & filters.group
  & filters.incoming
  & filters.reply
  & filters.regex(regex_upvote)
  & ~filters.via_bot
  & ~filters.bot,
  group=karma_positive_group,
)
async def upvote(_,message):
#   chat_id = message.chat.id
#   is_karma = sql.is_karma(chat_id)
#   if not is_karma:
#         return
  if not message.reply_to_message.from_user:
        return
  if not message.from_user:
        return
  if message.reply_to_message.from_user.id == message.from_user.id:
        return
  user_id = message.reply_to_message.from_user.id
  user_mention = message.reply_to_message.from_user.mention
  current_karma = await get_karma(await int_to_alpha(user_id)
    )
  if current_karma:
        current_karma = current_karma['karma']
        karma = current_karma + 100
  else:
        karma = 100
  new_karma = {"karma": karma}
  await update_karma(await int_to_alpha(user_id), new_karma
    )
  await message.reply_text(
        f"Waku Waku! Anya added 100 dalcs to {user_mention}'s Wallet\nCurrent Dalcs: {karma}Đ"
    )

@app.on_message(
    filters.text
    & filters.group
    & filters.incoming
    & filters.reply
    & filters.regex(regex_downvote)
    & ~filters.via_bot
    & ~filters.bot,
    group=karma_negative_group,
)

async def downvote(_, message):
    # chat_id = message.chat.id
    # is_karma = sql.is_karma(chat_id)
    # if not is_karma:
    #     return
    if not message.reply_to_message.from_user:
        return
    if not message.from_user:
        return
    if message.reply_to_message.from_user.id == message.from_user.id:
        return

    user_id = message.reply_to_message.from_user.id
    user_mention = message.reply_to_message.from_user.mention
    current_karma = await get_karma(await int_to_alpha(user_id))
    if current_karma:
        current_karma = current_karma["karma"]
        karma = current_karma - 100
    else:
        karma = 100
    new_karma = {"karma": karma}
    await update_karma(await int_to_alpha(user_id), new_karma)
    await message.reply_text(
        f"Anya is Sad :( took 100 dalcs from {user_mention}'s Wallet\nCurrent Dalcs: {karma}Đ"
    )

@app.on_message(filters.command("dalcstat") & filters.group)
async def karma(_, message):
    # chat_id = message.chat.id
    if not message.reply_to_message:
        m = await message.reply_text("Matte! Anya will ask chichi for wallets of this chat...")
        # karma = await get_karmas(chat_id)
        # if not karma:
        #     await m.edit("Anya is Sad. No Dalcs in DB for this chat.")
        #     return
        msg = f"Dalc list of {message.chat.title}:- \n"
        limit = 0
        karma_dicc = {}
        for i in karma:
            user_id = await alpha_to_int(i)
            user_karma = karma[i]["karma"]
            karma_dicc[str(user_id)] = user_karma
            karma_arranged = dict(
                sorted(karma_dicc.items(), key=lambda item: item[1], reverse=True)
            )
        if not karma_dicc:
            await m.edit("Anya is Sad. No Dalcs in DB for this chat.")
            return
        for user_idd, karma_count in karma_arranged.items():
            if limit > 9:
                break
            try:
                user = await app.get_users(int(user_idd))
                await asyncio.sleep(0.8)
            except Exception:
                continue
            first_name = user.first_name
            if not first_name:
                continue
            username = user.username
            msg += f"{karma_count}  {(first_name[0:12] + '...') if len(first_name) > 12 else first_name}  {('@' + username) if username else user_idd}\n"
            limit += 1
        await m.edit(msg)
    else:
        user_id = message.reply_to_message.from_user.id
        karma = await get_karma(await int_to_alpha(user_id))
        karma = karma["karma"] if karma else 0
        await message.reply_text(f"Total Dalcs: {karma} Đ")

# @app.on_message(filters.command("dalcstat") & filters.group)
# async def mywallet(_, message):
#     chat_id = message.chat.id
#     user_id = message.reply_to_message.from_user.id
#     karma = await get_karma(chat_id, await int_to_alpha(user_id))
#     karma = karma["karma"] if karma else 0
#     await message.reply_text(f"Total Dalcs: {karma}Đ")

# KARMA_REGEX_HANDLER = DisableAbleMessageHandler(
#       filters.text
#     & filters.group
#     & filters.incoming
#     & filters.reply
#     & filters.regex(regex_downvote)
#     & ~filters.via_bot
#     & ~filters.bot,
#     group=karma_negative_group
# )

 # ❍ Reply to any meassage with (`+, +1, thx, thanx, thanks, pro, cool, good,pro, pero, op, nice, noice, best, uwu, owo, right, correct, peru, piro`, 👍) to increse karma of user.
 # ❍ Reply to any meassage with (`-, -1, 👎, noob, baka, idiot, chutiya, nub, noob, wrong, incorrect, chaprii, chapri, weak`) to decrease karma of user.

__mod_name__ = "Currency System"

__help__ = """
Currency System[Dalc(Đ)]
 ❍ `/dalc` : To enable / disable Currency system
 ❍ `/dalcstat`: Get stats of waller for your chat
 ❍ Reply message with (`+, +100) to add dalcs to there Wallet.
 ❍ Reply message with (`-, -100`) to snitch dalcs from there Wallet.
"""


nome = input('Digite o seu nome: ')
altura = float(input('Digite sua altura '))
peso = float(input('Digite seu peso '))
imc = peso / (altura * altura)
if imc <18.5:
    print("{} está Abaixo do peso".format(nome))
elif imc <25:
    print('{} está Peso Ideal'.format(nome))
elif imc <30:
    print('{} está com Sobrepeso'.format(nome))
elif imc <40:
    print('{} está Obeso'.format(nome))
else:
    print('{} Está com obesidade morbida'.format(nome))
print('Obrigado por se consultar com a calculadora IMC')