from check_your_heuristic.dataset.ReCoRDDataset import ReCoRDDataset
from check_your_heuristic.heuristics.Heuristic import BaseHeuristicSolver
from typing import Dict, Any, List
import pandas as pd
import string
import numpy as np
import logging

class ReCoRDHeuristics(BaseHeuristicSolver):
    def __init__(self, config: Dict[str, Any], dataset: ReCoRDDataset):
        super(BaseHeuristicSolver, self).__init__(dataset=dataset, config=config)
        self.passage_column = config["passage_column"]
        self.question_column = config["question_column"]
        self.entities_column = config["entities_column"]

    @staticmethod
    def normalize_answer(text: str):
        """Lower text and remove punctuation, articles and extra whitespace."""

        def white_space_fix(line):
            return ' '.join(line.split())

        def remove_punct(line):
            exclude = set(string.punctuation)
            return ''.join(ch for ch in line if ch not in exclude)

        return white_space_fix(remove_punct(text.lower()))

    def _get_entities(self, row, column_name:str):
        words = [
            row[self.passage_column][x["start"]: x["end"]]
            for x in row[column_name]
        ]
        return words

    def get_basic_pred(self,
                       row: pd.DataFrame,
                       words: List[str],
                       _words: List[str],
                       line_candidates: List[str]
                       ) -> str:
        if len(_words) == 0:
            if len(words) == 1:
                pred = words[0]
            else:
                for word in words:
                    line_candidates.append(row[self.question_column].replace("@placeholder", word))
                pred_idx = np.random.choice(np.arange(1, len(line_candidates)),
                                            size=1)[0]
                pred = np.array(words)[pred_idx]
        elif len(_words) == 1:
            pred = _words[0]
        else:
            for word in _words:
                line_candidates.append(row[self.question_column].replace("@placeholder", word))
            pred_idx = np.random.choice(np.arange(1, len(line_candidates)),
                                        size=1)[0]
            pred = np.array(_words)[pred_idx]
        return pred

    def filtration_count_heuristic(self, row: pd.DataFrame) -> str:
        """
        Heuristic that removes some candidates and filters out candidates depended on times they occurred in the text
        If there are a lot of candidates the one is chosen randomly
        """
        line_candidates = []
        _words = []
        text = row[self.passage_column].split()
        words = self._get_entities(row=row, column_name=self.entities_column)
        for word in words:
            if word[:-2] not in row[self.question_column] or text.count(words[:-2]) >= 2:
                _words.append(word)
        pred = self.get_basic_pred(row=row, words=words, _words=_words, line_candidates=line_candidates)
        return self.normalize_answer(pred)

    def remove_candidates_heuristic(self, row: pd.DataFrame) -> str:
        """
        Heuristic that removes candidates that occur in the question
        """
        words = self._get_entities(row=row, column_name=self.entities_column)
        line_candidates = []
        _words = []
        for word in words:
            if word[:-1] not in row[self.question_column]:
                _words.append(word)

        pred = self.get_basic_pred(row=row, words=words, _words=_words, line_candidates=line_candidates)
        return self.normalize_answer(pred)

    def metric_max_over_ground_truths(self, row: pd.DataFrame, predictions_colname: str) -> float:
        """
        As there is several true answers, we go over all and compute metric for all
        :param row: row of the data frame predicted
        :param predictions_colname: the name for heuristic
        :return:
        """
        scores_for_ground_truths = [0]
        prediction = row[predictions_colname]
        ground_truths = self._get_entities(row=row, column_name=self.target_name)
        for ground_truth in ground_truths:
            score = self.exact_match_score(prediction, ground_truth)
            scores_for_ground_truths.append(score)
        return max(scores_for_ground_truths)

    def check_heuristics(self) -> Dict[str, float]:
        """
        Checks how the heuristics are present in the data sets and prints the results
        :return: json-like object with all the results
        """

        result = {}

        self.train["pred_remove_candidates_heuristic"] = self.train.apply(
            self.remove_candidates_heuristic,
            axis=1
        )
        result["exact_match_score_remove_candidates_heuristic"] = np.mean(self.train.apply(
            lambda row: self.metric_max_over_ground_truths(
                row=row,
                predictions_colname="pred_remove_candidates_heuristic"
            ),
            axis=1).to_list()
        )

        self.train["pred_filtration_count_heuristic"] = self.train.apply(
            self.filtration_count_heuristic,
            axis=1
        )
        self.train["true_filtration_count_heuristic"] = self.train[self.target_name]
        result["exact_match_score_filtration_count_heuristic_train"] = np.mean(self.train.apply(
            lambda row: self.metric_max_over_ground_truths(
                row=row,
                predictions_colname="true_filtration_count_heuristic"
            ),
            axis=1
        ).to_list()
        )
        if self.valid is not None:
            result_df = pd.DataFrame()
            result_df["pred_remove_candidates_heuristic"] = self.valid.apply(
                self.remove_candidates_heuristic,
                axis=1
            )
            result_df["true_labels"] = self.valid[self.target_name]
            result["exact_match_score_remove_candidates_heuristic_valid"] = np.mean(result_df.apply(
                lambda row: self.metric_max_over_ground_truths(
                    row=row,
                    predictions_colname="pred_remove_candidates_heuristic"
                ),
                axis=1
                ).to_list()
            )

            result_df["pred_filtration_count_heuristic"] = self.valid.apply(
                self.filtration_count_heuristic,
                axis=1
            )
            result_df["true_filtration_count_heuristic"] = self.valid[self.target_name]
            result["exact_match_score_filtration_count_heuristic_valid"] = np.mean(result_df.apply(
                lambda row: self.metric_max_over_ground_truths(
                    row=row,
                    predictions_colname="pred_filtration_count_heuristic"
                ),
                axis=1).to_list()
            )
        for key, value in result.items():
            print(key, '\n', value, '\n')

        return result

    def exact_match_score(self, prediction: str, ground_truth: str) -> bool:
        return prediction == self.normalize_answer(ground_truth)

    def all_methods(self):
        logging.error("Method is deprecated for this type of dataset")
        raise AttributeError

    def random_balanced_choice(self):
        logging.error("Method is deprecated for this type of dataset")
        raise AttributeError

    def random_choice(self):
        logging.error("Method is deprecated for this type of dataset")
        raise AttributeError

    def majority_class(self):
        logging.error("Method is deprecated for this type of dataset")
        raise AttributeError

    def show_report(self):
        logging.error("Method is deprecated for this type of dataset")
        raise AttributeError


import numpy as np
from numpy import ma
import matplotlib.pyplot as plt
import matplotlib.patches as mp
from matplotlib.collections import PatchCollection

m_s = 4
m_e = 1
x_s, y_s = 0, 0
x_e, y_e = 2, 0
x_c, y_c = (m_s*x_s+m_e*x_e)/(m_s+m_e), (m_s*y_s+m_e*y_e)/(m_s+m_e)
gamma = 1.0

x = np.linspace(-2.5, 4, 1000)
y = np.linspace(-2.5, 2.5, 1000)
X, Y = np.meshgrid(x, y)

Omega = np.sqrt(gamma*((m_s+m_e)/(((x_s-x_e)**2+(y_s-y_e)**2)**(3/2))))

def f(X, Y):
    global x_s, y_s, m_s, x_e, y_e, m_e, x_c, y_c, Omega
    U = Omega**2*(X-x_c) - gamma*m_s*((X-x_s)/(((X-x_s)**2+(Y-y_s)**2)**(3/2))) \
        - gamma*m_e*((X-x_e)/(((X-x_e)**2+(Y-y_e)**2)**(3/2)))
    V = Omega**2*(Y-y_c) - gamma*m_s*((Y-y_s)/(((X-x_s)**2+(Y-y_s)**2)**(3/2))) \
        - gamma*m_e*((Y-y_e)/(((X-x_e)**2+(Y-y_e)**2)**(3/2)))
    return U, V

U, V = f(X, Y)

def findZero(i1, i2, f, I=50):
    rn = i1
    rp = i2
    for i in range(I):
        ra = np.array(rn) - np.array(f(*rn))*((np.array(rn)-np.array(rp))/(np.array(f(*rn))-np.array(f(*rp))))
        rp = rn
        rn = ra
    return rn

#U = gamma*( -(m_s/((X**2+Y**2)**(3/2)))*X - (m_e/(((X-d)**2+Y**2)**(3/2)))*(X-d) )
#V = gamma*( -(m_s/((X**2+Y**2)**(3/2)))*Y - (m_e/(((X-d)**2+Y**2)**(3/2)))*Y )

G_e = m_s/(((x_s-x_e)**2+(y_s+y_e)**2)**(3/2))
D = 0.1

A = np.sqrt(U**2+V**2)
#print(np.max(A))
sel = np.logical_and(A <= (G_e+D), A >= (G_e-D))
#print(np.sum(sel))

fig, ax = plt.subplots()

def limit(x, l=5):
    x[x > l] = l
    x[x < -l] = -l
    return x

def limit2d(x, y, l=5):
    m = np.hypot(x, y) > l
    x[m] = (x[m]/np.hypot(x[m], y[m]))*l
    y[m] = (y[m]/np.hypot(x[m], y[m]))*l
    return x, y

U, V = limit2d(U, V)
A = limit(A)

xmin, xmax, ymin, ymax = np.amin(x), np.amax(x), np.amin(y), np.amax(y)
extent = xmin, xmax, ymin, ymax

plt.imshow(5-A, cmap=plt.cm.jet, alpha=1, extent=extent)
#plt.colorbar()

plt.imshow(sel, cmap=plt.cm.jet, alpha=0.5, extent=extent)
#plt.colorbar()

stx = x.shape[0]/10
sty = y.shape[0]/10
Q = plt.quiver(X[::stx, ::sty], Y[::stx, ::sty], U[::stx, ::sty], V[::stx, ::sty],
               scale=100, width=.002,linewidth=1)

