#!/usr/bin/env python3
"""
Adam optimization, mini-batch gradient descent, learning rate decay,
and batch normalization neural network model in tensorflow
"""
import tensorflow as tf
import numpy as np

def create_layer(prev, n, activation):
    """
    He et al initialization
    :param prev: is the tensor output of the previous layer
    :param n: is the number of nodes in the layer to create
    :param activation: is the activation function that the layer should use
    :return: the tensor output of the layer
    """
    init = tf.contrib.layers.variance_scaling_initializer(mode="FAN_AVG")
    layer = tf.layers.Dense(units=n, activation=activation,
                            kernel_initializer=init, name="layer")
    return layer(prev)

def create_batch_norm_layer(prev, n, activation):
    """
    creates a batch normalization layer for a neural network in tensorflow
    :param prev: is the activated output of the previous layer
    :param n: is the number of nodes in the layer to be created
    :param activation: is the activation function to be used on the output
    :return: a tensor of the activated output for the layer
    """
    # Layers
    init = tf.contrib.layers.variance_scaling_initializer(mode="FAN_AVG")
    output = tf.layers.Dense(units=n, kernel_initializer=init)
    Z = output(prev)

    # Gamma and Beta initialization
    gamma = tf.Variable(initial_value=tf.constant(1.0, shape=[n]),
                        name="gamma", trainable=True)
    beta = tf.Variable(initial_value=tf.constant(0.0, shape=[n]),
                       name="beta", trainable=True)

    # Batch normalization
    mean, var = tf.nn.moments(Z, axes=0)  # return tensor mean, variance
    b_norm = tf.nn.batch_normalization(Z, mean, var, offset=beta, scale=gamma,
                                       variance_epsilon=1e-8)
    if activation is None:
        return b_norm
    else:
        return activation(b_norm)

def forward_prop(x, layer_sizes=[], activations=[]):
    """
    Creates the forward propagation graph for the neural network
    :param x: is the placeholder for the input data
    :param layer_sizes: is a list containing the number of nodes in each layer
    of the network
    :param activations: is a list containing the activation functions for each
    layer of the network
    :return: the prediction of the network in tensor form
    """

    prediction = create_batch_norm_layer(x, layer_sizes[0], activations[0])
    for layer in range(1, len(layer_sizes)):
        if layer != len(layer_sizes) - 1:
            prediction = create_batch_norm_layer(prediction, layer_sizes[
                layer], activations[layer])
        else:
            prediction = create_layer(prediction, layer_sizes[layer],
                                      activations[layer])
    return prediction

def calculate_accuracy(y, y_pred):
    """
    calculates the accuracy of a prediction
    :param y: is a placeholder for the labels of the input data
    :param y_pred: is a tensor containing the network’s predictions
    :return: a tensor containing the decimal accuracy of the prediction
    """
    prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_pred, 1))
    return tf.reduce_mean(tf.cast(prediction, tf.float32))

def calculate_loss(y, y_pred):
    """
    a function that calculates the loss of a prediction
    :param y: a placeholders with the right labels of the input data
    :param y_pred: tensor containing the network's predictions
    :return: a tensor containing the loss of a prediction
    """
    return tf.losses.softmax_cross_entropy(y, y_pred)

def shuffle_data(X, Y):
    """
    shuffles the data points in two matrices the same way
    :param X:  is the first numpy.ndarray of shape (m, nx) to shuffle
            m is the number of data points
            nx is the number of features in X
    :param Y: is the second numpy.ndarray of shape (m, ny) to shuffle
            m is the same number of data points as in X
            ny is the number of features in Y

    :return: the shuffled X and Y matrices
    """
    m = X.shape[0]
    permutation = list(np.random.permutation(m))
    shuffled_X = X[permutation]
    shuffled_Y = Y[permutation]
    return shuffled_X, shuffled_Y

def learning_rate_decay(alpha, decay_rate, global_step, decay_step):
    """
    creates learning rate decay operation in tensorflow with inverse time decay
    :param alpha: is the original learning rate
    :param decay_rate: weight used determine the rate at which alpha will decay
    :param global_step: number of passes of gradient descent that have elapsed
    :param decay_step: number of passes of gradient descent that should
    occur before alpha is decayed further
    :return: the learning rate decay operation
    """
    return tf.train.inverse_time_decay(alpha, global_step, decay_step,
                                       decay_rate, staircase=True)

def create_Adam_op(loss, alpha, beta1, beta2, epsilon):
    """
    creates the training operation for a neural network in tensorflow using
    the Adam optimization algorithm
    :param loss: is the loss of the network
    :param alpha: is the learning rate
    :param beta1: is the weight used for the first moment
    :param beta2: is the weight used for the second moment
    :param epsilon: is a small number to avoid division by zero
    :return: the Adam optimization operation
    """
    return tf.train.AdamOptimizer(alpha, beta1, beta2, epsilon).minimize(loss)

def create_placeholders(nx, classes):
    """
    return two placeholders
    :param nx: the number of feature columns in our data
    :param classes: the number of classes in our classifier
    :return: placeholders named x and y, respectively
    """
    x = tf.placeholder("float", [None, nx], name="x")
    y = tf.placeholder("float", [None, classes], name="y")
    return x, y

def model(Data_train, Data_valid, layers, activations, alpha=0.001, beta1=0.9,
          beta2=0.999, epsilon=1e-8, decay_rate=1, batch_size=32,
          epochs=5, save_path='/tmp/model.ckpt'):
    """
    Builds, trains, and saves a neural network model in tensorflow using
    Adam optimization, mini-batch gradient descent, learning rate decay,
    and batch normalization
    :param Data_train: tuple containing the training inputs and training labels
    :param Data_valid: tuple containing the validation inputs and labels
    :param layers: list containing number of nodes in each layer of the network
    :param activations: list containing the activation functions
    used for each layer of the network
    :param alpha: is the learning rate
    :param beta1: weight for the first moment of Adam Optimization
    :param beta2: weight for the second moment of Adam Optimizatio
    :param epsilon: small number used to avoid division by zero
    :param decay_rate: decay rate for inverse time decay of the learning rate
    :param batch_size: number of data points that should be in a mini-batch
    :param epochs: number of times training should pass through whole dataset
    :param save_path: is the path where the model should be saved to
    :return: the path where the model was saved
    """

    # Data(X,Y); X=(50000,784) Y=(50000,10)
    nx = Data_train[0].shape[1]
    classes = Data_train[1].shape[1]

    (X_train, Y_train) = Data_train
    (X_valid, Y_valid) = Data_valid

    # first create a placeholder X, Y
    x, y = create_placeholders(nx, classes)
    tf.add_to_collection("x", x)
    tf.add_to_collection("y", y)

    # we need to print loss and accuracy, for that I need Y_hat

    y_pred = forward_prop(x, layers, activations)
    tf.add_to_collection("y_pred", y_pred)

    accuracy = calculate_accuracy(y, y_pred)
    tf.add_to_collection("accuracy", accuracy)

    loss = calculate_loss(y, y_pred)
    tf.add_to_collection("loss", loss)
    # apply learning rate decay to test adam
    global_step = tf.Variable(0)
    alpha_d = learning_rate_decay(alpha, decay_rate, global_step, 1)

    train_op = create_Adam_op(loss, alpha_d, beta1, beta2, epsilon)
    tf.add_to_collection("train_op", train_op)

    init = tf.global_variables_initializer()
    saver = tf.train.Saver()

    # initialize session and use mini batch gradient descent
    with tf.Session() as sess:
        sess.run(init)
        train = {x: X_train, y: Y_train}
        valid = {x: X_valid, y: Y_valid}
        m = X_train.shape[0]
        # mini batch definition
        if m % batch_size == 0:
            complete_minibatches = m // batch_size
        else:
            complete_minibatches = m // batch_size + 1

        for i in range(epochs + 1):
            cost_t = sess.run(loss, feed_dict=train)
            acc_t = sess.run(accuracy, feed_dict=train)
            cost_v = sess.run(loss, feed_dict=valid)
            acc_v = sess.run(accuracy, feed_dict=valid)

            print("After {} epochs:".format(i))
            print("\tTraining Cost: {}".format(cost_t))
            print("\tTraining Accuracy: {}".format(acc_t))
            print("\tValidation Cost: {}".format(cost_v))
            print("\tValidation Accuracy: {}".format(acc_v))

            if i < epochs:  # number of epochs to do
                shuffled_X, shuffled_Y = shuffle_data(X_train, Y_train)
                for k in range(complete_minibatches):  # mini batches
                    start = k * batch_size  # ex: batch_size=10, start:0,10,20
                    end = (k + 1) * batch_size  # same:10,20,30
                    if end > m:  # end case, goes until m otherwise out range
                        end = m
                    mini_batch_X = shuffled_X[start:end]
                    mini_batch_Y = shuffled_Y[start:end]
                    new_train = {x: mini_batch_X, y: mini_batch_Y}
                    sess.run(train_op, feed_dict=new_train)
                    if (k + 1) % 100 == 0 and k != 0:
                        mb_c, mb_a = sess.run([loss, accuracy], new_train)
                        print("\tStep {}:".format(k + 1))
                        print("\t\tCost: {}".format(mb_c))
                        print("\t\tAccuracy: {}".format(mb_a))
            sess.run(tf.assign(global_step, global_step + 1))
        return saver.save(sess, save_path)


import numpy as np
import pandas as pd
from skimage.morphology import ball,erosion
from sklearn.neighbors import NearestNeighbors

