'''
python InteractiveRunner.py python judges/DigitBlocks.py 0 -- python solvers/DigitBlocks.py
python InteractiveRunner.py python judges/DigitBlocks.py 1 -- python DigitBlocks.py
'''

'''
tower_count = 20
blocks_per_tower = 15
Test Set 1: P = 860939810732536850 (approx. 8.6 * 10 ** 17)
Test Set 2: P = 937467793908762347 (approx. 9.37 * 10 ** 17)

300 blocks means, on average
30 0s
30 1s
30 2s
...
30 9s
An ideal pair of towers would look like:
    998877665543210
    987654433221100
    Build a tower of non-9s to height of 14
    First nine you find goes on that tower
    Build a tower of non-9s
The average tower must end in 94 or greater to get both Test Sets
'''

import collections
import functools
import logging
import sys

logging.basicConfig(
    filename = 'DigitBlocks.out',
    filemode ='w',
    level = logging.DEBUG,
    format = '%(asctime)s - %(levelname)s: %(message)s',
    datefmt = '%m/%d/%Y %I:%M:%S %p',
    )

def log(message: str):
    enable_logging = False
    if enable_logging:
        logging.debug(message)

def receive() -> int:
    response = int(input())
    log('receive:' + str(response))
    result = response
    return result

def send(tower_id: int):
    request = str(tower_id)
    log('send:' + request)
    print(request)
    sys.stdout.flush()

def solve(tower_count: int, blocks_per_tower: int, target_score: int):
    assert tower_count == 20
    assert blocks_per_tower == 15
    log('tower_count:' + str(tower_count))
    log('blocks_per_tower:' + str(blocks_per_tower))
    log('target_score:' + str(target_score))
    # You can assume that the digit for each block is generated
    # uniformly at random, and independently for each digit
    # There are T * B exchanges
    # Each exchange is:
    #   one receive ('0' to '9'), followed by
    #   one send ('1' to 'T')
    towers = [0] + [blocks_per_tower] * (tower_count)
    block_count = 0
    while block_count < tower_count * blocks_per_tower:
        response = receive()
        log('response:' + str(response))
        if response == -1:
            exit()
        # Figure out the ideal tower to put the block onto
        request = -1
        if response == 9:
            # Put it on the first tower with 1 or more blocks remaining
            for tower_id in range(1, tower_count + 1):
                if towers[tower_id] >= 1:
                    request = tower_id
                    break
        elif response >= 8:
            # Put it on the first tower with 2 or more blocks remaining
            for tower_id in range(1, tower_count + 1):
                if towers[tower_id] >= 2:
                    request = tower_id
                    break
        else:
            # Put it on the first tower with 3 or more blocks remaining
            for tower_id in range(1, tower_count + 1):
                if towers[tower_id] >= 3:
                    request = tower_id
                    break
        if request == -1:
            # Put it on the first tower with 1 or more blocks remaining
            for tower_id in range(1, tower_count + 1):
                if towers[tower_id] >= 1:
                    request = tower_id
                    break
        towers[request] -= 1
        send(request)
        log('request:' + str(request))
        block_count += 1

test_case_count, tower_count, blocks_per_tower, target_score = map(int, input().split())
for i in range(0, test_case_count):
    solve(tower_count, blocks_per_tower, target_score)
# At the end of all tests, the judge will issue a verdict
verdict = receive()
log('verdict:' + str(verdict))
exit()


# https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/

from typing import List
from copy import deepcopy

class Solution:
    # O (N lgN)
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        nums_copy = deepcopy(nums)
        nums_copy.sort()
        map = {}
        for i in range(len(nums_copy)):
            if nums_copy[i] not in map:
                map[nums_copy[i]] = i

        return [map[num] for num in nums]

    # O(N)
    def smallerNumbersThanCurrentV2(self, nums: List[int]) -> List[int]:
        commulative_frequency = [0 for i in range(102)]
        for num in nums:
            commulative_frequency[num + 1] += 1

        for i in range(1, 102):
            commulative_frequency[i] = commulative_frequency[i] + commulative_frequency[i - 1]

        return [commulative_frequency[num] for num in nums]

print(Solution().smallerNumbersThanCurrent([6, 5, 4, 8]))
print(Solution().smallerNumbersThanCurrent([8, 1, 2, 2, 3]))

print(Solution().smallerNumbersThanCurrentV2([6, 5, 4, 8]))
print(Solution().smallerNumbersThanCurrentV2([8, 1, 2, 2, 3]))


import os
import shutil
import yaml

from argparse import ArgumentParser
from importlib import import_module
from typing import List, Text

import utils.constants as c
import utils.user_interfaces as ui

class Config:
    '''configurations
    '''

    def __init__(self):
        self.__swpdl_root = os.path.split(__file__)[0]
        self.a = self.parse_args() # from command line arguments
        self.conf = self.load_conf_file(self.from_swpdl_root(self.a['conf']))
        self.load()

    def parse_args(self):
        psr = arg_parser()
        a_dict = vars(psr.parse_args())
        return a_dict

    def load_conf_file(self, file_path):
        return read_yaml(file_path)

    def makedirs_after_confirmation(self, dir_path: Text):
        if os.path.exists(dir_path):
            confirmation_msg = 'Delete {}'.format(dir_path)
            refused_msg = 'Cannot delete the directory. Delete it or specify another file path and try again.'
            yes = ui.get_user_confirmation(confirmation_msg, refused_msg)
            if yes:
                shutil.rmtree(dir_path)
            else:
                exit()

        os.makedirs(dir_path)

    def load(self):
        # basic conf
        self.backend = set_backend(self.get_value('backend').upper())
        self.gpu_conf = self.set_gpu_conf(self.get_value('gpus'))
        self.save_dir = self.get_value('save_dir')
        self.makedirs_after_confirmation(self.save_dir)

        # dataset
        self.dataset = self.get_value('dataset')
        self.test_data = self.get_value('test_data')
        self.validation_data = self.get_value('validation_data')
        self.num_train_samples = None # need update after loading dataset
        self.num_test_samples = None # need update after loading dataset
        self.num_validation_samples = None # need update after loading dataset

        # network
        self.network = self.get_value('network')
        self.in_height_list = self.get_value('in_heights')
        self.in_width_list = self.get_value('in_widths')
        self.in_channels_list = self.get_value('in_channels')
        assert len(self.in_height_list) == len(self.in_width_list) == len(self.in_channels_list)
        self.out_classes_list = self.get_value('classes')
        self.set_weights_confs(self.get_value('weights'))
        self.dropout_keep_prob = self.get_value('dropout_keep_prob')
        self.l2_lambda = self.get_value('l2_lambda')

        # optimization
        self.optimizer = self.get_value('optimizer')
        self.learning_rate = self.get_value('learning_rate')
        self.learning_rate_decay = self.get_value('learning_rate_decay')

        # training
        self.batch_size = self.get_value('batch_size')
        self.num_epochs = self.get_value('num_epochs')
        self.train_steps_per_epoch = None # need update after loading dataset
        self.test_steps_per_epoch = None # need update after loading dataset
        self.validation_steps_per_epoch = None # need update after loading dataset

    def from_swpdl_root(self, path: Text):
        return os.path.join(self.__swpdl_root, path)

    def get_value(self, target):
        '''get config value
        1. try to get from command line arguments if defined
        2. get from config file
        '''
        if (target in self.a) and (self.a[target] is not None):
            return self.a[target]
        else:
            return self.conf[target]

    def set_gpu_conf(self, gpus: List[int]):
        print(self.backend)
        print(c.backend_mdls[self.backend])
        gpu_conf_mdl = import_module('fws.{}.gpu_conf'.format(c.backend_mdls[self.backend]))
        conf_class = getattr(gpu_conf_mdl, 'GPUConf')
        return conf_class(gpus)

    def set_weights_confs(self, weights: Text):
        if weights is None or weights == '':
            self.weights_type = c.WeightsType.RANDOM
            self.weights_path = None
        elif weights == 'imagenet':
            self.weights_type = c.WeightsType.PREPARED
            self.weights_path = None
        elif os.path.isfile(weights):
            self.weights_type = c.WeightsType.LOAD
            self.weights_path = weights
        else:
            raise RuntimeError('invalid weights type, "{}"'.format(wt))

    def set_num_samples_and_steps_per_epoch(
            self,
            num_train: int,
            num_test: int,
            num_validation: int
            ):
        self.num_train_samples = num_train
        self.num_test_samples = num_test
        self.num_validation_samples = num_validation
        if self.num_train_samples is not None:
            self.train_steps_per_epoch = self.num_train_samples // self.batch_size
        if self.num_test_samples is not None:
            self.test_steps_per_epoch = self.num_test_samples // self.batch_size
        if self.num_validation_samples is not None:
            self.validation_steps_per_epoch = self.num_validation_samples // self.batch_size

def arg_parser():
    psr = ArgumentParser()
    psr.add_argument('--conf', help='config yaml file path', default='config.yaml')
    # basic
    psr.add_argument('--gpus', help='device number list of gpus', nargs='+', type=int, required=False)
    psr.add_argument('--save_dir', help='directory to save all results and logs', required=False)
    # dataset
    psr.add_argument('--dataset', help='dataset name or directory path.', required=False)
    psr.add_argument('--test_data', help='test dataset directory path.', required=False)
    psr.add_argument('--validation_data', help='validation dataset directory path.', required=False)
    # network
    psr.add_argument('--network', help='name of network', required=False)
    psr.add_argument('--dropout_keep_prob', help='keep probability of dropout', required=False)
    psr.add_argument('--l2_lambda', help='lambda of l2 regularization for weight decay', required=False)
    # optimization
    psr.add_argument('--optimizer', help='name of the optmizer', required=False)
    psr.add_argument('--learning_rate', help='learning_rate', required=False)
    psr.add_argument('--learning_rate_decay', help='learning_rate_decay', required=False)
    # training
    psr.add_argument('--batch_size', help='global batch size', type=int, required=False)
    psr.add_argument('--num_epochs', help='the number of epochs for training', type=int, required=False)

    return psr

def read_yaml(file_path: Text):
    with open(file_path, 'r') as f:
        return yaml.load(f, Loader=yaml.SafeLoader)

def set_backend(be):
    if be == 'CAFFE':
        return c.Backend.CAFFE
    elif be == 'KERAS':
        return c.Backend.KERAS
    elif be == 'PYTORCH':
        return c.Backend.PYTORCH
    elif be == 'TENSORFLOW':
        return c.Backend.TENSORFLOW
    elif be == 'TF_KERAS':
        return c.Backend.TF_KERAS
    else:
        raise RuntimeError('invalid backend, "{}"'.format(be))


def test():
    import sys
    from PyQt5.QtWidgets import QApplication, QWidget, QStackedLayout
    from PyQt5.QtCore import pyqtSlot
    from .choosetype import NewProjectWindow
    from .setparameters import SetParametersWindow

    app = QApplication(sys.argv)

    window = QWidget()
    ctw = NewProjectWindow(window)
    spw = SetParametersWindow(window)

    stacked_layout = QStackedLayout(window)
    stacked_layout.addWidget(ctw)
    stacked_layout.addWidget(spw)
    stacked_layout.setCurrentIndex(0)
    window.setLayout(stacked_layout)
    window.setFixedSize(586, 485)
    window.show()

    @pyqtSlot()
    def next_():
        stacked_layout.setCurrentIndex(1)

    @pyqtSlot()
    def previous_():
        stacked_layout.setCurrentIndex(0)

    ctw.next_button.clicked.connect(next_)
    spw.previous_button.clicked.connect(previous_)

    sys.exit(app.exec_())


import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as st
import numpy as np
import sympy
# ------------------------------------配置区------------------------------------------------------
# 数据
L = 33
D1 = 0.02
D2 = 15.7
R0 = 47.82
# 这里的路径都是相对路径，当然你也可以写绝对路径
# 原文件
FILE_INPUT = 'res/physical.xlsx'
# 处理后的文件
FILE_OUTPUT = 'res/fucking-physical.xlsx'
# 图片保存路径
IMAGE_OUTPUT = 'res'
# ------------------------------------配置区-------------------------------------------------------

# 读入文件
physical = pd.read_excel(FILE_INPUT)

