#!/usr/bin/env python

# This example shows how to extract portions of an unstructured grid
# using vtkExtractUnstructuredGrid. vtkConnectivityFilter is also used
# to extract connected components.
#
# The data found here represents a blow molding process. Blow molding
# requires a mold and parison (hot, viscous plastic) which is shaped
# by the mold into the final form. The data file contains several steps
# in time for the analysis.

import vtk
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()

# Create a reader to read the unstructured grid data. We use a
# vtkDataSetReader which means the type of the output is unknown until
# the data file is read. So we follow the reader with a
# vtkCastToConcrete and cast the output to vtkUnstructuredGrid.
reader = vtk.vtkDataSetReader()
reader.SetFileName(VTK_DATA_ROOT + "/Data/blow.vtk")
reader.SetScalarsName("thickness9")
reader.SetVectorsName("displacement9")
castToUnstructuredGrid = vtk.vtkCastToConcrete()
castToUnstructuredGrid.SetInputConnection(reader.GetOutputPort())
warp = vtk.vtkWarpVector()
warp.SetInput(castToUnstructuredGrid.GetUnstructuredGridOutput())

# The connectivity filter extracts the first two regions. These are
# know to represent the mold.
connect = vtk.vtkConnectivityFilter()
connect.SetInputConnection(warp.GetOutputPort())
connect.SetExtractionModeToSpecifiedRegions()
connect.AddSpecifiedRegion(0)
connect.AddSpecifiedRegion(1)
moldMapper = vtk.vtkDataSetMapper()
moldMapper.SetInputConnection(reader.GetOutputPort())
moldMapper.ScalarVisibilityOff()
moldActor = vtk.vtkActor()
moldActor.SetMapper(moldMapper)
moldActor.GetProperty().SetColor(.2, .2, .2)
moldActor.GetProperty().SetRepresentationToWireframe()

# Another connectivity filter is used to extract the parison.
connect2 = vtk.vtkConnectivityFilter()
connect2.SetInputConnection(warp.GetOutputPort())
connect2.SetExtractionModeToSpecifiedRegions()
connect2.AddSpecifiedRegion(2)

# We use vtkExtractUnstructuredGrid because we are interested in
# looking at just a few cells. We use cell clipping via cell id to
# extract the portion of the grid we are interested in.
extractGrid = vtk.vtkExtractUnstructuredGrid()
extractGrid.SetInputConnection(connect2.GetOutputPort())
extractGrid.CellClippingOn()
extractGrid.SetCellMinimum(0)
extractGrid.SetCellMaximum(23)
parison = vtk.vtkGeometryFilter()
parison.SetInputConnection(extractGrid.GetOutputPort())
normals2 = vtk.vtkPolyDataNormals()
normals2.SetInputConnection(parison.GetOutputPort())
normals2.SetFeatureAngle(60)
lut = vtk.vtkLookupTable()
lut.SetHueRange(0.0, 0.66667)
parisonMapper = vtk.vtkPolyDataMapper()
parisonMapper.SetInputConnection(normals2.GetOutputPort())
parisonMapper.SetLookupTable(lut)
parisonMapper.SetScalarRange(0.12, 1.0)
parisonActor = vtk.vtkActor()
parisonActor.SetMapper(parisonMapper)

# graphics stuff
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

# Add the actors to the renderer, set the background and size
ren.AddActor(parisonActor)
ren.AddActor(moldActor)
ren.SetBackground(1, 1, 1)
ren.ResetCamera()
ren.GetActiveCamera().Azimuth(60)
ren.GetActiveCamera().Roll(-90)
ren.GetActiveCamera().Dolly(2)
ren.ResetCameraClippingRange()
renWin.SetSize(500, 375)

iren.Initialize()
renWin.Render()
iren.Start()


import numpy as np

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

def sigmoid_prime(y_hat):
    return y_hat * (1 - y_hat)

class Perceptron:
    """Perceptron implements a simple perceptron cell."""

    def __init__(self, inputs):
        self.weights = np.random.randn(1, inputs)
        self.bias = 0

    def predict(self, inputs):
        z = np.dot(self.weights, inputs) + self.bias
        return sigmoid(z)

    def train(self, x, y, epochs=100, eta=1):
        for i in range(epochs):
            # 1. make a prediction for given training input
            y_hat = self.predict(x)
            print("loss={}".format((1. / 2.) * np.power(y - y_hat, 2)))

            # 2. estimate error (delta)
            delta = (y_hat - y) * sigmoid_prime(y_hat)

            # 3. calculate adjustments for weights and bias
            dW = np.dot(delta, x.T)
            dB = delta

            # 4. update weights and bias
            self.weights = self.weights - eta * dW
            self.bias = self.bias - eta * dB

if __name__ == "__main__":
    p = Perceptron(2)

    # OR gate input combinations and outputs
    x = np.array([[0, 0],
                  [0, 1],
                  [1, 0],
                  [1, 1]]).T
    y = np.array([[0, 1, 1, 1]])

    print("Before Training:\n{} -> {}".format(x.T, p.predict(x)))
    p.train(x, y)
    print("After Training:\n{} -> {}".format(x.T, p.predict(x)))


from bs4 import BeautifulSoup
import requests, os

#Configuration Variables
search_refs = True
build_path = "API"
API_URL = "https://pythonapi.upbge.org/"

#Further addons
headers = {"bge" + os.sep + "types.py" : """
import mathutils

inf = 0
class CListValue:
    def __init__(self, ctype):
        self.__ret__ = ctype
        self.__i__ = None
        self.__itf__ = False

    def __instanceme__(self):
        if self.__i__ == None:
            self.__i__ = self.__ret__()
        return self.__i__

    def __getitem__(self, key): return self.__instanceme__()
    def __setitem__(self, key, val): return self.__instanceme__()
    def get(self, key): return self.__instanceme__()

    def __iter__(self): return self
    def __next__(self):
        self.__itf__ = not self.__itf__
        if self.__itf__: return self.__instanceme__()
        else: raise StopIteration
""",
"bge" + os.sep + "logic.py" :
"""globalDict = {}
keyboard = None
mouse = None
joysticks = []
"""}

erase = {"bge" + os.sep + "logic.py" : [
"""globalDict = None
keyboard = None
mouse = None
joysticks = None"""]}

fixes = {
"RandomMusic": [(", transition=(5)", ", transition=(5,0,0))")]
}

def dataToPath(dp):
    i = dp.rfind(".")
    return os.path.normpath(dp[:len(dp) if i == -1 else i].replace(".", "/") + ".py")

class File:
    done_files = []
    done_urls = []
    registred_class = {}

    def __init__(self, url, recursive=False, prefix=""):
        self.current_class = ""
        self.current_module = ""
        self.recursive = recursive

        self.makePage(url, recursive=recursive, prefix=prefix)

    def getType(self, dl, noerror=False):
        if dl==None: raise Exception("dl should not be None")
        if type(dl)!=str:
            try: t = dl.dd.table.tbody.tr.td.get_text()
            except Exception: return "None"
        else: t=dl
        t=t.replace("\t", "")
        t=t.replace("‘s", "")

        #Correctors
        if t == "MeshProxy": t = "KX_MeshProxy"
        if t == "boolen": t = "bool"

        #Registred
        if t == self.current_class: return "self"
        if t in File.registred_class.keys():
            m = File.registred_class[t]
            if self.current_module == m: return t + "()"
            else: return m + '.' + t +"()"
        for k, v in File.registred_class.items():
            m = v+'.'+k
            if m == t: return m + "()"

        #Direct addressing
        if t in ["float", "int", "bool"]: return t + "()"
        if t in ["boolean", "boolean.", "bool"]: return "bool()"
        if t == "double": return "float()"
        if t in ["integer", "bitfield"]: return "int()"
        if t in ["string", "str"]: return "str()"
        if t in ["matrix", "Matrix", "mathutils.Matrix"]:
            if self.current_module != "mathutils": return "mathutils.Matrix()"
            else: return "Matrix()"
        if t in ["vector", "Vector", "mathutils.Vector"]:
            if self.current_module != "mathutils": return "mathutils.Vector()"
            else: return "Vector()"
        if t == "list" and not noerror: return "list()"
        if t == "dict" and not noerror: return "dict()"
        if t == "tuple" and not noerror: return "tuple()"
        if t == "Quaternion":
            if self.current_module != "mathutils": return "mathutils.Quaternion()"
            else: return "Quaternion()"

        #Special cases
        if t == "list of functions and/or methods": return "list()"
        if t == "3d vector.": return "mathutils.Vector()"
        if t == "3-tuple (float, 3-tuple (x, y, z), 3-tuple (x, y, z))": return "(float, (0,0,0), (0,0,0))"
        if t.startswith("\n3-tuple (KX_GameObject, 3-tuple (x, y, z), 3-tuple (nx, ny, nz))"):
            return "(KX_GameObject, (0,0,0), (0,0,0), KX_PolyProxy, (0,0))"
        if t == "list [x, y]": return "[0,0]"
        if t in ["(integer, integer)", "(int,int)", "(int, int)"]: return "(0,0)"
        if t == "list [str]": return "[str()]"
        if t == "list [r, g, b]": return "[0,0,0]"
        if t == "list[x, y, z]": return "[0,0,0]"
        if t == "(Vector, float) pair": return "(Vector(), float())"
        if t == "Matrix4x4 (read only)": return "mathutils.Matrix()"
        if t == "tuple of two ints": return "(0,0)"
        if t == "sequence of two ints": return "[0,0]"
        if t == "sequence of two floats": return "[0.0,0.0]"
        if t == "sequence of three ints": return "[0,0,0]"
        if t == "sequence of four sequences of two ints": return "[[0,0],[0,0],[0,0],[0,0]]"
        if t == "sequence of four sequences of five ints": return "[[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]"
        if t == "Buffer\n": return "bgl.Buffer()"
        if t == "sequence supporting index/string lookups and iteration.": return "dict()"

        #Addressing of containers
        for st in ["list of ", "CListValue of "]:
            if t.startswith(st):
                h=self.getType(t[len(st):], True)
                if h != "None":
                    if h.endswith("()"): h=h[:-2]
                    if h=="self": h=self.current_class
                    if self.current_module == "bge.types":
                        return "CListValue(" + h + ")"
                    else: return "bge.types.CListValue(" + h + ")"

        if t.startswith("Vector"):
            if self.current_module != "mathutils": return "mathutils.Vector()"
            else: return "Vector()"

        #Last chances to get it right
        for ch in ['\n', ' ', ',']:
            if ch in t:
                for x in t.split(ch):
                    h=self.getType(x, True)
                    if h!="None": return h

        for x in ["non-negative", "None"]:
            if x in t: return "None"

        if not noerror:
            if type(dl) != str and search_refs:
                links = dl.dd.table.tbody.tr.td.find_all("a")
                url = File.done_urls[-1]
                base_url = url[:url.rfind("/")+1]
                for l in links:
                    link = l["href"]
                    if not "CListValue" in link:
                        link = base_url + link[:link.rfind("#")]
                        File(link, recursive=True)
                        return self.getType(dl, noerror)

            print("Unknown type:", t)

        return "None"

    def getReturnType(self, o):
        if o.dd.table == None: return "None"
        for tr in o.dd.table.tbody.find_all("tr"):
            if tr.th.string=="Return type:":
                return self.getType(tr.td.get_text())
        return "None"

    def makePage(self, url, tab='', recursive=False, prefix=""):
        if url in File.done_urls: return
        else: File.done_urls.append(url)

        if not url.endswith(".html"):
            print("Skipped:", url)
            return

        print("Building page: ", url)

        r = requests.get(url).text
        soup = BeautifulSoup(r, "html.parser")

        body = soup.body.find("h1").parent
        if body.p.get_text().startswith("base class"):
            link = body.p.a["href"]
            link = url[:url.rfind("/")+1] + link[:link.rfind("#")]
            if recursive==True:
                File(link, recursive)

        #Get current module, autodetect class vs module using case sensitive.
        self.current_module = prefix + url[url.rfind('/')+1:url.rfind(".html")]
        i = self.current_module.rfind(".")
        if i != -1:
            if not self.current_module.split(".")[-1][0:1].islower():
                self.current_module = self.current_module[:i]
                dest = url[url.rfind('/')+1:url.rfind(".html")]
            else: dest = self.current_module + "."
        else: dest = self.current_module + "."

        #Identify Class or Module level data
        code = ""
        for dl in soup.find_all("dl"):
            dtype=dl.get("class")
            if dtype[0]=="class":
                code += '\n' + self.makePythonClass(dl) + '\n'

            if dtype[0]=="data":
                name = dl.dt["id"]
                #Make sure it's at module level
                if len(name.split('.')) == len(self.current_module.split('.'))+1:
                    value = "None"
                    for th in dl.find_all("th"):
                        if th.get_text() == "Value:":
                            value = th.parent.td.get_text()
                    code += name.split('.')[-1] + " = " + value + "\n"

            if dtype[0]=="function":
                name = dl.dt["id"]
                if len(name.split('.')) == len(self.current_module.split('.'))+1:
                    code += self.writeFunction(dl, False, '')

        #Write the file
        odest =  dataToPath(dest)
        dest = build_path + os.sep + odest

        if os.sep in dest:
            os.makedirs(os.path.dirname(dest), exist_ok=True)
        if dest in File.done_files:
            with open(dest, "a+", encoding="utf-8") as out: out.write(code)
        else:
            try: code = headers[odest] + code
            except KeyError: pass

            try:
                for x in erase[odest]: code=code.replace(x, "")
            except KeyError: pass

            with open(dest, "w", encoding="utf-8") as out: out.write(code)
            File.done_files.append(dest)

    def makePythonClassTitle(self, dt):
        cn = dt["id"]
        self.current_class = cn[cn.rfind(".")+1:]
        File.registred_class[self.current_class] = self.current_module
        code = "class " + self.current_class + '('
        for x in dt.find_all("em"):
            if x.get("class"): continue
            if not x.string[0].isupper(): continue
            if x.string in ["A", "B", "C", "D", "E", "F"]: continue
            code += x.string + ','
        if code.endswith(","): return code[:-1] + '):\n'
        else: return code [:-1]+ ":\n"

    def makePythonClass(self, dl, tab=''):
        tab+='\t'
        docstring = '"""' + dl.dd.p.get_text() + '"""'
        code = self.makePythonClassTitle(dl.dt) + tab + docstring + '\n\n'

        temp_code = tab + "def __init__(self, "

        for x in dl.dt.find_all("em"):
            if x.get("class"): continue
            if not x.string[0].islower() and not x.string in ["A", "B", "C", "D", "E", "F"]: continue
            if not "=" in x.string: temp_code += x.string+"=None, "
            else:
                if x.string.split("=")[1][0]== '<':
                    temp_code += x.string.split("=")[0] + "=None, "
                else:
                    temp_code += x.string + ', '

        temp_code = temp_code[:-2] + "):\n"
        tab+='\t'

        for o in dl.dd.find_all("dl"):
            if o["class"][0]=="data":
                temp_code += tab + "self." + o.dt.code.string + " = int()\n"
            if o["class"][0]=="attribute":
                temp_code += tab + "self." + o.dt.code.string + " = " + self.getType(o) + '\n'

        if not temp_code.endswith(":\n"): code += temp_code

        tab=tab[:-1]
        for o in dl.dd.find_all("dl"):
            if o["class"][0]=="method":
                code += self.writeFunction(o, True, tab)

        if self.current_class in fixes:
            for el in fixes[self.current_class]:
                x, y = el
                code = code.replace(x, y)

        return code

    def writeFunction(self, o, is_method=True, tab='\t'):
        if is_method:
            code = '\n' + tab + "def " + o.dt.code.string + "(self, "
        else:
            code = '\n' + tab + "def " + o.dt.find_all("code")[-1].string + "("

        for arg in o.dt.find_all("em"):
            m = arg.string.split("=")
            if len(m)>1 and any([m[1].startswith(x) for x in ["KX_", "IMB_"]]):
                 code += m[0] + '=None, '
            else: code += arg.string + ', '
        if code.endswith("("): code += "):"
        else: code = code[:-2]+"):"

        try:
            docstring = '"""' + o.dd.p.get_text() + '"""'
            code += '\n' + tab + '\t' + docstring + '\n'
        except Exception: code += " pass\n"

        rt = self.getReturnType(o)
        if rt != "None":
            if code.endswith(" pass\n"): code=code[:-len(" pass\n")]+"\n"
            tab+='\t'
            if "bge." in rt: code += tab + "import bge\n"
            code += tab + "return " + rt + '\n'
            tab=tab[:-1]

        if "deprecated" in code or "Deprecated" in code: return ""
        return code

