from pygame import draw, Rect, image, transform

class Bird:
    def __init__(self, scr, width, height, r):
        self.scr = scr
        self.width = width
        self.height = height

        self.x = self.width/2
        self.r = r
        self.y = self.height-self.r

        self.vy = 0
        self.gravity = 0.3

        # imaage
        self.img = image.load("img/android.png")
        self.img = transform.scale(self.img, (self.r, self.r))

    def update(self):
        self.y += self.vy
        self.vy += self.gravity

    def up(self, num=10):
        self.vy = -num

    def move(self, num):
        self.x += num
        if self.x+self.r < 0:
            self.x = self.width-self.r
        elif self.x >= self.width:
            self.x = 0
        else:
            pass

    def constrain(self, var, minmum, maximum):
        if var <= minmum:
            return minmum
        elif var >= maximum:
            return maximum
        else:
            return var

    def show(self):
        self.y = self.constrain(self.y, 100, self.height-self.r)
        # draw.rect(self.scr, (100,100,100), Rect(self.x, self.y, self.r, self.r))
        self.scr.blit(self.img, (self.x, self.y))


from google.appengine.ext import db
import webapp2
from google.appengine.api import users, mail

from main import BaseHandler
from models import *

class AdminListHandler(BaseHandler):
  def get(self):
    user = users.get_current_user()
    if not user:
      self.redirect("/login")
    elif not UserInfo.isAdmin(user.user_id()):
      self.redirect("/")
    else:
      rqs = ScheduleRequest.all()
      template_args ={
        'user': user,
        'rqs': rqs,
        'timetable': timetable
      }
      self.render_template("adminlist.html", **template_args)

  def post(self):
    arqs = self.request.get_all("approve")
    drqs = self.request.get_all("deny")
    parqs = []
    pdrqs = []
    for rq in arqs:
      if rq in drqs: drqs.remove(rq)
      rq = db.get(rq)
      parqs.append(rq)
      accepted = RoomSchedule(roomnum=rq.roomnum, userid=rq.userid,role=rq.role,
                              startdate=rq.startdate,
                              starttime=rq.starttime,endtime=rq.endtime,
                              deletekey=rq.deletekey, reserved=True)
      accepted.put()
      sender_address = "Room Scheduling Notification <notification@roomscheduler490.appspotmail.com>"
      subject = "Your request has been approved"
      body = """
      Your request of room %s has been approved.
      """ % rq.roomnum
      user_address = rq.useremail
      mail.send_mail(sender_address, user_address, subject, body)
      rq.delete()

    for rq in drqs:
      rq = db.get(rq)
      pdrqs.append(rq)
      sender_address = "Room Scheduling Notification <notification@roomscheduler490.appspotmail.com>"
      subject = "Your request has been denied"
      body = """
      Your request of room %s has been denied.
      """ % rq.roomnum
      user_address = rq.useremail
      mail.send_mail(sender_address, user_address, subject, body)
      rq.delete()

    template_args = {
      'user': users.get_current_user(),
      'arqs': parqs,
      'drqs': pdrqs,
      'timetable': timetable
    }
    self.render_template("adminsuccess.html", **template_args)


from telegram.ext import ConversationHandler

from src.templates import KeyboardTemplates, MessageTemplates
from src.managers import LoggerManager, UserManager

TIMEOUT_DURATION_IN_MINUTES = MessageTemplates.TIMEOUT_DURATION_IN_MINUTES
EMPTY_LIST_LENGTH = 0

def check_membership_status(update):
    user_id = update.message.from_user.id

    LoggerManager.general_logs(
        f"Checking if user {update.message.from_user.username} ({user_id}) is a member")

    return UserManager.is_a_member(user_id)

def log_command_accessed_timing(update):
    username = update.message.from_user.username
    user_id = update.message.from_user.id
    command_entered_by_user = update.message.text

    LoggerManager.init_command_log(username,
                                   user_id,
                                   command_entered_by_user)

def prompt_user_next_action(update):
    message_to_send = MessageTemplates.ask_user_action_message
    update.message.reply_text(message_to_send,
                              disable_web_page_preview=True,
                              reply_markup=KeyboardTemplates.start_keyboard)

def cancel_current_action(update, context):
    user_id = str(update.message.from_user.id)

    try:
        context.user_data[user_id].clear()
        context.chat_data[user_id].clear()
        del update.message.photo[:]

    except:
        pass

    update.message.reply_text(
        MessageTemplates.cancel_action_message, reply_markup=KeyboardTemplates.start_keyboard)

    return ConversationHandler.END

def dispatch_voucher(update, voucher_path, caption_to_send):
    try:
        LoggerManager.general_logs(
            f"Sending voucher to {update.message.from_user.username} ({update.message.from_user.id}) now")

        update.message.reply_photo(photo=open(voucher_path, 'rb'),
                                   caption=caption_to_send)

    except Exception as e:
        update.message.reply_text(MessageTemplates.error_message)
        LoggerManager.exception_logs(e)

def timeout_handler(update, context):
    LoggerManager.general_logs(f"No action performed after {context.effective_message.text} " +
                               f"by user {context.effective_message.chat.username} " +
                               f"({context.effective_message.chat.id})"
                               )

    context.message.reply_text(MessageTemplates.action_auto_cancelled_message,
                               reply_markup=KeyboardTemplates.start_keyboard)

    return ConversationHandler.END

def error(update, context):
    # Log errors caused by Updates.
    LoggerManager.telegram_error_logs(update, context)


"""
Non-equivariant ResNet and U-net
"""

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

