import time
import os
import sys
import traceback

from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.common.exceptions import TimeoutException as SeleniumTimeoutException
from selenium import webdriver

from common import COLORS, say

def get_driver():
    options = webdriver.ChromeOptions()
    options.add_argument('--no-sandbox')

    options.add_argument('--disable-gpu')
    options.add_argument("--disable-extensions")
    options.add_argument("--disable-infobars")

    options.add_argument("--start-maximized")
    options.add_argument('--window-size=1000,700')

    options.add_argument("--headless")
    options.add_argument("--log-level=1")
    options.add_argument('--disable-dev-shm-usage')

    service = ChromeService(executable_path=ChromeDriverManager().install())
    return webdriver.Chrome(options=options, service=service)

def wait_for_scripts(driver):
    height = None
    while (height is None):
        height = driver.execute_script("return UI;")['window_height'];
        say(0, '~', end='', flush=True)
    say(1, '+')

def take_screenshots(driver, output_dir):
    screenshots = []
    error = None
    while (True):
        try:
            ts  = driver.execute_async_script("UI._set_redraw_hook(arguments[arguments.length-1]);")
            delta = abs(ts) - screenshots[~0]["ts"] if len(screenshots)>0 else 0
            #print('received pingback:', ts, ' +', delta)
            say(0, '.', end='', flush=True)
            file_name = f"{output_dir}/grab_{len(screenshots):03g}_{delta}.png"
            driver.save_screenshot(file_name)
            screenshots.append({
                "name": file_name
                ,"delta": delta
                ,"ts" : ts
            })
        except SeleniumTimeoutException as ex:
            say(0, '?', end='')
            say(0, COLORS.WARNING, "selenium timed out while waiting for redraw_hook callback", COLORS.ENDC)
            say(2, 'Exception:', ex)
            say(2, 'Trace:', traceback.format_exc())
            error = (ex, None)
        except Exception as ex:
            error = (ex, traceback.format_exc())

        if (ts < 0):
            say(0, '+', end='')
            say(1, "")
            say(1, "received stop signal")
            break

        if (error is not None):
            if (error[1] is None):
                break
            say(0, '!')
            say(0, "received error:", type(error[0]), error[0])
            say(0, "trace: ", error[1])
            break

    return screenshots, error

def main(user, ip, uri, speedup, output_dir):
    """
    ip = '172.17.0.2'
    uri = 'test-pen-1'
    speedup = '0.2'
    output_dir = '/chalkboard/tmp'
    """
    speedup = float(speedup)

    driver = get_driver()
    url = f'http://{ip}:5000/index.html#{uri}$play?speedup={speedup}'

    say(2, f"selenium fetching URL: {url} into {output_dir}")
    driver.get(url)

    say(2, "selenium waiting for scripts")
    wait_for_scripts(driver)

    say(2, "capturing screenshots")
    screenshots, error = take_screenshots(driver, output_dir)

    if (error is not None)and(error[1] is not None):
        pass
    else:
        say(0, "[s]", end='')
        say(2, "waiting for settlement")
        time.sleep(3)

    say(0, "[c]", end='')
    say(2, "taking final screenshot")
    driver.save_screenshot(f"{output_dir}/result.png")

    say(0, "[l]", end='')
    say(2, "saving js logs")
    logs = driver.execute_script("return UI.logger.logs")
    with open(f"{output_dir}/js_log.txt", "wt") as f:
        f.write("\n".join(map(lambda l:str(l[1]) + '::' + str(l[0]), logs[::-1])))

    say(0, "[d]", end='')
    say(2, "closing selenium driver")
    driver.quit()

    say(0, "[g]", end='')
    say(2, "converting screenshots into gif")
    convert_cmd = ("convert " + " ".join([
        f"-delay {int(f['delta'] * speedup / 10)} {f['name']}" for f in screenshots
    ]) + f" -loop 0  -layers Optimize {output_dir}/result.gif")
    os.system(convert_cmd)

    say(0, "[x]", end='')
    say(2, "cleaning up screenshots")
    for f in screenshots:
        say(2, '.', end='', flush=True)
        os.remove(f["name"])
    say(2, '')

    say(0, "[o]", end='')
    say(2, "switching ownership")
    os.system(f"chown -R {user} {output_dir}/*")

    return ((error is not None)and(error[1] is not None))*1

if __name__ == "__main__":
    if (len(sys.argv) != 7) or (sys.argv[1] == "?"):
        print("usage: play.py <owner> <ip> <uri> <speedup> <output_dir> <verbosity>")
        sys.exit(-1)

    say.__level = int(sys.argv[6])
    say(2, "args: ", sys.argv)

    try:
        code = main(*sys.argv[1:-1])
    except KeyboardInterrupt:
        code = -2

    sys.exit(code)


def jobschedule(joblist):
    jobs = sorted(joblist,key = lambda x:(x[2],x[0]))
    jobs = jobs[-1::-1]
    sumTime = 0
    sumLength = 0
    for job in jobs:
        sumLength += job[1]
        sumTime += job[0] * sumLength
    print(sumTime)

if __name__ == "__main__":
    f = open('quiz1.txt','r')
    lines = f.readlines()[1:]
    jobs = []

    for line in lines:
        weight = int(line.split()[0])
        length = int(line.split()[1])
        jobs.append([weight,length,weight - length])
    jobschedule(jobs)


import tkinter
from tkinter import ttk

window = tkinter.Tk()

main_frame = ttk.Frame(window, border=1, borderwidth=1, padding=15)
main_frame.pack(fill='both', expand=True, ipadx=20, ipady=40)

main_frame.columnconfigure(0, weight=2)
main_frame.columnconfigure(1, weight=2)

lenguajes = [
    'Python',
    'Java',
    'JavaScript',
    'C',
    'PHP',
    'C/C++',
    'R',
    'TypeScript'
]

desc_label = ttk.Label(main_frame, text='Lenguajes de Programación')
desc_label.grid(column=0, row=0, padx=15, pady=5)

lista_lenguajes = ttk.Combobox(main_frame, values=lenguajes)
lista_lenguajes.grid(column=0, row=1)

window.mainloop()


target, time = map(int, input().split())
counter = 0

iter = 0
while True:
    iter += 1
    if iter > target:
        print(0)
        break

    if target % iter == 0:
        counter += 1

    if counter == time:
        print(iter)
        break


from data import load_original_gmd_dataset_pickle

# Load 2bar gmd dataset as a dictionary
gmd_dict = load_original_gmd_dataset_pickle(
    gmd_pickle_path="data/gmd/resources/storedDicts/groove_2bar-midionly.bz2pickle")

gmd_dict.keys()          # dict_keys(['train', 'test', 'validation'])
gmd_dict['train'].keys()        #dict_keys(['drummer', 'session', 'loop_id', 'master_id', 'style_primary', 'style_secondary', 'bpm', 'beat_type', 'time_signature', 'full_midi_filename', 'full_audio_filename', 'midi', 'note_sequence'])

# =================================================================================================
# Extract HVO_Sequences from the dictionaries

from data import extract_hvo_sequences_dict, get_drum_mapping_using_label

hvo_dict = extract_hvo_sequences_dict (
    gmd_dict=gmd_dict,
    beat_division_factor=[4],
    drum_mapping=get_drum_mapping_using_label("ROLAND_REDUCED_MAPPING"))

# =================================================================================================

# Load GMD Dataset in `HVO_Sequence` format using a single command
from data import load_gmd_hvo_sequences
test_set = load_gmd_hvo_sequences(
    dataset_setting_json_path="data/dataset_json_settings/4_4_Beats_gmd.json",
    subset_tag="test",
    force_regenerate=False)

# =================================================================================================
# Load dataset as torch.utils.data.Dataset
from data import MonotonicGrooveDataset

# load dataset as torch.utils.data.Dataset
training_dataset = MonotonicGrooveDataset(
    dataset_setting_json_path="data/dataset_json_settings/4_4_Beats_gmd.json",
    subset_tag="train",
    max_len=32,
    tapped_voice_idx=2,
    collapse_tapped_sequence=False,
    load_as_tensor=True,
    sort_by_metadata_key="loop_id",
    genre_loss_balancing_beta=0.5,
    voice_loss_balancing_beta=0.5
)

training_dataset.__getitem__(0)
training_dataset.get_voice_counts()
training_dataset.get_genre_distributions_dict()
# training_dataset.visualize_global_hit_count_ratios_heatmap()
#training_dataset.visualize_genre_distributions(show_inverted_weights=True)
# =================================================================================================

# use the above dataset in the training pipeline, you need to use torch.utils.data.DataLoader
from torch.utils.data import DataLoader
train_dataloader = DataLoader(training_dataset, batch_size=32, shuffle=True)

epochs = 10
for epoch in range(epochs):
    # in each epoch we iterate over the entire dataset
    for batch_count, (inputs, outputs, indices) in enumerate(train_dataloader):
        print(f"Epoch {epoch} - Batch #{batch_count} - inputs.shape {inputs.shape} - "
              f"outputs.shape {outputs.shape} - indices.shape {indices.shape} ")


import re
import datetime

import snscrape.modules.twitter as sntwitter

from .scraper import Scraper, Content