def build(url): File(url, recursive=True, prefix="core." if "api/" in url else "")
def build_bge(url):
    build(url + "mathutils.html")
    build(url + "bge.types.KX_MeshProxy.html")
    build(url + "bge.types.KX_CharacterWrapper.html")
    build(url + "bge.types.KX_VehicleWrapper.html")
    build(url + "bge.types.SCA_PythonController.html")
    build(url + "bge.types.KX_Scene.html")
    build(url + "bge.logic.html")
    build(url + "bge.texture.html")
    build(url + "bge.events.html")
    build(url + "bge.app.html")
    build(url + "bge.constraints.html")

    init="from . import logic, types, texture, events, app, constraints"
    init_path = build_path + os.sep + "bge" + os.sep + "__init__.py"
    with open(init_path, "w", encoding="utf-8") as out: out.write(init)

def build_core(url):
    build(url + "api/media.html")
    build(url + "api/event.html")
    build(url + "api/sequencer.html")
    build(url + "api/utils.html")

    init="from . import media, event, utils, sequencer\nmedia.music=media.AudioFile()"
    init_path = build_path + os.sep + "core" + os.sep + "__init__.py"
    with open(init_path, "w", encoding="utf-8") as out: out.write(init)

def test():
    test_bge()
    test_core()

def test_bge():
    import traceback
    sys.path.append(build_path)

    try:
        import mathutils, bge
        v=mathutils.Vector()
        m=mathutils.Matrix()
        scn = bge.logic.getCurrentScene()
        o = scn.objects["some"]
        a=o.isPlayingAction()
        b=o.parent.addDebugProperty("LOL")
        o.endObject()

        print("Test BGE: OK")
    except Exception: traceback.print_exc()

def test_core():
    import traceback
    sys.path.append(build_path)

    try:
        import core
        core.media.music.filepath = ""

        print("Test CORE: OK")
    except Exception: traceback.print_exc()

build_path = os.path.normpath(build_path)

import sys
if len(sys.argv) == 1:
    build_bge(API_URL)
    build_core("http://coredoc.royalwebhosting.net/")
    test()
    print("Done.")

if len(sys.argv) == 2:
    if sys.argv[1] == "-test": test()


from sklearn.model_selection import train_test_split
from src.config import config
from mindspore import Tensor
import mindspore

class ModelDataProcessor:
    def __init__(self):
        self.get_dict()

    def get_dict(self):
        self.word_dict = {}
        with open(config.vocab_file, 'r') as f:
            cnt = 0
            for line in f:
                line = line.rstrip()
                self.word_dict[line] = cnt
                cnt += 1

    def process_file(self, file_name:str):
        setences_list = []

        with open(file_name, 'r', encoding='Windows-1252') as f:
            for line in f:
                text = line.rstrip().split()
                setences_list.append(text)

        return setences_list

    def process_data(self, file_name_pos, file_name_neg):
        setences_list_pos = self.process_file(file_name_pos)
        setences_list_neg = self.process_file(file_name_neg)

        # 添加标签
        setences_list = setences_list_pos + setences_list_neg

        labels = [1 for i in range(len(setences_list_pos))] + [0 for i in range(len(setences_list_neg))]

        # 制作数据集
        X_train, X_test, y_train, y_test = train_test_split(setences_list, labels, test_size=0.3, shuffle=True, random_state=0, stratify=labels)

        return X_train, X_test, y_train, y_test

    def get_data(self):
        # 提供给训练文件获取分割好的数据集
        file_name_pos = './data/rt-polaritydata/pos.txt'
        file_name_neg = './data/rt-polaritydata/neg.txt'

        X_train, X_test, y_train, y_test = self.process_data(file_name_pos, file_name_neg)

        return X_train, X_test, y_train, y_test

    def get_data_loader(self):
        X_train, X_test, y_train, y_test = self.get_data()
        # 中间应该还增加对文本的编码
        train_text_ids = [[self.word_dict[word] for word in item] for item in X_train]
        test_text_ids = [[self.word_dict[word] for word in item] for item in X_test]

        return train_text_ids, test_text_ids, y_train, y_test

    def get_batch(self, x, y):
        assert len(x) == len(y) , "error shape!"

        n_batches = int(len(x) / config.batch_size)  # 统计共几个完整的batch
        for i in range(n_batches - 1):
            x_batch = x[i*config.batch_size: (i + 1)*config.batch_size]
            y_batch = y[i*config.batch_size: (i + 1)*config.batch_size]
            lengths = [len(seq) for seq in x_batch]
            max_length = max(lengths)
            for i in range(len(x_batch)):
                x_batch[i] = x_batch[i] + [0 for j in range(max_length-len(x_batch[i]))]

            yield x_batch, y_batch

if __name__ == '__main__':
    data_processor = ModelDataProcessor()
    X_train, X_test, y_train, y_test = data_processor.get_data_loader()
    for x_batch, y_batch in data_processor.get_batch(X_train, y_train):
        x_batch = Tensor(x_batch, mindspore.int32)
        y_batch = Tensor(y_batch, mindspore.int32)
        print(x_batch)
        print(y_batch)


"""

You have a matrix MxN that represents a map. There are 2 possible states on the map: 1 - islands, 0 - ocean. Your task is to calculate the number of islands in the most effective way. Please write code in Python 3.

Inputs:
M N
Matrix

Examples:
Input:
3 3
0 1 0
0 0 0
0 1 1
Output: 2

Input:
3 4
0 0 0 1
0 0 1 0
0 1 0 0
Output:

"""
import numpy as np

t = np.array([[0,1,0], [0,0,0], [0,1,1]])
k = np.array([[0,0,0,1], [0,0,1,0], [ 0,1,0,0]])
p = np.array([[0,0,0,1], [0,0,1,1], [0,1,0,1]])

# print(f'{t} :2 islands\n')
# print(f'{k} :3 islands\n')
# print(f'{p} :2 islands\n')

m = np.random.randint(2, size=(6, 5)) #random map
# print(f' {m} how many islands ? ')

def islands(map):  # input is matrix MxN that represents map
    row, columns = map.shape
    counter = 0
    visit = np.zeros((row, columns))  # array that hold information about visited cell - graph search

    def graph(i, j):
        if i < 0 or i >= row or j < 0 or j >= columns or visit[i][j] or map[i][j] == 0:
            return  # do nothing - boundries aor already visited or '0' on the map - (ocean)
        else:
            visit[i][
                j] = 1  # if cell was not visited before - put the flag '1' - (True) and check recurence graph around this cell
            graph(i + 1, j)
            graph(i - 1, j)
            graph(i, j + 1)
            graph(i, j - 1)

    for i in range(row):  # look for '1' on the map
        for j in range(columns):
            if not visit[i][j] and map[i][j] == 1:
                graph(i, j)
                counter += 1

    print(f'Your maps shape is: {map.shape}, and it looks like this: \n {map}')

    return (f'Number of islands: {counter}\n')

# print(f'{islands(k)}\n')
# print(f'{islands(t)}\n')
print(f'{islands(p)}\n')
print(f'{islands(m)}\n')


from pydantic import BaseModel, Field, validator

class Address(BaseModel):
    region: str
    city: str
    street_type: str
    street: str
    house_type: str
    house: str
    value: str
    lat: float
    lng: float

class Salary(BaseModel):
    from_: int = Field(alias='from')
    to: int
    currency: str
    gross: bool

class Contacts(BaseModel):
    fullName: str
    phone: str
    email: str

    '''тривиальная проверка почты'''

    @validator('email')
    def at_in_email(cls, v: str) -> str:
        if not '@' in v:
            raise ValueError('Email некорректный')
        return v

class CandidateInfo(BaseModel):
    description: str
    employment: str
    address: Address
    name: str
    salary: Salary
    contacts: Contacts

class Experience(BaseModel):
    id = "noMatter"

class ChangedCoordinates(BaseModel):
    latitude: float
    longitude: float

class Phone(BaseModel):
    city: str
    country: str
    number: str

class ChangedContacts(BaseModel):
    email: str
    name: str
    phone: Phone

class ChangedSalary(BaseModel):
    from_: int = Field(alias='from')
    to: int

class Schedule(BaseModel):
    id: str

class ResultInfo(BaseModel):
    address: str
    allow_messages = True
    billing_type = "packageOrSingle"
    business_area = 1
    contacts: ChangedContacts
    coordinates: ChangedCoordinates
    description: str
    experience: Experience
    html_tags = True
    image_url = "https://img.hhcdn.ru/employer-logo/3410666.jpeg"
    name: str
    salary: int
    salary_range: ChangedSalary
    schedule: Schedule


#Developed By: Tonumoy Mukherjee

import os
from scipy.io import wavfile
import scipy
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from keras.layers import Conv2D, MaxPool2D, Flatten, LSTM
from keras.layers import Dropout, Dense, TimeDistributed
from keras.models import Sequential
from keras.utils import to_categorical
from keras import optimizers
from sklearn.utils.class_weight import compute_class_weight
from tqdm import tqdm
from python_speech_features import mfcc
import pickle
from keras.callbacks import ModelCheckpoint
from cfg import Config
import random
import theano
from keras.utils import plot_model
#import pdb
from mpl_toolkits.axes_grid1 import make_axes_locatable