# 表格数据处理
def processTableData():
    # UI=U*I,四舍五入保留三位小数
    physical['UI'] = round(physical['U'] * physical['I'] * 1e-3, 3)
    # U/I=U/I,四舍五入保留一位小数
    physical['U/I'] = round(physical['U'] / (physical['I'] * 1e-3), 1)
    # 迭代
    for i in physical.index:
        # dQ/dt=UI-P(真空)
        if i > 0:
            physical['dQ/dt'].at[i] = physical['UI'].at[i] - \
                physical['UI'].at[0]
        # P^-1=1/P,四舍五入保留两位小数
        if i > 0:
            physical['P^-1'].at[i] = round(1 / physical['P'].at[i], 2)
        # (dQ/dt)^-1,四舍五入保留三位小数
        if i > 0:
            physical['(dQ/dt)^-1'].at[i] = round(1 /
                                                 physical['dQ/dt'].at[i], 3)
    # print(physical)
    # 导出文件
    physical.to_excel(FILE_OUTPUT, index=False)

# 其他数据处理

def processOtherData():
    fp = pd.read_excel(FILE_OUTPUT)
    # R1
    R1 = round(fp['U/I'].mean(), 2)
    print("R1:", R1)
    # t1,T1
    a = 5.1e-3
    t1 = round((R1 - R0) / (a * R0), 1)
    T1 = round(273.15 + t1, 2)
    print("t1：", t1)
    print("T1：", T1)
    # t2,T2
    t2 = round(fp['t2'].mean(), 1)
    T2 = round(273.15 + t2, 2)
    print('t2：', t2)
    print('T2：', T2)
    # 平均热导系数λ_
    y0 = 2.38e-2
    # 首先定义 `T`为一个符号，代表一个未知数
    T = sympy.Symbol('T')
    # 把函数式赋给一个变量
    f = y0 * ((T / 273.15) ** (3 / 2))
    # 传入函数表达式和积分变量、积分下限、上限
    y_ = sympy.integrate(f, (T, T2, T1)) * 1 / (T1 - T2)
    print("λ_：", round(y_, 5))
    # λ1
    y1 = gety(1, None, T1, T2)
    # 百分差Ep1
    Ep1 = (y1 - y_) / y_
    print("Ep1：", round(Ep1, 4))
    # λ2
    y2 = gety(1, 10, T1, T2)
    # 百分差Ep2
    Ep2 = (y2 - y_) / y_
    print("Ep2：", round(Ep2, 4))
    # λ3
    y3 = gety(9, 20, T1, T2)
    # 百分差Ep3
    Ep3 = (y3 - y_) / y_
    print("Ep3：", round(Ep3, 4))

# 图像处理

def processGraphics(start, stop):
    # 线性拟合，可以返回斜率，截距，r 值，p 值，标准误差,x,y
    slope, intercept, r_value, p_value, std_err, x, y = getLinregress(
        start, stop)
    # 散点图
    plt.scatter(x, y, color='green')
    # 期望函数
    exp = x * slope + intercept
    # 画出回归直线
    plt.plot(x, exp, color='orange')
    plt.xlabel('P^-1 (1/kPa)')
    plt.ylabel('(∆Q/∆t)^-1 (1/W)')
    # 结果保留三位小数
    plt.title(
        f'y={round(slope, 3)}x+{round(intercept, 3)}    R^2={round(r_value ** 2, 3)}',
        fontsize=16)
    plt.tight_layout()
    # plt.show()
    if stop is None:
        fileName = '0.10-1.00kPa'
    elif stop == 10:
        fileName = '0.10-0.50kPa'
    else:
        fileName = '0.50-1.00kPa'
    plt.savefig(IMAGE_OUTPUT + '/' + fileName + '.jpg')
    plt.close()

# 获取线性回归方程

def getLinregress(start, stop):
    fp = pd.read_excel(FILE_OUTPUT)
    # 获取数据
    # 0.10-1.00
    # x = fp.iloc[1:, 5]
    # y = fp.iloc[1:, 6]
    # 0.10-0.50
    # x = fp.iloc[1:10, 5]
    # y = fp.iloc[1:10, 6]
    # 0.50-1.00
    # x = fp.iloc[9:20, 5]
    # y = fp.iloc[9:20, 6]
    x = fp.iloc[start:stop, 5]
    y = fp.iloc[start:stop, 6]
    # 线性拟合，可以返回斜率，截距，r 值，p 值，标准误差
    slope, intercept, r_value, p_value, std_err = st.linregress(x, y)
    return slope, intercept, r_value, p_value, std_err, x, y

# 获取导热系数

def gety(start, stop, T1, T2):
    # λ1
    slope, intercept, r_value, p_value, std_err, x, y = getLinregress(
        start, stop)
    y1 = (1 / (intercept * 2 * 3.1416 * L * 1e-2)) * \
         (np.log(15 / 0.02) / (T1 - T2))
    if stop is None:
        name = 'λ1：'
    elif stop == 10:
        name = 'λ2：'
    else:
        name = 'λ3：'
    print(name, round(y1, 5))
    return y1

processTableData()
processOtherData()
processGraphics(1, None)
processGraphics(1, 10)
processGraphics(9, 20)


import os
import sys
import unittest
import unittest.mock
import io

class Test(unittest.TestCase):

    def get_dir(folder_name):
        cwd = os.getcwd()
        basepath = ""
        while True:
            if os.path.exists(folder_name):
                break
            os.chdir("..")
            basepath = os.path.join(basepath, "..")
        os.chdir(cwd)
        if not basepath in sys.path:
            sys.path.insert(0, basepath)

    get_dir("cleaner")
    get_dir("fetcher")

    from cleaner.Cleaner import DataCleaner
    from fetcher.Fetcher import DataFetcher

    cleaner = DataCleaner()
    fetcher = DataFetcher()

    # Tests fetch_a_stock in Fetcher class so it successfully fetches data for GOOG
    @unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
    def test_fetcher(self, mock_stdout):
        self.fetcher.fetch_a_stock('GOOG')
        self.assertEqual('Fetched data for GOOG\n', mock_stdout.getvalue(),'Failed when fetching data')

    # Tests clean_a_stock in Cleaner class so it successfully cleans data for GOOG
    @unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
    def test_cleaner(self, mock_stdout):
        self.cleaner.clean_a_stock('GOOG')
        self.assertEqual('Cleaning data for GOOG\n', mock_stdout.getvalue(), 'Failed when cleaning data')

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


"""SoftWebauthnDevice class tests"""

from fido2.server import Fido2Server
from fido2.webauthn import AttestationObject, AuthenticatorData, CollectedClientData, PublicKeyCredentialRpEntity

from soft_webauthn import SoftWebauthnDevice

def test_register():
    """test registering generated credential"""

    device = SoftWebauthnDevice()

    server = Fido2Server(PublicKeyCredentialRpEntity(name='test server', id='example.org'))
    exclude_credentials = []
    options, state = server.register_begin(
        {'id': b'randomhandle', 'name': 'username', 'displayName': 'User Name'},
        exclude_credentials
    )
    attestation = device.create(options, 'https://example.org')
    auth_data = server.register_complete(
        state,
        CollectedClientData(attestation['response']['clientDataJSON']),
        AttestationObject(attestation['response']['attestationObject'])
    )

    assert isinstance(auth_data, AuthenticatorData)

def test_authenticate():
    """test authentication"""

    device = SoftWebauthnDevice()
    device.cred_init('example.org', b'randomhandle')
    registered_credential = device.cred_as_attested()

    server = Fido2Server(PublicKeyCredentialRpEntity(name='test server', id='example.org'))
    options, state = server.authenticate_begin([registered_credential])
    assertion = device.get(options, 'https://example.org')
    server.authenticate_complete(
        state,
        [registered_credential],
        assertion['rawId'],
        CollectedClientData(assertion['response']['clientDataJSON']),
        AuthenticatorData(assertion['response']['authenticatorData']),
        assertion['response']['signature']
    )


import os
import slack
from get_firestore_tracked_cases import get_firestore_tracked_cases

def list_tracked_cases_all(channel_id, user_id):
    """
    Display all the Google Cloud support cases being tracked in the Slack
    worskpace to the user that submitted the command.

    Parameters
    ----------
    channel_id : str
      unique string used to idenify a Slack channel. Used to send messages to
      the channel
    user_id : str
      the Slack user_id of the user who submitted the request. Used to send
      ephemeral messages to the user
    """
    client = slack.WebClient(token=os.environ.get("SLACK_TOKEN"))
    tracked_cases = get_firestore_tracked_cases()

    all_tracked_cases = []
    for tc in tracked_cases:
        temp = {"channel": tc["channel_name"], "case": tc["case"]}
        all_tracked_cases.append(temp)

    if len(all_tracked_cases) > 0:
        client.chat_postEphemeral(
            channel=channel_id,
            user=user_id,
            text=f"Currently tracking cases {all_tracked_cases}")
    else:
        client.chat_postEphemeral(
            channel=channel_id,
            user=user_id,
            text="There are no cases currently being tracked in Slack")

if __name__ == "__main__":
    test_channel_id = os.environ.get("TEST_CHANNEL_ID")
    test_user_id = os.environ.get("TEST_USER_ID")
    list_tracked_cases_all(test_channel_id, test_user_id)


import torch
from torchvision.datasets import ImageFolder
from data.transforms import *
import settings.environment as env
import pandas as pd
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.transforms import Resize
from typing import Tuple, Union, List
from pathlib import Path
import os

def preprocess(img: torch.tensor,
                mean: Tuple(float)=(0.485, 0.456, 0.406),
                std: Tuple(float)=(0.485, 0.456, 0.406)
                ) -> np.ndarray:
    """
    Reverse transform an image that was normalized by the dataloader
    to be plotted
    Args:
        img (torch.tensor): data tensor to be visualized
        mean:(Tuple(float)): mean applied in the dataloader Normalize transform
        std:(Tuple(float)): standard deviation applied in the dataloader Normalize transform
    Returns:
        npimg (np.ndarray): data numpy array ready to be imshowed
    """

    for t, m, s in zip(img, mean, std):
        t.mul_(s).add_(m)
    npimg = img.numpy()
    npimg = np.transpose(npimg, (1, 2, 0))
    return npimg

class CelebaDataset(Dataset):
    """
    Custom Dataset for loading CelebA face images
    """

    def __init__(self, txt_path: Union[str, Path],
                img_dir: Union[str, Path],
                transform: transforms=None
                ) -> None:
        """
        Dataset construction
        Args:
            - text_path (Union[str, Path]): path of the csv file containing the image id along with their label
            Example:
                image_id    y
            0   00001.jpg   1
            1   03234.jpg   0
            2   00024.jpg   1

            - img_dir (Union[str, Path]): path of the folder containing the celebaimages
            Example:
                ./datasets/celeba/img_align_celeba
            - transform (torchvision.transforms): image transform to be applied to the image upon getting an item
        """
        df = pd.read_csv(txt_path)
        self.img_dir = img_dir
        self.txt_path = txt_path
        self.img_names = df["image_id"].values
        self.y = df["y"].values
        self.transform = transform

    def __getitem__(self, index: int) -> Tuple[torch.tensor, torch.tensor]:
        """
        Note that at each __getitem__call, the image is loaded
        from the self.img_dir directory using its path
        """
        img = Image.open(os.path.join(self.img_dir,
                                      self.img_names[index])
                        )
        if self.transform is not None:
            img = self.transform(img)

        label = self.y[index]
        return img, label

    def __len__(self) -> int:
        return self.y.shape[0]