def res_over_dapi_erosion(num_dims, spots, dapi_binary, method='clustermap', minus1 = False):

    '''
    Erase cells that do not overlap with DAPI signals

    params :    - spots (dataframe) = spatial locations and gene identities
                - dapi_binary (ndarray) = binarized DAPI image
                - method (str) = name of column containing the results
                                 of segmentation
                - minus1 (bool) = if spots' locations start at 1 instead of 0

    returns :   None
    '''

    dapi_binary_eroded = dapi_binary
    cell_list = np.unique(spots[method])[1:]
    if minus1:
        for cell in cell_list:
            if num_dims==3:
                spots_cell = spots.loc[spots[method]==cell, ['spot_location_2', 'spot_location_1', 'spot_location_3']].to_numpy()
                number_overlap = np.sum(dapi_binary_eroded[spots_cell[:,0] - 1,spots_cell[:,1] - 1, spots_cell[:,2] - 1])
            else:
                spots_cell = spots.loc[spots[method]==cell, ['spot_location_2', 'spot_location_1']].to_numpy()
                number_overlap = np.sum(dapi_binary_eroded[spots_cell[:,0] - 1,spots_cell[:,1] - 1])
            if number_overlap ==0:
                spots.loc[spots[method]==cell, method] = -1
    else:
        for cell in cell_list:
            if num_dims==3:
                spots_cell = spots.loc[spots[method]==cell, ['spot_location_2', 'spot_location_1', 'spot_location_3']].to_numpy()
                number_overlap = np.sum(dapi_binary_eroded[spots_cell[:,0]-1,spots_cell[:,1]-1, spots_cell[:,2] - 1])
            else:
                spots_cell = spots.loc[spots[method]==cell, ['spot_location_2', 'spot_location_1']].to_numpy()
                number_overlap = np.sum(dapi_binary_eroded[spots_cell[:,0]-1,spots_cell[:,1]-1])
            if number_overlap ==0:
                spots.loc[spots[method]==cell, method] = -1

def erase_small_clusters(spots, N=10,method='clustermap'):

    '''
    Erase small cells

    params :    - spots (dataframe) = dataset
                - method (str) = name of column containing the results
                                 of segmentation
                - N (int) = minimal number of spots within a cell

    returns :   None
    '''

    spots_per_cluster = spots.groupby(method).size()
    dico_corres = dict([(leid, -1) if spots_per_cluster.loc[leid]<=N else (leid, leid) for leid in spots_per_cluster.index.to_numpy()])
    spots[method] = list(map(dico_corres.get, spots[method]))


'''
This module contains the Study class,
used to launch a study session during a Jupyter notebook/lab session.
The module prepares and consumes data from the Mahir deck handlers and uses Text-Fabric
to display formatted font.

FOR THE FUTURE:
• Design a term object with callable attributes that can be populated from terms_dict.
'''

import os
from pathlib import Path
import pickle
import collections
import json
import random
import time
import math
import copy
from datetime import datetime, timedelta
from tf.app import use
from tf.fabric import Fabric
from IPython.display import clear_output, display, HTML

def safediv(a, b):
    '''Return zero in zero divisions'''
    try:
        return a/b
    except ZeroDivisionError:
        return 0

def loadStudy(vocab_json, tf_app='bhsa'):
        """Determine how to load a study session"""

        vocab_json = Path(vocab_json)

        # check for existing saves
        savefile = next(Path().glob(f'{vocab_json.stem}.save'), None)
        # check for expiration of save
        # if expired, delete the save (!)
        # this is a little extra motivation to finish each day
        if savefile is not None:
            lastmod = datetime.fromtimestamp(os.path.getmtime(savefile))
            elapsed = ((datetime.now() - lastmod).total_seconds() / 60) / 60

            # disable file deletions for now
            if False: #elapsed > 15:
                print('\nOld session found but expired! Deleting it!\n')
                savefile.unlink() # bye bye :)

        # load the save
        if savefile is not None and savefile.exists():
            with open(savefile, 'rb') as infile:
                savedata = pickle.load(infile)
            return Study(
                vocab_json,
                tf_app,
                set_data=savedata['set_data'],
                session_data=savedata['session_data'],
                resume_time=savedata['resume_time'],
                term_n=savedata['term_n'],
                pause_times=savedata['pause_times'],
            )

        # load new session
        else:
            return Study(vocab_json, tf_app)