def check_data():
    if os.path.isfile(config.p_path):
        print('Loading exixting data for {} model' .format(config.mode))
        with open(config.p_path, 'rb') as handle:
            tmp = pickle.load(handle)
            return tmp
    else:
        return None
#%% Feature Extraction

def build_rand_feat():
    tmp = check_data()
    if tmp:
        return tmp.data[0], tmp.data[1]
    X = []
    y = []
    _min, _max = float('inf'), -float('inf')
    for _ in tqdm(range(n_samples)):
        rand_class = np.random.choice(class_dist.index, p=prob_dist)
        file = np.random.choice(df[df.label==rand_class].index)
        rate, wav = wavfile.read('clean-train/'+file)
        label = df.at[file, 'label']
        rand_index = np.random.randint(0, wav.shape[0]-config.step)
        sample = wav[rand_index:rand_index+config.step]
        X_sample = mfcc(sample, rate,
                        numcep=config.nfeat, nfilt=config.nfilt, nfft=config.nfft)
        _min = min(np.amin(X_sample), _min)
        _max = max(np.amax(X_sample), _max)
        X.append(X_sample)
        y.append(classes.index(label))
    config.min = _min
    config.max = _max
    X, y  = np.array(X), np.array(y)
    X = (X - _min) / (_max - _min)
    if config.mode == 'conv':
        X = X.reshape(X.shape[0], X.shape[1], X.shape[2],1)
    elif config.mode == 'time':
        X = X.reshape(X.shape[0], X.shape[1], X.shape[2])
    y = to_categorical(y, num_classes=2)
    config.data = (X, y)

    with open(config.p_path, 'wb') as handle:
        pickle.dump(config, handle, protocol=2)

    return X,y

#%% CNN Model

def get_conv_model():
    model = Sequential()
    model.add(Conv2D(16, (3, 3), activation='relu', strides=(1, 1),
                     padding='same', input_shape=input_shape))
    #pdb.set_trace()
    model.add(Conv2D(32, (3, 3), activation='relu', strides=(1, 1),

                     padding='same', input_shape=input_shape))
    model.add(Conv2D(64, (3, 3), activation='relu', strides=(1, 1),
                     padding='same', input_shape=input_shape))
    model.add(Conv2D(128, (3, 3), activation='relu', strides=(1, 1),
                     padding='same', input_shape=input_shape))
    model.add(MaxPool2D((2, 2)))
    model.add(Dropout(0.5))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(64, activation='relu'))
    #model.add(Dense(32, activation='relu'))
    #model.add(Dense(16, activation='relu'))
    model.add(Dense(2, activation='softmax'))
    model.summary()
    #adam = optimizers.Adam(lr=0.00001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=1e-9, amsgrad=False)
    model.compile(loss='categorical_crossentropy',
                  optimizer='adam',
                  metrics=['acc'])
    #keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
    return model

#%% LSTM Model

def get_recurrent_model():
    #shape of data for RNN is (n, time, features)
    model = Sequential()
    model.add(LSTM(128, return_sequences=True, input_shape=input_shape))
    model.add(LSTM(128, return_sequences=True))
    model.add(LSTM(128, return_sequences=True))
    model.add(LSTM(128, return_sequences=True))
    model.add(Dropout(0.5))
    model.add(TimeDistributed(Dense(64, activation='relu')))
    model.add(TimeDistributed(Dense(32, activation='relu')))
    model.add(TimeDistributed(Dense(16, activation='relu')))
    model.add(TimeDistributed(Dense(8, activation='relu')))
    model.add(Flatten())
    model.add(Dense(2, activation='softmax'))
    model.summary()
    #sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    #adam = optimizers.Adam(lr=0.00001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=1e-9, amsgrad=False)
    model.compile(loss='categorical_crossentropy',
                  optimizer='adam',
                  metrics=['acc'])
#    model.contrib.layers.l2_regularizer(
#    scale=1 ,
#    scope=None
#)
    return model

#%% Data Management & Model Selection

df = pd.read_csv('Quake_mod.csv')
df.set_index('fname', inplace=True)

for f in df.index:
    rate, signal = wavfile.read('clean-train/'+f)
    signal =signal[0:int(0.2*rate)] #first 0.2 sec of signal
    df.at[f, 'length'] = signal.shape[0]/rate

classes = list(np.unique(df.label))
class_dist = df.groupby(['label'])['length'].mean()

n_samples = 2 * int(df['length'].sum()/0.1) #10th of a second
prob_dist = class_dist/class_dist.sum()
choices = np.random.choice(class_dist.index, p=prob_dist)

fig, ax = plt.subplots()
ax.set_title('Class Distribution', y=1.08,fontsize='large', fontweight='bold')
ax.pie(class_dist, labels=class_dist.index,autopct='%2.2f%%',
       shadow=False, startangle=90)
ax.axis('equal')
plt.show()

config = Config(mode='conv')

if config.mode == 'conv':
    X, y = build_rand_feat()
    y_flat = np.argmax(y, axis=1)
    input_shape = (X.shape[1], X.shape[2], 1)
    model = get_conv_model()

elif config.mode == 'time':
    X, y = build_rand_feat()
    y_flat = np.argmax(y, axis=1)
    input_shape = (X.shape[1], X.shape[2])
    model = get_recurrent_model()

#%%   Training
class_weight = compute_class_weight('balanced', np.unique(y_flat), y_flat)

checkpoint = ModelCheckpoint(config.model_path, monitor='val_acc', verbose=1, mode='max',
                             save_best_only=True, save_weights_only=False, period=1)

model.fit(X, y, epochs=100, batch_size=32, shuffle=True,
          class_weight=class_weight, validation_split=0.1,
          callbacks=[checkpoint])

model.save(config.model_path)
plot_model(model, to_file='convolutional_neural_network.png')

#%%

#def plot_filters(layer,X,y):
##
##
##    filters = layer.W.get_value()
#    filters, biases = layer.get_weights()
#    fig = plt.figure()
#    for j in range(len (filters)):
#        ax = fig.add_subplot(y,X,j+1)
#        ax.matshow(filters[j][0], cmap = cm.binary)
##
#        plt.xticks(np.array([]))
#        plt.yticks(np.array([]))
#    plt.tight_layout()
#    return plt
##
#plot_filters(model.layers[0],4,4) #first convolution layer filters
##
##%%
#for layer in model.layers:
#	# check for convolutional layer
#	if 'conv' not in layer.name:
#		continue
#	# get filter weights
#	filters, biases = layer.get_weights()
#	print(layer.name, filters.shape)

#%% Apda Cde Img Resize Nearest Neighbour

def my_resize(arr, f):
    newarr = np.ones((arr.shape[0]*f, arr.shape[1]*f, arr.shape[2], arr.shape[3]))
    for k1 in range(arr.shape[2]):
        for k2 in range(arr.shape[3]):
            temp = arr[:, :, k1, k2]
            temp = (temp-np.min(temp))/(np.max(temp)-np.min(temp))
            for i in range(arr.shape[0]):
                for j in range(arr.shape[1]):
                    newarr[i*f:(i+1)*f, j*f:(j+1)*f, k1, k2]=temp[i, j]
    return newarr

def plot_filter(arr, f, padd):
    up_arr = my_resize(arr, f)
    newarr = np.ones((arr.shape[2]*(up_arr.shape[0]+padd), arr.shape[3]*(up_arr.shape[1]+padd)))
    for i in range(arr.shape[2]):
        for j in range(arr.shape[3]):
            newarr[i*up_arr.shape[0]+i*padd:(i+1)*up_arr.shape[0]+i*padd, j*up_arr.shape[0]+j*padd:(j+1)*up_arr.shape[0]+j*padd]= \
            up_arr[:,:,i, j]
    return newarr

#%%    Filter output plots CNN

fig1, (ax1,ax2,ax3,ax4) = plt.subplots(nrows=4 , ncols=1)
ax1.set_title("Layer 1 - 16 Filters")
#ax1.set_xlabel("X-label for axis 1"
filters, bias = model.layers[0].get_weights() #1st layer 16 filters
#filters = filters.reshape(3, 3, 4,4)
#title_obj = plt.title('16 Filters of Layer - 1') #get the title property handler
#plt.getp(title_obj, 'text') #print out the properties of title
out = plot_filter(filters, 8, 1)
ax1.imshow(out, cmap=cm.gray)

filters, bias = model.layers[1].get_weights() #2nd layer 32 filters
out = random.sample(list(plot_filter(filters, 8, 1)),32)
ax2.imshow(out, cmap=cm.gray)
ax2.set_title("Layer 2 - 16 X 32 Filters")

filters, bias = model.layers[2].get_weights() #3rd layer 64 filters
out = random.sample(list(plot_filter(filters, 8, 1)),64)
ax3.imshow(out, cmap=cm.gray)
ax3.set_title("Layer 3 - 32 X 64 Filters")

filters, bias = model.layers[3].get_weights() #4thlayer 128 filters
out = random.sample(list(plot_filter(filters, 8, 1)),128)
ax4.imshow(out, cmap=cm.gray)
ax4.set_title("Layer 4 - 64 X 128 Filters")

#%%

fig2, axs = plt.subplots(nrows=2 , ncols=5)
axs[0,0].imshow(X[1,:,:,0]) #Positive Class I/P
axs[0,0].set_title("Positive Class I/P")
axs[1,0].imshow(X[0,:,:,0]) #Negative Class I/P
axs[1,0].set_title("Negative Class I/P")

axs[0,1].imshow(X[5,:,:,0]) #Positive Class I/P
axs[0,1].set_title("Positive Class I/P")
axs[1,1].imshow(X[6,:,:,0]) #Negative Class I/P
axs[1,1].set_title("Negative Class I/P")

axs[0,2].imshow(X[8,:,:,0]) #Positive Class I/P
axs[0,2].set_title("Positive Class I/P")
axs[1,2].imshow(X[9,:,:,0]) #Negative Class I/P
axs[1,2].set_title("Negative Class I/P")

axs[0,3].imshow(X[20,:,:,0]) #Positive Class I/P
axs[0,3].set_title("Positive Class I/P")
axs[1,3].imshow(X[21,:,:,0]) #Negative Class I/P
axs[1,3].set_title("Negative Class I/P")

axs[0,4].imshow(X[24,:,:,0]) #Positive Class I/P
axs[0,4].set_title("Positive Class I/P")
axs[1,4].imshow(X[25,:,:,0]) #Negative Class I/P
axs[1,4].set_title("Negative Class I/P")

#%%
#from keras import backend as K
#def get_activations(model, layer_idx, X_batch):
#    get_activations = K.function([model.layers[0].input, K.learning_phase()], [model.layers[layer_idx].output,])
#    activations = get_activations([X_batch,0])
#    return activations

# visualizing intermediate layers

#output_layer = model.layers[0].get_output()
#output_fn = theano.function([model.layers[0].get_input()], output_layer)
#
## the input image
#
#input_image=X[1,:,:,0]
#print(input_image.shape)
#
#plt.imshow(input_image[0,:,:,0],cmap ='gray')
#plt.imshow(input_image[0,0,:,0])
#
#
#output_image = output_fn(input_image)
#print(output_image.shape)
#
## Rearrange dimension so we can plot the result
#output_image = np.rollaxis(np.rollaxis(output_image, 3, 1), 3, 1)
#print(output_image.shape)

fig3, axs = plt.subplots(nrows=3 , ncols=5)

filters, bias = model.layers[3].get_weights()

filt1 = filters[:,:,0,0] # 1st filter
filt2 = filters[:,:,0,1] # 2nd filter
filt3 = filters[:,:,0,11] # 3rd filter
filt4 = filters[:,:,0,13] # 4th filter
filt5 = filters[:,:,0,14] # 5th filter

inp1 = X[8,:,:,0] # random input

fst_conv = scipy.signal.convolve2d(inp1, filt1, mode='same', boundary='fill', fillvalue=0) #first filter convolution
fst_conv[fst_conv<0] = 0 #relu

scnd_conv = scipy.signal.convolve2d(inp1, filt2, mode='same', boundary='fill', fillvalue=0) #second filter convolution
scnd_conv[scnd_conv<0] = 0 #relu

thrd_conv = scipy.signal.convolve2d(inp1, filt3, mode='same', boundary='fill', fillvalue=0) #third filter convolution
thrd_conv[thrd_conv<0] = 0 #relu

frth_conv = scipy.signal.convolve2d(inp1, filt4, mode='same', boundary='fill', fillvalue=0) #fourth filter convolution
frth_conv[frth_conv<0] = 0 #relu

ffth_conv = scipy.signal.convolve2d(inp1, filt5, mode='same', boundary='fill', fillvalue=0) #fifth filter convolution
ffth_conv[ffth_conv<0] = 0 #relu