def GenerateLabelsFromDNF(dnf: List[List[Tuple[Union(str, int)]]],
                        csv_path: Union[str, Path]
                        ) -> Tuple[np.ndarray, np.ndarray]:
    """
    Generates image ids along with associated label
    where label=1 is given by a disjunctive normal form (dnf)

    Args:
        - dnf (List[List[Tuple[Union(str, int)]]]):
        each disjunctive normal form is parsed as a list of conjunctions,
        where each conjunction is itself a list of predicates, and each predicate
        is a tuple containing the predicate name (e.g. "Blond_Hair") and whether it
        is negated (-1) or not (+1).

        Example:
            To parse "If it's chubby man with gray hair OR a blond women with eye glasses, then label 1",
            write:
            dnf = [
            [("Gray_Hair", 1), ("Male", 1), ("Chubby", 1)],
            [("Blond_Hair", 1), ("Male", -1), ("Eyeglasses", 1)]
            ]

        - csv_path (Union[str, Path]): path of the whole Celeb csv file (list_attr_celeba.csv) containing, for each of the image_id, the boolean evaluation
        of each of the 40 attributes (1 is True, -1 otherwise)

        Aspect of list_attr_celeba.csv:
                image_id    Attribute 1     Attribute 2     Attribute 3     ...
                000001.jpg      -1              1               1           ...
                000002.jpg       1             -1               1           ...
                000003.jpg       1              1               1           ...

    Returns:
        labels (np.ndarray): boolean evaluation of the DNF over each sample of the CelebA dataset
                            (DNF == True is encoded as 1, 0 otherwise)
        paths (np.ndarray): associated image_ids of each CelebA sample
    """

    df = pd.read_csv(csv_path)
    # Load all available binary descriptors/predicates
    predicates = df.columns[1:].to_numpy()

    # Build a dictionary that maps a predicates to an index
    predicates_dict = {value:key for key, value in enumerate(predicates)}

    # Convert DataFrame to numpy array
    df_np = df.to_numpy()
    batch =  df_np[:, 1:]
    labels = np.zeros(batch.shape[0], dtype=int)
    paths = df_np[:, 0]

    # Evaluate each conjunction in the DNF over the batch
    for conj in dnf:
        # From the data, select only the attributes (i.e. columns) involved in the current conjunction
        conj_idx = [predicates_dict[c[0]] for c in conj]
        batch_tmp = batch[:, conj_idx]

        # Form a mask of the same size as batch_tmp to flip the Truth value
        # of the negated predicate in the current conjunction
        mask = np.tile([c[1] for c in conj], (batch.shape[0], 1))

        #Convert -1 (False) + 1 (True) values to 0 (False) 1 (True) values
        batch_tmp = np.maximum(batch_tmp * mask, 0)

        # Evaluate the conjunction by multiplying along dim 1 (along the columns, e.g. predicates)
        labels += np.prod(batch_tmp, axis=1, dtype=int)

    # Evaluate the DNF over the batch
    labels = np.minimum(labels, 1)

    return labels, paths

def CreateDatasetDataFrame(labels: np.ndarray,
                            paths: np.ndarray,
                            csv_path: Union[Path, str],
                            split: int=0
                            ) -> pd.DataFrame:
    """
    Creates a Pandas Dataframe with image_ids along with
    label DNF evaluation, with balanced positive and negative
    examples, for a given split (train, val or test). The split index
    (i.e. whether a sample belongs to train, val or test) is given
     by a .csv file given with the CelebA dataset

    Args:
        - labels (np.ndarray): numpy array with the label/DNF evaluation
        - paths (np.ndarray): numpy array with the image_id associated to each
                            label/DNF evaluation
        -csv_path (Union[Path, str]): path to the list_eval_partition.csv file partition
                                where each image id is paired with a label 0, 1 or 2 if it
                                belongs to the train, val or test split

    Returns:
        df (pd.DataFrame): Pandas Dataframe containing each image id along with label 0 and 1
                            specified by the DNF given. The first N rows are filled with negative
                            examples (label 0) and the next N ones with positive examples (label 1).
                            The examples are shuffle by the Dataloader object that is subsequently
                            built from this Dataframe (see GenerateDataLoader)

        Example:
                image_id    label
            0   000032.jpg      0
            1   000054.jpg      0
            ...
            N   000124.jpg      1
            N+1 000434.jpg      1
            ...
    """

    df_split = pd.read_csv(csv_path)
    df_split_np = df_split.to_numpy()
    split_idx = df_split_np[:, 1]
    labels, paths = labels[split_idx == split], paths[split_idx == split]
    labels_pos = labels[labels == 1]
    paths_pos = paths[labels == 1]
    labels_neg = labels[labels == 0]
    paths_neg = paths[labels == 0]

    # Ensure the classes are even
    if labels_pos.shape[0] >= labels_neg.shape[0]:
        rand_idx = np.random.permutation(np.arange(labels_pos.shape[0]))
        rand_idx = rand_idx[:labels_neg.shape[0]]
        labels_pos = labels_pos[rand_idx]
        paths_pos = paths_pos[rand_idx]
    else:
        rand_idx = np.random.permutation(np.arange(labels_neg.shape[0]))
        rand_idx = rand_idx[:labels_pos.shape[0]]
        labels_neg = labels_neg[rand_idx]
        paths_neg = paths_neg[rand_idx]

    labels = np.concatenate((labels_pos, labels_neg), 0)
    paths = np.concatenate((paths_pos, paths_neg), 0)

    df = np.concatenate((np.expand_dims(paths, 1), np.expand_dims(labels, 1)), axis = 1)
    df = pd.DataFrame(df, columns = ['image_id', 'y'])
    return df

def GenerateSplitFromDNFs(dnf: List[List[Tuple[Union(str, int)]]],
                        csv_attr_path: Union[Path, str],
                        csv_split_path: Union[Path, str],
                        csv_save_path: Union[Path, str]
                        ) -> None:
    """
    Generate a DataFrame file containing image ids along with labels (specified by a DNF)
    for each split (train, val and test) and save them in the dataset directory

    Args:
        - dnf (List[List[Tuple[Union(str, int)]]]):
        each disjunctive normal form is parsed as a list of conjunctions,
        where each conjunction is itself a list of predicates, and each predicate
        is a tuple containing the predicate name (e.g. "Blond_Hair") and whether it
        is negated (-1) or not (+1).

        Example:
            To parse "If it's chubby man with gray hair OR a blond women with eye glasses, then label 1",
            write:
            dnf = [
            [("Gray_Hair", 1), ("Male", 1), ("Chubby", 1)],
            [("Blond_Hair", 1), ("Male", -1), ("Eyeglasses", 1)]
            ]
        - csv_attr_path (Union[Path, str]): path to the .csv file containing the image_ids with the 40 attributes
        - csv_split_path (Union[Path, str]): path to the list_eval_partition.csv file partition
                                where each image id is paired with a label 0, 1 or 2 if it
                                belongs to the train, val or test split
        - csv_save_path (Union[Path, str]): path where to save the output .csv files
    Returns:
        None (directly saves the .csv files generated)
    """

    labels, paths = GenerateLabelsFromDNF(dnf, csv_attr_path)
    dict_split = {"train": 0, "val": 1, "test": 2}
    df_dict = {key: CreateDatasetDataFrame(labels,
                                            paths, csv_split_path,
                                            split=value)
                for key, value in dict_split.items()
                }
    for key, value in df_dict.items():
        assert len(value.loc[value["y"] == 0]) == len(value.loc[value["y"] == 1])
        value.to_csv(csv_save_path + '/' + key + '.csv')

def GenerateDataLoader(csv_path: Union[str, Path],
                        im_path: Union[str, Path],
                        im_size: int,
                        batch_size: int
                        )-> DataLoader:
    '''
    Creates a dataloader object from the csv_path containing image ids and associated labels
    and path of the directory containing the images
    Args:
        - csv_path (Union[str, Path]): csv file containing the image ids along with labels
        - im_path (Union[str, Path]): path of the directory containing the CelebA images
        - im_size (int): desired width and height of the images
        - batch_size (int): desired batch size
    Returns:
        dataloader (DataLoader)
    '''

    custom_transform = transforms.Compose([
                                        transforms.ToTensor(),
                                        # Resize(size=(im_size, im_size)),
                                        # transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
                                        ])

    dataset = CelebaDataset(txt_path=csv_path,
                                img_dir=im_path,
                                transform=custom_transform)

    dataloader = DataLoader(dataset=dataset,
                            batch_size=batch_size,
                            shuffle=True,
                            num_workers=1)

    return dataloader

if __name__ == "__main__":

    '''
    Initial parsing of a disjunctive normal form:
    Example: If (no eye glasses, male and chubby) or (blond hair and female) => 1
    '''

    dnf = [
            [("Gray_Hair", 1), ("Male", 1), ("Chubby", 1)],
            [("Blond_Hair", 1), ("Male", -1), ("Eyeglasses", 1)]
        ]

    GenerateSplitFromDNFs(dnf,
                        env.DATASETS_FOLDER + '/celeba/list_attr_celeba.csv',
                        env.DATASETS_FOLDER + '/celeba/list_eval_partition.csv',
                        env.DATASETS_FOLDER
                        )

    train_loader = GenerateDataLoader(csv_path = env.DATASETS_FOLDER + '/train.csv',
                                        im_path = env.DATASETS_FOLDER + '/celeba/img_align_celeba/',
                                        im_size = 32,
                                        batch_size = 64)

    _, (x, y) = next(enumerate(train_loader))

    x_pos = x[torch.where(y==1)[0], :][:6, :]
    x_neg = x[torch.where(y==0)[0], :][:6, :]

    fig, (axes1, axes2) = plt.subplots(nrows=2, ncols=6, figsize=[16,6])
    for i in range(len(axes1)):
        axes1[i].imshow(preprocess(x_pos[i]))
        axes1[i].set_title("Positive")
        axes2[i].imshow(preprocess(x_neg[i]))
        axes2[i].set_title("Negative")
    plt.show()

    print("Done!")


import pyspark
from operator import add
import time

"""
Transactions layout
0 - block_number: Block number where this transaction was in
1 - from_address: Address of the sender
2 - to_address: Address of the receiver. null when it is a contract creation transaction
3 - value: Value transferred in Wei (the smallest denomination of ether)
4 - gas: Gas provided by the sender
5 - gas_price : Gas price provided by the sender in Wei
6 - block_timestamp: Timestamp the associated block was registered at (effectively timestamp of the transaction)

ScamsCSV layout
0 - Scam ID
1 - Name
2 - URL
3 - Coin
4 - Category
5 - Sub-category
6 - Address
7 - Status
"""

sc = pyspark.SparkContext()

def is_good_line(line):
    try:
        fields = line.split(',')
        if len(fields) == 7: # transactions
            str(fields[2]) # to_addr
            if int(fields[3]) == 0:
                return False
        elif len(fields) == 8: # contracts
            str(fields[6]) # Scam addr
            str(fields[4]) # Scam category
        else:
            return False
        return True
    except:
        return False

def mapper_transactions(line):
    try:
        fields = line.split(',')
        to_addr = fields[2]
        wei = int(fields[3])
        raw_timestamp = int(fields[6])
        year_month = time.strftime('%Y-%m', time.gmtime(raw_timestamp))

        key = to_addr
        value = ( year_month, wei, 1 )
        return (key, value)
    except:
        pass

transactions = sc.textFile('/data/ethereum/transactions').filter(is_good_line)
scams = sc.textFile('scams.csv').filter(is_good_line)

scams_addr = scams.map(lambda l: (l.split(',')[6], l.split(',')[4]))

# calculate Wei received at each address in each month
step1 = transactions.map(mapper_transactions)
step2 = step1.join(scams_addr)
step3 = step2.map(lambda x: ((x[1][1], x[1][0][0]), (x[1][0][1], x[1][0][2])))
step4 = step3.reduceByKey(lambda a, b: (a[0]+b[0], a[1]+b[1]) )
step5 = step4.map(lambda x: '{},{},{},{},{}'.format(x[0][0], x[0][1], float(x[1][0]/1000000000000000000), x[1][1], float(x[1][0]/1000000000000000000)/x[1][1]))

step5.saveAsTextFile('out_monthly_scam_transactions')


from typing import List, Dict
from tools_for_graph import *
from tools_for_heuristics import *
from tools_for_plotting import *
from algs.test_single_alg import test_single_alg
from algs.alg_a_star_space_time import a_star_xyt
from environments.env_LL_MAPF import EnvLifelongMAPF