class TwitterScraper(Scraper):
	def __init__(self) -> None:
		pass

	def _query_constructor(
		self,
		ticker: str,
		min_date: datetime.datetime,
		max_date: datetime.datetime,
		min_faves: int = 300) -> str:
		format_date = lambda date: (
			f'{date.year}-'
			f'{str(date.month).rjust(2, "0")}-'
			f'{str(date.day).rjust(2, "0")}')

		return (
			f'${ticker} min_faves:{min_faves} until:{format_date(max_date)} '
			f'since:{format_date(min_date)}')

	def fetch_content_for_day(
		self,
		ticker: str,
		day: datetime.datetime) -> list[Content]:
		return self._fetch_content_for_day(ticker=ticker, day=day)

	def _fetch_content_for_day(
		self,
		ticker: str,
		day: datetime.datetime,
		min_faves: int = 300,
		limit: int = 25) -> list[Content]:
		query = self._query_constructor(
			ticker=ticker,
			min_faves=min_faves,
			min_date=day,
			max_date=day + datetime.timedelta(days=1))

		raw_tweets = sntwitter.TwitterSearchScraper(query).get_items()

		tweets = list()
		for _ in range(limit):
			curr_tweet = next(raw_tweets, None)
			if not curr_tweet:
				break

			tweet_content_trunc = curr_tweet.rawContent[:127]
			tweets.append(Content(content=tweet_content_trunc, date=day))

		return tweets


import sys
sys.stdin=open('input.txt', 'r')

# 배열의 모든 원소에 대해 +1이 되는 지점으로 이동하며 cnt
# cnt=1 부터 시작

# 방향 배열(상(0),하(1),좌(2),우(3))
dy,dx = [-1,1,0,0],[0,0,-1,1]

# 1 더 큰 수를 탐색하는 함수 생성
def one_plus(y,x,cnt=1):
    if visited[y][x]==1:
        return 0
    q = [[y,x]]
    while q:
        y,x = q.pop(0)
        for d in range(4):
            ny = y+dy[d]
            nx = x+dx[d]
            if 0<=ny<n and 0<=nx<n:
                if arr[ny][nx] != arr[y][x]+1:
                    continue
                visited[ny][nx]=1
                cnt+=1
                q.append([ny,nx])
    return cnt

for tc in range(1,1+int(input())):

    n = int(input())

    arr = [list(map(int,input().split())) for _ in range(n)]
    visited = [[0]*n for _ in range(n)]
    Max=0
    Max_n=0
    Max_n_lst=[]
    for i in range(n):
        for j in range(n):
            cnt = one_plus(i,j)
            if cnt>Max:
                Max=cnt
                Max_n=arr[i][j]
                Max_n_lst=[Max_n]
            elif cnt==Max:
                Max_n_lst.append(arr[i][j])

    print(f'#{tc} {min(Max_n_lst)} {Max}')


#8 Resumen y multi-solución
"""8.1.-Definir una clase usuario que contenga como atributos:
Usuario
Contraseña
Rol
Nombre
CURP
Ciudad"""
import os
class usuario:
    Administradores = {"Usuario": "Admin", "Contraseña": "1234", "Rol": "Adminitrador",
                            "Nombre": "Bryan Mendoza", "CURP": "CSCFSF232dd", "Ciudad": "Nuevo Laredo"}
    Usuarios = {"Admin": Administradores}
    listaCURP = []
    def __init__(self) -> None:
        self.Usuario=""
        self.Contraseña=""
        self.Rol="cliente"
        self.Nombre=""
        self.CURP=""
        self.Ciudad=""
        self.DiccionarioUsuario = {}
    def RegistrarUsuario(self):
        igual=False
        for l in self.listaCURP:
            if self.CURP == l:
                igual = True
        if igual==False:
            self.DiccionarioUsuario = {'Usuario': self.Usuario, 'Contraseña': self.Contraseña,
                                       'Rol': self.Rol, 'Nombre': self.Nombre, 'CURP': self.CURP, 'Ciudad': self.Ciudad}
            self.listaCURP.append(self.CURP)
            self.Usuarios[self.Usuario] = self.DiccionarioUsuario
            print(self.DiccionarioUsuario)
            print(self.Usuarios)
        elif igual==True:
            print
            print("             El Usuario ya existe ")
            print
    def inicioSesion(self):
        encontrado=False
        su=False
        res=False
        if self.Usuario in self.Usuarios:
                for key,value in self.Usuarios[self.Usuario].items():
                    if key=="Contraseña" and self.Contraseña==value:
                        encontrado=True
                        res=encontrado
                    if value=="Admin":su=True
        else:
            print("             Datos incorrectos | Usuario no existe")
            os.system("pause")
            return res
        if self.Usuario in self.Usuarios and encontrado==True:
            if su==True:
                os.system('cls')
                print('                                              Lista de Usuarios')
                for clave, valor in self.Usuarios.items():
                    print(f"Usuario: {clave} Rol : {valor['Rol']}  Nombre : {valor['Nombre']} CURP : {valor['CURP']} Ciudad : {valor['Ciudad']}")
            else:
                os.system('cls')
                print("               Datos del Usuario ")
                for key, value in self.Usuarios[self.Usuario].items():
                    print(" ")
                    print(key.title()+' : ',value)

        elif self.Usuario in self.Usuarios and encontrado != True:
            print("             Datos incorrectos | Contraseña incorrecta !")
            os.system("pause")
            return res


# -- coding: utf-8 --
# @File : test_wechat.py
import time

from appium import webdriver

class TestWeChart:
    def setup(self):
        condition = {
            "platformName": "android",
            "deviceName": "111", #一定不能少这个参数
            "udid": "127.0.0.1:7555", #如果只有一个设备可以不写，多个设备就要写进行指定
            "appPackage": "com.tencent.wework",
            "appActivity": ".launch.WwMainActivity",
            "settings[waitForIdleTimeout]": 0, #把动态网页，当作静态处理，减少元素定位时间，一定是[]不能是()
            "noReset": "true",  # 记录之前的操作或登录信息，不清除缓存
            "skipDeviceInitialization": "true"  # 跳过设备初始化
        }
        self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", condition)  # ip port num不要忘记！！
        self.driver.implicitly_wait(5)

    def test_wechat(self):
        self.driver.find_element_by_xpath("//*[@text='工作台']").click()
        #这里打卡页面，打卡元素在下面，无法直接定位，只能通过滚动定位
        self.driver.find_element_by_android_uiautomator('new UiScrollable(new UiSelector().'
                                                        'scrollable(true).instance(0)).'
                                                        'scrollIntoView(new UiSelector().'
                                                        'text("打卡").'
                                                        'instance(0));').click()
        self.driver.find_element_by_id('com.tencent.wework:id/i1x').click()
        #文本属性包含外出的进行定位
        time.sleep(2)
        self.driver.find_element_by_android_uiautomator('new UiSelector().textContains("次外出")').click() #注意Contains是大写
        #也可以这么写
        # self.driver.find_element_by_xpath("//*[contains(@text,'次外出')]")
        ele = self.driver.find_element_by_id('com.tencent.wework:id/pu').text
        assert '外出打卡成功' == ele


from Common.ReadXml import ReadXml
from Common.WriteExcel import WriteExcel
from Common.WriteExcel2 import WriteExcel2
from Common.Feed import Feed
import time

if __name__ == '__main__':
    timestr = time.strftime("%Y-%m-%d-%H%M%S", time.localtime())
    reportname='report'+timestr+'.xlsx'

    readXml=ReadXml('testresult.xml')
    testcaseList=readXml.ReadTestCase()
    testsuiteList=readXml.TestSuiteList()
    testappList = readXml.TestAppList()

    writeExcel2=WriteExcel2(reportname)
    writeExcel2.init()
    writeExcel2.test_suite(testsuiteList)
    writeExcel2.test_detail(testcaseList)
    writeExcel2.test_summary(testappList)
    writeExcel2.close()

    b=1


#1753. Maximum Score From Removing Stones
def maximumScore(a, b, c):
    import heapq
    l1 = []
    heapq.heapify(l1)
    for i in [a, b, c]:
        heapq.heappush(l1, -i)

    result = 0
    while len(l1) >= 2:
        top, top2 = heapq.nsmallest(2, l1)
        heapq.heappop(l1)
        heapq.heappop(l1)
        result -= 1
        top += 1
        top2 += 1
        if top < 0:
            heapq.heappush(l1, top)
        if top2 < 0:
            heapq.heappush(l1, top2)
    return abs(result)

res = maximumScore(2,4,6)
print(res)


"""
Szyfrowanie tekstu korzystające z ECC.

Autor: Maciej Milewski
Źródło algorytmu szyfrującego: https://pypi.org/project/pycrypto/
"""

from tinyec import registry
from Crypto.Cipher import AES
import hashlib, secrets, binascii
import timeit
import os

def encrypt_AES_GCM(msg, secretKey):
    """ encrypt AES in GCM mode """
    aesCipher = AES.new(secretKey, AES.MODE_GCM)
    ciphertext, authTag = aesCipher.encrypt_and_digest(msg)
    return (ciphertext, aesCipher.nonce, authTag)

def decrypt_AES_GCM(ciphertext, nonce, authTag, secretKey):
    """ decrypt AES in GCM mode """
    aesCipher = AES.new(secretKey, AES.MODE_GCM, nonce)
    plaintext = aesCipher.decrypt_and_verify(ciphertext, authTag)
    return plaintext

def ecc_point_to_256_bit_key(point):
    """ setting generator point for elliptic curve """
    sha = hashlib.sha256(int.to_bytes(point.x, 32, 'big'))
    sha.update(int.to_bytes(point.y, 32, 'big'))
    return sha.digest()

def encrypt_ECC(msg, pubKey, curve):
    """ Encryption using ECC with 256 bit key and GCM mode to chain cipher blocks """
    ciphertextPrivKey = secrets.randbelow(curve.field.n)
    sharedECCKey = ciphertextPrivKey * pubKey
    secretKey = ecc_point_to_256_bit_key(sharedECCKey)
    ciphertext, nonce, authTag = encrypt_AES_GCM(msg, secretKey)
    ciphertextPubKey = ciphertextPrivKey * curve.g
    return (ciphertext, nonce, authTag, ciphertextPubKey)