axs[0,0].imshow(filt1, cmap =cm.gray)
axs[0,0].set_title("Layer 1, Filter 1")

axs[0,1].imshow(filt2, cmap =cm.gray)
axs[0,1].set_title("Layer 1, Filter 2")

axs[0,2].imshow(filt3, cmap =cm.gray)
axs[0,2].set_title("Layer 1, Filter 3")

axs[0,3].imshow(filt4, cmap =cm.gray)
axs[0,3].set_title("Layer 1, Filter 4")

axs[0,4].imshow(filt5, cmap =cm.gray)
axs[0,4].set_title("Layer 1, Filter 5")

axs[1,0].imshow(inp1, cmap =cm.gray)
axs[1,1].imshow(inp1, cmap =cm.gray)
axs[1,2].imshow(inp1, cmap =cm.gray)
axs[1,2].set_title("Identical Positive Input to the filters")
axs[1,3].imshow(inp1, cmap =cm.gray)
im5  = axs[1,4].imshow(inp1, cmap =cm.gray)
divider = make_axes_locatable(axs[1,4])
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(im5, cax=cax, orientation='vertical')

axs[2,0].imshow(fst_conv, cmap =cm.gray)
axs[2,0].set_title("Layer 1, Filter 1 Activation")

axs[2,1].imshow(scnd_conv, cmap =cm.gray)
axs[2,1].set_title("Layer 1, Filter 2 Activation")

axs[2,2].imshow(thrd_conv, cmap =cm.gray)
axs[2,2].set_title("Layer 1, Filter 3 Activation")

axs[2,3].imshow(frth_conv, cmap =cm.gray)
axs[2,3].set_title("Layer 1, Filter 4 Activation")

axs[2,4].imshow(ffth_conv, cmap =cm.gray)
axs[2,4].set_title("Layer 1, Filter 5 Activation")

#plt.imshow(conv, cmap = cm.gray) # activations


from gobigger.utils import SequenceGenerator
from gobigger.players import HumanSPPlayer
from .player_manager import PlayerManager

class PlayerSPManager(PlayerManager):

    def __init__(self, cfg, border, team_num, player_num_per_team, spore_manager_settings,
                 random_generator=None, sequence_generator=None):
        super(PlayerSPManager, self).__init__(cfg, border, team_num, player_num_per_team, spore_manager_settings,
                                              random_generator=random_generator)
        if sequence_generator is not None:
            self.sequence_generator = sequence_generator
        else:
            self.sequence_generator = SequenceGenerator()

    def init_balls(self, custom_init=None):
        if custom_init is None or len(custom_init) == 0:
            for i in range(self.team_num):
                team_id = i
                for j in range(self.player_num_per_team):
                    player_id = i * self.player_num_per_team + j
                    player = HumanSPPlayer(cfg=self.cfg.ball_settings, team_id=team_id, player_id=player_id,
                                           border=self.border, spore_settings=self.spore_settings,
                                           sequence_generator=self.sequence_generator)
                    player.respawn(position=self.border.sample())
                    self.players[player_id] = player
        else:
            raise NotImplementedError


def isPrime(num):
  if num == 1:
    return False
  else:
    for i in range(2, int(num**0.5) + 1):
      if num % i == 0:
        return False
    return True

i = int(input())

while True:
  i = list(str(i))
  if i == i[::-1]:
    if isPrime(int(''.join(i))):
      print(''.join(i))
      break

  i = int(''.join(i))
  i += 1


"""
Function in this module shuffles sentence with leaving it readable.
"""

from random import randint, shuffle

def shuffle_string(string):
    while True:
        symbols_list = list(string)
        shuffle(symbols_list)
        result = ''.join(symbols_list)

        if result != string:
            return result

def shuffle_word(word):
    if len(word) < 4 or word.isalpha() is False:
        return word
    else:
        inner_letters = word[1: -1]
        list_of_parts = [inner_letters[i:i + 3] for i in range(0, len(inner_letters), 3)]

        for i, part in enumerate(list_of_parts):
            if len(part) > 1:
                list_of_parts[i] = shuffle_string(part)

        return word[0] + ''.join(list_of_parts) + word[-1]

def permutuate(text):
    words = text.split(' ')
    for i, word in enumerate(words):
        words[i] = shuffle_word(word)

    return ' '.join(words)

def main():
    sentence = input('Enter sentence: ')
    shuffled_sentence = permutuate(sentence)
    print(f'Original text is: {sentence}')
    print(f'Shuffled text is: {shuffled_sentence}')

main()


import logging
import time
import sys

from selenium import webdriver
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.edge.service import Service as EdgeService
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from selenium.common.exceptions import TimeoutException

class WhatsappBot(object):
    def __init__(self, config):
        self.config = config

        # set options as you wish
        self.options = Options()
        self.options.add_argument("--disable-infobars")
        self.options.add_argument("start-maximized")
        self.options.add_argument("--disable-extensions")
        if self.config.user_dir_folder:
            self.options.add_argument("--user-data-dir=" + self.config.user_dir_folder)

        # setup Edge Driver
        self.browser = webdriver.Edge(service=EdgeService(EdgeChromiumDriverManager().install()), options=self.options)

    def send_message(self, to, message=""):
        # identify contact / group
        name_argument = f"//span[contains(@title,'{to}')]"
        title = self.wait.until(EC.presence_of_element_located((By.XPATH, name_argument)))
        title.click()

        # many a times class name or other HTML properties changes so keep a track of current class name for input box by using inspect elements
        input_path = '//*[@id="main"]/footer//p[@class="selectable-text copyable-text"]'
        box = self.wait.until(EC.presence_of_element_located((By.XPATH, input_path)))
        # wait for security
        time.sleep(1)
        # send your message followed by an Enter
        box.send_keys(message + Keys.ENTER)
        # wait for security
        time.sleep(2)

    def get_back(self):
        """
        Simulate a back action on browser.
        """
        self.browser.back()

    def login(self):
        try:

            self.browser.get("https://web.whatsapp.com/")
            self.browser.maximize_window()
            self.wait = WebDriverWait(driver=self.browser, timeout=900)

            # wait 5s until leanding page displays
            try :
                landing = WebDriverWait(driver=self.browser, timeout=20).until(
                    EC.presence_of_element_located((By.XPATH, '//div[@class="landing-main"]'))
                )
                if landing:
                    print("Scan QR Code, And then Enter")
                    input()
                    print("Logged In")
            except TimeoutException as e:
                print("No need to authenticate !")

        except Exception as e:
            logging.info("There was some error while logging in.")
            logging.info(sys.exc_info()[0])
            exit()

    def close_and_quit(self):
        """
        Close current browser page and quit browser instance
        """
        self.browser.close()
        self.browser.quit()


#!/usr/bin/python3
# Coding: utf-8
# Author: Rogen
# Description: 專家系統功能集

from os import walk
from tkinter import *
from PIL import ImageTk, Image
from tkinter import ttk, messagebox, font, filedialog
from tkintertable.TableModels import TableModel
from tkintertable.Tables import TableCanvas
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
from GUI_language import *
from Table4Results import TkSheet
from openpyxl import load_workbook
import matplotlib.pyplot as plt
import matplotlib.backends._tkagg
import pandas as pd
import graphviz as gz
import os, re, subprocess, csv, shutil

class RuleStruct(object):
	"""docstring for RuleStruct"""
	def __init__(self, sheet_name='SiteEvaluation'):
		os.environ["PATH"] += os.pathsep + './Graphviz2.38/bin/'
		self.rules_database_path = './Diagnosis_Rules.xlsm'
		self.rule_srtucture_graph = './RuleGraph/'
		self.dataset_path = './Dataset/'
		self.sheet_name = sheet_name
		self.all_diagnosis = []
		self.OpenRuleFile()

	# 讀取規則庫excel
	def OpenRuleFile(self):
		rule_counter = 0
		del_nodes = []
		self.subtitle = {}
		self.subtitle[1] = {}		# Storage chinese subtitle
		self.subtitle[2] = {}		# Storage english subtitle
		self.df = pd.read_excel(self.rules_database_path, header=0, sheet_name=self.sheet_name, encoding='utf_8_sig',
			converters = {'Rule':str, 'Node':int, 'Question':str, 'Yes':str, 'No':str, 'Unknown':str, 'Pictures':str})
		self.rulebase_list = pd.ExcelFile(self.rules_database_path).sheet_names

		for rule_num in map(str, self.df.iloc[:, 0]):					# Rule column
			if re.search(r'Main Branch', rule_num):
				del_nodes.append(rule_counter)
				sp_rule_num = rule_num.split(': ')
				en_subtitle = sp_rule_num[1]
				ch_subtitle = self.df.iloc[rule_counter,9]				# Chinese question column
			elif rule_num == 'nan':
				del_nodes.append(rule_counter)
			else:
				self.subtitle[1][self.df.Node[rule_counter]] = ch_subtitle
				self.subtitle[2][self.df.Node[rule_counter]] = en_subtitle
			rule_counter += 1

		self.df.drop(del_nodes, inplace=True)
		self.df.reset_index(drop=True, inplace=True)

	# 規則關係圖形化 (會搭配Graphviz2.38套件來畫圖，只會在新增、篩除、修改規則時使用)
	def __graph__(self, master):
		def senten_cut(sentence):
			line = []
			temp = []
			count = 1
			senten = ''
			sp_sen = sentence.split(' ')
			for word in sp_sen:
				if count == len(sp_sen):
					temp.append(word)
					line.append(' '.join(temp))
					senten = '\n'.join(line)
				elif count % 6 != 0:
					temp.append(word)
				else:
					line.append(' '.join(temp))
					temp = []
					temp.append(word)
				count += 1
			return(senten)

		# 規則關係圖x、y軸
		def scrolled_canvas(frame):
			w,h = frame.maxsize()
			frame.title('Rule Structure Graph')
			canv = Canvas(frame, relief=SUNKEN)
			sbarV = Scrollbar(frame, orient=VERTICAL, command=canv.yview)
			sbarH = Scrollbar(frame, orient=HORIZONTAL, command=canv.xview)

			im = Image.open(self.rule_srtucture_graph + 'Graph.png')
			im = ExpertSystemFunctions(1,self.sheet_name).image_resize(im, w)
			im2 = ImageTk.PhotoImage(im)
			width,height = self.im.size
			canv.config(scrollregion=(0,0,width,height), width=width, height=height, yscrollcommand=sbarV.set, xscrollcommand=sbarH.set, highlightthickness=0)
			canv.create_image(0,0,anchor="nw",image=im2)

			sbarV.pack(side=RIGHT, fill=Y)
			sbarH.pack(side=BOTTOM, fill=X)
			canv.pack(side=LEFT, expand=YES, fill=BOTH)

		dot = gz.Digraph()
		for row in range(len(self.df.index)):
			l = self.df.iloc[row].tolist()
			dot.node(str(l[1]), senten_cut(str(l[1])+': '+l[2])) # Original_Node

			if str(l[3]) == 'nan' or str(l[4]) == 'nan':
				pass
			else:
				l[3] = l[3].replace('#','')
				l[4] = l[4].replace('#','')

				if re.search(r'\d+:.+', l[3]): # Yes_Node
					sp_ = l[3].split(':')
					dot.node(sp_[0], senten_cut(l[3]))
					dot.edge(str(l[1]), sp_[0], label='yes')
				else:
					dot.edge(str(l[1]), l[3], label='yes')

				if re.search(r'\d+:.+', l[4]): # No_Node
					sp_ = l[4].split(':')
					dot.node(sp_[0], senten_cut(l[4]))
					dot.edge(str(l[1]), sp_[0], label='No')
				else:
					dot.edge(str(l[1]), l[4], label='No')

		dot.render(self.rule_srtucture_graph + 'Graph', format='png')
		# dot.view('test')
		self.rule_win = Toplevel(master)
		scrolled_canvas(self.rule_win)

	# 診斷結果表格顯示
	def __table__(self, master):
		try:
			if self.rule_win.state() == 'normal':
				pass
		except:
			data = {}
			colnums = ['Rule','Node','Question','Yes','No']
			rule_dict = self.df.ix[:,'Rule':'No']

			for r in range(len(rule_dict.index)):
				plice = {}
				for c in range(len(rule_dict.columns)):
					if rule_dict.iloc[r,c] == 'nan':
						plice[rule_dict.columns[c]] = ' '
					else:
						plice[rule_dict.columns[c]] = rule_dict.iloc[r,c]
				data[str(r)] = plice

			self.rule_win = Toplevel(master)
			frame = Frame(self.rule_win)
			frame.pack()
			model = TableModel()

			for key in colnums:
				model.addColumn(key) #sort the columns

			model.importDict(data)
			table = TableCanvas(frame, model=model, width=800, height=500, rowheight=20, editable=False, cellbackgr='#E3F6CE', reverseorder=1, rowselectedcolor='yellow')
			table.createTableFrame()
			table.sortTable(columnName='Rule')

	def __destroy__(self):
		try:
			if self.rule_win.state() == 'normal':
				self.rule_win.destroy()
		except:
			pass