class Study:
    '''
    Prepares and consumes data from Mahir
    and formats it for use in a Jupyter notebook.
    '''

    def __init__(self, vocab_json, tf_app='bhsa',
                 set_data=None, session_data=None,
                 resume_time=False, term_n=0,
                 pause_times=[]):

        # set meta data for study loop (for saves)
        self.session_data = session_data
        self.set_data = set_data
        self.term_n = term_n
        self.pause_times = pause_times

        self.tf_app = tf_app
        self.fstem = vocab_json.stem # for save names

        # load set data
        if not set_data:
            with open(vocab_json, encoding='utf8') as setfile:
                set_data = json.load(setfile)
                self.set_data = set_data

        # retrieve TF app data
        appdata = set_data['app_data']
        app = appdata['app']
        datversion = appdata['version']
        self.glossfeat = appdata['gloss_feature']
        self.freqfeat = appdata['freq_feature']
        self.wordtype = appdata['wordtype']
        self.context = appdata['context']

        # load the app
        print('preparing TF...')
        self.TF = use(app, version=datversion, silent=True)
        self.F, self.T, self.L = self.TF.api.F, self.TF.api.T, self.TF.api.L

        # prepare for run, check cycle length
        run = self.check_end_cycle(set_data)
        if not run:
            self.save_file(set_data, vocab_json)
            raise Exception('EXIT PROGRAM INITIATED; FILE SHUFFLED AND SAVED')

        # build the study set, prep data for study session
        if session_data is None:
            self.session_data = Session(set_data)  # build session data
        self.vocab_json = vocab_json

        if resume_time:
            print(f'\nSession is resumed from {resume_time}.\n')

        # preliminary session report
        deck_stats = self.session_data.deck_stats
        print(set_data['name'], 'ready for study.')
        print(f"this is session {set_data['cycle_data']['total_sessions']+1}:")
        for score, stat in deck_stats.items():
            print(f'score {score}: {stat} terms')
        print(f'total: {sum(deck_stats.values())}')

    def learn(self):
        '''
        Runs a study session with the user.
        '''
        print('beginning study session...')
        self.start_time = datetime.now() # to be filled in on first instructions

        def pause_time():
            """Pause the timer"""
            this_duration = datetime.now() - self.start_time
            self.pause_times.append(this_duration)
            self.start_time = None # reset clock

        deck = self.session_data.deck
        terms_dict = self.set_data['terms_dict']

        # make shortform TF methods / data names
        glossfeat, freqfeat, wordtype, context = self.glossfeat, self.freqfeat, self.wordtype, self.context
        F, L, T, Fs = self.F, self.L, self.T, self.TF.api.Fs

        # allow toggling of progress indicator
        show_progress = True

        # begin UI loop
        term_n = self.term_n
        while True:

            # get term data
            term_ID = deck[term_n]
            term_text = terms_dict[term_ID]['term']
            gloss = terms_dict[term_ID]['gloss']
            score = terms_dict[term_ID]['score']
            missed = terms_dict[term_ID]['stats']['missed']

            # -- assemble and select examples (cycle through lexemes) --
            lexs = terms_dict[term_ID]['source_lexemes']
            ex_lex = random.choice(lexs)
            ex_instance = random.choice(L.d(ex_lex, wordtype))
            ex_passage = L.u(ex_instance, context)[0]
            std_glosses = [(lx, Fs(glossfeat).v(lx), Fs(freqfeat).v(lx))
                               for lx in lexs]

            # build parse string for BHSA app
            if self.TF.appName == 'bhsa':
                gender = F.gn.v(ex_instance)
                number = F.nu.v(ex_instance)
                if F.pdp.v(ex_instance) == 'verb':
                    person = F.ps.v(ex_instance)
                    stem = F.vs.v(ex_instance)
                    tense = F.vt.v(ex_instance)
                    parse_string = f'{stem}.{tense}.{person}.{gender}.{number}'
                else:
                    state = F.st.v(ex_instance)
                    parse_string = f'{gender}.{number}.{state}'

            # -- display passage prompt and score box --
            clear_output()

            if show_progress:
                display(
                    HTML(f'{term_n+1}/{len(deck)}')
                )

            highlights = {'0': 'pink'}
            highlight = highlights.get(score, 'lightgreen') # default to light green

            passage = self.TF.sectionStrFromNode(ex_passage)
            display(HTML(
                f'{passage}'))
            self.TF.plain(ex_passage, highlights={ex_instance: highlight})

            # -- get user input --
            while True:
                user_instruct = self.good_choice(
                    {'', ',', '.', 'q', 'c',
                     'e', 'l', '>', '<', 'p',
                     'save', 'hprog'}
                    , ask='', allowNumber=True)

                # start timer upon user instruct if not already
                if self.start_time is None:
                    self.start_time = datetime.now()

                # show term glosses and data
                if user_instruct in {''}:
                    display(HTML(
                        f'{term_text}'))
                    display(HTML(
                        f'{gloss} '))

                    # show parse string for BHSA app
                    if self.TF.appName == 'bhsa':
                        display(HTML(
                            f'{parse_string} ')
                        )

                    display(HTML(
                        f'{score}'))
                    display(HTML(
                        f'{std_glosses}'))
                    display(HTML(
                        f'missed: {missed}'))

                # score term
                elif user_instruct.isnumeric():

                    if user_instruct not in self.set_data['term_queues']:
                        confirm = self.good_choice({'y','n'}, ask=f'Add new score [{user_instruct}]?')
                        if confirm == 'y':
                            pass
                        else:
                            break

                    terms_dict[term_ID]['score'] = user_instruct
                    term_n += 1
                    break

                # move one term back/forward
                elif user_instruct in {',', '.'}:
                    if user_instruct == ',':
                        if term_n != 0:
                            term_n -= 1
                    elif user_instruct == '.':
                        if term_n != len(deck):
                            term_n += 1
                    break

                # skip to beginning or end of deck
                elif user_instruct in {'>', '<'}:
                    if user_instruct == '>':
                        term_n = len(deck)
                    elif user_instruct == '<':
                        term_n = 0
                    break

                # get a different word context
                elif user_instruct == 'c':
                    break

                # edit term gloss on the fly
                elif user_instruct == 'e':
                    new_def = self.good_choice(
                        set(), ask=f'edit def [{gloss}]')
                    terms_dict[term_ID]['gloss'] = new_def
                    break

                # edit lexeme nodes on the fly
                elif user_instruct == 'l':

                    # confirm lexeme edit
                    confirm = self.good_choice({'y','n'}, ask='Edit lex nodes?')
                    if confirm == 'n':
                        break

                    lexs = terms_dict[term_ID].get('source_lexemes', )
                    new_lexs = self.good_choice(
                        set(), ask=f'edit lex nodes {lexs}')
                    new_lexs = [int(l.strip()) for l in new_lexs.split(',')]
                    terms_dict[term_ID]['source_lexemes'] = new_lexs
                    break

                # pause timer
                elif user_instruct == 'p':
                    pause_time()
                    self.save_session(term_n) # save a back up just in case
                    print('Session time paused...')

                # allow for saving sessions
                elif user_instruct == 'save':
                    pause_time()
                    self.save_session(term_n)
                    print('Session saved for 15 hours...')
                    print(f'\telapsed: {sum(self.pause_times, timedelta())}')
                    return

                # user quit
                elif user_instruct == 'q':
                    confirm = self.good_choice({'y', 'n'}, ask='confirm quit?') # double check
                    if confirm == 'y':
                        raise Exception('Quit initiated. Nothing saved.')
                    else:
                        break

                # toggle progress indicator
                elif user_instruct == 'hprog':
                    show_progress = not show_progress
                    break

            # launch end program sequence
            if term_n > len(deck)-1:
                clear_output()
                ask_end = self.good_choice(
                    {'y', 'n'}, 'session is complete, quit now?')

                if ask_end == 'y':
                    times = [datetime.now() - self.start_time] + self.pause_times
                    self.finalize_session(times)
                    break

                elif ask_end == 'n':
                    term_n -= 1

        clear_output()
        print('The following scores were changed ')
        for change, amount in self.set_data['stats'][-1]['changes'].items():
            print(change, '\t\t', amount)
        print('\nduration: ', self.set_data['stats'][-1]['duration'])
        print('\nseconds per term:', self.set_data['stats'][-1]['secs_per_term'])

    def save_session(self, term_n):
        """Save a session for later."""
        savedata = {
            'set_data': self.set_data,
            'session_data': self.session_data,
            'resume_time': str(datetime.now()),
            'pause_times': self.pause_times,
            'term_n': term_n,
        }
        with open(f'{self.fstem}.save', 'wb') as outfile:
            pickle.dump(savedata, outfile)

    def clean_session_saves(self):
        """Checks for saves and removes them"""
        savefile = next(Path().glob(f'{self.fstem}.save'), None)
        if savefile is not None and savefile.exists():
            savefile.unlink()

    def finalize_session(self, times):
        '''
        Updates and saves session data and stats.
        '''

        # log session stats
        session_stats = {}
        duration = sum(times, timedelta())
        secs_per_term = round(duration.total_seconds() / len(self.session_data.deck), 2) # average seconds per term
        session_stats['date'] = str(datetime.now())
        session_stats['duration'] = str(duration)
        session_stats['secs_per_term'] = secs_per_term
        session_stats['deck'] = self.session_data.deck_stats
        session_stats['cycle'] = self.set_data['cycle_data']['ncycle']
        for term in self.session_data.deck:
            # count term as seen
            self.set_data['terms_dict'][term]['stats']['seen'] += 1

        # reset queues based on changed scores & update stats
        session_stats['changes'] = collections.Counter()
        self.add_new_scores()
        self.update_queues(session_stats['changes'])
        # track final score count at end of session
        session_stats['score_counts'] = dict((score, len(queue))
                                             for score, queue in self.set_data['term_queues'].items())

        # update set data
        self.set_data['cycle_data']['total_sessions'] += 1
        self.set_data['stats'].append(session_stats)

        # save new data
        self.save_file(self.set_data, self.vocab_json)
        self.clean_session_saves()

    def update_queues(self, stats_dict):
        '''
        Adjusts term queues to the terms_dict when a term is changed to a new score.
        Terms are removed from their old queue and added to the new ones.
        All terms go to the back of their respective queues.
        '''

        term_queues = self.set_data['term_queues']
        terms_dict = self.set_data['terms_dict']
        # make buffer queues for iteration
        # prevents altering original during iteration
        buffer_queues = copy.deepcopy(term_queues)

        # make adjustments
        for score, term_queue in buffer_queues.items():
            for term in term_queue:

                cur_score = terms_dict[term]['score']

                # compare old/new score, change if needed
                if score != cur_score:

                    # check for certain term changes
                    isdowngrade = int(cur_score) < int(score)
                    change = f'{cur_score}<-{score}' if isdowngrade else f'{score}->{cur_score}'
                    missed = (
                        int(cur_score) < int(score)
                        and int(score) > 2
                    )
                    learned = (
                        int(score) < 3
                        and int(cur_score) > 2
                        and terms_dict[term]['stats']['missed'] == 0
                    )

                    # make records of missed or learned terms
                    stats_dict.update([change])
                    if missed:
                        terms_dict[term]['stats']['missed'] += 1
                    if learned:
                        terms_dict[term]['stats']['learned'] = str(datetime.now())

                    # assign new queue position
                    term_queues[score].remove(term)
                    if cur_score != '0':
                        # scores >0 go to back of queue
                        term_queues[cur_score].append(term)
                    else:
                        # score 0 goes to front of queue
                        term_queues[cur_score].insert(0, term)

                # if no change, move on
                else:
                    continue

    def check_end_cycle(self, set_data):
        '''
        Checks whether the deck is finished
        for the cycle. If so, runs a quick
        parameters reassignment session.
        '''

        run_study = True

        if safediv(set_data['cycle_data']['cycle_length'], set_data['cycle_data']['total_sessions']) == 1:
            print('cycle for this set is complete...')
            keep_same = self.good_choice(
                {'y', 'n'}, ask='keep cycle parameters the same?')

            if keep_same == 'y':
                set_data['cycle_data']['total_sessions'] = 0  # reset sessions
                set_data['cycle_data']['ncycle'] += 1

                # some scores reset at cyclic intervals (e.g. S3 and S4)
                # this config allows those scores to be reset on a modulo trigger
                for score, configdata in set_data['scoreconfig'].items():
                    ncycle = set_data['cycle_data']['ncycle']
                    nreset = configdata['nreset']
                    shuffle = configdata['shuffle']
                    if ncycle % nreset == 0:
                        if shuffle == 'yes':
                            random.shuffle(set_data['term_queues'][score])
                        set_data['cycle_data']['score_starts'][score] = len(
                            set_data['term_queues'][score])

            elif keep_same == 'n':
                print('You must reset parameters manually...')
                run_study = False

        return run_study

    def add_new_scores(self):
        '''
        Adds any new scores to the vocab set
        by checking term scores against term queues and score config.
        '''
        queues = self.set_data['term_queues']
        score_configs = self.set_data['scoreconfig']
        terms_dict = self.set_data['terms_dict']

        # add new scores and terms to term queues
        for termID, tdata in terms_dict.items():
            score = tdata['score']
            if score not in queues:
                if score not in score_configs:
                    print(
                        f'CAUTION: score {score} is not configured! (found on term {termID})')
                    print('NB: a new score queue has been generated!')
                queues[score] = []
                self.set_data['cycle_data']['score_starts'][score] = 0

    def good_choice(self, good_choices, ask='', allowNumber=False):
        '''
        Gathers and checks a user's input against the
        allowed choices. Runs loop until valid choice provided.
        '''
        choice = input(ask)

        if allowNumber and choice.isnumeric():  # allow arbitrary score choices
            good_choices.add(choice)

        while (not {choice} & good_choices) and (good_choices):
            print(f'Invalid. Choose from {good_choices}')
            choice = input(ask)

        return choice

    def save_file(self, set_data, file):
        '''
        Save json set dat with proper encoding
        and indentation.
        '''
        with open(file, 'w', encoding='utf8') as outfile:
            json.dump(set_data, outfile, indent=1, ensure_ascii=False)

class Session:

    '''
    Constructs a study set for a session that contains words scored 0-3.
    term_queues is a dict with scores as keys, lists as values containing term IDs.
    The quota for term 0 (new terms) is set by the user in the new_quota key of cycle_data.
    The cycle_len is the number of days in a full review cycle that class should calculate.

    The key to buildDeck is the term queue.
    The term queue is a list of term IDs of a given score.
    These lists are modified while a deck is constructed.
    When class adds terms to a deck, it also moves them to the end of their queue (with list.pop(0)).
    The modified lists are then returned (along with the deck) to be used for the next study session.
    The cycle is repeated in the subsequent session.
    '''

    def __init__(self, set_data):

        # grab set data
        term_queues = set_data['term_queues']
        new_min = set_data['cycle_data']['new_quota']
        cycle_len = set_data['cycle_data']['cycle_length']
        nsession = set_data['cycle_data']['total_sessions']
        # sum of scores at start of the cycle
        s_starts = set_data['cycle_data']['score_starts']
        # sum of all scores by this session
        s_counts = dict((score, len(terms))
                        for score, terms in term_queues.items())

        # calculate daily set quotas, NB math.ceil rounds up^
        # score 4-5 formula optimizes with decimal issues in Python
        # formula is: int(round(((nterms/nsessions/nreset)*(NthSession-1))-int((nterms/nsessions/nreset)*(NthSession-1)) + (nterms/nsessions/nreset), 2))

        score2quota = {
            # s6 seen every 8 cycles
            '6': int(round(((s_starts['6']/cycle_len/8)*(nsession-1))-int((s_starts['6']/cycle_len/8)*(nsession-1))
              + (s_starts['6']/cycle_len/8), 2)) if s_counts.get('6', 0) else 0,
            # s5 seen every 4 cycles
            '5': int(round(((s_starts['5']/cycle_len/4)*(nsession-1))-int((s_starts['5']/cycle_len/4)*(nsession-1))
                          + (s_starts['5']/cycle_len/4), 2)) if s_counts.get('5', 0) else 0,
            # s4 seen every 2 cycles
            '4': int(round(((s_starts['4']/cycle_len/2)*(nsession-1))-int((s_starts['4']/cycle_len/2)*(nsession-1))
                          + (s_starts['4']/cycle_len/2), 2)) if s_counts.get('4', 0) else 0,
            # s3 seen every cycle
            '3': math.ceil(s_starts['3'] / cycle_len) if s_counts.get('3', 0) else 0,
            # s2 seen every 4 sessions
            '2': math.ceil(s_counts['2'] / 4) if s_counts.get('2', 0) else 0,
            # s1 seen ever other session
            '1': math.ceil(s_counts['1'] / 2) if s_counts.get('1', 0) else 0,
            # s0 set by user
            '0': new_min
        }

        # construct a study deck and keep stats
        deck = []

        deck_stats = collections.Counter()

        # add quotas from scores and advance known queues
        for score, quota in score2quota.items():
            for i in range(0, quota):

                # stop if no more terms
                if len(term_queues[score]) < i+1:
                    break

                # add new terms to deck
                # move known terms to back of their queues
                if score != '0':
                    deck.append(term_queues[score][0])
                    term_queues[score].append(term_queues[score].pop(0))

                # score 0 selected differently; their queue is not advanced
                else:
                    deck.append(term_queues[score][i])

                # log count for statistics tracking
                deck_stats.update([score])

        # shuffle deck data
        random.shuffle(deck)

        # make session data available to class
        self.deck = deck
        self.deck_stats = deck_stats
        self.term_queues = term_queues