def decrypt_ECC(encryptedMsg, privKey):
    """ ECC decryption """
    (ciphertext, nonce, authTag, ciphertextPubKey) = encryptedMsg
    sharedECCKey = privKey * ciphertextPubKey
    secretKey = ecc_point_to_256_bit_key(sharedECCKey)
    plaintext = decrypt_AES_GCM(ciphertext, nonce, authTag, secretKey)
    return plaintext

def main():
    """ Crypt&Decrypt message using ECC & AES """
    curve = registry.get_curve('brainpoolP256r1')
    msg = input("Podaj wiadomość: ")
    msg = msg.encode('utf-8')
    print("Oryginalna wiadomość:", msg.decode("ISO-8859-1").rstrip('\0'))

    privKey = secrets.randbelow(curve.field.n)
    pubKey = privKey * curve.g

    starttime = timeit.default_timer()
    encryptedMsg = encrypt_ECC(msg, pubKey, curve)
    encryptedMsgObj = {
        'ciphertext': binascii.hexlify(encryptedMsg[0]),
        'nonce': binascii.hexlify(encryptedMsg[1]),
        'authTag': binascii.hexlify(encryptedMsg[2]),
        'ciphertextPubKey': hex(encryptedMsg[3].x) + hex(encryptedMsg[3].y % 2)[2:]
    }
    print("Czas szyfrowania używając ECC: ", timeit.default_timer() - starttime, "s")

    starttime = timeit.default_timer()
    decryptedMsg = decrypt_ECC(encryptedMsg, privKey)
    print("Czas odszyfrowania ECC: ", timeit.default_timer() - starttime, "s")

    print("Zaszyfrowana wiadomość:", encryptedMsgObj)
    print("Odszyfrowana wiadomość:", decryptedMsg.decode("ISO-8859-1").rstrip('\0'))

if __name__ == "__main__":
    main()


f = open("./27-A.txt")
n = int(f.readline())
a = [int(x) for x in f]

mn_p, mn_i = 10**10, 0
for i in range(n):
    pr_i = 0
    for j in range(n):
        dist = abs(i-j)
        pr_i += a[j]*min(dist, n-dist)
    if pr_i < mn_p:
        mn_p = pr_i
        mn_i = i

print(mn_i+1)  # нумеруются от 1 до N


############################################################################################################
###      MIA Model with Tag    - baseline- equal budget distribution for tag and user selection      ######
############################################################################################################

def MIP_path_to_target(DG, t, weight = 'dummy_weight'):
    #path_list = []
    MIP_Path = {}
    for a in list(DG.predecessors(t)):
        path_from_a = [a, t]
        #path_list.append(path_from_a)
        prob_at = DG[a][t][weight]
        MIP_Path[(a,t)] = (path_from_a, prob_at)
        for b in list(DG.predecessors(a)):
            path_from_b = path_from_a.copy()
            prob_ba = prob_at * DG[b][a][weight]
            if b not in path_from_b:
                path_from_b.insert(0, b)
                try:
                    current_prob = MIP_Path[(b,t)][1]
                    if current_prob < prob_ba:
                        MIP_Path[(b,t)] = (path_from_b, prob_ba)
                except:
                    MIP_Path[(b,t)] = (path_from_b, prob_ba)

                #path_list.append(path_from_b)
                for c in list(DG.predecessors(b)):
                    path_from_c= path_from_b.copy()
                    prob_cb = prob_ba * DG[c][b][weight]
                    if c not in path_from_c:
                        path_from_c.insert(0, c)
                        #path_list.append(path_from_c)
                        try:
                            current_prob_1  = MIP_Path[(c,t)][1]
                            if current_prob_1 < prob_cb:
                                MIP_Path[(c,t)] = (path_from_c, prob_cb)
                        except:
                            MIP_Path[(c,t)] = (path_from_c, prob_cb)

                    del path_from_c, prob_cb
            del path_from_b, prob_ba
        del path_from_a, prob_at

    return MIP_Path

def Maximum_Influence_In_Arborescence(DG, t, theta, weight = 'dummy_weight'):
    MIIA = {}
    MIP_target_Path = MIP_path_to_target(DG, t, weight)
    for st in MIP_target_Path.keys():
        MIP_Path, MIP_prob = MIP_target_Path[st]
        if MIP_prob >= theta:
            MIIA[st] = (MIP_Path, MIP_prob)
    return MIIA

def activation_probability(DG, SeedSet, t, All_MIIA, l, weight):
    if l == 0:
        return 0.0

    if t in SeedSet:
        return 1.0
    elif len(list(DG.predecessors(t))) == 0:
        return 0.0
    else:
        product_term = 1.0
        for w in list(DG.predecessors(t)):
            new_l = l - 1
            try:
                pp_wt = All_MIIA[t][(w,t)][1]
            except:
                pp_wt = 0.0
            product_term = product_term*(1.0-(activation_probability(DG, SeedSet, w, All_MIIA, new_l, weight)* pp_wt))
        ap_t = 1.0 - product_term
        return ap_t

def Expected_Influence(DG, SeedSet, All_MIIA, l=3, weight= 'dummy_weight'):
    EI = 0.0
    for s in DG.nodes():
        #print('node :', s)
        EI = EI + activation_probability(DG, SeedSet, s, All_MIIA, l, weight)

    return EI


#!/usr/bin/python
import json

import psycopg2

import db_connection
import programminglanguage

def db_connect():
    conn_string = db_connection.get_connection_string()
    # get a connection, if a connect cannot be made an exception will be raised here
    conn = psycopg2.connect(conn_string)
    # conn.cursor will return a cursor object, you can use this cursor to perform queries
    return conn

def make_query(query):
    connection = db_connect()
    cursor = connection.cursor()
    cursor.execute(query)
    objects = create_objects(cursor.fetchall())
    cursor.close()
    connection.close()
    return objects

def update(program):
    conn = db_connect()
    cursor = conn.cursor()
    sql = "UPDATE programmeerimiskeel SET nimi = %s, loomise_aasta = %s, disainer = %s WHERE id = %s"
    cursor.execute(sql, (program.name, program.year, program.designer, program.id))
    conn.commit()
    cursor.close()
    conn.close()

def insert(program):
    conn = db_connect()
    cursor = conn.cursor()
    sql = "INSERT INTO programmeerimiskeel (nimi, loomise_aasta, disainer) VALUES (%s, %s, %s)"
    cursor.execute(sql, (program.name, program.year, program.designer))
    conn.commit()
    cursor.close()
    conn.close()

def create_objects(records):
    result = "["
    size = len(records)
    for index, record in enumerate(records):
        prlng = programminglanguage.ProgrammingLanguage(record[0], record[1], int(record[2]), record[3])
        result += (json.dumps(prlng.serialize()))
        if index < size -1:
            result += ','
    result += "]"
    return result

def delete(id):
    conn = db_connect()
    cursor = conn.cursor()
    sql = "DELETE FROM programmeerimiskeel WHERE programmeerimiskeel.id = " + str(id)
    cursor.execute(sql)
    conn.commit()
    cursor.close()
    conn.close()

def search(id, name, designer, year):
    conn = db_connect()
    cursor = conn.cursor()
    where_clause = ""
    id = id.encode('utf-8')
    name = name.encode('utf-8')
    designer = designer.encode('utf-8')
    year = year.encode('utf-8')
    if not id is "":
        where_clause = " id = " + id
    if not name is '':
        if where_clause is "":
            where_clause += " UPPER(nimi) LIKE UPPER('%" + name + "%')"
        else:
            where_clause += " AND UPPER(nimi) LIKE UPPER('%" + name + "%')"
    if not designer is "":
        if where_clause is "":
            where_clause += " UPPER(disainer) LIKE UPPER('%" + designer + "%')"
        else:
            where_clause += " AND UPPER(disainer) LIKE UPPER('%" + designer + "%')"
    if not year is '':
        if where_clause is "":
            where_clause += " loomise_aasta = " + year
        else:
            where_clause += " AND loomise_aasta = " + year
    # If no search params inserted then return all
    if where_clause is '':
        sql = "SELECT * FROM programmeerimiskeel"
    else:
        sql = "SELECT * FROM programmeerimiskeel WHERE" + where_clause
    cursor.execute(sql)
    objects = create_objects(cursor.fetchall())
    cursor.close()
    conn.close()
    return objects


import pygame
import time
import math
from utils import scale_image, blit_rotate_center

GRASS = scale_image(pygame.image.load("imgs/grass.jpg"), 2.5)
TRACK = scale_image(pygame.image.load("imgs/track.png"), 0.9)

TRACK_BORDER = scale_image(pygame.image.load("imgs/track-border.png"), 0.9)
TRACK_BORDER_MASK = pygame.mask.from_surface(TRACK_BORDER)

FINISH = pygame.image.load("imgs/finish.png")
FINISH_MASK = pygame.mask.from_surface(FINISH)
FINISH_POSITION = (130, 250)

RED_CAR = scale_image(pygame.image.load("imgs/red-car.png"), 0.55)
GREEN_CAR = scale_image(pygame.image.load("imgs/green-car.png"), 0.55)

WIDTH, HEIGHT = TRACK.get_width(), TRACK.get_height()
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Racing Game!")

FPS = 60