def conv(input_channels, output_channels, kernel_size, stride):
    return nn.Sequential(
        nn.Conv2d(input_channels, output_channels, kernel_size = kernel_size,
                  stride = stride, padding=(kernel_size - 1) // 2),
        nn.ReLU()
    )

def deconv(input_channels, output_channels):
    return nn.Sequential(
        nn.ConvTranspose2d(input_channels, output_channels, kernel_size = 4,
                           stride = 2, padding=1),
        nn.ReLU()
    )

class Unet(nn.Module):
    def __init__(self, input_channels, output_channels, kernel_size):
        super(Unet, self).__init__()
        self.input_channels = input_channels
        self.conv1 = conv(input_channels, 64, kernel_size=kernel_size, stride=2)
        self.conv2 = conv(64, 128, kernel_size=kernel_size, stride=2)
        self.conv2_1 = conv(128, 128, kernel_size=kernel_size, stride=1)
        self.conv3 = conv(128, 256, kernel_size=kernel_size, stride=2)
        self.conv3_1 = conv(256, 256, kernel_size=kernel_size, stride=1)
        self.conv4 = conv(256, 512, kernel_size=kernel_size, stride=2)
        self.conv4_1 = conv(512, 512, kernel_size=kernel_size, stride=1)

        self.deconv3 = deconv(512, 128)
        self.deconv2 = deconv(384, 64)
        self.deconv1 = deconv(192, 32)
        self.deconv0 = deconv(96, 16)

        self.output_layer = nn.Conv2d(16 + input_channels, output_channels, kernel_size=kernel_size,
                                      stride = 1, padding=(kernel_size - 1) // 2)

    def forward(self, x):
        out_conv1 = self.conv1(x)
        out_conv2 = self.conv2_1(self.conv2(out_conv1))
        out_conv3 = self.conv3_1(self.conv3(out_conv2))
        out_conv4 = self.conv4_1(self.conv4(out_conv3))

        out_deconv3 = self.deconv3(out_conv4)
        concat3 = torch.cat((out_conv3, out_deconv3), 1)
        out_deconv2 = self.deconv2(concat3)
        concat2 = torch.cat((out_conv2, out_deconv2), 1)
        out_deconv1 = self.deconv1(concat2)
        concat1 = torch.cat((out_conv1, out_deconv1), 1)
        out_deconv0 = self.deconv0(concat1)
        concat0 = torch.cat((x, out_deconv0), 1)
        out = self.output_layer(concat0)
        return out

class Resblock(nn.Module):
    def __init__(self, input_channels, hidden_dim, kernel_size):
        super(Resblock, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(input_channels, hidden_dim, kernel_size = kernel_size, padding = (kernel_size-1)//2),
            nn.BatchNorm2d(hidden_dim),
            nn.LeakyReLU()
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(hidden_dim, hidden_dim, kernel_size = kernel_size, padding = (kernel_size-1)//2),
            nn.BatchNorm2d(hidden_dim),
            nn.LeakyReLU()
        )

        if input_channels != hidden_dim:
            self.upscale = nn.Sequential(
                nn.Conv2d(input_channels, hidden_dim, kernel_size = kernel_size, padding = (kernel_size-1)//2),
                nn.LeakyReLU()
                )
        self.input_channels = input_channels
        self.hidden_dim = hidden_dim

    def forward(self, xx):
        out = self.layer1(xx)
        if self.input_channels != self.hidden_dim:
            out = self.layer2(out) + self.upscale(xx)
        else:
            out = self.layer2(out) + xx
        return out

class ResNet(nn.Module):
    def __init__(self, input_channels, output_channels, kernel_size):
        super(ResNet, self).__init__()
        layers = [Resblock(input_channels, 64, kernel_size), Resblock(64, 64, kernel_size)]
        layers += [Resblock(64, 128, kernel_size), Resblock(128, 128, kernel_size)]
        layers += [Resblock(128, 256, kernel_size), Resblock(256, 256, kernel_size)]
        layers += [Resblock(256, 512, kernel_size), Resblock(512, 512, kernel_size)]
        layers += [nn.Conv2d(512, output_channels, kernel_size = kernel_size, padding = (kernel_size-1)//2)]
        self.model = nn.Sequential(*layers)

    def forward(self, xx):
        out = self.model(xx)
        return out


from unittest import TestCase

from mock import patch, Mock

from gofer.devel import ipatch

with ipatch('qpid'):
    from gofer.messaging.adapter.qpid import model
    from gofer.messaging.adapter.qpid.model import Error, Method
    from gofer.messaging.adapter.qpid.model import Exchange, BaseExchange
    from gofer.messaging.adapter.qpid.model import Queue, BaseQueue

class TestError(TestCase):

    def test_init(self):
        code = 18
        description = '12345'
        error = Error(description, code)
        self.assertEqual(error.code, code)
        self.assertEqual(error.args[0], description)

class TestMethod(TestCase):

    @patch('gofer.messaging.adapter.qpid.model.Connection')
    def test_init(self, _connection):
        url = 'test-url'
        name = model.CREATE
        arguments = {'a': 1}
        method = Method(url, name, arguments)
        _connection.assert_called_once_with(url)
        self.assertEqual(method.url, url)
        self.assertEqual(method.name, name)
        self.assertEqual(method.arguments, arguments)
        self.assertEqual(method.connection, _connection.return_value)
        self.assertEqual(method.session, None)
        self.assertEqual(method.sender, None)
        self.assertEqual(method.receiver, None)

    def test_content(self):
        url = 'test-url'
        name = model.CREATE
        arguments = {'a': 1}
        method = Method(url, name, arguments)
        self.assertEqual(
            method.content,
            {
                '_object_id': model.OBJECT_ID,
                '_method_name': name,
                '_arguments': arguments
            })

    def test_properties(self):
        url = 'test-url'
        method = Method(url, model.CREATE, {})
        self.assertEqual(
            method.properties,
            {
                'qmf.opcode': '_method_request',
                'x-amqp-0-10.app-id': 'qmf2',
                'method': 'request'
            })

    def test_reply_succeeded(self):
        url = 'test-url'
        content = ''
        properties = {
            'qmf.opcode': ''
        }
        reply = Mock(content=content, properties=properties)
        method = Method(url, '', {})
        method.on_reply(reply)

    def test_reply_failed(self):
        url = 'test-url'
        values = {
            'error_code': 18,
            'error_text': 'just failed'
        }
        content = {'_values': values}
        properties = {
            'qmf.opcode': '_exception'
        }
        reply = Mock(content=content, properties=properties)
        method = Method(url, '', {})
        self.assertRaises(Error, method.on_reply, reply)

    def test_reply_already_exists(self):
        url = 'test-url'
        values = {
            'error_code': model.EEXIST,
            'error_text': 'just failed'
        }
        content = {'_values': values}
        properties = {
            'qmf.opcode': '_exception'
        }
        reply = Mock(content=content, properties=properties)
        method = Method(url, '', {})
        method.on_reply(reply)

    @patch('gofer.messaging.adapter.qpid.model.uuid4')
    @patch('gofer.messaging.adapter.qpid.model.Connection')
    def test_open(self, _connection, uuid):
        url = 'url-test'
        uuid.return_value = '5138'
        connection = Mock()
        _connection.return_value = connection
        session = Mock()
        session.close.side_effect = ValueError
        sender = Mock()
        sender.close.side_effect = ValueError
        receiver = Mock()
        receiver.close.side_effect = ValueError
        connection.session.return_value = session
        session.receiver.return_value = receiver
        session.sender.return_value = sender
        reply_to = model.REPLY_TO % uuid.return_value

        # test
        method = Method(url, '', {})
        method.open()

        # validation
        connection.open.assert_called_once_with()
        session.sender.assert_called_once_with(model.ADDRESS)
        session.receiver.assert_called_once_with(reply_to)
        self.assertEqual(method.connection, connection)
        self.assertEqual(method.sender, sender)
        self.assertEqual(method.receiver, receiver)

    @patch('gofer.messaging.adapter.qpid.model.Connection', Mock())
    def test_open_already(self):
        # test
        method = Method('', '', {})
        method.is_open = Mock(return_value=True)
        method.open()

        # validation
        self.assertFalse(method.connection.open.called)

    @patch('gofer.messaging.adapter.qpid.model.uuid4')
    @patch('gofer.messaging.adapter.qpid.model.Method.close')
    @patch('gofer.messaging.adapter.qpid.model.Connection')
    def test_repair(self, _connection, close, uuid):
        url = 'url-test'
        uuid.return_value = '5138'
        connection = Mock()
        _connection.return_value = connection
        session = Mock()
        session.close.side_effect = ValueError
        sender = Mock()
        sender.close.side_effect = ValueError
        receiver = Mock()
        receiver.close.side_effect = ValueError
        connection.session.return_value = session
        session.receiver.return_value = receiver
        session.sender.return_value = sender
        reply_to = model.REPLY_TO % uuid.return_value

        # test
        method = Method(url, '', {})
        method.repair()

        # validation
        close.assert_called_once_with()
        connection.close.assert_called_once_with()
        connection.open.assert_called_once_with()
        session.sender.assert_called_once_with(model.ADDRESS)
        session.receiver.assert_called_once_with(reply_to)
        self.assertEqual(method.connection, connection)
        self.assertEqual(method.sender, sender)
        self.assertEqual(method.receiver, receiver)

    def test_close(self):
        connection = Mock()
        session = Mock(connection=connection)
        sender = Mock()
        receiver = Mock()
        method = Method('', '', {})
        method.connection = connection
        method.session = session
        method.sender = sender
        method.receiver = receiver

        session.close.side_effect = ValueError
        sender.close.side_effect = ValueError
        receiver.close.side_effect = ValueError

        # test
        method.close()

        # validation
        receiver.close.assert_called_once_with()
        sender.close.assert_called_once_with()
        session.close.assert_called_once_with()
        self.assertFalse(connection.close.called)

    @patch('gofer.messaging.adapter.qpid.model.uuid4')
    @patch('gofer.messaging.adapter.qpid.model.Message')
    def test_call(self, message, uuid):
        url = 'url-test'
        name = model.CREATE
        arguments = {'a': 1}

        # test
        method = Method(url, name, arguments)
        method.reply_to = '234'
        method.open = Mock()
        method.close = Mock()
        method.session = Mock()
        method.sender = Mock()
        method.receiver = Mock()
        method.on_reply = Mock()
        method()

        # validation
        method.open.assert_called_once_with()
        message.assert_called_once_with(
            content=method.content,
            reply_to=method.reply_to,
            properties=method.properties,
            correlation_id=str(uuid.return_value).encode(),
            subject=model.SUBJECT
        )

        method.session.acknowledge.assert_called_once_with()
        method.sender.send.assert_called_once_with(message.return_value)
        method.on_reply.assert_called_once_with(method.receiver.fetch.return_value)
        method.close.assert_called_once_with()

class TestExchange(TestCase):

    def test_init(self):
        name = 'test-exchange'
        policy = 'direct'

        # test
        exchange = Exchange(name, policy=policy)

        # validation
        self.assertTrue(isinstance(exchange, BaseExchange))
        self.assertEqual(exchange.name, name)
        self.assertEqual(exchange.policy, policy)

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_declare(self, method):
        url = 'test-url'

        # test
        exchange = Exchange('test', policy='direct')
        exchange.durable = 0
        exchange.auto_delete = 1
        exchange.declare(url)

        # validation
        arguments = {
            'strict': True,
            'name': exchange.name,
            'type': 'exchange',
            'exchange-type': exchange.policy,
            'properties': {
                'auto-delete': exchange.auto_delete,
                'durable': exchange.durable
            }
        }
        method.assert_called_once_with(url, model.CREATE, arguments)
        method.return_value.assert_called_once_with()

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_delete(self, method):
        url = 'test-url'

        # test
        exchange = Exchange('test')
        exchange.delete(url)

        # validation
        arguments = {
            'strict': True,
            'name': exchange.name,
            'type': 'exchange',
            'properties': {}
        }
        method.assert_called_once_with(url, model.DELETE, arguments)
        method.return_value.assert_called_once_with()

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_bind(self, method):
        url = 'test-url'
        queue = Queue('test-queue')

        # test
        exchange = Exchange('test')
        exchange.bind(queue, url)

        # validation
        arguments = {
            'strict': True,
            'name': '/'.join((exchange.name, queue.name, queue.name)),
            'type': 'binding',
            'properties': {}
        }
        method.assert_called_once_with(url, model.CREATE, arguments)
        method.return_value.assert_called_once_with()

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_unbind(self, method):
        url = 'test-url'
        queue = Queue('test-queue')

        # test
        exchange = Exchange('test')
        exchange.unbind(queue, url)

        # validation
        arguments = {
            'strict': True,
            'name': '/'.join((exchange.name, queue.name, queue.name)),
            'type': 'binding',
            'properties': {}
        }
        method.assert_called_once_with(url, model.DELETE, arguments)
        method.return_value.assert_called_once_with()

class TestQueue(TestCase):

    def test_init(self):
        name = 'test-queue'

        # test
        queue = Queue(name)

        # validation
        self.assertTrue(isinstance(queue, BaseQueue))
        self.assertEqual(queue.name, name)

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_declare(self, method):
        url = 'test-url'

        # test
        queue = Queue('test-queue')
        queue.durable = 0
        queue.auto_delete = True
        queue.expiration = 10
        queue.exclusive = 3
        queue.declare(url)

        # validation
        arguments = {
            'strict': True,
            'name': queue.name,
            'type': 'queue',
            'properties': {
                'exclusive': queue.exclusive,
                'auto-delete': queue.auto_delete,
                'durable': queue.durable
            }
        }
        method.assert_called_once_with(url, model.CREATE, arguments)
        method.return_value.assert_called_once_with()

    @patch('gofer.messaging.adapter.qpid.model.Method')
    def test_delete(self, method):
        url = 'test-url'

        # test
        queue = Queue('test-queue')
        queue.delete(url)

        # validation
        arguments = {
            'strict': True,
            'name': queue.name,
            'type': 'queue',
            'properties': {}
        }
        method.assert_called_once_with(url, model.DELETE, arguments)
        method.return_value.assert_called_once_with()


from src.Database.EnrollmentObjectMapper import EnrollmentObjectMapper
import pytest
from unittest.mock import Mock, patch
# import src.Database.DatabaseHelper as DatabaseHelperFile
from src.Database.DatabaseHelper import DatabaseHelper

# Everything here has been tested in other classes
# This suggests my design can be improved
# @patch('__main__.DatabaseHelper', 'getInstance', autospec=True)
@patch('__main__.DatabaseHelper', 'getInstance', autospec=True)
def test_insert():
    enrollable = Mock()
    enrollable.section_number = 0
    enrollable.course_id = 241
    enrollable.department = 'POTS'
    enrollable.student_id = 178
    db_helper = Mock()
    db_helper.insert.return_value = True
    DatabaseHelper.getInstance.return_value = db_helper
    mapper = EnrollmentObjectMapper.getInstance()
    rv = mapper.insert(enrollable)
    assert rv == True


from models.modules import *
from models.cycleGAN import CycleGAN
from utils import helper
from evaluation.vis import *
import numpy as np
import tensorflow as tf
import pprint
import pandas as pd

#=========================================================================
#
#  This file implements our method for synthetic data generation, which
#  consists of four CycleGANs and a classifier.
#
#=========================================================================

class QuadCycleGAN():

    def __init__(self,
                 X_source_1, X_target_1, source_name_1, target_name_1,
                 X_source_2, X_target_2, source_name_2, target_name_2,
                 X_source_3, X_target_3, source_name_3, target_name_3,
                 X_source_4, X_target_4, source_name_4, target_name_4,
                 session_id, dim_g, dim_d, dim_c,
                 save_path, GPU_CONFIG,
                 lr, keep_probs,batch_size, train_epochs,
                 lambda_cyc, lambda_cls, params=None):
        self.X_source_1 = X_source_1
        self.X_target_1 = X_target_1
        self.source_name_1 = source_name_1
        self.target_name_1 = target_name_1
        self.X_source_2 = X_source_2
        self.X_target_2 = X_target_2
        self.source_name_2 = source_name_2
        self.target_name_2 = target_name_2
        self.X_source_3 = X_source_3
        self.X_target_3 = X_target_3
        self.source_name_3 = source_name_3
        self.target_name_3 = target_name_3
        self.X_source_4 = X_source_4
        self.X_target_4 = X_target_4
        self.source_name_4 = source_name_4
        self.target_name_4 = target_name_4
        self.session_id = session_id
        self.dim_g = dim_g
        self.dim_d = dim_d
        self.dim_c = dim_c
        self.save_path = save_path
        self.GPU_CONFIG = GPU_CONFIG
        self.lr = lr
        self.keep_probs = keep_probs
        self.batch_size = batch_size
        self.train_epochs = train_epochs
        self.lambda_cyc = lambda_cyc
        self.lambda_cls = lambda_cls
        self.params = params
        self.cgan_1 = CycleGAN(self.X_source_1, self.X_target_1,
                               self.source_name_1, self.target_name_1,
                               self.session_id, self.dim_g, self.dim_d,
                               save_path=self.save_path+'/'+ \
                                           self.target_name_1+'/',
                               GPU_CONFIG=self.GPU_CONFIG,
                               batch_size=self.batch_size,
                               train_epochs=self.train_epochs,
                               lambda_cyc=self.lambda_cyc,
                               params=self.params[
                                   self.source_name_1+'2'+self.target_name_1
                               ])
        self.cgan_2 = CycleGAN(self.X_source_2, self.X_target_2,
                               self.source_name_2, self.target_name_2,
                               self.session_id, self.dim_g, self.dim_d,
                               save_path=self.save_path+'/'+ \
                                           self.target_name_2+'/',
                               GPU_CONFIG=self.GPU_CONFIG,
                               batch_size=self.batch_size,
                               train_epochs=self.train_epochs,
                               lambda_cyc=self.lambda_cyc,
                               params=self.params[
                                   self.source_name_2+'2'+self.target_name_2
                               ])
        self.cgan_3 = CycleGAN(self.X_source_3, self.X_target_3,
                               self.source_name_3, self.target_name_3,
                               self.session_id, self.dim_g, self.dim_d,
                               save_path=self.save_path+'/'+ \
                                           self.target_name_3+'/',
                               GPU_CONFIG=self.GPU_CONFIG,
                               batch_size=self.batch_size,
                               train_epochs=self.train_epochs,
                               lambda_cyc=self.lambda_cyc,
                               params=self.params[
                                   self.source_name_3+'2'+self.target_name_3
                               ])
        self.cgan_4 = CycleGAN(self.X_source_4, self.X_target_4,
                               self.source_name_4, self.target_name_4,
                               self.session_id, self.dim_g, self.dim_d,
                               save_path=self.save_path+'/'+ \
                                           self.target_name_4+'/',
                               GPU_CONFIG=self.GPU_CONFIG,
                               batch_size=self.batch_size,
                               train_epochs=self.train_epochs,
                               lambda_cyc=self.lambda_cyc,
                               params=self.params[
                                   self.source_name_4+'2'+self.target_name_4
                               ])

    def build(self):
        self.lr_d = tf.placeholder(tf.float32)
        self.lr_g = tf.placeholder(tf.float32)
        self.cgan_1.build(encoder_id='encoder_1',
                          decoder_id='decoder_1',
                          discriminator_id_A='discriminator_A_1',
                          discriminator_id_B='discriminator_B_1')
        self.cgan_2.build(encoder_id='encoder_2',
                          decoder_id='decoder_2',
                          discriminator_id_A='discriminator_A_2',
                          discriminator_id_B='discriminator_B_2')
        self.cgan_3.build(encoder_id='encoder_3',
                          decoder_id='decoder_3',
                          discriminator_id_A='discriminator_A_3',
                          discriminator_id_B='discriminator_B_3')
        self.cgan_4.build(encoder_id='encoder_4',
                          decoder_id='decoder_4',
                          discriminator_id_A='discriminator_A_4',
                          discriminator_id_B='discriminator_B_4')
        self.d_loss = self.cgan_1.d_loss + self.cgan_2.d_loss + \
                        self.cgan_3.d_loss + self.cgan_4.d_loss
        self.g_loss = self.cgan_1.g_loss + self.cgan_2.g_loss + \
                        self.cgan_3.g_loss + self.cgan_4.g_loss
        # define classification loss
        if self.lambda_cls > 0:
            self.keep_prob_cls = tf.placeholder(tf.float32)
            syn = tf.concat([self.cgan_1.encoding_A,
                             self.cgan_2.encoding_A,
                             self.cgan_3.encoding_A,
                             self.cgan_4.encoding_A], axis=0)
            logits = discriminator(syn, self.dim_c, 'classifier',
                                   keep_prob=self.keep_prob_cls)
            self.labels = tf.placeholder(tf.int64, shape=(None,))
            self.c_loss = tf.reduce_mean(
                tf.nn.sparse_softmax_cross_entropy_with_logits(
                    logits=logits, labels=self.labels
                )
            )
            self.g_loss += self.lambda_cls*self.c_loss

    def set_optimizer(self):
        t_vars = tf.trainable_variables()
        self.saver = tf.train.Saver(t_vars)
#         pprint.pprint(t_vars)
        d_vars = [var for var in t_vars
                  if 'discriminator' in var.name or 'encoder' in var.name]
        g_vars = [var for var in t_vars
                  if 'encoder' in var.name or 'decoder' in var.name or \
                  'classifier' in var.name]
        self.D_optimizer = tf.train.AdamOptimizer(
            self.lr_d).minimize(self.d_loss, var_list=d_vars)
        self.G_optimizer = tf.train.AdamOptimizer(
            self.lr_g).minimize(self.g_loss, var_list=g_vars)

    def feed_losses(self, sess, losses, epoch):
        d_l_1, g_l_1 = sess.run([self.cgan_1.d_loss, self.cgan_1.g_loss],
                                feed_dict={
                                    self.cgan_1.input_A: self.X_source_1,
                                    self.cgan_1.input_B: self.X_target_1,
                                    self.cgan_1.keep_prob: 1.0
                                }
                               )
        d_l_2, g_l_2 = sess.run([self.cgan_2.d_loss, self.cgan_2.g_loss],
                                feed_dict={
                                    self.cgan_2.input_A: self.X_source_2,
                                    self.cgan_2.input_B: self.X_target_2,
                                    self.cgan_2.keep_prob: 1.0
                                }
                               )
        d_l_3, g_l_3 = sess.run([self.cgan_3.d_loss, self.cgan_3.g_loss],
                                feed_dict={
                                    self.cgan_3.input_A: self.X_source_3,
                                    self.cgan_3.input_B: self.X_target_3,
                                    self.cgan_3.keep_prob: 1.0
                                }
                               )
        d_l_4, g_l_4 = sess.run([self.cgan_4.d_loss, self.cgan_4.g_loss],
                                feed_dict={
                                    self.cgan_4.input_A: self.X_source_4,
                                    self.cgan_4.input_B: self.X_target_4,
                                    self.cgan_4.keep_prob: 1.0
                                }
                               )
        print('CycleGAN_1 - Epoch %i: D Loss: %f, G Loss: %f;' % (epoch,
                                                                  d_l_1,
                                                                  g_l_1))
        print('CycleGAN_2 - Epoch %i: D Loss: %f, G Loss: %f;' % (epoch,
                                                                  d_l_2,
                                                                  g_l_2))
        print('CycleGAN_3 - Epoch %i: D Loss: %f, G Loss: %f;' % (epoch,
                                                                  d_l_3,
                                                                  g_l_3))
        print('CycleGAN_4 - Epoch %i: D Loss: %f, G Loss: %f;' % (epoch,
                                                                  d_l_4,
                                                                  g_l_4))
        losses['d1'].append(d_l_1)
        losses['g1'].append(g_l_1)
        losses['d2'].append(d_l_2)
        losses['g2'].append(g_l_2)
        losses['d3'].append(d_l_3)
        losses['g3'].append(g_l_3)
        losses['d4'].append(d_l_4)
        losses['g4'].append(g_l_4)
        return losses

    def generate_synthetic_samples(self, sess, save=True):
        # synthetic samples for source 1
        enc_1 = sess.run(self.cgan_1.encoding_A,
                         feed_dict={self.cgan_1.input_A: self.X_source_1,
                                    self.cgan_1.input_B: self.X_target_1,
                                    self.cgan_1.keep_prob: 1.0}
                        )
        enc_1_df = pd.DataFrame(
            enc_1, index=[v+"_syn_"+self.target_name_1
                          for v in self.X_source_1.index.values])
        enc_1_df.columns = self.X_source_1.columns.values
        if save:
            enc_1_df.to_hdf(
                self.save_path+'syn_samples/syn_'+self.session_id+'.h5',
                key=self.target_name_1
            )
        # synthetic samples for source 2
        enc_2 = sess.run(self.cgan_2.encoding_A,
                         feed_dict={self.cgan_2.input_A: self.X_source_2,
                                    self.cgan_2.input_B: self.X_target_2,
                                    self.cgan_2.keep_prob: 1.0}
                        )
        enc_2_df = pd.DataFrame(
            enc_2, index=[v+"_syn_"+self.target_name_2
                          for v in self.X_source_2.index.values])
        enc_2_df.columns = self.X_source_2.columns.values
        if save:
            enc_2_df.to_hdf(
                self.save_path+'syn_samples/syn_'+self.session_id+'.h5',
                key=self.target_name_2
            )
        # synthetic samples for source 3
        enc_3 = sess.run(self.cgan_3.encoding_A,
                         feed_dict={self.cgan_3.input_A: self.X_source_3,
                                    self.cgan_3.input_B: self.X_target_3,
                                    self.cgan_3.keep_prob: 1.0})
        enc_3_df = pd.DataFrame(
            enc_3, index=[v+"_syn_"+self.target_name_3
                          for v in self.X_source_3.index.values])
        enc_3_df.columns = self.X_source_3.columns.values
        if save:
            enc_3_df.to_hdf(
                self.save_path+'syn_samples/syn_'+self.session_id+'.h5',
                key=self.target_name_3)
        # synthetic samples for source 4
        enc_4 = sess.run(self.cgan_4.encoding_A,
                         feed_dict={self.cgan_4.input_A: self.X_source_4,
                                    self.cgan_4.input_B: self.X_target_4,
                                    self.cgan_4.keep_prob: 1.0}
                        )
        enc_4_df = pd.DataFrame(
            enc_4, index=[v+"_syn_"+self.target_name_4
                          for v in self.X_source_4.index.values])
        enc_4_df.columns = self.X_source_4.columns.values
        if save:
            enc_4_df.to_hdf(
                self.save_path+'syn_samples/syn_'+self.session_id+'.h5',
                key=self.target_name_4)

    def learn_representation(self):
        tf.reset_default_graph()
        self.build()
        self.set_optimizer()
        t_vars = tf.trainable_variables()
        pprint.pprint(t_vars)
        # start training
        losses = {'d1': [], 'g1': [], 'd2': [], 'g2': [], 'd3': [], 'g3': [],
                  'd4': [], 'g4': [],}
        init = tf.global_variables_initializer()
        with tf.Session(config=self.GPU_CONFIG) as sess:
            sess.run(init)
            for epoch in range(self.train_epochs+1):
                X_source_1_shuffle = self.X_source_1.sample(frac=1)
                X_target_1_shuffle = self.X_target_1.sample(frac=1)
                X_source_2_shuffle = self.X_source_2.sample(frac=1)
                X_target_2_shuffle = self.X_target_2.sample(frac=1)
                X_source_3_shuffle = self.X_source_3.sample(frac=1)
                X_target_3_shuffle = self.X_target_3.sample(frac=1)
                X_source_4_shuffle = self.X_source_4.sample(frac=1)
                X_target_4_shuffle = self.X_target_4.sample(frac=1)
                length_source_1 = int(
                    len(X_source_1_shuffle) / self.batch_size)
                length_target_1 = int(
                    len(X_target_1_shuffle) / self.batch_size)
                length_source_2 = int(
                    len(X_source_2_shuffle) / self.batch_size)
                length_target_2 = int(
                    len(X_target_2_shuffle) / self.batch_size)
                length_source_3 = int(
                    len(X_source_3_shuffle) / self.batch_size)
                length_target_3 = int(
                    len(X_target_3_shuffle) / self.batch_size)
                length_source_4 = int(
                    len(X_source_4_shuffle) / self.batch_size)
                length_target_4 = int(
                    len(X_target_4_shuffle) / self.batch_size)
                lr_d_current = self.lr['d']*(0.8**int(epoch / 50))
                lr_g_current = self.lr['g']*(0.8**int(epoch / 50))
                if self.lambda_cls > 0:
                    labels = np.concatenate(
                        [[i]*self.batch_size for i in range(4)]
                    )
                for i in range(min([length_source_1, length_target_1,
                                    length_source_2, length_target_2,
                                    length_source_3, length_target_3,
                                    length_source_4, length_target_4])):
                    X_source_1_batch = X_source_1_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_target_1_batch = X_target_1_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_source_2_batch = X_source_2_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_target_2_batch = X_target_2_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_source_3_batch = X_source_3_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_target_3_batch = X_target_3_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_source_4_batch = X_source_4_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    X_target_4_batch = X_target_4_shuffle.iloc[
                        i*self.batch_size : (i+1)*self.batch_size]
                    sess.run([self.D_optimizer],
                             feed_dict={
                                 self.cgan_1.input_A: X_source_1_batch,
                                 self.cgan_1.input_B: X_target_1_batch,
                                 self.cgan_2.input_A: X_source_2_batch,
                                 self.cgan_2.input_B: X_target_2_batch,
                                 self.cgan_3.input_A: X_source_3_batch,
                                 self.cgan_3.input_B: X_target_3_batch,
                                 self.cgan_4.input_A: X_source_4_batch,
                                 self.cgan_4.input_B: X_target_4_batch,
                                 self.cgan_1.keep_prob: self.keep_probs['d'],
                                 self.cgan_2.keep_prob: self.keep_probs['d'],
                                 self.cgan_3.keep_prob: self.keep_probs['d'],
                                 self.cgan_4.keep_prob: self.keep_probs['d'],
                                 self.lr_d: lr_d_current
                             })
                    for _ in range(2):
                        feed_dict={
                            self.cgan_1.input_A: X_source_1_batch,
                            self.cgan_1.input_B: X_target_1_batch,
                            self.cgan_2.input_A: X_source_2_batch,
                            self.cgan_2.input_B: X_target_2_batch,
                            self.cgan_3.input_A: X_source_3_batch,
                            self.cgan_3.input_B: X_target_3_batch,
                            self.cgan_4.input_A: X_source_4_batch,
                            self.cgan_4.input_B: X_target_4_batch,
                            self.cgan_1.keep_prob: self.keep_probs['g'],
                            self.cgan_2.keep_prob: self.keep_probs['g'],
                            self.cgan_3.keep_prob: self.keep_probs['g'],
                            self.cgan_4.keep_prob: self.keep_probs['g'],
                            self.lr_g: lr_g_current
                        }
                        if self.lambda_cls > 0:
                            feed_dict[self.keep_prob_cls] = self.keep_probs['c']
                            feed_dict[self.labels] = labels
                            sess.run([self.G_optimizer], feed_dict=feed_dict)
                        else:
                            sess.run([self.G_optimizer], feed_dict=feed_dict)

                if epoch % 10 == 0:
                    losses = self.feed_losses(sess, losses, epoch)
            # save losses
            pd.DataFrame(losses).to_hdf(
                self.save_path+'losses/losses_'+self.session_id+'.h5',
                key='quad_cycle')
            # generate synthetic samples with transferred emotions
            self.generate_synthetic_samples(sess)


import json
import os
import random
from collections import defaultdict
from typing import List, Optional

from pytorch_lightning import LightningDataModule
from torch.utils.data import DataLoader, Dataset

class GAD_Dataset(Dataset):
    def __init__(self, data_dir, split: str):
        with open(os.path.join(data_dir, f"{split}.json")) as f:
            """
            'id': '0'
            'sentence': 'this study proposes that A/A genotype at position -607 in @GENE$ gene can be used as a new genetic maker in Thai population for predicting @DISEASE$ development.'
            'label': '1'
            """
            self.data = [
                json.loads(line)
                for line in f
            ]
            for d in self.data:
                if d["label"] == '0':
                    d["label"] = 'no answer'
                else: # '1'
                    d["label"] = 'has answer'
                d["sentence"] = d["sentence"][0].upper() + d["sentence"][1:]
                assert "@GENE$" in d["sentence"] and "@DISEASE$" in d["sentence"]
                # unused
                d["entity1"] = ["@GENE$", "GENE", -1, -1]
                d["entity2"] = ["@DISEASE$", "DISEASE", -1, -1]

    def __getitem__(self, idx) -> dict:
        ret: dict = self.data[idx]
        ret["dataset_name"] = "GAD"
        return ret

    def __len__(self):
        return len(self.data)

    @staticmethod
    def collate_fn(samples: List[dict]):
        ret = defaultdict(list)
        for sample in samples:
            for k, v in sample.items():
                ret[k].append(v)
        ret["LABEL_VERBALIZER"] = DataModule.LABEL_VERBALIZER
        return ret

def hypo_template(w1, w2, verbalized, abstain=True, **kwargs):
    """
    w1 and w2 must be @GENE#, @DISEASE#
    verbalized either no answer or has answer
    """
    assert abstain
    if verbalized == "no answer":
        hypo = f"There is no relation between {w1} and {w2}."
    else:
        hypo = f"{w1} and {w2} are correlated."
    return hypo[0].upper() + hypo[1:]

class DataModule(LightningDataModule):
    LABEL_VERBALIZER = {
        "has answer": "has answer",
        "no answer": "no answer"
    }

    def __init__(self, data_dir, adaptive_neg_sample: bool = False,
                 # dataloader
                 batch_size: int = 64, num_workers: int = 0, pin_memory: bool = False,
                 **kwargs):
        super().__init__()
        assert os.path.exists(data_dir)
        self.datasets = {}
        self.save_hyperparameters(logger=False)

    def setup(self, stage: Optional[str] = None):
        for split in ["train", "dev", "test"]:
            self.datasets[split] = GAD_Dataset(self.hparams.data_dir, split)

    def load_dataloader(self, split: str):
        return DataLoader(
            self.datasets[split],
            num_workers=self.hparams.num_workers,
            pin_memory=self.hparams.pin_memory,
            collate_fn=GAD_Dataset.collate_fn,
            batch_size=self.hparams.batch_size,
            shuffle=(split == "train"),
        )

    def train_dataloader(self):
        return self.load_dataloader("train")

    def val_dataloader(self):
        return self.load_dataloader("dev")

    def test_dataloader(self):
        return self.load_dataloader("test")

    def predict_dataloader(self):
        return [self.train_dataloader(), self.test_dataloader()]

    @staticmethod
    def random_neg_sample(batch: dict, num_negs: int = 1) -> dict:
        """
        randomly sample 1 from all possible labels
        :return: new batch with field "neg_label" List[List[str]] where List[str] is num_negs-len neg samples
        """
        neg = [
            random.sample(list(filter(
                lambda l: l != label,
                DataModule.LABEL_VERBALIZER
            )), k=num_negs)
            for label in batch["label"]
        ]
        assert len(neg) == len(batch["label"])
        batch["neg_label"] = neg
        return batch


import heapq
import sys
from collections import defaultdict

class Dijkstras:

    def find_shortest(self, adjs, N):
        graph = defaultdict(list)
        for u, v, w in adjs:
            graph[u].append((v, w))

        distance = [sys.maxsize] * N
        distance[0] = 0
        pq = [[0, 0]]  # cost, node
        visited = [False] * N
        while pq:
            curr_dist, node = heapq.heappop(pq)
            visited[node] = True
            for nei, nei_cost in graph[node]:
                if not visited[nei]:
                    distance[nei] = min(distance[nei], curr_dist + nei_cost)
                    heapq.heappush(pq, (distance[nei], nei))
        return distance

if __name__ == '__main__':
    init = Dijkstras()
    conn = [
        [0, 1, 3],
        [0, 2, 2],
        [1, 2, 8],
        [1, 5, 2],
        [2, 4, 7],
        [3, 1, 9],
        [3, 5, 1],
        [5, 7, 1],
        [6, 2, 6],
        [6, 4, 7],
        [7, 5, 7],
        [7, 6, 2],
    ]
    print(init.find_shortest(conn, 8))


from typing import Optional
from urllib.parse import urljoin
from datetime import date

class Customer:
    def __init__(self,
        id: str,
        dateCreated: date,
        name: str,
        cpfCnpj: str,
        **kwargs
    ) -> None:

        self.id                   = id
        self.dateCreated          = dateCreated if type(dateCreated) == date else date.fromisoformat(dateCreated)
        self.name                 = name
        self.cpfCnpj              = cpfCnpj
        self.email                = kwargs.get('email', None)
        self.phone                = kwargs.get('phone', None)
        self.mobilePhone          = kwargs.get('mobilePhone', None)
        self.address              = kwargs.get('address', None)
        self.addressNumber        = kwargs.get('addressNumber', None)
        self.complement           = kwargs.get('complement', None)
        self.province             = kwargs.get('province', None)
        self.postalCode           = kwargs.get('postalCode', None)
        self.externalReference    = kwargs.get('externalReference', None)
        self.notificationDisabled = kwargs.get('notificationDisabled', None)
        self.additionalEmails     = kwargs.get('additionalEmails', None)
        self.municipalInscription = kwargs.get('municipalInscription', None)
        self.stateInscription     = kwargs.get('stateInscription', None)
        self.observations         = kwargs.get('observations', None)

    def __repr__(self) -> str:
        return f'Customer(id={self.id}, name={self.name}, email={self.email})'


import numpy as np

import torch
import torch.nn as nn

import torchvision.models as models
import torchvision.datasets as datasets
import torchvision.transforms as T

from tqdm import tqdm

def accuracy(output, target):
    with torch.no_grad():
        pred = output.argmax(-1)
        # print(pred, target)
        # print(pred.shape, target.shape)
        correct = (pred == target).float().sum() / len(target)
        return correct

transform = T.Compose([
    T.Resize(224),
    T.CenterCrop(224),
    T.ToTensor(),
    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

val_ds = datasets.ImageFolder("imagenet/val", transform=transform)
val = torch.utils.data.DataLoader(val_ds, batch_size=8, shuffle=False, num_workers=4)

# model = models.mobilenet_v2()
model = torch.load("checkpoints/model.pt")

criterion = nn.CrossEntropyLoss()

model.eval()
accur, losses = [], []
with torch.no_grad():
    for images, target in tqdm(val):

        output = model(images)
        loss = criterion(output, target)

        acc = accuracy(output, target)
        accur.append(acc)

    print(f'Accuracy Val: {np.round(np.mean(accur), 3)}')


import base64
import hashlib

from fastapi.testclient import TestClient
import pytest

from test.conftest import set_preferred_colourmap, unset_preferred_colourmap

class TestChannelSummary:
    @pytest.mark.parametrize(
        "channel_name, expected_summary",
        [
            pytest.param(
                "N_COMP_FF_E",
                {
                    "first_date": "2022-04-07T14:16:16",
                    "most_recent_date": "2022-04-08T16:58:57",
                    "recent_sample": [
                        {"2022-04-08T16:58:57": -8535000.0},
                        {"2022-04-08T16:41:36": -8461000.0},
                        {"2022-04-08T16:29:56": -8582000.0},
                    ],
                },
                id="Scalar channel (number) summary",
            ),
            pytest.param(
                "GEM_SHOT_TYPE_STRING",
                {
                    "first_date": "2022-04-07T14:16:16",
                    "most_recent_date": "2022-04-08T16:58:57",
                    "recent_sample": [
                        {"2022-04-08T16:58:57": "FP"},
                        {"2022-04-08T16:41:36": "FP"},
                        {"2022-04-08T16:29:56": "FP"},
                    ],
                },
                id="Scalar channel (string) summary",
            ),
        ],
    )
    def test_valid_scalar_channel_summary(
        self,
        test_app: TestClient,
        login_and_get_token,
        channel_name,
        expected_summary,
    ):
        test_response = test_app.get(
            f"/channels/summary/{channel_name}",
            headers={"Authorization": f"Bearer {login_and_get_token}"},
        )

        assert test_response.status_code == 200
        assert test_response.json() == expected_summary

    @pytest.mark.parametrize(
        "channel_name, expected_summary, use_preferred_colourmap",
        [
            pytest.param(
                "N_COMP_FF_IMAGE",
                {
                    "first_date": "2022-04-07T14:16:16",
                    "most_recent_date": "2022-04-08T16:58:57",
                    "recent_sample": [
                        {"2022-04-08T16:58:57": "b6a2da4589c22afc212d2dd9079aabe0"},
                        {"2022-04-08T16:41:36": "bff557f25cc563f292d7a65f8cbd6ea4"},
                        {"2022-04-08T16:29:56": "0ed38c29e8eddb50e469b6d6ab4fc5c9"},
                    ],
                },
                False,
                id="Image channel summary (using system default colourmap)",
            ),
            # repeat the above test but with the user's preferred colour map set to
            # check that the preference overrides the system default colour map
            pytest.param(
                "N_COMP_FF_IMAGE",
                {
                    "first_date": "2022-04-07T14:16:16",
                    "most_recent_date": "2022-04-08T16:58:57",
                    "recent_sample": [
                        {"2022-04-08T16:58:57": "3e78b905df05f4b08a188e0fbd7fcc2a"},
                        {"2022-04-08T16:41:36": "d3e6761e20d18344ade71bd5329b1a36"},
                        {"2022-04-08T16:29:56": "183898d6a41f1b3cb1debdcc8ef0942f"},
                    ],
                },
                True,
                id="Image channel summary (using user's preferred colourmap)",
            ),
            pytest.param(
                "N_COMP_SPEC_TRACE",
                {
                    "first_date": "2022-04-07T14:16:16",
                    "most_recent_date": "2022-04-08T16:58:57",
                    "recent_sample": [
                        {"2022-04-08T16:58:57": "c0e0f944d8589c6ac866ffb013a05598"},
                        {"2022-04-08T16:41:36": "6ee54947b79040480bf2a75220d71889"},
                        {"2022-04-08T16:29:56": "928527492ca3bd051d7771c14c61f0f4"},
                    ],
                },
                False,
                id="Waveform channel summary",
            ),
        ],
    )
    def test_valid_thumbnail_channel_summary(
        self,
        test_app: TestClient,
        login_and_get_token,
        channel_name,
        expected_summary,
        use_preferred_colourmap,
    ):

        """
        Compare the response with the expected result, but convert the returned base64
        thumbnails to an MD5 checksum beforehand (to prevent bloating this file with
        long base64 strings)
        """

        set_preferred_colourmap(test_app, login_and_get_token, use_preferred_colourmap)

        test_response = test_app.get(
            f"/channels/summary/{channel_name}",
            headers={"Authorization": f"Bearer {login_and_get_token}"},
        )

        assert test_response.status_code == 200
        json_output = test_response.json()
        for sample in json_output["recent_sample"]:
            for timestamp, checksum in sample.items():
                bytes_thumbnail = base64.b64decode(checksum)
                sample[timestamp] = hashlib.md5(bytes_thumbnail).hexdigest()

        unset_preferred_colourmap(
            test_app,
            login_and_get_token,
            use_preferred_colourmap,
        )

        assert json_output == expected_summary

    @pytest.mark.parametrize(
        "channel_name",
        [
            pytest.param(
                "RANDOM_CHANNEL_NAME",
                id="Channel that doesn't exist",
            ),
            pytest.param(
                1234567,
                id="Integer channel",
            ),
        ],
    )
    def test_invalid_channel_summary(
        self,
        test_app: TestClient,
        login_and_get_token,
        channel_name,
    ):
        test_response = test_app.get(
            f"/channels/summary/{channel_name}",
            headers={"Authorization": f"Bearer {login_and_get_token}"},
        )
        assert test_response.status_code == 400


import sys

import sqlite3
from PyQt5 import QtSql, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QTableWidgetItem, QDialog
import UI.addEditCoffeeForm, UI.addPost, UI.editPost, UI.main

class MyWidget(QMainWindow, UI.main.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle('Кофе')
        self.pushButton.clicked.connect(self.run)
        self.choiceButton.hide()
        self.updateButton.hide()
        self.choiceButton.clicked.connect(self.choice)
        self.db_name = None
        self.new_window = None
        self.updateButton.clicked.connect(self.load_data)

    def run(self):
        try:
            fname = QFileDialog.getOpenFileName(self, 'Выбрать базу данных', '',
                                                'Файл (*.sqlite);;Файл (*.sqlite3);;Все файлы (*)')[0]
            self.db_name = fname
            self.load_data()
            self.choiceButton.show()
            self.updateButton.show()
        except Exception as er:
            print(er)

    def load_data(self):
        con = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        con.setDatabaseName(self.db_name)
        con.open()
        stm = QtSql.QSqlTableModel(parent=self.tableView)
        stm.setTable('Coffee')
        stm.select()
        model = QtSql.QSqlQueryModel()
        model.setQuery("""SELECT * FROM data""")
        model.setHeaderData(1, QtCore.Qt.Horizontal, 'Сорт')
        model.setHeaderData(2, QtCore.Qt.Horizontal, 'Обжарка')
        model.setHeaderData(3, QtCore.Qt.Horizontal, 'Форма')
        model.setHeaderData(4, QtCore.Qt.Horizontal, 'Вкус')
        model.setHeaderData(5, QtCore.Qt.Horizontal, 'Цена')
        model.setHeaderData(6, QtCore.Qt.Horizontal, 'Вес')

        self.tableView.setModel(model)
        self.tableView.setSelectionBehavior(1)

    def choice(self):
        try:
            if self.new_window is None:
                self.new_window = ChoiceWindow(self.db_name)
            self.new_window.show()
        except Exception as er:
            print(er)

class ChoiceWindow(QMainWindow, UI.addEditCoffeeForm.Ui_MainWindow):
    def __init__(self, db_name):
        super().__init__()
        self.db_name = db_name
        self.setupUi(self)
        self.setWindowTitle('Изменение/добавление записей')
        self.con = sqlite3.connect(self.db_name)
        self.selectButton.clicked.connect(self.change)
        self.addPostButton.clicked.connect(self.add_post)
        self.tableWidget.cellClicked.connect(self.sel)
        self.selected_row = None
        self.show_data()
        self.updateButton.clicked.connect(self.show_data)

    def sel(self):
        self.selected_row = self.tableWidget.currentRow() + 1
        self.show_data()

    def item_changed(self, item):
        self.modified[self.titles[item.column()]] = item.text()

    def change(self):
        try:
            if self.selected_row:
                post_id = self.tableWidget.item(self.selected_row - 1, 0).text()
                print(post_id)
                post_id = int(post_id)
                edit_form = ChangePost(post_id, self.db_name)
                edit_form.exec_()
        except Exception as er:
            print(er)

    def add_post(self):
        add_form = AddPost(self.db_name)
        add_form.exec_()

    def show_data(self):
        cur = self.con.cursor()
        result = cur.execute("SELECT * FROM data").fetchall()
        self.tableWidget.setRowCount(len(result))
        if not result:
            self.statusBar().showMessage('Ничего не нашлось')
            return
        else:
            self.statusBar().showMessage(f"Данные есть")
        self.tableWidget.setColumnCount(len(result[0]))
        self.titles = [description[0] for description in cur.description]
        for i, elem in enumerate(result):
            for j, val in enumerate(elem):
                self.tableWidget.setItem(i, j, QTableWidgetItem(str(val)))

class ChangePost(QDialog, UI.editPost.Ui_Dialog):
    def __init__(self, post_id, db_name):
        super().__init__()
        self.post_id = post_id
        self.setupUi(self)
        self.con = sqlite3.connect(db_name)
        self.pushButton.clicked.connect(self.save)
        cur = self.con.cursor()
        row_data = [str(i) for i in list(cur.execute("""SELECT * FROM data WHERE id = ?""", (self.post_id,)))[0][1:]]
        print(row_data)
        self.sortEdit.setText(row_data[0])
        self.fryEdit.setText(row_data[1])
        self.formEdit.setText(row_data[2])
        self.tasteEdit.setText(row_data[3])
        self.priceEdit.setText(row_data[4])
        self.weightEdit.setText(row_data[5])

    def save(self):
        try:
            cur = self.con.cursor()
            query = """UPDATE data SET name = ?, degree = ?, form = ?, taste = ?, price = ?, volume = ? WHERE id = ?"""
            cur.execute(query, (self.sortEdit.text(), self.fryEdit.text(), self.formEdit.text(),
                                self.tasteEdit.text(), self.priceEdit.text(),
                                self.weightEdit.text(), self.post_id))
            self.con.commit()
            self.accept()
        except Exception as er:
            print(er)

class AddPost(QDialog, UI.addPost.Ui_Dialog):
    def __init__(self, db_name):
        super().__init__()
        self.con = sqlite3.connect(db_name)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.save)

    def save(self):
        try:
            cur = self.con.cursor()
            query = """INSERT INTO data (name, degree, form, taste, price, volume) VALUES (?, ?, ?, ?, ?, ?)"""
            cur.execute(query, (self.sortEdit.text(), self.fryEdit.text(), self.formEdit.text(),
                                self.tasteEdit.text(), self.priceEdit.text(),
                                self.weightEdit.text()))
            self.con.commit()
            self.accept()
        except Exception as er:
            print(er)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWidget()
    ex.show()
    sys.exit(app.exec())


#! /usr/bin/env python

import rospy
from gazebo_msgs.msg import ModelStates
from geometry_msgs.msg import Pose
from std_msgs.msg import Float64

import math

def distance(a, b):
    '''
    2D euclidean distance
    a: Pose
    b: Pose
    '''
    return math.sqrt(math.pow(abs(b.position.x) - abs(a.position.x), 2)
    	+ math.pow(abs(b.position.y) - abs(a.position.y), 2))

def callback(msg):
	idx_iris = msg.name.index("iris")
	idx_person = msg.name.index("static_person")
	iris_pub.publish(msg.pose[idx_iris])
	person_pub.publish(msg.pose[idx_person])

	d = distance(msg.pose[idx_iris], msg.pose[idx_person])
	dist_pub.publish(d)
	error_pub.publish(abs(4.5-d))

rospy.init_node('solution_tester')
rospy.Subscriber('/gazebo/model_states', ModelStates, callback)
iris_pub = rospy.Publisher('/tester/iris', Pose, queue_size=10)
person_pub = rospy.Publisher('/tester/person', Pose, queue_size=10)
dist_pub = rospy.Publisher('/tester/dist', Float64, queue_size=10)
error_pub = rospy.Publisher('/tester/error', Float64, queue_size=10)

rospy.spin()


a, b = map(int, input().split())
c = 1
while a < b:
    if not b % 2:
        b //= 2
    elif b % 10 == 1:
        b //= 10
    else:
        break
    c += 1
print(-1 if a-b else c)


#!usr/local/bin

class Stack:
    def __init__(self):
        """ Using a python list for implementing the Stack class. """
        self.stack = []
        self.size = 0

    def push(self, data):
        """ A push operation that appends new item on top of the Stack. """
        self.stack.append(data)
        self.size += 1

    def pop(self):
        """ A pop operation that takes out the news item from top of the Stack. """
        if self.size == 0:
            raise Exception("The stack is empty!")
        self.size -= 1
        return self.stack.pop()

    def is_empty(self):
        """ A method that checks whether the stack is empty."""
        return self.size == 0

    def __repr__(self):
        """ Stack representation """
        return "stack: " + str(self.stack)

class Queue:
    def __init__(self):
        """ Using a python list for implementing the Queue class. """
        self.queue = []
        self.size = 0

    def is_empty(self):
        """ A function to see if the queue is empty. """
        return self.size == 0

    def enqueue(self, data):
        """ Adding new element to the queue. """
        self.queue.insert(0, data)
        self.size += 1

    def dequeue(self):
        """ A method for taking out the oldest element form queue. """
        if self.size == 0:
            raise Exception("The queue is empty!")
        self.size -= 1
        return self.queue.pop()

    def __repr__(self):
        """ A method for printing out the queue elements. """
        return "queue: " + str(self.queue)

class CircularBuffer:
    def __init__(self, size):
        """ Constructor of a fixed size buffer. """
        self.buffer = [None] * size
        self.low = 0
        self.high = 0
        self.size = size
        self.count = 0

    def is_empty(self):
        """ A method to see if the buffer is empty."""
        return self.count == 0

    def is_full(self):
        """ A method to check if the buffer is full. """
        return self.count == self.size

    def add(self, data):
        """ A method for adding elements to circular buffer. """
        if self.is_full():
            self.low = (self.low + 1) % self.size
        else:
            self.count += 1
        # Overwrite the value of high index
        self.buffer[self.high] = data
        self.high = (self.high + 1) % self.size

    def remove(self):
        """ A method for removing items from circular buffer."""
        if self.count == 0:
            raise Exception('The circular buffer is empty!')
        value = self.buffer[self.low]
        self.low = (self.low + 1) % self.size
        self.count -= 1
        return value

    def __len__(self):
        """ The len method for having the length of the circular buffer"""
        return self.count

    def __iter__(self):
        """ A python generator that iterates through the circular buffer. """
        index = self.low
        i = self.count
        while i > 0:
            yield self.buffer[index]
            i -= 1
            index = (index + 1) % self.size

    def __repr__(self):
        """ A method for printing out the available elements of the buffer. """
        if self.is_empty():
            return 'circular buffer:[]'

        return 'circular buffer:[' + ','.join(map(str, self)) + ']'

class Node:
    def __init__(self, data, next_node=None):
        """ Constructor for creating a node for linklist. """
        self.data = data
        self.next = next_node

class SinglyLinkList:
    def __init__(self, *start):
        """ Singly Linklist Constructor """
        self.head = None
        self.size = 0

        for _ in start:
            self.prepend(_)

    def prepend(self, data):
        """ Add the data to the beginning of the link list. """
        self.head = Node(data, self.head)
        self.size += 1

    def remove(self, data):
        """ A method for removing an element from the list. """
        h = self.head
        current = None
        while h is not None:
            if h.data == data:
                if current is None:
                    self.head = self.head.next
                else:
                    current.next = h.next
                self.size -= 1
                return True
            current = h
            h = h.next
        return False

    def pop(self):
        """ Remove the first node from the list"""
        if self.head is None:
            raise Exception('The link list is empty!')
        data = self.head.data
        self.head = self.head.next
        return data

    def __iter__(self):
        """ An iterator to iterate trough the link list."""
        h = self.head
        while h is not None:
            yield h.data
            h = h.next

    def __repr__(self):
        """ A method for printing out the available elements of the list.  """
        if self.head is None:
            return 'Link list:[]'
        return 'Link list:[{0:s}]'.format(','.join(map(str, self)))

class QueueLinkList:
    def __init__(self, *start):
        """ The constructor for LinkList type queue."""
        self.head = None
        self.tail = None
        self.size = 0

        for _ in start:
            self.append(_)

    def append(self, data):
        """ Add the data to the beginning of the link list. """
        new_node = Node(data, None)
        if self.head is None:
            self.head = self.tail = new_node
        else:
            self.tail.next = new_node
            self.tail = new_node
        self.size += 1

    def check_infinite(self):
        """ A method to check whether there is an infinite loop in the link list."""
        p1 = p2 = self.head
        while p1 is not None and p2 is not None:
            if p2.next is None:
                return False

            p1 = p1.next
            p2 = p2.next.next

            if p1 == p2:
                return True
        return False

    def pop(self):
        """ Remove the first node from the list"""
        if self.head is None:
            raise Exception('The link list is empty!')
        data = self.head.data
        self.head = self.head.next
        if self.head is None:
            self.tail = None
        return data

    def __iter__(self):
        """ An iterator to iterate trough the link list."""
        h = self.head
        while h is not None:
            yield h.data
            h = h.next

    def __repr__(self):
        """ A method for printing out the available elements of the list.  """
        if self.head is None:
            return 'Link list:[]'
        return 'Link list:[{0:s}]'.format(','.join(map(str, self)))

class Leaf:
    def __init__(self, data):
        """ A constructor for creating a leaf node for a tree. """
        self.data = data
        self.left = None
        self.right = None
        self.height = 0

    def compute_height(self):
        """Compute height of node in BST."""
        height = -1
        if self.left:
            height = max(height, self.left.height)
        if self.right:
            height = max(height, self.right.height)

        self.height = height + 1

    def height_difference(self):
        """Compute height difference of node's children in BST."""
        left_target = 0
        right_target = 0

        if self.left:
            left_target = 1 + self.left.height
        if self.right:
            right_target = 1 + self.right.height

        return left_target - right_target

    def rotate_right(self):
        """Perform right rotation around given node."""
        new_root = self.left
        grandson = new_root.right
        self.left = grandson
        new_root.right = self

        self.compute_height()
        return new_root

    def rotate_left(self):
        """Perform left rotation around given node."""
        new_root = self.right
        grandson = new_root.left
        self.right = grandson
        new_root.left = self

        self.compute_height()
        return new_root

    def rotate_left_right(self):
        """Perform left, then right rotation around given node."""
        leaf = self.left
        new_root = leaf.right
        grand1 = new_root.left
        grand2 = new_root.right
        leaf.right = grand1
        self.left = grand2

        new_root.left = leaf
        new_root.right = self

        leaf.compute_height()
        self.compute_height()
        return new_root

    def rotate_right_left(self):
        """Perform right, then left rotation around given node."""
        leaf = self.right
        new_root = leaf.left
        grand1 = new_root.left
        grand2 = new_root.right
        leaf.left = grand2
        self.right = grand1

        new_root.left = self
        new_root.right = leaf

        leaf.compute_height()
        self.compute_height()
        return new_root

    def insert(self, value):
        """Adds a new node to the tree with value and Rebalance as needed."""
        new_root = self

        if value <= self.data:
            self.left = self.__append_to_subtree(self.left, value)
            if self.height_difference() == 2:
                if value <= self.left.value:
                    new_root = self.rotate_right()
                else:
                    new_root = self.rotate_left_right()
        else:
            self.right = self.__append_to_subtree(self.right, value)
            if self.height_difference() == -2:
                if value > self.right.data:
                    new_root = self.rotate_left()
                else:
                    new_root = self.rotate_right_left()

        new_root.compute_height()
        return new_root

    @staticmethod
    def __append_to_subtree(root, data):
        if root is None:
            return Leaf(data)
        root = root.insert(data)
        return root

    def find(self, data):
        """ A recursive function for searching on a tree recursively. """
        # Check left side of the tree
        if self.data < data:
            if self.left is None:
                return "\n" + str(data) + " not available on left side of the tree."
            return self.left.find(data)
        # Check right side of the tree
        elif self.data > data:
            if self.right is None:
                return "\n" + str(data) + " not available on right side of the tree."
            return self.right.find(data)
        else:
            return "\n" + str(data) + " is available on the tree."

    def inorder(self):
        """In order traversal generator of tree rooted at given leaf."""
        if self.left:
            for d in self.left.inorder():
                yield d

        yield self.data

        if self.right:
            for d in self.right.inorder():
                yield d

    def remove(self, value):
        """
         Remove value of self from BinaryTree. Works in conjunction with remove
         method in BinaryTree.
        """
        new_root = self

        if self.data == value:
            if self.left is None:
                return self.right

            leaf = self.left
            while leaf.right:
                leaf = leaf.right

            leaf_val = leaf.value
            self.left = self.__remove_from_parent(self.left, leaf_val)
            self.data = leaf_val

            if self.height_difference() == -2:
                if self.right.height_difference() <= 0:
                    new_root = self.rotate_left()
                else:
                    new_root = self.rotate_right_left()
        elif self.data > value:
            self.left = self.__remove_from_parent(self.left, value)
            if self.height_difference() == -2:
                if self.right.height_difference() <= 0:
                    new_root = self.rotate_left()
                else:
                    new_root = self.rotate_right_left()
        else:
            self.right = self.__remove_from_parent(self.right, value)
            if self.height_difference() == 2:
                if self.left.height_difference() >= 0:
                    new_root = self.rotate_right()
                else:
                    new_root = self.rotate_left_right()

        new_root.compute_height()
        return new_root

    @staticmethod
    def __remove_from_parent(parent, value):
        """Helper method for remove. Ensures proper behavior when removing node that
        has children."""
        if parent:
            return parent.remove(value)
        return None

    def __repr__(self):
        """Useful debugging function to produce linear tree representation."""
        left_sub = ''
        right_sub = ''
        if self.left:
            left_sub = str(self.left)
        if self.right:
            right_sub = str(self.right)
        return "(L:" + left_sub + " " + str(self.data) + " R:" + right_sub + ")"

class BinaryTree:
    def __init__(self):
        self.size = 0
        self.root = None

    def __str__(self):
        if self.root:
            return str(self.root)

    def add(self, value):
        if self.root is None:
            self.root = Leaf(value)
        else:
            self.root.insert(value)
        self.size += 1

    def remove(self, item):
        """
        Remove value from tree.
        """
        if self.root is not None:
            self.root = self.root.remove(item)
            self.size -= 1

    def get_min(self):
        """
        A function for finding the minimum value in the tree
        """
        if self.root is None:
            raise Exception("The binary tree is empty")

        current_root = self.root
        while current_root.left:
            current_root = current_root.left
        return current_root.data

    def get_max(self):
        """
        A method for finding the maximum value in the tree
        """
        if self.root is None:
            raise Exception("The binary tree is empty")

        current_root = self.root
        while current_root.right:
            current_root = current_root.right
        return current_root.data

    def get_closest_value_to(self, target):
        """
        A method for finding the closest value in the tree to the target value
        """
        if self.root is None:
            return None
        leaf = self.root
        best = leaf
        distance = abs(leaf.data - target)

        while leaf is not None:
            if abs(leaf.data - target) < distance:
                best = leaf
                distance = abs(leaf.data - target)

            if target < leaf.data:
                leaf = leaf.left
            elif target > leaf.data:
                leaf = leaf.right
            else:
                return target
        return best.data

    def __contains__(self, data):
        """
        Check whether BST contains target value.
        """
        leaf = self.root
        while leaf is not None:
            if data < leaf.data:
                leaf = leaf.left
            elif data > leaf.data:
                leaf = leaf.right
            else:
                return True
        return False

    def __iter__(self):
        """In-order traversal of elements in the tree."""
        if self.root:
            for e in self.root.inorder():
                yield e

    def __repr__(self):
        if self.root is None:
            return "binary tree:()"
        return "binary tree:" + str(self.root)


from torrent_eztv import EZTVAPI
from torrent_scrapyard import ScrapYardAPI
from torrent_torrentproject import TorrentProjectAPI

class TorrentMediaSearcher():

	PROVIDERS = {
		'eztv': EZTVAPI,
		'scrapyard' : ScrapYardAPI,
		'torrentproject' : TorrentProjectAPI
	}

	@staticmethod
	def request_movie_magnet(provider, movie, year=None, quality=None):
		if provider in TorrentMediaSearcher.PROVIDERS:
			provider_class = TorrentMediaSearcher.PROVIDERS[provider]
		else:
			raise ValueError('No valid search provider selected, choose from: ' + str(TorrentMediaSearcher.PROVIDERS.keys()))

		if year is not None and 1000 > year > 9999:
			raise ValueError('Invalid year input, please use the yyyy format or do not use the year parameter (results will be less accurate)')

		search = provider_class()
		return search.create_movie_request(movie=movie, year=year, quality=quality)

	@staticmethod
	def request_tv_magnet(provider, show, season, episode, quality=None):
		if provider in TorrentMediaSearcher.PROVIDERS:
			provider_class = TorrentMediaSearcher.PROVIDERS[provider]
		else:
			raise ValueError('No valid search provider selected, choose from: ' + str(TorrentMediaSearcher.PROVIDERS.keys()))

		search = provider_class()
		return search.create_tvshow_request(show=show, season=season, episode=episode, quality=quality)


# p.361 실패율

def solution(N, stages):
    count = [0] * (max(stages) + 1) # 필요한 값에 대한 인덱스 생성

    for i in range(len(stages)):
        count[stages[i]] += 1  # 각 인덱스 값에 대한 숫자 확인

    # 도달한 인원 수 확인
    success = []
    for i in range(len(count)):
        if i == 0:
            tmp = len(stages) - count[i]
        else:
            tmp -= count[i - 1]
        success.append(tmp)

    # 다음 단계로 넘어가지 못한 인원 수를 도달 인원 수로 나눠서 실패율 계산
    fail_rate = []
    for i in range(len(success)):
        tmp = count[i] / success[i]
        fail_rate.append((i, tmp))

    # 0과 6(N+1)은 삭제하고 fail_rate 값을 기준으로 내림차순 정렬
    fail_rate = sorted(fail_rate[1:N+1], key=lambda k: k[1], reverse=True)

    # 정답 리스트 생성 및 반환
    answer = []
    for i in fail_rate:
        answer.append(i[0])
    return answer

print(solution(5, [2, 1, 2, 6, 2, 4, 3, 3]))
print(solution(4, [4, 4, 4, 4, 4]))


from odoo import fields, models

class TextTemplateConfig(models.Model):
    _name = 'text.template.config'
    _description = 'Text Template Config'

    # region Fields
    name = fields.Char(
        string='Description',
        help='Text field, which will be printed in the documents.',
        readonly=True,
        translate=True,
    )
    model = fields.Many2one(
        comodel_name='ir.model',
        readonly=True,
    )
    default_text = fields.Text(
        translate=True,
    )
    # endregion

    # region Business Methods
    def get_template_text(self, lang, field_xml_list):
        lang = lang or self.env.user.lang or 'en_US'
        return {
            field: self.env.ref(xml_id).with_context(lang=lang).default_text
            for field, xml_id
            in field_xml_list
        }
    # endregion


from torch.autograd import Variable
from torch.nn.parameter import Parameter
import torch.nn as nn
import torch.nn.functional as F
import torch

import math
import cv2
import numpy as np

from bauta.utils.CudaUtils import CudaUtils
from bauta.utils.ModelUtils import ModelUtils
from bauta.utils.ImageUtils import ImageUtils

class MaskRefiner(nn.Module):

    def __init__(self):
        super(MaskRefiner, self).__init__()
        hidden_filter_banks = 64
        filter_size = 7
        self.dilation1_4_decode  = ModelUtils.createDilatedConvolutionPreservingSpatialDimensions(9, 1, filter_size, 1, False)
        self.dilation1_3_decode  = ModelUtils.createDilatedConvolutionPreservingSpatialDimensions(17, int(hidden_filter_banks / 8), filter_size, 1)
        self.dilation1_2_decode  = ModelUtils.createDilatedConvolutionPreservingSpatialDimensions(65, int(hidden_filter_banks / 4), filter_size, 1)
        self.dilation1_1_decode  = ModelUtils.createDilatedConvolutionPreservingSpatialDimensions(125, int(hidden_filter_banks), filter_size, 1)
        ModelUtils.xavier(self.dilation1_4_decode)
        #logits for initial output near 0.01, useful as most of targets are backgrounds
        self.dilation1_4_decode.weight.data = self.dilation1_4_decode.weight.data.abs() * -4.0

    def forward(self, input):
        input_image_size, predicted_masks_16, mask_embeddings_16, embeddings_16, embeddings_8, embeddings_4, embeddings_2 = input
        embeddings_16 = torch.cat([predicted_masks_16, mask_embeddings_16, embeddings_16], 1)
        embeddings_16 = F.relu(self.dilation1_1_decode(embeddings_16))

        embeddings_8 = torch.cat(\
            [F.upsample(embeddings_16, size=(embeddings_8.size()[2], embeddings_8.size()[3]), mode='bilinear'),
            embeddings_8.sum(1).unsqueeze(1)],
            1)
        embeddings_8 = F.relu(self.dilation1_2_decode(embeddings_8))

        embeddings_4 = torch.cat([\
            F.upsample(embeddings_8, size=(embeddings_4.size()[2], embeddings_4.size()[3]), mode='bilinear'),
            embeddings_4.sum(1).unsqueeze(1)],
            1)
        embeddings_4 = F.relu(self.dilation1_3_decode(embeddings_4))

        embeddings_2 = torch.cat([\
            F.upsample(embeddings_4, size=(embeddings_2.size()[2], embeddings_2.size()[3]), mode='bilinear'),\
            embeddings_2.sum(1).unsqueeze(1)], 1)
        mask = F.sigmoid(self.dilation1_4_decode(embeddings_2))
        return mask


from pyfr.solvers.baseadvec import (BaseAdvectionIntInters,
                                    BaseAdvectionMPIInters,
                                    BaseAdvectionBCInters)

class FluidIntIntersMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if self.cfg.get('solver', 'shock-capturing') == 'entropy-filter':
            self._be.pointwise.register('pyfr.solvers.euler.kernels.intcent')

            self.kernels['comm_entropy'] = lambda: self._be.kernel(
                'intcent', tplargs={}, dims=[self.ninters],
                entmin_lhs=self._entmin_lhs, entmin_rhs=self._entmin_rhs
            )

class TplargsMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        rsolver = self.cfg.get('solver-interfaces', 'riemann-solver')
        if self.cfg.get('solver', 'shock-capturing') == 'entropy-filter':
            self.p_min = self.cfg.getfloat('solver-entropy-filter', 'p_min',
                                           1e-6)
        else:
            self.p_min = self.cfg.getfloat('solver-interfaces', 'p_min',
                                           5*self._be.fpdtype_eps)

        self._tplargs = dict(ndims=self.ndims, nvars=self.nvars,
                             rsolver=rsolver, c=self.c, p_min=self.p_min)

class FluidMPIIntersMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if self.cfg.get('solver', 'shock-capturing') == 'entropy-filter':
            self._be.pointwise.register('pyfr.solvers.euler.kernels.mpicent')

            self.kernels['comm_entropy'] = lambda: self._be.kernel(
                'mpicent', tplargs={}, dims=[self.ninters],
                entmin_lhs=self._entmin_lhs, entmin_rhs=self._entmin_rhs
            )

class EulerIntInters(TplargsMixin, FluidIntIntersMixin,
                     BaseAdvectionIntInters):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._be.pointwise.register('pyfr.solvers.euler.kernels.intcflux')

        self.kernels['comm_flux'] = lambda: self._be.kernel(
            'intcflux', tplargs=self._tplargs, dims=[self.ninterfpts],
            ul=self._scal_lhs, ur=self._scal_rhs, nl=self._pnorm_lhs
        )

class EulerMPIInters(TplargsMixin, FluidMPIIntersMixin,
                     BaseAdvectionMPIInters):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._be.pointwise.register('pyfr.solvers.euler.kernels.mpicflux')

        self.kernels['comm_flux'] = lambda: self._be.kernel(
            'mpicflux', self._tplargs, dims=[self.ninterfpts],
            ul=self._scal_lhs, ur=self._scal_rhs, nl=self._pnorm_lhs
        )

class EulerBaseBCInters(TplargsMixin, BaseAdvectionBCInters):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._be.pointwise.register('pyfr.solvers.euler.kernels.bccflux')

        self._tplargs |= dict(bctype=self.type, ninters=self.ninters)

        self.kernels['comm_flux'] = lambda: self._be.kernel(
            'bccflux', tplargs=self._tplargs, dims=[self.ninterfpts],
            extrns=self._external_args, ul=self._scal_lhs, nl=self._pnorm_lhs,
            **self._external_vals
        )

        if self.cfg.get('solver', 'shock-capturing') == 'entropy-filter':
            self._be.pointwise.register('pyfr.solvers.euler.kernels.bccent')

            self.kernels['comm_entropy'] = lambda: self._be.kernel(
                'bccent', tplargs=self._tplargs, dims=[self.ninterfpts],
                extrns=self._external_args, entmin_lhs=self._entmin_lhs,
                nl=self._pnorm_lhs, ul=self._scal_lhs, **self._external_vals
            )

class EulerSupInflowBCInters(EulerBaseBCInters):
    type = 'sup-in-fa'

    def __init__(self, be, lhs, elemap, cfgsect, cfg):
        super().__init__(be, lhs, elemap, cfgsect, cfg)

        self.c |= self._exp_opts(
            ['rho', 'p', 'u', 'v', 'w'][:self.ndims + 2], lhs
        )

class EulerSupOutflowBCInters(EulerBaseBCInters):
    type = 'sup-out-fn'
    cflux_state = 'ghost'

class EulerCharRiemInvBCInters(EulerBaseBCInters):
    type = 'char-riem-inv'

    def __init__(self, be, lhs, elemap, cfgsect, cfg):
        super().__init__(be, lhs, elemap, cfgsect, cfg)

        self.c |= self._exp_opts(
            ['rho', 'p', 'u', 'v', 'w'][:self.ndims + 2], lhs
        )

class EulerSlpAdiaWallBCInters(EulerBaseBCInters):
    type = 'slp-adia-wall'


# -*- coding: utf-8 -*-
"""
@author: velmurugan.jeyaram
"""

import cv2
import glob
import numpy as np
import random
import os
import utils

class EmotionData():

    def __init__(self):
        self.i = 0
        self.training_images = None
        self.training_labels = None
        self.test_images = None
        self.test_labels = None

    def get_files(self, emotion): #Define function to get file list, randomly shuffle it and split 80/20
        files = glob.glob("SampleDataset\\%s\\*" %emotion)
        random.shuffle(files)
        training = files[:int(len(files)*0.8)] #get first 80% of file list
        prediction = files[-int(len(files)*0.2):] #get last 20% of file list
        return training, prediction

    def one_hot_encode(self, vec, vals=5):
        '''
        For use to one-hot encode 5- possible labels
        '''
        n = len(vec)
        out = np.zeros((n, vals))
        out[range(n), vec] = 1
        return out

    def make_sets(self):
        train_data = []
        train_labels = []
        val_data = []
        val_labels = []
        for emotion in utils.emotions:
            print(" working on %s" %emotion)
            training, validation = self.get_files(emotion)
            #Append data to training and prediction list, and generate labels 0-7
            for item in training:
                try:
                    image = cv2.imread(item) #open image
                    newimg = cv2.resize(image, (int(32), int(32)))
                    rgb = cv2.cvtColor(newimg, cv2.IMREAD_COLOR) #convert to grayscale
                    rgb_imge = np.array(rgb)
                    train_data.append(rgb_imge) #append image array to training data list
                    train_labels.append(utils.emotions.index(emotion))
                except Exception:
                    os.remove(item)
                    print("Invalid file " + str(item)+ " removed")
            for item in validation:
                try:
                    image = cv2.imread(item)
                    newimg = cv2.resize(image, (int(32), int(32)))
                    rgb = cv2.cvtColor(newimg, cv2.IMREAD_COLOR)
                    rgb_imge = np.array(rgb)
                    val_data.append(rgb_imge)
                    val_labels.append(utils.emotions.index(emotion))
                except Exception:
                    os.remove(item)
                    print("Invalid file " + str(item)+ " removed")
        self.training_images = np.asarray(train_data)/255
        self.training_labels = self.one_hot_encode(train_labels,5)
        self.test_images = np.asarray(val_data)/255
        self.test_labels = self.one_hot_encode(val_labels,5)
        #return training_data, training_labels, prediction_data, prediction_labels

    def next_batch(self, batch_size):
        x = self.training_images[self.i:self.i+batch_size].reshape(-1,32,32,3)
        y = self.training_labels[self.i:self.i+batch_size]
        self.i = self.i + batch_size
        return x, y