class ParObsPFPrPAgent:
    """
    Public methods:
    .update_obs(obs, **kwargs)
    .clean_nei()
    .add_nei(agent1)
    .build_plan(h_agents)
    .choose_action()
    """

    def __init__(self, num: int, start_node, next_goal_node, **kwargs):
        # h_value = h_dict[to_node.xy_name][from_node.x, from_node.y]
        self.num = num
        self.name = f'agent_{num}'
        self.start_node: Node = start_node
        self.name_start_node = start_node.xy_name
        self.prev_node: Node = start_node
        self.curr_node: Node = start_node
        self.prev_goal_node: Node = start_node
        self.next_goal_node: Node = next_goal_node
        self.name_next_goal_node = next_goal_node.xy_name
        self.first_goal_node: Node = next_goal_node
        self.closed_goal_nodes: List[Node] = []
        self.plan = None
        self.plan_succeeded = False
        self.nodes = kwargs['nodes']
        self.nodes_dict = kwargs['nodes_dict']
        self.h_func = kwargs['h_func']
        self.h_dict = kwargs['h_dict']
        self.params = kwargs['params']
        self.map_dim = kwargs['map_dim']
        self.heuristic_value = None
        self.heuristic_value_init = self.h_dict[self.next_goal_node.xy_name][self.curr_node.x, self.curr_node.y]
        self.pf_field = None
        self.memory = np.zeros((self.map_dim[0], self.map_dim[1]))
        self.nei_list, self.nei_dict, self.nei_plans_dict, self.nei_h_dict, self.nei_pf_dict, self.nei_succ_dict = [], {}, {}, {}, {}, {}
        self.nei_num_dict = {}
        self.nei_pfs = None
        self.h, self.w = set_h_and_w(self)
        self.pf_weight = set_pf_weight(self)
        self.latest_arrival = None
        self.time_passed_from_last_goal = None

    def update_obs(self, obs, **kwargs):
        self.curr_node = obs['curr_node']
        self.prev_node = obs['prev_node']
        self.prev_goal_node = obs['prev_goal_node']
        self.next_goal_node = obs['next_goal_node']
        self.closed_goal_nodes = obs['closed_goal_nodes']
        self.latest_arrival = obs['latest_arrival']
        self.time_passed_from_last_goal = obs['time_passed_from_last_goal']
        self.heuristic_value = self.h_dict[self.next_goal_node.xy_name][self.curr_node.x, self.curr_node.y]
        if self.curr_node.xy_name != self.next_goal_node.xy_name:
            self.memory[self.curr_node.x, self.curr_node.y] += 1

    def clean_nei(self):
        self.nei_list, self.nei_dict, self.nei_plans_dict, self.nei_h_dict, self.nei_pf_dict, self.nei_succ_dict = [], {}, {}, {}, {}, {}
        self.nei_num_dict = {}

    def add_nei(self, nei_agent):
        self.nei_list.append(nei_agent)
        self.nei_dict[nei_agent.name] = nei_agent
        self.nei_plans_dict[nei_agent.name] = nei_agent.plan
        self.nei_h_dict[nei_agent.name] = nei_agent.heuristic_value
        self.nei_num_dict[nei_agent.name] = nei_agent.num
        self.nei_pf_dict[nei_agent.name] = None  # in the _all_exchange_plans method
        self.nei_succ_dict[nei_agent.name] = None  # in the _all_exchange_plans method

    def build_plan(self, h_agents, goal=None):
        # self._execute_a_star(h_agents)
        if self.plan is None or len(self.plan) == 0:
            nei_h_agents = [agent for agent in h_agents if agent.name in self.nei_dict]
            sub_results = create_sub_results(nei_h_agents)
            v_constr_dict, e_constr_dict, perm_constr_dict, xyt_problem = build_constraints(self.nodes, sub_results)
            nei_pfs, max_plan_len = self._build_nei_pfs(nei_h_agents)
            if goal is None:
                goal = self.next_goal_node
            self.execute_a_star(v_constr_dict, e_constr_dict, perm_constr_dict, xyt_problem, nei_pfs, goal=goal)
        return self.plan

    def correct_nei_pfs(self):
        if self.nei_pfs is not None:
            self.nei_pfs = self.nei_pfs[:, :, 1:]
            if self.nei_pfs.shape[2] == 0:
                self.nei_pfs = None

    def choose_action(self):
        next_node: Node = self.plan.pop(0)
        if self.pf_weight != 0:
            self.pf_field = self.pf_field[:, :, 1:]
            self.correct_nei_pfs()
        return next_node.xy_name

    def get_full_plan(self):
        full_plan = [self.curr_node]
        full_plan.extend(self.plan)
        return full_plan

    def _get_weight(self, nei_heuristic_value):

        # pf_weight_pref = self.params['pf_weight_pref'] if 'pf_weight_pref' in self.params else 'short_paths'
        # pf_weight_pref = self.params['pf_weight_pref'] if 'pf_weight_pref' in self.params else 'long_paths'
        # pf_weight_pref = self.params['pf_weight_pref'] if 'pf_weight_pref' in self.params else 'my_h_long'
        # pf_weight_pref = self.params['pf_weight_pref'] if 'pf_weight_pref' in self.params else 'my_h_short'
        pf_weight_pref = self.params['pf_weight_pref'] if 'pf_weight_pref' in self.params else 'uniform'

        # Prefer Longer Paths
        if pf_weight_pref == 'long_paths':
            relative_length = (nei_heuristic_value / self.heuristic_value) / 2
            if 0 <= relative_length < 0.2:
                return 0
            if 0.2 <= relative_length < 0.4:
                return 0.25 * self.pf_weight
            if 0.4 <= relative_length < 0.6:
                return 0.5 * self.pf_weight
            if 0.6 <= relative_length < 0.8:
                return 0.75 * self.pf_weight
            if 0.8 <= relative_length:
                return self.pf_weight

        # Prefer Shorter Paths
        if pf_weight_pref == 'short_paths':
            relative_length = (nei_heuristic_value / self.heuristic_value) / 2
            if 0 <= relative_length < 0.2:
                return self.pf_weight
            if 0.2 <= relative_length < 0.4:
                return 0.75 * self.pf_weight
            if 0.4 <= relative_length < 0.6:
                return 0.5 * self.pf_weight
            if 0.6 <= relative_length < 0.8:
                return 0.25 * self.pf_weight
            if 0.8 <= relative_length:
                return 0

        if pf_weight_pref == 'my_h_long':
            big_size = max(self.map_dim) / 2
            if self.heuristic_value < big_size:
                partial = 1 - (self.heuristic_value / big_size)
                return partial * self.pf_weight
            return 0

        if pf_weight_pref == 'my_h_short':
            big_size = max(self.map_dim) / 2
            if self.heuristic_value < big_size:
                partial = self.heuristic_value / big_size
                return partial * self.pf_weight
            return self.pf_weight

        if pf_weight_pref == 'uniform':
            return self.pf_weight

        return self.pf_weight

    # POTENTIAL FIELDS ****************************** pf_weight ******************************
    def _build_nei_pfs(self, h_agents):
        if self.pf_weight == 0:
            self.nei_pfs = None
            return None, None
        if len(h_agents) == 0:
            return None, None
        max_plan_len = max([len(agent.plan) for agent in h_agents])
        nei_pfs = np.zeros((self.map_dim[0], self.map_dim[1], max_plan_len))  # x, y, t
        for nei_agent in h_agents:
            up_until_t = len(nei_agent.plan)
            weight = self._get_weight(nei_heuristic_value=nei_agent.heuristic_value)
            nei_pfs[:, :, :up_until_t] += weight * nei_agent.pf_field

        self.nei_pfs = nei_pfs
        return nei_pfs, max_plan_len

    # POTENTIAL FIELDS ****************************** pf_size  ******************************
    # POTENTIAL FIELDS ****************************** pf_shape ******************************
    def _get_gradient_list(self):
        pf_size = self.params['pf_size']
        pf_shape = self.params['pf_shape'] if 'pf_shape' in self.params else 2
        if pf_size == 'h':
            h_value = self.h_func(self.start_node, self.next_goal_node)
        else:
            h_value = pf_shape ** pf_size
        biggest_value = h_value
        gradient_list = [h_value]
        while h_value > 1:
            h_value /= pf_shape
            gradient_list.append(h_value)
        gradient_list = [i / biggest_value for i in gradient_list]
        return gradient_list

    # POTENTIAL FIELDS ************************* pf_shape of circle ************************
    def _create_pf_field(self):
        # if self.curr_node.xy_name == self.next_goal_node.xy_name: return
        if self.pf_weight == 0: return
        gradient_list = self._get_gradient_list()
        if len(gradient_list) == 0: return

        self.pf_field = np.zeros((self.map_dim[0], self.map_dim[1], len(self.plan)))
        if check_stay_at_same_node(self.plan, self.next_goal_node):
            return
        for i_time, next_node in enumerate(self.plan):
            nei_nodes, nei_nodes_dict = get_nei_nodes(next_node, len(gradient_list), self.nodes_dict)
            for i_node in nei_nodes:
                distance_index = min(len(gradient_list) - 1, math.floor(euclidean_distance_nodes(next_node, i_node)))
                self.pf_field[i_node.x, i_node.y, i_time] += float(gradient_list[distance_index])
        # plot_magnet_field(self.magnet_field)

    def execute_a_star(self, v_constr_dict, e_constr_dict, perm_constr_dict, xyt_problem, nei_pfs,
                       goal=None):
        if goal is None:
            goal = self.next_goal_node
        # v_constr_dict, e_constr_dict, perm_constr_dict, xyt_problem = self._create_constraints(h_agents)
        new_plan, a_s_info = a_star_xyt(start=self.curr_node, goal=goal,
                                        nodes=self.nodes, nodes_dict=self.nodes_dict, h_func=self.h_func,
                                        v_constr_dict=v_constr_dict, e_constr_dict=e_constr_dict,
                                        perm_constr_dict=perm_constr_dict,
                                        agent_name=self.name,
                                        nei_pfs=nei_pfs, k_time=self.w + 1, xyt_problem=xyt_problem)
        if new_plan is not None:
            # pop out the current location, because you will order to move to the next location
            self.plan_succeeded = True
            new_plan.pop(0)
            self.plan = new_plan
            self._fulfill_the_plan()
            self._create_pf_field()
        else:
            # self.plan = None
            # IStay
            self.set_istay()

    def _fulfill_the_plan(self):
        if len(self.plan) == 0:
            self.plan = [self.curr_node]
        if self.h and self.h < 1000:
            while len(self.plan) < self.h:
                self.plan.append(self.plan[-1])

    def set_istay(self):
        self.plan = [self.curr_node]
        self._fulfill_the_plan()
        self._create_pf_field()
        self.plan_succeeded = False
        # print(f' \r\t --- [{self.name}]: I stay!', end='')