class AbstractCar:
    def __init__(self, max_vel, rotation_vel):
        self.img = self.IMG
        self.max_vel = max_vel
        self.vel = 0
        self.rotation_vel = rotation_vel
        self.angle = 0
        self.x, self.y = self.START_POS
        self.acceleration = 0.1

    def rotate(self, left=False, right=False):
        if left:
            self.angle += self.rotation_vel
        elif right:
            self.angle -= self.rotation_vel

    def draw(self, win):
        blit_rotate_center(win, self.img, (self.x, self.y), self.angle)

    def move_forward(self):
        self.vel = min(self.vel + self.acceleration, self.max_vel)
        self.move()

    def move_backward(self):
        self.vel = max(self.vel - self.acceleration, -self.max_vel/2)
        self.move()

    def move(self):
        radians = math.radians(self.angle)
        vertical = math.cos(radians) * self.vel
        horizontal = math.sin(radians) * self.vel

        self.y -= vertical
        self.x -= horizontal

    def collide(self, mask, x=0, y=0):
        car_mask = pygame.mask.from_surface(self.img)
        offset = (int(self.x - x), int(self.y - y))
        poi = mask.overlap(car_mask, offset)
        return poi

    def reset(self):
        self.x, self.y = self.START_POS
        self.angle = 0
        self.vel = 0

class PlayerCar(AbstractCar):
    IMG = RED_CAR
    START_POS = (180, 200)

    def reduce_speed(self):
        self.vel = max(self.vel - self.acceleration / 2, 0)
        self.move()

    def bounce(self):
        self.vel = -self.vel
        self.move()

def draw(win, images, player_car):
    for img, pos in images:
        win.blit(img, pos)

    player_car.draw(win)
    pygame.display.update()

def move_player(player_car):
    keys = pygame.key.get_pressed()
    moved = False

    if keys[pygame.K_a]:
        player_car.rotate(left=True)
    if keys[pygame.K_d]:
        player_car.rotate(right=True)
    if keys[pygame.K_w]:
        moved = True
        player_car.move_forward()
    if keys[pygame.K_s]:
        moved = True
        player_car.move_backward()

    if not moved:
        player_car.reduce_speed()

run = True
clock = pygame.time.Clock()
images = [(GRASS, (0, 0)), (TRACK, (0, 0)),
          (FINISH, FINISH_POSITION), (TRACK_BORDER, (0, 0))]
player_car = PlayerCar(8, 8)

while run:
    clock.tick(FPS)

    draw(WIN, images, player_car)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            break

    move_player(player_car)

    if player_car.collide(TRACK_BORDER_MASK) != None:
        player_car.bounce()

    finish_poi_collide = player_car.collide(FINISH_MASK, *FINISH_POSITION)
    if finish_poi_collide != None:
        if finish_poi_collide[1] == 0:
            player_car.bounce()
        else:
            player_car.reset()
            print("finish")

pygame.quit()


import json
import requests
import time

print("In order for this script to work, the channel ids, auth token, and username are required in the info.json file")

with open('info.json', 'r') as f:
    info = json.load(f)

username = info['username']
auth_token = info['auth_token']
channels = info['channels']

def get_all_user_messages(auth_token, channel_id):
    all_messages = []
    num_of_returned_messages = 100
    last_message_id = ''
    while num_of_returned_messages == 100:
        messages = get_100_messages(auth_token, channel_id, last_message_id)  # get 100 messages
        if messages:
            # last_message_id = min(messages, key=lambda x: x['timestamp'])
            last_message = sorted(messages, key=lambda x: x['timestamp'], reverse=True)[-1]  # get the last message
            last_message_id = last_message['id']
            print('Downloading messages... {}'.format(last_message['timestamp']), end='\r')
            filtered_messages = [m for m in messages if m['author']['username'] == username]  # filter for user's messages
            all_messages += filtered_messages  # add these messages to the list
            num_of_returned_messages = len(messages)  # count how many messages we got this time
    return all_messages

def get_100_messages(auth, id, last=''):
    if not last:  # first method call, start from beginning (might be able to remove)
        messages = json.loads(requests.get("http://discordapp.com/api/v6/channels/" + id + "/messages",
                                           headers={"authorization": auth},
                                           params={"limit": 100}).content)
    else:
        messages = json.loads(requests.get("http://discordapp.com/api/v6/channels/" + id + "/messages",
                                           headers={"authorization": auth},
                                           params={"before": last, "limit": 100}).content)

    return messages

def delete_messages(auth, id, user, messages):
    print("deleting all messages in {} from username {}".format(id, user))
    for message in messages:
        print(message['content'])
        requests.delete("http://discordapp.com/api/v6/channels/" + id + "/messages/" + message["id"],
                        headers={"authorization": auth})
        time.sleep(0.2)  # avoid rate limiting
    print("all messages deleted")

if __name__ == '__main__':
    for channel_id in channels:
        user_messages = get_all_user_messages(auth_token, channel_id)
        delete_messages(auth_token, channel_id, username, user_messages)


from django.shortcuts import render, HttpResponse
from .models import PokemonSpawn, NestMigrations

from .config_parser import get_gmaps_api_key
from .tasks import update_migration_date
from .utils.google_storage import download_xml

def show_map(request):
    nxt = NestMigrations.objects.get_last_datetime()
    if not nxt:
        nxt = update_migration_date()

    api_key = get_gmaps_api_key()
    PokemonSpawn.objects.filter(on_map=True)
    return render(request, template_name='map.html', context={'api_key': api_key,
                                                              'file': 'poke_spawn_test.xml',
                                                              'next_migration_date': nxt.strftime(
                                                                  "%Y-%m-%dT%H:%M:%SZ")})

def proxy(request):
    xml = download_xml(request.GET['url'])
    return HttpResponse(xml, content_type='text/xml')


##Note the parser need s to be re-configured if the PARE validation output have different coulumn structure/numbers

## This script parses the results from PARE validation pipeline - jixian
##Before running this script you may want to filter the PARE pipeline results using PARE_validation_optimization.py
## Immediate old version - parsing_validated_soya.py

import csv

#Open the validated targets file using csv reader
fh_in=open('PARE_validated_miRNAs', 'r')
csv_validated=csv.reader(fh_in, delimiter='\t')

# Open the file to write parsed results
fh_out=open('PARE_valid_parsed', 'w')
csv_validated_parsed=csv.writer(fh_out, delimiter=',')

#Create an empty list so as to read the file row by row and append to this list- loop run directly on csv_val now
#csv_val_table=[]

##Populate the list
#for row in csv_val:
#    csv_val_table.append(row)

validated_entry_count=0
#for i in csv_val_table:
for i in csv_validated:
    miDNA=i[1]
    chromo_up=i[4]
    chromo=chromo_up.lower()## to change 'Chr' to 'chr' as in cleaveland file
    cleave=i[10]
#    print(miDNA, chromo, cleave)
    csv_validated_parsed.writerow([miDNA]+[chromo]+[cleave])
    validated_entry_count+=1

print('The total number of validated entries were:', validated_entry_count)

fh_in.close()
fh_out.close()

'''
Created on Apr 14, 2012

@author: atul
'''


import re

def check(filename, empty_sep_mode):
    """
    Ensures the numbering and title are separated from each other with a dash and not with a dot or not separated at all.
    This assumes numbering is already done, as numbering handler is called before this.
    Setting empty_sep_mode to True makes separators be no characters.
    """

    if not empty_sep_mode:
        if check_correct_dash(filename):
            return filename
    else:
        if check_correct_empty(filename):
            return filename

    new_filename = filename

    new_filename = check_dash(new_filename, empty_sep_mode)
    new_filename = check_empty(new_filename, empty_sep_mode)
    new_filename = check_dot(new_filename, empty_sep_mode)
    new_filename = check_space(new_filename, empty_sep_mode)

    if new_filename == filename:
        print("Separator isn't valid, but no action could be done.")
        print("Do you want to give the file a new name manually?")
        response = input("(Y/N) > ")
        if response.lower() == "y":
            print("Enter new filename, EXCLUDING extension!")
            print("If the song has any features, you don't need to fix them.")
            new_filename = input("Enter new filename, EXCLUDING extension >")
        elif response.lower() == "n":
            print("Skipping separator check for this file.")

    return new_filename

dash_pattern = re.compile(r"\d\d - .*")
empty_pattern = re.compile(r"^(\d\d[^\d. -].*)|(\d\d \d.*)$")
dot_pattern = re.compile(r"\d\d\. .*")
space_pattern = re.compile(r"\d\d [^-]+")

# checks if separator is correct already
def check_correct_dash(filename):
    # check if it already uses dash separators, if so then end function
    if dash_pattern.match(filename):
        print("Separator is valid")
        return True
    return False

def make_empty_sep(trackno, trackname):
    return trackno + (" " if (trackname[0].isdigit()) else "") + trackname

def make_dash_sep(trackno, trackname):
    trackno + " - " + trackname

def check_dash(filename, empty_sep_mode):
    if empty_sep_mode and dash_pattern.match(filename):
        print("Separator is a dash, replacing with an empty separator")
        trackno = filename[0:2]
        trackname: str = filename[5:]
        return make_empty_sep(trackno, trackname)
    return filename

def check_correct_empty(filename):
    if empty_pattern.match(filename):
        print("Separator is valid")
        return True
    return False

# "12Name.flac" or "12 22.flac"
def check_empty(filename: str, empty_sep_mode):
    if not empty_sep_mode and empty_pattern.match(filename):
        print("Empty separator, replacing with a dash")
        trackno = filename[0:2]
        trackname = filename[2:].lstrip()
        return trackno + " - " + trackname
    return filename

# check if filename uses dots (i.e. "12. Title.flac")
def check_dot(filename, empty_sep_mode):
    if dot_pattern.match(filename):
        print("Separator is a dot")
        trackno = filename[0:2]
        trackname = filename[4:]
        return make_dash_sep(trackno, trackname) if not empty_sep_mode else make_empty_sep(trackno, trackname)
    return filename

# check if filename uses a single space
def check_space(filename, empty_sep_mode):
    if space_pattern.match(filename):
        print("Single space separator")
        trackno = filename[0:2]
        trackname = filename[3:]
        return make_dash_sep(trackno, trackname) if not empty_sep_mode else make_empty_sep(trackno, trackname)
    return filename


#in order -> left, root, right