from django.urls import path
from apps.producto.views import index, CrearProducto, ConsultarProducto, EditarProducto, inicio

urlpatterns = [
 path('', index),
 path('CrearProducto/', CrearProducto),
 path('ConsultarProducto/', ConsultarProducto),
 path('EditarProducto/<id_prod>', EditarProducto, name = 'EditarProducto'),
 path('Inicio/', inicio)
]


from abc import abstractmethod
from functools import lru_cache

import torch

from torch_mist.estimators.base import MIEstimator
from torch_mist.estimators.discriminative.base import DiscriminativeMIEstimator
from torch_mist.utils.freeze import is_trainable

class HybridMIEstimator(DiscriminativeMIEstimator):
    def __init__(
        self,
        generative_estimator: MIEstimator,
        discriminative_estimator: DiscriminativeMIEstimator,
    ):
        super().__init__(
            critic=discriminative_estimator.critic,
            neg_samples=discriminative_estimator.neg_samples,
        )

        self.discriminative_estimator = discriminative_estimator
        self.generative_estimator = generative_estimator

        informax_gradient = generative_estimator.infomax_gradient
        informax_gradient = {
            key: value and discriminative_estimator.infomax_gradient[key]
            for key, value in informax_gradient.items()
        }
        self.infomax_gradient = informax_gradient

    @lru_cache(maxsize=1)
    def unnormalized_log_ratio(
        self, x: torch.Tensor, y: torch.Tensor
    ) -> torch.Tensor:
        f = self.critic(x, y)
        assert f.ndim == y.ndim - 1

        partial_log_ratio = self.generative_estimator.log_ratio(x, y)

        assert f.shape == partial_log_ratio.shape
        return f + partial_log_ratio

    def _approx_log_partition(
        self, x: torch.Tensor, f_: torch.Tensor
    ) -> torch.Tensor:
        return self.discriminative_estimator._approx_log_partition(x, f_)

    @abstractmethod
    def sample_negatives(
        self, x: torch.Tensor, y: torch.Tensor
    ) -> torch.Tensor:
        raise NotImplementedError()

    def batch_loss(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        # Compute only the discriminative loss component
        # Note that we can skip computing the log r(y|x)/p(y)
        unnormalized_log_ratio = (
            self.discriminative_estimator.unnormalized_log_ratio(x, y)
        )
        log_partition = self.approx_log_partition(x, y)

        # The loss is the same as for generative estimators with the difference in the computation for the normalization
        # constant
        batch_loss = -(unnormalized_log_ratio - log_partition)

        # If the generative component is not trainable, there is no need to compute the log-ratio or the generative loss
        if not is_trainable(self.generative_estimator):
            batch_loss += self.generative_estimator.batch_loss(x, y)

        return batch_loss

class ReWeighedHybridMIEstimator(HybridMIEstimator):
    @lru_cache(maxsize=1)
    def approx_log_partition(
        self,
        x: torch.Tensor,
        y: torch.Tensor,
    ) -> torch.Tensor:
        y_ = self.sample_negatives(x, y)

        # Evaluate the unnormalized_log_ratio f(x,y) on the samples from p(x)r(y|x)
        # The tensor f_ has shape [M, N...] in which f_[i,j] contains critic(x[j], y_[i,j]).
        # and y_ is sampled from r(y|x), which is set to the empirical p(y) unless a proposal is specified
        f_ = self.critic(x, y_)

        log_Z = self.discriminative_estimator._approx_log_partition(x, f_)

        weights = self.generative_estimator.log_ratio(x.unsqueeze(0), y_).exp()
        assert log_Z.shape == weights.shape
        log_Z = log_Z * weights.detach()

        assert log_Z.shape[0] == self.n_negatives_to_use(x.shape[0])
        assert (
            not isinstance(x, torch.LongTensor)
            and log_Z.shape[1:] == x.shape[:-1]
        ) or (isinstance(x, torch.LongTensor) and log_Z.shape[1:] == x.shape)

        return log_Z.mean(0)


import pandas as pd
import numpy as np

from numpy import dot

def clip(pred, max_pred=5, min_pred=1):
    """
    Clipping predict values in range [min_pred, max_pred].

    Args:
      pred : float
          predict value
      max_pred : int
          max value of rating
      min_pred : int
          min value of rating

    Returns:

    pred: int
        predict value cliped
    """

    pred = max_pred if pred > max_pred else pred
    pred = min_pred if pred < min_pred else pred

    return pred

def train_test_split(X, test_split=0.2):
    """
    Split dataset in train and test.

    Args:
      X: np.array
          ratings
      test_split: float
          percentage of data for the test dataset

    Returns:

    train: np.array
        train dataset
    test:
        test dataset
    """

    size = int(X.shape[0])
    all_indexes = list(range(size))

    indexes_test = list(np.random.choice(np.arange(0,size), int(size*test_split), replace=False))
    indexes_train = set(all_indexes) - set(indexes_test)

    train = X.loc[indexes_train].reset_index(drop=True)
    test = X.loc[indexes_test].reset_index(drop=True)

    return train, test

def get_ratings_by_item(
    df, users_df, items, rating_column='Rating', user_column='UserId', item_column='ItemId'):
    """
    Get ratings of the items.

    Args:
      df: pd.DataFrame
          ratings df
      users_df: pd.DataFrame
          Dataframe with all unique users
      items : list of string
          items id
      rating_column: str, default Rating
          name of column with rating values
      user_column: str, default UserId
          name of column with users id
      item_column: str, default ItemId

    Returns:

    list of strings with all items ids evaluated by user target
    """

    aux = df.loc[df[item_column].isin(items)]
    aux = aux.pivot_table(index=user_column, columns=item_column, values=rating_column)
    users_df = users_df.merge(aux, how='left', on=[user_column])
    users_df = users_df.fillna('0')

    return users_df

def get_items_by_users(
    df, users, user_column='UserId', item_column='ItemId'):
    """
    Get items id evaluates by user target.

    Args:
      df: ps.DataFrame
          predict rating value
      user: str
          user id
      user_column: str, default UserId
          name of column with users id
      item_column: str, default ItemId

    Returns:

    list of strings with all items ids evaluated by user target
    """

    items = [list(df.loc[df[user_column] == user][item_column]) for user in users]
    items = sorted(set(sum(items, [])))

    return items

def get_common_users_items(
    df, item, user_column='UserId', item_column='ItemId'):
    """
    Get the ids of users that evaluate a item.

    Args:
      df: ps.DataFrame
          predict rating value
      item: str
          item id
      user_column: str, default UserId
          name of column with users id
      item_column: str, default ItemId
          name of column with items id
    Returns:

    list of strings with all users ids that evaluate a target item
    """

    return list(df.loc[df[item_column] == item][user_column])

def cosine_similarity(x, y):
    """
    Calculates cosine similarity between two vectors.

    Args:
      x: np.array
         vector of values
      y: np.array
         vector of valuesitem id

    Returns:

    cosine similarity between x and y
    """

    return np.dot(x, y)/(norm(x)*norm(y))

def get_item_neighbors(item_sim, item_target, ratings_df):
    """
    Retrieve an item's neighbors

    Args:
      item_target: str
         target item of neighborhood analysis
      ratings_df: pd.DataFrame
          database with users ratings for itens

    Returns:
    neighbors: pd.DataFrame
        target item neighbors
    """

    common_users = get_common_users_items(ratings_df, item=item_target)

    if common_users == []:
        return None

    candidate_items = get_items_by_users(ratings_df, users=common_users)

    if candidate_items == []:
        return None

    neighbors = item_sim[item_sim['items'].apply(lambda x: item_target in x)]
    neighbors = neighbors.loc[neighbors['items'].apply(lambda x: any(candidate in x for candidate in candidate_items))]
    neighbors = neighbors.reset_index(drop=True)

    return neighbors

def round_(x):
    """
    Rounds the value to the integer more close.

    Args:
      x: float
          Value to be rounded
    Returns:
        integer value
    """

    return int(x + 0.5)

def format_and_save(
    result, name_file='out.csv', user_column='UserId', item_column='ItemId',
    rating_column='Rating', round_preds=False):

    """
    Format predictions
    """

    if round_preds:
        result[rating_column] = result[rating_column].apply(round_)
    else:
        result[rating_column] = result[rating_column]

    new_result = pd.DataFrame(np.vstack([result.columns, result]))
    text = list(new_result[0] + ":" + new_result[1] + "," + new_result[2].astype(str))

    result = "\n".join(text)

    return result


import tqdm, tqdm.notebook
import torch
import os
import os.path as op
import copy

from pathlib import Path
from hloc import extract_features, match_features, reconstruction, visualization, pairs_from_exhaustive, match_dense, pairs_from_retrieval, pairs_from_covisibility, triangulation
from hloc.visualization import plot_images, read_image
from hloc.utils import viz_3d
from hloc.utils.parsers import parse_retrieval
from kaglib.utils import create_submission
from collections import defaultdict
from kaglib.utils import read_csv_data_path, create_submission
import pycolmap
from hloc.utils.io import list_h5_names

src = '/home/jsmoon/kaggle/input/image-matching-challenge-2023/train'
device = torch.device('cuda')
cwd = op.dirname(__file__)
csv_path = op.join(
    cwd, 'input/image-matching-challenge-2023/train/train_labels.csv')
num_loc = 5

data_dict = read_csv_data_path(csv_path)
out_results = defaultdict(dict)
print(data_dict)
for dataset, _ in data_dict.items():
    for scene in data_dict[dataset]:
        img_dir = f'{src}/{dataset}/{scene}/images'
        if not os.path.exists(img_dir):
            continue
        # if scene != 'cyprus':
        #     continue
        # Wrap the meaty part in a try-except block.
        out_results[dataset][scene] = {}

        images = Path(f'{src}/{dataset}/{scene}/images')
        outputs = Path(f'/home/jsmoon/kaggle/loftr/{dataset}_{scene}')
        if not os.path.isdir(outputs):
            os.makedirs(outputs, exist_ok=True)
        sfm_pairs = outputs / 'pairs-sfm.txt'
        loc_pairs = outputs / 'pairs-loc.txt'
        sfm_dir = outputs / 'sfm'
        features = outputs / 'features.h5'
        matches = outputs / 'matches.h5'

        matcher_conf = match_dense.confs['loftr']
        retrieval_conf = extract_features.confs['netvlad']

        references = [str(p.relative_to(images)) for p in images.iterdir()]
        print(len(references), "mapping images")

        global_descriptors = extract_features.main(retrieval_conf, images,
                                                   outputs)
        if not list_h5_names(global_descriptors):
            continue
        pairs_from_retrieval.main(global_descriptors,
                                  sfm_pairs,
                                  num_loc,
                                  db_prefix=references,
                                  db_list=references)
        if len(parse_retrieval(sfm_pairs)) < 100:
            print("too small num from netvlad")
            pairs_from_exhaustive.main(sfm_pairs, image_list=references)
        features, sfm_matches = match_dense.main(matcher_conf,
                                                 sfm_pairs,
                                                 images,
                                                 outputs,
                                                 max_kps=8192,
                                                 overwrite=False)
        print(sfm_matches)
        options = {'min_model_size': 3}
        model = reconstruction.main(sfm_dir,
                                    images,
                                    sfm_pairs,
                                    features,
                                    sfm_matches,
                                    image_list=references,
                                    mapper_options=options)
        if model:
            for k, im in model.images.items():
                key1 = f'{dataset}/{scene}/images/{im.name}'
                R = copy.deepcopy(im.rotmat())
                t = copy.deepcopy(im.tvec)
                # if R is None or t is None or not isinstance(
                #         R, np.ndarray) or not isinstance(t, np.ndarray):
                #     raise OSError(key1)
                out_results[dataset][scene][key1] = {}
                out_results[dataset][scene][key1]["R"] = copy.deepcopy(
                    im.rotmat())
                out_results[dataset][scene][key1]["t"] = copy.deepcopy(im.tvec)
                print("im print!!!!")
                print(im.rotmat())
                print(im.tvec)
create_submission(out_results, data_dict)


# -*- coding: utf-8 -*-
from __future__ import print_function

import json

from clu.constants.consts import PROJECT_NAME
# from clu.config.keymap import FrozenNested
from clu.config.base import Nested
from clu.config.filebase import FileBase
from clu.exporting import Exporter

exporter = Exporter(path=__file__)
export = exporter.decorator()

options = { 'separators' : (',', ' : '),
             'sort_keys' : True,
                'indent' : 4 }

@export
class JsonFileBase(FileBase, Nested):

    """ The base class for “clu.config.jsonfile.JsonFile”. Override this
        class in your own project to use JSON file data in your Schema
        pipelines as a NamespacedMutableMapping – q.v. the docstring for
        “clu.config.jsonfile.JsonFile” sub.

        This class uses two mixins: both “clu.config.base.AppName” and
        “clu.config.filebase.FileName” are part of its inheritance chain.
        The “AppName” mixin acts on the “appname” class keyword, and the
        “FileName” mixin acts on the “filename” class keyword (furnishing
        many related class methods).
    """

    def loads(self, loaded):
        """ Load nested namespaced dictionary data from a JSON-encoded string """
        self.tree = json.loads(loaded)

    def dumps(self):
        """ Dump a JSON-encoded string from nested namespaced dictionary data """
        return json.dumps(self.tree, **options)

json_appname  = PROJECT_NAME
json_filename = f'{PROJECT_NAME}-config.json'

@export
class JsonFile(JsonFileBase, appname=json_appname,
                            filename=json_filename):

    """ A representation of a JSON file’s data as a NamespacedMutableMapping.

        This class is specifically germane to the CLU project – note
        that the “appname” and “filename” class keywords are used to
        assign values that are CLU-specific.

        CLU users who wish to use JSON files as NamespacedMutableMappings
        in their own projects should create a subclass of JsonFileBase of
        their own. Like this one, it needs to assign both the “appname”
        and the “filename” class keywords; it is unnecessary (but OK!) to
        define further methods, properties, class constants, and whatnot.
    """
    pass

# Assign the modules’ `__all__` and `__dir__` using the exporter:
__all__, __dir__ = exporter.all_and_dir()


import pygame as pg

pg.init()

# Resolução de tela
tela_x = 1260
tela_y = 700

# Criação de tela
tela = pg.display.set_mode((tela_x, tela_y))

# Ajuste de altura
alt_tela = 60  # Ajusta a altura do trem (apenas para desenvolvimento e testes)

# Configuração de raio das rodas
ext_r = 50  # Raio interno da roda
ext_g = 50
ext_b = 50
inter_r = 255  # Raio externo da roda
inter_g = 255
inter_b = 255

# Variáveis de posição de cada estaca do trilho
x0_mad = 0
x1_mad = 60
x2_mad = 120
x3_mad = 180
x4_mad = 240
x5_mad = 300
x6_mad = 360
x7_mad = 420
x8_mad = 480
x9_mad = 540
x10_mad = 600
x11_mad = 660
x12_mad = 720
x13_mad = 780
x14_mad = 840
x15_mad = 900
x16_mad = 960
x17_mad = 1020
x18_mad = 1080
x19_mad = 1140
x20_mad = 1200

y_mad = 595  # Altura das estacas
vx_mad = 0.1  # Velocidade das estacas (Serve como timer para manter sincronia nas ações)

# tempo
dia = (0, 160, 255)  # Define a cor da esfera que desliza a cor do dia
noite = (10, 0, 0)  # Define a cor da esfera que desliza a cor da noite
cor_fundo = dia  # Serve para declarar a cor de fundo, inicia como a cor de dia

# Lua e Sol
cor_lua = (150, 150, 255)  # Cor da Lua
cor_sol = (255, 255, 150)  # Cor do Sol
cor_luasol = cor_sol #Inicia como sol
x_ls = tela_x - 100  # Posição X
y_ls = 100  # Posição Y
r_ls = 50 # Raio lua e sol

#Lanterna
l_on = (255, 255, 0)
l_off = (cor_fundo)
lanterna = l_off

while True:
    for e in pg.event.get():
        if e.type == pg.QUIT:
            pg.quit()

        #Move o personagem com as teclas do teclado
        if e.type == pg.KEYDOWN:
            if e.key == pg.K_UP:
                if vx_mad >= 0.1:
                    vx_mad += 0.1
            elif e.key == pg.K_DOWN:
                if vx_mad >= 0.2:
                    vx_mad -= 0.1
            elif e.key == pg.K_RIGHT:
                if cor_fundo == dia:
                    cor_fundo = noite
                    cor_luasol = cor_lua
                elif cor_fundo == noite:
                    cor_fundo = dia
                    cor_luasol = cor_sol
            elif e.key == pg.K_LEFT:
                if lanterna == l_on:
                    lanterna = l_off
                elif lanterna == l_off:
                    lanterna == l_on

    # Apagar a tela
    tela.fill(cor_fundo)

    # Montagem de cena
    # Define a Lua e o Sol
    pg.draw.circle(tela, (cor_luasol), (x_ls, y_ls), r_ls)

    # Grama
    pg.draw.polygon(tela, (34, 177, 76), [(0, 610), (tela_x, 610), (tela_x, tela_y), (0, tela_y)])

    # Estrutura do Trem
    pg.draw.rect(tela, (150, 150, 150), (150, 330 + alt_tela, 200, 170))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (100, 100, 100), (350, 470 + alt_tela, 30, 20))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (150, 150, 150), (380, 250 + alt_tela, 150, 250))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (100, 100, 100), (350, 210 + alt_tela, 210, 40))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (cor_fundo), (410, 280 + alt_tela, 90, 90))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (120, 120, 120), (530, 350 + alt_tela, 250, 150))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.polygon(tela, (50, 50, 50), [(780, 370 + alt_tela), (780, 480 + alt_tela), (860, 480 + alt_tela)])
    pg.draw.rect(tela, (150, 150, 150), (700, 300 + alt_tela, 50, 50))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (50, 50, 50), (750, 310 + alt_tela, 10, 25))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.polygon(tela, (lanterna), [
        (760, 310 + alt_tela),
        (760, 335 + alt_tela),
        (1100, 540 + alt_tela),
        (tela_x, 540 + alt_tela),
        (tela_x, 500 + alt_tela)
    ])
    pg.draw.polygon(tela, (50, 50, 50), [(685, 300 + alt_tela), (725, 260 + alt_tela), (765, 300 + alt_tela)])

    # Rodas do Trem
    pg.draw.circle(tela, ((ext_r, ext_g, ext_b)), (200, 500 + alt_tela), 40)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((inter_r, inter_g, inter_b)), (200, 500 + alt_tela), 20)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((ext_r, ext_g, ext_b)), (300, 500 + alt_tela), 40)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((inter_r, inter_g, inter_b)), (300, 500 + alt_tela), 20)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((ext_r, ext_g, ext_b)), (430, 500 + alt_tela), 40)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((inter_r, inter_g, inter_b)), (430, 500 + alt_tela), 20)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((ext_r, ext_g, ext_b)), (550, 500 + alt_tela), 40)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((inter_r, inter_g, inter_b)), (550, 500 + alt_tela), 20)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((ext_r, ext_g, ext_b)), (750, 500 + alt_tela), 40)  # ((x_pos, y_pos), raio)
    pg.draw.circle(tela, ((inter_r, inter_g, inter_b)), (750, 500 + alt_tela), 20)  # ((x_pos, y_pos), raio)

    # Trilho de aço
    pg.draw.rect(tela, (120, 120, 120), (0, 600, tela_x, 10))  # (x_pos, y_pos, tam_x, tam_y)

    # Estacas do trilho (tabuas)
    pg.draw.rect(tela, (92, 64, 51), (x0_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x1_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x2_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x3_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x4_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x5_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x6_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x7_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x8_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x9_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x10_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x11_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x12_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x13_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x14_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x15_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x16_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x17_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x18_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x19_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)
    pg.draw.rect(tela, (92, 64, 51), (x20_mad, y_mad, 30, 15))  # (x_pos, y_pos, tam_x, tam_y)

    # Atualizar o frame
    pg.display.flip()

    # Movimento das estacas dos trilhos (tabuas)
    x0_mad += -vx_mad
    x1_mad += -vx_mad
    x2_mad += -vx_mad
    x3_mad += -vx_mad
    x4_mad += -vx_mad
    x5_mad += -vx_mad
    x6_mad += -vx_mad
    x7_mad += -vx_mad
    x8_mad += -vx_mad
    x9_mad += -vx_mad
    x10_mad += -vx_mad
    x11_mad += -vx_mad
    x12_mad += -vx_mad
    x13_mad += -vx_mad
    x14_mad += -vx_mad
    x15_mad += -vx_mad
    x16_mad += -vx_mad
    x17_mad += -vx_mad
    x18_mad += -vx_mad
    x19_mad += -vx_mad
    x20_mad += -vx_mad

    # Controle de colisão das estacas (tabuas) dos trilhos
    # Caso a estaca chegue no X = 0, a mesma é jogada para o ponto X limite da tela
    if x0_mad < 0:
        x0_mad = tela_x
    elif x1_mad < 0:
        x1_mad = tela_x
    elif x2_mad < 0:
        x2_mad = tela_x
    elif x3_mad < 0:
        x3_mad = tela_x
    elif x4_mad < 0:
        x4_mad = tela_x
    elif x5_mad < 0:
        x5_mad = tela_x
    elif x6_mad < 0:
        x6_mad = tela_x
    elif x7_mad < 0:
        x7_mad = tela_x
    elif x8_mad < 0:
        x8_mad = tela_x
    elif x9_mad < 0:
        x9_mad = tela_x
    elif x10_mad < 0:
        x10_mad = tela_x
    elif x11_mad < 0:
        x11_mad = tela_x
    elif x12_mad < 0:
        x12_mad = tela_x
    elif x13_mad < 0:
        x13_mad = tela_x
    elif x14_mad < 0:
        x14_mad = tela_x
    elif x15_mad < 0:
        x15_mad = tela_x
    elif x16_mad < 0:
        x16_mad = tela_x
    elif x17_mad < 0:
        x17_mad = tela_x
    elif x18_mad < 0:
        x18_mad = tela_x
    elif x19_mad < 0:
        x19_mad = tela_x
    elif x20_mad < 0:
        x20_mad = tela_x


# -*- coding: utf-8 -*-

from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from datetime import datetime
from datetime import date
from datetime import time
from dateutil.relativedelta import relativedelta

class AllocationShift(models.Model):
    _name = 'hr.shift.allocation'
    _description = 'This table handle the data of shift allocation in attendance'
    _rec_name = 'name'

    name = fields.Char(string='Name', readonly=True)
    employee_id = fields.Many2many('hr.employee', string='Employee')
    department_id = fields.Many2one('hr.department', string='Department')
    date_start = fields.Date(string='Start Date', required=True)
    date_end = fields.Date(string='End Date', required=True)
    is_proceed = fields.Boolean(default=False)
    shift_id = fields.Many2one('hr.shift')
    branch_id = fields.Many2one('res.branch')

    # max_shift_day = fields.Selection([
    #     ('1', '1'),
    #     ('2', '2'),
    # ], string='Max Shifts/Day', required=True, copy=False, index=True, tracking=3, default='1')

    allocation_lines = fields.One2many('hr.shift.allocation.line', 'rel_allocation')

    def action_add_shift(self):
        start = "01:00"
        end = "08:59"
        start_dt = datetime.strptime(start, '%H:%M')
        end_dt = datetime.strptime(end, '%H:%M')
        diff = end_dt-start_dt
        seconds = diff.total_seconds()
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        seconds = seconds % 60
        print(hours)
        print(minutes)
        print(seconds)
        for line in self.allocation_lines:
            line.shift_one_type = self.shift_id.id

    @api.onchange('department_id', 'branch_id')
    def onchange_department_id(self):
        employees = []
        if self.department_id.id and self.branch_id.id:
            employees = self.env['hr.employee'].search([('department_id', '=', self.department_id.id)])
        elif self.department_id.id:
            employees = self.env['hr.employee'].search(
                [('department_id', '=', self.department_id.id)])
        elif self.branch_id.id:
            employees = self.env['hr.employee'].search(
                [('branch_id', '=', self.branch_id.id)])
        print(employees)
        if employees:
            self.employee_id = employees.ids
        else:
            print('ff')
            self.employee_id = False

    # def unlink(self):
    #     if not self.env.user.has_group('de_shift_attendance.allow_parent_allocation_deletion'):
    #         raise UserError(('You Did Not Have Access Rights to Delete The Record '))
    #     else:
    #         super(AllocationShift,self).unlink()

    # @api.onchange('max_shift_day')
    # def show_shifts(self):
    #     if self.max_shift_day == '1':
    #         self.allocation_lines.hide_field = True

    @api.onchange('date_start','date_end')
    def create_records(self):
        for line in self.allocation_lines:
            line.unlink()
        if self.date_start and self.date_end:
            delta = self.date_start - self.date_end
            total_days = abs(delta.days)
            for i in range(0, total_days + 1):
                date_after_month = self.date_start + relativedelta(days=i)
                day_week = '0'
                if date_after_month.weekday() == 0:
                    day_week = '0'
                elif date_after_month.weekday() == 1:
                    day_week = '1'
                elif date_after_month.weekday() == 2:
                    day_week = '2'
                elif date_after_month.weekday() == 3:
                    day_week = '3'
                elif date_after_month.weekday() == 4:
                    day_week = '4'
                elif date_after_month.weekday() == 5:
                    day_week = '5'
                elif date_after_month.weekday() == 6:
                    day_week = '6'

                vals = {
                    'rel_allocation': self.id,
                    'date': date_after_month,
                    'day': day_week,
                }
                if vals['day'] == self.shift_id.off_day:
                    vals['rest_day'] = True
                self.env['hr.shift.allocation.line'].create(vals)
                i = i + 1

    @api.model
    def create(self, vals):
        if vals.get('name', ('New')) == ('New'):
            vals['name'] = self.env['ir.sequence'].next_by_code('hr.shift.allocation.sequence') or _('New')
        result = super(AllocationShift, self).create(vals)
        return result

    def create_management_data(self):
        self.is_proceed = True
        for employee in self.employee_id:
            line_vals = []
            for line in self.allocation_lines:
                line_vals.append((0,0, {
                    'rel_management': line.id,
                    'date': line.date,
                    'shift_one': line.shift_one_type.id,
                    'check_in': line.shift_one_type.time_in,
                    'check_out': line.shift_one_type.time_out,
                    'shift_two': line.shift_two_type.id,
                    'rest_day': line.rest_day,
                    'day': line.day,
                }))
            vals = {
                'employee_id': employee.id,
                'name': self.name,
                'date_start': self.date_start,
                'date_end': self.date_end,
                'management_lines': line_vals
            }
            lines = self.env['hr.shift.management'].create(vals)

class AllocationShiftLine(models.Model):
    _name = 'hr.shift.allocation.line'

    rel_allocation = fields.Many2one('hr.shift.allocation')
    date = fields.Date(string='Date')
    shift_one = fields.Boolean(string='Shift 1', default=True)
    shift_one_type = fields.Many2one('hr.shift', string='Shift 1 Type')
    shift_two = fields.Boolean(string='Shift 2', default=False)
    shift_two_type = fields.Many2one('hr.shift', string='Shift 2 Type')
    # hide_field = fields.Boolean(string='Hide', default=False, readonly=True)
    rest_day = fields.Boolean(string='Rest Day')
    day = fields.Selection([
        ('0', 'Monday'),
        ('1', 'Tuesday'),
        ('2', 'Wednesday'),
        ('3', 'Thursday'),
        ('4', 'Friday'),
        ('5', 'Saturday'),
        ('6', 'Sunday'),
    ], string='Day',copy=False, default='0')

    # def get_day(date_string):
    #     date = datetime.strptime(date_string, '%Y-%m-%d')
    #     print('_______________________',date)
    #     return date.day

    @api.onchange('rest_day')
    def _onchange_rest_day(self):
        for line in self:
            if line.rest_day == True:
                line.shift_one = False
                line.shift_two = False
            else:
                line.shift_one = True
                line.shift_two = True

    def unlink(self):
        if not self.env.user.has_group('de_shift_attendance.allow_allocation_deletion'):
            raise UserError(('You Did Not Have Access Rights to Delete The Record '))
        else:
            super(AllocationShiftLine,self).unlink()


#!/usr/bin/env python3
from operator import itemgetter
import sys

current_state = None
current_city = None
state_count = 0
city_count = 0

# read the entire line from STDIN
for line in sys.stdin:
    # remove leading and trailing whitespace
    line = line.strip()
    state_city, count = line.split('\t', 1)
    state, city = state_city.split('#', 1)
    printed = False

    # splitting the data on the basis of tab we have provided in mapper.py
    try:
        count = int(count)
    except ValueError:
        continue

    # Only works because Hadoop sorts map output by key (here: word) before it is passed to the reducer
    if current_state == state:
        state_count += count
    else:
        if current_city:
            print ('%s\t%s' % (current_city[:-2], city_count))
            printed = True
        if current_state:
            print ('%s\t%s' % (current_state, state_count))

        print('%s' % (state))
        state_count = count
        current_state = state

    if current_city == city:
        city_count += count
    else:
        #if current_city and printed == False:
        if current_city and printed == False:
            print ('%s\t%s' % (current_city[:-2], city_count))

        city_count = count
        current_city = city

#if current_state == state is False:
print('%s\t%s' % (current_city[:-2], city_count))
print('%s\t%s' % (current_state, state_count))


#
# Converts an Integer into a String (in roman numerals)
#
# (c) Joseph Moon, 2018
#

class RomanNumeralizer:
    """
    Converts an integer input into its Roman Numeral equivalent
    """

    def __init__(self, dictionary):
        self.dictionary = dictionary

    def convert_int_to_roman_numeral_characters(self, _int):
        self._chars = []
        return self._correct_nines(self._assign_roman_numerals(_int))

    def _correct_nines(self, _string):
        _string = list(_string)
        for i in range(len(_string)-2):
            if _string[i] == _string[i+2] != _string[i+1]:
                _string[i] = ''
                _string[i+2] = list(self.dictionary.keys())[list(self.dictionary.values()).index(self.dictionary[_string[i+2]]*2)]
        return ''.join(_string)

    def _assign_roman_numerals(self, _int):
        index, list_of_keys = 0, []
        for key, value in self.dictionary.items():
            list_of_keys += key
            if _int//value > 0 and _int//value < 4:
                for i in range(_int//value):
                    self._chars += key
                _int = _int % value
            elif _int//value == 4:           # correct 4's
                self._chars += key
                self._chars += list_of_keys[index-1]
                _int = _int % value
            index += 1
        return ''.join(self._chars)

if __name__ == "__main__":
    Dictionary = {'M':1000, 'D':500, 'C':100, 'L':50, 'X':10, 'V':5, 'I':1}
    r = RomanNumeralizer(Dictionary)
    print(r.convert_int_to_roman_numeral_characters(2019))
    print(r.convert_int_to_roman_numeral_characters(1999))
    print(r.convert_int_to_roman_numeral_characters(1876))


#14. Faça um algoritmo que leia dois inteiros A e B, e crie um
#algoritmo para trocar os valores dessas variáveis.
c = 0
d = 0

a = int(input("Forneça dois valores inteiros para \"a\" e \"b\", respectivamente: "))
b = int(input())

c = a
d = b
b = c
a = d

print("O valor de \"a\" é", a, "e o de \"b\" é", b, end = ".\n")


import csv
from .variables_mapping import event_index

def form_unique_events_list():
    with open('athlete_events.csv') as athletes_file:
        reader = csv.reader(athletes_file)
        events_dict = {}
        for row in reader:
            if reader.line_num == 1:
                continue
            event = row[event_index]
            if '"' in event:
                event = event.replace('"', '\'')
            event_id = reader.line_num
            event_obj = {'event_name': event,
                         'id': event_id}
            events_dict[event] = event_obj
        return events_dict


"""
This module defines whatever for generating new sudoku puzzles
of varying difficulty.
"""

from .concrete import UniqueProver, StartCreating, FinishCreating
from .data import State
from .errors import NoNextMoveError, Catastrophic

def check_unique(grid, grconfig=None):
    """Shortcut to call UniqueProver.check on a grid."""
    gc = grid.copy()
    state = State(gc, grconfig=grconfig)
    up = UniqueProver(state)
    return up.check()

def create_terminal_pattern(*, grconfig=None):
    """Make a randomized solved grid."""
    state = State({}, grconfig)
    sc = StartCreating(state)
    sc.solve()
    fin = FinishCreating(state)
    try:
        fin.solve()
    except NoNextMoveError:
        # Oops, sc created a puzzle with no solutions; start over
        return create_terminal_pattern(grconfig=grconfig)
    except Catastrophic:
        # See docstring for errors.Catastrophic
        return create_terminal_pattern(grconfig=grconfig)
    return state.clues


#Leap year check program
#Name: TEMA, Thabo Hebert
#Student number: TMXTHA006
#Date: 11 March 2014

year = eval(input("Enter a year:\n"))

if ((year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))):
    print(year, "is a leap year.")
else:
    print(year, "is not a leap year.")


print("WELCOME TO BUBBLE GAME".center(50,"*"))
print(">ENTER SPACE TO CREATE A BUBBLE".rjust(40,"="))
print(">ENTER UP TO DELETE A BUBBLE".rjust(40,"="))

import pygame
import random
from random import randint
pygame.init()
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
surface = pygame.Surface((100, 100))
done = False
class Bubble(object):
    WIDTH = 800
    HEIGHT = 600
    def __init__(self,size,speed,screen,x=0,y=0):
        self.size = size
        self.speed = speed
        self.xSpeed = speed
        self.ySpeed = speed
        self.screen = screen
        self.color = (randint(1,255), randint(1,255), randint(1,255))
        self.x = x
        self.y = y
    def set_color(self,color):
        self.color = color
    def run_bubble(self):
        if(self.x<=self.size):
            self.xSpeed = self.speed
        if(self.y<=self.size):
            self.ySpeed = self.speed
        if(self.x>=WIDTH-self.size):
            self.xSpeed = -self.speed
        if(self.y>=HEIGHT-self.size):
            self.ySpeed = -self.speed
        self.x+=self.xSpeed
        self.y+=self.ySpeed
        # pygame.draw.rect(self.screen, self.color, pygame.Rect(self.x, self.y, self.size, self.size))
        pygame.draw.circle(screen, self.color, (self.x,self.y), self.size)
bubble_stack = []
N = 3
for i in range(N):
    b = Bubble(randint(10,100),randint(1,4),screen,randint(0,WIDTH),randint(0,HEIGHT))
    bubble_stack.append(b)
while not done:
        for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    done = True
                if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                    t = Bubble(randint(10,50),randint(1,4),screen,randint(0,WIDTH),randint(0,HEIGHT))
                    bubble_stack.append(t)
                if event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
                    bubble_stack.pop()

        screen.fill((0, 0, 1))
        for b in bubble_stack:
            b.run_bubble()
        pygame.display.flip()
        clock.tick(60)


import torch
from torch import nn
from torch.nn.init import kaiming_uniform
from torch.autograd import Variable
import numpy as np

import torch.nn.functional as F

class RelationNetworks(nn.Module):
    def __init__(self, n_vocab, conv_hidden=24, embed_hidden=32,
                 lstm_hidden=128, mlp_hidden=256, classes=29):
        super(RelationNetworks, self).__init__()

        COORS8 = np.zeros((8, 8, 2))
        for i in range(8):
            for j in range(8):
                COORS8[i, j, 0] = (i-3.5)/3.5
                COORS8[i, j, 1] = (j-3.5)/3.5

        self.ma_conv1 = nn.Conv2d(1, 24, 5, stride=2, padding=2)
        self.ma_batchNorm1 = nn.BatchNorm2d(24)
        self.ma_conv2 = nn.Conv2d(24, 32, 5, stride=2, padding=2)
        self.ma_batchNorm2 = nn.BatchNorm2d(32)
        self.ma_conv3 = nn.Conv2d(32, 16, 8, stride=1, padding=0)
        self.ma_batchNorm3 = nn.BatchNorm2d(16)

        self.seg_conv1 = nn.Conv2d(3, 16, 3, stride=1, padding=1)
        self.seg_batchNorm1 = nn.BatchNorm2d(16)
        self.seg_conv2 = nn.Conv2d(16, 16, 3, stride=1, padding=1)
        self.seg_batchNorm2 = nn.BatchNorm2d(16)
        self.seg_conv3 = nn.Conv2d(16, 16, 8, stride=1, padding=0)
        self.seg_batchNorm3 = nn.BatchNorm2d(16)
#        self.seg_conv3 = nn.Conv2d(24, 24, 3, stride=2, padding=1)
#        self.seg_batchNorm3 = nn.BatchNorm2d(24)

        self.g2_fc1 = nn.Linear(192, 256)
#        self.g2_fc2 = nn.Linear(256, 256)
#        self.g2_fc3 = nn.Linear(256, 256)
        self.g2_fc4 = nn.Linear(256, 256)

        self.g3_fc1 = nn.Linear(224, 256)
#        self.g3_fc2 = nn.Linear(256, 256)
#        self.g3_fc3 = nn.Linear(256, 256)
        self.g3_fc4 = nn.Linear(256, 256)

        self.f_fc1 = nn.Linear(512, 256)
        self.f_fc2 = nn.Linear(256, 256)
        self.f_fc3 = nn.Linear(256, 29)

        self.embed = nn.Embedding(n_vocab, embed_hidden)
        self.lstm = nn.LSTM(embed_hidden, lstm_hidden, batch_first=True)

        self.n_concat = conv_hidden * 2 + lstm_hidden + 4

        self.conv_hidden = conv_hidden
        self.lstm_hidden = lstm_hidden
        self.mlp_hidden = mlp_hidden

        coors_tensor = torch.FloatTensor(COORS8)

        if torch.cuda.is_available():
            self.coors_tensor = Variable(coors_tensor).cuda()
        else:
            self.coors_tensor = Variable(coors_tensor)
        #self.initialize_weights()

    def forward(self, apps, masks, num_layers, question, question_len):

        batch_size, MX_N, _, _ = masks.size()

        question_len = question_len.data.cpu().numpy().tolist()

        embed = self.embed(question)
        embed_pack = nn.utils.rnn.pack_padded_sequence(embed, question_len,
                                                    batch_first=True)
        _, (h, c) = self.lstm(embed_pack)

        qst = h.permute(1, 0, 2) # batchsize*self.lstm_hidden

        num_layers_value = num_layers.data.cpu().numpy()

        """masks"""
        masks = masks.unsqueeze(2).view(batch_size*MX_N, 1, 32, 32)
        x_m = self.ma_conv1(masks)
        x_m = F.relu(x_m)
        x_m = self.ma_batchNorm1(x_m)
        x_m = self.ma_conv2(x_m)
        x_m = F.relu(x_m)
        x_m = self.ma_batchNorm2(x_m)
        x_m = self.ma_conv3(x_m)
        x_m = F.relu(x_m)
        x_m = self.ma_batchNorm3(x_m)
        x_m = x_m.view(batch_size, MX_N, 16)
        # imshow
#        if not torch.cuda.is_available():
#            import matplotlib.pyplot as plt
#            for b in range(batch_size):
#                img = image[b].permute(1, 2, 0)
#                img = img.data.cpu().numpy()
#                img_tmp = np.zeros_like(img)
#                img_tmp[:,:,0] = img[:,:,2]
#                img_tmp[:,:,2] = img[:,:,0]
##                print (img_tmp)
#
#    #            print (img_tmp)
#                fig = plt.figure()
#                ax = fig.add_subplot(111)
#                ax.imshow(img)
#                plt.show()
#                for l in range(num_layers_value[b]):
#                    img = apps[b, l].permute(1, 2, 0)
#                    img = img.data.cpu().numpy()
#                    img_tmp = np.zeros_like(img)
#                    img_tmp[:,:,0] = img[:,:,2]
#                    img_tmp[:,:,2] = img[:,:,0]
#                    fig = plt.figure()
#                    ax = fig.add_subplot(111)
#                    ax.imshow(img)
#                    plt.show()

        """segs"""
        x_all = apps.view(batch_size*MX_N, 3, 32, 32)
        x_all = self.seg_conv1(x_all) # num_layers*128*128*3
        x_all = F.relu(x_all)
        x_all = self.seg_batchNorm1(x_all)
        x_all = F.max_pool2d(x_all, 2)
        x_all = self.seg_conv2(x_all)
        x_all = F.relu(x_all)
        x_all = self.seg_batchNorm2(x_all)
        x_all = F.max_pool2d(x_all, 2)
        x_all = self.seg_conv3(x_all)
        x_all = F.relu(x_all)
        x_all = self.seg_batchNorm3(x_all)

#        print (x_all.size())
#        x_all = x_all.contiguous().view(batch_size, MX_N, 24, 8, 8)
#        x_flat = x_all.permute(0, 1, 3, 4, 2) # batch_size*N*8*8*24
#        x_flat = x_flat.contiguous().view(-1, 8*8*24) # batch_size*N*8*8, 24
##            print (x_flat) # N, 1536
#        x_all = self.seg_fc(x_flat) # batch_size*N, 22
        x_all = x_all.view(batch_size, MX_N, 16)
        x_all = torch.cat([x_all, x_m], -1) # batch_size, MX_N, 32
#        x_all = torch.cat([x_all, coors, sizes.unsqueeze(-1).repeat(1, 1, 2)], -1)
        x_i = x_all.unsqueeze(1).repeat(1, MX_N, 1, 1)
        x_j = x_all.unsqueeze(2).repeat(1, 1, MX_N, 1)

        x_i_3 = x_all.unsqueeze(1).unsqueeze(1).repeat(1, MX_N, MX_N, 1, 1)
        x_j_3 = x_all.unsqueeze(2).unsqueeze(1).repeat(1, MX_N, 1, MX_N, 1)
        x_k_3 = x_all.unsqueeze(2).unsqueeze(2).repeat(1, 1, MX_N, MX_N, 1)

        qst_2 = qst.unsqueeze(1).repeat(1, MX_N, MX_N, 1)
        qst_3 = qst.unsqueeze(1).unsqueeze(1).repeat(1, MX_N, MX_N, MX_N, 1)
#        print (qst_2)
#        print (qst_3)
        concat_vec_2 = torch.cat([x_i, x_j, qst_2], -1)
        concat_vec_3 = torch.cat([x_i_3, x_j_3, x_k_3, qst_3], -1)
#        print (concat_vec_2.size())
#        print (concat_vec_3.size())

        concat_vec_2 = concat_vec_2.view(-1, 192)
        concat_vec_3 = concat_vec_3.view(-1, 224)

        """g2 """
        x_2 = self.g2_fc1(concat_vec_2)
        x_2 = F.relu(x_2)
#        x_2 = self.g2_fc2(x_2)
#        x_2 = F.dropout(x_2)
#        x_2 = F.relu(x_2)
#        x_2 = self.g2_fc3(x_2)
#        x_2 = F.relu(x_2)
        x_2 = self.g2_fc4(x_2)
        x_2 = F.dropout(x_2)
        x_2 = F.relu(x_2) # num_layers_value[b]*num_layers_value[b], 256
        x_2 = x_2.view(batch_size, MX_N, MX_N, 256)
#            print (x_)
        apps_vector_2 = []
        for b in range(batch_size):
            N = int(num_layers_value[b])
            x_2_tmp = x_2[b, :N, :N, :]
            x_2_tmp = x_2_tmp.contiguous().view(N*N, 256)
            x_2_tmp = x_2_tmp.sum(0).squeeze()
            apps_vector_2.append(x_2_tmp)
#        x_2 = x_2.sum(1).squeeze() # 256
        apps_vector_2 = torch.stack(apps_vector_2)

        """g3 """
        x_3 = self.g3_fc1(concat_vec_3)
        x_3 = F.relu(x_3)
#        x_3 = self.g3_fc2(x_3)
#        x_3 = F.relu(x_3)
#        x_3 = self.g3_fc3(x_3)
#        x_3 = F.relu(x_3)
        x_3 = self.g3_fc4(x_3)
        x_3 = F.dropout(x_3)
        x_3 = F.relu(x_3) # num_layers_value[b]*num_layers_value[b], 256
        x_3 = x_3.view(batch_size, MX_N, MX_N, MX_N, 256)
#            print (x_)
        apps_vector_3 = []
        for b in range(batch_size):
            N = int(num_layers_value[b])
            x_3_tmp = x_3[b, :N, :N, :N, :]
            x_3_tmp = x_3_tmp.contiguous().view(N*N*N, 256)
            x_3_tmp = x_3_tmp.sum(0).squeeze()
            apps_vector_3.append(x_3_tmp)
#        x_3 = x_3.sum(1).squeeze() # 256
        apps_vector_3 = torch.stack(apps_vector_3)

#        x_g = torch.cat([apps_vector_2, apps_vector_3], -1)
        x_g = torch.cat([apps_vector_2, apps_vector_3], -1)

#        print (x_g.size())
        """f"""
        x_f = self.f_fc1(x_g)
        x_f = F.relu(x_f)
        x_f = self.f_fc2(x_f)
        x_f = F.relu(x_f)
        x_f = F.dropout(x_f)
        x_f = self.f_fc3(x_f)

        return F.log_softmax(x_f)


import math

try:
    print('Now enter please coefficients of our quadratic equation')
    a = float(input('a (the highest term coefficient) '))
    b = float(input('b (the coefficient at x) '))
    c = float(input('c (free member) '))
    D = math.sqrt(b ** 2 - 4 * a * c)
    x_1 = (-b + D) / (2 * a)
    x_2 = (-b - D) / (2 * a)
    print('The first solution {}, the second {}'.format(round(x_1, 2), round(x_2, 2)))
except Exception as ex:
    print(ex)


import random, sys, json

with open('names.txt') as F:
    NAMES = F.read().split()

_, filename, N = sys.argv
N = int(N)

def leaves(family):
    # all leaves
    return { x  for x in family
                if not family[x]['spouse'] and not (any(x in family[y]['parents'] for y in family)) }

#print(NAMES)
ancestors  = random.sample(NAMES, k=10)
names      = random.sample(list(set(NAMES)-set(ancestors)), k=N)
family = {}
print(ancestors)
for name in ancestors:
    family[name] = {
        'alive'  : random.randint(1, 100) > 50,
        'parents': [],
        'spouse' : None
    }
for name in ancestors:
    if random.randint(1, 100) <= 20:        # 20% prob to be married (times 2 = at most 40% married)
        spouse = random.choice(ancestors)
        if not family[spouse]['spouse']:
            family[name]['spouse'] = spouse
            family[spouse]['spouse'] = name

print(json.dumps(family))

for name in names:
    family[name] = {
        'alive'  : random.randint(1,100) > 50,
        'parents': random.sample(list(family.keys()), k=2),
        'spouse' : None
    }
    if random.randint(1, 100) <= 20:
        foglie = list(leaves(family)-{name})
        print(foglie)
        spouse = random.choice(foglie)
        if not family[spouse]['spouse']:
            family[name]['spouse'] = spouse
            family[spouse]['spouse'] = name

print(json.dumps(family, indent=4))

with open(filename+'.json', mode='w', encoding='utf8') as F:
    json.dump(family, F, indent=4)

with open(filename+'.dot', mode='w', encoding='utf8') as F:
    print('digraph G {rankdir=LR', file=F)
    for p,v in family.items():
        if v['alive']:
            print(f'{p}', file=F)
        else:
            print(f'{p} [color=red]', file=F)
        for g in v['parents']:
            print(f'{p} -> {g}', file=F)
        if v['spouse']:
            print(f'{p} -> {v["spouse"]} [color=green]', file=F)
    print('}', file=F)


import strawberry
from enum import Enum
from strawberry.django import auto
from typing import List
import strawberry_django

from fruits import models

@strawberry.enum
class ColorName(Enum):
    RED     = "Rojo"
    YELLOW  = "Amarillo"
    BLUE    = "Azul"
    ORANGE  = "Naranja"
    PURPLE  = "Violeta"
    GREEN   = "Verde"

@strawberry.django.type(models.Fruit)
class Fruit:
    id: auto
    name: auto
    color: 'Color'
    amount: auto

@strawberry.django.type(models.Color)
class Color:
    id: auto
    name: auto
    fruits: List[Fruit]

@strawberry_django.input(models.Color)
class ColorInput:
    id: auto
    name: auto
    fruits: auto

@strawberry_django.input(models.Fruit)
class FruitInput:
    id: auto
    name: auto
    amount: auto
    color: auto