class AlgParObsPFPrPSeq:
    """
    Public methods:
    .first_init(env)
    .reset()
    .get_actions(observations)
    """

    def __init__(self, params, alg_name):
        self.params = params
        self.alg_name = alg_name
        self.env = None
        self.agents = None
        self.agents_dict = {}
        self.n_agents = None
        self.map_dim = None
        self.nodes, self.nodes_dict = None, None
        self.h_dict = None
        self.h_func = None
        self.curr_iteration = None
        self.agents_names_with_new_goals = []
        self.i_agent = None

        # RHCR part
        self.h, self.w = set_h_and_w(self)

        # limits
        self.time_to_think_limit = None

    def first_init(self, env: EnvLifelongMAPF, **kwargs):
        self.env = env
        self.n_agents = env.n_agents
        self.map_dim = env.map_dim
        self.nodes, self.nodes_dict = env.nodes, env.nodes_dict
        self.h_dict = env.h_dict
        self.h_func = env.h_func

        self.agents = None
        self.agents_dict = {}
        self.curr_iteration = None
        self.agents_names_with_new_goals = []

        # limits
        self.time_to_think_limit = 1e6
        if 'time_to_think_limit' in kwargs:
            self.time_to_think_limit = kwargs['time_to_think_limit']

    def reset(self):
        self.agents: List[ParObsPFPrPAgent] = []
        for env_agent in self.env.agents:
            new_agent = ParObsPFPrPAgent(
                num=env_agent.num, start_node=env_agent.start_node, next_goal_node=env_agent.next_goal_node,
                nodes=self.nodes, nodes_dict=self.nodes_dict, h_func=self.h_func, h_dict=self.h_dict,
                map_dim=self.map_dim, params=self.params
            )
            self.agents.append(new_agent)
            self.agents_dict[new_agent.name] = new_agent
            self.curr_iteration = 0
        self.i_agent = self.agents_dict['agent_0']

    # @check_time_limit()
    def get_actions(self, observations, **kwargs):
        """
        observations[agent.name] = {
                'num': agent.num,
                'curr_node': agent.curr_node,
                'next_goal_node': agent.next_goal_node,
            }
        actions: {agent_name: node_name, ...}
        """
        self.curr_iteration = kwargs['iteration']

        # update the current state
        self.agents_names_with_new_goals = observations['agents_names_with_new_goals']
        for agent in self.agents:
            agent.update_obs(observations[agent.name], agents_dict=self.agents_dict)

        # update neighbours - RHCR part
        self._update_neighbours()

        # build the plans - PF part
        build_plans_info = self._build_plans()

        # choose the actions
        actions = {agent.name: agent.choose_action() for agent in self.agents}
        self._add_one_shot_to_actions(actions)

        alg_info = {
            'i_agent': self.i_agent,
            'i_nodes': self.nodes,
            'alg_name': self.alg_name,
            'time_to_think_limit': self.time_to_think_limit,
        }
        alg_info.update(build_plans_info)

        # checks
        check_actions_if_vc(self.agents, actions)
        check_actions_if_ec(self.agents, actions)

        return actions, alg_info

    def _update_neighbours(self):
        _ = [agent.clean_nei() for agent in self.agents]
        if self.h is None or self.h >= 1e6:
            for agent1, agent2 in combinations(self.agents, 2):
                agent1.add_nei(agent2)
                agent2.add_nei(agent1)
        else:
            for agent1, agent2 in combinations(self.agents, 2):
                distance = manhattan_distance_nodes(agent1.curr_node, agent2.curr_node)
                if distance <= 2 * self.h + 1:
                    agent1.add_nei(agent2)
                    agent2.add_nei(agent1)

    def _update_order(self):
        finished_list = []
        unfinished_list = []
        for agent in self.agents:
            if agent.plan is not None and len(agent.plan) == 0:
                finished_list.append(agent)
            else:
                unfinished_list.append(agent)
        self.agents = unfinished_list
        self.agents.extend(finished_list)

    def _reshuffle_agents(self):
        # print(f'\n**************** random reshuffle ****************\n')

        stuck_agents = [agent for agent in self.agents if not agent.plan_succeeded]
        good_agents = [agent for agent in self.agents if agent.plan_succeeded]
        random.shuffle(stuck_agents)
        random.shuffle(good_agents)
        stuck_agents.extend(good_agents)
        self.agents = stuck_agents

        # random.shuffle(self.agents)

        for agent in self.agents:
            agent.plan = None

    def _implement_istay(self):
        # IStay
        there_is_conf = True
        # pairs_list = list(combinations(self.agents, 2))
        standing_agents = set()
        while there_is_conf:
            there_is_conf = False
            for agent1, agent2 in combinations(self.agents, 2):
                if agent1.name not in agent2.nei_dict:
                    continue
                if agent1.name in standing_agents:
                    if agent2.name in standing_agents:
                        continue
                    if not plan_has_no_conf_with_vertex(agent2.plan, agent1.curr_node):
                        there_is_conf = True
                        agent2.set_istay()
                        standing_agents.add(agent2.name)
                        break
                    else:
                        continue
                if agent2.name in standing_agents:
                    if not plan_has_no_conf_with_vertex(agent1.plan, agent2.curr_node):
                        there_is_conf = True
                        agent1.set_istay()
                        standing_agents.add(agent1.name)
                        break
                    else:
                        continue
                if not two_plans_have_no_confs(agent1.plan, agent2.plan):
                    there_is_conf = True
                    agent1.set_istay()
                    agent2.set_istay()
                    standing_agents.add(agent1.name)
                    standing_agents.add(agent2.name)
                    break

    def _cut_up_to_the_limit(self, i):
        if len(self.agents) >= i:
            for failed_agent in self.agents[i + 1:]:
                failed_agent.set_istay()
        self._implement_istay()

    def _build_plans_restart(self):
        if self.h and self.curr_iteration % self.h != 0 and self.curr_iteration != 0:
            return
        start_time = time.time()
        self._update_order()

        h_agents = []
        need_to_shuffle = False
        for i, agent in enumerate(self.agents):
            agent.build_plan(h_agents)
            h_agents.append(agent)
            if not agent.plan_succeeded:
                need_to_shuffle = True

            # limit check
            end_time = time.time() - start_time
            if end_time > self.time_to_think_limit:
                self._cut_up_to_the_limit(i)
                return

        # IStay
        self._implement_istay()

        if need_to_shuffle:
            random.shuffle(self.agents)

    def initial_prp_assignment(self, start_time):
        # Persist
        h_agents = []
        for i, agent in enumerate(self.agents):
            agent.build_plan(h_agents)
            h_agents.append(agent)

            # limit check
            end_time = time.time() - start_time
            if end_time > self.time_to_think_limit:
                self._cut_up_to_the_limit(i)
                return True
        return False

    def _build_plans_persist(self):
        if self.h and self.curr_iteration % self.h != 0 and self.curr_iteration != 0:
            return
        start_time = time.time()
        # self._update_order()
        self._reshuffle_agents()

        # Persist
        time_limit_crossed = self.initial_prp_assignment(start_time)
        if time_limit_crossed:
            return

        # IStay
        self._implement_istay()

    def _add_one_shot_to_actions(self, actions):
        if 'one_shot' in self.params:
            actions['one_shot'] = self.params['one_shot']
            actions['latest_arrivals'] = {}
            actions["succeeded"] = True
            for agent in self.agents:
                if not agent.plan_succeeded:
                    actions["succeeded"] = False
                    break
                else:
                    actions['latest_arrivals'][agent.name] = len(agent.plan)

    def _build_plans(self):
        if self.h is None:
            self._build_plans_restart()
        else:
            self._build_plans_persist()
        return {}

@use_profiler(save_dir='../stats/alg_par_obs_pf_prp_seq.pstat')
def main():
    # Alg params
    # alg_name = 'PrP'
    # alg_name = 'PF-PrP'
    alg_name = 'ParObs-PrP'
    # alg_name = 'ParObs-PF-PrP'

    params_dict = {
        'PrP': {},
        'PF-PrP': {
            # 'pf_weight': 0.1,
            'pf_weight': 1,
            # 'pf_weight': 2,
            # 'pf_size': 'h',
            'pf_size': 3,
            # 'pf_size': 5,
            # 'pf_size': 2,
            'pf_shape': 2,
        },
        'ParObs-PrP': {
            # For RHCR
            'h': 5,  # my step
            'w': 5,  # my planning
        },
        'ParObs-PF-PrP': {
            # For PF
            # 'pf_weight': 0.5,
            'pf_weight': 1,
            # 'pf_weight': 2,
            # 'pf_weight': 3,
            # 'pf_weight': 5,
            # 'pf_weight': 10,
            # 'pf_size': 'h',
            # 'pf_size': 5,
            'pf_size': 4,
            # 'pf_size': 2,
            # For RHCR
            'h': 5,  # my step
            'w': 5,  # my planning
        },
    }

    alg = AlgParObsPFPrPSeq(params=params_dict[alg_name], alg_name=alg_name)
    test_single_alg(
        alg,

        # GENERAL
        # random_seed=True,
        random_seed=False,
        seed=321,
        PLOT_PER=1,
        PLOT_RATE=0.001,
        PLOT_FROM=1,
        middle_plot=True,
        # middle_plot=False,
        final_plot=True,
        # final_plot=False,

        # FOR ENV
        iterations=200,
        # iterations=100,
        # iterations=50,
        n_agents=300,
        n_problems=1,
        classical_rhcr_mapf=True,
        # classical_rhcr_mapf=False,
        global_time_limit=100000,
        time_to_think_limit=100000,  # seconds
        rhcr_mapf_limit=10000,

        # Map
        # img_dir='empty-32-32.map',  # 32-32
        img_dir='random-32-32-10.map',  # 32-32          | LNS | Up to 400 agents with w=5, h=2, lim=1min.
        # img_dir='random-32-32-20.map',  # 32-32
        # img_dir='room-32-32-4.map',  # 32-32
        # img_dir='maze-32-32-2.map',  # 32-32
        # img_dir='empty-48-48.map',
    )

if __name__ == '__main__':
    main()


import jsonpath
import requests
import json

# API URL
url = "https://regres.in/api/users?page2"

# send get request -74
response = requests.get(url)

# Parse response to Json format
json_response =  json.loads(response.text)
print(json_response)

# Fetch value using json-path
pages = jsonpath.jsonpath(json_response,'total_page') # this will produce a list of values
print(pages(0)) # the '0' inside the brackets represents the index value
assert pages[0] == 4 # number value we should expect, therefore no error if true - any other number entered will give error

# Fetch value using advance json-path
for i in range(0, 3):
    first_name = jsonpath.jsonpath(json_response, 'data[' + str(i) + '].first_name')
    print((first_name[0]))


import logging
from lxml import html
from joj.model.output_variable import OutputVariable
from joj.utils import constants

log = logging.getLogger(__name__)

class JulesOutputVariableParser(object):
    """
    Parser for the Jules documentation
    Parses the html output variables into the database objects
    """

    # Some variables depend on the value of nsmax - keep a record of those names here:
    _DEPENDS_ON_NSMAX = ['snow_ice_gb', 'snow_liq_gb', 'snow_ice_tile', 'snow_liq_tile',
                         'rgrainl', 'snow_ds', 'snow_ice', 'snow_liq', 'tsnow']

    #variable which should appear in the output list (must be lower case)
    _VARIABLES_THAT_SHOULD_BE_USED = \
        ['fqw_gb',
         'ecan_gb',
         'esoil_gb',
         'ei_gb',
         'ftl_gb',
         'cs_gb',
         'cv',
         'gpp_gb',
         'lit_c_mean',
         'npp_gb',
         'resp_p_gb',
         'resp_s_gb',
         'runoff',
         'surf_roff',
         'sub_surf_roff',
         'swet_tot',
         'swet_liq_tot',
         'snow_depth_gb',
         'snow_frac',
         'snow_mass_gb',
         'tstar_gb',
         'smc_tot',
         'rad_net',
         'lw_down',
         'sw_down',
         'wind',
         'tl1',
         'qw1',
         'pstar',
         'precip']

    def parse(self, file_path):
        """
        Run the parser on the output variables file and return a list of OutputVariables
        :param file_path: path of output-variables.html
        :return: list of OutputVariables
        """
        log.info("Parsing %s" % file_path)
        tree = html.parse(file_path)
        output_variables = []
        output_table_rows = tree.xpath(
            '//div[@id="variables-that-have-a-single-value-at-each-land-gridpoint"]/table/tbody/tr[@class="row-even"] '
            '| //div[@id="variables-that-have-a-single-value-at-each-land-gridpoint"]/table/tbody/tr[@class="row-odd"]'
            '| //div[@id="variables-that-have-a-single-value-at-each-gridpoint-land-and-sea"]/table/tbody/tr[@class="row-even"] '
            '| //div[@id="variables-that-have-a-single-value-at-each-gridpoint-land-and-sea"]/table/tbody/tr[@class="row-odd"]')

        for output_row in output_table_rows:
            output_variable = OutputVariable()
            name = str(output_row.xpath('td/tt/span[@class="pre"]/text()')[0])
            if name.lower() in self._VARIABLES_THAT_SHOULD_BE_USED:
                output_variable.name = name
                # Need to reconstruct the description because of <sup> tags
                desc_texts = output_row.xpath('td[2]/text() | td[2]/p[1]/text()')
                desc_tags = output_row.xpath('td[2]/sup/text() | td[2]/p[1]/sup/text() | td[2]/tt/span/text() '
                                             '| td[2]/a/tt/span/text()')
                output_variable.description = unicode(desc_texts[0])
                for i in range(len(desc_tags)):
                    output_variable.description += desc_tags[i]
                    output_variable.description += desc_texts[i+1]
                output_variable.depends_on_nsmax = output_variable.name in constants.DEPENDS_ON_NSMAX
                output_variables.append(output_variable)

        if (len(output_variables) != len(self._VARIABLES_THAT_SHOULD_BE_USED)):
            log.error("'Output variables' length, %s, if different to 'variables to use' length, %s "
                      % (len(output_variables), len(self._VARIABLES_THAT_SHOULD_BE_USED)))
            exit(-1)
        return output_variables

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    parser = JulesOutputVariableParser()
    file_path = '../docs/Jules/user_guide/html/output-variables.html'
    parser.parse(file_path)


"""This script creates the reverse complement of a sequence.

The reverse_complement() function is the default function to create the reverse complement.
The reverse_complement_mitos() function is the one that should be used when dealing with MITOS annotations.
The reverse_complement_annotation() function adjusts the annotation coordinates of features to match the ones from the reverse complemented sequence.

"""

import sys
from Bio import SeqIO