patches = []
colors = []
Sun = mp.Circle((x_s,y_s), 0.1, ec='none')
patches.append(Sun)
colors.append('#FFFF00')
Earth = mp.Circle((x_e,y_e), 0.1, ec='none')
patches.append(Earth)
colors.append('#0000FF')

p = [(0,0)] #make set
initial = [
    [[1, 1], [0.5, 0.5]],
    [[-1, -1], [-0.5, -0.5]],
]
for i1, i2 in initial:
    pn = findZero(np.array(i1), np.array(i2), f)
    print(pn)
    L = mp.Circle((pn[0], pn[1]), 0.1, ec='none')
    patches.append(L)
    colors.append('#FFFFFF')

collection = PatchCollection(patches, facecolors=colors)
ax.add_collection(collection)

plt.axis('off')
plt.savefig("lagrangePoints.png")
plt.axis('on')
plt.show()


from ..utils import Object

class MessageForwardInfo(Object):
    """
    Contains information about a forwarded message

    Attributes:
        ID (:obj:`str`): ``MessageForwardInfo``

    Args:
        origin (:class:`telegram.api.types.MessageForwardOrigin`):
            Origin of a forwarded message
        date (:obj:`int`):
            Point in time (Unix timestamp) when the message was originally sent
        public_service_announcement_type (:obj:`str`):
            The type of a public service announcement for the forwarded message
        from_chat_id (:obj:`int`):
            For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel's discussion group, the identifier of the chat from which the message was forwarded last time; 0 if unknown
        from_message_id (:obj:`int`):
            For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel's discussion group, the identifier of the original message from which the new message was forwarded last time; 0 if unknown

    Returns:
        MessageForwardInfo

    Raises:
        :class:`telegram.Error`
    """
    ID = "messageForwardInfo"

    def __init__(self, origin, date, public_service_announcement_type, from_chat_id, from_message_id, **kwargs):

        self.origin = origin  # MessageForwardOrigin
        self.date = date  # int
        self.public_service_announcement_type = public_service_announcement_type  # str
        self.from_chat_id = from_chat_id  # int
        self.from_message_id = from_message_id  # int

    @staticmethod
    def read(q: dict, *args) -> "MessageForwardInfo":
        origin = Object.read(q.get('origin'))
        date = q.get('date')
        public_service_announcement_type = q.get('public_service_announcement_type')
        from_chat_id = q.get('from_chat_id')
        from_message_id = q.get('from_message_id')
        return MessageForwardInfo(origin, date, public_service_announcement_type, from_chat_id, from_message_id)


from gym import spaces
from gym import Env
import numpy as np
from pathlib import Path
from PIL import Image
from gym.utils import seeding
from spg.view import TopDownView

import arcade

from spg.playground import Playground, Room
from spg.playground.collision_handlers import get_colliding_entities
from spg.utils.definitions import CollisionTypes
from spg.element import ColorWall

# My Custom Entities
from resources.apple import Apple, AppleCollisionType
from resources.reversedForwardBase import ReversedForwardBase
from resources.reverseHeadAgent import ReverseHeadAgent

# Created a Custom Collision Handler to confirm when an Apple and Agent collide
def apple_agent_collision(arbiter, _, data):
    playground: Playground = data["playground"]
    (apple, _), (agent, _) = get_colliding_entities(playground, arbiter)

    assert isinstance(apple, Apple)
    assert isinstance(agent, ReversedForwardBase)

    if apple.agent == agent:
        agent.activate(apple)
    return True

class PerturbationEnv(Env):
    def __init__(self):
        super().__init__()

        self.seed()

        # Initialization of playground and interaction
        playground = Room(size=(256, 256), wall_color=arcade.color.AERO_BLUE)
        playground.add_interaction(
            AppleCollisionType.APPLE, CollisionTypes.PART, apple_agent_collision
        )

        # Initialization of agent (can reverse X or Y controls on creation)
        agent = ReverseHeadAgent(reverse=(False, False))
        playground.add(agent)

        # Initialization of walls
        wall_1 = ColorWall(
            pos_start=(50, 50),
            pos_end=(100, 100),
            width=5,
            color=arcade.color.AERO_BLUE,
        )
        playground.add(wall_1, ((50, 0), 0))
        wall_2 = ColorWall(
            pos_start=(50, 50),
            pos_end=(100, 100),
            width=5,
            color=arcade.color.AERO_BLUE,
        )
        playground.add(wall_2, ((-50, 0), 0))
        wall_3 = ColorWall(
            pos_start=(-50, 50),
            pos_end=(100, 50),
            width=5,
            color=arcade.color.AERO_BLUE,
        )
        playground.add(wall_3, wall_3.wall_coordinates)

        self.playground = playground
        self.agent = self.playground.agents[0]
        self.playground.time_limit = 1000
        self.gui = TopDownView(self.playground)
        self.images = []
        self.no_of_apples = self.num_apples()

        # Code for creating action and observation space taken from:
        # https://github.com/gaorkl/spg-experiments/blob/master/spg_experiments/envs/spg/base.py

        # Create action space
        lows = []
        highs = []

        for controller in zip(self.agent.controllers):
            lows.append(controller[0].min)
            highs.append(controller[0].max)

        self.action_space = spaces.Box(
            low=np.array(lows).astype(np.float32),
            high=np.array(highs).astype(np.float32),
            dtype=np.float32,
        )

        # Create observation space
        elems = 0
        for sensor in self.agent.sensors:
            if isinstance(sensor.shape, int):
                elems += sensor.shape
            else:
                elems += np.prod(sensor.shape)

        self.observation_space = spaces.Box(
            low=0,
            high=1,
            shape=(elems,),
            dtype=np.float32,
        )

    def step(self, action):
        # Code for obtaining the controller names was taken from:
        # https://github.com/gaorkl/spg-experiments/blob/master/spg_experiments/envs/spg/base.py

        commands = {}
        command_dict = {}

        for controller, act in zip(self.agent.controllers, action):
            commands[controller.name] = act

        command_dict[self.agent] = commands

        _observation, msg, reward, _done = self.playground.step(commands=command_dict)

        reward = reward[self.agent]
        reward -= 0.01

        observation = self._get_obs()

        if msg is None:
            msg = {}

        # Checks if all apples have been eaten
        done = bool(self.no_of_apples == 0) or bool(
            self.playground.timestep >= self.playground.time_limit
        )

        self.gui.update()

        self.no_of_apples = self.num_apples()

        return observation, reward, done, msg

    def render(self, mode="rgb_array"):
        im = Image.fromarray(self.gui.get_np_img())
        self.images.append(im)
        return None

    def reset(self):
        self.playground.reset()
        observation = self._get_obs()
        self.images = []
        self.no_of_apples = self.num_apples()
        return observation

    # Additional methods for functionality

    def num_apples(self):
        apples = 0
        for element in self.playground.elements:
            if isinstance(element, Apple):
                apples += 1
        return apples

    # Saves all images to a file to name.png
    def save_gif(self, name):
        im = self.images[0]
        im.save(
            Path(f"gifs/{name}.gif"),
            format="GIF",
            append_images=self.images[1:],
            save_all=True,
            duration=10,
            loop=1,
        )

    # Code for seed taken from:
    # https://github.com/openai/gym/blob/master/gym/envs/box2d/lunar_lander.py
    def seed(self, seed=None):
        self.np_random, seed = seeding.np_random(seed)
        return [seed]

    # Code for get and process observation taken from:
    # https://github.com/gaorkl/spg-experiments/blob/master/spg_experiments/envs/spg/base.py

    # Calculate values for sensors on agent and return numpy array
    def _get_obs(self):
        sensor_values = {}
        for sensor in self.agent.sensors:
            sensor_values[sensor.name] = sensor._values
        return self.process_obs(sensor_values)

    # Creates numpy array from values in _get_obs()
    def process_obs(self, obs):
        obs_vec = []
        for _, v in obs.items():
            obs_vec.append(v.ravel())

        return np.concatenate(obs_vec)


import pandas as pd
import helper
import weaviate

# initiate the Weaviate client
client = weaviate.Client("http://localhost:8080")
client.timeout_config = (3, 200)

# empty schema and create new schema
client.schema.delete_all()
schema = {
    "classes": [
        {
            "class": "Wine",
            "properties": [
                {
                    "name": "title",
                    "dataType": ["text"]
                },
                {
                    "name": "description",
                    "dataType": ["text"]
                }
            ]
        }
    ]
}
client.schema.create(schema)

# open wine dataset (10000 items)
df = pd.read_csv('data/wine_reviews.csv', index_col=0)

def add_wines(data, batch_size=512, debug_mode=False):
    """ upload wines to Weaviate

    :param data: wine data in panda dataframe object
    :type data: panda dataframe object (2 columns: 'title' and 'description')
    :param batch_size: number of data objects to put in one batch, defaults to 512
    :type batch_size: int, optional
    :param debug_mode: set to True if you want to display upload errors, defaults to False
    :type debug_mode: bool, optional
    """

    no_items_in_batch = 0

    for index, row in data.iterrows():
        wine_object = {
            "title": row["title"] + '.',
            "description": row["description"],
        }

        wine_uuid = helper.generate_uuid('wine', row["title"]+row["description"])

        client.batch.add_data_object(wine_object, "Wine", wine_uuid)
        no_items_in_batch += 1

        if no_items_in_batch >= batch_size:
            results = client.batch.create_objects()

            if debug_mode:
                for result in results:
                    if result['result'] != {}:
                        helper.log(result['result'])

                message = str(index) + ' / ' + str(data.shape[0]) +  ' items imported'
                helper.log(message)

            no_items_in_batch = 0

    client.batch.create_objects()

add_wines(df.head(2500), batch_size=99, debug_mode=True)


# Utilities
############################################################################
# Imports
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import pickle

############################################################################
# Function to read the embedding_dataset from the "total_embedding.pickle"
def creatEmbedding():
    with open("C:\\Users\\balln\\Desktop\\PART_PythonGUI\\data_base\\total_embedding.pickle", 'rb') as f:
        embedding_dataset = pickle.load(f)
    return embedding_dataset