#Definition for a binary tree node.
class Node:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def inorderTraversal_iterative(self, root):
        if root == None:
            return None

        stack = []
        output = []

        curr = root

        while (curr != None or len(stack) != 0):
            #add all left nodes to stack
            while (curr != None):
                stack.append(curr)
                curr = curr.left

            #add the left most stack
            curr = stack.pop()
            output.append(curr.val)

            #
            curr = curr.right

        return output

    def inorderTraversal_recursive(self, root):
        output = []
        stack = []

        self.helper(root, output)
        return output

    def helper(self,elem, output):
        if elem != None:
            if (elem.left != None):
                self.helper(elem.left, output)

            output.append(elem.val)

            if (elem.right != None):
                self.helper(elem.right, output)

node5 = Node(5)
node6 = Node(6)
node3 = Node(3, node5, node6)
node4 = Node(4)
node1 = Node(1, node3, node4)

solution = Solution()
print(solution.inorderTraversal_iterative(node1))

print(solution.inorderTraversal_recursive(node1))


# Casos y dinero que tiene Cherlo
N,M = map(int, input().strip().split())

# Recogo los datos y guardo lo que me interesa
candidatos = []

for i in range(N):
    coste, beneficio = map(int, input().strip().split())
    candidatos.append((beneficio/coste, coste, beneficio, i))

candidatos.sort(reverse=True)

# recorro la lista de candidatos
j = 0
sol = []
benFinal = 0
while(j < len(candidatos) and M > 0):
    M = M - candidatos[j][1]
    if M < 0:
        benFinal += round((M + candidatos[j][1]) * candidatos[j][0])
        sol.append(candidatos[j][3])
    else:
        benFinal += candidatos[j][2]
        sol.append(candidatos[j][3])
    j += 1

sol.sort()

for a in sol:
    print(a, "", end="")
print()
print(benFinal)


from dto.base_response import BaseResponse

class AssetResponse(BaseResponse):
    def __init__(self):
        super().__init__()
        self.asset_data = []
        self.assets = []

    def serialize(self):
        return {
            "asset_data": self.asset_data,
            "assets": self.assets,
            "infos": self.infos.serialize(),
            "response_code": self.response_code
        }


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

"""Loop detector

Detect loops in Hi-C contact maps with pattern matching.

"""

from setuptools import setup, find_packages

CLASSIFIERS = [
    "Development Status :: 1 - Planning",
    "Intended Audience :: Science/Research",
    "License :: OSI Approved :: Artistic License",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3.6",
    "Topic :: Scientific/Engineering",
    "Topic :: Scientific/Engineering :: Bio-Informatics",
    "Topic :: Scientific/Engineering :: Visualization",
    "Operating System :: Microsoft :: Windows",
    "Operating System :: POSIX",
    "Operating System :: Unix",
    "Operating System :: MacOS",
]

name = "declooptor"

MAJOR = 0
MINOR = 1
MAINTENANCE = 0
VERSION = f"{MAJOR}.{MINOR}.{MAINTENANCE}"

LICENSE = "Artistic"

with open("requirements.txt", "r") as f:
    REQUIREMENTS = f.read().splitlines()

with open("serpentine/version.py", "w") as f:
    f.write("__version__ = '{}'\n".format(VERSION))

setup(
    name=name,
    author="axel.cournac@pasteur.fr",
    description=__doc__,
    version=VERSION,
    license=LICENSE,
    classifiers=CLASSIFIERS,
    packages=find_packages(exclude=["demos"]),
    install_requires=REQUIREMENTS,
    include_package_data=True,
    entry_points={"console_scripts": ["declooptor=declooptor.detector:_main"]},
)


'''

Anthony Thomas-Bell
V1.0 July 23rd 2019
Updated: December 7th 2

Class that is going to run the scikit learn models for the cannabis classification problem.

'''

class MlModel:
    # TODO Insert INIT function that sets the X_Train, X_Test, y_train, y_test datasets
    # def __init__(self, x_train, x_test, y_train, y_test):
    #     self.X_TRAIN = x_train
    #     self.X_TEST = x_test
    #     self.Y_TRAIN = y_train
    #     self.Y_TEST = x_test

    # Balance the classes in the target column utilizing SMOTE or ADASYN oversampling techniques
    def balance_dataset(self, x_data, y_data, target_col=None, sampling='SMOTE'):
        from imblearn.over_sampling import SMOTE, ADASYN
        # TODO Get the Highest class value, and set every other class to be sampled with that amount in dictionary
        # Since the training dataset is skewed we are going to use SMOTE and ADASYN to artificially inflate
        # our minority classes for this is for training purposes only, it will not effect the testing data.
        # need to adjust balance dict to account for target_col variable that is passed in
        balance_dict = {0: len(y_data), 1: len(y_data)}

        # Sampling Algorithms
        sm = SMOTE(random_state=42, sampling_strategy=balance_dict)
        ada = ADASYN(random_state=42, sampling_strategy=balance_dict)
        # try:

        # Resampled training data
        X_res, y_res = sm.fit_resample(x_data, y_data)
        X_res_ada, y_res_ada = ada.fit_resample(x_data, y_data)

        # except:
        # print("Exception Occurred")

        # print(X_res, y_res)
        return X_res, X_res_ada, y_res, y_res_ada

    # Output the Models Metric information such as the Accuracy, Precision, Recall, F-1 Score, and AUC value
    def model_metrics(self, y_test, predictions, model_name="ML Model", plot=True):
        from sklearn.metrics import accuracy_score, precision_recall_fscore_support, roc_curve, roc_auc_score
        from matplotlib import pyplot as plt

        print("==================================================================")
        print(model_name + "\n")
        print("==================================================================")
        print("{} has an accuracy of {}".format(model_name, accuracy_score(y_test, predictions)))
        print("==================================================================")
        print("Precision, Recall, F-Score, Weight")
        print("Base Information {}".format(precision_recall_fscore_support(y_test, predictions)))
        print("Macro {}".format(
            precision_recall_fscore_support(y_test, predictions, average='macro')))
        print("Micro {}".format(
            precision_recall_fscore_support(y_test, predictions, average='micro')))
        print("Weighted {}".format(
            precision_recall_fscore_support(y_test, predictions, average='weighted')))
        print("==================================================================")
        auc = roc_auc_score(y_test, predictions)
        print("{} has a AUC(area under the curve) of : {}".format(model_name, auc))
        print("==================================================================")

        if plot:
            # Plotting the ROC Curve
            fpr, tpr, thresholds = roc_curve(y_test, predictions)
            plt.plot(1, 1)
            plt.plot(fpr, tpr, color='green', label='ROC', marker='.')
            plt.plot([0, 1], [0, 1], color='darkblue', linestyle='--')
            plt.xlabel('False Positive Rate')
            plt.ylabel('True Positive Rate')
            plt.title('{} ROC Curve'.format(model_name))
            plt.legend()
            plt.figlegend(["AUC = {0:.4f}".format(auc)])
            plt.show()

    # Plot and show the confusion matrix
    def plot_and_confusion_matrix(self, model, data_predictions, type_labels, X_test, y_test, model_name, n_classes=2):
        from matplotlib import pyplot as plt
        import seaborn as sn
        from sklearn.metrics import confusion_matrix

        modelcm = confusion_matrix(y_test, data_predictions)
        print("{} confusion matrix numbers \n{}".format(model_name, modelcm))
        print("Type : {}".format(type(modelcm)))

        # Getting the y_score based on the selected model name, fix redundant elif
        if model_name.__contains__("Decision Tree"):
            y_score = model.decision_path(X_test)
        elif model_name.__contains__("KNN"):
            y_score = model.score(X_test, y_test)
        else:
            y_score = model.score(X_test, y_test)

        plt.title(model_name)
        sn.heatmap(modelcm, annot=True, xticklabels=type_labels, yticklabels=type_labels, fmt=".2f")
        plt.ylabel("Truth")
        plt.xlabel("Predicted")
        plt.show()

    def multilabel_classifier(self, X_train, y_train, X_test, y_test, estimator=None):
        from sklearn.multiclass import OneVsRestClassifier
        from sklearn.svm import SVC

        if estimator:
            classifer = OneVsRestClassifier(estimator).fit(X_train, y_train)
        else:
            classifer = OneVsRestClassifier(SVC(kernel='linear')).fit(X_train, y_train)

        # print("Multilabel Classifier Score {}".format(classifer.score(X_test, y_test)))
        y_score = classifer.decision_function(X_test)

        return classifer, y_score

    def k_nearest_neighbors(self, neighbors, X_train, y_train, X_test):
        from sklearn.neighbors import KNeighborsClassifier
        # knn model
        try:
            knn = KNeighborsClassifier(n_neighbors=neighbors, p=2).fit(X_train, y_train)
        except ValueError:
            print("KNN was not created and threw a Value Error")

        knn_predictions = knn.predict(X_test)

        return knn, knn_predictions

    def decision_tree(self, max_depth, X_train, X_test, y_train, y_test):
        from sklearn.tree import DecisionTreeClassifier
        dtree_model = DecisionTreeClassifier(max_depth=max_depth).fit(X_train, y_train)
        # print(dtree_model.score(X_test, y_test))
        dtree_predictions = dtree_model.predict(X_test)

        return dtree_model, dtree_predictions

    def svm_classifier(self, X_train, X_test, y_train, kernal='rbf', c=1.0):
        from sklearn.svm import SVC
        svm_model_linear = SVC(kernel=kernal, C=c, probability=True)
        svm_model_linear.fit(X_train, y_train)
        svm_predictions = svm_model_linear.predict(X_test)
        log_svm_predictions = svm_model_linear.predict_log_proba(X_test)
        # print(log_svm_predictions)

        return svm_model_linear, svm_predictions

    def logistic_regression(self, x, y, x_test, y_test, multi=False):
        from sklearn.linear_model import LogisticRegression

        if multi:
            log_regres_model = LogisticRegression(multi_class="multinomial", solver="newton-cg")
        else:
            log_regres_model = LogisticRegression()

        predicted_labels = None

        if x is not None and y is not None:

            log_regres_model.fit(X=x, y=y)
            r_sq = log_regres_model.score(x, y)
            print("The R Squared for this model is : {}".format(r_sq))

            if x_test is not None:
                predicted_labels = log_regres_model.predict(X=x_test)
                # print(predicted_labels)
                # print(y_test)
                #
                # test_df = pd.DataFrame(data={"predicted": predicted_labels, "actual": y_test})
                # print(test_df)

        return log_regres_model, predicted_labels

    def nb_guassian_classifer(self, X_train, y_train, X_test):
        from sklearn.naive_bayes import GaussianNB

        gnb = GaussianNB()
        gnb_predictions = gnb.fit(X_train, y_train).predict(X_test)
        # print(gnb_predictions)

        return gnb, gnb_predictions

    def csv_to_json(self, csvFilePath, jsonFilePath):
        import csv
        import json

        data = {}

        # Reading and converting csvFile into JSON using the StrainID as the id
        with open(csvFilePath) as csvFile:
            for rows in csv.DictReader(csvFile):
                id = rows['StrainID']
                data[id] = rows
        with open(jsonFilePath, 'w') as jsonFile:
            jsonFile.write(json.dumps(data, indent=4))

        return jsonFile