def reverse_complement(in_gb, out_gb):

    # open original record and convert it to
    # its reverse complement (rc_record)
    record = SeqIO.read(in_gb, "genbank")
    rc_record = record.reverse_complement(id=record.id + "_rc")
    # needs to set molecule type as DNA because Biopython deletes
    # this info when parsing
    rc_record.annotations["molecule_type"] = "DNA"

    with open(out_gb, "w") as f:
        SeqIO.write(rc_record, f, "genbank")

    out_fasta = out_gb.replace(".gb", ".fasta")
    with open(out_fasta, "w") as f:
        SeqIO.write(rc_record, f, "fasta")

def reverse_complement_mitos(in_fasta, out_fasta):

    # open original record and convert it to
    # its reverse complement (rc_record)
    record = SeqIO.read(in_fasta, "fasta")
    rc_record = record.reverse_complement(id=record.id + "_rc")

    with open(out_fasta, "w") as f:
        SeqIO.write(rc_record, f, "fasta")

def reverse_complement_annotation(mitogenome_annotation, mitogenome_fasta, mitogenome_annotation_rc):

    for record in SeqIO.parse(mitogenome_fasta, "fasta"):
        mitogenome_len = len(record.seq)

    with open(mitogenome_annotation, "r") as f:
        for line in f:
            fields = line.strip().split()
            new_start = mitogenome_len - int(fields[3]) + 1
            new_end = mitogenome_len - int(fields[4]) + 1
            old_strand = fields[6]

            # switches the signal
            if old_strand == "+":
                new_strand = "-"
            else:
                new_strand = "+"

            # sets first coord as start
            # and second coord as end
            if new_start > new_end:
                b = new_start
                new_start = new_end
                new_end = b

            fields[3] = str(new_start)
            fields[4] = str(new_end)
            fields[6] = new_strand
            with open(mitogenome_annotation_rc, "a") as f2:
                f2.write("\t".join(fields) + "\n")

if __name__ == "__main__":
    in_gb = sys.argv[1]
    out_gb = sys.argv[2]
    reverse_complement(in_gb, out_gb)


import scrapy

class BakerySpider(scrapy.Spider):
  name = 'bakery'
#   start_urls = ['https://keewahsf.com/collections/in-store-pick-up-only',]

# scrapy crawl bakery -a category=in-store-pick-up-only
  def __init__(self, category=None, *args, **kwargs):
    super(BakerySpider, self).__init__(*args, **kwargs)
    self.start_urls = [f'https://keewahsf.com/collections/{category}',]

  def parse(self, response):
    for item in response.css('div.info'):
      yield {
        'name': item.css('span.title::text').get(),
        'price':  item.css('span.money::text').get()
      }

    next = response.css('span.next a::attr("href")').get()
    if next is not None:
      yield response.follow(next, self.parse)


# Tests containing Python 3.5+ syntax, extracted from test_client_server.py.
# To avoid test discovery, this module's name must not start with test_.

import asyncio

from ..client import *
from ..server import *
from ..test_client_server import handler

class ClientServerContextManager:

    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

    def tearDown(self):
        self.loop.close()

    def test_basic(self):
        server = serve(handler, 'localhost', 8642)
        self.server = self.loop.run_until_complete(server)

        async def basic():
            async with connect('ws://localhost:8642/') as client:
                await client.send("Hello!")
                reply = await client.recv()
                self.assertEqual(reply, "Hello!")

        self.loop.run_until_complete(basic())

        self.server.close()
        self.loop.run_until_complete(self.server.wait_closed())


import torch
import torch.nn as nn
import numpy as np
from scipy.optimize import linear_sum_assignment
import os
import os.path
import torch.nn.functional as F

class TransformTwice:
    def __init__(self, transform):
        self.transform = transform

    def __call__(self, inp):
        out1 = self.transform(inp)
        out2 = self.transform(inp)
        return out1, out2

class AverageMeter(object):

    def __init__(self, name, fmt=':f'):
        self.name = name
        self.fmt = fmt
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

    def __str__(self):
        fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
        return fmtstr.format(**self.__dict__)

def accuracy(output, target):

    num_correct = np.sum(output == target)
    res = num_correct / len(target)

    return res

def cluster_acc(y_pred, y_true):
    """
    Calculate clustering accuracy. Require scikit-learn installed
    # Arguments
        y: true labels, numpy.array with shape `(n_samples,)`
        y_pred: predicted labels, numpy.array with shape `(n_samples,)`
    # Return
        accuracy, in [0,1]
    """
    y_true = y_true.astype(np.int64)
    assert y_pred.size == y_true.size
    D = max(y_pred.max(), y_true.max()) + 1
    w = np.zeros((D, D), dtype=np.int64)
    for i in range(y_pred.size):
        w[y_pred[i], y_true[i]] += 1
    row_ind, col_ind = linear_sum_assignment(w.max() - w)

    return w[row_ind, col_ind].sum() / y_pred.size

def entropy(x):
    """
    Helper function to compute the entropy over the batch
    input: batch w/ shape [b, num_classes]
    output: entropy value [is ideally -log(num_classes)]
    """
    EPS = 1e-8
    x_ =  torch.clamp(x, min = EPS)
    b =  x_ * torch.log(x_)

    if len(b.size()) == 2: # Sample-wise entropy
        return - b.sum(dim = 1).mean()
    elif len(b.size()) == 1: # Distribution-wise entropy
        return - b.sum()
    else:
        raise ValueError('Input tensor is %d-Dimensional' %(len(b.size())))

class MarginLoss(nn.Module):

    def __init__(self, m=0.2, weight=None, s=10):
        super(MarginLoss, self).__init__()
        self.m = m
        self.s = s
        self.weight = weight

    def forward(self, x, target):
        index = torch.zeros_like(x, dtype=torch.uint8)
        index.scatter_(1, target.data.view(-1, 1), 1)
        x_m = x - self.m * self.s

        output = torch.where(index, x_m, x)
        return F.cross_entropy(output, target, weight=self.weight)


import random as rnd
import numpy as np
from Rain import Rain
import threading
from matplotlib import pyplot as plt
import time

class Soil:
    LAYERS_SIZE = []
    NUMBER_OF_LAYERS = 5
    LAYERS_PENETRATION = []
    TIME = 0
    DAY_LIMIT_TIME = 20
    DAY = 0
    MONTH = 0
    SEASON = 'spring'
    SEASONS = ['winter', 'winter', 'spring', 'spring', 'spring', 'summer', 'summer', 'summer', 'autumn', 'autumn',
               'autumn', 'winter']
    SPEED = 0
    # Specific properties of Soil
    VALVE_CAPACITY = 40
    IS_WATERING = False
    LAYERS_MOISTURE = []
    RAIN_CHANCE = 0.2
    SEASON_CHANGING_RAIN_MUTATION = {'spring': +.02 , 'summer': -.01 , 'autumn': +0.01, 'winter': +0.01}
    SEASON_CHANGING_PENETRATION = {'spring': +.01, 'summer': +.04, 'autumn': +.0, 'winter': -.4}
    CHANGING_PENETRATION_CHANCE = 0.02
    DAY_EVAPORATE_BASE = 0.02
    DAY_EVAPORATE_ERROR = 0.008
    NIGHT_EVAPORATE_BASE = 0.001
    NIGHT_EVAPORATE_ERROR = 0.008

    input_water = 0

    def __init__(self):
        self.LAYERS_PENETRATION = [np.random.rand() for i in range(self.NUMBER_OF_LAYERS)]
        self.LAYERS_MOISTURE = [np.random.rand() for i in range(self.NUMBER_OF_LAYERS)]
        self.LAYERS_SIZE = [np.random.rand()*50 for i in range(self.NUMBER_OF_LAYERS)]
        self.rain = Rain(time_limit=100, intensity=3, speed=0.1)
        '''
        self.LAYERS_PENETRATION = [0.5, 0.5, 0.5, 0.5]
        self.LAYERS_MOISTURE = [0.7, 0.2, 0.1, 0.0]
        self.LAYERS_SIZE = [70, 80, 90, 90]
        '''

    def irrigation_handler(self):
        all_data = []
        counter = 0
        while self.DAY < 3:
            self.irrigate()
            counter = counter +1
            all_data.append(self.LAYERS_MOISTURE.copy())
            print(self.LAYERS_MOISTURE)
            '''
            print('TIME: '+str(self.TIME) + ' , DAY: '+str(self.DAY)+' , MONTH: '+
                  str(self.MONTH)+' , SEASON: '+str(self.SEASON) + ' , RAINING: ' + str(self.rain.active)+
                  ' , RAINING_TIME_LIMIT: ' + str(self.rain.time_limit))
            for j in range(0, s.NUMBER_OF_LAYERS):
                print(str(s.LAYERS_MOISTURE[j]) + " , " + str(s.LAYERS_SIZE[j]) + " , " + str(s.LAYERS_PENETRATION[j]))
            print()
            time.sleep(1)
            '''
        all_data = np.array(all_data)
        time_axis = np.arange(0, counter)
        print(all_data)
        for i in range(0, self.NUMBER_OF_LAYERS):
            plt.plot(time_axis, all_data[:, i], label='layer '+str(i))
            plt.xlabel('time')
            plt.ylabel('moisture')
        plt.legend()
        plt.show()

    # Calender
    def increase_time(self):
        if self.TIME >= self.DAY_LIMIT_TIME:
            self.TIME = 0
            self.DAY += 1
            if self.DAY >= 30:
                self.DAY = 0
                self.MONTH += 1
                self.SEASON = self.SEASONS[self.MONTH]
                if self.MONTH >= 12:
                    self.MONTH = 0
        else:
            self.TIME += 1

    def penetration_mutation(self,*args):
        for i in range(self.NUMBER_OF_LAYERS):
            self.LAYERS_PENETRATION[i] = self.LAYERS_PENETRATION[i] if np.random.rand() > self.CHANGING_PENETRATION_CHANCE \
                else (self.LAYERS_PENETRATION[i] + np.random.rand()) / 2

    def rain_operation(self):
        if not self.rain.active:
            self.rain.start_rain(self.RAIN_CHANCE + self.SEASON_CHANGING_RAIN_MUTATION[self.SEASON])
        if self.rain.active:
            self.input_water += self.rain.rain()
        if self.IS_WATERING:
            self.input_water += self.VALVE_CAPACITY

    def make_mutation(self):
        self.penetration_mutation()
        self.rain_operation()

    def start_penetration(self):
        # first layer
        if self.input_water > self.LAYERS_SIZE[0]*(1 - self.LAYERS_MOISTURE[0]):
            self.input_water -= self.LAYERS_SIZE[0]*(1 - self.LAYERS_MOISTURE[0])
            self.LAYERS_MOISTURE[0] = 1
        else:
            self.input_water = 0
            self.LAYERS_MOISTURE[0] =(self.LAYERS_SIZE[0]*self.LAYERS_MOISTURE[0] + self.input_water) / self.LAYERS_SIZE[0]
        # other layers
        for i in range(self.NUMBER_OF_LAYERS-1, 0, -1):
            passed_water = self.LAYERS_MOISTURE[i-1]*self.LAYERS_SIZE[i-1]*self.LAYERS_PENETRATION[i-1]
            if passed_water > self.LAYERS_SIZE[i]*(1-self.LAYERS_MOISTURE[i]):
                passed_water = self.LAYERS_SIZE[i]*(1-self.LAYERS_MOISTURE[i])
            self.LAYERS_MOISTURE[i] += passed_water/self.LAYERS_SIZE[i]
            self.LAYERS_MOISTURE[i-1] -= passed_water/self.LAYERS_SIZE[i-1]

    def decorator(func):
        def wrapper(self, *args):
            self.increase_time()
            return func(self, args)
        return wrapper

    @decorator
    def irrigate(self, *args):
        self.make_mutation()
        self.start_penetration()

s = Soil()
t = threading.Thread(target=Soil.irrigation_handler(s))
t.start()


# -*- coding: utf-8 -*-
"""
Created on Sat Dec 19 10:17:32 2020

@author: Medyan
"""

# coding: utf-8

"""
process-data.py is a group of functions which
        deal with sqlite database and
        make some manipulation for text
Author: Medyan AbdelHamid
Date: Dec. 2020
"""
import sqlite3
import numpy as np
import string
import re

emoticons_str = r"""
    (?:
        [:=;] # Eyes
        [oO\-]? # Nose (optional)
        [D\)\]\(\]/\\OpP] # Mouth
    )"""

