import sympy as sp
import numpy as np
import itertools
import pandas as pd
import math
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from sympy.core.function import Function

def round_down(n, decimals=0):
    multiplier = 10 ** decimals
    return math.floor(n * multiplier) / multiplier

def GPSPathFinder(initial_location, final_location, obstacles_location_1, obstacles_location_2):
    steps =[0.0, 0.0]
    steps[0] = round_down(((final_location[0] - initial_location[0])/100), 10)
    steps[1] = round_down(((final_location[1] - initial_location[1])/100), 10)

    a1 = [0.0, 0.0]
    a1[0] = round_down(((obstacles_location_1[0] - initial_location[0]) / steps[0]), 10)
    a1[1] = round_down(((obstacles_location_1[1] - initial_location[1]) / steps[1]), 10)
    a2 = [0.0, 0.0]
    a2[0] = round_down(((obstacles_location_2[0] - initial_location[0]) / steps[0]), 10)
    a2[1] = round_down(((obstacles_location_2[1] - initial_location[1]) / steps[1]), 10)

    initial_loc = [0.0 , 0.0]
    cur_loc = initial_loc

    final_loc = [100.0, 100.0]
    mu = [a1, a2]
    sigma = [[50.0, 0.0], [0.0, 50.0]]
    u, v = sp.symbols('u v')
    w = (np.power(final_loc[0]-u, 2) + np.power(final_loc[1]-v,2))/20000 + \
        1e4 * (1/(sp.det(sp.Matrix(sigma))*2*np.pi) )  *  sp.exp(-(1/2) * np.transpose([(u-mu[0][0]),(v-mu[0][1])]).dot( np.linalg.pinv(sigma).dot([(u-mu[0][0]),(v-mu[0][1])]))) + \
        1e4 * (1/(sp.det(sp.Matrix(sigma))*2*np.pi) )  *  sp.exp(-(1/2) * np.transpose([(u-mu[1][0]),(v-mu[1][1])]).dot( np.linalg.pinv(sigma).dot([(u-mu[1][0]),(v-mu[1][1])])))

    dx = sp.diff(w, u)
    dy = sp.diff(w, v)
    dz = sp.lambdify([u,v],w,'numpy')

    x = list(np.arange(0.0, 104.0, 4.0))
    y = list(np.arange(0.0, 104.0, 4.0))
    x, y = np.meshgrid(x, y)
    z = dz(x,y)

    fig1 = plt.figure()
    ax = fig1.add_subplot(projection='3d')
    ax.plot_wireframe(x, y, z,  rstride=1, cstride=1, alpha = 0.5)
    ax.scatter(initial_loc[0],initial_loc[1], dz(initial_loc[0], initial_loc[1]),c = 'b',marker = '*',alpha = 0.8)

    ax.text(initial_loc[0],initial_loc[1], dz(initial_loc[0], initial_loc[1]), " Source", color='red')
    ax.scatter(final_loc[0],final_loc[1], dz(final_loc[0], final_loc[1]),c = 'r',marker = '*',alpha = 0.8)
    ax.text(final_loc[0],final_loc[1], dz(final_loc[0], final_loc[1]), " Goal", color='blue')

    p = []
    while not(cur_loc == final_loc) :
        if (cur_loc[0] > final_loc[0] or cur_loc[1] > final_loc[1]) :
            break
        dX = round_down(dx.evalf(subs = {u : cur_loc[0], v : cur_loc[1]}), 10)
        dY = round_down(dy.evalf(subs = {u : cur_loc[0], v : cur_loc[1]}), 10)
        d = sp.sqrt(dX**2 + dY**2)
        alpha = round_down(1/d, 10)

        cur_loc = list(cur_loc - (alpha * np.array([dX, dY],dtype ='float')))
        cur_loc = [round_down(inx, 10) for inx in cur_loc]
        ax.scatter(cur_loc[0],cur_loc[1],float(w.evalf(subs = {u : cur_loc[0], v : cur_loc[1]})),c = 'g',marker = '*',alpha = 0.8)
        p.append(cur_loc)

    for i in p:
        print(i[0])
        i[0] = (i[0] * steps[0]) + initial_location[0]
        i[1] = (i[1] * steps[1]) + initial_location[1]
    plt.show()
    return p

initial_location = [32.865816, -117.210019]
final_location = [32.865695, -117.210167]
obstacles_location_1 = [32.865797, -117.210067]
obstacles_location_2 = [32.865731, -117.210106]
path = GPSPathFinder(initial_location, final_location, obstacles_location_1, obstacles_location_2)
path.append(obstacles_location_1)
path.append(obstacles_location_2)
df = pd.DataFrame(path)
df.columns = ['Latitude', 'Longitude']
df.to_csv (r'C:\Users\Omid\Desktop\export_dataframe.csv', index = False, header=True)
#go to GoogleMyMaps and import the .csv file
print(df)


'''
뱀의 색깔과 관련하여, 노란색 뱀의 몸통 색깔은 비교적 잘보이는 하늘색으로 표현했습니다.
또한 제목은 저의 학번과 SNAKE GAME이라는 것을 알 수 있도록 작성하였습니다.
'''
import pygame
import random

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
LIGHTRED = (255, 178, 102)
YELLOW = (255, 255, 0)
LIGHTYELLOW = (153, 255, 255)
GREEN = (0, 255, 0)

class Player:
    dx = 0
    dy = 0
    player1_lst = []
    player2_lst = []
    change1 = ''
    direction1 = ''
    change2 = ''
    direction2 = ''
    speed1 = 1
    speed2 = 1

    def __init__(self, x, y, game):
        self.game = game
        self.active = True
        self.x = x
        self.y = y

    def handle_event1(self, event):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RSHIFT]:
            self.speed1 = 2
        else:
            self.speed1 = 1

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                self.change1 = 'left'
            elif event.key == pygame.K_RIGHT:
                self.change1 = 'right'
            elif event.key == pygame.K_UP:
                self.change1 = 'up'
            elif event.key == pygame.K_DOWN:
                self.change1 = 'down'

        if self.change1 == 'left' and self.direction1 != 'right':
            self.direction1 = 'left'
            self.dx = -self.speed1
            self.dy = 0
        elif self.change1 == 'right' and self.direction1 != 'left':
            self.direction1 = 'right'
            self.dx = self.speed1
            self.dy = 0
        elif self.change1 == 'up' and self.direction1 != 'down':
            self.direction1 = 'up'
            self.dx = 0
            self.dy = -self.speed1
        elif self.change1 == 'down' and self.direction1 != 'up':
            self.direction1 = 'down'
            self.dx = 0
            self.dy = self.speed1

    def handle_event2(self, event):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LSHIFT]:
            self.speed2 = 2
        else:
            self.speed2 = 1

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                self.change2 = 'left'
            elif event.key == pygame.K_d:
                self.change2 = 'right'
            elif event.key == pygame.K_w:
                self.change2 = 'up'
            elif event.key == pygame.K_s:
                self.change2 = 'down'

        if self.change2 == 'left' and self.direction2 != 'right':
            self.direction2 = 'left'
            self.dx = -self.speed2
            self.dy = 0
        elif self.change2 == 'right' and self.direction2 != 'left':
            self.direction2 = 'right'
            self.dx = self.speed2
            self.dy = 0
        elif self.change2 == 'up' and self.direction2 != 'down':
            self.direction2 = 'up'
            self.dx = 0
            self.dy = -self.speed2
        elif self.change2 == 'down' and self.direction2 != 'up':
            self.direction2 = 'down'
            self.dx = 0
            self.dy = self.speed2

    def handle_tick(self):
        self.x += self.dx
        self.y += self.dy

    def draw1(self):
        block_size = self.game.block_size
        pygame.draw.rect(self.game.display, YELLOW, [self.player1_lst[-1][0] * block_size, self.player1_lst[-1][1] * block_size, block_size, block_size])
        k = 1
        length1 = 1
        previous1 = self.player1_lst[-1]
        while True:
            index1 = len(self.player1_lst)-2-k
            if length1 != len(self.player1_lst)//2:
                if self.player1_lst[index1] != previous1:
                    pygame.draw.rect(self.game.display, LIGHTYELLOW, [self.player1_lst[index1][0] * block_size, self.player1_lst[index1][1] * block_size, block_size, block_size])
                    length1 += 1
                    previous1 = self.player1_lst[index1]
                k += 1
            else:
                break

    def draw2(self):
        block_size = self.game.block_size
        pygame.draw.rect(self.game.display, RED, [self.player2_lst[-1][0] * block_size, self.player2_lst[-1][1] * block_size, block_size, block_size])
        w = 1
        length2 = 1
        previous2 = self.player2_lst[-1]
        while True:
            index2 = len(self.player2_lst)-2-w
            if length2 != len(self.player2_lst)//2:
                if self.player2_lst[index2] != previous2:
                    pygame.draw.rect(self.game.display, LIGHTRED, [self.player2_lst[index2][0] * block_size, self.player2_lst[index2][1] * block_size, block_size, block_size])
                    length2 += 1
                    previous2 = self.player2_lst[index2]
                w += 1
            else:
                break

class Food:
    def __init__ (self, game):
        x = random.randint(0, game.n_cols - 1)
        y = random.randint(0, game.n_rows - 1)
        self.game = game
        self.active = True
        self.x = x
        self.y = y

    def draw(self):
        block_size = self.game.block_size
        pygame.draw.rect(self.game.display, GREEN, [self.x * block_size, self.y * block_size, block_size, block_size])