############################################################################
# Returns 2 embedding vectors one of the author of the imposter text and one for William Shakespeare
def twoEmbeddings(embedding_dataset, imposterText):
    # Find The embedding of the imposter book that was chosen
    filtered_imposter = embedding_dataset[embedding_dataset['book'] == imposterText]
    embedding_imposter = None
    if not filtered_imposter.empty:
        # Access the embedding value of the first matching row
        embedding_imposter = filtered_imposter['embedding'].iloc[0]

    # Get The embedding of the first book matched to be written by William Shakespeare
    filtered_shake = embedding_dataset[embedding_dataset['author'] == 'Shakespeare']
    embedding_shake = None
    if not filtered_shake.empty:
        embedding_shake = filtered_shake['embedding'].iloc[0]
    return embedding_shake, embedding_imposter

#################################################################################################
# Return cosine Similarity between 2 embeddings
def cosine_similarity_percentage(embed1, embed2):
    similarity = cosine_similarity(embed1.reshape(1, -1), embed2.reshape(1, -1))
    similarity_percentage = np.clip(similarity[0][0], -1, 1) * 100
    return similarity_percentage


from fastapi import FastAPI, Path

from typing import Optional
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    color: Optional[str] = None

inventory = {
    1: {
        'name': 'Milk',
        'price': 3.99,
        'color': 'white'
    }
}

app = FastAPI()

@app.get('/')
async def home():
    return [1,'a','3']#{"Welcome": "Home Python"}

@app.get("/items/{item_id}")
async def get_item(item_id:int = Path(None, description="This is item get method")):
    return inventory[item_id]

@app.post('/create-items/{item_id}')
async def create_item(item_id:int, item: Item):
    if item_id in inventory:
        return "Item already exists"
    else:
        inventory[item_id] = item
        return inventory[item_id]


'''
542. 01 Matrix
https://leetcode.com/problems/01-matrix/
'''

from collections import defaultdict, deque
from typing import List

# Approach 1: BFS from '1' columns to '0'
# The problem is we do BFS for 1, which is sub-optimal
class Solution:
    def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:

        m = len(matrix)
        n = len(matrix[0])

        def bfs(i,j):
            q = deque()
            q.append((i,j,0))

            visited = set()
            visited.add((i,j))

            while q:
                x, y, distance = q.popleft()
                if matrix[x][y] == 0:
                    return distance

                neighbors = [(x,y+1), (x,y-1), (x-1,y), (x+1,y)]
                for i,j in neighbors:
                    if i<0 or i>=m or j<0 or j>=n:
                        continue
                    if (i,j) not in visited:
                        q.append((i,j,distance+1))
                        visited.add((i,j))

        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 1:
                    matrix[i][j] = bfs(i,j)

        return matrix

# Approach 2: Simultaneous BFS
# Instead of calling BFS from each '1' cell, go in the other direction
# from '0' cell to '1' and update distance - this will be guaranteed to be shortest using BFS
from collections import deque
class Solution:
    def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:

        R = len(matrix)
        if R == 0:
            return matrix

        C = len(matrix[0])

        #dist = defaultdict(lambda: float('inf'))
        queue = deque()
        for r in range(R):
            for c in range(C):
                if matrix[r][c] == 0:
                    queue.append((r,c))
                else:
                    matrix[r][c] = float('inf')

        dr = [-1,1,0,0]
        dc = [0,0,1,-1]

        # bfs
        while queue:
            r, c = queue.popleft()

            # 4 directions - east, west, north, south
            for i in range(4):
                rr = r + dr[i]
                cc = c + dc[i]

                # eliminate border cases
                if rr >= 0 and cc >=0 and rr < R and cc < C:
                    if matrix[rr][cc] > matrix[r][c] + 1:
                        matrix[rr][cc] = matrix[r][c] + 1
                        queue.append((rr,cc))
        return matrix


# Example: echo server, using StreamServer

import logging
import argparse

from gruvi import get_hub, util
from gruvi.stream import StreamServer

logging.basicConfig()

parser = argparse.ArgumentParser()
parser.add_argument('port', type=int)
args = parser.parse_args()

def echo_handler(stream, protocol, client):
    peer = client.getpeername()
    print('Connection from {0}'.format(util.saddr(peer)))
    while True:
        buf = stream.read(4096)
        if not buf:
            break
        stream.write(buf)
    print('Connection closed')

server = StreamServer(echo_handler)
server.listen(('0.0.0.0', args.port))

hub = get_hub()
hub.switch(interrupt=True)


import nltk

def nouns_transform(sentence):
    tokenized = nltk.word_tokenize(sentence)

    def is_noun (pos):
        return pos[:2] == 'NN'
    return [word for (word, pos) in nltk.pos_tag(tokenized) if is_noun(pos)]

def render_template(template_name='html pages/home.html', context={}):
    html_str = ""
    with open(template_name, 'r') as f:
        html_str = f.read()
        html_str = html_str.format(**context)
    return html_str

def main(environ, start_response):
    query = environ.get("QUERY_STRING")
    path = environ.get("PATH_INFO")

    if len(query) > len("text="):
       sentence = query[5:].replace("+"," ").replace("%27","'")
       nouns = nouns_transform(sentence)
       data = render_template(template_name='html pages/nouns.html', context={"nouns_key": nouns})

    elif path == "/":
        data = render_template()
    else:
        data = render_template(template_name='html pages/404.html')

    data = data.encode("utf-8")
    start_response(
        f"200 OK", [
            ("Content-Type", "text/html"),
            ("Content-Length", str(len(data)))
        ]
    )
    return iter([data])


from django import forms
from ..contrib.sysdate import dateFromLocal

class DateBigInput(forms.DateInput):
    def value_from_datadict(self, data, files, name):
        valData = super().value_from_datadict(data, files, name)
        return dateFromLocal(valData)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['data-provide'] = 'datepicker'
        context['widget']['attrs']['data-date-language'] = 'th-th'
        # context['widget']['attrs']['data-date-startdate'] = '-10d'
        # context['widget']['attrs']['data-date-enddate'] = '+10d'
        context['widget']['attrs']['class'] = 'form-control'
        return context

class NumberBigInput(forms.TextInput):
    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['data-inputmask-alias'] = 'currency'
        context['widget']['attrs']['class'] = 'form-control'
        return context

class TextBigInput(forms.TextInput):
    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['class'] = 'form-control'
        return context

class DecimalBigInput(forms.TextInput):
    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['data-inputmask-alias'] = 'currency'
        context['widget']['attrs']['class'] = 'form-control'
        return context

class IntegerBigInput(forms.TextInput):
    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['data-inputmask-alias'] = 'integer'
        context['widget']['attrs']['class'] = 'form-control'
        return context

# class ChoiceBigSelect(forms.Select):
#     def get_context(self, name, value, attrs):
#         context = super().get_context(name, value, attrs)
#         context['widget']['attrs']['class'] = 'form-control'
#         return context

class FormMixinBig:
    use_required_attribute = False
    readonly = []
    field_require = []
    currency = []
    # selectChoice = []

    def form_init(self):
        self.__WidgetBase()
        self.__FieldBase()

    def __FieldBase(self):
        for field in iter(self.fields):
            self.fields[field].required = False
            fieldType = self.fields[field].widget.__class__.__name__
            if fieldType not in ['Select', 'Select2','HiddenInput']:
                clsAttr = self.fields[field].widget.attrs.get('class','')
                if clsAttr.find('form-control') < 0 :
                    self.fields[field].widget.attrs['class'] = '{} form-control'.format(clsAttr)

            if fieldType in ['DateInput', 'DateTimeInput']:
                self.fields[field].widget = DateBigInput()
            if field in self.currency:
                self.fields[field].widget = NumberBigInput()

            if field in self.readonly or self.readonly == 'all':
                self.fields[field].widget.attrs['readonly'] = True
                if fieldType in ['DateInput', 'DateTimeInput']:
                    self.fields[field].widget.attrs['disabled'] = True

            if field in self.field_require or self.field_require == 'all':
                self.fields[field].required = True
                # if self.fields[field].label and not self.fields[field].label[0:1] == '*':
                #     self.fields[field].label = '*{}'.format(self.fields[field].lable)

    def __WidgetBase(self):
        if not hasattr(self,'Meta') : return
        if not hasattr(self.Meta, 'widgets'): return
        for widget in self.Meta.widgets:
            fieldType = self.Meta.widgets[widget].__class__.__name__
            if fieldType not in ['Select', 'Select2','HiddenInput']:
                clsAttr = self.Meta.widgets[widget].attrs.get('class', '')
                if clsAttr.find('form-control') < 0:
                    self.Meta.widgets[widget].attrs['class'] = '{} form-control'.format(clsAttr)

class BaseEditModelForm(forms.ModelForm,FormMixinBig):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.form_init()

    def clean(self):
        super().clean()
        for f in self.cleaned_data:
            if not self.cleaned_data[f] and not self.cleaned_data[f] == 0:
                self.cleaned_data[f] = None

class BaseEditForm(forms.Form,FormMixinBig):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.form_init()


#aoc20150101

import pathlib
import sys

def parse(path):
  return list(pathlib.Path(path).read_text())

def solve(puzzleInput):
  finalFloor = 0

  for datum in puzzleInput:
    if datum == '(':
      finalFloor += 1
    else:
      finalFloor -= 1

  return finalFloor

if __name__ == "__main__":
  for path in sys.argv[1:]:
    puzzleInput = parse(path)
    print(puzzleInput, solve(puzzleInput))


import logging
from random import randint
from time import sleep
from typing import List
import pandas as pd
import requests  # type: ignore

from models.auction import Lot, Lots
from models.item import Item, Items
from models.media import Media, Medias
from scrape.item_scraper import ItemScraper
from scrape.lot_scraper import LotScraper
from scrape.media_scraper import MediaScraper
from utils.aws import S3Connector

logger = logging.getLogger(__name__)