regex_str = [
    emoticons_str,
    r'<[^>]+>', # HTML tags
    r'(?:@[\w_]+)', # @-mentions
    r"(?:\#+[\w_]+[\w\'_\-]*[\w_]+)", # hash-tags
    r'http[s]?://(?:[a-z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-f][0-9a-f]))+', # URLs

    r'(?:(?:\d+,?)+(?:\.?\d+)?)', # numbers
    r"(?:[a-z][a-z'\-_]+[a-z])", # words with - and '
    r'(?:[\w_]+)', # other words
    r'(?:\S)' # anything else
]

tokens_re = re.compile(r'(' + '|'.join(regex_str) + ')', re.VERBOSE | re.IGNORECASE)
emoticon_re = re.compile(r'^' + emoticons_str + '$', re.VERBOSE | re.IGNORECASE)
db_file = 'C:/Users/ASUS/Documents/Thesis/Code/Python/SoureCode/fdata-2020.db'

def remove_url(text):
    import re
    return re.sub(r'^https?:\/\/.*[\r\n]*', '', text, flags=re.MULTILINE)

def strip_all_entities(text):
    entity_prefixes = ['@','#']
    for separator in  string.punctuation:
        if separator not in entity_prefixes :
            text = text.replace(separator,' ')
    words = []
    for word in text.split():
        word = word.strip()
        if word:
            if word[0] not in entity_prefixes:
                words.append(word)
    return ' '.join(words)

def remove_emoji(text):
    emoji_pattern = re.compile("["
        u"\U0001F600-\U0001F64F"  # emoticons
        u"\U0001F300-\U0001F5FF"  # symbols & pictographs
        u"\U0001F680-\U0001F6FF"  # transport & map symbols
        u"\U0001F1E0-\U0001F1FF"  # flags (iOS)
                           "]+", flags=re.UNICODE)
    return emoji_pattern.sub(r'', text) # no emoji

def preprocess_tweet(text):
    from pyarabic.araby import strip_tashkeel, strip_tatweel, tokenize, is_arabicrange
    text = remove_url(text)
    text = strip_all_entities(text)
    text = strip_tashkeel(text)
    text = strip_tatweel(text)
    tokens = tokenize(text, conditions=is_arabicrange, morphs=strip_tashkeel)
    tokens = [token if emoticon_re.search(token) else token.lower() for token in tokens]
    return ' '.join(tokens)

def reverse_tweet(text):
    # split the string on space
    words = text.split()
    # reverse the words using reversed() function
    words = list(reversed(words))
    # join the words and return
    return ' '.join(words)

def remove_last_word(text):
    return text.rsplit(' ', 1)[0]

def remove_first_word(text):
    return text.split(' ', 1)[1]

def get_test_seq():
    conn = sqlite3.connect(db_file)
    sql = 'SELECT seq FROM SQLITE_SEQUENCE where name=\'TESTS\''
    cur = conn.cursor()
    cur.execute(sql)
    last = cur.fetchone()[0] + 1
    conn.close()
    return last

def add_test_to_database(results, notes):
    conn = sqlite3.connect(db_file)
    sql = "INSERT INTO TESTS (RESULTS, NOTES)  VALUES (?, ?)"
    args = (results, notes,)
    conn.execute(sql, args)
    conn.commit()

def normalize_tweets():
    conn = sqlite3.connect(db_file)
    sql = "SELECT * FROM TRAINSET "
    cur = conn.cursor()
    cur.execute(sql)
    records = cur.fetchall()
    for rec in records:
        # print(rec[0])
        # print(rec[4])
        # print(preprocess_tweet(rec[4]))
        # exit
        sql = "UPDATE TRAINSET SET FULLTEXT = ? WHERE NB = ?"
        args = (preprocess_tweet(rec[4]),rec[0],)
        conn.execute(sql, args)
    conn.commit()

def augment_hate_tweets():
    conn = sqlite3.connect(db_file)
    sql = "SELECT NB, FULLTEXT FROM TRAINSET WHERE ANOMALY = 1 "
    cur = conn.cursor()
    cur.execute(sql)
    records = cur.fetchall()
    for rec in records:
        # print(rec[0])
        # print(rec[4])
        # print(preprocess_tweet(rec[4]))
        # exit
        sql = "INSERT INTO TRAINSET (ANOMALY, FULLTEXT, FULLTEXT) VALUES (1,?,?) "
        rev1 = reverse_tweet(rec[1])
        rev2 = remove_last_word(rec[1])
        rev3 = remove_first_word(rec[1])
        args = (rev1, rev1)
        conn.execute(sql, args)
        args = (rev2, rev2)
        conn.execute(sql, args)
        args = (rev3, rev3)
        conn.execute(sql, args)
    conn.commit()

def get_vec(n_model,dim, token):
    vec = np.zeros(dim)
    if token not in n_model.wv:
        _count = 0
        for w in token.split("_"):
            if w in n_model.wv:
                _count += 1
                vec += n_model.wv[w]
        if _count > 0:
            vec = vec / _count
    else:
        vec = n_model.wv[token]
    return vec

# normalize all tweets
# normalize_tweets()
# augment hate tweets
augment_hate_tweets()


from django.conf.urls import url
import student
import managementview
import teacher

urlpatterns = [

    url(r'^studentlist$', student.studentlist, name='studentlist'),
    url(r'^ajax/studentdata$', student.data, name='getstudentdata'),
    url(r'^ajax/studentselectdata$', student.selectdata, name='getstudentselectdata'),
    url(r'^ajax/teacherselectdata$', teacher.selectdata, name='getteacherselectdata'),
    url(r'^teacherlist', teacher.teacherlist, name='teacherlist'),
    url(r'^ajax/teacherdata$', teacher.data, name='getteacherdata'),
    url(r'^classlist', managementview.classlist, name='classlist'),
    url(r'^ajax/classdata', managementview.classdata, name='getclassdata'),
    url(r'^majorlist', managementview.majorlist, name='majorlist'),
    url(r'^ajax/majordata', managementview.majordata, name='getmajordata'),
    url(r'^departmentlist', managementview.departmentlist, name='departmentlist'),
    url(r'^ajax/departmentdata', managementview.departmentdata, name='getdepartmentdata'),
    url(r'^administrationlist', managementview.administrationlist, name='administrationlist'),
    url(r'^ajax/administrationdata', managementview.administrationdata, name='getadministrationdata'),
    url(r'^classroomlist', managementview.classroomlist, name='classroomlist'),
    url(r'^ajax/classroomdata', managementview.classroomdata, name='getclassroomdata'),
    url(r'^schoolterm$', managementview.schoolterm, name='schoolterm'),
    url(r'^classtime$', managementview.classtime, name='classtime'),

]


from subscriptions.models import Subscription, SubscriptionCategory
from rest_framework import serializers

class SubscriptionSerializer(serializers.ModelSerializer):
    """Subscription serializer."""

    class Meta:
        """Meta class."""

        model = Subscription
        fields = [
            "id",
            "name",
            "slug",
            "price",
            "support_email",
            "support_reply_number",
            "support_postal_code",
            "support_city",
            "correspondence_address",
            "correspondence_postal_code",
            "correspondence_city",
            "support_phone_number",
            "cancellation_number",
            "category",
            "can_generate_letter",
            "can_generate_email",
            "explanation_field",
        ]

class SubscriptionCategorySerializer(serializers.ModelSerializer):
    """Subscription category serializer."""

    class Meta:
        """Meta class."""

        model = SubscriptionCategory
        fields = ["id", "name", "category"]


from config import GOODREADS_DATABASE_NAME
from wsgi.exceptions import NotFoundException
from wsgi.goodreads_api import GoodreadsClient
from wsgi.models import Resume, ReadingList, ResumeSettings

from wsgi import create_app
app = create_app()

shelves_to_pull = {'read-to-share', 'read-to-share-work', 'to-read-work', 'currently-reading-work'}
resume_mapping = {
    'read-to-share': 'finished_reading_general',
    'read-to-share-work': 'finished_reading',
    'to-read-work': 'to_read',
    'currently-reading-work': 'currently_reading'
}

""" goodreads sync.

Handles sync of goodreads book list data from goodreads to a user resume object specified in the
database
"""

def sync_bookshelves_from_goodreads(resume):
    service_link = None
    for sl in resume.service_links_list:
        if sl.name == GOODREADS_DATABASE_NAME:
            service_link = sl
            break

    gr_client = GoodreadsClient(service_link.key,
                                service_link.secret,
                                service_link.oauth_key,
                                service_link.oauth_secret,
                                service_link.user_id)

    shelves = set(gr_client.list_shelves_by_name())
    if len(shelves_to_pull) != len(shelves_to_pull & shelves):
        raise NotFoundException('Error: reading list mismatch ', shelves_to_pull & shelves)

    reading_lists = ReadingList()
    for shelf in shelves_to_pull:
        book_list = [book for book in gr_client.get_books_for_shelf(shelf)]
        setattr(reading_lists, resume_mapping[shelf], book_list)

    resume.reading_list = reading_lists
    resume.save()

if __name__ == '__main__':
    try:
        resume_setting = ResumeSettings.objects.all()[0]
    except IndexError:
        raise NotFoundException('Error: no ResumeSettings model object describing goodreads '
                                'to resume linkage exists.')
    sync_bookshelves_from_goodreads(resume_setting.resume_to_sync)


import pygame
from constants import BALL_RADIUS, SCREEN_HEIGHT, SCREEN_WIDTH, FPS
from support import Support
from math import sin, pi, cos
import numpy as np
import matplotlib.pyplot as plt

def pendulum_func(parameters):
    return np.array([parameters[1], -gravity*sin(parameters[0])/length])

def runge_kutta_step(parameters, step):
    k1 = pendulum_func(parameters)
    intermediate = parameters + step*k1
    k2 = pendulum_func(intermediate)
    return parameters + step*(k1 + k2)/2

length = 1
gravity = 9.8
theta0 = -pi/3
params = np.array([theta0, 0.0])
ceiling = 150
path_radius = 200

pygame.init()
window = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pêndulo Simples")
clock = pygame.time.Clock()
font = pygame.font.SysFont('Arial', 20, True)
support = Support((SCREEN_WIDTH/2, SCREEN_HEIGHT/2 - path_radius),
                  path_radius, path_radius - BALL_RADIUS, 20, params[0])
running = True

time_history = []
angle_history = []
ideal_history = []
iterations = 0

while running:
    clock.tick(FPS)

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

    window.fill((200, 255, 255))

    params = runge_kutta_step(params, 1/FPS)
    x, y = support.ball_position(params[0])
    support.update_line(params[0])
    pygame.draw.circle(window, (0, 0, 0), (int(x), int(y)), BALL_RADIUS, BALL_RADIUS - 1)
    support.draw(window)
    pygame.display.update()

    time_history.append(iterations/FPS)
    ideal_history.append(theta0*cos(np.sqrt(gravity/length)*iterations/FPS))
    angle_history.append(params[0])
    iterations = iterations + 1

plt.figure()
plt.xlabel('Tempo (s)')
plt.ylabel('Ângulo (rad)')
plt.plot(time_history, angle_history, time_history, ideal_history)
plt.title('Histórico do ângulo')
plt.legend(['real', 'aprox'])
plt.savefig('angle_history.jpg')

pygame.quit()


from os import F_OK, access, sep
try:
    from subprocess import PIPE, Popen
except ImportError:
    PIPE, Popen = None, None

# relax module imports.
from lib.compat import SYSTEM
import lib.structure.internal.object
from status import Status; status = Status()

version = "repository commit"
repo_head = None
repo_type = None
repo_url = None