class ExpertSystemFunctions(RuleStruct):
	# 全域變數宣告
	global _rulebase_diagnosis_recode, _rulebase_diagnosis_done, _answer_dict
	_rulebase_diagnosis_recode = {}
	_rulebase_diagnosis_done = []
	_answer_dict = {}

	def __init__(self, ver, sheet_name, code):
		super(ExpertSystemFunctions, self).__init__(sheet_name)
		self.sheet_name = sheet_name
		self.language = ver
		self.internal_code = code
		self.answer_store = {}
		self.answer_diagnosis = ''
		self.query = ''
		self.Yes_score = 0
		self.No_score = 0
		self.tree_iterater = 0
		self.optiontree_iterater = 0
		self.photo_image_counter = 0
		self.note_pointer = 0
		self.save_path = '.\\Save'
		self.photo_path = '.\\Photo\\' + self.sheet_name
		self.photo_temp = '.\\Photo\\TempFile'
		self.image_nonavailable = '.\\Photo\\Interface\\img_not_available.png'
		self.hidden_answer = '.\\Temp\\Answers.TXT'
		self.GuiInitiation()

	# 專家系統啟動前超參數設定
	def GuiInitiation(self):
		if self.language == 1:
			ch = Chinese()
			self.interface = ch.ES_GUI_Interface()
			self.Q_list = self.df.中文問題

		elif self.language == 2:
			en = English()

			self.interface = en.ES_GUI_Interface()
			self.Q_list = self.df.Question

		self.cur_node = self.df.Node[0]
		self.query = self.Q_list[0]

	# 專家系統離開設定
	def GuiClose(self):
		# Update the SiteEva_Table.csv
		self.siteval_df = pd.read_csv('./Dataset/SiteEva_Table.csv')
		with open('CropVISTMapInfo.txt','r',encoding='utf-8') as file:
			lines = file.readlines()

		inter_code = lines[6].split(r' = ')[1].replace('\n','')
		index = self.siteval_df.index[self.siteval_df['Internal_Code'] == inter_code]

		center_location = re.split(r'[,|=| ]+',lines[3])
		NS_direction = lines[4].split(' = ')[1].replace('\n','')
		EW_direction = lines[5].split(' = ')[1].replace('\n','')
		self.siteval_df.iloc[index,2:5] = center_location[2:5]
		self.siteval_df.iloc[index,6:9] = center_location[6:9]
		self.siteval_df.iloc[index,13:15] = [EW_direction,NS_direction]
		self.siteval_df.to_csv('./Dataset/SiteEva_Table.csv', index=False, encoding='utf_8_sig')
		print(center_location,EW_direction,NS_direction,inter_code)

		# Delete the figures of TempFile folder
		for root, dirs, files in walk(self.photo_temp):
			for f in files:
				fullpath = os.path.join(root,f)
				if os.path.isfile(fullpath):
					os.remove(fullpath)

		# Delete the diagnosed csv files
		for root, dirs, files in walk(self.save_path):
			for f in files:
				fullpath = os.path.join(root,f)
				if os.path.isfile(fullpath) and re.search(r'.+_Diagnosis\.csv', f):
					os.remove(fullpath)

		# Listing the full diagnosed results of rulebases into excel file
		# self.diagnosis_export()

	#---------- Photograph Controled Area ----------#
	# 第一張圖片設定
	def pri_photo(self):
		if str(self.df.Pictures[0]) == 'nan':
			self.photo_images = [self.image_nonavailable]
		else:
			priphoto_folder = os.path.join(self.photo_path, self.df.Pictures[0])
			exist = self.node_folder_exist(priphoto_folder)
			if exist:
				self.photo_images = [os.path.join(priphoto_folder, _) for _ in os.listdir(priphoto_folder)]
				if len(self.photo_images) == 0:
					self.photo_images = [self.image_nonavailable]
			else:
				self.photo_images = [self.image_nonavailable]

		self.im = Image.open(self.photo_images[0])
		image_file = ImageTk.PhotoImage(self.image_resize(self.im))
		self.figure_title(self.photo_images[0])

		return(image_file)

	# 專家系統第一張圖片設定
	def figure_iterator(self,state):
		if len(self.photo_images) < 2:
			pass
		else:
			if state == 'forward' and self.photo_image_counter < len(self.photo_images)-1:
				self.photo_image_counter += 1
			elif state == 'back' and self.photo_image_counter > 0:
				self.photo_image_counter -= 1

			self.im = Image.open(self.photo_images[self.photo_image_counter])
			self.iterative_image = ImageTk.PhotoImage(self.image_resize(self.im))

			self.fig_label.config(image=self.iterative_image)
			self.fig_label.update_idletasks()
			self.figure_title(self.photo_images[self.photo_image_counter])

	# 下一張圖片
	def next_figure(self):
		self.photo_image_counter = 0
		self.photo_folder = self.df.Pictures[self.df.Node == self.cur_node].tolist()[0]

		if str(self.photo_folder) == 'nan':
			self.photo_images = [self.image_nonavailable]
		else:
			self.photo_fullpath = os.path.join(self.photo_path, self.photo_folder)
			if re.match(r'^N\d\d$',self.photo_folder):
				try:
					self.temp_path = os.path.join(self.photo_temp, self.photo_folder)
					self.photo_images = [os.path.join(self.temp_path, _) for _ in os.listdir(self.temp_path)]
				except FileNotFoundError as e:
					self.photo_images = ''
			else:
				exist = self.node_folder_exist(self.photo_fullpath)
				if exist:
					self.photo_images = [os.path.join(self.photo_fullpath, _) for _ in os.listdir(self.photo_fullpath)]
				else:
					self.photo_images = [self.image_nonavailable]

		# If the node's folder exists, there are no picture in folder
		if len(self.photo_images) == 0:
			self.photo_images = [self.image_nonavailable]

		self.im = Image.open(self.photo_images[0])
		self.next_image = ImageTk.PhotoImage(self.image_resize(self.im))

		self.fig_label.config(image=self.next_image)
		self.fig_label.update_idletasks()
		self.figure_title(self.photo_images[0])

	# 圖片控制(放大、截圖、移動等)
	def figure_magnification(self, image):
		# Setting figure size and quality
		f = Figure(figsize=(5,3), dpi=150)
		a = f.add_subplot(111)

		# Plotting figure
		# img_arr = matplotlib.image.imread('figure path')
		a.imshow(image)
		a.axis('off')
		a.axes.get_xaxis().set_visible(False)
		a.axes.get_yaxis().set_visible(False)

		# Display the graphics on the tkinter window
		canvas = FigureCanvasTkAgg(f, master=self.photo_win)
		canvas.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=1)

		# Putting the toolbar of matplotlib graphics on the tkinter window
		toolbar = NavigationToolbar2Tk(canvas, self.photo_win)
		toolbar.update()
		canvas._tkcanvas.pack(side=BOTTOM, fill=BOTH, expand=True)

	# 判斷資料夾是否存在
	def node_folder_exist(self, path):
		result = 1 if os.path.exists(path) else 0
		return(result)

	# 圖像尺寸縮放
	def image_resize(self, image):
		w, h = image.size
		f1 = self.label_width/w
		f2 = self.label_height/h
		factor = min([f1, f2])
		width = int(w*factor)
		height = int(h*factor)
		return(image.resize((width, height), Image.ANTIALIAS))

	#---------- Query Controled Area ----------#
	# 圖片路徑
	def figure_title(self,name):
		self.figframe.config(text=name)

	# 問題標題
	def query_title(self,note):
		def branch(n):
			return(self.subtitle[self.language][n])

		if len(str(note)) == 1: 	#main branch
			return(branch(note))
		else:						#secondary branch
			m = int(re.match(r'^(\d)',str(note)).group(0))
			main_branch = branch(m)
			sec_branch = branch(note)

			if sec_branch == '':
				return(main_branch)
			else:
				return('%s-%s' % (main_branch,sec_branch))

	# 初始診斷問題
	def pri_query(self):
		self.unknown_button_control(self.cur_node)

		# The node is been hidden
		if str(self.df.Hidden_Answer[self.df.Node == self.cur_node].tolist()[0]) != 'nan':
			ans, error = self.note_hidden(0)
			if error == 0:		# Hidden node have answer
				self.user_answer.set(ans)
				self.next_step()
			else:				# Hidden node don't have answer, but user loaded previous study
				self.loading_answer()

		# The node isn't been hidden
		else:
			self.loading_answer()

	# 上一步
	def back_step(self):
		array = [k for k in sorted(self.answer_store.keys()) if int(k) % 100 != 0]

		self.cur_node = int(array[-1])
		self.next_node = self.cur_node
		self.query = self.answer_store[str(self.cur_node)][1]
		self.querylabel.config(text=self.query)
		del self.answer_store[str(self.cur_node)]		# delete the current node
		self.next_figure()
		self.figure_descript()
		self.query_descript()

		# Button crontrol
		self.r1.config(state=ACTIVE)
		self.r2.config(state=ACTIVE)
		self.next_button.config(state=ACTIVE)
		self.submit_button.config(state=DISABLED)
		self.unknown_button_control(self.cur_node)

		self.note_pointer -= 1
		if self.note_pointer == 0:
			self.back_button.config(state=DISABLED)

		try:
			if self.rulepath_win.state() == 'normal':
				self.option_record('onebyone',-1)		# Delete one answer of rule path
		except:
			pass

	#---- Record the current note info and give next note ----#
	# 下一步
	def next_step(self):
		yesScore = '-'; noScore = '-'; diag = '-'

		if self.user_answer.get() == 'None':
			messagebox.showerror('ERROR', 'The option is empty!')
		else:
			curIdx = self.df.index[self.df.Node == self.cur_node].tolist()[0]

			# Cumulative yes/no score
			if self.user_answer.get() == 'yes':
				self.next_node = self.df.Yes[curIdx]

				if str(self.df.Yes診斷[curIdx]) != 'nan':
					if self.language == 1:
						diag = self.df.Yes診斷[curIdx]
					elif self.language == 2:
						# If the english version of diagnosis is presented, it will be changed...
						diag = self.df.Yes診斷[curIdx]

				if str(self.df.Yes_score[curIdx]) != 'nan':
					self.Yes_score += self.df.Yes_score[curIdx]
					yesScore = self.df.Yes_score[curIdx]

			elif self.user_answer.get() == 'no':
				self.next_node = self.df.No[curIdx]

				if str(self.df.No診斷[curIdx]) != 'nan':
					if self.language == 1:
						diag = self.df.No診斷[curIdx]
					elif self.language == 2:
						# If the english version of diagnosis is presented, it will be changed...
						diag = self.df.No診斷[curIdx]

				if str(self.df.No_score[curIdx]) != 'nan':
					self.No_score += self.df.No_score[curIdx]
					noScore = self.df.No_score[curIdx]

			else:
				self.next_node = self.df.Unknown[curIdx]

			# Recode the solution way of each note
			solution = '-' if str(self.df.處理對策[curIdx]) == 'nan' else self.df.處理對策[curIdx]
			diag = self.answer_diagnosis if self.answer_diagnosis != '' else diag

			self.answer_store[str(self.cur_node)] = [self.cur_node, self.query, str(self.user_answer.get()), yesScore, noScore, diag, solution]
			self.next_node = int(self.next_node.replace('#',''))

			# Button controled
			if self.next_node == 0:
				self.done()
			self.unknown_button_control(self.next_node)
			self.back_button.config(state=ACTIVE)
			self.analyze_button.config(state=DISABLED)

			try:
				if self.rulepath_win.state() == 'normal':
					self.option_record('onebyone',1)		# Inserting one rule in the rule path
			except:
				pass

			# the Order of code can not change!!!
			self.answer_diagnosis = ''
			self.next_query(curIdx)
			self.query_descript()
			self.figure_descript()
			self.note_pointer += 1

	#---- Goto the next query, and resetting the figures and buttons ----#
	# 下一個診斷問題
	def next_query(self, curIdx):
		next_node_idx = self.df.index[self.df.Node == self.next_node].tolist()[0]

		if str(self.Q_list[next_node_idx]) == 'nan':
			# Ending this section of all diagnosis
			self.querylabel.config(text=self.interface['diag_complete']['done'])
		else:
			# Hidden node find corresponding answer
			if str(self.df.Hidden_Answer[next_node_idx]) != 'nan':
				ans, error = self.note_hidden(next_node_idx)
				if error == 0:
					# Entry the chapter of diagnosis after hidden node
					if self.next_node % 100 == 0:
						self.diag_summary(next_node_idx)
					else:
						self.query = self.Q_list[next_node_idx]
						self.cur_node = self.df.Node[next_node_idx]
						self.user_answer.set(ans)
						self.next_step()

			# Error replace hidden node not find corresponding answer
			if str(self.df.Hidden_Answer[next_node_idx]) == 'nan' or error == 1:
				# Entry the chapter of diagnosis
				if self.next_node % 100 == 0:
					self.diag_summary(next_node_idx)
				else:
					self.cur_node = self.df.Node[next_node_idx]
					self.query = self.Q_list[next_node_idx]
					self.querylabel.config(text=self.query)

			querytitle = self.query_title(self.cur_node)
			self.queryframe.config(text=querytitle)
			self.user_answer.set(None)
			self.next_figure()
			self.loading_answer()

	# 診斷結束
	def done(self):
		self.submit_button.config(state=ACTIVE)
		self.next_button.config(state=DISABLED)
		self.r1.config(state=DISABLED)
		self.r2.config(state=DISABLED)
		self.r3.config(state=DISABLED)
		self.querylabel.config(text=self.interface['diag_complete']['done'])

	# "分析"按鈕控制
	def analyze_button_control(self, option):
		if option == 1 and self.sheet_name == 'SiteEvaluation' and (self.cur_node == 1101 or self.cur_node == 1201):
			self.analyze_button.config(state=ACTIVE)
			self.next_button.config(state=DISABLED)
		elif option == 2:
			self.analyze_button.config(state=DISABLED)
			self.next_button.config(state=ACTIVE)

	# "未知"按鈕控制
	def unknown_button_control(self, note):
		if str(self.df.Unknown[self.df.Node == note].tolist()[0]) == 'nan':
			self.r3.config(state=DISABLED)
		else:
			self.r3.config(state=ACTIVE)

	# 診斷結果分數計算
	def diag_summary(self,next_node_idx):
		self.cur_node = self.df.Node[next_node_idx]
		self.query = self.Q_list[next_node_idx]

		if self.df.Yes_score[next_node_idx] != 0 and str(self.df.Yes_score[next_node_idx]) != 'nan':
			y = round(self.Yes_score*100/self.df.Yes_score[next_node_idx])
			y = [100 if y >= 100 else y][0]
		else:
			y = 0

		if self.df.No_score[next_node_idx] != 0 and str(self.df.No_score[next_node_idx]) != 'nan':
			n = round(self.No_score*100/self.df.No_score[next_node_idx])
			n = [100 if n >= 100 else n][0]
		else:
			n = 0

		self.Yes_score = 0
		self.No_score = 0
		self.answer_store[str(self.cur_node)] = [self.cur_node, self.query, '*', str(y)+'%', str(n)+'%', '-', '-']

		# It's end note, but it is deprecated
		if self.df.No[next_node_idx] == 'Max Possible' and str(self.df.Yes[next_node_idx]) == 'nan':
			self.done()

		elif self.df.No[next_node_idx] == 'Max Possible' and str(self.df.Yes[next_node_idx]) != 'nan':
			self.next_node = self.df.Yes[next_node_idx]
			self.next_node = int(self.next_node.replace('#',''))
			next_node_idx = self.df.index[self.df.Node == self.next_node].tolist()[0]

			# It's end note (#node:0)
			if self.df.Node[next_node_idx] == 0:
				self.done()
			else:
				if str(self.df.Hidden_Answer[next_node_idx]) != 'nan':
					ans, error = self.note_hidden(next_node_idx)
					if error == 0:
						self.cur_node = self.df.Node[next_node_idx]
						self.query = self.Q_list[next_node_idx]
						self.user_answer.set(ans)
						self.next_step()

				if str(self.df.Hidden_Answer[next_node_idx]) == 'nan' or error == 1:
					self.query = self.Q_list[next_node_idx]
					self.cur_node = self.df.Node[next_node_idx]
					self.querylabel.config(text=self.query)
					self.unknown_button_control(self.next_node)
					self.loading_answer()

	#---------- Output Controled Area ----------#
	# 儲存診斷結果
	def save_diagnosis(self):
		mode = 'a' if os.path.exists('%s/Diagnosis_%s.xlsx' % (self.save_path, self.internal_code)) else 'w'

		with pd.ExcelWriter('%s/Diagnosis_%s.xlsx' % (self.save_path, self.internal_code), engine='openpyxl', mode=mode) as writer:
			save_df = pd.read_csv('%s/%s_Diagnosis.csv' % (self.save_path, self.sheet_name), delimiter=",")
			save_df.to_excel(writer, sheet_name=self.sheet_name, index = None)
			writer.save()

		self.save.config(state=DISABLED)

	# 所有規則庫診斷結果匯出成一個CSV檔
	def diagnosis_export(self):
		# Export full rulebased diagnosis into csv file
		file = self.save_path+'/Diagnosis-Export.csv'
		flag = [True for f in os.listdir(self.save_path) if re.search('tmp-.+',f)]
		if not True in flag:
			messagebox.showinfo('ERROR','No any diagnosed output!')
		else:
			if os.path.exists(file):
				os.remove(file)
			with open(file, 'w+', encoding='utf_8_sig', newline='') as d:
				out_csv = csv.writer(d, quoting=csv.QUOTE_ALL)
				for i in self.rulebase_list:
					if os.path.exists(self.save_path+'/tmp-'+i):
						out_lines = [
							[self.interface['ruledb_name'][i]],
							['-'*50],
							[self.interface['done_title']['diagnosis'], self.interface['done_title']['yescore'], self.interface['done_title']['noscore']],
							['-'*50]
						]
						out_csv.writerows(out_lines)

						with open(self.save_path+'/tmp-'+i, 'r', encoding='utf_8_sig', newline='') as t:
							data = csv.reader(t, delimiter='\t')
							out_csv.writerows(data)
						out_csv.writerow(['_'*50])
						out_csv.writerow(['\n'*2])
						os.remove(self.save_path+'/tmp-'+i)

			# Including the "Diagnosis-Export" file into excel file
			# with pd.ExcelWriter('%s/Diagnosis_%s.xlsx' % (self.save_path, self.internal_code), engine='openpyxl', mode='a') as writer:
			# 	diagnosis_df = pd.read_csv(file, delimiter='\t')
			# 	diagnosis_df.to_excel(writer, sheet_name='Diagnosis-Export', index = None)
			# 	writer.save()
			# 	os.remove(file)

			messagebox.showinfo('INFO','Output have done.')

	# 診斷結果表格設置
	def diagnosis_done(self,tree):
		for key in sorted(self.answer_store.keys()):
			if self.answer_store[key][2] == '*' or len(key) == 1:
				branchs = 'main_branch' if len(key) == 1 else 'secondary_branch'
				tree.insert('',self.tree_iterater,values=['']*7)
				tree.insert('',self.tree_iterater+1,values=self.answer_store[key][:7],tags=(branchs,))
				self.tree_iterater += 2
			else:
				if self.answer_store[key][2] == 'no' or self.answer_store[key][2] == 'unknown':
					self.answer_store[key][6] = '-'
				tree.insert('',self.tree_iterater,values=self.answer_store[key][:7])
				self.tree_iterater += 1

		with open(self.save_path+'/tmp-'+self.sheet_name, 'w+', encoding='utf_8_sig') as f:
			tag = 0
			for key in sorted(self.answer_store.keys()):
				ans = self.answer_store[key]
				if ans[5] != '-':
					f.write('\t'.join(map(str,[ans[5],ans[3],ans[4]])) + '\n')
					tag = 1
				elif ans[2] == '*':
					# f.write('\n')
					f.write('\t'.join(map(str,[ans[1],ans[3],ans[4]])) + '\n')
					tag = 1
			if tag == 0:
				f.write(self.interface['done_unknown']['unknown'])
				f.write('\n')

		# Save diagnosis results in csv file
		with open(self.save_path+'/'+self.sheet_name+'_Diagnosis.csv', 'w', encoding='utf_8_sig', newline='') as out_csv:
			out_writer = csv.writer(out_csv, quoting=csv.QUOTE_ALL)
			out_writer.writerow(['Node','Question','Answer','Yes score','No score','Diagnosis','Solution'])
			for key in sorted(self.answer_store.keys()):
				out_writer.writerow(map(str,self.answer_store[key]))

		# Rulebase OptioinMenu Controled Area
		if self.sheet_name == 'SiteEvaluation':
			for i in range(len(self.rulebase_list)):
				s = ACTIVE if i == 1 else DISABLED
				self.next_rulebase['menu'].entryconfigure(i, state=s)

		elif self.sheet_name == 'Soils':
			for j in range(len(self.rulebase_list)):
				s = DISABLED if j <= 1 else ACTIVE
				self.next_rulebase['menu'].entryconfigure(j, state=s)

		else:
			for index in _rulebase_diagnosis_done+[0]:			# Adding "[0]" into list because the 'SiteEvaluate' rulebase does not include in list.
				self.next_rulebase['menu'].entryconfigure(index, state=DISABLED)

		if len(_rulebase_diagnosis_done) == 4:
			self.submit.config(state=DISABLED)

		# Recodeing this diagosed results
		_rulebase_diagnosis_recode[self.sheet_name] = self.answer_store

	# 診斷結果表格(使用TkSheet外部套件設置，沒用到)
	def table4result(self):
		result = []; tag = []; i = 0
		for key in sorted(self.answer_store.keys()):
			if self.answer_store[key][2] == '*' or len(key) == 1:
				i+=1
				branchs = 'main_branch' if len(key) == 1 else 'secondary_branch'
				result.append(['']*7)
				tag.append([i,branchs])

			result.append(self.answer_store[key])
			i+=1

		ts = TkSheet(result, tag, self.interface)
		ts.mainloop()

	# 將儲存的結果用excel開啟 (方便使用者查閱)
	def open_csv_excel(self):
		os.startfile("%s/Save/%s_Diagnosis.csv" % (os.getcwd(),self.sheet_name))
		# command_line = 'C:/Program Files/Microsoft Office/root/Office16/EXCEL.EXE %s/Save/%s_Diagnosis.csv' % (os.getcwd(),self.sheet_name)
		# subprocess.Popen(command_line)

	# 給新增、刪除、修改規則使用 (沒用到)
	def diagnosis_node_index(self,index):
		No_Node = self.df.No.dropna().tolist()
		No_Node.remove('Max Possible')
		yesDiag = [i for i in self.df.Yes.dropna().tolist() if int(re.search(r'#(\d+)',i).group(1)) == index.get()]
		noDiag = [i for i in No_Node if int(re.search(r'#(\d+)',i).group(1)) == index.get()]
		return(yesDiag, noDiag)

	#---------- Other Controled Area ----------#
	# 紀錄使用者回答規則路徑
	def option_record(self, condiction, step=None):
		if condiction == 'showhand':
			count = 0
			for key in sorted(self.answer_store.keys()):
				if int(key) % 100 != 0:
					self.optiontree.insert('','end',values=self.answer_store[key][:3])
				else:
					count += 1
			self.optiontree_iterater = len(self.answer_store)-count
		else:
			if step == 1:
				if self.cur_node % 100 != 0:
					self.optiontree.insert('',self.optiontree_iterater,values=self.answer_store[str(self.cur_node)][:3])
					self.optiontree_iterater += 1
			else:
				tree_items = self.optiontree.get_children()
				self.optiontree.delete(tree_items[-1])
				self.optiontree_iterater -= 1

	# 處理規則中隱藏的節點，加速專家系統的診斷
	def note_hidden(self,note_index):
		note_hindden_error = 0
		negative_flag = 0
		answer = ''
		answer_list = {'Y':'yes','N':'no','U':'unknown'}
		opposite_answer = {'yes':'no','no':'yes','unknown':'unknown'}

		correspondence = self.df.Hidden_Answer[note_index]
		sp_correspondence = correspondence.split('-')

		if re.match('Answer', sp_correspondence[0]):
			csvfile = pd.read_csv(self.hidden_answer, delimiter=',')
			index = csvfile.index[csvfile['Q ID'] == int(sp_correspondence[1])].tolist()[0]
			answer = csvfile.iloc[index,3]
			answer = answer_list[answer]
			if re.match(r'[yes|no]',answer) and str(csvfile.iloc[index,4]) != 'nan':
				self.answer_diagnosis = csvfile.iloc[index,4]
		else:
			if re.match('Negative', sp_correspondence[0]):
				rulebase = sp_correspondence[0].split(' ')[1]
				negative_flag = 1
			else:
				rulebase = sp_correspondence[0]

			note = sp_correspondence[1]

			# If the note's answer don't recode in the base, progress must search in the dictionary of rulebase diagnosis
			if rulebase != self.sheet_name:
				dictionary = _rulebase_diagnosis_recode[rulebase]

				# To confirm whether the correspond answer exists in dictory or not
				try:
					answer = opposite_answer[dictionary[note][2]] if negative_flag == 1 else dictionary[note][2]
				except:
					note_hindden_error = 1
			else:
				try:
					answer = opposite_answer[self.answer_store[note][2]] if negative_flag == 1 else self.answer_store[note][2]
				except:
					note_hindden_error = 1

		return(answer, note_hindden_error)

	# 問題的原因描述
	def query_descript(self):
		self.query_desc_text.delete(1.0,END)
		texture = self.df.問題說明[self.next_node == self.df.Node].tolist()[0]
		if str(texture) == 'nan':
			self.query_desc_text.insert(1.0,'')
		else:
			self.query_desc_text.insert(1.0,texture)

	# 圖片的內容描述
	def figure_descript(self):
		self.fig_desc_text.delete(1.0,END)
		texture = self.df.圖片說明[self.next_node == self.df.Node].tolist()[0]
		if str(texture) == 'nan':
			self.fig_desc_text.insert(1.0,'')
		else:
			self.fig_desc_text.insert(1.0,texture)

	# 程序重啟動
	def program_restart(self):
		super().__destroy__()												# Destroy rule structure graph
		self.windows.destroy()												# Destroy main windows
		self.__init__(self.language, self.sheet_name, self.internal_code)	# To get the newest dataframe
		self.gui()

	# 下一個診斷規則庫
	def next_rulesbase_diag(self):
		sheet = self.rulebase.get()
		if sheet == '':
			messagebox.showwarning('WARNNING','You must choose one of rulebases!')
		else:
			_rulebase_diagnosis_done.append(self.rulebase_list.index(sheet))
			self.windows.destroy()											# Destroy windows must be the first step
			self.sheet_name = sheet
			self.__init__(self.language, self.sheet_name, self.internal_code)
			self.gui()

	# 外部程式連接 (UVA跟衛星影像圖分析程式)
	def external_link(self):
		if self.language == 1:
			CropVISTMapInfo = 'CropVISTMapInfoTWN.exe'
			UVA_Analysis = 'UAV_Analysis.exe'
		elif self.language == 2:
			CropVISTMapInfo = 'CropVISTMapInfoENG.exe'
			UVA_Analysis = 'UAV_Analysis.exe'

		exe = UVA_Analysis if str(self.cur_node) == '1101' else CropVISTMapInfo
		# p = subprocess.run(exe, shell=True)
		p = subprocess.call(exe, shell=True)

		# Checking progress does exist or not
		# command_line = 'TASKLIST', '/FI', 'imagename eq %s.exe' % exe
		# output = subprocess.check_output(command_line).decode()
		# last_line = output.strip().split('\r\n')[-1]
		# if not last_line.lower().startswith(exe.lower()):
		# 	self.program_restart()

		# Move figure of UVA/VIST to TempFile folder
		for f in os.listdir(self.photo_temp):
			if os.path.isfile(os.path.join(self.photo_temp,f)):
				findout = re.search(r'[NDVI|NDWI|SWC|\d+]_(\d)-(N\d+)',f)
				if findout:
					note_folder = findout.group(2)
					if not os.path.exists('%s/%s'% (self.photo_temp,note_folder)):
						os.mkdir('%s/%s'% (self.photo_temp,note_folder))
					shutil.move(os.path.join(self.photo_temp,f),os.path.join(self.photo_temp,note_folder,f))

		self.next_figure()
		self.next_button.config(state=ACTIVE)

	# 外部診斷結果匯入
	def save_import(self):
		temp = {}
		file = filedialog.askopenfilename(initialdir = "./Save", title='Select Input file', filetype=[("excel file","*.xls"),("excel file","*.xlsx")])
		xl = pd.ExcelFile(file)
		for sheet in xl.sheet_names:
			df = xl.parse(sheet)
			df = df.drop(df.index[df.Answer == '*'])
			df = df.reset_index(drop=True)
			df = df[['Node','Answer']]
			for i in range(len(df)):
				temp[df.Node[i]] = df.Answer[i]
			_answer_dict[sheet] = temp
		self.program_restart()

	# 外部診斷結果查詢
	def loading_answer(self):
		try:
			answer = _answer_dict[self.sheet_name][self.cur_node]
			self.user_answer.set(answer)

		except Exception as e:
			pass

	# 衛星航拍圖開啟介面
	def open_temp_images(self):
		def openimage():
			types = imagename.get()

			if types == 'None':
				messagebox.showerror('ERROR','Please choose which image would you like to view!')
			else:
				if types == 'uva':
					floder = 'N11'
				elif types == 'ndvi':
					floder = 'N12'
				elif types == 'ndwi':
					floder = 'N13'
				elif types == 'swc':
					floder = 'N15'
				elif types == 'irrig':
					floder = 'N16'
				else:
					floder = 'N17'

				images = [os.path.join(self.photo_temp,floder, _) for _ in os.listdir(os.path.join(self.photo_temp,floder))]
				for image in images:
					im = Image.open(image)
					im.show()

		showtempimages = Toplevel(self.windows)
		showtempimages.title('Show Figures')
		showtempimages.geometry('320x120')

		imagename = StringVar()
		imagename.set(None)

		option_frame = LabelFrame(showtempimages, text='Please choose one type of figure')
		option_frame.place(x=10,y=10)

		for folder in ['N11','N12','N13','N15','N16','N17']:
			if not os.path.exists(os.path.join(self.photo_temp, folder)):
				os.mkdir('./%s/%s' % (self.photo_temp,folder))

			locals()['%s_state' % folder] = ACTIVE if os.listdir(os.path.join(self.photo_temp, folder)) else DISABLED

		uva = Radiobutton(option_frame, text='UVA', variable=imagename, value='uva', state=locals()['%s_state' % 'N11'])
		uva.grid(row=0, column=0, padx=3, pady=1)
		ndvi = Radiobutton(option_frame, text='NDVI', variable=imagename, value='ndvi', state=locals()['%s_state' % 'N12'])
		ndvi.grid(row=0, column=1, padx=3, pady=1)
		ndwi = Radiobutton(option_frame, text='NDWI', variable=imagename, value='ndwi', state=locals()['%s_state' % 'N13'])
		ndwi.grid(row=0, column=2, padx=3, pady=1)
		swc = Radiobutton(option_frame, text='SWC', variable=imagename, value='swc', state=locals()['%s_state' % 'N15'])
		swc.grid(row=1, column=0, padx=3, pady=1)
		irrig = Radiobutton(option_frame, text='Irrigation', variable=imagename, value='irrig', state=locals()['%s_state' % 'N16'])
		irrig.grid(row=1, column=1, padx=3, pady=1)
		msavi = Radiobutton(option_frame, text='MSAVI', variable=imagename, value='msavi', state=locals()['%s_state' % 'N17'])
		msavi.grid(row=1, column=2, padx=3, pady=1)

		showbutton = Button(showtempimages, text='Show Figure',command=openimage)
		showbutton.place(x=200,y=90)