#!/usr/bin/env python
# encoding: utf-8
r"""
Routines for reading and writing a NetCDF output file

Routines for reading and writing a NetCDF output file via either
    - netcdf4-python - http://code.google.com/p/netcdf4-python/
    - pupynere - http://pypi.python.org/pypi/pupynere/

These interfaces are very similar so if a different module needs to be used,
it can more than likely be inserted with a minimal of effort.

This module will first try to import the netcdf4-python module which is based
on the compiled libraries and failing that will attempt to import the pure
python interface pupynere which requires no libraries.

To install the netCDF 4 library, please see:
    http://www.unidata.ucar.edu/software/netcdf/

:Authors:
    Kyle T. Mandli (2009-02-17) Initial version
"""
# ============================================================================
#      Copyright (C) 2009 Kyle T. Mandli <mandli@amath.washington.edu>
#
#  Distributed under the terms of the Berkeley Software Distribution (BSD)
#  license
#                     http://www.opensource.org/licenses/
# ============================================================================

import os,sys
import logging

import clawpack.pyclaw.solution

logger = logging.getLogger('pyclaw.fileio')

# Import appropriate netcdf package
use_netcdf4 = False
use_pupynere = False
try:
    import netCDF4
    use_netcdf4 = True
except:
    pass
if not use_netcdf4:
    try:
        import pupynere
        use_pupynere = True
    except:
        error_msg = ("Could not import netCDF4 or Pupynere, please install " +
            "one of the available modules for netcdf files.  Refer to this " +
            "modules doc_string for more information.")
        #raise Exception(error_msg)
        print(error_msg)

def write(solution,frame,path,file_prefix='claw',write_aux=False,
                    options={},write_p=False):
    r"""
    Write out a NetCDF data file representation of solution

    :Input:
     - *solution* - (:class:`~pyclaw.solution.Solution`) Pyclaw object to be
       output
     - *frame* - (int) Frame number
     - *path* - (string) Root path
     - *file_prefix* - (string) Prefix for the file name. ``default = 'claw'``
     - *write_aux* - (bool) Boolean controlling whether the associated
       auxiliary array should be written out. ``default = False``
     - *options* - (dict) Optional argument dictionary, see
       `NetCDF Option Table`_

    .. _`NetCDF Option Table`:

    +-------------------------+----------------------------------------------+
    | Key                     | Value                                        |
    +=========================+==============================================+
    | description             | Dictionary of key/value pairs that will be   |
    |                         | attached to the root group as attributes,    |
    |                         | i.e. {'time':3}                              |
    +-------------------------+----------------------------------------------+
    | format                  | Can be one of the following netCDF flavors:  |
    |                         | NETCDF3_CLASSIC, NETCDF3_64BIT,              |
    |                         | NETCDF4_CLASSIC, and NETCDF4                 |
    |                         | ``default = NETCDF4``                        |
    +-------------------------+----------------------------------------------+
    | clobber                 | if True (Default), file will be overwritten, |
    |                         | if False an exception will be raised         |
    +-------------------------+----------------------------------------------+
    | zlib                    | if True, data assigned to the Variable       |
    |                         | instance is compressed on disk.              |
    |                         | ``default = False``                          |
    +-------------------------+----------------------------------------------+
    | complevel               | the level of zlib compression to use (1 is   |
    |                         | the fastest, but poorest compression, 9 is   |
    |                         | the slowest but best compression).  Ignored  |
    |                         | if zlib=False.  ``default = 6``              |
    +-------------------------+----------------------------------------------+
    | shuffle                 | if True, the HDF5 shuffle filter is applied  |
    |                         | to improve compression. Ignored if           |
    |                         | zlib=False. ``default = True``               |
    +-------------------------+----------------------------------------------+
    | fletcher32              | if True (default False), the Fletcher32      |
    |                         | checksum algorithm is used for error         |
    |                         | detection.                                   |
    +-------------------------+----------------------------------------------+
    | contiguous              | if True (default False), the variable data   |
    |                         | is stored contiguously on disk.  Setting to  |
    |                         | True for a variable with an unlimited        |
    |                         | dimension will trigger an error.             |
    |                         | ``default = False``                          |
    +-------------------------+----------------------------------------------+
    | chunksizes              | Can be used to specify the HDF5 chunksizes   |
    |                         | for each dimension of the variable. A        |
    |                         | detailed discussion of HDF chunking and I/O  |
    |                         | performance is available here. Basically,    |
    |                         | you want the chunk size for each dimension   |
    |                         | to match as closely as possible the size of  |
    |                         | the data block that users will read from the |
    |                         | file. chunksizes cannot be set if            |
    |                         | contiguous=True.                             |
    +-------------------------+----------------------------------------------+
    | least_significant_digit | If specified, variable data will be          |
    |                         | truncated (quantized). In conjunction with   |
    |                         | zlib=True this produces 'lossy', but         |
    |                         | significantly more efficient compression.    |
    |                         | For example, if least_significant_digit=1,   |
    |                         | data will be quantized using around          |
    |                         | (scale*data)/scale, where scale = 2**bits,   |
    |                         | and bits is determined so that a precision   |
    |                         | of 0.1 is retained (in this case bits=4).    |
    |                         | ``default = None``, or no quantization.      |
    +-------------------------+----------------------------------------------+
    | endian                  | Can be used to control whether the data is   |
    |                         | stored in little or big endian format on     |
    |                         | disk. Possible values are little, big or     |
    |                         | native (default). The library will           |
    |                         | automatically handle endian conversions when |
    |                         | the data is read, but if the data is always  |
    |                         | going to be read on a computer with the      |
    |                         | opposite format as the one used to create    |
    |                         | the file, there may be some performance      |
    |                         | advantage to be gained by setting the        |
    |                         | endian-ness.                                 |
    +-------------------------+----------------------------------------------+
    | fill_value              | If specified, the default netCDF _FillValue  |
    |                         | (the value that the variable gets filled     |
    |                         | with before any data is written to it) is    |
    |                         | replaced with this value. If fill_value is   |
    |                         | set to False, then the variable is not       |
    |                         | pre-filled.                                  |
    +-------------------------+----------------------------------------------+

    .. note::
        The zlib, complevel, shuffle, fletcher32, contiguous, chunksizes and
        endian keywords are silently ignored for netCDF 3 files that do not
        use HDF5.

    """

    # Option parsing
    option_defaults = {'format':'NETCDF4','zlib':False,'complevel':6,
                       'shuffle':True,'fletcher32':False,'contiguous':False,
                       'chunksizes':None,'endian':'native',
                       'least_significant_digit':None,'fill_value':None,
                       'clobber':True,'description':{}}
    for (k,v) in option_defaults.items():
        if k in options:
            exec("%s = options['%s']" % (k,k))
        else:
            exec('%s = v' % k)

    # Filename
    filename = os.path.join(path,"%s%s.nc" % (file_prefix,str(frame).zfill(4)))

    if use_netcdf4:
        # Open new file
        f = netCDF4.Dataset(filename,'w',clobber=clobber,format=format)

        # Loop through description dictionary and add the attributes to the
        # root group
        for (k,v) in description.items():
            exec('f.%s = %s' % (k,v))

        # For each patch, write out attributes
        for state in solution.states:
            patch = solution.patch
            # Create group for this patch
            subgroup = f.createGroup('patch%s' % patch.patch_index)

            # General patch properties
            for attr in ['t','num_eqn']:
                setattr(subgroup,attr,getattr(state,attr))
            for attr in ['patch_index','level']:
                setattr(subgroup,attr,getattr(patch,attr))

            # Write out dimension names
            setattr(subgroup,'dim_names',patch.name)

            # Create dimensions for q (and aux)
            for dim in patch.dimensions:
                subgroup.createDimension(dim.name,dim.num_cells)
                # Write other dimension attributes
                for attr in ['num_cells','lower','delta','upper','bc_lower',
                             'bc_upper','units']:
                    if hasattr(dim,attr):
                        if getattr(dim,attr) is not None:
                            attr_name = '%s.%s' % (dim.name,attr)
                            setattr(subgroup,attr_name,getattr(dim,attr))
            subgroup.createDimension('num_eqn',state.num_eqn)

            # Write q array
            from copy import copy
            dim_names = copy(patch.name)
            dim_names.append('num_eqn')
            index_str = ','.join( [':' for name in dim_names] )
            q = subgroup.createVariable('q','f8',dim_names,zlib,
                                            complevel,shuffle,fletcher32,
                                            contiguous,chunksizes,endian,
                                            least_significant_digit,fill_value)
            exec("q[%s] = state.q" % index_str)

            # Write out aux
            if state.num_aux > 0 and write_aux:
                dim_names[-1] = 'num_aux'
                subgroup.createDimension('num_aux',state.num_aux)
                aux = subgroup.createVariable('aux','f8',dim_names,
                                            zlib,complevel,shuffle,fletcher32,
                                            contiguous,chunksizes,endian,
                                            least_significant_digit,fill_value)
                exec("aux[%s] = state.aux" % index_str)

        f.close()
    elif use_pupynere:
        logging.critical("Pupynere support has not been implemented yet.")
        raise IOError("Pupynere support has not been implemented yet.")
    else:
        err_msg = "No netcdf python modules available."
        logging.critical(err_msg)
        raise Exception(err_msg)