def repo_information():
    """Determine the subversion revision number and URL from svn or git-svn copies of the repository."""

    # The global variables
    global repo_head
    global repo_type
    global repo_url

    # The variables are already set, so do nothing.
    if repo_head != None or repo_type != None or repo_url != None:
        return

    # Python 2.3 and earlier.
    if Popen == None:
        return

    # Command separator.
    symbol = ";"
    if SYSTEM == 'Windows' or SYSTEM == 'Microsoft':
        symbol = "&&"

    # The command to use.
    cmd = None
    if access(status.install_path+sep+'.git'+sep+'svn'+sep+'refs', F_OK):
        cmd = 'cd %s %s git svn info' % (status.install_path, symbol)
        repo_type = 'git-svn'
    elif access(status.install_path+sep+'.git', F_OK):
        cmd = 'cd %s %s git rev-parse HEAD %s git remote -v' % (status.install_path, symbol, symbol)
        repo_type = 'git'
    elif access(status.install_path+sep+'.svn', F_OK):
        cmd = 'svn info %s' % status.install_path
        repo_type = 'svn'

    # Not a repository copy, so do nothing.
    if not cmd:
        return

    # Open the pipe and run the command.
    pipe = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=False)

    # Loop over the output lines.
    lines = pipe.stdout.readlines()
    for i in range(len(lines)):
        # Decode Python 3 byte arrays.
        if hasattr(lines[i], 'decode'):
            lines[i] = lines[i].decode()

        # Git info.
        if repo_type == 'git':
            # Git hash.
            if i == 0:
                repo_head = lines[i].strip()
                continue

            # Remote URL.
            if repo_url:
                repo_url += '\n'
            else:
                repo_url = ''
            remote_info = lines[i].split()
            repo_url += "%s %s" % (remote_info[1], remote_info[2])

        # SVN and git-svn.
        else:
            # Split up the line.
            row = lines[i].split()

            # Store revision as the global variable.
            if len(row) and row[0] == 'Revision:':
                repo_head = str(row[1])

            # Store URL as the global variable.
            if len(row) and row[0] == 'URL:':
                repo_url = str(row[1])

def version_full():
    """Return the full relax version, including all SVN info for repository versions.

    @return:    The relax version string.
    @rtype:     str
    """

    # The relax version.
    ver = version

    # Repository version.
    if ver == 'repository commit':
        # The global variables
        global repo_head
        global repo_type
        global repo_url

        # Change the version string.
        if repo_head != None:
            if repo_type == 'git':
                ver = version + " " + repo_head
            else:
                ver = version + " r" + repo_head
        if repo_url != None:
            ver += " " + repo_url.replace('\n', '; ')

    # Return the version.
    return ver

# Fetch the repository information, if present.
repo_information()

# Set the version in the relax internal structural object.
lib.structure.internal.object.RELAX_VERSION = version_full()


import cv2
import cv
import sklearn
import numpy as np
import os
from Images import Images
from matplotlib import pyplot as plt
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn import metrics
import lasagne
import theano
import theano.tensor as T
theano.config.exception_verbosity='high'
theano.config.traceback.limit=100

path2 = '/home/karna/Karna_Work/Handwriting_Project/Handwriting-Segmentation/testdata2/uppercontour/'

uppercontourimg = Images(path2)
#testimg.applyCanny()
#testimg.invertImages()
#testimg.normalize()
#plt.imshow(testimg.getImage(2),cmap='gray')
#plt.show()
#testimg.createImageFeatures()
uppercontourno = uppercontourimg.cnt

path2 = '/home/karna/Karna_Work/Handwriting_Project/Handwriting-Segmentation/testdata2/lowercontour/'

imglowercont = Images(path2)
#testimg.applyCanny()
#imglowercont.invertImages()
#testimg.normalize()
#plt.imshow(imglowercont.getImage(2),cmap='gray')
#plt.show()
#testimg.createImageFeatures()
lowercontourno = imglowercont.cnt

batchsize = lowercontourno + uppercontourno
#batchsize = uppercontourno
#batchsize = lowercontourno

#CNN Configuration

var_in = T.tensor4('var_in')
var_t = T.imatrix('var_t')
#batchsize = T.scalar('batchsize')
network = lasagne.layers.InputLayer(shape=(batchsize,1,150,150),input_var=var_in)

network1 = lasagne.layers.Conv2DLayer(
        network, num_filters=30, filter_size=(10,10),pad='full',
        nonlinearity=lasagne.nonlinearities.sigmoid,
        W=lasagne.init.GlorotNormal(),b=lasagne.init.Constant(0.))

network = lasagne.layers.Pool2DLayer(network1, pool_size=(2, 2),mode='max')

network = lasagne.layers.Conv2DLayer(network, num_filters=40,pad='full', filter_size=(5,5),nonlinearity=lasagne.nonlinearities.sigmoid,W=lasagne.init.GlorotNormal(),b=lasagne.init.Constant(0.))

network = lasagne.layers.Pool2DLayer(network, pool_size=(2, 2),mode='max')

#network = lasagne.layers.Conv2DLayer(network, num_filters=batchsize*3,pad='same', filter_size=(3,3),nonlinearity=lasagne.nonlinearities.sigmoid,W=lasagne.init.GlorotNormal(),b=lasagne.init.Constant(0.))

#network = lasagne.layers.Pool2DLayer(network, pool_size=(2, 2),mode='max')

network = lasagne.layers.DenseLayer(network,num_units = 2,nonlinearity=lasagne.nonlinearities.softmax,W=lasagne.init.GlorotNormal(), b=lasagne.init.Constant(0.))
#weights = network2.W.get_value()

prediction = lasagne.layers.get_output(network)

loss = lasagne.objectives.squared_error(prediction, var_t).mean()
all_params = lasagne.layers.get_all_params(network, trainable=True)
updates=lasagne.updates.sgd(loss,all_params,0.1)

train = theano.function([var_in, var_t], loss, updates=updates )

#theano.config.optimizer_verbose = 1
#theano.config.compute_test_value = 'warn'
#theano.config.optimizer='fast_compile'

#Training Data preparation

varout=[]
varin=()
#output = np.eye(imglowercont.cnt,batchsize)
#output=output.astype(int)
size=150

for i in range(0,uppercontourno):
    timgi = uppercontourimg.getImage(i)/255.0
    sh = np.shape(timgi[:,:,0])
    dest = np.ones((size,size,1))
    dest[0:sh[0],0:sh[1],:]=timgi[:,:,0,None]
    lst = list(varin)
    lst.append(dest)
    varin=tuple(lst)
    varout.append(tuple([1.0,0.0]))

for i in range(0,lowercontourno):
    timgi = imglowercont.getImage(i)/255.0
    sh = np.shape(timgi[:,:,0])
    dest = np.ones((size,size,1))
    dest[0:sh[0],0:sh[1],:]=timgi[:,:,0,None]
    lst = list(varin)
    lst.append(dest)
    varin=tuple(lst)
    varout.append(tuple([0.0,1.0]))

varin=np.transpose(varin,(0,3,1,2))

#training

maxepoch=10
for epoch in range(maxepoch):
    loss = 0
    loss += train(varin, varout)
    print("Epoch %d: Loss %g" % (epoch + 1, loss))

#test data preparation

path1 = '/home/karna/Karna_Work/Handwriting_Project/Handwriting-Segmentation/data/'
img = Images(path1)
imgcan = img.getImage(0)
sh=np.shape(imgcan)
imgcan[imgcan>180]=255
sh=np.shape(imgcan)

a=imgcan[sh[0]/2+250:sh[0]/2 + 400,sh[1]/2+500:sh[1]/2 + 650]
plt.imshow(a,cmap='gray')
plt.show()

imgcutcan=imgcan[sh[0]/2+250:sh[0]/2 + 400,sh[1]/2+500:sh[1]/2 + 650]/255.0
#imgsh=imgcan[sh[0]/2+250:sh[0]/2 + 400,sh[1]/2+500:sh[1]/2 + 650]

#testing
varin = ()
varout=[]
for i in range(batchsize):
    timgi = imgcutcan[None,95:120,:,0]
    sh = np.shape(timgi[:,:,:])
    dest = np.ones((1,size,size))
    dest[:,0:sh[1],0:sh[2]]=timgi[None,:,:]
    lst = list(varin)
    lst.append(dest)
    varin=tuple(lst)

#Testing
test_prediction = lasagne.layers.get_output(network, deterministic=False)
#predict_fn = theano.function([var_in], T.argmax(test_prediction, axis=1))
predict_fn = theano.function([var_in], test_prediction)
print("Predicted class for first test input: %r" % predict_fn(varin))


import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
from pycompss.api.api import compss_wait_on
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

import dislib as ds
from dislib.classification import CascadeSVM, RandomForestClassifier

def main():
    h = .02  # step size in the mesh

    names = ["Linear C-SVM", "RBF C-SVM", "Random forest"]

    classifiers = [
        CascadeSVM(kernel="linear", c=0.025, max_iter=5),
        CascadeSVM(gamma=2, c=1, max_iter=5),
        RandomForestClassifier(random_state=1)
    ]

    x, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                               random_state=1, n_clusters_per_class=1)
    rng = np.random.RandomState(2)
    x += 2 * rng.uniform(size=x.shape)
    linearly_separable = (x, y)

    datasets = [make_moons(noise=0.3, random_state=0),
                make_circles(noise=0.2, factor=0.5, random_state=1),
                linearly_separable
                ]

    preprocessed_data = dict()
    scores = dict()
    mesh_accuracy_ds = dict()
    for ds_cnt, data in enumerate(datasets):
        # preprocess dataset, split into training and test part
        x, y = data
        x = StandardScaler().fit_transform(x)
        x_train, x_test, y_train, y_test = \
            train_test_split(x, y, test_size=.4, random_state=42)
        ds_x_train = ds.array(x_train, block_size=(20, 2))
        ds_y_train = ds.array(y_train.reshape(-1, 1), block_size=(20, 1))
        ds_x_test = ds.array(x_test, block_size=(20, 2))
        ds_y_test = ds.array(y_test.reshape(-1, 1), block_size=(20, 1))

        x_min, x_max = x[:, 0].min() - .5, x[:, 0].max() + .5
        y_min, y_max = x[:, 1].min() - .5, x[:, 1].max() + .5
        xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                             np.arange(y_min, y_max, h))
        preprocessed_data[ds_cnt] = x, x_train, x_test, y_train, y_test, xx, yy

        for name, clf in zip(names, classifiers):
            clf.fit(ds_x_train, ds_y_train)
            scores[(ds_cnt, name)] = clf.score(ds_x_test, ds_y_test)

            mesh = np.c_[xx.ravel(), yy.ravel()]
            mesh_array = ds.array(mesh, (mesh.shape[0], 2))

            if hasattr(clf, "decision_function"):
                mesh_proba = clf.decision_function(mesh_array)
            else:
                mesh_proba = clf.predict_proba(mesh_array)
            mesh_accuracy_ds[(ds_cnt, name)] = mesh_proba

    # Synchronize while plotting the results
    plt.figure(figsize=(27, 9))
    i = 1
    for ds_cnt, data in enumerate(datasets):
        x, x_train, x_test, y_train, y_test, xx, yy = preprocessed_data[ds_cnt]

        # just plot the dataset first
        cm = plt.cm.RdBu
        cm_bright = ListedColormap(['#FF0000', '#0000FF'])
        ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
        if ds_cnt == 0:
            ax.set_title("Input data")
        # Plot the training points
        ax.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap=cm_bright,
                   edgecolors='k')
        # Plot the testing points
        ax.scatter(x_test[:, 0], x_test[:, 1], c=y_test, cmap=cm_bright,
                   alpha=0.6,
                   edgecolors='k')
        ax.set_xlim(xx.min(), xx.max())
        ax.set_ylim(yy.min(), yy.max())
        ax.set_xticks(())
        ax.set_yticks(())
        i += 1

        # iterate over classifiers
        for name, clf in zip(names, classifiers):
            ax = plt.subplot(len(datasets), len(classifiers) + 1, i)

            score = compss_wait_on(scores[(ds_cnt, name)])
            mesh_proba = mesh_accuracy_ds[(ds_cnt, name)]

            if hasattr(clf, "decision_function"):
                Z = mesh_proba.collect()
            else:
                Z = mesh_proba.collect()[:, 1]

            # Put the result into a color plot
            Z = Z.reshape(xx.shape)
            ax.contourf(xx, yy, Z, cmap=cm, alpha=.8)

            # Plot the training points
            ax.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap=cm_bright,
                       edgecolors='k')
            # Plot the testing points
            ax.scatter(x_test[:, 0], x_test[:, 1], c=y_test, cmap=cm_bright,
                       edgecolors='k', alpha=0.6)

            ax.set_xlim(xx.min(), xx.max())
            ax.set_ylim(yy.min(), yy.max())
            ax.set_xticks(())
            ax.set_yticks(())
            if ds_cnt == 0:
                ax.set_title(name)
            ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'),
                    size=15, horizontalalignment='right')
            i += 1

    plt.tight_layout()
    plt.show()

if __name__ == "__main__":
    main()