import numpy as np
import pygame as pyg
from math import cos, sin
from src.objects.point import Point

class Cube(Point):

    def __init__(self, x: int, y: int, z: int, side:int, rotation: str = 'xyz', static: bool = False) -> None:
        super().__init__(x, y, z, rotation, static)

        self.center = self.vector

        self.vertexes = [Point(
            side*(1 if i in (1, 2, 5, 6) else 0) + x-side/2,
            side*(1 if i in (2, 3, 6, 7) else 0) + y-side/2,
            side*(1 if i in (4, 5, 6, 7) else 0) + z-side/2,
            rotation, static, self.center
        ) for i in range(8)]

        for j in (0, 2):
            for i in (1, 3, 4+j):
                self.vertexes[j].attachedPoints.append(self.vertexes[i])

            for i in (1+j, 4, 6):
                self.vertexes[j+5].attachedPoints.append(self.vertexes[i])

    def update(self, angle: float) -> None:
        for i in self.vertexes:
            i.update(angle)

        return super().update(angle)

    def draw_ortho(self, screen: pyg.Surface, scale: int) -> None:
        for i in self.vertexes:
            i.draw_ortho(screen, scale)

        return super().draw_ortho(screen, scale)


__author__ = 'eladron'

import folium

#variables
lat  = 32.12830
long = 34.79269
loc = [lat,long]
zs   = 18
tls  = 'Stamen Terrain'
map_path = 'App2-Leaflet_Webmaps/map_test.html'