def read(solution,frame,path='./',file_prefix='claw',read_aux=True,
                options={}):
    r"""
    Read in a NetCDF data files into solution

    :Input:
     - *solution* - (:class:`~pyclaw.solution.Solution`) Pyclaw object to be
       output
     - *frame* - (int) Frame number
     - *path* - (string) Root path
     - *file_prefix* - (string) Prefix for the file name.  ``default = 'claw'``
     - *write_aux* - (bool) Boolean controlling whether the associated
       auxiliary array should be written out.  ``default = False``
     - *options* - (dict) Optional argument dictionary, unused for reading.
    """

    # Option parsing
    option_defaults = {}
    for (k,v) in option_defaults.items():
        if k in options:
            exec("%s = options['%s']" % (k,k))
        else:
            exec('%s = v' % k)

    # Filename
    filename = os.path.join(path,"%s%s.nc" % (file_prefix,str(frame).zfill(4)))

    if use_netcdf4:
        # Open file
        f = netCDF4.Dataset(filename,'r')

        # We only expect subgroups of patches, otherwise we need to put some
        # sort of conditional here
        for subgroup in f.groups.values():
            # Construct each dimension
            dimensions = []

            # Read in dimension attribute to keep dimension order
            dim_names = getattr(subgroup,'dim_names')
            for dim_name in dim_names:
                dim = pyclaw.solution.Dimension(
                                      getattr(subgroup,'%s.lower' % dim_name),
                                      getattr(subgroup,'%s.upper' % dim_name),
                                      getattr(subgroup,'%s.n' % dim_name),
                                      name = dim_name)
                 # Optional attributes
                for attr in ['bc_lower','bc_upper','units']:
                    attr_name = "%s.%s" % (dim_name,attr)
                    if hasattr(subgroup,attr_name):
                        setattr(dim,attr,getattr(subgroup, "%s.%s" % (dim_name,attr)))
                dimensions.append(dim)

            # Create patch
            patch = pyclaw.solution.Patch(dimensions)

            # General patch properties
            for attr in ['t','num_eqn','patch_index','level']:
                setattr(patch,attr,getattr(subgroup,attr))

            # Read in q
            index_str = ','.join( [':' for i in range(patch.num_dim+1)] )
            exec("patch.q = subgroup.variables['q'][%s]" % index_str)

            # Read in aux if applicable
            if read_aux and 'num_aux' in subgroup.dimensions:
                exec("patch.aux = subgroup.variables['aux'][%s]" % index_str)

            solution.patches.append(patch)

        f.close()
    elif use_pupynere:
        logging.critical("Pupynere support has not been implemented yet.")
        raise IOError("Pupynere support has not been implemented yet.")
    else:
        err_msg = "No netcdf python modules available."
        logging.critical(err_msg)
        raise Exception(err_msg)


import pickle
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
from sklearn.model_selection import ShuffleSplit
from feature_engineering import FeatureEngineering
from sklearn.ensemble import RandomForestClassifier
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.naive_bayes import MultinomialNB
import pandas as pd

with open("features_train.pickle", 'rb') as output :
	features_train = pickle.load(output)

with open("labels_train.pickle", 'rb') as output :
	labels_train = pickle.load(output)

with open("features_test.pickle", 'rb') as output :
	features_test = pickle.load(output)

with open("labels_test.pickle", 'rb') as output :
	labels_test = pickle.load(output)

class modellig :

	# Build base model using Random Forest Classifier
	# def RFC(self,features_train, labels_train,features_test, labels_test,clean_data_frame):
		# print(features_train.shape)
		# print(features_test.shape)

		# rf_0 = RandomForestClassifier(random_state = 8)
		# print('Parameters currently in use:\n')
		# print(rf_0.get_params())

		# # n_estimators
		# n_estimators = [int(x) for x in np.linspace(start = 200, stop = 1000, num = 5)]

		# # max_features
		# max_features = ['auto', 'sqrt']

		# # max_depth
		# max_depth = [int(x) for x in np.linspace(20, 100, num = 5)]
		# max_depth.append(None)

		# # min_samples_split
		# min_samples_split = [2, 5, 10]

		# # min_samples_leaf
		# min_samples_leaf = [1, 2, 4]

		# # bootstrap
		# bootstrap = [True, False]

		# # Create the random grid
		# random_grid = {'n_estimators': n_estimators,
		#                'max_features': max_features,
		#                'max_depth': max_depth,
		#                'min_samples_split': min_samples_split,
		#                'min_samples_leaf': min_samples_leaf,
		#                'bootstrap': bootstrap}

		# print(random_grid)

		# # First create the base model to tune
		# rfc = RandomForestClassifier(random_state=8)

		# # Definition of the random search
		# random_search = RandomizedSearchCV(estimator=rfc,
		#                                    param_distributions=random_grid,
		#                                    n_iter=50,
		#                                    scoring='accuracy',
		#                                    cv=3,
		#                                    verbose=1,
		#                                    random_state=8)

		# # Fit the random search model
		# random_search.fit(features_train, labels_train)

		# print("The best hyperparameters from Random Search are:")
		# print(random_search.best_params_)
		# print("")
		# print("The mean accuracy of a model with these hyperparameters is:")
		# print(random_search.best_score_)

		# Create the parameter grid based on the results of random search
		# bootstrap = [False]
		# max_depth = [30, 40, 50]
		# max_features = ['sqrt']
		# min_samples_leaf = [1, 2, 4]
		# min_samples_split = [5, 10, 15]
		# n_estimators = [800]

		# param_grid = {
		#     'bootstrap': bootstrap,
		#     'max_depth': max_depth,
		#     'max_features': max_features,
		#     'min_samples_leaf': min_samples_leaf,
		#     'min_samples_split': min_samples_split,
		#     'n_estimators': n_estimators
		# }

		# # Create a base model
		# rfc = RandomForestClassifier(random_state=8)

		# # Manually create the splits in CV in order to be able to fix a random_state (GridSearchCV doesn't have that argument)
		# cv_sets = ShuffleSplit(n_splits = 3, test_size = .33, random_state = 8)

		# # Instantiate the grid search model
		# grid_search = GridSearchCV(estimator=rfc,
		#                            param_grid=param_grid,
		#                            scoring='accuracy',
		#                            cv=cv_sets,
		#                            verbose=1)

		# # Fit the grid search to the data
		# grid_search.fit(features_train, labels_train)

		# print("The best hyperparameters from Grid Search are:")
		# print(grid_search.best_params_)
		# print("")
		# print("The mean accuracy of a model with these hyperparameters is:")
		# print(grid_search.best_score_)

		# best_rfc = grid_search.best_estimator_
		# best_rfc

		# best_rfc.fit(features_train, labels_train)
		# rfc_pred = best_rfc.predict(features_test)

		# # Training accuracy
		# print("The training accuracy is: ")
		# print(accuracy_score(labels_train, best_rfc.predict(features_train)))

		# # Test accuracy
		# print("The test accuracy is: ")
		# print(accuracy_score(labels_test, rfc_pred))

		# # Classification report
		# print("Classification report")
		# print(classification_report(labels_test,rfc_pred))

		# aux_df = clean_data_frame[['Sentiment Class', 'Category_Code']].drop_duplicates().sort_values('Category_Code')
		# conf_matrix = confusion_matrix(labels_test, rfc_pred)
		# plt.figure(figsize=(12.8,6))
		# sns.heatmap(conf_matrix,
		#             annot=True,
		#             xticklabels=aux_df['Sentiment Class'].values,
		#             yticklabels=aux_df['Sentiment Class'].values,
		#             cmap="Blues")
		# plt.ylabel('Predicted')
		# plt.xlabel('Actual')
		# plt.title('Confusion matrix')
		# plt.show()

		# base_model = RandomForestClassifier(random_state = 8)
		# base_model.fit(features_train, labels_train)
		# accuracy_score(labels_test, base_model.predict(features_test))

		# best_rfc.fit(features_train, labels_train)
		# accuracy_score(labels_test, best_rfc.predict(features_test))

		# d = {
		#      'Model': 'Random Forest',
		#      'Training Set Accuracy': accuracy_score(labels_train, best_rfc.predict(features_train)),
		#      'Test Set Accuracy': accuracy_score(labels_test, rfc_pred)
		# }

		# df_models_rfc = pd.DataFrame(d, index=[0])

		# df_models_rfc

		# with open('Models/best_rfc.pickle', 'wb') as output:
		#     pickle.dump(best_rfc, output)

		# with open('Models/df_models_rfc.pickle', 'wb') as output:
		#     pickle.dump(df_models_rfc, output)

		# using multinomial naive bayes classifier

	def MNB(self,features_train, labels_train,features_test, labels_test,clean_data_frame):

		print(features_train.shape)
		print(features_test.shape)

		mnbc = MultinomialNB()
		mnbc

		mnbc.fit(features_train, labels_train)
		mnbc_pred = mnbc.predict(features_test)
		# Training accuracy
		print("The training accuracy is: ")
		print(accuracy_score(labels_train, mnbc.predict(features_train)))

		# Test accuracy
		print("The test accuracy is: ")
		print(accuracy_score(labels_test, mnbc_pred))

		# Classification report
		print("Classification report")
		print(classification_report(labels_test,mnbc_pred))

		aux_df = clean_data_frame[['Sentiment Class', 'category_code']].drop_duplicates().sort_values('category_code')
		conf_matrix = confusion_matrix(labels_test, mnbc_pred)
		plt.figure(figsize=(12.8,6))
		sns.heatmap(conf_matrix/np.sum(conf_matrix),
		            annot=True,
		            fmt='.2%',
		            xticklabels=aux_df['Sentiment Class'].values,
		            yticklabels=aux_df['Sentiment Class'].values,
		            cmap="Blues")
		plt.ylabel('Predicted')
		plt.xlabel('Actual')
		plt.title('Confusion matrix')
		plt.show()

		d = {
		     'Model': 'Multinomial Naïve Bayes',
		     'Training Set Accuracy': accuracy_score(labels_train, mnbc.predict(features_train)),
		     'Test Set Accuracy': accuracy_score(labels_test, mnbc_pred)
		}

		df_models_mnbc = pd.DataFrame(d, index=[0])

		df_models_mnbc

		with open('df_models_mnbc.pickle', 'wb') as output:
			pickle.dump(df_models_mnbc, output)

	def main(self):
		FE=FeatureEngineering()
		features_train, labels_train,features_test, labels_test,clean_data_frame=FE.main()
		# RandomforestC=self.RFC(features_train, labels_train,features_test, labels_test,clean_data_frame)
		MultinomialNB = self.MNB(features_train, labels_train,features_test, labels_test,clean_data_frame)