class AuctionScraper:
    def __init__(self, access_token: str, bucket: str):
        self.access_token = access_token
        self.s3_connector = S3Connector(bucket)

    def crawl(self, sample: int = 0):
        lots_scraper = LotScraper(self.access_token)
        lots: Lots = lots_scraper.crawl()

        if lots:
            df = pd.DataFrame.from_records(lots.dict()["lots"])
            path = self.s3_connector.create_parquet_path("lots")
            self.s3_connector.write_parquet(df, path)
            logger.info(f"Wrote to {path}")

        logger.info(f"{len(lots.lots)} lots crawled..")

        self.item_ids = list({lot.item.id for lot in lots.lots})
        logger.info(f"{len(self.item_ids)} item ids found..")

        scraped_item_ids: List[int] = self._read_item_ids()
        print(f"Previous {len(scraped_item_ids)} item ids found")
        item_ids = [
            item_id for item_id in self.item_ids if item_id not in scraped_item_ids
        ]
        if sample > 0:
            sample_item_ids = []
            for _ in range(sample):
                rand_item_id = randint(0, len(item_ids) - 1)
                sample_item_ids.append(rand_item_id)
            item_ids = sample_item_ids

        logger.info(f"{len(item_ids)} item ids found. Crawling items..")
        print(f"{len(item_ids)} item ids found")

        item_scraper = ItemScraper(self.access_token)
        media_scraper = MediaScraper(self.access_token)

        handled_items: List[Item] = []
        handled_media: List[Media] = []
        try:
            logger.info(f"Crawling {len(item_ids)}")
            for i, item_id in enumerate(item_ids):
                item: Item = item_scraper.crawl(item_id)
                sleep(1)
                if item:
                    handled_items.append(item)
                media: Media = media_scraper.crawl(item_id)
                sleep(1)
                if media:
                    handled_media.append(media)
                scraped_item_ids.append(item_id)
                logger.info(f"Item {i+1}/{len(item_ids)} crawled.")
                print(f"Item {i+1}/{len(item_ids)} crawled.")

                # write intermediate hanlded item_ids to s3 in case of failure
                if (i + 1) % 100 == 0:
                    self._store(
                        items=handled_items,
                        media=handled_media,
                        item_ids=scraped_item_ids,
                    )

            # write the final results
            self._store(
                items=handled_items,
                media=handled_media,
                item_ids=scraped_item_ids,
            )
        except Exception as e:
            logger.error(e)
            logger.info("Storing processed item_ids.")

    def _store(self, items: list[Item], media: list[Media], item_ids: list[int]):
        items_ = Items(items=items)
        df_items = pd.DataFrame.from_records(items_.dict()["items"])
        self._write_to_s3(df_items, "items")
        medias_ = Medias(media=media)
        df_media = pd.DataFrame.from_records(medias_.dict()["media"])
        self._write_to_s3(df_media, "media")
        self._write_item_ids(item_ids)

        # clear handled items
        items = []
        media = []

    def random_lots(self, lots: List[Lot], size: int = 1) -> Lots:
        sample_lots: List[Lot] = []
        for _ in range(size):
            random_lot: Lot = lots[randint(0, len(lots))]
            sample_lots.append(random_lot)

        return sample_lots

    def _write_to_s3(self, df: pd.DataFrame, name: str):
        path = self.s3_connector.create_parquet_path(name)
        self.s3_connector.write_parquet(df, path)
        logger.info(f"Wrote to {path}")

    def _read_item_ids(self) -> List[int]:
        df = self.s3_connector.read_csv("item_ids.csv")
        return list(df["id"].values)

    def _write_item_ids(self, item_ids: List[int]) -> pd.DataFrame:
        df = pd.DataFrame(item_ids, columns=["id"])
        self.s3_connector.write_csv(df, "item_ids.csv")


from functools import wraps
from . import database as db
from .reddit import user_exists, subreddit_exists
from sqlalchemy.exc import IntegrityError
from . import constants as c
from .template import get_template
from .utils import message_url

from sqlalchemy.orm import joinedload

_COMMANDS = {}
_MENTION_COMMANDS = {}
_INV_MSG = r"""Invalid arguments specified for {cmd}.

Required arguments: {args}
"""
_SUB_EXISTS_MSG = r"""You are already subscribed to /u/{author} on /r/{subreddit}
"""
_SUB_NOT_EXISTS_MSG = r"""You are not already subscribed to /u/{author} on /r/{subreddit}
"""
_SUB_REMOVED_MSG = r"""You are now unsubscribed to /u/{author} on /r/{subreddit}
"""

def command(command, *fargs, owner_only=False):
    def wrapper(func):
        _COMMANDS[command] = (func, fargs, owner_only)
        return func

    return wrapper

def mention_command(command, *fargs):
    def wrapper(func):
        _MENTION_COMMANDS[command] = (func, fargs)
        return func

    return wrapper

def check_mention(message):
    body = message.body.strip()
    args = body.split()[1:]
    command = args.pop(0).lower()
    if command not in _MENTION_COMMANDS.keys():
        return
    func, rargs = _MENTION_COMMANDS[command]
    if len(args) != len(rargs):
        message.reply(
            get_template("base.j2").render(
                message=_INV_MSG.format(cmd=command, args=", ".join(rargs))
            )
        )
        return
    func(message, *args)

def check_command(message):
    body = message.body.strip()
    args = body.split()
    command = args.pop(0).lower()[1:]
    if command not in _COMMANDS.keys():
        return
    func, rargs, owner_only = _COMMANDS[command]
    if owner_only:
        user = message.author.name.lower()
        if not user == c.OWNER_USERNAME:
            return
    if len(args) != len(rargs):
        message.reply(
            get_template("base.j2").render(
                message=_INV_MSG.format(cmd=command, args=", ".join(rargs))
            )
        )
        return
    func(message, *args)

@command("post", "Subreddit", owner_only=True)
def post(message, sub):
    sub_s = sub.split("/")[-1].lower()
    subreddit = db.session.query(db.Subreddit).filter_by(name=sub_s).first()
    if not subreddit:
        message.reply(f"The subreddit /r/{sub_s} is not in my database.")
        return
    subreddit.post = True
    db.session.add(subreddit)
    db.session.commit()
    message.reply(f"I will now comment on posts in /r/{sub_s}")

@command("nopost", "Subreddit", owner_only=True)
def nopost(message, sub):
    sub_s = sub.split("/")[-1].lower()
    subreddit = db.session.query(db.Subreddit).filter_by(name=sub_s).first()
    if not subreddit:
        message.reply(f"The subreddit /r/{sub_s} is not in my database.")
        return
    subreddit.post = False
    db.session.add(subreddit)
    db.session.commit()
    message.reply(f"I will not comment on posts in /r/{sub_s} from now on.")

@command("unsubscribe", "Author", "Subreddit")
def unsubscribe(message, auth, sub):
    auth_s = auth.split("/")[-1]
    author_s = auth_s.lower()
    sub_s = sub.split("/")[-1]
    subreddit_s = sub_s.lower()
    subscriber_s = message.author.name.lower()
    subscription = db.get_subscription(subscriber_s, author_s, subreddit_s)
    if not subscription:
        message.reply(
            get_template("base.j2").render(
                message=_SUB_NOT_EXISTS_MSG.format(author=auth_s, subreddit=sub_s)
            )
        )
        return
    try:
        db.session.delete(subscription)
        db.session.commit()
    except:
        db.session.rollback()
        raise
    message.reply(
        get_template("base.j2").render(
            message=_SUB_REMOVED_MSG.format(author=auth_s, subreddit=sub_s)
        )
    )

@command("mysubscriptions")
def mysubscriptions(message):
    subscriber = message.author.name.lower()
    subscriptions = (
        db.session.query(db.Subscription)
        .join(db.Subscription.subscriber)
        .filter(db.User.username == subscriber)
        .options(
            joinedload(db.Subscription.author), joinedload(db.Subscription.subreddit)
        )
        .all()
    )
    message.reply(get_template("subscriptions.j2").render(subscriptions=subscriptions))

@command("subscribe", "Author", "Subreddit")
def subscribe(message, auth, sub):
    auth_s = auth.split("/")[-1]
    author_s = auth_s.lower()
    sub_s = sub.split("/")[-1]
    subreddit_s = sub_s.lower()
    subscriber_s = message.author.name.lower()
    author = db.get_or_create_if(
        db.User, lambda: user_exists(author_s), username=author_s
    )
    if not author:
        message.reply(
            get_template("base.j2").render(
                message=f"The user /u/{author_s} doesn't exist"
            )
        )
        return
    subreddit = db.get_or_create_if(
        db.Subreddit, lambda: subreddit_exists(subreddit_s), name=subreddit_s
    )
    if not subreddit:
        message.reply(
            get_template("base.j2").render(
                message=f"The subreddit /r/{subreddit_s} doesn't exist"
            )
        )
        return
    subscriber = db.create_or_get(db.User, username=subscriber_s)
    subscription = db.Subscription(
        author=author, subreddit=subreddit, subscriber=subscriber
    )
    try:
        db.session.add(subscription)
        db.session.commit()
    except IntegrityError:
        db.session.rollback()
        message.reply(
            get_template("base.j2").render(
                message=_SUB_EXISTS_MSG.format(author=auth_s, subreddit=sub_s)
            )
        )
        return
    message.reply(
        get_template("base.j2").render(
            message=c.SUBSCRIPTION_SUCCESS.format(author=auth_s, subreddit=sub_s)
        )
    )