class Game:
    block_size = 10
    def __init__(self, n_rows, n_cols):
        pygame.init()
        pygame.display.set_caption("DCCP Snake Game made by 2020-19845 RIM SEJIN")
        self.display = pygame.display.set_mode((n_cols * self.block_size, n_rows * self.block_size))
        self.n_rows = n_rows
        self.n_cols = n_cols
        self.clock = pygame.time.Clock()
        self.game_over = False

    def play(self, n_foods = 20):
        player1 = Player(self.n_cols*3//4, self.n_rows//2, self)
        player2 = Player(self.n_cols//4, self.n_rows//2, self)
        foods = [Food(self) for _ in range(n_foods)]
        while not self.game_over:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.game_over = True
                    break
                player1.handle_event1(event)
                player2.handle_event2(event)

            #게임이 끝나는 조건1: 두 마리의 뱀이 영역을 벗어난 경우
            if player1.x < 0 or player1.x >= self.n_cols or player1.y < 0 or player1.y >= self.n_rows:
                self.game_over = True
            if player2.x < 0 or player2.x >= self.n_cols or player2.y < 0 or player2.y >= self.n_rows:
                self.game_over = True

            #각각의 뱀에 대한 결과를 각각 적용한다.
            player1.handle_tick()
            player2.handle_tick()

            #배경화면 설정
            self.display.fill(BLACK)

            #길이가 0이면, 다음을 수행한다.
            if len(player1.player1_lst) == 0:
                player1.player1_lst.append([player1.x, player1.y])
                player1.player1_lst.append([player1.x, player1.y])
            player1_length = len(player1.player1_lst)

            if len(player2.player2_lst) == 0:
                player2.player2_lst.append([player2.x, player2.y])
                player2.player2_lst.append([player2.x, player2.y])
            player2_length = len(player2.player2_lst)

            #food를 check한다.===========================player1
            GROW1 = False
            for food in foods:
                if food.active:
                    food.draw()
                if [food.x, food.y] in player1.player1_lst:
                    GROW1 = True
                    EatenFood_index = foods.index(food)
                    foods[EatenFood_index] = Food(self)
            if GROW1:
                player1_length += 2

            #food를 check한다.===========================player2
            GROW2 = False
            for food in foods:
                if food.active:
                    food.draw()
                if [food.x, food.y] in player2.player2_lst:
                    GROW2 = True
                    EatenFood_index = foods.index(food)
                    foods[EatenFood_index] = Food(self)
            if GROW2:
                player2_length += 2

            #player1 정보 update
            player1.player1_lst.append([player1.x, player1.y])
            player1.player1_lst.append([player1.x, player1.y])
            if len(player1.player1_lst) > player1_length:
                del player1.player1_lst[0]
                del player1.player1_lst[0]

            if player1.speed1 == 2:
                for i_idx in range(player1_length-3, 0, -1):
                    if i_idx % 2 == 1:
                        first1 = (player1.player1_lst[i_idx-1][0]+player1.player1_lst[i_idx+1][0])//2
                        second1 = (player1.player1_lst[i_idx-1][1]+player1.player1_lst[i_idx+1][1])//2
                        player1.player1_lst[i_idx][0] = first1
                        player1.player1_lst[i_idx][1] = second1

            #player2 정보 update
            player2.player2_lst.append([player2.x, player2.y])
            player2.player2_lst.append([player2.x, player2.y])
            if len(player2.player2_lst) > player2_length:
                del player2.player2_lst[0]
                del player2.player2_lst[0]

            if player2.speed2 == 2:
                for j_idx in range(player2_length-3, 0, -1):
                    if j_idx % 2 == 1:
                        first2 = (player2.player2_lst[j_idx-1][0]+player2.player2_lst[j_idx+1][0])//2
                        second2 = (player2.player2_lst[j_idx-1][1]+player2.player2_lst[j_idx+1][1])//2
                        player2.player2_lst[j_idx][0] = first2
                        player2.player2_lst[j_idx][1] = second2

            #게임이 끝날 조건2: 뱀의 머리가 몸통이랑 만날 경우
            sub1 = []
            sub2 = []
            if len(player1.player1_lst) != 2 or len(player1.player1_lst) != 0:
                k = 1
                length1 = 1
                previous1 = player1.player1_lst[-1]
                sub1.append(previous1)
                while True:
                    index1 = len(player1.player1_lst)-2-k
                    if length1 != len(player1.player1_lst)//2:
                        if player1.player1_lst[index1] != previous1:
                            sub1.append(player1.player1_lst[index1])
                            length1 += 1
                            previous1 = player1.player1_lst[index1]
                        k += 1
                    else:
                        break
                if sub1[-1] in sub1[:-2]:
                    self.game_over = True

            if len(player2.player2_lst) != 2 or len(player2.player2_lst) != 0:
                k = 1
                length2 = 1
                previous2 = player2.player2_lst[-1]
                sub2.append(previous2)
                while True:
                    index2 = len(player2.player2_lst)-2-k
                    if length2 != len(player2.player2_lst)//2:
                        if player2.player2_lst[index2] != previous2:
                            sub2.append(player2.player2_lst[index2])
                            length2 += 1
                            previous2 = player2.player2_lst[index2]
                        k += 1
                    else:
                        break
                if sub2[-1] in sub2[:-2]:
                    self.game_over = True

            #위의 과정을 다 수행한 뒤 각각의 뱀을 그려준다.
            player1.draw1()
            player2.draw2()

            ##게임이 끝날 조건3: 두 뱀이 서로 만날 경우
            for p in player1.player1_lst:
                if p in player2.player2_lst:
                    self.game_over = True

            pygame.display.update()
            self.clock.tick(10)

if __name__ == "__main__":
    Game(n_rows=60, n_cols=80).play(n_foods=20)


from __future__ import annotations

from argparse import ArgumentParser
from json import dumps as json_dumps, loads as json_loads
import logging
from pathlib import Path
from typing import Any, Dict, List, Optional
import sys

from dns.resolver import Resolver

NAMESERVERS = ["1.1.1.1"]

def setup_logger():
    """Setup the logger."""
    logger = logging.getLogger("Fetch DNS info")
    logger.setLevel(logging.INFO)

    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)

    formatter = logging.Formatter("%(asctime)s:%(name)s:%(levelname)s:%(message)s")

    handler.setFormatter(formatter)
    logger.addHandler(handler)

    return logger

LOGGER = setup_logger()

class HarInfo:
    def __init__(self, website: str, hosts: List[str]) -> None:
        self.website = website
        self.hosts: Dict[str, List[str]] = {host: [] for host in hosts}

    @classmethod
    def parse_har(cls, har_file: Path) -> Optional[HarInfo]:
        content = json_loads(har_file.read_text())
        if not content:
            return None

        website = content[0]

        if website is None:
            return None

        links: List[Dict[str, Any]] = content[2]

        hosts: List[str] = [link["host"] for link in links]

        return cls(website, hosts)

    def fetch_addrinfo(self, resolver: Resolver) -> None:
        for host in self.hosts.keys():
            try:
                ips = [rdata.address for rdata in resolver.resolve(host)]
                self.hosts[host] = ips
                LOGGER.info("Fetched DNS info for %s", host)
            except:
                LOGGER.warning("Failed to retrieve info for %s", host)

def retrieve_all_addrinfo(dataset_dir: Path, output_file: Path) -> None:
    har_files = dataset_dir.glob("*.har")

    hars: List[HarInfo] = list(
        filter(lambda x: x is not None,
        (HarInfo.parse_har(har_file) for har_file in har_files)) # type: ignore
    )

    resolver = Resolver()
    resolver.nameservers = NAMESERVERS

    for har in hars:
        har.fetch_addrinfo(resolver)

    json_struct = {har.website: har.hosts for har in hars}
    output_file.write_text(json_dumps(json_struct))

def main(program: str, args: List[str]):
    parser = ArgumentParser(program)

    parser.add_argument(
        "dataset",
        type=Path
    )

    parser.add_argument(
        "output",
        type=Path
    )

    namespace = parser.parse_args(args)

    dataset: Path = namespace.dataset
    if not dataset.is_dir():
        raise Exception(f"{dataset} does not exists!")

    output: Path = namespace.output
    if output.exists():
        raise Exception(f"{output} already exists!")

    retrieve_all_addrinfo(dataset, output)

if __name__ == "__main__":
    main(sys.argv[0], sys.argv[1:])


import socket
#import sys
import hashlib

#konstansok
TCP_IP = 'localhost'
TCP_PORT = 10000 #ez egy arbitary random port
BUFFER_SIZE = 1024
reply = b'Hello kliens'     #b = reply.encode()
        #b: byte-okként legyen eltárolva

#socket osztálynak az inicializátora
    #AD_INET: IPV_4 használata
    #SOCK_STREAM: TCP használata
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

#bind-oljuk a megadott ip-címre és portra, ezek leszünk mi
    #tupleként adjuk át
sock.bind((TCP_IP, TCP_PORT))
#elkezdjük figyelni a forgalmat
    #paraméter: hány klienst leszek hajlandó kiszolgálni
sock.listen(1)

#ha valaki csatlakozik, visszakapokkét objektumot (tupleként)
    #conn: socket connection object
    #addr: tuple
conn, addr = sock.accept()
print('Valaki csatlakozott:', addr)

while True:
    #fogadok a klienstől ennyi byteot
    data = conn.recv(BUFFER_SIZE)
    if not data: #ha üres (eof karaktert kaptunk, ami megegyezésre kapcsolat bontást jelent)
	    break

    print("Üzenet:", data.decode()) #bytestring-et kapunk, tehát ezt visszakapjuk
    conn.send(reply)
conn.close()
#sock.close()


import re

#classe CPF

class Cpf():
    def __init__(self):
        pass

    @classmethod
    def validar_digito(self, stringTeste, stringDigito):
        soma = 0
        i = len(stringTeste) + 1
        for digito in stringTeste:
            soma += int(digito) * i
            i -= 1
        if (soma * 10) % 11 == int(stringDigito):
            return True
        else:
            return False
    @classmethod
    def validar_cpf(self, cpf):
        validar_1 = False
        validar_2 = False

        # remover . e - do cpf
        if not cpf.isdigit():
            cpf = re.sub(r'[. -]', '', cpf)

        # verifica quantidade de digito
        if len(cpf) != 11:
            raise ValueError

        parte1 = cpf[:9]
        parte2 = cpf[:10]

        # validacao da parte 1
        validar_1 = self.validar_digito(parte1, cpf[9])

        # validacao da parte 2
        validar_2 = self.validar_digito(parte2, cpf[10])

        if validar_1 and validar_2:
            return cpf
        else:
            raise ValueError


import os
import config
import tkinter as tk
from tkinter import ttk
from tkinter.ttk import Notebook
import docker.db as db
import docker

class Timer(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title(config.title)
        self.geometry(config.geometry)

        self.notebook = Notebook(self)
        running_tab = RunTag(self.notebook)
        images_tab = ImagesTab(self.notebook)

        self.notebook.add(running_tab, text="运行中的容器")
        self.notebook.add(images_tab, text="镜像管理")
        self.notebook.pack(fill=tk.BOTH, expand=1)

class RunTag(tk.Frame):
    def __init__(self, master=None, cnf={}, **kw):
        super().__init__()

        rigth_frame = tk.LabelFrame(self)
        rigth_frame.pack(side=tk.RIGHT, expand=1, fill=tk.X, anchor=tk.N)

        content = tk.LabelFrame(self, background="cyan")
        content.pack(side=tk.RIGHT, expand=0, fill=tk.X)

        docker_ps = docker.container.running()

        tree = ttk.Treeview(content, columns=("NAMES", "IMAGE", "PORTS"), height=18, show="headings")
        tree.heading("NAMES", text=docker.container.titleKeyToName("NAMES"), anchor=tk.W)
        tree.column("NAMES", anchor=tk.W, width=100)
        tree.heading("IMAGE", text=docker.container.titleKeyToName("IMAGE"), anchor=tk.W)
        tree.column("IMAGE", anchor=tk.W, width=180)
        tree.heading("PORTS", text=docker.container.titleKeyToName("PORTS"), anchor=tk.W)
        tree.column("PORTS", anchor=tk.W, width=250)

        for values in docker_ps:
            value = (values["NAMES"], values["IMAGE"], values["PORTS"])
            tree.insert("", tk.END, values=value)
        tree.pack()

        translate_button = tk.Button(rigth_frame, text="开始")
        translate_button.pack(side=tk.TOP, fill=tk.BOTH)
        translate_button = tk.Button(rigth_frame, text="停止")
        translate_button.pack(side=tk.TOP, fill=tk.X)
        translate_button = tk.Button(rigth_frame, text="重启")
        translate_button.pack(side=tk.TOP, fill=tk.X)
        translate_button = tk.Button(rigth_frame, text="删除")
        translate_button.pack(side=tk.BOTTOM, fill=tk.X)

class ImagesTab(tk.Frame):
    def __init__(self, master=None, cnf={}, **kw):
        super().__init__()
        self.italian_copy_button = tk.Button(self, text="Copy to Clipboard", command=self.test())
        self.italian_copy_button.pack(side=tk.BOTTOM, fill=tk.X)

        self.italian_translation = tk.StringVar(self)
        self.italian_translation.set("")

        self.italian_label = tk.Label(self, textvar=self.italian_translation, bg="lightgrey", fg="black")
        self.italian_label.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

    def test(self):
        pass

if __name__ == "__main__":
    timer = Timer()

    if not os.path.isfile("docker.db"):
        db.create()

    timer.mainloop()


from collections import Counter

def solution(progresses, speeds):

    day = [0]*len(progresses)
    for i in range(len(progresses)):
        div, mod = divmod((100-progresses[i]), speeds[i])
        if mod == 0 : day[i] = div
        else : day[i] = div+1

    for i in range(len(day)-1):
        if day[i+1] < day[i]:
            day[i+1] = day[i]

    return list(Counter(day).values())


# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/
# contributed by Joseph LaFata

from sys import argv

try:
    N = int(argv[1])
except:
    N = 100

i = k = ns = 0
k1 = 1
n,a,d,t,u = (1,0,1,0,0)
while(1):
    k += 1
    t = n<<1
    n *= k
    a += t
    k1 += 2
    a *= k1
    d *= k1
    if a >= n:
        t,u = divmod(n*3 +a,d)
        u += n
        if d > u:
            ns = ns*10 + t
            i += 1
            if i % 10 == 0:
                print ('%010d\t:%d' % (ns, i))
                ns = 0
            if i >= N:
                break
            a -= d*t
            a *= 10
            n *= 10


#!/usr/bin/env python3
import getopt
import ssl
import uuid
import sys
import paho.mqtt.client as mqtt
import Adafruit_DHT
import logging
from logging.handlers import RotatingFileHandler

sensor = Adafruit_DHT.DHT22

# create logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logFile = "./logs/temperature.log"

# comes from outside as arguments
thingName = ""
mqttTopic_pub = ""
sensorPin = "21"
mqttEndpoint = ""  # something like A1B71MLXKNXXXX.iot.us-east-1.amazonaws.com

mqttCert_Protocol = ssl.PROTOCOL_TLSv1_2
mqttCert_ca = "./cert/VeriSign-Class-3-Public-Primary-Certification-Authority-G5.pem"
mqttPort = 8883
mqttClientId = "consumer-" + str(uuid.uuid4())
mqttClient = mqtt.Client(client_id=mqttClientId, clean_session=True)

# called while client tries to establish connection with the server
def on_connect(mqttc, obj, flags, rc):
    if rc == 0:
        global mqttClientConnCount
        logger.info("Client " + mqttClientId + " conntected : " + str(rc) + " | Connection status: successful.")
        # initial publication of temperature and humidty
        publish_data()

def on_disconnect(client, userdata, rc):
    logger.info("Client connection closed.")

def teardown():
    mqttClient.disconnect()
    mqttClient.loop_stop()
    sys.exit()

def on_publish(mosq, obj, mid):
    publish_data()

def on_log(pahoClient, obj, level, string):
    logger.debug(string)

def addFileLogger():
    global logger
    handler = RotatingFileHandler(logFile, maxBytes=1024*1024*10,backupCount=3)
    handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger.addHandler(handler)

def addConsoleLogger():
    global logger
    handler = logging.StreamHandler(sys.stdout)
    handler.setFormatter(logging.Formatter('%(message)s'))
    logger.addHandler(handler)

def publish_data():
    humidity, temperature = Adafruit_DHT.read_retry(sensor, int(sensorPin))
    if humidity is not None and temperature is not None:
        payload = '{{"state":{{"reported":{{"humidity":{0:0.1f},"temperature":{1:0.1f}}}}}}}' \
            .format(humidity,celsiusToFahrenheit(temperature))
        logger.info("Publish {0} to {1}".format(payload, mqttTopic_pub))
        mqttClient.publish(mqttTopic_pub, payload, 0, False)

def celsiusToFahrenheit(temperature):
    return (temperature * (9/5)) + 32

def connect_mqtt():
    mqttCert = "./cert/" + thingName + "/certificate.pem.crt"
    mqttCert_priv = "./cert/" + thingName + "/private.pem.key"
    # subsribe callback methods to mqtt-events
    mqttClient.on_connect = on_connect
    mqttClient.on_publish = on_publish
    mqttClient.on_disconnect = on_disconnect
    mqttClient.on_log = on_log

    # Configure network encryption and authentication options. Enables SSL/TLS support.
    # adding client-side certificates and enabling tlsv1.2 support as required by aws-iot service
    mqttClient.tls_set(mqttCert_ca, certfile=mqttCert, keyfile=mqttCert_priv, tls_version=mqttCert_Protocol, ciphers=None)

    logger.info("Start connecting to " + mqttEndpoint + ":" + str(mqttPort) + " ...")

    try:
        # connecting to aws-account-specific iot-endpoint
        mqttClient.connect(mqttEndpoint, port=mqttPort)
        mqttClient.loop_forever()
    except (KeyboardInterrupt, SystemExit):
        teardown()

def main(argv):
    opts, args = getopt.getopt(argv, "vt:p:e:", ["thing=","pin=","endpoint=","verbose"])
    global thingName
    global mqttTopic_pub
    global sensorPin
    global mqttEndpoint

    addFileLogger()

    for opt, arg in opts:
        if opt in ('-t', '--thing'):
            thingName = arg
            mqttTopic_pub = "$aws/things/" + thingName + "/shadow/update"
        elif opt in ('-p', '--pin'):
            sensorPin = arg
        elif opt in ('-e', '--endpoint'):
            mqttEndpoint = arg
        elif opt in ('-v', '--verbose'):
            addConsoleLogger()

    if not thingName:
        logger.error("No thing set. Provide a thing registered in AWS IoT to report air condition to with -t or --thing argument.")
    elif not sensorPin:
        logger.error("No GPIO pin set. Provide a GPIO pin which is connect to DHT22 temperature sensor with -p or --pin argument.")
    elif not mqttEndpoint:
        logger.error("No MQTT endpoint set. Provide an endpoint address to AWS IoT with -e or --endpoint argument. And endpoint is expected to look like A1B71MLXKNXXXX.iot.us-east-1.amazonaws.com")
    else:
        connect_mqtt()

if __name__ == "__main__":
    main(sys.argv[1:])


import re
from abc import ABC, abstractmethod
from enum import Enum
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Union

from gqlalchemy.exceptions import (
    GQLAlchemyExtraKeywordArguments,
    GQLAlchemyInstantiationError,
    GQLAlchemyLiteralAndExpressionMissing,
    GQLAlchemyMissingOrder,
    GQLAlchemyOperatorTypeError,
    GQLAlchemyOrderByTypeError,
    GQLAlchemyResultQueryTypeError,
    GQLAlchemyTooLargeTupleInResultQuery,
)
from gqlalchemy.graph_algorithms.integrated_algorithms import IntegratedAlgorithm
from gqlalchemy.vendors.memgraph import Memgraph
from gqlalchemy.models import Node, Relationship
from gqlalchemy.utilities import to_cypher_labels, to_cypher_properties, to_cypher_value, to_cypher_qm_arguments
from gqlalchemy.vendors.database_client import DatabaseClient

class DeclarativeBaseTypes:
    CALL = "CALL"
    CREATE = "CREATE"
    DELETE = "DELETE"
    FOREACH = "FOREACH"
    LIMIT = "LIMIT"
    LOAD_CSV = "LOAD_CSV"
    MATCH = "MATCH"
    MERGE = "MERGE"
    NODE = "NODE"
    ORDER_BY = "ORDER BY"
    RELATIONSHIP = "RELATIONSHIP"
    REMOVE = "REMOVE"
    RETURN = "RETURN"
    SET = "SET"
    SKIP = "SKIP"
    UNION = "UNION"
    UNWIND = "UNWIND"
    WHERE = "WHERE"
    WITH = "WITH"
    YIELD = "YIELD"

class MatchConstants:
    DIRECTED = "directed"
    LABELS_STR = "labels_str"
    OPTIONAL = "optional"
    PROPERTIES_STR = "properties_str"
    QUERY = "query"
    TYPE = "type"
    VARIABLE = "variable"

class Result(Enum):
    RETURN = 1
    YIELD = 2
    WITH = 3

class Where(Enum):
    WHERE = 1
    AND = 2
    OR = 3
    XOR = 4
    NOT = 5

class Operator(Enum):
    ASSIGNMENT = "="
    EQUAL = "="
    GEQ_THAN = ">="
    GREATER_THAN = ">"
    INEQUAL = "<>"
    LABEL_FILTER = ":"
    LESS_THAN = "<"
    LEQ_THAN = "<="
    NOT_EQUAL = "!="
    INCREMENT = "+="

class Order(Enum):
    ASC = 1
    ASCENDING = 2
    DESC = 3
    DESCENDING = 4

class NoVariablesMatchedException(Exception):
    def __init__(self):
        message = "No variables have been matched in the query"
        super().__init__(message)

class InvalidMatchChainException(Exception):
    def __init__(self):
        message = "Invalid match query when linking!"
        super().__init__(message)

class PartialQuery(ABC):
    def __init__(self, type: str):
        self.type = type

    @abstractmethod
    def construct_query(self) -> str:
        pass

class MatchPartialQuery(PartialQuery):
    def __init__(self, optional: bool):
        super().__init__(DeclarativeBaseTypes.MATCH)

        self.optional = optional

    def construct_query(self) -> str:
        if self.optional:
            return " OPTIONAL MATCH "

        return " MATCH "

class MergePartialQuery(PartialQuery):
    def __init__(self):
        super().__init__(DeclarativeBaseTypes.MERGE)

    def construct_query(self) -> str:
        return " MERGE "

class CreatePartialQuery(PartialQuery):
    def __init__(self):
        super().__init__(DeclarativeBaseTypes.CREATE)

    def construct_query(self) -> str:
        return " CREATE "

class CallPartialQuery(PartialQuery):
    def __init__(self, procedure: str, arguments: Optional[Union[str, Tuple[Union[str, int, float]]]]):
        super().__init__(DeclarativeBaseTypes.CALL)

        self.procedure = procedure
        self.arguments = to_cypher_qm_arguments(arguments)

    def construct_query(self) -> str:
        return f" CALL {self.procedure}({self.arguments if self.arguments else ''}) "

class WhereConditionPartialQuery(PartialQuery):
    _LITERAL = "literal"
    _EXPRESSION = "expression"

    def __init__(self, item: str, operator: Operator, keyword: Where = Where.WHERE, is_negated: bool = False, **kwargs):
        super().__init__(type=keyword.name if not is_negated else f"{keyword.name} {Where.NOT.name}")
        self.query = self._build_where_query(item=item, operator=operator, **kwargs)

    def construct_query(self) -> str:
        """Constructs a where partial query."""
        return f" {self.type} {self.query} "

    def _build_where_query(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Builds parts of a WHERE Cypher query divided by the boolean operators."""
        literal = kwargs.get(WhereConditionPartialQuery._LITERAL)
        value = kwargs.get(WhereConditionPartialQuery._EXPRESSION)

        operator_str = operator.value if isinstance(operator, Operator) else operator

        if operator_str not in Operator._value2member_map_:
            raise GQLAlchemyOperatorTypeError(clause=self.type)

        if value is None:
            if literal is None:
                raise GQLAlchemyLiteralAndExpressionMissing(clause=self.type)

            value = to_cypher_value(literal)
        elif literal is not None:
            raise GQLAlchemyExtraKeywordArguments(clause=self.type)

        return ("" if operator_str == Operator.LABEL_FILTER.value else " ").join(
            [
                item,
                operator_str,
                value,
            ]
        )

class WhereNotConditionPartialQuery(WhereConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, keyword: Where = Where.WHERE, **kwargs):
        super().__init__(item=item, operator=operator, keyword=keyword, is_negated=True, **kwargs)

class AndWhereConditionPartialQuery(WhereConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.AND, **kwargs)

class AndNotWhereConditionPartialQuery(WhereNotConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.AND, **kwargs)

class OrWhereConditionPartialQuery(WhereConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.OR, **kwargs)

class OrNotWhereConditionPartialQuery(WhereNotConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.OR, **kwargs)

class XorWhereConditionPartialQuery(WhereConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.XOR, **kwargs)

class XorNotWhereConditionPartialQuery(WhereNotConditionPartialQuery):
    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(item=item, operator=operator, keyword=Where.XOR, **kwargs)

class NodePartialQuery(PartialQuery):
    def __init__(self, variable: Optional[str], labels: str, properties: str):
        super().__init__(DeclarativeBaseTypes.NODE)

        self._variable = "" if variable is None else variable
        self._labels = labels
        self._properties = properties

    @property
    def variable(self) -> str:
        return self._variable

    @property
    def labels(self) -> str:
        return self._labels

    @property
    def properties(self) -> str:
        return self._properties

    def construct_query(self) -> str:
        """Constructs a node partial query."""
        return f"({self.variable}{self.labels}{' ' + self.properties if self.properties else ''})"

class RelationshipPartialQuery(PartialQuery):
    def __init__(
        self,
        variable: Optional[str],
        relationship_type: str,
        algorithm: str,
        properties: str,
        directed: bool,
        from_: bool,
    ):
        super().__init__(DeclarativeBaseTypes.RELATIONSHIP)

        self.directed = directed
        self._variable = "" if variable is None else variable
        self._relationship_type = relationship_type
        self._algorithm = algorithm
        self._properties = properties
        self._from = from_

    @property
    def variable(self) -> str:
        return self._variable

    @property
    def relationship_type(self) -> str:
        return self._relationship_type

    @property
    def algorithm(self) -> str:
        return self._algorithm

    @property
    def properties(self) -> str:
        return self._properties

    def construct_query(self) -> str:
        """Constructs a relationship partial query."""
        relationship_query = f"{self.variable}{self.relationship_type}{self.algorithm}{self.properties}"

        if not self.directed:
            relationship_query = f"-[{relationship_query}]-"
            return relationship_query

        if self._from:
            relationship_query = f"<-[{relationship_query}]-"
        else:
            relationship_query = f"-[{relationship_query}]->"

        return relationship_query

class UnwindPartialQuery(PartialQuery):
    def __init__(self, list_expression: str, variable: str):
        super().__init__(DeclarativeBaseTypes.UNWIND)

        self.list_expression = list_expression
        self.variable = variable

    def construct_query(self) -> str:
        """Constructs an unwind partial query."""
        return f" UNWIND {self.list_expression} AS {self.variable} "

def dict_to_alias_statement(alias_dict: Dict[str, str]) -> str:
    """Creates a string expression of alias statements from a dictionary of
    expression, variable name dictionary.
    """
    return ", ".join(
        f"{key} AS {value}" if value != "" and key != value else f"{key}" for (key, value) in alias_dict.items()
    )

class _ResultPartialQuery(PartialQuery):
    def __init__(
        self,
        keyword: Result,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ):
        if type(self) is _ResultPartialQuery:
            raise GQLAlchemyInstantiationError(class_name=type(self).__name__)

        super().__init__(type=keyword.name)

        if results is None:
            self.query = None
        elif isinstance(results, str):
            self.query = results
        elif isinstance(results, dict):
            self.query = self._return_read_dict(results)
        elif isinstance(results, tuple):
            self.query = self._return_read_tuple(results)
        elif isinstance(results, (list, set)):
            self.query = self._return_read_iterable(results)
        else:
            raise GQLAlchemyResultQueryTypeError(clause=self.type)

    def construct_query(self) -> str:
        """Creates a RETURN/YIELD/WITH statement Cypher partial query."""
        if self.query is None:
            return f" {self.type} * "

        return f" {self.type} {self.query} "

    def _return_read_iterable(
        self, iterable: Union[List[Union[str, Tuple[str, str]]], Set[Union[str, Tuple[str, str]]]]
    ):
        return ", ".join(self._return_read_item(item=item) for item in iterable)

    def _return_read_item(self, item: Union[str, Tuple]) -> str:
        if isinstance(item, str):
            return item

        if isinstance(item, tuple):
            return f"{self._return_read_tuple(item)}"

        raise GQLAlchemyResultQueryTypeError(clause=self.type)

    def _return_read_tuple(self, tuple: Tuple[str, str]) -> str:
        if len(tuple) > 2:
            raise GQLAlchemyTooLargeTupleInResultQuery(clause=self.type)

        if not isinstance(tuple[0], str) or not isinstance(tuple[1], str):
            raise GQLAlchemyResultQueryTypeError(clause=self.type)

        if tuple[0] == tuple[1] or tuple[1] == "":
            return f"{tuple[0]}"

        return f"{tuple[0]} AS {tuple[1]}"

    def _return_read_dict(self, results: Dict[str, str]):
        return f"{dict_to_alias_statement(results)}"

class WithPartialQuery(_ResultPartialQuery):
    def __init__(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ):
        super().__init__(keyword=Result.WITH, results=results)

class UnionPartialQuery(PartialQuery):
    def __init__(self, include_duplicates: bool):
        super().__init__(DeclarativeBaseTypes.UNION)

        self.include_duplicates = include_duplicates

    def construct_query(self) -> str:
        """Creates a UNION statement Cypher partial query."""
        return f" UNION{f' ALL' if self.include_duplicates else ''} "

class DeletePartialQuery(PartialQuery):
    def __init__(self, variable_expressions: Union[str, List[str]], detach: bool):
        super().__init__(DeclarativeBaseTypes.DELETE)

        self._variable_expressions = variable_expressions
        self.detach = detach

    @property
    def variable_expressions(self) -> str:
        return self._variable_expressions

    def construct_query(self) -> str:
        """Creates a DELETE statement Cypher partial query."""
        return f" {'DETACH' if self.detach else ''} DELETE {', '.join(self.variable_expressions) if isinstance(self.variable_expressions, list) else self.variable_expressions} "

class RemovePartialQuery(PartialQuery):
    def __init__(self, items: Union[str, List[str]]):
        super().__init__(DeclarativeBaseTypes.REMOVE)

        self._items = items

    @property
    def items(self) -> str:
        return self._items

    def construct_query(self) -> str:
        """Creates a REMOVE statement Cypher partial query."""
        return f" REMOVE {', '.join(self.items) if isinstance(self.items, list) else self.items} "

class YieldPartialQuery(_ResultPartialQuery):
    def __init__(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ):
        super().__init__(keyword=Result.YIELD, results=results)

class ReturnPartialQuery(_ResultPartialQuery):
    def __init__(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ):
        super().__init__(keyword=Result.RETURN, results=results)

class OrderByPartialQuery(PartialQuery):
    def __init__(self, properties: Union[str, Tuple[str, Order], List[Union[str, Tuple[str, Order]]]]):
        super().__init__(DeclarativeBaseTypes.ORDER_BY)

        self.query = (
            self._order_by_read_list(properties)
            if isinstance(properties, list)
            else self._order_by_read_item(properties)
        )

    def construct_query(self) -> str:
        """Creates a ORDER BY statement Cypher partial query."""
        return f" {self.type} {self.query} "

    def _order_by_read_item(self, item: Union[str, Tuple[str, Order]]) -> str:
        if isinstance(item, str):
            return item
        elif isinstance(item, tuple):
            return f"{self._order_by_read_tuple(item)}"
        else:
            raise GQLAlchemyOrderByTypeError

    def _order_by_read_list(self, property: List[Union[str, Tuple[str, Order]]]):
        return ", ".join(self._order_by_read_item(item=item) for item in property)

    def _order_by_read_tuple(self, tuple: Tuple[str, Order]) -> str:
        if not isinstance(tuple[1], Order):
            raise GQLAlchemyMissingOrder

        return f"{tuple[0]} {tuple[1].name}"

class LimitPartialQuery(PartialQuery):
    def __init__(self, integer_expression: Union[str, int]):
        super().__init__(DeclarativeBaseTypes.LIMIT)

        self.integer_expression = integer_expression

    def construct_query(self) -> str:
        """Creates a LIMIT statement Cypher partial query."""
        return f" LIMIT {self.integer_expression} "

class SkipPartialQuery(PartialQuery):
    def __init__(self, integer_expression: Union[str, int]):
        super().__init__(DeclarativeBaseTypes.SKIP)

        self.integer_expression = integer_expression

    def construct_query(self) -> str:
        """Creates a SKIP statement Cypher partial query."""
        return f" SKIP {self.integer_expression} "

class AddStringPartialQuery(PartialQuery):
    def __init__(self, custom_cypher: str):
        super().__init__(DeclarativeBaseTypes.SKIP)

        self.custom_cypher = custom_cypher

    def construct_query(self) -> str:
        return f"{self.custom_cypher}"

class ForeachPartialQuery(PartialQuery):
    def __init__(self, variable: str, expression: str, update_clauses: str):
        super().__init__(DeclarativeBaseTypes.FOREACH)
        self._variable = variable
        self._expression = expression
        self._update_clauses = update_clauses

    @property
    def variable(self) -> str:
        return self._variable

    @property
    def expression(self) -> str:
        return self._expression

    @property
    def update_clauses(self) -> str:
        return self._update_clauses

    def construct_query(self) -> str:
        """Creates a FOREACH statement Cypher partial query."""
        return f" FOREACH ( {self.variable} IN {self.expression} | {self.update_clauses} ) "

class SetPartialQuery(PartialQuery):
    _LITERAL = "literal"
    _EXPRESSION = "expression"

    def __init__(self, item: str, operator: Operator, **kwargs):
        super().__init__(DeclarativeBaseTypes.SET)

        self.query = self._build_set_query(item=item, operator=operator, **kwargs)

    def construct_query(self) -> str:
        """Constructs a set partial query."""
        return f" {self.type} {self.query}"

    def _build_set_query(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Builds parts of a SET Cypher query divided by the boolean operators."""
        literal = kwargs.get(SetPartialQuery._LITERAL)
        value = kwargs.get(SetPartialQuery._EXPRESSION)

        operator_str = operator.value if isinstance(operator, Operator) else operator

        if operator_str not in Operator._value2member_map_:
            raise GQLAlchemyOperatorTypeError(clause=self.type)

        if value is None:
            if literal is None:
                raise GQLAlchemyLiteralAndExpressionMissing(clause=self.type)

            value = to_cypher_value(literal)
        elif literal is not None:
            raise GQLAlchemyExtraKeywordArguments(clause=self.type)

        return ("" if operator_str == Operator.LABEL_FILTER.value else " ").join(
            [
                item,
                operator_str,
                value,
            ]
        )

class DeclarativeBase(ABC):
    def __init__(self, connection: Optional[DatabaseClient] = None):
        self._query: List[PartialQuery] = []
        self._connection = connection if connection is not None else Memgraph()
        self._fetch_results: bool = False

    def match(self, optional: bool = False) -> "DeclarativeBase":
        """Obtain data from the database by matching it to a given pattern.

        Args:
            optional: A bool indicating if missing parts of the pattern will be
            filled with null values.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Get all nodes with a certain label:

            Python: `match().node(labels='Country', variable='c').return_(results='c').execute()`
            Cypher: `MATCH (c:Country) RETURN c;`

            Get a relationship of a certain type that connects two nodes with certain label:

            Python: `match().node(labels='Town', variable='t').to(relationship_type='BELONGS_TO', variable='b').node(labels='Country', variable='c').return_(results='b').execute()`
            Cypher: `MATCH (t:Town)-[b:BELONGS_TO]->(c:Country) RETURN b;`
        """
        self._query.append(MatchPartialQuery(optional))

        return self

    def merge(self) -> "DeclarativeBase":
        """Ensure that a pattern you are looking for exists in the database.
        This means that if the pattern is not found, it will be created. In a
        way, this clause is like a combination of MATCH and CREATE.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Merge node with properties:

            Python: `merge().node(variable='city').where(item='city.name', operator=Operator.EQUAL, literal='London').return_(results='city').execute()`
            Cypher: `MERGE (city) WHERE city.name = 'London' RETURN city;`
        """
        self._query.append(MergePartialQuery())

        return self

    def create(self) -> "DeclarativeBase":
        """Create nodes and relationships in a graph.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Create a single node:

            Python: `create().node(labels='Person', variable='p').return_(results='p').execute()`
            Cypher: `CREATE (p:Person) RETURN p;`
        """
        self._query.append(CreatePartialQuery())

        return self

    def call(
        self, procedure: str, arguments: Optional[Union[str, Tuple[Union[str, int, float]]]] = None
    ) -> "DeclarativeBase":
        """Call a query module procedure.

        Args:
            procedure: A string representing the name of the procedure in the
              format `query_module.procedure`.
            arguments: A string representing the arguments of the procedure in
              text format.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Call procedure with no arguments:

            Python: `call('pagerank.get').yield_().return_().execute()`
            Cypher: `CALL pagerank.get() YIELD * RETURN *;`

            Call procedure with arguments:

            Python: `call('json_util.load_from_url', "'https://some-url.com'").yield_('objects').return_(results='objects').execute()
            Cypher: `CALL json_util.load_from_url(https://some-url.com) YIELD objects RETURN objects;`
        """
        self._query.append(CallPartialQuery(procedure, arguments))

        return self

    def node(
        self,
        labels: Union[str, List[str], None] = "",
        variable: Optional[str] = None,
        node: Optional["Node"] = None,
        **kwargs,
    ) -> "DeclarativeBase":
        """Add a node pattern to the query.

        Args:
            labels: A string or list of strings representing the labels of the
              node.
            variable: A string representing the name of the variable for storing
              results of the node pattern.
            node: A `Node` object to construct the pattern from.
            **kwargs: Arguments representing the properties of the node.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Create a node and return it:

            Python: `create().node(labels='Person', variable='n', first_name='Kate').return_(results='n').execute()`
            Cypher: `CREATE (n:Person {first_name: 'Kate'}) RETURN n;`
        """
        if not self._is_linking_valid_with_query(DeclarativeBaseTypes.NODE):
            raise InvalidMatchChainException()

        if node is None:
            labels_str = to_cypher_labels(labels)
            properties_str = to_cypher_properties(kwargs)
        else:
            labels_str = to_cypher_labels(node._labels)
            properties_str = to_cypher_properties(node._properties)

        self._query.append(NodePartialQuery(variable, labels_str, properties_str))

        return self

    def to(
        self,
        relationship_type: Optional[str] = "",
        directed: Optional[bool] = True,
        variable: Optional[str] = None,
        relationship: Optional["Relationship"] = None,
        algorithm: Optional[IntegratedAlgorithm] = None,
        **kwargs,
    ) -> "DeclarativeBase":
        """Add a relationship pattern to the query.

        Args:
            relationship_type: A string representing the type of the relationship.
            directed: A bool indicating if the relationship is directed.
            variable: A string representing the name of the variable for storing
              results of the relationship pattern.
            relationship: A `Relationship` object to construct the pattern from.
            algorithm: algorithm object to use over graph data.
            **kwargs: Arguments representing the properties of the relationship.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Match and return a relationship:

            Python: `match().node(labels='Town', variable='t').to(relationship_type='BELONGS_TO', variable='b').node(labels='Country', variable='c').return_(results='b').execute()`
            Cypher: `MATCH (t:Town)-[b:BELONGS_TO]->(c:Country) RETURN b;`
        """
        if not self._is_linking_valid_with_query(DeclarativeBaseTypes.RELATIONSHIP):
            raise InvalidMatchChainException()

        if relationship is None:
            type_str = to_cypher_labels(relationship_type)
            properties_str = to_cypher_properties(kwargs)
        else:
            type_str = to_cypher_labels(relationship._type)
            properties_str = to_cypher_properties(relationship._properties)

        self._query.append(
            RelationshipPartialQuery(
                variable=variable,
                relationship_type=type_str,
                algorithm="" if algorithm is None else str(algorithm),
                properties=properties_str,
                directed=bool(directed),
                from_=False,
            )
        )

        return self

    def from_(
        self,
        relationship_type: Optional[str] = "",
        directed: Optional[bool] = True,
        variable: Optional[str] = None,
        relationship: Optional["Relationship"] = None,
        algorithm: Optional[IntegratedAlgorithm] = None,
        **kwargs,
    ) -> "Match":
        """Add a relationship pattern to the query.

        Args:
            relationship_type: A string representing the type of the relationship.
            directed: A bool indicating if the relationship is directed.
            variable: A string representing the name of the variable for storing
              results of the relationship pattern.
            relationship: A `Relationship` object to construct the pattern from.
            **kwargs: Arguments representing the properties of the relationship.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Match and return a relationship:

            Python: `match().node(labels='Country', variable='c').from_(relationship_type='BELONGS_TO', variable='b').node(labels='Town', variable='t').return_(results='b').execute()`
            Cypher: `MATCH (c:Country)<-[b:BELONGS_TO]-(t:Town) RETURN b;`
        """
        if not self._is_linking_valid_with_query(DeclarativeBaseTypes.RELATIONSHIP):
            raise InvalidMatchChainException()

        if relationship is None:
            type_str = to_cypher_labels(relationship_type)
            properties_str = to_cypher_properties(kwargs)
        else:
            type_str = to_cypher_labels(relationship._type)
            properties_str = to_cypher_properties(relationship._properties)

        self._query.append(
            RelationshipPartialQuery(
                variable=variable,
                relationship_type=type_str,
                algorithm="" if algorithm is None else str(algorithm),
                properties=properties_str,
                directed=bool(directed),
                from_=True,
            )
        )

        return self

    def where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates a WHERE statement Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Raises:
            GQLAlchemyLiteralAndExpressionMissingInWhere: Raises an error when neither literal nor expression keyword arguments were provided.
            GQLAlchemyExtraKeywordArgumentsInWhere: Raises an error when both literal and expression keyword arguments were provided.

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by the equality of `name` properties of two connected nodes.

            Python: `match().node(variable='n').to().node(variable='m').where(item='n.name', operator=Operator.EQUAL, expression='m.name').return_()`
            Cypher: `MATCH (n)-[]->(m) WHERE n.name = m.name RETURN *;`

            Filtering query results by the node label.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').return_()`
            Cypher: `MATCH (n) WHERE n:User RETURN *;`

            Filtering query results by the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n.age > 18 RETURN *;`
        """
        # WHERE item operator (literal | expression)
        # item: variable | property
        # expression: label | property
        self._query.append(WhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def where_not(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates a WHERE NOT statement Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Raises:
            GQLAlchemyLiteralAndExpressionMissingInWhere: Raises an error when neither literal nor expression keyword arguments were provided.
            GQLAlchemyExtraKeywordArgumentsInWhere: Raises an error when both literal and expression keyword arguments were provided.

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by the equality of `name` properties of two connected nodes.

            Python: `match().node(variable='n').to().node(variable='m').where_not(item='n.name', operator='=', expression='m.name').return_()`
            Cypher: `MATCH (n)-[]->(m) WHERE NOT n.name = m.name RETURN *;`
        """
        self._query.append(WhereNotConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def and_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an AND statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').and_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User AND n.age > 18 RETURN *;`
        """
        self._query.append(AndWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def and_not_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an AND NOT statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').and_not_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User AND NOT n.age > 18 RETURN *;`
        """
        self._query.append(AndNotWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def or_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an OR statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').or_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User OR n.age > 18 RETURN *;`
        """
        self._query.append(OrWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def or_not_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an OR NOT statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').or_not_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User OR NOT n.age > 18 RETURN *;`
        """
        self._query.append(OrNotWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def xor_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an XOR statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').xor_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User XOR n.age > 18 RETURN *;`
        """
        self._query.append(XorWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def xor_not_where(self, item: str, operator: Operator, **kwargs) -> "DeclarativeBase":
        """Creates an XOR NOT statement as a part of WHERE Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: A string representing the operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Filtering query results by node label or the comparison of node property and literal.

            Python: `match().node(variable='n').where(item='n', operator=Operator.LABEL_FILTER, expression='User').xor_not_where(item='n.age', operator=Operator.GREATER_THAN, literal=18).return_()`
            Cypher: `MATCH (n) WHERE n:User XOR NOT n.age > 18 RETURN *;`
        """
        self._query.append(XorNotWhereConditionPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def unwind(self, list_expression: str, variable: str) -> "DeclarativeBase":
        """Unwind a list of values as individual rows.

        Args:
            list_expression: A list of strings representing the list of values.
            variable: A string representing the variable name for unwinding results.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Python: `unwind(list_expression="[1, 2, 3, null]", variable="x").return_(results=["x", ("'val'", "y")]).execute()`
            Cypher: `UNWIND [1, 2, 3, null] AS x RETURN x, 'val' AS y;`
        """
        self._query.append(UnwindPartialQuery(list_expression, variable))

        return self

    def with_(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ) -> "DeclarativeBase":
        """Chain together parts of a query, piping the results from one to be
        used as starting points or criteria in the next.

        Args:
            results: A dictionary mapping variables in the first query with
            aliases in the second query.

        Raises:
            GQLAlchemyResultQueryTypeError: Raises an error when the provided argument is of wrong type.
            GQLAlchemyTooLargeTupleInResultQuery: Raises an error when the given tuple has length larger than 2.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Pipe the result from first part of the query for the further use:

            Python: `match().node(variable='n').with('n').execute()`
            Cypher: `MATCH (n) WITH n;
        """
        self._query.append(WithPartialQuery(results))

        return self

    def union(self, include_duplicates: Optional[bool] = True) -> "DeclarativeBase":
        """Combine the result of multiple queries.

        Args:
            include_duplicates: A bool indicating if duplicates should be
              included.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Combine queries and retain duplicates:

            Python: `match().node(variable="c", labels="Country").return_(results=("c.name", "columnName")).union().match().node(variable="p", labels="Person").return_(results=("p.name", "columnName")).execute()`
            Cypher: `MATCH (c:Country) RETURN c.name AS columnName UNION ALL MATCH (p:Person) RETURN p.name AS columnName;`

            Combine queries and remove duplicates:

            Python: `match().node(variable="c", labels="Country").return_(results=("c.name", "columnName")).union(include_duplicates=False).match().node(variable="p", labels="Person").return_(results=("p.name", "columnName")).execute()`
            Cypher: `MATCH (c:Country) RETURN c.name AS columnName UNION MATCH (p:Person) RETURN p.name AS columnName;`
        """
        self._query.append(UnionPartialQuery(include_duplicates))

        return self

    def delete(self, variable_expressions: Union[str, List[str]], detach: Optional[bool] = False) -> "DeclarativeBase":
        """Delete nodes and relationships from the database.

        Args:
            variable_expressions: A string or list of strings indicating which node(s)
              and/or relationship(s) should be removed.
            detach: A bool indicating if relationships should be deleted along
              with a node.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Delete a node:

            Python: `match().node(labels='Node1', variable='n1').delete(variable_expressions='n1').execute()`
            Cypher: `MATCH (n1:Node1) DELETE n1;`
        """
        self._query.append(DeletePartialQuery(variable_expressions, detach))

        return self

    def remove(self, items: Union[str, List[str]]) -> "DeclarativeBase":
        """Remove labels and properties from nodes and relationships.

        Args:
            items: A string or list of strings indicating which label(s) and/or properties
              should be removed.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Remove a property from a node:

            Python: `match().node(labels='Country', variable='n', name='United Kingdom').remove(items='n.name').return_(results='n').execute()`
            Cypher: `MATCH (n:Country {name: 'United Kingdom'}) REMOVE n.name RETURN n;`
        """
        self._query.append(RemovePartialQuery(items))

        return self

    def yield_(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ) -> "DeclarativeBase":
        """Yield data from the query.

        Args:
            results: A dictionary mapping items that are returned with alias names.

        Raises:
            GQLAlchemyResultQueryTypeError: Raises an error when the provided argument is of wrong type.
            GQLAlchemyTooLargeTupleInResultQuery: Raises an error when the given tuple has length larger than 2.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Yield all data from a query:

            Python: `call(procedure='pagerank.get').yield_().return_().execute()`
            Cypher: `CALL pagerank.get() YIELD * RETURN *;`

            Yield some data from a query:

            Python: `.call(procedure='pagerank.get').yield_(results=['node', 'rank']).return_(results=['node','rank']).execute()`
            Cypher: `CALL pagerank.get() YIELD node, rank RETURN node, rank;`
        """
        self._query.append(YieldPartialQuery(results))

        return self

    def return_(
        self,
        results: Optional[
            Union[
                str,
                Tuple[str, str],
                Dict[str, str],
                List[Union[str, Tuple[str, str]]],
                Set[Union[str, Tuple[str, str]]],
            ]
        ] = None,
    ) -> "DeclarativeBase":
        """Return data from the query.

        Args:
            results: An optional string, tuple or iterable of strings and tuples for alias names.

        Raises:
            GQLAlchemyResultQueryTypeError: Raises an error when the provided argument is of wrong type.
            GQLAlchemyTooLargeTupleInResultQuery: Raises an error when the given tuple has length larger than 2.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Return all variables from a query:

            Python: `match().node(labels='Person', variable='p').return_().execute()`
            Cypher: `MATCH (p:Person) RETURN *;`

            Return specific variables from a query:

            Python: `match().node(labels='Person', variable='p1').to().node(labels='Person', variable='p2').return_(results=[('p1','first'), 'p2']).execute()`
            Cypher: `MATCH (p1:Person)-[]->(p2:Person) RETURN p1 AS first, p2;`
        """
        self._query.append(ReturnPartialQuery(results=results))
        self._fetch_results = True

        return self

    def order_by(
        self, properties: Union[str, Tuple[str, Order], List[Union[str, Tuple[str, Order]]]]
    ) -> "DeclarativeBase":
        """Creates an ORDER BY statement Cypher partial query.

        Args:
            properties: Properties and order (DESC/DESCENDING/ASC/ASCENDING) by which the query results will be ordered.

        Raises:
            GQLAlchemyOrderByTypeError: Raises an error when the given ordering is of the wrong type.
            GQLAlchemyMissingOrder: Raises an error when the given property is neither string nor tuple.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Examples:
            Ordering query results by the property `n.name` in ascending order
            and by the property `n.last_name` in descending order:

            Python: `match().node(variable='n').return_().order_by(properties=['n.name', ('n.last_name', Order.DESC)]).execute()`
            Cypher: `MATCH (n) RETURN * ORDER BY n.name, n.last_name DESC;`
        """
        self._query.append(OrderByPartialQuery(properties=properties))

        return self

    def limit(self, integer_expression: Union[str, int]) -> "DeclarativeBase":
        """Limit the number of records when returning results.

        Args:
            integer_expression: An integer indicating how many records to limit
              the results to.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Limit the number of returned results:

            Python: `match().node(labels='Person', variable='p').return_().limit(integer_expression='10').execute()`
            Cypher: `MATCH (p:Person) RETURN * LIMIT 10;`
        """
        self._query.append(LimitPartialQuery(integer_expression))

        return self

    def skip(self, integer_expression: Union[str, int]) -> "DeclarativeBase":
        """Skip a number of records when returning results.

        Args:
            integer_expression: An integer indicating how many records to skip
              in the results.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            Skip the first result:

            Python: `match().node(variable='n').return_(results='n').skip(integer_expression='1').execute()`
            Cypher: `MATCH (n) RETURN n SKIP 1;`
        """
        self._query.append(SkipPartialQuery(integer_expression))

        return self

    def add_custom_cypher(self, custom_cypher: str) -> "DeclarativeBase":
        """Inject custom Cypher code into the query.

        Args:
            custom_cypher: A string representing the Cypher code to be injected
              into the query.

        Returns:
            A `DeclarativeBase` instance for constructing queries.
        """
        self._query.append(AddStringPartialQuery(custom_cypher))
        if " RETURN " in custom_cypher:
            self._fetch_results = True

        return self

    def get_single(self, retrieve: str) -> Any:
        """Returns a single result with a `retrieve` variable name.

        Args:
            retrieve: A string representing the results variable to be returned.

        Returns:
            An iterator of dictionaries containing the results of the query.
        """
        query = self._construct_query()

        result = next(self._connection.execute_and_fetch(query), None)

        if result:
            return result[retrieve]
        return result

    def foreach(
        self, variable: str, expression: str, update_clause: Union[str, List[str], Set[str]]
    ) -> "DeclarativeBase":
        """Iterate over a list of elements and for every iteration run every update clause.

        Args:
            variable: The variable name that stores each element.
            expression: Any expression that results in a list.
            update_clauses: One or more Cypher update clauses:
                SET, REMOVE, CREATE, MERGE, DELETE, FOREACH.

        Returns:
            A `DeclarativeBase` instance for constructing queries.

        Example:
            For each number in a list, create a node:

            Python: `update_clause = QueryBuilder().create().node(variable="n", id=PropertyVariable("i"))`
                    `query_builder = QueryBuilder().foreach("i", "[1, 2, 3]", update_clause.construct_query())`
            Cypher: `FOREACH ( i IN [1, 2, 3] | CREATE (n {id: i}) )`
        """
        if isinstance(update_clause, list):
            update_clause = " ".join(update_clause)

        self._query.append(ForeachPartialQuery(variable, expression, update_clause))

        return self

    def set_(self, item: str, operator: Operator, **kwargs):
        """Creates a SET statement Cypher partial query.

        Args:
            item: A string representing variable or property.
            operator: An assignment, increment or label filter operator.

        Kwargs:
            literal: A value that will be converted to Cypher value, such as int, float, string, etc.
            expression: A node label or property that won't be converted to Cypher value (no additional quotes will be added).

        Raises:
            GQLAlchemyLiteralAndExpressionMissingInWhere: Raises an error when neither literal nor expression keyword arguments were provided.
            GQLAlchemyExtraKeywordArgumentsInWhere: Raises an error when both literal and expression keyword arguments were provided.

        Returns:
            self: A partial Cypher query built from the given parameters.

        Examples:
            Set or update a property.

            Python: `match().node(variable='n').where(item='n.name', operator=Operator.EQUAL, literal='Germany').set_(item='n.population', operator=Operator.ASSIGNMENT, literal=83000001).return_().execute()`
            Cypher: `MATCH (n) WHERE n.name = 'Germany' SET n.population = 83000001 RETURN *;`

            Set or update multiple properties.

            Python: `match().node(variable='n').where(item='n.name', operator=Operator.EQUAL, literal='Germany').set_(item='n.population', operator=Operator.ASSIGNMENT, literal=83000001).set_(item='n.capital', operator=Operator.ASSIGNMENT, literal='Berlin').return_().execute()`
            Cypher: `MATCH (n) WHERE n.name = 'Germany' SET n.population = 83000001 SET n.capital = 'Berlin' RETURN *;`

            Set node label.

            Python: `match().node(variable='n').where(item='n.name', operator=Operator.EQUAL, literal='Germany').set_(item='n', operator=Operator.LABEL_FILTER, expression='Land').return_().execute()`
            Cypher: `MATCH (n) WHERE n.name = 'Germany' SET n:Land RETURN *;`

            Replace all properties using map.

            Python: `match().node(variable='c', labels='Country').where(item='c.name', operator=Operator.EQUAL, literal='Germany').set_(item='c', operator=Operator.ASSIGNMENT, literal={'name': 'Germany', 'population': '85000000'}).return_().execute()`
            Cypher: `MATCH (c:Country) WHERE c.name = 'Germany' SET c = {name: 'Germany', population: '85000000'} RETURN *;`

            Update all properties using map.

            Python: `match().node(variable='c', labels='Country').where(item='c.name', operator=Operator.EQUAL, literal='Germany').set_(item='c', operator=Operator.INCREMENT, literal={'name': 'Germany', 'population': '85000000'}).return_().execute()`
            Cypher: `MATCH (c:Country) WHERE c.name = 'Germany' SET c += {name: 'Germany', population: '85000000'} RETURN *;`

        """
        self._query.append(SetPartialQuery(item=item, operator=operator, **kwargs))

        return self

    def execute(self) -> Iterator[Dict[str, Any]]:
        """Executes the Cypher query and returns the results.

        Returns:
            An iterator of dictionaries containing the results of the query.
        """
        query = self._construct_query()
        if self._fetch_results:
            return self._connection.execute_and_fetch(query)
        else:
            return self._connection.execute(query)

    def _construct_query(self) -> str:
        """Constructs the (partial) Cypher query so it can be executed."""
        query = [""]

        # if not self._any_variables_matched():
        #    raise NoVariablesMatchedException()

        for partial_query in self._query:
            query.append(partial_query.construct_query())

        joined_query = "".join(query)
        joined_query = re.sub("\\s\\s+", " ", joined_query)
        return joined_query

    def construct_query(self) -> str:
        return self._construct_query()

    def _any_variables_matched(self) -> bool:
        """Checks if any variables are present in the result."""
        return any(
            q.type in [DeclarativeBaseTypes.RELATIONSHIP, DeclarativeBaseTypes.NODE] and q.variable not in [None, ""]
            for q in self._query
        )

    def _is_linking_valid_with_query(self, match_type: str):
        """Checks if linking functions match the current query."""
        return len(self._query) == 0 or self._query[-1].type != match_type

class Create(DeclarativeBase):
    def __init__(self, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(CreatePartialQuery())

class Match(DeclarativeBase):
    def __init__(self, optional: bool = False, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(MatchPartialQuery(optional))

class Merge(DeclarativeBase):
    def __init__(self, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(MergePartialQuery())

class Call(DeclarativeBase):
    def __init__(self, procedure: str, arguments: Optional[str] = None, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(CallPartialQuery(procedure, arguments))

class Unwind(DeclarativeBase):
    def __init__(self, list_expression: str, variable: str, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(UnwindPartialQuery(list_expression, variable))

class With(DeclarativeBase):
    def __init__(self, results: Optional[Dict[str, str]] = {}, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(WithPartialQuery(results))

class Foreach(DeclarativeBase):
    def __init__(
        self,
        variable: str,
        expression: str,
        update_clauses: Union[str, List[str], Set[str]],
        connection: Optional[DatabaseClient] = None,
    ):
        super().__init__(connection)
        self._query.append(ForeachPartialQuery(variable, expression, update_clauses))

class Return(DeclarativeBase):
    def __init__(self, results: Optional[Dict[str, str]] = {}, connection: Optional[DatabaseClient] = None):
        super().__init__(connection)
        self._query.append(ReturnPartialQuery(results))
        self._fetch_results = True


 #-*- coding:utf-8 -*-
import math
import matplotlib.pyplot as plt
import pandas as pd
import time

plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False ## 设置正常显示符号
#数据集进行划分，生成点
def  data_split():
    data=pd.read_csv('dataset.txt',encoding='utf-8',names=['密度','含糖量'])
    count= len(data)
    dataset=[]
    for i in range(count):
        a=data.values[i][0]
        b=data.values[i][1]
        dataset.append((a,b))
    return dataset
#计算欧几里得距离,a,b分别为两个元组
def dist(a, b):
    return math.sqrt(math.pow(a[0]-b[0], 2)+math.pow(a[1]-b[1], 2))

#dist_min
def dist_min(Ci, Cj):
    return min(dist(i, j) for i in Ci for j in Cj)
#dist_max
def dist_max(Ci, Cj):
    return max(dist(i, j) for i in Ci for j in Cj)
#dist_avg
def dist_avg(Ci, Cj):
    return sum(dist(i, j) for i in Ci for j in Cj)/(len(Ci)*len(Cj))

#找到距离最小的下标
def find_Min(M):
    min = 1000
    x = 0; y = 0
    for i in range(len(M)):
        for j in range(len(M[i])):
            if i != j and M[i][j] < min:
                min = M[i][j];x = i; y = j
    return (x, y, min)

#算法模型：
def AGNES(dataset, dist, k):
    time1=time.perf_counter()
    #初始化C和M
    C = [];M = []
    for i in dataset:
        Ci = []
        Ci.append(i)
        C.append(Ci)
    for i in C:
        Mi = []
        for j in C:
            Mi.append(dist(i, j))#Mi中存放了i簇到其余簇的距离
        M.append(Mi) #保存了两簇之间的距离
    q = len(dataset)
    #合并更新
    while q > k:
        x, y, min = find_Min(M)
        C[x].extend(C[y])#两个簇进行合并
        C.remove(C[y])#从全部簇的列表中删除被合并的簇
        #更新簇之间的距离
        M = []
        for i in C:
            Mi = []
            for j in C:
                Mi.append(dist(i, j))
            M.append(Mi)
        q -= 1
    time2=time.perf_counter()
    print('共耗时{:.5f}s'.format(time2 - time1))
    return C
#画图
def draw(C):
    colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
    for i in range(len(C)):
        coo_X = []    #x坐标列表
        coo_Y = []    #y坐标列表
        for j in range(len(C[i])):
            coo_X.append(C[i][j][0])
            coo_Y.append(C[i][j][1])
        plt.scatter(coo_X, coo_Y, marker='o', color=colValue[i%len(colValue)], label=i)
    plt.legend(loc='best')
    plt.title("AGNES算法聚类", fontsize=20)
    plt.xlabel("密度")
    plt.ylabel("含糖量")
    plt.show()
if __name__ == '__main__':
    C = AGNES(data_split(), dist_max, 2)
    draw(C)


from xotl.tools.future.codecs import safe_decode

from xoeuf.signals import (
    mock_replace,
    post_create,
    pre_create,
    write_wrapper,
    pre_fields_view_get,
    no_signals,
)

from odoo.tests.common import TransactionCase, at_install, post_install

# Don't import relatively
from odoo.addons.test_signals.models import (
    post_save_receiver,
    post_save_receiver_all_models,
    pre_save_receiver,
    wrap_nothing,
    pre_fvg_receiver,
)

@at_install(False)
@post_install(True)
class TestXoeufSignals(TransactionCase):
    def setUp(self):
        super(TestXoeufSignals, self).setUp()
        self.Model = self.env["test_signals.signaling_model"]
        self._ready_before = self.env.registry.ready
        self.env.registry.ready = True

    def tearDown(self):
        self.env.registry.ready = self._ready_before

    def test_post_create(self):
        with mock_replace(
            post_create, post_save_receiver
        ) as mock_post_create, mock_replace(
            pre_create, post_save_receiver
        ) as mock_pre_create:
            self.Model.create(dict(name="My name"))
            self.assertTrue(mock_post_create.called)
            self.assertFalse(mock_pre_create.called)

    def test_pre_create(self):
        with mock_replace(
            post_create, pre_save_receiver
        ) as mock_post_create, mock_replace(
            pre_create, pre_save_receiver
        ) as mock_pre_create:
            self.Model.create(dict(name="My name"))
            self.assertFalse(mock_post_create.called)
            self.assertTrue(mock_pre_create.called)

    def test_writer_wrap(self):
        def wrapper(sender, signal, *args, **kwargs):
            yield

        who = self.Model.create(dict(name="My name"))
        with mock_replace(write_wrapper, wrap_nothing, side_effect=wrapper) as mock:
            self.assertFalse(mock.called)
            who.write(dict(name="My new name"))
            self.assertTrue(mock.called)
        with mock_replace(write_wrapper, wrap_nothing, side_effect=wrapper) as mock:
            who.name = "My new other name"
            self.assertTrue(mock.called)

    def test_not_called_for_partners(self):
        with mock_replace(post_create, post_save_receiver) as mock, mock_replace(
            post_create, post_save_receiver_all_models
        ) as mock_all:
            partner = self.env["res.partner"].create(dict(name="Contact Info"))
            partner.email = "a@b.c"
            self.assertFalse(mock.called)
            self.assertTrue(mock_all.called)

    def test_fvg_in_abstract_models(self):
        who = self.Model.create(dict(name="My name"))
        with mock_replace(pre_fields_view_get, pre_fvg_receiver) as mock:
            result = who.fields_view_get()
            self.assertTrue(mock.called)
            self.assertIn("fgv-is-present", safe_decode(result["arch"], "utf-8"))

    def test_no_signals(self):
        # Test mocks outside and inside
        with mock_replace(pre_create, pre_save_receiver) as mock:
            with no_signals(pre_create):
                self.Model.create(dict(name="My name"))
            self.Model.create(dict(name="My name"))
            self.assertEqual(mock.call_count, 1)

        with no_signals(pre_create):
            with mock_replace(pre_create, pre_save_receiver) as mock:
                self.Model.create(dict(name="My name"))
                self.assertFalse(mock.called)

    def test_model_create_multi(self):
        with mock_replace(pre_create, pre_save_receiver) as mock:
            result = self.Model.create([dict(name="My name"), dict(name="Second obj")])
            # The mock is called once even though there are two records to
            # create.
            self.assertEqual(mock.call_count, 1)
            self.assertEqual(len(result), 2)


from flask import Blueprint, json, jsonify, request, abort, make_response
from app.models.dessert import Dessert
from app import db

desserts_bp = Blueprint("desserts_bp", __name__, url_prefix="/desserts")

@desserts_bp.route("", methods=["POST"])
def create_dessert():
    request_body = request.get_json()

    # guard clause
    if "name" not in request_body or "description" not in request_body:
        return jsonify("Invalid Request"), 400

    new_dessert = Dessert(
        name = request_body["name"],
        description = request_body["description"]
    )

    db.session.add(new_dessert)
    db.session.commit()

    return jsonify(f"{new_dessert.name} has been successfully created"), 201

@desserts_bp.route("", methods=["GET"])
def read_all_desserts():
    desserts = Dessert.query.all()
    desserts_response = [ dessert.to_dict() for dessert in desserts]
    print(desserts)
    return jsonify(desserts_response), 200

@desserts_bp.route("/<id>", methods=["GET"])
def read_one_dessert(id):
    try:
        id = int(id)
    except ValueError:
        abort(make_response({"message": f"dessert {id} is invalid"}, 400))

    dessert = Dessert.query.get(id)

    if not dessert:
        return abort(make_response({"message": f"dessert {id} not found"}, 404))

    return dessert.to_dict()

@desserts_bp.route("/<id>", methods=["PUT"])
def update_one_dessert(id):
    try:
        id = int(id)
    except ValueError:
        abort(make_response({"message": f"dessert {id} is invalid"}, 400))

    dessert = Dessert.query.get(id)
    request_body = request.get_json()
    dessert.update(request_body)
    db.session.commit()
    return jsonify(f"Dessert {dessert.id} successfully updated"), 200

@desserts_bp.route("/<id>", methods=["DELETE"])
def delete_one_dessert(id):
    try:
        id = int(id)
    except ValueError:
        abort(make_response({"message": f"dessert {id} is invalid"}, 400))

    dessert = Dessert.query.get(id)

    if not dessert:
        return abort(make_response({"message": f"dessert {id} not found"}, 404))

    db.session.delete(dessert)
    db.session.commit()
    return jsonify(f"Dessert {dessert.id} successfully deleted"), 200

##################################################
#               Review Routes                    #
##################################################

reviews_bp = Blueprint("reviews_bp", __name__, url_prefix="/reviews")

@reviews_bp.route("", methods=["POST"])
def create_review():
    pass


import torch.nn as nn
model_name = 'bert-base-uncased'
max_seq_len = 25

class BERTda(nn.Module):

    def __init__(self, bert):
        super(BERTda, self).__init__()
        self.bert_large = model_name == 'bert-large-uncased'
        self.bert = bert

        # dropout layer
        self.dropout = nn.Dropout(0.1)

        # relu activation function
        self.relu = nn.ReLU()

        # dense layer 0 if bert_large is true, else skip it
        if self.bert_large:
            self.fc0 = nn.Linear(1024, 768)

        self.fc1 = nn.Linear(768, 512)

        # dense layer 2 (Output layer)
        self.fc2 = nn.Linear(512, 2)

        # softmax activation function
        self.softmax = nn.LogSoftmax(dim=1)

    # define the forward pass
    def forward(self, sent_id, mask):
        # pass the inputs to the model
        _, cls_hs = self.bert(sent_id, attention_mask=mask, return_dict=False)

        if self.bert_large:
            x = self.fc0(cls_hs)

            x = self.relu(x)

            x = self.dropout(x)
        else:
            x = cls_hs

        x = self.fc1(x)

        x = self.relu(x)

        x = self.dropout(x)

        # output layer
        x = self.fc2(x)

        # apply softmax activation
        x = self.softmax(x)

        return x