if __name__ == '__main__':
	KNN = modellig()
	KNN.main()


#!/usr/bin/python3

from models.base import Base

class Rectangle(Base):
    def __init__(self, width, height, x=0, y=0, id=None):
        super().__init__(id)
        self.width = width
        self.height = height
        self.x = x
        self.y = y

    @property
    def width(self):
        return self.__width

    @width.setter
    def width(self, value):
        self.validation_case("width", value)
        self.__width = value

    @property
    def height(self):
        return self.__height

    @width.setter
    def height(self, value):
        self.validation_case("height", value)
        self.__height = value

    @property
    def x(self):
        return self.__x

    @width.setter
    def x(self, value):
        self.validation_case("x", value)
        self.__x = value

    @property
    def y(self):
        return self.__y

    @width.setter
    def y(self, value):
        self.validation_case("y", value)
        self.__y = value

    def validation_case(self, name, value):
        if type(value) != int:
            raise TypeError("{} must be an integer". format(name))

        if name == "width" or name == "heigth":
            if value <= 0:
                raise ValueError("{} must be > 0".format(name))

        if value < 0:
            raise ValueError("{} must be >= 0".format(name))

    """ PUBLIC METHODS """

    def area(self):
        return self.__width * self.__height

    def display(self):
        print(('\n' * self.__y) + ((" " * self.__x) \
            + "#" * self.__width + '\n') * self.__height, end='')

    def __str__(self):
        return "[{}] ({}) {}/{} - {}/{}".format(__class__.__name__,
                                        self.id,
                                        self.__x,
                                        self.__y,
                                        self.__width,
                                        self.__height)

    def update(self, *args, **kwargs):
        if args is not  None and len(args) > 0:
            for i, ar in enumerate(args):
                if i == 0:
                    super().__init__(ar)
                    self.id = ar
                if i == 1:
                    self.__width = ar
                if i == 2:
                    self.__height = ar
                if i == 3:
                    self.__x = ar
                if i == 4:
                    self.__y = ar

        elif kwargs is not None and len(kwargs) > 0:
            for key, value in kwargs.items():
                if key == 'id':
                    super().__init__(value)
                    self.id = value
                if key == 'width':
                    self.__width = value
                if key == 'height':
                    self.__height = value
                if key == 'x':
                    self.__x = value
                if key == 'y':
                    self.__y = value

    def to_dictionary(self):
        l = ['id', 'width', 'height', 'x', 'y']
        d = {}

        for arg in l:
            a = {arg: getattr(self, arg)}
            d.update(a)
        return d


import os
import datetime
import numpy as np
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import (
    Concatenate,
    Dense,
    Embedding,
    Flatten,
    Input,
    Multiply,
)
from tensorflow.keras import Model
from tensorflow.keras.regularizers import l2
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.utils import to_categorical
from typing import List

__author__ = 'linhthi'

class NeuMF:
    def __init__(self,
                 number_of_users: int,
                 number_of_items: int,
                 latent_dim_mf: int = 4,
                 latent_dim_mlp: int = 32,
                 reg_mf: float = 0,
                 reg_mlp: float = 0.01,
                 dense_layers: List[int] = [8, 4],
                 reg_layers: List[int] = [0.01, 0.01],
                 activation_dense: str = "relu"
                 ) -> keras.Model:
        """ Init class NeuMF """

        self.activation_dense = activation_dense
        self.reg_layers = reg_layers
        self.dense_layers = dense_layers
        self.reg_mlp = reg_mlp
        self.reg_mf = reg_mf
        self.latent_dim_mlp = latent_dim_mlp
        self.latent_dim_mf = latent_dim_mf
        self.number_of_items = number_of_items
        self.number_of_users = number_of_users

    def get_model(self) -> object:
        # input layer
        user = Input(shape=(1), dtype="int32", name="user_id")
        item = Input(shape=(1), dtype="int32", name="item_id")

        # embedding layer
        mf_user_embedding = Embedding(
            input_dim=self.number_of_items,
            output_dim=self.latent_dim_mf,
            name="mf_user_embedding",
            embeddings_initializer="RandomNormal",
            embeddings_regularizer=l2(self.reg_mf),
            input_length=1,
        )
        mf_item_embedding = Embedding(
            input_dim=self.number_of_items,
            output_dim=self.latent_dim_mf,
            name="mf_item_embedding",
            embeddings_initializer="RandomNormal",
            embeddings_regularizer=l2(self.reg_mf),
            input_length=1,
        )
        mlp_user_embedding = Embedding(
            input_dim=self.number_of_users,
            output_dim=self.latent_dim_mlp,
            name="mlp_user_embedding",
            embeddings_initializer="RandomNormal",
            embeddings_regularizer=l2(self.reg_mlp),
            input_length=1,
        )
        mlp_item_embedding = Embedding(
            input_dim=self.number_of_items,
            output_dim=self.latent_dim_mlp,
            name="mlp_item_embedding",
            embeddings_initializer="RandomNormal",
            embeddings_regularizer=l2(self.reg_mlp),
            input_length=1,
        )

        # MF vector
        mf_user_latent = Flatten()(mf_user_embedding(user))
        mf_item_latent = Flatten()(mf_item_embedding(item))
        mf_cat_latent = Multiply()([mf_user_latent, mf_item_latent])

        # MLP vector
        mlp_user_latent = Flatten()(mlp_user_embedding(user))
        mlp_item_latent = Flatten()(mlp_item_embedding(item))
        mlp_cat_latent = Concatenate()([mlp_user_latent, mlp_item_latent])

        mlp_vector = mlp_cat_latent

        # build dense layers for model
        for i in range(len(self.dense_layers)):
            layer = Dense(
                self.dense_layers[i],
                activity_regularizer=l2(self.reg_layers[i]),
                activation=self.activation_dense,
                name="layer%d" % i,
            )
            mlp_vector = layer(mlp_vector)

        predict_layer = Concatenate()([mf_cat_latent, mlp_vector])
        result = Dense(1, name="predict_rating")
        output = result(predict_layer)

        model = Model(
            inputs=[user, item],
            outputs=output
        )

        return model

    def train(self, train, valid, n_epochs):
        N_EPOCHS = n_epochs
        self.neuMF_model = self.get_model()

        self.neuMF_model.compile(
            optimizer=SGD(lr=0.001),
            loss = tf.keras.losses.MSE,
            metrics=[
                tf.keras.metrics.mae,
                tf.keras.metrics.RootMeanSquaredError(),
            ]
        )

        self.neuMF_model._name = "neural_matrix_factorization"
        self.neuMF_model.summary()

        user_train, item_train, rating_train = [], [], []
        for data in train:
            user_train.append(data[0])
            item_train.append(data[1])
            rating_train.append(data[3])
        # print(user_train.reshape())
        # print(ds_train.shape)

        user_valid, item_valid, rating_valid = [], [], []
        for data in valid:
            user_valid.append(data[0])
            item_valid.append(data[1])
            rating_valid.append(data[3])

        # define logs and callbacks
        logdir = os.path.join("logs", datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
        tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
        early_stopping_callback = tf.keras.callbacks.EarlyStopping(patience=6)

        self.neuMF_model.fit(
            x=[np.array(user_train), np.array(item_train)],  # input
            y = np.array(rating_train).astype(float),  # label rating
            validation_data=([np.array(user_valid), np.array(item_valid)], np.array(rating_valid).astype(float)),
            epochs=N_EPOCHS,
            callbacks=[tensorboard_callback, early_stopping_callback],
            verbose=1,
        )
        self.neuMF_model.save("my_neuMF_h5_model.h5")

    def test(self, test):
        user_test, item_test, rating_test = [], [], []
        for data in test:
            user_test.append(data[0])
            item_test.append(data[1])
            rating_test.append(data[3])
        self.neuMF_model.evaluate([np.array(user_test), np.array(item_test)], np.array(rating_test))