map = folium.Map(location=loc, zoom_start = zs)
map.simple_marker(location=loc, popup='My address' , marker_color='purple')

map.create_map(map_path)


# exclude from patching
DONT_PATCH_MY_STAR_IMPORTS = True
from mods.RiftOptimizer.Patcher import *

import threading
import queue
import Level
import LevelGen
import inspect
import logging
import SteamAdapter
import Game
import os
import pygame
import dill as pickle

import mods.RiftOptimizer.RiftOptimizer as RiftOptimizer

####################################################
# Importing RiftWizard.py                          |
# Credit to trung on discord                       |
#                                                  |
#----------------------------------------------    |
import inspect #                                   |
def get_RiftWizard(): #                            |
    # Returns the RiftWizard.py module object      |
    for f in inspect.stack()[::-1]: #              |
        if "file 'RiftWizard.py'" in str(f): #     |
            return inspect.getmodule(f[0]) #       |
     #                                             |
    return inspect.getmodule(f[0]) #               |
#                                                  |
RiftWizard = get_RiftWizard() #                    |
#                                                  |
#                                                  |
####################################################

import sys

need_to_setup_print_logs = False
if 'print' in sys.argv:
    need_to_setup_print_logs = True

# Level.py calls both logging.debug and Logger.debug which are distinct apparently
original_logging_debug = logging.debug
def logging_debug(self, *args, **kwargs):
    channel.put((original_logging_debug, (self, *args, *kwargs)))

Level.logging.debug = logging_debug
logging.debug = logging_debug

original_debug = logging.Logger.debug
def log_debug(self, *args, **kwargs):
    channel.put((original_debug, (self, *args, *kwargs)))

def local_setup_logging(self):
    # Clear handlers if they exist
    for h in list(self.combat_log.handlers):
        self.combat_log.removeHandler(h)

    if need_to_setup_print_logs:
        self.combat_log.addHandler(logging.StreamHandler(sys.stdout))

    self.combat_log.addHandler(logging.FileHandler(os.path.join(self.logdir if self.logdir else '.', 'combat_log.txt'), mode='a'))

LevelGen.level_logger.debug = log_debug.__get__(LevelGen.level_logger,logging.Logger)
RiftWizard.mem_log.debug = log_debug.__get__(RiftWizard.mem_log,logging.Logger)
SteamAdapter.stats_log.debug = log_debug.__get__(SteamAdapter.stats_log,logging.Logger)

def setup_logging(self, logdir, level_num):
    self.combat_log = logging.getLogger("damage")
    self.combat_log.setLevel(logging.DEBUG)
    self.combat_log.propagate = False
    self.combat_log.debug = log_debug.__get__(self.combat_log,logging.Logger)

    self.logdir = logdir
    self.level_no = level_num

    channel.put((local_setup_logging, (self)))

Level.Level.setup_logging = setup_logging

original_next_log_turn = Level.Level.next_log_turn
def next_log_turn(self, *args, **kwargs):
    channel.put((original_next_log_turn, (self, *args, *kwargs)))
Level.Level.next_log_turn = next_log_turn

def write_finalize_level(stats, run_number, level_number):
    filename = os.path.join('saves', str(run_number), 'stats.level_%d.txt' % level_number)

    dirname = os.path.dirname(filename)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    with open(filename, 'w') as outfile:
        outfile.write(''.join(stats))

def finalize_level(self, victory):
    self.total_turns += self.cur_level.turn_no

    stats = []

    stats.append("Realm %d\n" % self.level_num)
    if self.trial_name:
        stats.append(self.trial_name + "\n")
    stats.append("Outcome: %s\n" % ("VICTORY" if victory else "DEFEAT"))
    stats.append("\nTurns taken:\n")
    stats.append("%d (L)\n" % self.cur_level.turn_no)
    stats.append("%d (G)\n" % self.total_turns)

    counts = sorted(self.cur_level.spell_counts.items(), key=lambda t: -t[1])

    spell_counts = [(s, c) for (s, c) in counts if not s.item]
    if spell_counts:
        stats.append("\nSpell Casts:\n")
        for s, c in spell_counts:
            stats.append("%s: %d\n" % (s.name, c))

    dealers = sorted(self.cur_level.damage_dealt_sources.items(), key=lambda t: -t[1])
    if dealers:
        stats.append("\nDamage to Enemies:\n")
        for s, d in dealers[:5]:
            stats.append("%d %s\n" % (d, s))
        if len(dealers) > 6:
            total_other = sum(d for s,d in dealers[5:])
            stats.append("%d Other\n" % total_other)

    sources = sorted(self.cur_level.damage_taken_sources.items(), key=lambda t: -t[1])
    if sources:
        stats.append("\nDamage to Wizard:\n")
        for s, d in sources[:5]:
            stats.append("%d %s\n" % (d, s))
        if len(sources) > 6:
            total_other = sum(d for s,d in sources[5:])
            stats.append("%d Other\n" % total_other)

    item_counts = [(s, c) for (s, c) in counts if s.item]
    if item_counts:
        stats.append("\nItems Used:\n")
        for s, c in item_counts:
            stats.append("%s: %d\n" % (s.name, c))

    if self.recent_upgrades:
        stats.append("\nPurchases:\n")
        for u in self.recent_upgrades:
            fmt = u.name
            if getattr(u, 'prereq', None):
                fmt = "%s %s" % (u.prereq.name, u.name)
            stats.append("%s\n" % fmt)

    self.recent_upgrades.clear()

    channel.put((write_finalize_level, (stats, self.run_number, self.level_num)))