@mention_command("subscribe")
def msubcribe(message):
    author_s = message.submission.author.name.lower()
    subreddit_s = message.submission.subreddit.display_name.lower()
    subscriber_s = message.author.name.lower()
    author = db.create_or_get(db.User, username=author_s)
    subreddit = db.create_or_get(db.Subreddit, name=subreddit_s)
    subscriber = db.create_or_get(db.User, username=subscriber_s)
    subscription = db.Subscription(
        author=author, subreddit=subreddit, subscriber=subscriber
    )
    try:
        db.session.add(subscription)
        db.session.commit()
    except IntegrityError:
        db.session.rollback()
        message.author.message(
            subject="Re: subscribe",
            message=get_template("base.j2").render(
                message=_SUB_EXISTS_MSG.format(author=author_s, subreddit=subreddit_s)
            ),
        )
        return
    message.author.message(
        subject="Re: subscribe",
        message=get_template("base.j2").render(
            message=c.SUBSCRIPTION_SUCCESS.format(
                author=author_s, subreddit=subreddit_s
            )
        ),
    )


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
	from the month of edge deletion, find the SR before, at the time and after
"""
from collections import defaultdict
import codecs
import os
import json
import numpy as np

IN_DIR = "../../../DATA/General/MO_MENT_networks"
os.chdir(IN_DIR)

F_IN = "mention_edges_monthly_SR"
F_OUT = "mention_network_dir_w"

MONTHS =  ["5", "6", "7", "8", "9", "10", "11"]

def read_in_monthly_mentions(MO):
	monthly_ment = defaultdict(dict)
	f_in = str(MO) + "mention_edges_monthly_SR"
	f = open(f_in, 'r')
	for line in f:
		(u1, u2, SR, w1, w2) = line.split()
		userA = int(u1)
		userB = int(u2)
		w1 = int(w1)
		w2 = int(w2)
		if w1 > 0:
			monthly_ment[(u1, u2)] = w1
		if w2 > 0:
			monthly_ment[(u2, u1)] = w2
	f.close()
	return monthly_ment

def save_monthly_network_dir_w(MO):
	monthly_ment = read_in_monthly_mentions(MO)
	f_out = str(MO) + "mention_edgelist_dir_w"
	f = open(f_out, 'w')
	for el in monthly_ment:
		userA = el[0]
		userB = el[1]
		w = monthly_ment[el]
		f.write(str(userA) + '\t' + str(userB) + '\t' + str(w) + '\n')
	f.close()

for MO in MONTHS:
	save_monthly_network_dir_w(MO)


import os
import time
from dotenv import dotenv_values
from selenium import webdriver
from selenium.webdriver import Chrome
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
from utilities.commons.exceptions import DriverSetupFailedException
from utilities.commons.context import Context
from utilities.scripts.script_executor import ScriptExecutor
import requests
from requests.exceptions import ConnectionError

def _get_env_values() -> dict:
    config = dotenv_values(".env")
    return {**config} if config else None

def _load_init_configs(context):
    env_values = _get_env_values()
    context: Context = context
    if env_values is not None:
        context.WEB_URL = env_values.get("WEB_URL")
        context.API_URL = env_values.get("API_URL")
    else:
        raise Exception(f"Env file/values are missing")

def _get_service() -> Service:
    try:
        service = Service(executable_path=ChromeDriverManager(path=os.path.dirname(__file__)).install())
    except DriverSetupFailedException:
        raise DriverSetupFailedException(msg="Failed to install driver or create service")
    return service

def _get_chrome_options():
    options = webdriver.ChromeOptions()
    options.add_argument("no-sandbox")
    options.add_argument("--verbose")
    options.add_argument("--disable-gpu")
    options.add_argument("--disable-web-security")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--ignore-certificate-errors")
    options.add_argument("--allow-insecure-localhost")
    return options

def _get_local_webdriver():
    service: Service = _get_service()
    try:
        browser = Chrome(service=service, \
                         options=_get_chrome_options())
    except DriverSetupFailedException:
        raise DriverSetupFailedException(msg="Failed to initialize driver")
    return browser

def _build_selenium_remote_base_url(host):
    if host is None or len(host) > 1:
        return f"http://{host}:4444/"
    else:
        raise ValueError("host cannot be None or empty, please provide host")

def _get_remote_selenium_url(hosts: list) -> str:
    if len(hosts) < 1:
        raise ValueError("Please enter host(s) as list, at least one host is expected")
    retry = True
    max_retries = 5
    retry_attempt = 0
    while retry:
        retry_attempt += 1
        for host in hosts:
            try:
                selenium_remote_url = _build_selenium_remote_base_url(host)
                status_code = requests.get(selenium_remote_url).status_code
                if status_code == 200:
                    retry = False
                    return selenium_remote_url + "wd/hub"
                else:
                    print(f"request to {selenium_remote_url} failed due to status code: {status_code} ")
                    retry = False
            except ConnectionError:
                print(f"{selenium_remote_url} is not reachable \n")
                if hosts.index(host) + 1 < len(hosts):
                    print(f"now trying to reach selenium at:{_build_selenium_remote_base_url(hosts[hosts.index(host) + 1])}")
                if retry_attempt >= max_retries:
                    retry = False
                time.sleep(5)
        print(f"*** retry attempt:{retry_attempt} ***\n")

def _get_webdriver_from_remote():
    remote_selenium_url = _get_remote_selenium_url(hosts=["selenium", "localhost"])
    return webdriver.Remote(command_executor=remote_selenium_url, \
                            options=_get_chrome_options())

def before_scenario(context, scenario):
    _load_init_configs(context)
    context.browser = _get_local_webdriver() \
        if os.environ.get("RUN_ENV") == "local" \
        else _get_webdriver_from_remote()

def after_scenario(context, scenario):
    context.browser.quit()

def after_all(context):
    ScriptExecutor.delete_temp_files()

'''
#other available hooks

def before_step(context, step):
    pass

def after_step(context, step):
    pass

def before_feature(context, feature):
    pass

def after_feature(context, feature):
    pass

def before_tag(context, tag):
    pass

def after_tag(context, tag):
    pass

def before_all(context):
    pass

def after_all(context):
    pass
'''


from collections import Iterable
l = isinstance('abc',Iterable)
print(l)

L=list(range(1,11))
print(L)

L2 = [x * x for x in range(1,20)]
print(L2)

L3 = [m + n for m in 'abc' for n in 'hkl']
print(L3)

import os
L4 = [d for d in os.listdir('.')]
print('all dir',L4)

L5 = ['Hello','World',18,'Apple',None]
L6 = [s.lower() for s in L5 if isinstance(s,str)]
print(L6)

L7 = ['Hello','World',18,'Apple',None]
L8 = [s.lower() if isinstance(s,str) else s for s in L7]
print(L8)


from ..shared.list_arithmatic import add
from ..shared.digits import to_digits
from itertools import permutations
from ..shared.solver import Solver

def digit_sum(n:int)->int:
    return add(to_digits(n))

def digit_sums(biggest: int):
    pool = list(range(0,biggest))
    for a, b in permutations(pool,2):
        power = a**b
        yield a, b, power, digit_sum(power)

def _solve(print=print):
    biggest = max(digit_sums(100), key=lambda x: x[3])
    print(f"{biggest[0]}**{biggest[1]}=={biggest[2]}")
    print(f"Digit sum: {biggest[3]}")
    return True

description = '''A googol (10**100) is a massive number: one followed by one-hundred zeros; 100**100 is almost
unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.

Considering natural numbers of the form, a**b, where a, b < 100, what is the maximum digital sum?
'''

solver = Solver(56,
                'Powerful digit sum',
                description,
                _solve
                )


import json
import os.path as osp
from typing import Union

class Prompter(object):
    __slots__ = ("template", "_verbose")

    def __init__(self, template_name: str = "", verbose: bool = False):
        self._verbose = verbose

        if not template_name:
            template_name = "KoRAE_template"
        file_name = osp.join("templates", f"{template_name}.json")
        if not osp.exists(file_name):
            raise ValueError(f"Can't read {file_name}")
        with open(file_name) as fp:
            self.template = json.load(fp)
        if self._verbose:
            print(
                f"Using prompt template {template_name}: {self.template['description']}"
            )

    def generate_prompt(
        self,
        instruction: str,
        system_msg: Union[None, str] = None,
        input: Union[None, str] = None,
        output: Union[None, str] = None,
    ) -> str:
        # returns the full prompt from instruction and optional system message and input
        # if a label is provided, it's also appended
        if system_msg:
            res = self.template['prompt'].format(
                prompt=system_msg,
                instruction=instruction + " " + input
            )
        else:
            res = self.template['no_prompt'].format(
                instruction=instruction + " " + input,
            )

        if output:
            res = f"{res}{output}"

        return res

    def get_response(self, output: str) -> str:
        return output.split(self.template["response_split"])[1].strip()


import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader

import torchvision as tv

from time import time
from src.model.madry_model import WideResNet
from src.attack import FastGradientSignUntargeted
from src.utils import makedirs, create_logger, tensor2cuda, numpy2cuda, evaluate, save_model

from src.argument import parser, print_args

class Trainer():
    def __init__(self, args, logger, attack):
        self.args = args
        self.logger = logger
        self.attack = attack

    def standard_train(self, model, tr_loader, va_loader=None):
        self.train(model, tr_loader, va_loader, False)

    def adversarial_train(self, model, tr_loader, va_loader=None):
        self.train(model, tr_loader, va_loader, True)

    def train(self, model, tr_loader, va_loader=None, adv_train=False):
        args = self.args
        logger = self.logger

        opt = torch.optim.SGD(model.parameters(), args.learning_rate,
                              weight_decay=args.weight_decay,
                              momentum=args.momentum)
        scheduler = torch.optim.lr_scheduler.MultiStepLR(opt,
                                                         milestones=[40000, 60000],
                                                         gamma=0.1)
        _iter = 0

        begin_time = time()

        for epoch in range(1, args.max_epoch+1):
            for data, label in tr_loader:
                data, label = tensor2cuda(data), tensor2cuda(label)

                if adv_train:
                    # When training, the adversarial example is created from a random
                    # close point to the original data point. If in evaluation mode,
                    # just start from the original data point.
                    adv_data = self.attack.perturb(data, label, 'mean', True)
                    output = model(adv_data, _eval=False)
                else:
                    output = model(data, _eval=False)

                loss = F.cross_entropy(output, label)

                opt.zero_grad()
                loss.backward()
                opt.step()

                if _iter % args.n_eval_step == 0:
                    t1 = time()

                    if adv_train:
                        with torch.no_grad():
                            stand_output = model(data, _eval=True)
                        pred = torch.max(stand_output, dim=1)[1]

                        # print(pred)
                        std_acc = evaluate(pred.cpu().numpy(), label.cpu().numpy()) * 100

                        pred = torch.max(output, dim=1)[1]
                        # print(pred)
                        adv_acc = evaluate(pred.cpu().numpy(), label.cpu().numpy()) * 100

                    else:

                        adv_data = self.attack.perturb(data, label, 'mean', False)

                        with torch.no_grad():
                            adv_output = model(adv_data, _eval=True)
                        pred = torch.max(adv_output, dim=1)[1]
                        # print(label)
                        # print(pred)
                        adv_acc = evaluate(pred.cpu().numpy(), label.cpu().numpy()) * 100

                        pred = torch.max(output, dim=1)[1]
                        # print(pred)
                        std_acc = evaluate(pred.cpu().numpy(), label.cpu().numpy()) * 100

                    t2 = time()

                    logger.info(f'epoch: {epoch}, iter: {_iter}, lr={opt.param_groups[0]["lr"]}, '
                                f'spent {time()-begin_time:.2f} s, tr_loss: {loss.item():.3f}')

                    logger.info(f'standard acc: {std_acc:.3f}%, robustness acc: {adv_acc:.3f}%')

                    # begin_time = time()

                    # if va_loader is not None:
                    #     va_acc, va_adv_acc = self.test(model, va_loader, True)
                    #     va_acc, va_adv_acc = va_acc * 100.0, va_adv_acc * 100.0

                    #     logger.info('\n' + '='*30 + ' evaluation ' + '='*30)
                    #     logger.info('test acc: %.3f %%, test adv acc: %.3f %%, spent: %.3f' % (
                    #         va_acc, va_adv_acc, time() - begin_time))
                    #     logger.info('='*28 + ' end of evaluation ' + '='*28 + '\n')

                    begin_time = time()

                if _iter % args.n_store_image_step == 0:
                    tv.utils.save_image(torch.cat([data.cpu(), adv_data.cpu()], dim=0),
                                        os.path.join(args.log_folder, f'images_{_iter}.jpg'),
                                        nrow=16)

                if _iter % args.n_checkpoint_step == 0:
                    file_name = os.path.join(args.model_folder, f'checkpoint_{_iter}.pth')
                    save_model(model, file_name)

                _iter += 1
                # scheduler depends on training interation
                scheduler.step()

            if va_loader is not None:
                t1 = time()
                va_acc, va_adv_acc = self.test(model, va_loader, True, False)
                va_acc, va_adv_acc = va_acc * 100.0, va_adv_acc * 100.0

                t2 = time()
                logger.info('\n'+'='*20 +f' evaluation at epoch: {epoch} iteration: {_iter} ' \
                    +'='*20)
                logger.info(f'test acc: {va_acc:.3f}%, test adv acc: {va_adv_acc:.3f}%, spent: {t2-t1:.3f} s')
                logger.info('='*28+' end of evaluation '+'='*28+'\n')

    def test(self, model, loader, adv_test=False, use_pseudo_label=False):
        # adv_test is False, return adv_acc as -1

        total_acc = 0.0
        num = 0
        total_adv_acc = 0.0

        with torch.no_grad():
            for data, label in loader:
                data, label = tensor2cuda(data), tensor2cuda(label)

                output = model(data, _eval=True)

                pred = torch.max(output, dim=1)[1]
                te_acc = evaluate(pred.cpu().numpy(), label.cpu().numpy(), 'sum')

                total_acc += te_acc
                num += output.shape[0]

                if adv_test:
                    # use predicted label as target label
                    with torch.enable_grad():
                        adv_data = self.attack.perturb(data,
                                                       pred if use_pseudo_label else label,
                                                       'mean',
                                                       False)

                    adv_output = model(adv_data, _eval=True)

                    adv_pred = torch.max(adv_output, dim=1)[1]
                    adv_acc = evaluate(adv_pred.cpu().numpy(), label.cpu().numpy(), 'sum')
                    total_adv_acc += adv_acc
                else:
                    total_adv_acc = -num

        return total_acc / num , total_adv_acc / num

def main(args):

    save_folder = '%s_%s' % (args.dataset, args.affix)

    log_folder = os.path.join(args.log_root, save_folder)
    model_folder = os.path.join(args.model_root, save_folder)

    makedirs(log_folder)
    makedirs(model_folder)

    setattr(args, 'log_folder', log_folder)
    setattr(args, 'model_folder', model_folder)

    logger = create_logger(log_folder, args.todo, 'info')

    print_args(args, logger)

    model = WideResNet(depth=34, num_classes=10, widen_factor=10, dropRate=0.0)

    attack = FastGradientSignUntargeted(model,
                                        args.epsilon,
                                        args.alpha,
                                        min_val=0,
                                        max_val=1,
                                        max_iters=args.k,
                                        _type=args.perturbation_type)

    if torch.cuda.is_available():
        model.cuda()

    trainer = Trainer(args, logger, attack)

    if args.todo == 'train':
        transform_train = tv.transforms.Compose([
                tv.transforms.RandomCrop(32, padding=4, fill=0, padding_mode='constant'),
                tv.transforms.RandomHorizontalFlip(),
                tv.transforms.ToTensor(),
            ])
        tr_dataset = tv.datasets.CIFAR10(args.data_root,
                                       train=True,
                                       transform=transform_train,
                                       download=True)

        tr_loader = DataLoader(tr_dataset, batch_size=args.batch_size, shuffle=True, num_workers=4)

        # evaluation during training
        te_dataset = tv.datasets.CIFAR10(args.data_root,
                                       train=False,
                                       transform=tv.transforms.ToTensor(),
                                       download=True)

        te_loader = DataLoader(te_dataset, batch_size=args.batch_size, shuffle=False, num_workers=4)

        trainer.train(model, tr_loader, te_loader, args.adv_train)
    elif args.todo == 'test':
        te_dataset = tv.datasets.CIFAR10(args.data_root,
                                       train=False,
                                       transform=tv.transforms.ToTensor(),
                                       download=True)

        te_loader = DataLoader(te_dataset, batch_size=args.batch_size, shuffle=False, num_workers=4)

        checkpoint = torch.load(args.load_checkpoint)
        model.load_state_dict(checkpoint)

        std_acc, adv_acc = trainer.test(model, te_loader, adv_test=True, use_pseudo_label=False)

        print(f"std acc: {std_acc * 100:.3f}%, adv_acc: {adv_acc * 100:.3f}%")

    else:
        raise NotImplementedError

if __name__ == '__main__':
    args = parser()

    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu

    main(args)


import numpy
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure

img_path = '/home/moby/PycharmProjects/datasets_processing/figures/'
plt.rcParams.update({

    'font.family': 'serif',
    'font.sans-serif': ['Times'],
    'text.latex.preamble':
        r'\usepackage[T2A]{fontenc}'
        r'\usepackage[utf8]{inputenc}'
})
classes = [
    'Normal (Без спец. техники)',
    'Muting (Пиццикато)',
    'Vibrato (Вибрато)',
    'Pull-off (Нисх. легато)',
    'Hammer-on (Восх. легато)',
    'Sliding (Глиссандо)',
    'Bending (Бенд)'
]
vals = np.array([
    2009,
    385,
    637,
    525,
    581,
    1162,
    1281
])

def absolute_value(val):
    a = numpy.round(val / 100. * vals.sum(), 0)
    return int(a)

fig1, ax1 = plt.subplots(figsize=(9, 5))
ax1.pie(vals, labels=classes, autopct=absolute_value,
        shadow=False, startangle=90,
        textprops={'fontsize': 15}
        )
# ax1.axis('equal')  # Equal aspect ratio ensures that pie is drawn as a circle
# fig1.set_size_inches(18.5, 10.5)
# plt.tight_layout()
plt.savefig(img_path + "gpt_pie" + '.pdf')
plt.show()


from SortAlgs import *
import matplotlib.pyplot as plt
import plotly.express as px
import timeit
import random
import numpy as np

N = 10000
X = [random.randint(0, N) for _ in range(N)]

naive_time = timeit.timeit("naive_sort(X, X)", globals=globals(), number=1)
merge_time = timeit.timeit("merge_sort(X, X)", globals=globals(), number=1)
count_time = timeit.timeit("count_sort(X, X)", globals=globals(), number=1)

naive_complexity = lambda n: naive_time/10000**2             * n**2
merge_complexity = lambda n: merge_time/10000/np.log2(10000) * n*np.log2(n)
count_complexity = lambda n: count_time/10000                * n

n = np.logspace(1, 10, 10000)
fig = px.line(x=n, y=naive_complexity(n)/3600/24/365.25, labels={"x": "n", "y": "time [years]"}, title="Naive sort")
fig.add_scatter(x=n, y=merge_complexity(n)/3600/24/365.25, name="Merge sort")
fig.add_scatter(x=n, y=count_complexity(n)/3600/24/365.25, name="Count sort")
fig.update_xaxes(type="log")
fig.update_yaxes(type="log")
fig.update_layout(yaxis=dict(exponentformat="power"), xaxis=dict(exponentformat="power"))
fig.show()


from __future__ import absolute_import

import logging
import tempfile
import unittest

from apache_beam.examples.cookbook import group_with_coder
from apache_beam.testing.util import open_shards

# Patch group_with_coder.PlayerCoder.decode(). To test that the PlayerCoder was
# used, we do not strip the prepended 'x:' string when decoding a Player object.
group_with_coder.PlayerCoder.decode = lambda self, s: group_with_coder.Player(  # type: ignore[assignment]
    s.decode('utf-8'))

class GroupWithCoderTest(unittest.TestCase):

  SAMPLE_RECORDS = [
      'joe,10',
      'fred,3',
      'mary,7',
      'joe,20',
      'fred,6',
      'ann,5',
      'joe,30',
      'ann,10',
      'mary,1'
  ]

  def create_temp_file(self, records):
    with tempfile.NamedTemporaryFile(delete=False) as f:
      for record in records:
        f.write(b'%s\n' % record.encode('utf-8'))
      return f.name

  def test_basics_with_type_check(self):
    # Run the workflow with pipeline_type_check option. This will make sure
    # the typehints associated with all transforms will have non-default values
    # and therefore any custom coders will be used. In our case we want to make
    # sure the coder for the Player class will be used.
    temp_path = self.create_temp_file(self.SAMPLE_RECORDS)
    group_with_coder.run(
        ['--input=%s*' % temp_path, '--output=%s.result' % temp_path],
        save_main_session=False)
    # Parse result file and compare.
    results = []
    with open_shards(temp_path + '.result-*-of-*') as result_file:
      for line in result_file:
        name, points = line.split(',')
        results.append((name, int(points)))
      logging.info('result: %s', results)
    self.assertEqual(
        sorted(results),
        sorted([('x:ann', 15), ('x:fred', 9), ('x:joe', 60), ('x:mary', 8)]))

  def test_basics_without_type_check(self):
    # Run the workflow without pipeline_type_check option. This will make sure
    # the typehints associated with all transforms will have default values and
    # therefore any custom coders will not be used. The default coder (pickler)
    # will be used instead.
    temp_path = self.create_temp_file(self.SAMPLE_RECORDS)
    group_with_coder.run([
        '--no_pipeline_type_check',
        '--input=%s*' % temp_path,
        '--output=%s.result' % temp_path
    ],
                         save_main_session=False)
    # Parse result file and compare.
    results = []
    with open_shards(temp_path + '.result-*-of-*') as result_file:
      for line in result_file:
        name, points = line.split(',')
        results.append((name, int(points)))
      logging.info('result: %s', results)
    self.assertEqual(
        sorted(results),
        sorted([('ann', 15), ('fred', 9), ('joe', 60), ('mary', 8)]))

if __name__ == '__main__':
  logging.getLogger().setLevel(logging.INFO)
  unittest.main()


from django.urls import path

from . import views
from django.urls import include, path, re_path

# /playlist
# /user/<id>

urlpatterns = [
    path('index/', views.index, name='index'), # page
    re_path('^index/registration/', views.registration),
    path('login/', views.login), # page
    path('logout/', views.logout),
    path('user/playlist', views.userlist), # page userId=1&playlistId=2
    path('userlist/track/', views.addTrack), #page
    re_path('^userlist/track/add/', views.addTrack),
    re_path('^userlists/delete/', views.userlists),  # page -_-
    re_path('^userlists/create/add/', views.addPlaylist),
    re_path('^userlists/create/', views.addPlaylist),
    path('user/playlist/modify/', views.modify_pl),
    path('user/playlist/modify/add/', views.modify_pl),
    path('user/playlist/modify/put/', views.mod_put),
    path('user/playlist/modify/put/put/', views.mod_put)
]


import io
import json
import sys

INDENT = 4 * " "
DEFAULT_NEWRESPARAM = "res"

def toCppType(t):
    if isinstance(t, list):
        if len(t) == 2:
            return "{}<{}>".format(t[0], t[1])
        elif len(t) == 3:
            return "{}<{}<{}>>".format(t[0], t[1], t[2])
        else:
            raise RuntimeError("unexpected nesting level of template types: {}".format(t))
    else:
        return t

def generateKernelInstantiation(kernelTemplateInfo, templateValues, opCodes, outFile, API):
    # Extract some information.
    opName = kernelTemplateInfo["opName"]
    returnType = kernelTemplateInfo["returnType"]
    templateParams = kernelTemplateInfo["templateParams"]
    runtimeParams = kernelTemplateInfo["runtimeParams"]
    opCodeAsTemplateParam = False
    if "opCodeAsTemplateParam" in kernelTemplateInfo:
        opCodeAsTemplateParam = True if kernelTemplateInfo["opCodeAsTemplateParam"] == 1 else False

    if len(templateParams) != len(templateValues):
        raise RuntimeError(
            f"kernel \"{opName}\" has {len(templateParams)} template parameters, but "
            f"{len(templateValues)} template values are supplied in an instantiation"
        )

    if opCodes is not None:
        # We assume that the op-code is the first run-time parameter.
        opCodeType = runtimeParams[0]["type"]
        runtimeParams = runtimeParams[1:]
    else:
        opCodeType = None

    # Create mapping from original template argument names to assigned C++
    # types.
    templateArgToCppType = {tp["name"]: toCppType(tv) for tp, tv in zip(templateParams, templateValues)}

    # ToDo: commented by mdokter - maybe remove. I think this would be too verbose
    # Comments indicating values assigned to original template arguments.
    # for tp in templateParams:
    #     outStr = INDENT + "// {} = {}\n".format(tp["name"], templateArgToCppType[tp["name"]])
    #     outFile.write(outStr)

    # The function wrapping the generated kernel instantiation always has
    # the return type void. If the considered kernel returns a scalar value,
    # we prepend an additional run-time parameter.
    extendedRuntimeParams = [
        {"name": DEFAULT_NEWRESPARAM, "type": "{} *".format(returnType), "isOutput": True}
    ] if (returnType != "void") else []
    # Add all run-time parameters of the kernel. We need to copy, because
    # we apply string replacements to the types.
    extendedRuntimeParams.extend([rp.copy() for rp in runtimeParams])
    # Replace occurences of original template arguments by their assigned
    # types.
    for rp in extendedRuntimeParams:
        for tpIdx, tp in enumerate(templateParams):
            if isinstance(templateValues[tpIdx], list):
                rp["type"] = rp["type"].replace("typename {}::VT".format(tp["name"]), templateValues[tpIdx][1])
            rp["type"] = rp["type"].replace(tp["name"], templateArgToCppType[tp["name"]])
        if rp["type"].endswith("*&"):
            rp["type"] = rp["type"][:-2] + "**"
            rp["isOutput"] = True
        if rp["type"].endswith("&"):
            rp["type"] = rp["type"][:-1]
            rp["isOutput"] = True
        elif "isOutput" not in rp:
            rp["isOutput"] = False

    isCreateDaphneContext = opName == "createDaphneContext"

    # typesForName = "__".join([("{}_{}".format(tv[0], tv[1]) if isinstance(tv, list) else tv) for tv in templateValues])
    typesForName = "__".join([
        rp["type"]
            [((rp["type"].rfind("::") + 2) if "::" in rp["type"] else 0):]
            .replace("const ", "")
            .replace(" **", "" if rp["isOutput"] else "_variadic")
            .replace(" *", "_variadic" if "isVariadic" in rp and rp["isVariadic"] else "")
            .replace("& ", "")
            .replace("<", "_").replace(">", "")
        for rp in extendedRuntimeParams
    ])
    if typesForName != "":
        typesForName = "__" + typesForName
    params = ", ".join(
        ["{} {}".format(rtp["type"], rtp["name"]) for rtp in extendedRuntimeParams] +
        ([] if isCreateDaphneContext else ["DCTX(ctx)"])
    )

    def generateFunction(opCode):
        # Obtain the name of the function to be generated from the opName by
        # removing suffices "Sca"/"Mat"/"Obj" (they are not required here), and
        # potentially by inserting the opCode into the name.
        if API != "CPP":
            funcName = API + "_" + opName
        else:
            funcName = "_" + opName
        while funcName[-3:] in ["Sca", "Mat", "Obj"]:
            funcName = funcName[:-3]
        funcName = funcName.replace("::", "_")

        if opCode is not None:
            opCodeWord = opCodeType[:-len("OpCode")]
            funcName = funcName.replace(opCodeWord, opCode[0].upper() + opCode[1:].lower())
            funcName = funcName.replace(opCodeWord.lower(), opCode.lower())

        # Signature of the function wrapping the kernel instantiation.
        outFile.write(INDENT + "void {}{}({}) {{\n".format(
            funcName,
            typesForName,
            # Run-time parameters, possibly including DaphneContext:
            params
        ))

        # List of parameters for the call.
        if opCode is None or opCodeAsTemplateParam:
            callParams = []
        else:
            callParams = ["{}::{}".format(opCodeType, opCode)]

        callParams.extend([
            # Dereference double pointer for output parameters.
            "{}{}".format("*" if (rp["type"].endswith("**") and rp["isOutput"]) else "", rp["name"])
            for rp in extendedRuntimeParams[(0 if returnType == "void" else 1):]
        ])

        # List of template parameters for the call.
        callTemplateParams = [toCppType(tv) for tv in templateValues]
        if opCodeAsTemplateParam and opCode is not None:
            opCodeWord = opCodeType[:-len("OpCode")]
            callTemplateParams = ["{}::{}".format(opCodeWord if API == "CPP" else API + "::" + opCodeWord, opCode)] + callTemplateParams

        # Body of that function: delegate to the kernel instantiation.
        outFile.write(2 * INDENT)
        if returnType != "void":
            outFile.write("*{} = ".format(DEFAULT_NEWRESPARAM))

        kernelCallString = "{}{}::apply({});\n" if opCodeAsTemplateParam else "{}{}({});\n"

        outFile.write(kernelCallString.format(
            opName if API == "CPP" else (API + "::" + opName),
            # Template parameters, if the kernel is a template:
            "<{}>".format(", ".join(callTemplateParams)) if len(templateValues) else "",
            # Run-time parameters, possibly including DaphneContext:
            ", ".join(callParams + ([] if isCreateDaphneContext else ["ctx"])),
        ))
        outFile.write(INDENT + "}\n")

    # Generate the function(s).
    if opCodes is None:
        generateFunction(None)
    else:
        for opCode in opCodes:
            generateFunction(opCode)
    # outFile.write(INDENT + "\n")

def printHelp():
    print("Usage: python3 {} INPUT_SPEC_FILE OUTPUT_CPP_FILE API".format(sys.argv[0]))
    print(__doc__)

if __name__ == "__main__":
    if len(sys.argv) == 2 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
        printHelp()
        sys.exit(0)
    elif len(sys.argv) != 4:
        print("Wrong number of arguments.")
        print()
        printHelp()
        sys.exit(1)
    # Parse arguments.
    inFilePath = sys.argv[1]
    outFilePath = sys.argv[2]
    API = sys.argv[3]
    ops_inst_str = ""
    header_str = ""

    # Load the specification (which kernel template shall be instantiated
    # with which template arguments) from a JSON-file.
    with open(inFilePath, "r") as inFile:
        kernelsInfo = json.load(inFile)

        for kernelInfo in kernelsInfo:
            kernelTemplateInfo = kernelInfo["kernelTemplate"]
            if "api" in kernelInfo:
                for api in kernelInfo["api"]:
                    for name in api["name"]:
                        # print("Processing API: " + name)
                        # print("  OpName: " + kernelTemplateInfo["opName"])
                        # print("  Instantiations: " + str(api["instantiations"]))
                        # if "opCodes" in api:
                        #     print("  opCodes: " + str(api["opCodes"]))
                        if name == API:
                            # Comment reporting the kernel name.
                            ops_inst_str += INDENT + "// {}\n".format("-" * 76)
                            ops_inst_str += INDENT + "// {}\n".format(kernelTemplateInfo["opName"])
                            ops_inst_str += INDENT + "// {}\n".format("-" * 76)

                            # Include for the required header.
                            if API != "CPP":
                                header_str = header_str + "#include <runtime/local/kernels/{}/{}>\n".format(API, kernelTemplateInfo["header"])
                            else:
                                header_str = header_str + "#include <runtime/local/kernels/{}>\n".format(kernelTemplateInfo["header"])

                            outBuf = io.StringIO()
                            for instantiation in api["instantiations"]:
                                generateKernelInstantiation(kernelTemplateInfo, instantiation,
                                                            api.get("opCodes", None), outBuf, API)
                            ops_inst_str += outBuf.getvalue()
            else:
                if API == "CPP":
                    # Comment reporting the kernel name.
                    ops_inst_str += INDENT + "// {}\n".format("-" * 76)
                    ops_inst_str += INDENT + "// {}\n".format(kernelTemplateInfo["opName"])
                    ops_inst_str += INDENT + "// {}\n".format("-" * 76)

                    # Include for the required header.
                    header_str = header_str + "#include <runtime/local/kernels/{}>\n".format(kernelTemplateInfo["header"])
                    # One function per instantiation of the kernel.
                    opCodes = kernelInfo.get("opCodes", None)
                    outBuf = io.StringIO()
                    for instantiation in kernelInfo["instantiations"]:
                        generateKernelInstantiation(kernelTemplateInfo, instantiation, opCodes, outBuf, API)
                    ops_inst_str += outBuf.getvalue()

    with open(outFilePath, "w") as outFile:
        outFile.write("// This file was generated by {}. Don't edit manually!\n\n".format(sys.argv[0]))
        outFile.write("#include <runtime/local/context/DaphneContext.h>\n")
        outFile.write(header_str)
        outFile.write("\nextern \"C\" {\n")
        outFile.write(ops_inst_str)
        outFile.write("}\n")


import sys
import os
import subprocess
import graphviz_gen

from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QPlainTextEdit, QVBoxLayout
from PySide6.QtCore import QFile, QThread, Slot, Qt
from PySide6.QtUiTools import QUiLoader
from PySide6.QtSvgWidgets import QSvgWidget

class Base(QWidget):
    def __init__(self):
        super(Base, self).__init__()
        self.load_ui()
        # self.thread = Worker()
        self.domain_in = self.ui.findChild(QLineEdit, "domain_in")
        self.text_box = self.ui.findChild(QPlainTextEdit, "log_out")
        self.btn = self.ui.findChild(QPushButton, 'rs_button')
        self.graph_btn = self.ui.findChild(QPushButton, 'graph_btn')

    def load_ui(self):
        loader = QUiLoader()
        path = os.path.join(os.path.dirname(__file__), "form.ui")
        ui_file = QFile(path)
        ui_file.open(QFile.ReadOnly)
        self.ui = loader.load(ui_file, self)
        ui_file.close()

class GraphWindow(QWidget):
    def __init__(self, path):
        super().__init__()
        layout = QVBoxLayout()
        self.svg_wid = QSvgWidget(self)
        self.svg_wid.load(path)
#        self.svg_wid.show()
        layout.addWidget(self.svg_wid)
        self.setLayout(layout)

class Implement(Base):
    def __init__(self):
        super().__init__()
        self.w = None
        print(self.text_box)
        self.btn.clicked.connect(self.run_script)
        self.graph_btn.clicked.connect(self.graph_disp)

    @Slot()
    def run_script(self):
        text_value = self.domain_in.text()
        print(type(text_value))
        out_file = open("output", 'w')
        script_path = "{insert your path here for the bash script }"
        rc = subprocess.run(
            [script_path, text_value],
            stdout=out_file,
            stderr=subprocess.PIPE
        )
        out_file.close()
        self.show_output_box()

    @Slot()
    def show_output_box(self):
        out_file = open("output").read()
        print(out_file)
        self.text_box.clear()
        self.text_box.insertPlainText(out_file)

    def graph_disp(self):
        graphviz_gen.gengraph(self.domain_in.text())
#        if self.w is None:
        print(self.domain_in.text())
        self.w = GraphWindow("final_graph"+self.domain_in.text()+".svg")
        self.w.show()

if __name__ == "__main__":
    app = QApplication([])
    widget = Implement()
    widget.show()
#    widget.show_ui_object()
    sys.exit(app.exec_())


"""
Snapping
"""

def snap_points_to_near_line(lineShp, pointShp, epsg, workGrass,
                             outPoints, location='overlap_pnts', api='grass',
                             movesShp=None):
    """
    Move points to overlap near line

    API's Available:
    * grass;
    * saga.
    """

    if api == 'grass':
        """
        Uses GRASS GIS to find near lines.
        """

        import os;          import numpy
        from geopandas      import GeoDataFrame
        from glass.pys.oss  import fprop
        from glass.wenv.grs import run_grass
        from glass.rd.shp   import shp_to_obj
        from glass.wt.shp   import df_to_shp

        # Create GRASS GIS Location
        grassBase = run_grass(workGrass, location=location, srs=epsg)

        import grass.script as grass
        import grass.script.setup as gsetup
        gsetup.init(grassBase, workGrass, location, 'PERMANENT')

        # Import some GRASS GIS tools
        from glass.gp.prox      import grs_near as near
        from glass.tbl.attr  import geomattr_to_db
        from glass.it.shp import shp_to_grs, grs_to_shp

        # Import data into GRASS GIS
        grsLines = shp_to_grs(
            lineShp, fprop(lineShp, 'fn', forceLower=True)
        )

        grsPoint = shp_to_grs(
            pointShp, fprop(pointShp, 'fn', forceLower=True)
        )

        # Get distance from points to near line
        near(grsPoint, grsLines, nearCatCol="tocat", nearDistCol="todistance")

        # Get coord of start/end points of polylines
        geomattr_to_db(grsLines, ['sta_pnt_x', 'sta_pnt_y'], 'start', 'line')
        geomattr_to_db(grsLines, ['end_pnt_x', 'end_pnt_y'],   'end', 'line')

        # Export data from GRASS GIS
        ogrPoint = grs_to_shp(grsPoint, os.path.join(
            workGrass, grsPoint + '.shp', 'point', asMultiPart=True
        ))

        ogrLine = grs_to_shp(grsLines, os.path.join(
            workGrass, grsLines + '.shp', 'point', asMultiPart=True
        ))

        # Points to GeoDataFrame
        pntDf = shp_to_obj(ogrPoint)
        # Lines to GeoDataFrame
        lnhDf = shp_to_obj(ogrLine)

        # Erase unecessary fields
        pntDf.drop(["todistance"], axis=1, inplace=True)
        lnhDf.drop([c for c in lnhDf.columns.values if c != 'geometry' and
                    c != 'cat' and c != 'sta_pnt_x' and c != 'sta_pnt_y' and
                    c != 'end_pnt_x' and c != 'end_pnt_y'],
                    axis=1, inplace=True)

        # Join Geometries - Table with Point Geometry and Geometry of the
        # nearest line
        resultDf = pntDf.merge(
            lnhDf, how='inner', left_on='tocat', right_on='cat')

        # Move points
        resultDf['geometry'] = [geoms[0].interpolate(
            geoms[0].project(geoms[1])
        ) for geoms in zip(resultDf.geometry_y, resultDf.geometry_x)]

        resultDf.drop(["geometry_x", "geometry_y", "cat_x", "cat_y"],
                      axis=1, inplace=True)

        resultDf = GeoDataFrame(
            resultDf, crs={"init" : 'epsg:{}'.format(epsg)}, geometry="geometry"
        )

        # Check if points are equal to any start/end points
        resultDf["x"] = resultDf.geometry.x
        resultDf["y"] = resultDf.geometry.y

        resultDf["check"] = numpy.where(
            (resultDf["x"] == resultDf["sta_pnt_x"]) & (resultDf["y"] == resultDf["sta_pnt_y"]),
            1, 0
        )

        resultDf["check"] = numpy.where(
            (resultDf["x"] == resultDf["end_pnt_x"]) & (resultDf["y"] == resultDf["end_pnt_y"]),
            1, 0
        )

        # To file
        df_to_shp(resultDf, outPoints)

    elif api == 'saga':
        """
        Snap Points to Lines using SAGA GIS
        """

        from glass.pys  import execmd

        mv="" if not movesShp else f" -MOVES {movesShp}"

        cmd = (
            f"saga_cmd shapes_points 19 -INPUT {pointShp} "
            f"-SNAP {lineShp} "
            f"-OUTPUT {outPoints}{mv}"
        )

        outcmd = execmd(cmd)

    else:
        raise ValueError(f"{api} is not available!")

    return outPoints