from utils import *
from model import DFHNet, SphereNet_hashing
import torch.backends.cudnn as cudnn
import argparse
from torchvision import datasets
from torch.utils.data import DataLoader
import time

"""
Model configuration and evaluation.
Support evaluation metrics: mAP, top-k, Precision@H=2, Recall@H=2
"""

parser = argparse.ArgumentParser(description='Evaluation on three datasets: {Facescrub, YouTubeFaces, VGGFace}; Supported metrics: {mAP, precision, recall, top-k}')
parser.add_argument('--load', type=str, help='Path to load the model')
parser.add_argument('--dataset', type=str, default='facescrub', help='should be one of {facescrub, youtube, vgg}')
parser.add_argument('--bs', type=int, default=256, help='Batch size of each iteration')
parser.add_argument('--len', type=int, default=48,
                    help='length of hashing codes,  should be one of {12, 24, 36, 48}')

args = parser.parse_args()

model_path = args.load
bits = args.len
dataset = args.dataset
device = "cuda:0" if torch.cuda.is_available() else "cpu"
cudnn.benchmark = True

def evaluation(model_path, bits, dataset):

    if dataset in ['facescrub', 'youtube']:

        transform_tensor = transforms.Compose([
            transforms.ToTensor()
        ])
        trainset = MyDataset(dataset, transform=transform_tensor, train=True)
        trainloader = DataLoader(trainset, batch_size=args.bs, shuffle=True)
        classes = len(np.unique(trainset.train_y))
        testset = MyDataset(dataset, transform=transform_tensor, train=False)
        testloader = DataLoader(testset, batch_size=args.bs, shuffle=False)
        net = DFHNet(bits)

    else:
        trainPaths = "./vgg_face2/train"
        testPaths = "./vgg_face2/test"
        Normalize = transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
        transform_test = transforms.Compose([
                    transforms.Resize(120),
                    transforms.CenterCrop(112),
                    transforms.ToTensor(),
                    Normalize])

        trainset = datasets.ImageFolder(root=trainPaths, transform=transform_test)
        trainloader = torch.utils.data.DataLoader(trainset, batch_size=args.bs, shuffle=True, num_workers=4)

        testset = datasets.ImageFolder(root=testPaths, transform=transform_test)
        testloader = torch.utils.data.DataLoader(testset, batch_size=args.bs, shuffle=False, num_workers=4)
        net = SphereNet_hashing(num_layers=20, hashing_bits=bits)
    net.to(device)
    top_list = torch.tensor([1, 5, 10]).int().tolist()

    checkpoint = torch.load('./checkpoint/%s' % model_path)
    print("evaluation on %s" % model_path)
    net.load_state_dict(checkpoint['backbone'])

    net.eval()
    with torch.no_grad():
        trainB, train_labels = compute_result(trainloader, net, device)
        testB, test_labels = compute_result(testloader, net, device)
        since = time.time()
        mAP = compute_mAP(trainB, testB, train_labels, test_labels, device)
        time_elapsed = time.time() - since
        print('[Evaluate Phase] MAP: %.2f%%' % (100. * float(mAP)))
        print("Calculate mAP in {:.0f} min {:.0f}s".format(time_elapsed // 60, time_elapsed % 60))
        print("=================================")

        top_results = compute_topK(trainB, testB, train_labels, test_labels, device, top_list)
        for i in range(len(top_list)):
            print("top%d: %.2f%%" %(top_list[i], 100. * top_results[i]))
        print("=================================")

        precision, recall = evaluate_recall_pre(train_labels, test_labels, trainB, testB, device)
        print('Precision with Hamming radius_2 : {:.2%}'.format(precision))
        print('Recall with Hamming radius_2 : {:.2%}'.format(recall))

if __name__ == '__main__':

    assert os.path.exists(os.path.join("./checkpoint", args.load)),  "invalid model path in the default directory"
    evaluation(model_path, bits, dataset)


import sys
from typing import List
from extract_column_data import TextPosition

class LabResult:
    ref_value_min = ''
    ref_value_max = ''

    def __init__(self, label: TextPosition, result: TextPosition, unit: TextPosition):
        if label is None:
            self.label = ''
        else:
            self.label = label.text

        if result is None:
            self.result = None
        else:
            self.result = result.text

        if unit is None:
            self.unit = ''
        else:
            self.unit = unit.text

    def set_ref_value(self, text: str):
        if text is not None:
            if text.lstrip().startswith('<'):
                self.ref_value_max = text.split('<')[1]
            elif text.lstrip().startswith('>'):
                self.ref_value_min = text.split('>')[1]
            splitted = text.split('-', 1)
            if len(splitted) == 2:
                min, max = splitted
                self.ref_value_min = min
                self.ref_value_max = max

# a = LabResult(None, None, None)
# a.set_ref_value(' >234  ')
# print(a.ref_value_min)
# print(a.ref_value_max)

class _ColumnData:
    def __init__(self, column_data: List[TextPosition]):
        self.idx = -1
        self.column_data = column_data
        self.increment()

    def increment(self):
        if self.idx + 1 < len(self.column_data):
            self.idx += 1
        else:
            self.idx = -1

    def get(self) -> TextPosition:
        if self.idx != -1:
            return self.column_data[self.idx]
        else:
            return None

# merge text that lies in the same line basing on the y coordinate
def merge_lab_result(labels: List[TextPosition], results: List[TextPosition], units: List[TextPosition], references: List[TextPosition], max_line_deviation=10.)->List[LabResult]:
    data = [_ColumnData(labels), _ColumnData(results), _ColumnData(units)]
    if references is not None:
        data.append(_ColumnData(references))
    data_merged = merge_text_positions(data, max_line_deviation)
    res: List[LabResult] = []
    for line in data_merged:
        lab_result = LabResult(line[0], line[1], line[2])
        if len(line) > 3 and line[3] is not None:
            lab_result.set_ref_value(line[3].text)
        res.append(lab_result)

    return res

def merge_text_positions(data: List[_ColumnData], max_line_deviation: float = 10.):
    res = []

    while True:
        # get data currently pointed by indexes of each column
        current_idx_data: List[TextPosition] = []
        current_min_y = sys.maxsize

        for column in data:
            current_idx_data.append(column.get())

            if column.get() is not None:
                # check which y is the lowest -> which comes first
                current_min_y = min(current_min_y, column.get().y1)

        # break the loop is there is no data to process (all column.get() returned None)
        if current_min_y == sys.maxsize:
            break

        # start comparing, checking which data is coming first in the column or lying in the same line
        line_data = []
        previous_y = current_min_y
        for i in range(len(current_idx_data)):
            column_line = current_idx_data[i]

            # is None only if no more elements left in this column
            if column_line is None:
                line_data.append(None)
                continue

            if abs(column_line.y1 - previous_y) <= max_line_deviation:
                # lies in the same line with the previous element
                line_data.append(column_line)

                # set new previous_y
                previous_y = column_line.y1
                # data used, increment the index
                data[i].increment()
                continue
            else:
                # this column has no element in this line, append None
                line_data.append(None)
                continue

        res.append(line_data)

    return res


from dominantcolors import get_image_dominant_colors
from pathlib import Path
import numpy as np
from PIL import Image
from colorsys import rgb_to_hsv
from math import ceil
from random import randint

class Art:
    """Store path and color information of each image in the collage for sorting"""

    def __init__(self,path):
        self.path = path
        self.dom_col = [255,255,255]

    def grab_color(self):
        dominant_colors = get_image_dominant_colors(image_path=self.path, num_colors=1)
        self.dom_col = dominant_colors[0]

    def __str__(self):
        return str(self.dom_col)

    def __repr__(self):
        return str(self.dom_col)

    def __len__(self):
        return len(self.dom_col)

def color_key_HSV(art):
    return rgb_to_hsv(art.dom_col[0],art.dom_col[1],art.dom_col[2])

def color_key_RGB(art):
    return art.dom_col

def create_image(init_path, out_path, out_name, sort_key_str,ratio,use_perfect_ratio,ratio_fixer, subimage_size=50,format="PNG"):
    """Core function: Gather files in folder, generate object lists and call collage(). Save output"""
    # initialize Directory
    directory = init_path
    png_list = Path(directory).glob('*.png')
    jpg_list = Path(directory).glob('*.jpg')
    art_list = []

    #Create a list of art objects to sort
    for path in png_list:
        new_art = Art(path)
        new_art.grab_color()
        art_list.append(new_art)
    for path in jpg_list:
        new_art = Art(path)
        new_art.grab_color()
        art_list.append(new_art)

    if sort_key_str == 'RGB':
        sort_key = color_key_RGB
    elif sort_key_str == 'HSV':
        sort_key = color_key_HSV
    else:
        sort_key = color_key_HSV

    art_list.sort(key=sort_key)
    list_len = len(art_list)

    ratio_1 = int(ratio[0])
    ratio_2 = int(ratio[1])

    if use_perfect_ratio == False:

        result = collage(list_len,art_list,subimage_size,ratio_1,ratio_2)

    elif use_perfect_ratio == True:
        if ratio_fixer == "stretch":

            result = collage(list_len, art_list, subimage_size, 1, 1)

            newsize = (int(result.size[0]*ratio_1/2),int(result.size[1]*ratio_2/2))

            result.resize(newsize)

        if ratio_fixer == "fill":

            ratio_mult = ratio_1*ratio_2

            tiles_to_add = int(ratio_mult*(ceil(list_len/ratio_mult)**2)-list_len)

            for adds in range(tiles_to_add):
                add_art = Art("fill_square.png")
                rand_pos = randint(1,list_len-1)

                art_list.insert(rand_pos,add_art)

            list_len = len(art_list)

            result = collage(list_len, art_list, subimage_size, ratio_1, ratio_2)

    if format == "PNG":
        result.save(str(out_path + "/" + out_name + '.png'), format="png")
    else:
        result.save(str(out_path + "/" + out_name + '.jpg'), format="jpg")

def collage(list_len,art_list,subimage_size,ratio_1,ratio_2):
    """Helper func for create_image(): perform calculations to organize the collage of desired ratio"""

    factors = []
    for i in range(1, list_len + 1):
        if list_len % i == 0:
            factors.append(i)

    fac_combos = set()
    for factor in range(len(factors) // 2):
        fac_combos.add((factors[factor], factors[-factor - 1]))
        print(fac_combos)

    closest = min(fac_combos, key=lambda x: abs((x[1] / x[0]) - (ratio_1 / ratio_2)))
    print(closest)

    data = np.array([art_list])
    newdata = data.reshape(closest)
    print(newdata)

    image_size = (closest[0] * subimage_size, closest[1] * subimage_size)

    result = Image.new("RGB", image_size)

    for ximg in range(closest[0]):
        for yimg in range(closest[1]):
            current_art = newdata[ximg][yimg]
            current_img = Image.open(current_art.path)
            current_img = current_img.resize((subimage_size, subimage_size))
            result.paste(current_img, (ximg * subimage_size, yimg * subimage_size))

    return result


"""Module for export of pairs data in pickle format for FR3D.
"""

import numpy as np
import os
import pickle

from pymotifs import core
from pymotifs import models as mod

from pymotifs.chains.info import Loader as ChainLoader
from pymotifs.units.centers import Loader as CentersLoader
from pymotifs.units.rotation import Loader as RotationsLoader
from pymotifs.exp_seq.mapping import Loader as MappingLoader
from pymotifs.exp_seq.positions import Loader as PositionLoader
from pymotifs.ife.info import Loader as IfeInfoLoader

from collections import defaultdict

from os import path

from sqlalchemy import and_
from sqlalchemy.orm import aliased
from sqlalchemy.sql import select
from sqlalchemy.sql import union

class Exporter(core.Loader):
    """Export pairs data in pickle format, one file per PDB.
    """

    # General Setup
    compressed = False
    mark = False
    dependencies = set([ChainLoader, CentersLoader, RotationsLoader,
                        PositionLoader, IfeInfoLoader, MappingLoader])

    def has_data(self, pdb, *args, **kwargs):
        self.logger.info("has_data: pdb: %s" % str(pdb))
        filename = self.filename(pdb)
        self.logger.info("has_data: filename: %s" % filename)
        if os.path.exists(filename) is True:
            self.logger.info("has_data: filename %s exists" % filename)
            return True
        self.logger.info("has_data: filename %s is missing" % filename)
        return False

    def remove():
        pass

    def filename(self, pdb, **kwargs):
        """Create the filename for the given PDB.

        Parameters
        ----------
        pdb : string
            The PDB ID for which to create a file.

        Returns
        -------
        filename : str
            The path to write to.
        """

        # TO DO: put the important directories into the config

        filename = pdb + '_RNA_pairs.pickle'

        self.logger.info("filename: filename: %s" % filename)

        return os.path.join("pickle-FR3D",filename)

    def data(self, pdb, **kwargs):
        """Get all pairs for the given PDB and format them for
        convenient use by FR3D.

        Parameters
        ----------
        pdb : string
            The PDB ID for which to look up pairs data.

        Returns
        -------
        resultset : list of dicts
        """

        with self.session() as session:
            self.logger.info("data: Inside data retrieval routine")
            self.logger.info("data: building query")

            fui1 = aliased(mod.UnitInfo)
            fui2 = aliased(mod.UnitInfo)
            fupf = mod.UnitPairsFlanking
            fupi = mod.UnitPairsInteractions

            iui1 = aliased(mod.UnitInfo)
            iui2 = aliased(mod.UnitInfo)
            iupf = mod.UnitPairsFlanking
            iupi = mod.UnitPairsInteractions

            subqueryI = session.query(iupi.unit_id_1,
                               iupi.unit_id_2,
                               iui1.model,
                               iui1.chain,
                               iui1.chain_index,
                               iui2.model,
                               iui2.chain,
                               iui2.chain_index,
                               iupi.f_lwbp,
                               iupi.f_stacks,
                               iupi.f_bphs,
                               iupi.f_brbs,
                               iupi.f_crossing,
                               iupf.flanking).\
                    join(iui1, iupi.unit_id_1 == iui1.unit_id).\
                    join(iui2, iupi.unit_id_2 == iui2.unit_id).\
                    outerjoin(iupf, and_(iupi.unit_id_1 == iupf.unit_id_1, iupi.unit_id_2 == iupf.unit_id_2,
                              iupi.pdb_id == iupf.pdb_id)).\
                    filter(iupi.unit_id_1.isnot(None)).\
                    filter(iupi.unit_id_2.isnot(None)).\
                    filter(iui1.unit_type_id == 'rna').\
                    filter(iui2.unit_type_id == 'rna').\
                    filter(iupi.pdb_id == pdb)

            subqueryF = session.query(fupf.unit_id_1,
                               fupf.unit_id_2,
                               fui1.model,
                               fui1.chain,
                               fui1.chain_index,
                               fui2.model,
                               fui2.chain,
                               fui2.chain_index,
                               fupi.f_lwbp,
                               fupi.f_stacks,
                               fupi.f_bphs,
                               fupi.f_brbs,
                               fupi.f_crossing,
                               fupf.flanking).\
                    join(fui1, fupf.unit_id_1 == fui1.unit_id).\
                    join(fui2, fupf.unit_id_2 == fui2.unit_id).\
                    outerjoin(fupi, and_(fupi.unit_id_1 == fupf.unit_id_1, fupi.unit_id_2 == fupf.unit_id_2,
                              fupi.pdb_id == fupf.pdb_id)).\
                    filter(fupf.unit_id_1.isnot(None)).\
                    filter(fupf.unit_id_2.isnot(None)).\
                    filter(fui1.unit_type_id == 'rna').\
                    filter(fui2.unit_type_id == 'rna').\
                    filter(fupf.pdb_id == pdb)

            query = subqueryI.union(subqueryF).order_by(iui1.model, iui1.chain, iui1.chain_index,
                               iui2.model, iui2.chain, iui2.chain_index)

            self.logger.debug("data: query built: %s" % str(query))

            count = query.count()
            if not count:
                self.logger.warning("No interactions found for %s", pdb)
            else:
                self.logger.info("Found %s interactions for %s", count, pdb)

            # TO DO:  implement parsing logic from pairFileParsing.py here
            # and return that data instead of the full load.

            constraintToPair = defaultdict(list)

            #constraintList = ['f_lwbp', 'f_stacks', 'f_bphs', 'f_brbs']

            for result in query:
                uid1 = result.unit_id_1
                uid2 = result.unit_id_2

                # FUTURE: iterate over a list of column names?

                if( result.f_lwbp is not None and len(result.f_lwbp) > 2):
                    constraintToPair[result.f_lwbp].append((uid1, uid2, result.f_crossing))
                    self.logger.debug("type: units/constraint: %s : %s, %s / %s" % (result.f_lwbp, uid1, uid2, result.f_crossing))

                if( result.f_stacks is not None and len(result.f_stacks) > 2):
                    constraintToPair[result.f_stacks].append((uid1, uid2, result.f_crossing))
                    self.logger.debug("type: units/constraint: %s : %s, %s / %s" % (result.f_stacks, uid1, uid2, result.f_crossing))

                if( result.f_bphs is not None and len(result.f_bphs) > 2):
                    constraintToPair[result.f_bphs].append((uid1, uid2, result.f_crossing))
                    self.logger.debug("type: units/constraint: %s : %s, %s / %s" % (result.f_bphs, uid1, uid2, result.f_crossing))

                if( result.f_brbs is not None and len(result.f_brbs) > 2):
                    constraintToPair[result.f_brbs].append((uid1, uid2, result.f_crossing))
                    self.logger.debug("type: units/constraint: %s : %s, %s / %s" % (result.f_brbs, uid1, uid2, result.f_crossing))

                #for constraint in constraintList:
                #    self.logger.info("constraint: %s" % constraint)
                #    #self.logger.info("constraint value: %s" % result.constraint.value())
                #    #if len(result.constraint.value()) > 2:
                #    #    constraintToPair[constraint].append((uid1, uid2, result.f_crossing))
                #    #    self.logger.info("type: units/constraint: %s : %s, %s / %s" % (result.getAttr(constraint), uid1, uid2, result.f_crossing))
                #    pass

                if result.flanking == "1":
                    constraintToPair["bSS"].append((uid1, uid2, None))
                    self.logger.debug("type: units/constraint: bSS : %s, %s / None" % (uid1, uid2))

                pass

            #return [row2dict(result) for result in query] # full load data for testing
            return constraintToPair

    def process(self, entry, **kwargs):
        """Load centers/rotations data for the given IFE-chain.

        Parameters
        ----------
        entry : object
            The entry to process.
        **kwargs : dict
            Generic keyword arguments.
        """

        webroot = self.config['locations']['fr3d_pickle_base'] + "/pairs/"

        filename = self.filename(entry)

        pinfo = self.data(entry)

        self.logger.debug("process: raw data: %s" % pinfo)

        with open(filename, 'wb') as fh:
            self.logger.info("process: filename open: %s" % filename)
            # Use 2 for "HIGHEST_PROTOCOL" for Python 2.3+ compatibility.
            pickle.dump(pinfo, fh, 2)

        os.system("rsync -u %s %s" % (filename, webroot))
        self.logger.info("rsync -u %s %s" % (filename, webroot))

        pass


def calc_fib_huge(n,m):
    a = []
    b = []
    a.append(0)
    a.append(1)
    b.append(0)
    b.append(1)
    if n >m :
        n,m=m,n
    for i in range(2, n + 3):
        a.append(a[i - 1]+a[i - 2])

    for i in range(2, m + 3):
        b.append(b[i - 1] + b[i - 2])
    if n==m :
        return a[n] % 10
    return ((b[m+2]-1)-(a[n+1]-1))%10
if __name__=="__main__":
    n ,m =[int(x) for x in input().split()]
    print(calc_fib_huge(n,m))


import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QLabel, QWidget, QPushButton, QLineEdit

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("KakaoTalk-like Application")
        self.setGeometry(100, 100, 600, 800)

        # Create a central widget and set it as the main window's central widget
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)

        # Create a layout for the central widget
        layout = QVBoxLayout(central_widget)
        layout.setContentsMargins(0, 0, 0, 0)  # Remove margins

        # Create and add labels to the layout
        label1 = QLabel("Label 1")
        label2 = QLabel("Label 2")
        label3 = QLabel("Label 3")
        layout.addWidget(label1)
        layout.addWidget(label2)
        layout.addWidget(label3)

        # Create and add line edits to the layout
        line_edit1 = QLineEdit()
        line_edit2 = QLineEdit()
        line_edit3 = QLineEdit()
        layout.addWidget(line_edit1)
        layout.addWidget(line_edit2)
        layout.addWidget(line_edit3)

        # Create and add push buttons to the layout
        button1 = QPushButton("Button 1")
        button2 = QPushButton("Button 2")
        button3 = QPushButton("Button 3")
        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(button3)

        # Apply stylesheet to the labels, line edits, and push buttons
        self.setStyleSheet("""
            QLabel, QLineEdit, QPushButton {
                color: white;
                background-color: #2E323D;
                padding: 10px;
                font-size: 18px;
                border-radius: 8px;
            }
        """)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())


import matplotlib.pyplot as plt
import numpy as np
from gp.predict import *
X_train = np.arange(0,10,0.1).reshape(100,1)
y_train = np.sin(X_train)
X = np.arange(0,10,0.5).reshape(20,1)
y = np.sin(X)
ypred = predict(X,X_train,y_train,phi=0.1,tau=0.1)

plt.plot(X_train,y_train)
plt.scatter(X,ypred)
plt.show()


#create a node class
class Node:
	def __init__(self, val = 0):
		self.val = val
		self.next = None

#create a linked list
class LinkedList:
	def __init__(self):
		self.size = 0
		self.head = None
		self.tail = None

	def isEmpty(self):
		return self.size == 0

	def addFirst(self, val):
		newNode = Node(val)
		if self.isEmpty():
			self.head = newNode
			self.tail = newNode
		else:
			newNode.next = self.head
			self.head = newNode

		self.size += 1

	def addLast(self, val):
		newNode = Node(val)
		if self.isEmpty():
			self.head = newNode
			self.tail = newNode
		else:
			self.tail.next = newNode
			self.tail = newNode

		self.size += 1

list = LinkedList()

# list.addFirst(1)
# list.addFirst(2)
# list.addFirst(3)

print(list.isEmpty())

# list.addLast(3)
# list.addLast(2)
# list.addLast(1)

nodeList = Node(1)
nodeList.next = Node(1)
nodeList.next.next = Node(2)
nodeList.next.next.next = Node(3)
nodeList.next.next.next.next = Node(3)

def print_list():
	curr = nodeList
	while curr.next is not None:
		print(curr.val)
		curr = curr.next

	print(curr.val)

def remove_duplicates():
	if nodeList is None or nodeList.next is None:
		return
	else:
		curr = nodeList
		prev = None
		while curr.next is not None:
			if prev is None:
				prev = curr

			curr = curr.next
			if prev.val != curr.val:
				prev.next = curr
				prev = prev.next

		curr = curr.next
		prev.next = curr

remove_duplicates()
print_list()


import torch.nn as nn
from transformers import AutoConfig, AutoModel
from transformers import LongformerModel, LongformerConfig
from config import config
import sklearn
import torch
import numpy as np

class LFModel(nn.Module):
    def __init__(self):
        super(LFModel, self).__init__()
        #configuration = LongformerConfig(attention_window = 512)
        self.model = AutoModel.from_pretrained("jpwahle/longformer-base-plagiarism-detection")

        self.dropout = nn.Dropout(0.2)
        self.fc1 = nn.Linear(768, 512)
        self.fc2 = nn.Linear(512, 128)
        self.fc3 = nn.Linear(128, 64)
        self.o = nn.Linear(64, 13)

        self.relu = nn.ReLU()

    def forward(self, input_ids, attention_mask):
        x = self.model(input_ids, attention_mask)
        x = self.dropout(x.pooler_output)
        x = self.fc1(x)
        x = self.dropout(x)
        x = self.fc2(x)
        x = self.dropout(x)
        x = self.fc3(x)
        x = self.dropout(x)
        x = self.o(x)
        x = self.relu(x)
        return x


import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix
from collections import Counter
import os
import json
# load C:\@code\APIMISUSE\data\misuse_jsons\auto_langchain\misuse_classification.json
with open('C:\@code\APIMISUSE\data\misuse_jsons\\auto_langchain\misuse_classification_v2_VSDB_diff_only_refine.json', encoding="utf-8") as f:
    data = f.readlines()
    data = [line for line in data if line != "\n"]
    for idx in range(len(data)):
        data[idx] = json.loads(data[idx])
    # data = [json.loads(line) for line in data]

# load C:\@code\APIMISUSE\data\misuse_jsons\manual\merged_split_hunk_AST_filter_manual_deduplica_reduced_category.json
with open('C:\@code\APIMISUSE\data\misuse_jsons\\auto_langchain\misuse_v2_compare.json', encoding="utf-8") as f:
    data_manual = f.readlines()
    data_manual = [line for line in data_manual if line != "\n"]
    data_manual = [json.loads(line) for line in data_manual]
    data_manual = [line for line in data_manual if line["manual_label"] != line["auto_label"]]

# load torch list C:\@code\APIMISUSE\data\API_method_list_torch.txt
API_method_list = []
with open('C:\@code\APIMISUSE\data\API_method_list_torch.txt', encoding="utf-8") as f:
    API_data = f.readlines()
    for x in API_data:
        if x != "\n":
            API_method_list.append(x.strip().lower())
with open('C:\@code\APIMISUSE\data\API_method_list_tf.txt', encoding="utf-8") as f:
    API_data = f.readlines()
    for x in API_data:
        if x != "\n":
            API_method_list.append(x.strip().lower())

no_API_counter = 0
wrong_manual_counter = 0
wrong_auto_counter = 0
y_test = []
y_pred = []
for idx in range(len(data)):
    number = data[idx]["number"]
    for data_manual_idx in data_manual:
        if data_manual_idx["number"] == number:
            break

    print(idx)
    if "if_API_misuse_fix" in data[idx]["misuse_classification"]:
        auto_label = data[idx]["misuse_classification"]['if_API_misuse_fix']
    if "If_API_misuse_fix" in data[idx]["misuse_classification"]:
        auto_label = data[idx]["misuse_classification"]['If_API_misuse_fix']
    auto_label = auto_label.strip().lower().replace(
        " ", "").replace("\n", "").replace("na", "no")

    manual_label = data_manual_idx["manual_label"]
    change = data_manual_idx["change"]
    added = data_manual_idx["added"]
    removed = data_manual_idx["removed"]
    number = data_manual_idx["number"]
    check_API ="False"
    for API_name in API_method_list:

        if API_name in added:
            check_API="True"
        if API_name in removed:
            check_API="True"
    if check_API == "False":
        no_API_counter += 1
        if manual_label == "yes":
            wrong_manual_counter += 1
        if auto_label == "yes":
            wrong_auto_counter += 1
            auto_label = "no"

    y_test.append(manual_label)
    y_pred.append(auto_label)

    if manual_label == "no" and auto_label == "yes":
        print("number: ")
        print(number)
        print("change: ")
        print(change)
        print("code explain: ")
        print(list(data_manual_idx.values())[-1])
        print("reason of fix: ")
        print(list(data[idx]["misuse_classification"].values())[-1])

# frequency counter
print(Counter(y_test))
print(Counter(y_pred))
print("no_API_counter", no_API_counter)
print("wrong_manual_counter", wrong_manual_counter)
print("wrong_auto_counter", wrong_auto_counter)

conf_mat = confusion_matrix(y_test, y_pred)
print(conf_mat)


import io

from flask import send_file

import chess.svg

def parse_args(args):
    result = {}

    orientation = args.get('orientation', 'white')
    flip = args.get('flip', None) is not None
    flipped = args.get('flipped', None) is not None

    result['flipped'] = flip or flipped or orientation == 'black'

    arrows = args.get('arrows', None)
    if arrows:
      arrows = arrows.split(',')
      result['arrows'] = map(lambda arrow: chess.svg.Arrow.from_pgn(arrow), arrows)

    return result

def send_svg(svg: str):
    fp = io.BytesIO(svg.encode('utf-8'))
    return send_file(fp, mimetype='image/svg+xml')

def render_svg(board: chess.Board, **kwargs):
    svg = chess.svg.board(board, **kwargs)

    return send_svg(svg)


import unittest

from adjacency_matrix_to_adjacency_list import mat_to_list

class TestConversionMatList(unittest.TestCase):
    def test_conversion_correct_1(self):
        adj_mat =  [[0, 1, 0, 1, 0, 0],
                    [0, 0, 1, 0, 0, 0],
                    [1, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 1, 0],
                    [0, 0, 0, 1, 0, 0],
                    [0, 0, 0, 0, 0, 0]]

        expected_result = [[1, 3], [2], [0], [4], [3], []]
        self.assertEqual(mat_to_list(adj_mat), expected_result)

    def test_conversion_correct_2(self):
        adj_mat = [ [0, 0, 1],
                    [0, 0, 1],
                    [1, 1, 0]]

        expected_result = [[2], [2], [0, 1]]
        self.assertEqual(mat_to_list(adj_mat), expected_result)

    def test_conversion_correct_3(self):
        adj_mat = []
        expected_result = []
        self.assertEqual(mat_to_list(adj_mat), expected_result)

    def test_conversion_correct_4(self):
        adj_mat = [1, 2, 3]
        expected_result = None
        self.assertEqual(mat_to_list(adj_mat), expected_result)

    def test_conversion_correct_5(self):
        adj_mat = [[0, 1, 0], [1, 0, 0], 1]
        expected_result = None
        self.assertEqual(mat_to_list(adj_mat), expected_result)

if __name__ == "__main__":
  unittest.main()


import sys, os
from ttk_path import TTK_ROOT

if sys.platform[:3] == "win":
    SLASH = '\\'
elif sys.platform[:3] == "lin":
    SLASH = '/'

TBAQ_FOLDER = 'TBAQ-cleaned'
AQUAINT_FOLDER = 'AQUAINT'
TIMEBANK_FOLDER = 'TimeBank'
SILVER_FOLDER = 'TE3-Silver-data'
PLATINUM_FOLDER = 'te3-platinumstandard' + SLASH + 'te3-platinum'
GOLD_INPUT_PATHS = [os.path.join(TBAQ_FOLDER, AQUAINT_FOLDER),
                    os.path.join(TBAQ_FOLDER, TIMEBANK_FOLDER)
                       ]
SILVER_INPUT_PATHS = [SILVER_FOLDER]
TEST_INPUT_PATHS = [PLATINUM_FOLDER]
DATA_PATH = os.path.join(TTK_ROOT, 'data')
INPUT_DATA_PATH = os.path.join(DATA_PATH, 'in')
FEATURES_DATA_PATH = os.path.join(DATA_PATH, 'features')
OUTPUT_DATA_PATH = os.path.join(DATA_PATH, 'out')
TEMPO_DATA_PATH = os.path.join(DATA_PATH, 'tmp')
LOG_DATA_PATH = os.path.join(DATA_PATH, 'logs')
BETWEEN_COMMAND_TEMPO_PATH = os.path.join(DATA_PATH, 'global_tmp')

GOLD_PROBLEM = 'gold'
SILVER_PROBLEM = 'silver'
TEST_PROBLEM = 'test'

FEATURES_SUFFIX = '_features'
PROBLEM_SUFFIX = '_problem'
QUOTE_CLEAN_SUFFIX = '.quoted_cleaned'
RUN_SUFFIX = '_run.txt'

MERGED_FILE_SUFFIX = '.pre.merged.xml'
TIMEBANK_SUFFIX = '*.tml'

SVM_FEATURES_DATA_PATH = os.path.join(DATA_PATH, 'svm_features')
SVM_FEATURES_DATA_PATH_WITH_NARRATIVE = os.path.join(DATA_PATH, 'svm_features_with_narrative')
MERGED_FILE_SUFFIX_PARSED = '.parsed.pre.merged.xml'
SVM_BETWEEN_COMMAND_TEMPO_PATH = os.path.join(DATA_PATH, 'global_tmp_svm')


import unittest
from unittest.mock import Mock

from opentelemetry.propagators.composite import CompositePropagator

def get_as_list(dict_object, key):
    value = dict_object.get(key)
    return [value] if value is not None else []

def mock_inject(name, value="data"):
    def wrapped(carrier=None, context=None, setter=None):
        carrier[name] = value
        setter.set({}, f"inject_field_{name}_0", None)
        setter.set({}, f"inject_field_{name}_1", None)

    return wrapped

def mock_extract(name, value="context"):
    def wrapped(carrier=None, context=None, getter=None):
        new_context = context.copy()
        new_context[name] = value
        return new_context

    return wrapped

def mock_fields(name):
    return {f"inject_field_{name}_0", f"inject_field_{name}_1"}

class TestCompositePropagator(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.mock_propagator_0 = Mock(
            inject=mock_inject("mock-0"),
            extract=mock_extract("mock-0"),
            fields=mock_fields("mock-0"),
        )
        cls.mock_propagator_1 = Mock(
            inject=mock_inject("mock-1"),
            extract=mock_extract("mock-1"),
            fields=mock_fields("mock-1"),
        )
        cls.mock_propagator_2 = Mock(
            inject=mock_inject("mock-0", value="data2"),
            extract=mock_extract("mock-0", value="context2"),
            fields=mock_fields("mock-0"),
        )

    def test_no_propagators(self):
        propagator = CompositePropagator([])
        new_carrier = {}
        propagator.inject(new_carrier)
        self.assertEqual(new_carrier, {})

        context = propagator.extract(
            carrier=new_carrier, context={}, getter=get_as_list
        )
        self.assertEqual(context, {})

    def test_single_propagator(self):
        propagator = CompositePropagator([self.mock_propagator_0])

        new_carrier = {}
        propagator.inject(new_carrier)
        self.assertEqual(new_carrier, {"mock-0": "data"})

        context = propagator.extract(
            carrier=new_carrier, context={}, getter=get_as_list
        )
        self.assertEqual(context, {"mock-0": "context"})

    def test_multiple_propagators(self):
        propagator = CompositePropagator(
            [self.mock_propagator_0, self.mock_propagator_1]
        )

        new_carrier = {}
        propagator.inject(new_carrier)
        self.assertEqual(new_carrier, {"mock-0": "data", "mock-1": "data"})

        context = propagator.extract(
            carrier=new_carrier, context={}, getter=get_as_list
        )
        self.assertEqual(context, {"mock-0": "context", "mock-1": "context"})

    def test_multiple_propagators_same_key(self):
        # test that when multiple propagators extract/inject the same
        # key, the later propagator values are extracted/injected
        propagator = CompositePropagator(
            [self.mock_propagator_0, self.mock_propagator_2]
        )

        new_carrier = {}
        propagator.inject(new_carrier)
        self.assertEqual(new_carrier, {"mock-0": "data2"})

        context = propagator.extract(
            carrier=new_carrier, context={}, getter=get_as_list
        )
        self.assertEqual(context, {"mock-0": "context2"})

    def test_fields(self):
        propagator = CompositePropagator(
            [
                self.mock_propagator_0,
                self.mock_propagator_1,
                self.mock_propagator_2,
            ]
        )

        mock_setter = Mock()

        propagator.inject({}, setter=mock_setter)

        inject_fields = set()

        for mock_call in mock_setter.mock_calls:
            inject_fields.add(mock_call[1][1])

        self.assertEqual(inject_fields, propagator.fields)


"""python-alsa-midi back-end for `MIDO`_.

To use this backend copy call this from a MIDO application::

    mido.set_backend('alsa_midi.mido_backend')

or set shell variable $MIDO_BACKEND to 'alsa_midi.mido_backend'

.. _MIDO: https://mido.readthedocs.io/
"""

import logging
import queue
import sys
import threading
from typing import Any, Callable, List, MutableMapping, Optional
from weakref import WeakValueDictionary

from mido.messages import Message
from mido.parser import Parser
from mido.ports import BaseInput, BaseOutput

import alsa_midi

logger = logging.getLogger("alsa_midi.mido_backend")

class _Client:
    instance: Optional['_Client'] = None

    client: alsa_midi.SequencerClient
    in_thread: threading.Thread
    ports: MutableMapping[int, 'PortCommon']
    closing: bool

    def __init__(self):
        name = f"{sys.argv[0]!r} MIDO"
        self.ports = WeakValueDictionary()
        self.client = alsa_midi.SequencerClient(name)
        self.closing = False
        self.in_thread = threading.Thread(name="ALSA seq input",
                                          target=self._input_loop,
                                          daemon=True)
        self.in_thread.start()

    def __del__(self):
        self.close()

    def close(self):
        self.closing = True
        self.client.close()

    @classmethod
    def get_instance(cls):
        if cls.instance is not None:
            return cls.instance
        cls.instance = cls()
        return cls.instance

    def get_devices(self, *args, **kwargs):
        _ = args, kwargs
        client = self.client
        devices = []
        for port in client.list_ports():
            devices.append({
                'name': f"{port.client_name}:{port.name} {port.client_id}:{port.port_id}",
                'is_input': port.capability & alsa_midi.PortCaps.READ,
                'is_output': port.capability & alsa_midi.PortCaps.WRITE,
            })
        return devices

    def _input_loop(self):
        try:
            while not self.closing:
                event = self.client.event_input(timeout=1,
                                                prefer_bytes=True)
                if event is None:
                    continue
                if not isinstance(event, alsa_midi.MidiBytesEvent):
                    continue
                assert event.dest is not None
                mido_port = self.ports.get(event.dest.port_id)
                if mido_port is None or not mido_port._for_input:
                    continue
                mido_port._handle_input_bytes(event.midi_bytes)
        except Exception:
            logger.error("Error in alsa_midi.mido_backend input loop:", exc_info=True)

def get_devices(*args, **kwargs):
    client = _Client.get_instance()
    return client.get_devices(*args, **kwargs)

def _find_port(ports: List[alsa_midi.PortInfo], name: str) -> alsa_midi.PortInfo:
    try:
        addr = alsa_midi.Address(name)
    except (ValueError, alsa_midi.exceptions.ALSAError):
        addr = None

    if addr is not None:
        # name is ALSA sequencer address, exact match
        for port in ports:
            if addr == alsa_midi.Address(port):
                return port
        else:
            raise IOError(f"unknown port {name!r}")

    # check for exact match with name from get_devices()
    for port in ports:
        mido_name = f"{port.client_name}:{port.name} {port.client_id}:{port.port_id}"
        if name == mido_name:
            return port

    # check for exact match for client_name:port_name
    for port in ports:
        check_name = f"{port.client_name}:{port.name}"
        if name == check_name:
            return port

    # check for exact match for client_name
    for port in ports:
        if name == port.client_name:
            return port

    # check for exact match for port_name
    for port in ports:
        if name == port.name:
            return port

    raise IOError(f"unknown port {name!r}")

class PortCommon(object):
    _last_num = 0
    _name_prefix = "inout"
    _caps = alsa_midi.PortCaps.READ | alsa_midi.PortCaps.WRITE
    _type = alsa_midi.PortType.MIDI_GENERIC
    _for_input = False
    _for_output = False

    _parser: Parser
    _virtual: bool = False
    _callback: Optional[Callable[[Message], Any]] = None

    _port: Optional[alsa_midi.Port] = None
    _dest_port: Optional[alsa_midi.PortInfo] = None
    name: str

    @classmethod
    def _generate_alsa_port_name(cls) -> str:
        num = cls._last_num + 1
        cls._last_num = num
        return f"{cls._name_prefix}{num}"

    def _open(self, virtual=False, **kwargs):

        self._queue = queue.Queue()
        self._callback = kwargs.get("callback")

        client = _Client.get_instance()

        port_caps = kwargs.get("alsa_capability", self._caps)
        port_type = kwargs.get("alsa_type", self._type)

        if virtual:
            if self._caps & alsa_midi.PortCaps.READ:
                self._caps |= alsa_midi.PortCaps.SUBS_READ
            if self._caps & alsa_midi.PortCaps.WRITE:
                self._caps |= alsa_midi.PortCaps.SUBS_WRITE
            if self.name is None:
                name = self._generate_alsa_port_name()
            else:
                name = self.name
            self._virtual = True
        else:
            name = self._generate_alsa_port_name()

        if virtual:
            dest_port = None
        else:
            ports = client.client.list_ports(input=self._for_input, output=self._for_output)

            if not ports:
                raise IOError('no ports available')

            if self.name is None:
                dest_port = ports[0]
            else:
                dest_port = _find_port(ports, self.name)

        self._port = client.client.create_port(name, caps=port_caps, type=port_type)

        if dest_port is not None:
            if self._for_output:
                self._port.connect_to(dest_port)
            if self._for_input:
                self._port.connect_from(dest_port)

        self._dest_port = dest_port

        api = 'seq'
        self._device_type = 'AlsaMidi/{}'.format(api)
        if virtual:
            self._device_type = 'virtual {}'.format(self._device_type)

        client.ports[self._port.port_id] = self

    def _handle_input_bytes(self, midi_bytes):
        if self._callback:
            self._parser.feed(midi_bytes)
            for message in self._parser:
                self._callback(message)
        else:
            self._queue.put(midi_bytes)

    def _close(self):
        port = self._port
        if port is not None:
            self._port = None
            port.close()

    @property
    def callback(self):
        return self._callback

    @callback.setter
    def callback(self, func):
        self._callback = func

class Input(PortCommon, BaseInput):
    _last_num = 0
    _name_prefix = "in"
    _for_input = True
    _caps = alsa_midi.PortCaps.WRITE

    def _receive(self, block=True):
        data = self._queue.get(block)
        self._parser.feed(data)

class Output(PortCommon, BaseOutput):
    _last_num = 0
    _name_prefix = "out"
    _for_output = True
    _caps = alsa_midi.PortCaps.READ

    def _send(self, message):
        client = _Client.get_instance().client
        event = alsa_midi.MidiBytesEvent(message.bytes())
        client.event_output(event,
                            port=self._port,
                            dest=self._dest_port)
        client.drain_output()


import numpy as np
import cv2

# (height, width, channel) of the image
shape = (50,50,1)
#maze = np.ones(shape)
# maze = np.full(shape, 255)
maze = np.zeros(shape) # this is fully black => blocked

freeShape = (10,10,1)
free = np.full(freeShape, 255)
#obstacle = np.zeros(obstacleShape)

m = [[0, 10],[10, 10],[20, 10],[30, 10],[ 30, 20],[20, 20],[20, 30],[20, 40],[10, 40]]

 # row , col
for i in m:
	r = i[0]
	c = i[1]
	maze[r:r+free.shape[0], c:c+free.shape[1],:] = free

# # assigns the part of the maze image as obstracle
# maze[r1:r1+obstacle.shape[0], c1:c1+obstacle.shape[1],:] = obstacle
# maze[r2:r2+obstacle.shape[0], c2:c2+obstacle.shape[1],:] = obstacle

# # r3, c3 = 25, 125
# # # r4, c4 = 125, 125
# # maze[r3:r3+obstacle.shape[0], c3:c3+obstacle.shape[1],:] = obstacle
# # maze[r4:r4+obstacle.shape[0], c4:c4+obstacle.shape[1],:] = obstacle
# # Mat b = cv.fromarray(maze)

# obstacleShapeTwo = (125,15,1)
# obstacleShapeTwo = np.zeros(obstacleShapeTwo)

# r2, c2 = 25, 100
# r3, c3 = 50, 140
# r4, c4 = 25, 180
# maze[r2:r2+obstacleShapeTwo.shape[0], c2:c2+obstacleShapeTwo.shape[1],:] = obstacleShapeTwo
# maze[r3:r3+obstacleShapeTwo.shape[0], c3:c3+obstacleShapeTwo.shape[1],:] = obstacleShapeTwo
# maze[r4:r4+obstacleShapeTwo.shape[0], c4:c4+obstacleShapeTwo.shape[1],:] = obstacleShapeTwo

cv2.imwrite('maze_2.png', maze)
# cv2.imshow('maze_basic', maze)
cv2.waitKey(0)
cv2.destroyAllWindows()


def move(pole1,num):
    print("Move disc", num, "to the", pole1, "pole\n")

def H_tower(n):
    for i in range(1,n**2):
        j = 1
        k = i
        while (k%2==0):
            j += 1
            k = k/2
        if ((k + 1)/2%3==0):
            move("A", n+1-j)
        elif ((n+1-j)%2==1 and (k+1)/2%3==1 or (n+1-j)%2==0 and (k+1)/2%3==2):
            move("C", n+1-j)
        elif (n+1-j)!=0:
            move("B", n+1-j)
H_tower(int(input("Enter the number of discs:")))


from telethon import events
import time

@borg.on(events.NewMessage(pattern=r".emoji (.*)", outgoing=True))
async def _(event):
    if event.fwd_from:
        return
    animation_interval = 0.3
    animation_ttl = range(0, 16)
    input_str = event.pattern_match.group(1)
    if input_str == "shrug":
        await event.edit("¯\_(ツ)_/¯")
    elif input_str == "apple":
        await event.edit("\uF8FF")
    elif input_str == ":/":
        await event.edit(input_str)
        animation_chars = [
            ":\\",
            ":/"
        ]
        for i in animation_ttl:
            time.sleep(animation_interval)
            await event.edit(animation_chars[i % 2])
    elif input_str == "-_-":
        await event.edit(input_str)
        animation_chars = [
            "-__-",
            "-_-"
        ]
        for i in animation_ttl:
            time.sleep(animation_interval)
            await event.edit(animation_chars[i % 2])


# На столе стоит две корзины с яблоками. Корзина a и корзина b. Введите количество яблок с клавиатуры. Затем поменяйте содержимое корзин местами и выведите результат.
busket1 = int(input('Введите количество яблок в первой корзине:'))
busket2 = int(input('Введите количество яблок во второй корзине:'))

if busket1 != busket2:
    busket1 = busket1 + busket2
    busket2 = busket1 - busket2
    busket1 = busket1 - busket2
    print(f'Яблок в первой корзине {busket1}. Яблок во второй корзине {busket2}.')
else:
    print('Количество яблок в корзинах равное.')


import glob, os, re
from itertools import islice
import statistics as stats
import matplotlib.pyplot as plot

schedule_lengths = open("schedule_lengths.csv", "w")
schedule_lengths.write(";Resource;Length;Nodes;Unequal\n")
schedule_lengths.close()
schedule_lengths = open("schedule_lengths.csv", "a")

open("no_schedule.txt", "w").close()
no_schedule = open("no_schedule.txt", "a")

unequal = []
no_list_schedule = []
exec_times = dict()
convergence = dict()

faster = dict()
list_scheduler_faster = 0
lazy_alap_faster = 0

root = "./benchmark"
#root = "./benchmark_fastest_30_sec_17_01"

with open(root + "/metrics.txt", "r+") as metrics:
    for line in metrics:
        if "unequal schedules" in line and "tried" not in line:
            dashes = [_.start() for _ in re.finditer("/", line)]
            dfgName = line[dashes[0]+1:dashes[1]]
            unequal.append(dfgName)
        elif line.startswith("Execution times"):
            for time in islice(metrics, 6):
                key = time[time.find(":")+2:time.find(",")]
                time = time[time.find(",")+1:]
                value = time[time.find(":")+2:time.rfind(":")]
                time = time[time.rfind(":")+2:time.rfind(",")]
                d = {value: time.replace("\n", "")}
                if key in exec_times:
                    d_old = exec_times[key]
                    exec_times[key] = d | d_old
                else:
                    exec_times[key] = d
        elif line.startswith("Convergence times"):
            for time in islice(metrics, 6):
                #remove -1, as those did not converge
                time = time.replace(", -1", "")
                key = time[time.find(":")+2:time.find(",")]
                time = time[time.find(",")+1:]
                value = time[time.find(":")+2:time.rfind(":")]
                time = time[time.rfind(":")+2:time.rfind(",")]
                d = {value: time.replace("\n", "")}
                if key in convergence:
                    d_old = convergence[key]
                    convergence[key] = d | d_old
                else:
                    convergence[key] = d

        else:
            for type in ["ASAP", "OWN", "PAPER"]:
                if line.startswith(" lBoundEstimator: " + type) and "than lBoundEstimator: " + type not in line and (line.count("lazy")>1 or line.count("listSchedule")>1):
                    times = line[line.find("times")-4:line.find("times")-1]
                    #times = [int(s) for s in times.split() if s.isdigit()][0]
                    if type in faster:
                        faster[type] = faster[type] + int(times)
                    else:
                        faster[type] = int(times)
                elif line.startswith(" lBoundEstimator: " + type) and "than lBoundEstimator: " + type in line:
                    alap_bound = line[line.find("ALAPBound: ")+11:line.find("faster")-1]
                    times = line[line.find("times")-4:line.find("times")-1]
                    times = [int(s) for s in times.split() if s.isdigit()][0]
                    if alap_bound == "listScheduler":
                        list_scheduler_faster += times
                    elif alap_bound == "lazyALAP":
                        lazy_alap_faster += times

print("Lazy ALAP faster: " + str(lazy_alap_faster))
print("ListScheduler faster: " + str(list_scheduler_faster))

plot.figure(0)
plot.bar(["ASAP faster", "OWN faster", "PAPER faster"], faster.values())
plot.ylabel("Occurances")
plot.savefig('estimator_faster.png')

#plot.show()

x = []
y = []
y_mean = []
y_median = []

x_6 = [1,2,3,4,5,6]

i = 1
for estimator in exec_times:
    for alap in exec_times[estimator]:
        mylist = [int(x) for x in exec_times[estimator][alap].split(',')]
        y_mean.append(stats.mean(mylist))
        y_median.append(stats.median(mylist))
        x += [i]*len(mylist)
        #randomNrs = numpy.random.choice(10, len(mylist), replace=True)
        y += mylist
        i += 1

plot.figure(1)
plot.scatter(x, y)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Execution time in ms")
plot.savefig('execution_time.png')
#plot.close()

plot.figure(2)
plot.scatter(x_6, y_mean)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Mean execution time in ms")
plot.savefig('mean_execution_time.png')
#plot.close()

plot.figure(3)
plot.scatter(x_6, y_median)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Median of execution time in ms")
plot.savefig('median_execution_time.png')
#plot.close()

x = []
y = []
y_mean = []
y_median = []

i = 1
for estimator in convergence:
    for alap in convergence[estimator]:
        mylist = [int(x) for x in convergence[estimator][alap].split(',')]
        y_mean.append(stats.mean(mylist))
        y_median.append(stats.median(mylist))
        x += [i]*len(mylist)
        y += mylist
        i += 1

plot.figure(4)
plot.scatter(x, y)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Convergence time in ms")
plot.savefig('convergence_time.png')
#plot.close()

plot.figure(5)
plot.scatter(x_6, y_mean)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Mean convergence time in ms")
plot.savefig('mean_convergence_time.png')
#plot.close()

plot.figure(6)
plot.scatter(x_6, y_median)
labels = ["ASAP\nlistSchedule", "ASAP\nlazyALAP", "OWN\nlistSchedule", "OWN\nlazyALAP", "PAPER\nlistSchedule", "PAPER\nlazyALAP"]
plot.xticks([1,2,3,4,5,6], labels)
plot.ylabel("Median of convergence time in ms")
plot.savefig('median_convergence_time.png')
#plot.close()

#plot.show()

too_conservative = dict()
diff_best_initial = []

faster = dict()

own_faster = []
paper_faster = []

timeout = dict()

for filename in glob.iglob(root + '/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        if "metrics" in filename:
            continue

        dashes = [_.start() for _ in re.finditer("/", filename)]
        dfgName = filename[dashes[1]+1:dashes[2]]
        resName = filename[dashes[2]+1:dashes[3]]

        min_len = 0
        max_len = 0
        nodes = 0

        if "eval" in filename:
            last_line = ""
            with open(filename, "r+") as file:
                for line in file:
                    if line.startswith("Found schedule of length"):
                        length = [int(i) for i in line.split() if i.isdigit()]
                        if dfgName in unequal:
                            if min_len == 0: min_len = length[0]
                            min_len = min(min_len, length[0])
                            max_len = max(max_len, length[0])
                        else:
                            min_len = length[0]
                            max_len = min_len
                        nodes = length[1]

                    elif "list scheduler did not complete once" in line:
                        preamble = open(filename.replace("eval.txt", "preamble.txt"), "r")
                        for line in preamble:
                            if line.startswith("Found schedule of length"):
                                length = [int(i) for i in line.split() if i.isdigit()]
                                nodes = length[1]
                                break
                        no_schedule.write(dfgName + " with " + resName + ", " + str(nodes) + " nodes\n")
                        no_list_schedule.append(dfgName)

                    elif line.startswith("Printing BULB metrics for"):
                        best_latency = 0
                        initial_latency = 0
                        for part in islice(file, 5):
                            if part.startswith("Best latency"):
                                best_latency = int(part[part.find(":")+1:])
                            elif part.startswith("Initial best latency"):
                                initial_latency = int(part[part.find(":")+1:])
                        diff_best_initial.append(initial_latency-best_latency)

                    elif line.startswith("faster: lBoundEstimator: "):
                        if line.startswith("faster: lBoundEstimator: OWN") and "vs. lBoundEstimator: PAPER" in line and (line.count("lazy")>1 or line.count("listSchedule")>1):
                            #compare PAPER and OWN lower bound estimator
                            alap_bound = line[line.find("ALAPBound: ")+11:line.find("->")-1]
                            difference1 = int(line[line.find("->")+3:line.find(", vs")])
                            difference2 = int(line[line.rfind("->")+3:])
                            difference = difference2
                            if difference1 > 0:
                                difference = difference2 / difference1
                            #if difference > 3:
                                #print(filename + ": OWN with " + alap_bound + " was faster > 3 times")
                            if "--->" not in last_line:
                                print("OWN vs: PAPER: compared schedules are not equal\n")
                            else:
                                own_faster.append(difference)

                        elif line.startswith("faster: lBoundEstimator: PAPER") and "vs. lBoundEstimator: OWN" in line and (line.count("lazy")>1 or line.count("listSchedule")>1):
                            #compare PAPER and OWN lower bound estimator
                            alap_bound = line[line.find("ALAPBound: ")+11:line.find("->")-1]
                            difference1 = int(line[line.find("->")+3:line.find(", vs")])
                            difference2 = int(line[line.rfind("->")+3:])
                            difference = difference2
                            if difference1 > 0:
                                difference = difference2 / difference1
                            #if difference > 3:
                                #print(filename + ": PAPER with " + alap_bound + " was faster > 3 times")
                            if "--->" not in last_line:
                                print("PAPER vs: OWN: compared schedules are not equal")
                            else:
                                paper_faster.append(difference)

                        for type in ["ASAP", "OWN", "PAPER"]:
                            if line.startswith("faster: lBoundEstimator: " + type) and "vs. lBoundEstimator: " + type not in line and (line.count("lazy")>1 or line.count("listSchedule")>1):
                                #compare lower bound estimators with same alap upper bound only
                                difference1 = int(line[line.find("->")+3:line.find(", vs")])
                                difference2 = int(line[line.rfind("->")+3:])

                                difference = difference2
                                if difference1 > 0:
                                    difference = difference2 / difference1

                                if "--->" not in last_line:
                                        #print("compared schedules are not equal")
                                        continue

                                #if difference > 1000:
                                    #print(filename + ": " + type + " was faster > 1000 times")

                                if resName not in faster:
                                    faster[resName] = {type:[difference]}
                                elif type not in faster[resName]:
                                    faster[resName] = faster[resName] | {type:[difference]}
                                else:
                                    faster[resName][type].append(difference)

                    last_line = line

            no_schedule.flush()

            if dfgName in unequal:
                schedule_lengths.write(dfgName + ";" + resName + ";" + str(min_len) + ";" + str(nodes) + ";yes\n")
            else:
                schedule_lengths.write(dfgName + ";" + resName + ";" + str(min_len) + ";" + str(nodes) + ";\n")
            schedule_lengths.flush()

        elif "logs" in filename:
            #print("printing timeout before" + str(timeout))
            parameter_line = ""
            with open(filename, "r+") as file:
                for line in file:
                    if "STARTING BULB SCHEDULE with" in line:
                        parameter_line = line
                    elif "Timeout reached while computing" in line:
                        estimator = parameter_line[parameter_line.find("with")+5:parameter_line.find("estimator")-1]
                        bound = parameter_line[parameter_line.find(", ")+2:parameter_line.find("alap ")-1]
                        if estimator in timeout:
                            if bound in timeout[estimator]:
                                timeout[estimator][bound] = timeout[estimator][bound] + 1
                            else:
                                timeout[estimator][bound] = 1
                        else:
                            timeout[estimator] = {bound: 1}

print("\nPrinting timeout: " + str(timeout))

plot.figure(7)
plot.hist(diff_best_initial)
plot.xlabel("Difference between initial and best schedule")
plot.ylabel("Occurances")
plot.savefig('initial_best_diff.png')
#plot.close()

#print(own_faster + paper_faster)

plot.figure(8)
plot.scatter(["OWN"]*len(own_faster) + ["PAPER"]*len(paper_faster), own_faster + paper_faster)
plot.ylabel("Occurances")
plot.savefig('own_vs_paper.png')

plot.figure(9)
plot.bar(["OWN", "PAPER"], [len(own_faster), len(paper_faster)])
plot.xlabel("Times faster than the other")
plot.ylabel("Occurances")
plot.savefig('own_vs_paper_times.png')
print("\n\n\nMax. times faster OWN - PAPER: " + str(max(own_faster)))
print("\n\n\nMax. times faster PAPER - OWN: " + str(max(paper_faster)))

print("Percentage of best schedules at initial run: " + str(diff_best_initial.count(0)/len(diff_best_initial)*100))

x = []
y = []
labels = []
means = []
i = 1
for res in faster:
    for type in faster[res]:
        means.append(stats.mean(faster[res][type]))
        labels += [res + "\n" + type]
        x += [i]*len(faster[res][type])
        y += faster[res][type]
        i += 1

plot.figure(10, figsize=(20,6), dpi=80)
plot.scatter(x, y)
plot.xticks([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18], labels)
plot.xlabel("Slower - faster for res " + res + " and type " + type)
plot.ylabel("Faster ... times")
plot.savefig('slower_faster_diff.png')
##plot.close()

plot.figure(11, figsize=(20,6), dpi=80)
plot.bar(labels, means)
plot.xlabel("Slower - faster for res " + res + " and type " + type)
plot.ylabel("Faster ... times")
plot.savefig('mean_slower_faster_diff.png')
##plot.close()

#plot.plot(stats.mean(diff_best_initial))
#plot.ylabel("Convergence time in s")
#plot.savefig('convergence_time.png')
plot.show()

schedule_lengths.close()
no_schedule.close()


from collections import deque

graph=[
  [],
  [2,3,8],
  [1,7],
  [1,4,5],
  [3,5],
  [3,4],
  [7],
  [2,6,8],
  [1,7]
]

visited=[False] *9
queue=deque([1])
visited[1]=True

while queue:
  vertex=queue.popleft()
  print(vertex,end=" ")

  for adj_vertex in graph[vertex]:
    if not visited[adj_vertex]:
      queue.append(adj_vertex)
      visited[adj_vertex]=True
print()