RiftOptimizer.replace_only_vanilla_code(Game.Game.finalize_level,finalize_level)

def threaded_screenshot(surface, filename, run_number, level_number):
    filename = os.path.join('saves', str(run_number), filename % level_number)

    dirname = os.path.dirname(filename)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    pygame.image.save(surface, filename)

def make_level_screenshot(self):
    self.draw_level()
    self.draw_character()
    fake_portal = Level.Portal(self.game.cur_level.gen_params)
    self.examine_target = fake_portal
    self.draw_examine()

    channel.put((threaded_screenshot, (self.screen.copy(), 'level_%d_begin.png', self.game.run_number, self.game.level_num)))

    self.examine_target = None
    self.draw_examine()

RiftOptimizer.replace_only_vanilla_code(RiftWizard.PyGameView.make_level_screenshot,make_level_screenshot)

def make_level_end_screenshot(self):
    self.draw_level()
    self.draw_character()

    self.examine_display.fill((0, 0, 0))
    self.draw_panel(self.examine_display)

    self.draw_level_stats()

    self.screen.blit(self.examine_display, (self.screen.get_width() - self.h_margin, 0))

    channel.put((threaded_screenshot, (self.screen.copy(), 'level_%d_finish.png', self.game.run_number, self.game.level_num)))

RiftOptimizer.replace_only_vanilla_code(RiftWizard.PyGameView.make_level_end_screenshot,make_level_end_screenshot)

def setup_logger_thread(channel):
    try:
        # let's wait for the first message
        try:
            msg = channel.get(timeout=1)
        except queue.Empty:
            print("\nthe ThreadedIO queue was empty after 1 second. the main thread might have crashed. will give up in 10 more seconds")
            # TODO - should this be configurable?
            giveup_timer = 10

            while giveup_timer > 0:
                try:
                    msg = channel.get(timeout=1)

                    print("communication reestablished\n")

                    break
                except queue.Empty:
                    giveup_timer -= 1
                    if giveup_timer <= 3 and giveup_timer > 0:
                        print(giveup_timer)

            if giveup_timer <= 0:
                # TODO - revert to default functions first?
                return

        if not handle_message(msg):
            return

        # messages arrive and are executed sequentially in the same order as the main thread sent them
        while True:
            msg = channel.get()

            if not handle_message(msg):
                return
    except:
        # just crash the whole game if the io thread crashes
        if not root_window:
            back_channel.put("crash")

        root_window.running = False
        raise

def handle_message(msg):
    if msg == "quit":
        back_channel.put("quitting")
        return False
    elif hasattr(msg, '__len__') and len(msg) == 2 and callable(msg[0]):
        if hasattr(msg[1], '__iter__'):
            msg[0](*msg[1])
        else:
            msg[0](msg[1])
    elif isinstance(msg, RiftWizard.PyGameView):
        root_window = msg
    else:
        print("unknown message to IO thread:")
        print(msg)

    return True

channel = queue.Queue()

back_channel = queue.Queue()

original_run = RiftWizard.PyGameView.run

io_thread = threading.Thread(target=setup_logger_thread, args=(channel,), name="WriterThread")
io_thread.start()

# override RiftWizard.run() in order to close thread, handle crashes, etc
def run(self):
    try:
        try:
            channel.put(self)
            back_channel.get(False)

            print("closing main thread due to ThreadedIO crash")

            return
        except queue.Empty:
            pass
        except:
            raise

        original_run(self)
    except:
        # make sure thread is killed if any error occurs
        channel.put("quit")

        io_thread.join()
        raise

    channel.put("quit")

    # give the io thread time to close
    try:
        back_channel.get(timeout=2)
    except queue.Empty:
        pass

    io_thread.join()

RiftWizard.PyGameView.run = run


# -*- coding: utf-8 -*-
"""
Created on Sat Jun  8 12:22:49 2019

@author: Swathi
"""
import math
def partition(items,left,right):
    print("The current items are ",items)
    pivot=items[math.floor((left+right)/2)]
    l=left
    r=right
    print("--pivot is ",pivot)
    print("--left element is and it's index is ",items[left],l)
    print("--right element is and it's index is  ",items[right],r)
    #print("--left pointer is ",l)
    #print("--right pointer is ",r)
    while(l<=r):
        while(items[l]<pivot):
            l+=1
            print("l is now pointing to: ",items[l])

        while(items[r]>pivot):
            r-=1
            print("r is now pointing to: ",items[r])
        if(l<=r):
            print("swaping the left and right elements: ",items[l],items[r])
            swap(items,l,r)
            l+=1
            r-=1
    return l
def quicksort(items,leftindex,rightindex):
    if(len(items)>1):
        pivotindex=partition(items,leftindex,rightindex)
        print("The pivot is",pivotindex)
        print("The one that have been found now to be pivot",items[pivotindex])
        if(leftindex<pivotindex-1):
            print("The pivot to the right-left sort is",pivotindex)
            quicksort(items,leftindex,pivotindex-1)
        print("The pivot to the right-middle sort is",pivotindex)#some stack magic happening here!!!
        if(rightindex>pivotindex):
            print("The pivot to the right sort is",pivotindex)
            print("The right index is",rightindex)
            quicksort(items,pivotindex-1,rightindex)
    return items
def swap(items,leftpointer,rightpointer):
    tempreference=items[leftpointer]
    items[leftpointer]=items[rightpointer]
    items[rightpointer]=tempreference
items=[19, 22, 63, 105, 2, 46]
print(quicksort(items, 0,len(items) - 1))


from doubly_linked_list import DoublyLinkedList
import math
import random

class HashTable:
    def __init__(self, items, table_size, auxiliary_hash_method='universal', collision_resolution='chaining'):
        self.items = items
        self.collision_resolution = collision_resolution
        self.auxiliary_hash_method = auxiliary_hash_method
        # creates an empty table where each entry is a doubly linked list and there are enough entries for the maximum value item
        self.table = [None] * table_size
        self.hash_functions = {
            'division': self.__divide,
            'multiplication': self.__multiply,
            'universal': self.__universal
        }
        self.__build_table()

    #################################
    # HASH TABLE INITIAL CONSTRUCTION
    #################################
    def __build_table(self):
        for item in self.items:
            if self.collision_resolution == 'chaining':
                hash_value = self.__compute_hash(item=str(item))
                if self.table[hash_value] is not None:
                    self.table[hash_value].insert(key=item, current_node=self.table[hash_value].nil)
                else:
                    self.table[hash_value] = DoublyLinkedList(items=[item])
            else:
                hash_value = self.__probe(k=item, hash_method='multiplication')
                if hash_value is None: continue
                self.table[hash_value] = item

    ##############################
    # HASH FUNCTION COMPUTATIONS #
    ##############################
    def __probe(self, k, hash_method, i=0, inserting=True):
        hash_value = self.__compute_hash(item=k, method=hash_method, i=i)
        table_slot = self.table[hash_value]
        if not inserting and table_slot == k: return hash_value
        if table_slot in [None, 'DELETED'] and inserting:
            return hash_value
        elif (i + 1) % len(self.table) != 0: # if we are not where we started yet
            hash_value = self.__probe(k=k, hash_method=hash_method, i=i + 1, inserting=inserting)
        else:
            return None
        return hash_value

    def __divide(self, k):
        return k % len(self.table)

    def __universal(self, k):
        p = 999331
        return ((2*k + 5) % (p+1)) % len(self.table)

    def __multiply(self, k):
        m, A = len(self.table), (math.sqrt(5) - 1) / 2
        fractional = math.sqrt((k * A))
        mod_frac = fractional % 1
        hash_value = math.floor(m * mod_frac)
        return hash_value

    @staticmethod
    def __find_radix(integer_list):
        base = len(integer_list)
        radix = sum([integer_list[i] ** (base - (i + 1)) for i in range(len(integer_list))])
        return radix

    def __compute_hash(self, item, method='multiplication', i=0):
        integer_list = [ord(x) for x in str(item)]
        k = self.__find_radix(integer_list)
        if self.collision_resolution == 'chaining':
            return self.hash_functions[method](k)
        elif self.collision_resolution == 'linear probing':
                return (self.hash_functions[method](k) + (i % len(self.table))) % len(self.table)
        elif self.collision_resolution == 'quadratic probing':
                c1, c2 = 1, 3
                return (self.hash_functions[method](k) + c1 * (i % len(self.table)) + c2 * ((i % len(self.table)) ** 2)) % len(self.table)
        elif self.collision_resolution == 'double hashing':
                return (self.hash_functions[method](k) + (i % len(self.table)) * self.__divide(k=k)) % len(self.table)

    #########################
    # HASH TABLE OPERATIONS #
    #########################
    def search(self, key):
        if self.collision_resolution == 'chaining':
            hash_value = self.__compute_hash(item=key)
            return self.table[hash_value].search(k=key)
        else:
            hash_value = self.__probe(k=key, hash_method='multiplication', inserting=False)
            if hash_value is None: raise Exception(f"Item does not exist in this table")
            return hash_value

    def insert(self, x):
        hash_value = self.__compute_hash(x)
        if self.collision_resolution == 'chaining':
            if self.table[hash_value] is not None:
                self.table[hash_value].insert(key=x, current_node=self.table[hash_value].nil)
            else:
                self.table[hash_value] = DoublyLinkedList(items=[x])
        else:
            hash_value = self.__probe(k=x, hash_method=self.auxiliary_hash_method)
            if hash_value is None: raise Exception(f"Cannot insert item because table is full.")
            self.table[hash_value] = x

    def delete(self, key):
        if self.collision_resolution == 'chaining':
            hash_value = self.__compute_hash(item=key)
            return self.table[hash_value].delete(k=key)
        else:
            hash_value = self.__probe(k=key, hash_method=self.auxiliary_hash_method, i=0, inserting=False)
            if hash_value is None: raise Exception("Item is not in table")
            self.table[hash_value] = "DELETED"
            return hash_value

if __name__ == '__main__':
    items = [{'54': 1000}, {'99': 983}, {'44': 962}, {'59': 767}, {'25': 355}, {'67': 668}, {'74': 696}, {'74': 320}, {'74': 867}, {'74': 188}, {'74': 120}]
    table = HashTable(items=items, auxiliary_hash_method='universal', collision_resolution='linear probing', table_size=1000)
    print(table.table)
    table.insert(x={'54': 1000})
    table.insert(x={'54': 1000})
    table.insert(x={'54': 1000})
    table.insert(x={'54': 1000})
    print(table.table)
    table.delete(key={'54': 1000})
    print(table.table)
    table.delete(key={'54': 1000})
    print(table.table)
    print(table.search(key={'74': 867}))


import os

from absl import flags

FLAGS = flags.FLAGS

def get_executable_path(py_binary_name):
  """Returns the executable path of a py_binary.

  This returns the executable path of a py_binary that is in another Bazel
  target's data dependencies.

  On Linux/macOS, the path and __file__ has the same root directory.
  On Windows, bazel builds an .exe file and we need to use the MANIFEST file
  the location the actual binary.

  Args:
    py_binary_name: string, the name of a py_binary that is in another Bazel
        target's data dependencies.

  Raises:
    RuntimeError: Raised when it cannot locate the executable path.
  """

  if os.name == 'nt':
    py_binary_name += '.exe'
    manifest_file = os.path.join(FLAGS.test_srcdir, 'MANIFEST')
    workspace_name = os.environ['TEST_WORKSPACE']
    manifest_entry = '{}/{}'.format(workspace_name, py_binary_name)
    with open(manifest_file, 'r') as manifest_fd:
      for line in manifest_fd:
        tokens = line.strip().split(' ')
        if len(tokens) != 2:
          continue
        if manifest_entry == tokens[0]:
          return tokens[1]
    raise RuntimeError(
        'Cannot locate executable path for {}, MANIFEST file: {}.'.format(
            py_binary_name, manifest_file))
  else:
    # NOTE: __file__ may be .py or .pyc, depending on how the module was
    # loaded and executed.
    path = __file__

    # Use the package name to find the root directory: every dot is
    # a directory, plus one for ourselves.
    for _ in range(__name__.count('.') + 1):
      path = os.path.dirname(path)

    root_directory = path
    return os.path.join(root_directory, py_binary_name)