import re
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from enum import Enum
from typing import List, Dict, Tuple, Union, TYPE_CHECKING, Optional
from PyAltium365.Connections import JsonConSearchAsync
from PyAltium365.Data.DataConVault import AluItem

if TYPE_CHECKING:
    from PyAltium365.AltiumApi import AltiumApi
else:
    from PyAltium365.Fix import AltiumApi

class SearchType(Enum):
    CONDITIONAL_QUERY = "DtoSearchConditionStrictQuery"
    CONDITIONAL_RANGE_QUERY = "DtoSearchConditionRangeQuery"
    CONDITIONAL_WILDCARD = "DtoSearchConditionWildcardQuery"

class DataType(Enum):
    NO_TYPE = ""
    CAPACITANCE = "0629FA77_2DBB3E_2D4045_2D91F0_2DCC1164D3D0AADD420E8DDD8B445E911A0601BB2B6D53"
    RESISTANCE = "B90F0DAE_2DB695_2D41F5_2DBCB0_2D0DE5F75C9E50DD420E8DDD8B445E911A0601BB2B6D53"
    VOLTAGE = "28379228_2DD94F_2D4F3B_2D8038_2D3FE85C36E292DD420E8DDD8B445E911A0601BB2B6D53"
    TOLERANCE = "935791AE_2D95D8_2D4D5E_2DB810_2DE9B66A56E5A5DD420E8DDD8B445E911A0601BB2B6D53"
    FREQUENCY = "F4CAEC49_2DEE33_2D46C9_2DAF4A_2D260721F7AA26DD420E8DDD8B445E911A0601BB2B6D53"
    DISTANCE = "B0C104C5_2D1A99_2D4DE5_2DA539_2DD5FC817D4B3EDD420E8DDD8B445E911A0601BB2B6D53"
    POWER = "A40E567D_2D1324_2D4823_2D8379_2DFB7E896E18B9DD420E8DDD8B445E911A0601BB2B6D53"

    @classmethod
    def _missing_(cls, value):  # type: ignore
        return DataType.NO_TYPE

@dataclass
class Counter:
    Name: str = ""
    Type: DataType = DataType.NO_TYPE
    Count: int = 0
    Values: Dict[str, int] = field(default_factory=lambda: {})

class CounterRange(Counter):
    Values: Dict[float, int] = field(default_factory=lambda: {})  # type: ignore
    MinValue: float = 0
    MaxValue: float = 0

@dataclass
class Counters:
    TotalCount: int = 0
    Counters: List[Counter] = field(default_factory=lambda: [])

@dataclass
class SearchDataBase:
    altium_api: AltiumApi
    Id: str = ""
    Parameters: Dict[str, Union[str, float]] = field(default_factory=lambda: {})
    HRID: str = ""
    CreatedAt: datetime = datetime(1, 1, 1)
    CreatedBy: str = ""
    ModifiedBy: str = ""
    LatestRevision: bool = False
    Updated: datetime = datetime(1, 1, 1)
    CreatedByGUID: str = ""
    UpdatedByGUID: str = ""
    AppType: str = ""
    Url: str = ""
    SubmitDate: datetime = datetime(1, 1, 1)
    Language: str = ""
    FolderGUID: str = ""
    FolderFullPath: str = ""
    Description: str = ""
    NamingSchemeGuid: str = ""
    Cat: str = ""
    ContentTypeGUID: str = ""
    Text: str = ""
    LifeCycle: str = ""
    ACL: str = ""
    ItemHRID: str = ""
    Comment: str = ""
    LifeCycleStateGUID: str = ""
    ItemGUID: str = ""
    RevisionId: int = -1
    AncestorRevisionGUID: str = ""
    ItemDescription: str = ""
    ReleaseNote: str = ""
    ReleaseDate: datetime = datetime(1, 1, 1)
    ReleaseDateNum: datetime = datetime(1, 1, 1)
    LifeCycleDefinitionGUID: str = ""

    def get_folder(self) -> None:
        raise NotImplementedError()

    def get_created_by(self) -> None:
        raise NotImplementedError()

    def get_updated_by(self) -> None:
        raise NotImplementedError()

    def get_content_type(self) -> None:
        raise NotImplementedError()

    def get_item(self) -> Optional[AluItem]:
        return self.altium_api.get_item_from_guid(self.ItemGUID)

    def get_life_cycle_state(self) -> None:
        raise NotImplementedError()

    def get_life_cycle_definition(self) -> None:
        raise NotImplementedError()

    def get_ancestor_revision(self) -> None:
        raise NotImplementedError()

@dataclass
class SearchDataComponent(SearchDataBase):
    FootprintName: List[str] = field(default_factory=lambda: [])
    FootprintDescription: List[str] = field(default_factory=lambda: [])

@dataclass
class SearchDataFootprint(SearchDataBase):
    pass

@dataclass
class SearchDataSymbol(SearchDataBase):
    pass

@dataclass
class SearchDataDatasheet(SearchDataBase):
    FileName: str = ""
    Caption: str = ""
    FileHash: str = ""
    FileSize: str = ""
    DynamicData: str = ""

@dataclass
class SearchDataProjectTemplate(SearchDataBase):
    MainFilename: str = ""
    Kind: str = ""
    DynamicData: str = ""

@dataclass
class SearchDataSchematicTemplate(SearchDataBase):
    pass

@dataclass
class SearchDataComponentTemplate(SearchDataBase):
    DynamicData: str = ""

@dataclass
class SearchDataScript(SearchDataBase):
    DynamicData: str = ""
    MainFilename: str = ""
    Kind: str = ""

@dataclass
class SearchDataLayerstack(SearchDataBase):
    pass

class SearchDataType(Enum):
    NO_TYPE = ("", SearchDataBase)
    COMPONENT = ("Component", SearchDataComponent)
    FOOTPRINT = ("Footprint", SearchDataFootprint)
    SYMBOL = ("Symbol", SearchDataSymbol)
    DATASHEET = ("Datasheet", SearchDataDatasheet)
    PROJECT_TEMPLATE = ("Project Template", SearchDataProjectTemplate)
    SCHEMATIC_TEMPLATE = ("Schematic Template", SearchDataSchematicTemplate)
    COMPONENT_TEMPLATE = ("Component Template", SearchDataComponentTemplate)
    SCRIPT = ("Script", SearchDataScript)
    LAYERSTACK = ("Layerstack", SearchDataLayerstack)

    @classmethod
    def _missing_(cls, value):  # type: ignore
        return SearchDataType.NO_TYPE

    def get_from_str(self, value: str):  # type: ignore
        for orig in SearchDataType:
            if orig.value[0].lower() == value.lower():
                return orig
        return SearchDataType._missing_(None)

encoding_decoding_naming = {
    "_5F": "_",
    "_20": " ",
    "_28": "(",
    "_29": ")",
    "_2C": ",",
    "_2D": "-",
    "_2E": ".",
    "_2F": "/",
    "_40": "@",
    "_5B": "[",
    "_5D": "]",
    "_5E": "^",
}

not_counted_search_parameters = [
    Counter(Name="LatestRevision"),
    Counter(Name="FolderFullPath")
]

class AsyncSearchObject:
    def __init__(self, searcher: JsonConSearchAsync, altium_api: AltiumApi):  # type: ignore
        self._searcher: JsonConSearchAsync = searcher  # type: ignore
        self._altium_api = altium_api
        self._search_parameters: List[Dict] = []
        self._counters: Counters = Counters()
        self._counters_up_to_date = False
        self._update_search_names_and_counters()

    def add_search_parameter(self, name: str, value: Union[str, List[str]], dtype: DataType = DataType.NO_TYPE, remove_old: bool = False) -> bool:
        self._update_search_names_and_counters()
        if type(value) == str:
            value = [value]
        counter = None
        for c in self._counters.Counters:
            if c.Name == name and c.Type == dtype:
                counter = c
                break
        if counter is None:
            return False
        full_name = self._get_index_name_from_name_and_type(counter.Name, counter.Type)
        for parameter in self._search_parameters:
            if parameter['Field'] == full_name:
                if remove_old:
                    parameter['Field'] = []
                for val in value:
                    if val not in parameter['Value']:
                        parameter['Value'].append(val)
                return True
        self._search_parameters.append({
            'Type': SearchType.CONDITIONAL_QUERY,
            'Field': full_name,
            'Value': value
        })
        self._counters_up_to_date = False
        return True

    def add_search_content_type(self, data_type: Union[SearchDataType, List[SearchDataType]], remove_old: bool = False) -> bool:
        if type(data_type) is not List:
            data_type = [data_type]  # type: ignore
        search_l = []
        for d_type in data_type:
            search_l.append(d_type.value[0])
        return self.add_search_parameter('ContentType', search_l, remove_old=remove_old)

    def add_search_parameter_range(self, name: str, minv: float, maxv: float, dtype: DataType = DataType.NO_TYPE, max_included: bool = True,
                                   min_included: bool = True, remove_old: bool = False) -> bool:
        self._update_search_names_and_counters()
        counter = None
        for c in self._counters.Counters:
            if c.Name == name and c.Type == dtype:
                counter = c
                break
        if counter is None:
            return False
        if remove_old:
            self.remove_search_parameter(name, dtype)
        full_name = self._get_index_name_from_name_and_type(counter.Name, counter.Type)
        for parameter_i in range(len(self._search_parameters)):
            parameter = self._search_parameters[parameter_i]
            if parameter['Field'] == full_name:
                self._search_parameters.pop(parameter_i)
                break

        self._search_parameters.append({
            'Type': SearchType.CONDITIONAL_RANGE_QUERY,
            'Field': full_name,
            'Min': minv,
            'Max': maxv,
            'MinInc': min_included,
            'MaxInc': max_included
        })
        self._counters_up_to_date = False
        return True

    def set_search_wildcard(self, wildcard: Optional[str]) -> bool:
        param = None
        for parameter_i in range(len(self._search_parameters)):
            parameter = self._search_parameters[parameter_i]
            if parameter['Type'] == SearchType.CONDITIONAL_WILDCARD:
                if wildcard is None:
                    self._search_parameters.pop(parameter_i)
                    return True
                param = parameter
        if wildcard is None:
            return True
        if param is None:
            param = {
                'Type': SearchType.CONDITIONAL_WILDCARD,
                'Field': []
            }
            self._search_parameters.append(param)
        param['Value'] = wildcard
        return True

    def remove_search_parameter(self, name: str, dtype: DataType = DataType.NO_TYPE) -> bool:
        counter = None
        for c in self._counters.Counters:
            if c.Name == name and c.Type == dtype:
                counter = c
                break
        if counter is None:
            return False
        full_name = self._get_index_name_from_name_and_type(counter.Name, counter.Type)
        for i in range(len(self._search_parameters)):
            if self._search_parameters[i]['Field'] == full_name:
                self._search_parameters.pop(i)
                return True
        return False

    def get_current_count(self) -> int:
        self._update_search_names_and_counters()
        return self._counters.TotalCount

    def get_all_search_names_and_type(self) -> List[Tuple[str, DataType]]:
        l: List[Tuple[str, DataType]] = []
        for c in self._counters.Counters:
            l.append((c.Name, c.Type))
        return l

    def get_all_search_names(self) -> List[str]:
        l: List[str] = []
        for c in self._counters.Counters:
            l.append(c.Name)
        return l

    def get_all_search_names_and_type_without_unusefull(self) -> List[Tuple[str, DataType]]:
        l: List[Tuple[str, DataType]] = []
        for c in self._counters.Counters:
            if len(c.Values) == 1:
                if c.Values.values()[0] == c.Count:  # type: ignore
                    l.append((c.Name, c.Type))
        return l

    def get_all_search_names_and_type_without_usefull(self) -> List[Tuple[str, DataType]]:
        l: List[Tuple[str, DataType]] = []
        for c in self._counters.Counters:
            if len(c.Values) > 1:
                l.append((c.Name, c.Type))
        return l

    def get_results(self, max_amount: int = 500) -> List[SearchDataBase]:
        if max_amount <= 0 or max_amount > 10000:
            max_amount = 10000
        converting = True
        results: List[SearchDataBase] = []
        while converting:
            raw_results = self._searcher.get_search_interface(self, len(results), min(10000, max_amount - len(results)))  # type: ignore
            if 'Documents' not in raw_results:
                return []
            for item in raw_results['Documents']:
                fields = item['Fields']

                part: SearchDataBase = SearchDataBase(self._altium_api)
                for field1 in fields:
                    raw_name = field1['Name']
                    value = field1['Value']
                    name, _ = self._get_facet_name_and_type(raw_name)
                    if name == 'ContentType':
                        part = SearchDataType.get_from_str(SearchDataType.NO_TYPE, value).value[1](self._altium_api)
                        break

                for field1 in fields:
                    raw_name = field1['Name']
                    value = field1['Value']
                    name, _ = self._get_facet_name_and_type(raw_name)

                    if name == 'ContentType':
                        continue

                    m = re.search(r'\d+$', name)
                    if m is not None:
                        sub_name = name[:-len(m.group())]
                        if hasattr(part, sub_name):
                            if type(getattr(part, sub_name)) == list:
                                li = getattr(part, sub_name)
                                index = int(m.group())
                                while len(li) < index:
                                    li.append("")
                                li[index - 1] = value
                                continue
                    if hasattr(part, name):
                        if type(getattr(part, name)) == datetime:
                            if value.replace('.', '', 1).isdecimal():
                                d = datetime(1899, 12, 31)
                                setattr(part, name, d + timedelta(days=float(value)))
                            else:
                                setattr(part, name, datetime.strptime(value, "%m/%d/%Y %H:%M:%S"))
                        elif type(getattr(part, name)) == int:
                            setattr(part, name, int(value))
                        elif type(getattr(part, name)) == bool:
                            setattr(part, name, int(value) > 0)
                        else:
                            setattr(part, name, value)
                        continue
                    part.Parameters[name] = value

                results.append(part)

            if len(results) == min(max_amount, raw_results['Total']):
                converting = False
        return results

    def _update_search_names_and_counters(self) -> None:
        if not self._counters_up_to_date:
            temp_counters = self._searcher.get_part_counters(self)  # type: ignore
            new_counters = Counters()
            new_counters.Counters.extend(not_counted_search_parameters)
            try:
                new_counters.TotalCount = temp_counters['Total']
                temp_counter = temp_counters['FacetedCounters']
                if type(temp_counter) is not list:
                    temp_counter = [temp_counter]
                for temp_c in temp_counter:
                    if 'SupportRange' in temp_c:
                        n_counter = CounterRange()
                        n_counter.MaxValue = float(temp_c['MaxValue'])
                        n_counter.MinValue = float(temp_c['MinValue'])
                    else:
                        n_counter = Counter()  # type: ignore
                    n_counter.Name, n_counter.Type = self._get_facet_name_and_type(temp_c['FacetName'])
                    if n_counter.Name.endswith('_T@x^'):
                        continue
                    n_counter.Count = temp_c['TotalHitCount']
                    for temp_cv in temp_c['Counters']:
                        if 'SupportRange' in temp_c:
                            val = float(temp_cv['Value'])
                        else:
                            val = temp_cv['Value']
                        n_counter.Values[val] = temp_cv['Count']
                    new_counters.Counters.append(n_counter)
                self._counters = new_counters
                self._counters_up_to_date = True
            except Exception:
                print("Data error")

    def _get_facet_name_and_type(self, indexed_name: str) -> Tuple[str, DataType]:
        m1 = re.match("^(.*)_5F([0-9A-F]{8}_[0-9A-F]{6}_[0-9A-F]{6}_[0-9A-F]{6}_[0-9A-F]{46})$", indexed_name)
        m2 = re.match("^(.*)([0-9A-F]{32})$", indexed_name)
        if m1 is not None:
            name = m1.group(1)
            index = m1.group(2)
        elif m2 is not None:
            name = m2.group(1)
            index = m2.group(2)
        else:
            name = indexed_name
            index = ""
        dtype = DataType(index)
        name = self._decode_naming_chars(name)
        return name, dtype

    def _get_index_name_from_name_and_type(self, name: str, dtype: DataType) -> str:
        if dtype == DataType.NO_TYPE:
            full_name = self._encode_naming_chars(name)
            full_name += "DD420E8DDD8B445E911A0601BB2B6D53"
        else:
            full_name = self._encode_naming_chars(name)
            full_name += "_5F" + dtype.value
        return full_name

    def _decode_naming_chars(self, inp: str) -> str:
        for key, val in encoding_decoding_naming.items():
            inp = inp.replace(key, val)
        return inp

    def _encode_naming_chars(self, inp: str) -> str:
        for key, val in encoding_decoding_naming.items():
            inp = inp.replace(val, key)
        return inp


#!/usr/bin/python
# melvin.alvarado

import time
import threading
import logging

import os

from PIR import PIR
from Stream import Stream
from Config import Config

class MotionAlarm:

	def __init__(self,camera,config,controls=None):
		self.event = threading.Event()
		self.sensor = PIR(pin=config.get('PIN_PIR'))
		self.is_running = True
		# self.stream = Stream(camera)
		self.camera = camera
		self.controls = controls
		self.config = config
		self.Cnt = 1

		espeak_cmd = 'espeak -ves+m2 -f '+Config.FRAMEWORK_PATH+'/alarm_on.txt --stdout | aplay'
		if config.enable('ALARM_ESPEAK'):
			os.system(espeak_cmd)
		self.controls.system('aplay /home/pi/framework/alarm_on.wav')

	def __del__(self):
		logging.info( 'MotionAlarm stopped' )

	def stop(self):
		self.is_running = False
		self.sensor.stop()
		# self.stream.stop()
		del(self.sensor)
		# del(self.stream)
		self.event.set()
		espeak_cmd = 'espeak -ves+m2 -f '+Config.FRAMEWORK_PATH+'/alarm_off.txt --stdout | aplay'
		if self.config.enable('ALARM_ESPEAK'):
			os.system(espeak_cmd)
		self.controls.system('aplay /home/pi/framework/alarm_on.wav')
		self.sleep(5)

	def sleep(self,cnt):
		self.event.wait(cnt)

	def alarm(self):
		# self.stream.capture('/tmp/foto_tmp.jpg')
		self.controls.photo()

		Cmd = 'echo "'+self.config.get('SERVER_NAME')+' Alarma" | mail -a "' + '/var/www/foto.jpg' + '" -s "Raspi Alarma E' + str(self.Cnt) + '" ' + self.config.get('ALARM_EMAILS')
		if self.config.enable('ALARM_SEND_EMAIL'):
			logging.info(Cmd)
			os.system(Cmd)

		self.Cnt = self.Cnt + 1
		logging.info( 'Correo enviado...' )

	def run(self):
		logging.info( 'Alarm starting...' )
		# self.stream.run()
		while self.is_running:
			self.sensor.wait_event()
			self.controls.display('motion detected')
			if(self.is_running):

				# t = threading.Thread(target=self.alarm)
				# t.start()
				self.alarm()

				espeak_cmd = 'espeak -ves+m2 -f '+Config.FRAMEWORK_PATH+'/alarm.txt --stdout | aplay'
				if self.config.enable('ALARM_ESPEAK'):
					os.system(espeak_cmd)

				for x in xrange(10):
					self.controls.system('aplay /home/pi/framework/siren.wav')

				self.sleep(5)
				self.controls.display('motion ready')


import sys
import logging
from azure.storage.queue import QueueService
from settings import CONNECTION_STRING, ACCOUNT_NAME, ACCOUNT_KEY

if len(sys.argv) != 2:
    print("Queue name argument required")
    exit(2)

if CONNECTION_STRING is None and (ACCOUNT_NAME is None and ACCOUNT_KEY is None):
    print("Connection string or account name/key not provided")
    exit(2)

logging.basicConfig(
    format='%(asctime)s [%(levelname)s] %(message)s',
    level=logging.INFO,
    datefmt='%d-%m-%Y %H:%M:%S')

queue_name = sys.argv[1]
poison_queue_name = "%s-poison" % queue_name

if CONNECTION_STRING is not None:
    logging.info("Connecting with connection string `%s`" % CONNECTION_STRING)
    client = QueueService(connection_string=CONNECTION_STRING)
else:
    logging.info("Connecting to account `%s` with key `%s`" % (ACCOUNT_NAME, ACCOUNT_KEY))
    client = QueueService(
        account_name=ACCOUNT_NAME,
        account_key=ACCOUNT_KEY)

logging.info("Queue `%s`" % queue_name)
logging.info("Poison `%s`" % poison_queue_name)

if not client.exists(queue_name):
    logging.info("Queue `%s` does not exist" % queue_name)
    exit(1)

if not client.exists(poison_queue_name):
    logging.info("Poison queue `%s` does not exist" % poison_queue_name)
    exit(1)

logging.info("Both queues exist")

while len(client.peek_messages(poison_queue_name)) > 0:
    messages = client.get_messages(poison_queue_name, 32, 32*2)
    logging.info("Requeuing %s messages" % len(messages))
    for message in messages:
        client.put_message(queue_name, message.content)
        client.delete_message(poison_queue_name, message.id, message.pop_receipt)

logging.info("Poison queue empty")
exit(0)


# Lib
import cv2
import glob
import tqdm
import torch
import numpy as np

def visualize(images, classes, batch_idx=0):
    '''
    batch data visualize
    if you use Linux OS(Docker):
        save image file in docs dir and check
    '''
    img = images[batch_idx].numpy()
    img = (np.transpose(img, (1, 2, 0)) * 255.).astype(np.uint8).copy()
    label = classes[batch_idx].numpy()

    # cv2.imshow('img', img)
    # cv2.waitKey(0)
    cv2.imwrite('/home/torch/Classification/docs/class'+str(label)+'.JPEG', img)

def create_annot(label_info, mode):
    txt_path = os.getcwd() + f'/generator/{mode}.txt'
    for label in tqdm(label_info, desc='Converting txt file'):
        with open(txt_path, 'a') as f:
            info = f'{label} \n'
            f.write(info)

if __name__ == '__main__':
    train_label = [os.basename(file) for file in glob(os.getcwd() + '/imagenet-ini/train/*')]
    val_label = [os.basename(file) for file in glob(os.getcwd() + '/imagenet-mini/val/*')]

    create_annot(train_label, mode='train')
    create_annot(valid_label, mode='val')


import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import FormatStrFormatter, LinearLocator
from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import

from BB import BB_gradient, gradient_method_backtracking, BB_gradient_nonmonotone
from boundary import FuncClass
from newton import globalized_newton, BFGS
from projection import projected_gradient
from problem_wrap import Problem
from net import accelerate_method
from momentum import Momentum_method
from momentum import Nestrov_acc
from compactBFGS import BFGS_DFP
from compactBFGS import L_BFGS
def plot3D(m, n, Z):
    x = np.linspace(0, 1, m)
    y = np.linspace(0, 1, n)
    X, Y = np.meshgrid(x, y)

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False)

'''
Unconstrained method:
    0: basic GD with backtracking
    1: globalized Newton method
    2: BFGS-DFP family
    3: nonmonotone line search procedures
    4: Barzilai-Borwein steps
    5: inertial techniques and momentum
    6: compact representation of the L-BFGS update
    7: Adam
    8: Nestrov's acceleration
Constrained method:
    0: Projected Gradient
'''
METHOD = 6
func_num = 0
FUNC = 'func_class.func{}'.format(func_num)
OPT = [2.0725090145, 2.1410255432128906, 1.2063673734664917, 1.0187329445407338, 3.086641232606508][func_num]
LB = 0 # Whether lower bounded

if __name__ == "__main__":
    # parameters
    m, n = 50, 50
    tol = 1e-5
    s, sigma, gamma = 1, 0.5, 0.1
    beta1 = beta2 = 1e-6
    p = 0.1
    max_iter, lr = 3000, 0.002

    func_class = FuncClass()
    problem = Problem(eval(FUNC), m, n)

    # initial
    # x = np.random.randn((m-2)*(n-2))
    x = np.zeros((m-2)*(n-2))

    # algorithm
    if not LB:
        if METHOD == 0:
            points, objs, grad_norm, times = gradient_method_backtracking(problem.obj, problem.grad, x, tol, s, sigma, gamma)
        elif METHOD == 1:
            points, objs, grad_norm, times = globalized_newton(problem.obj, problem.grad, problem.hess, x,  tol, s, sigma, gamma, beta1, beta2, p)
        elif METHOD == 2:
            points, objs, grad_norm, times = BFGS_DFP(problem.obj, problem.grad, problem.hess, x,  tol, s, sigma, gamma, beta1, beta2, p,lam=1)
        elif METHOD == 3:
            # points, objs, grad_norm, times = BB_gradient_nonmonotone(problem.obj, problem.grad, x,  tol, s, sigma)
            pass
        elif METHOD == 4:
            points, objs, grad_norm, times = BB_gradient(problem.obj, problem.grad, x, tol, s, sigma, gamma)
        elif METHOD == 5:
            points, objs, grad_norm, times = Momentum_method(problem.obj,problem.grad,x,tol,beta=0.2,sigma=0.5)
        elif METHOD == 6:
            points, objs, grad_norm, times = L_BFGS(problem.obj, problem.grad, problem.hess, x,  tol, s, sigma, gamma,m=25)
        elif METHOD == 7:
            points, objs, grad_norm, times = accelerate_method(eval(FUNC), m, n, lr, max_iter, tol)
        elif METHOD == 8:
            points, objs, grad_norm, times = Nestrov_acc(problem.obj, problem.grad, x, tol, alpha=0.1)
    else:
        # Construct the lower bound vector
        lower_bound = -np.ones((m-2, n-2)) * np.inf
        lower_bound[[7, 14, 21, 28, 35], 10:50] = 1.5
        lower_bound = lower_bound.flatten()

        if METHOD == 0:
            # Set \lambda_k value (should be bounded)
            lambda_k = lambda k: 0.5
            points, objs, grad_norm, times = projected_gradient(problem.obj, problem.grad, x, tol, s, sigma, gamma, lambda_k, lower_bound)

    # plot gap
    obj = np.array(objs)
    gap = np.abs(obj-OPT) / max(1, OPT)
    plt.figure()
    plt.plot(gap)
    plt.xlabel('iterations')
    plt.ylabel('gap')
    plt.show()

    plt.figure()
    plt.plot(times, gap)
    plt.xlabel('cpu time (second)')
    plt.ylabel('gap')
    plt.show()

    # plot
    plt.figure()
    plt.plot(grad_norm)
    plt.xlabel('iterations')
    plt.ylabel('grad_norm')
    plt.yscale('log')
    plt.show()

    plt.figure()
    plt.plot(times, grad_norm)
    plt.xlabel('cpu time (second)')
    plt.ylabel('grad_norm')
    plt.yscale('log')
    plt.show()

    # plot
    inputs = np.empty((m, n))
    x = points[-1]
    x = x.reshape(m-2, n-2)
    inputs[1:-1, 1:-1] = x
    problem.model.bound_constrain(inputs)
    plot3D(m, n, inputs.T)
    plt.savefig('../report/{}_method{}.pdf'.format(FUNC, METHOD))
    plt.show()


import sys
import subprocess
import re
import time
import datetime
import select
import logging
import warnings
import struct
import socket
import select
import serial
import json
import bluetooth
import threading
import serial.tools.list_ports

class NotYetImplemented(Exception):
    def __init__(self, value):
        self.value = value

class FormatError(Exception):
    def __init__(self, value):
        self.value = value

class DeviceError(Exception):
    def __init__(self, value):
        self.value = value

class AuthenticationError(Exception):
    def __init__(self, value):
        self.value = value

def get_time():
    # Required for logging
    now = datetime.datetime.today()
    return now.strftime("%d/%m/%Y %H:%M:%S | ")

def serial_scan(address_pattern):
    # Returns a list of com ports connected to arduinos
    matching_ports = []
    ports = serial.tools.list_ports.comports()

    for port in ports:
        if port.description.startswith(address_pattern):
            matching_ports.append(port.device)
    return matching_ports

class BluetoothDevice():
    """
    Device class is a wrapper for a Bluetooth socket. Defining this as a
    class allows us to keep track of sockets when they are passed to
    the select function.

    Most importantly, the class has the method:
        def fileno(self):
            return self.sock.fileno
    This method must not be removed - it means that select sees a Device object
    as a socket.

    This class handles all direct interaction with sockets.
    """
    def __init__(self, name, address):
        self.name = name
        self.subscriptions = set()
        self.address = address
        self.sock = None

    def fileno(self):
        """
        Returns integer file descriptor that is used by the underlying
        implementation to request I/O operations from the operating system

        MUST BE LEFT IN, OR SELECT WILL NOT WORK ON DEVICES
        """
        return self.sock.fileno()

    def disconnect(self):
        """
        Attemps to disconnect from the device. Does not delete the socket.

        Parameters
        ----------
        N/A

        Returns
        -------
        bool
            True if successful
            False otherwise
        """
        try:
            self.sock.close()
            return None

        except Exception as e:
            return e

    def send(self, message):
        """
        Attemps to send a message to the device.

        Uses Format to package the message components

        Parameters
        ----------
        components: list of strings

        Returns
        -------
        bool
            True if successful
            False otherwise
        """
        packet = json.dumps(message)
        try:
            self.sock.send(packet.encode('utf-8'))
            return None

        except Exception as e:
            return e

    def receive(self):
        """
        Attemps to receive a message from the socket.

        Receives data in chunks. Once it has a full packet
        (indicated by Format().find_packets returning a non-empty
        response), it returns the packet.

        If the timout is reached before a message is delivered,
        receive returns an empty list

        Parameters
        ----------
        N/A

        Returns
        -------
        list of lists
            The packets received from the socket.
        """

        data = b""

        while True:
            # Loop terminates at timout or error
            try:
                # Read the data in the buffer
                data += self.sock.recv(4096)
                try:
                    message = json.loads(data)
                except json.JSONDecodeError as e:
                    message = None

                return message, ''

            except Exception as e:
                # When there is no more data to read, we get Bluetooth error
                # In this case, we can wait a little while to see if more data is
                # transmitted
                return None, e

        # Error handling if no packet is received
        if len(data) > 0:
            return None, FormatError("Listen timeout: data received but incorrectly packaged. " +
                        "data: " + data.decode(errors="ignore"))
        else:
            return None, DeviceError("Listen timeout: no data transmitted!")

        return []

    def connect(self, timeout):
        """
        Attemps to connect to the bluetooth device with the address
        contained in self.address.

        This method is defined separately from init to allow for greater
        flexibility (e.g. keeping information about devices that we are
        not currently connected to.)

        Parameters
        ----------
        N/A

        Returns
        -------
        bool
            True if successful
            False otherwise
        """

        try:
            sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
            # The line below will not work on a Windows system because of the limitations
            # of Bluez - unable to set socket options.
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            #sock.settimeout(5)
            sock.connect((self.address, 1))

            self.sock = sock
            return None

        except Exception as e:
            # Setting a timeout causes an error to be thrown even if the connection
            # is made. In this case, ignore the error and carry on.
            if str(e) == "(77, 'File descriptor in bad state')":
                self.sock = sock
                return None
            else:
                return e

    def still_connected(self):
        """
        Checks if the device is still actually available
        (e.g. if it has powered down or moved out of range it won't be,
        but communications will fail).

        Tests availability using the getpeername method, which returns an
        error if the device is not longer available

        Parameters
        ----------
        N/A

        Returns
        -------
        bool
            True if connected
            False otherwise
        """
        try:
            self.sock.getpeername()
            return True
        except bluetooth.BluetoothError as e:
            # Rather than returning this error, we just use it to test
            # whether the socket still links to an endpoint
            return False

class SerialDevice():
    def __init__(self, comport):
        self.name = None
        self.subscriptions = set()
        self.comport = comport
        self.ser = None

    def connect(self, timeout=0):
        # Attempt to open a serial connection to the device
        try:
            self.ser = serial.Serial(self.comport, 9600, timeout=timeout)
            return None
        except Exception as e:
            return e

    def handshake(self, my_key, their_key):
        # Ask the device to authenticate
        message = {
            'source': 'sink',
            'type': 'handshake',
            'payload': my_key
        }
        flag = self.send(message)
        if flag:
            return flag

        # Wait until the device returns a response
        while True:
            # Check if the device has data waiting to be read
            if self.ser.in_waiting:
                # Receive a single message
                response = self.receive()

                if response['type'] == 'handshake':
                    if response['payload'] == their_key:
                        self.name = response['source']
                        return None
                    else:
                        return AuthenticationError("Wrong password")
                else:
                    return AuthenticationError("Incorrect response to handshake: " + response['type'])
            break

    def receive(self):
        """
        Receives a single message
        """
        data = ''
        while True:
            data += self.ser.readline().decode(errors='ignore').strip()
            # Note: this program cannot cope with internal '{}' brackets inside the json, so be sure not
            # to use them in the plaintext when composing a message!
            potential_messages = re.findall('\{[^\{\}]+\}', data)
            for potential_message in potential_messages:
                try:
                    message = json.loads(potential_message)
                    # json loads is a bit of a blunt instrument. It will interpret "hi" as a
                    # jsonic object!
                    if type(message) == dict:
                        return message

                except Exception as e:
                    pass

    def send(self, message):
        packet = json.dumps(message).encode('ascii')
        try:
            self.ser.write(packet)
            return None
        except Exception as e:
            return e

class Server():
    def __init__(self):
        self.devices = []

    def relay_local_packet(self, packet, device):
        # If a packet is destined for one of the switch's own dependent devices, forward
        # it to that device

        # Is this redundant? Is functionality already handled bu Device class?
        flag = device.send(packet)
        if flag is None:
            print('Packet sucessfully sent')
        else:
            raise flag

    def __prune_devices(self):
        # Remove devices that are no longer available
        # Devices that we are connected to do not show up in scans.
        # Therefore, we want to go through the list of connected devices and
        # prune any which have left.

        # Later, we may want to keep a list of previously connected devices

        current_devices = []
        for device in self.devices:
            if device.still_connected:
                current_devices.append(device)
            else:
                # Close up shop...
                device.disconnect()
        self.devices = current_devices

    def shutdown(self):
        # Terminate threads and gracefully close all connections
        for dev in self.devices:
            dev.disconnect()

class BTServer(Server):
    # Connects to any available BT devices matching its address pattern
    # Relays packets between nodes in local network

    def __init__(self, address_pattern, scan_duration=5):
        """
        Initialise a hub

        Parameters
        ----------
        address_pattern: string

        scan_duration: positive int
            (default = 5)
            If the scan duration is not a positive int, the scanner will hang!

        Returns
        -------
        N/A
        """
        Server.__init__(self, name)
        self.address_pattern = address_pattern

        # Error handling for scan duration
        # If not an integer, attempt to integerise it. If not positive
        # or equal to zero, leave the scan duration as default.
        if type(scan_duration) != int:
            try:
                scan_duration = int(scan_duration)
                if scan_duration > 0:
                    self.scan_duration = scan_duration
            except:
                self.scan_duration = 5
                #LOGGING
                pass
        else:
            if scan_duration > 0:
                self.scan_duration = scan_duration

    def __get_own_address(self):
        """
        Checks local device (device id = 0) and returns the bluetooth
        address.

        Parameters
        ----------
        None

        Returns
        -------
        string
            Bluetooth address in the form:
            '88:53:2E:86:BE:8C'

        """
        mac = ''
        if sys.platform.startswith("win"):
            interfaces = subprocess.check_output(["getmac", "/V"]).decode().split("\n")
            for interface in interfaces:
                if interface.startswith("Bluetooth"):
                    macs = re.findall("[A-Z0-9]{2}" + "-[A-Z0-9]{2}"*5, interface)
                    if len(macs) > 0:
                        mac = macs[0].replace('-', ':')

        elif sys.platform.startswith("linux"):
            interfaces = subprocess.check_output(["hcitool", "dev"]).decode().split("\n")
            for interface in interfaces:
                if interface.strip().startswith("hci"):
                    mac = re.findall("[A-Z0-9]{2}" + ":[A-Z0-9]{2}"*5, interface)[0]
        #mac = ':'.join(("%012X" % uuid.getnode())[i:i+2] for i in range(0, 12, 2))
        return mac.encode('ascii', 'ignore')

    def __scan(self):
        # As in Hub. Should be scanning in background and spawn new process if
        # an unknown device with the correct address pattern is found
        """
        Search for nearby Bluetooth devices whose friendly names match the
        chosen address pattern.

        Parameters
        ----------
        N/A

        Returns
        -------
        list of Devices
            List of MAC addresses of matching devices
        """
        matching_devices = []
        nearby_devices = bluetooth.discover_devices(flush_cache=True, duration=self.scan_duration)
        for device in nearby_devices:
            name = bluetooth.lookup_name(device)
            address = str(device)
            if name != None:
                if name.startswith(self.address_pattern):
                    matching_devices.append(BluetoothDevice(name, address))
        return matching_devices

    def update_devices(self):
        # This function will need to be run in a thread
        # Continually scans for devices using __scan
        # Updates our list of devices

        # Remove devices that are no longer active

        print("Removing unavailable devices")
        self.__prune_devices()

        # Scan for new devices
        print("Scanning")
        new_devices = self.__scan()

        print("Discovered " + str(len(new_devices)) + " new devices")
        # Add new devices:
        for dev in new_devices:
            # Attempt to connect
            print("Attempting to connect to device " + dev.address)
            flag = dev.connect(timeout=5)

            if flag is None:
                self.devices.append(dev)
                print("Successfully connected!")
            else:
                # For now, we report all errors as we find them. Later they
                # will just be logged.
                print(flag)

class Coordinator():
    # Maintains a routing table
    # Waits to be connected to via TCP (does not scan)
    # Routes traffic to distant nodes
    # Coordinator must always be listening and must accept all connections
    # (ignore authentication for now
    def __init__(self):
        self.routing_table = {}
        # Later, when we implement authentication, Coordinator will compile
        # a list of Swich devices' public keys
        #self.device_public_keys = {}
        raise NotYetImplemented()
    def __update_routing_table(self, message_source, message_sender):
        self.routing_table[message_source] = message_sender
    def loop(self, logging=True):
        raise NotYetImplemented()

if __name__ == "__main__":
    pass


import numpy as np
import pytest

from pandas import DataFrame, Index, Series
import pandas._testing as tm

def test_slice_float64():
    values = np.arange(10.0, 50.0, 2)
    index = Index(values)

    start, end = values[[5, 15]]

    s = Series(np.random.randn(20), index=index)

    result = s[start:end]
    expected = s.iloc[5:16]
    tm.assert_series_equal(result, expected)

    result = s.loc[start:end]
    tm.assert_series_equal(result, expected)

    df = DataFrame(np.random.randn(20, 3), index=index)

    result = df[start:end]
    expected = df.iloc[5:16]
    tm.assert_frame_equal(result, expected)

    result = df.loc[start:end]
    tm.assert_frame_equal(result, expected)

def test_getitem_negative_out_of_bounds():
    s = Series(tm.rands_array(5, 10), index=tm.rands_array(10, 10))

    msg = "index -11 is out of bounds for axis 0 with size 10"
    with pytest.raises(IndexError, match=msg):
        s[-11]
    with pytest.raises(IndexError, match=msg):
        s[-11] = "foo"

def test_getitem_setitem_slice_bug():
    s = Series(range(10), index=list(range(10)))
    result = s[-12:]
    tm.assert_series_equal(result, s)

    result = s[-7:]
    tm.assert_series_equal(result, s[3:])

    result = s[:-12]
    tm.assert_series_equal(result, s[:0])

    s = Series(range(10), index=list(range(10)))
    s[-12:] = 0
    assert (s == 0).all()

    s[:-12] = 5
    assert (s == 0).all()

def test_getitem_setitem_slice_integers():
    s = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16])

    result = s[:4]
    expected = s.reindex([2, 4, 6, 8])
    tm.assert_series_equal(result, expected)

    s[:4] = 0
    assert (s[:4] == 0).all()
    assert not (s[4:] == 0).any()

def test_slice_float_get_set(datetime_series):
    msg = (
        "cannot do slice indexing on DatetimeIndex with these indexers "
        r"\[{key}\] of type float"
    )
    with pytest.raises(TypeError, match=msg.format(key=r"4\.0")):
        datetime_series[4.0:10.0]

    with pytest.raises(TypeError, match=msg.format(key=r"4\.0")):
        datetime_series[4.0:10.0] = 0

    with pytest.raises(TypeError, match=msg.format(key=r"4\.5")):
        datetime_series[4.5:10.0]
    with pytest.raises(TypeError, match=msg.format(key=r"4\.5")):
        datetime_series[4.5:10.0] = 0


import pandas as pd
from keras.models import load_model

# Load the model
model = load_model('trained_model2.h5')

# Read the new products
X = pd.read_csv('../data/proposed_new_product.csv')

# Prediction
prediction = model.predict(X)
prediction = (prediction + 0.153415)/0.0000042367
print(prediction)


from django.urls import include, path
from django.views.generic import TemplateView
from rest_framework import routers
from rest_framework.schemas import get_schema_view
from . import views

router = routers.DefaultRouter()
router.register(r'apprenants', views.ApprViewSet)
router.register(r'briefs', views.BriefViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('briefs/gen_groups/<int:pk>', views.GenGoupsView.as_view(), name="gen_groups"),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    path('openapi', get_schema_view(
        title="Your Project",
        description="API for all things …",
        version="1.0.0"
    ), name='openapi-schema'),
    path('swagger-ui/', TemplateView.as_view(
        template_name='swagger_ui.html',
        extra_context={'schema_url':'openapi-schema'}
    ), name='swagger-ui'),
]


# -*- coding: utf-8 -*-
from transformers import AutoModel
import torch
from torch.utils.data import Dataset
from transformers import AutoTokenizer
import sys, os, re, csv, codecs, numpy as np
import json
from nltk.corpus import stopwords
from nltk.stem import SnowballStemmer
from sklearn import preprocessing
import time
TRAIN_DATA_LABEL='train.label.txt'
TRAIN_DATA_FILE='train_tweets.json'
DEV_DATA_LABEL='dev.label.txt'
DEV_DATA_FILE='dev_tweets.json'
TEST_DATA_LABEL='test.label.txt'
TEST_DATA_FILE='test_tweets.json'

# read local file
def read_file(url):
    f = open(url, "r", encoding='utf-8')
    file = f.readlines()
    f.close()
    return file
#Turn the original data into the data and label arrays required for training
def read_data(x_url, y_url, isTest = False):
    if isTest:
        x_final = []
        with open(x_url, "r") as json_file:
            json_dict = json.load(json_file)
            for i in range(len(json_dict)):
                str = []
                for j in range(len(json_dict[i])):
                    str.append(json_dict[i][j]["text"])
                x_final.append(str)
        json_file.close()
        return x_final
    x_final = []
    y_final = []
    file = read_file(y_url)
    tmp_y = []
    for line in file:
        line = line.strip("\n").split(",")
        tmp_y.append(line)
    print(len(tmp_y))
    with open(x_url, "r") as json_file:
        json_dict = json.load(json_file)
        for i in range(len(json_dict)):
            str = []
            for j in range(len(json_dict[i])):
                str.append(json_dict[i][j]["text"])
            if len(json_dict[i]) > 0 and json_dict[i][0]["text"] != "":
                x_final.append(str)
                y_final.append(tmp_y[i])
        json_file.close()
    label_encoder = preprocessing.LabelEncoder()
    y_final = label_encoder.fit_transform(y_final)
    return x_final, y_final

#the class of read dataset
class SSTDataset(Dataset):

    def __init__(self, dataUrl, labelUrl, maxlen):
        # read data
        self.sentences, self.labels = read_data(dataUrl, labelUrl)
        # make tokenizer
        self.tokenizer = AutoTokenizer.from_pretrained('digitalepidemiologylab/covid-twitter-bert')
        # longest input length
        self.maxlen = maxlen

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

    def __getitem__(self, index):
        #Preprocessing the text to be suitable for BERT
        sentences = self.sentences[index]
        label = self.labels[index]
        cnt = 0
        source_tweet = ""
        comment_tweets =  ""
        for sentence in sentences:
            if cnt == 0:
                cnt = 1
                source_tweet = sentence
            else:
                comment_tweets += (sentence + " ")
        tokens = self.tokenizer(source_tweet,
                                comment_tweets,
                                padding='max_length',
                                truncation=True,
                                max_length=self.maxlen) #Tokenize the sentence
        tokens_ids_tensor = torch.tensor(tokens['input_ids']) #Converting the list to a pytorch tensor

        #Obtaining the attention mask i.e a tensor containing 1s for no padded tokens and 0s for padded ones
        attn_mask = torch.tensor(tokens['attention_mask'])

        segments_ids = torch.tensor(tokens['token_type_ids'])

        return tokens_ids_tensor, attn_mask, segments_ids ,label

from torch.utils.data import DataLoader
import torch
import torch.nn as nn
from transformers import AutoModel
import torch.optim as optim
# torch.backends.cudnn.enable = False
# torch.backends.cudnn.benchmark = False
class SentimentClassifier(nn.Module):

    def __init__(self):
        super(SentimentClassifier, self).__init__()
        #Instantiating BERT model object
        self.bert_layer = AutoModel.from_pretrained('digitalepidemiologylab/covid-twitter-bert')
        hidden_size = self.bert_layer.config.hidden_size
        print(hidden_size)
         #Classification layer
        self.cls_layer = nn.Linear(hidden_size, 1)
    def forward(self, seq, attn_masks, segments_ids):

        #Feeding the input to BERT model to obtain contextualized representations
        outputs = self.bert_layer(seq, attention_mask = attn_masks,  token_type_ids = segments_ids)
        hidden_size = self.bert_layer.config.hidden_size
        cont_reps = outputs.last_hidden_state
        #Obtaining the representation of [CLS] head (the first token)
        cls_rep = cont_reps[:, 0]
        #Feeding cls_rep to the classifier layer
        logits = self.cls_layer(cls_rep)
        return logits

import time
import csv

def train(net, criterion, opti, train_loader, dev_loader, test_set, max_eps, device):

    best_acc = 0
    st = time.time()
    y_pred = []
    for ep in range(max_eps):

        net.train()
        for it, (seq, attn_masks, segments_ids, labels) in enumerate(train_loader):
            #Clear gradients
            opti.zero_grad()
            #Converting these to cuda tensors
            seq, attn_masks, segments_ids, labels = seq.to(device), attn_masks.to(device),segments_ids.to(device), labels.to(device)

            #Obtaining the logits from the model
            logits = net(seq, attn_masks, segments_ids)
            #logits = net(seq, attn_masks)
            #Computing loss
            loss = criterion(logits.squeeze(-1), labels.float())

            #Backpropagating the gradients
            loss.backward()
            #print(it)

            #Optimization step
            opti.step()

            if it % 100 == 0:
                dev_acc, dev_loss = evaluate(net, criterion, dev_loader, device)
                print("Iteration {} of epoch {} complete. Loss: {}; Accuracy: {}; Time taken (s): {}".format(it, ep, dev_loss, dev_acc, (time.time()-st)))

        dev_acc, dev_loss = evaluate(net, criterion, dev_loader, device)
        print("Epoch {} complete! Development Accuracy: {}; Development Loss: {}".format(ep, dev_acc, dev_loss))
        if dev_acc >= best_acc:
            print("Best development accuracy improved from {} to {}, saving model...".format(best_acc, dev_acc))
            best_acc = dev_acc
            y_pred = predict_rumour(net, test_set, device)
            torch.save(net.state_dict(), 'sstcls_{}.dat'.format(ep))
        st = time.time()

    #get test label
    headers = ['Id','Predicted']
    rows = []
    cnt = 0;
    for line in y_pred:
        rows.append([cnt, line]);
        cnt += 1

    with open('test.csv','w')as f:
        f_csv = csv.writer(f)
        f_csv.writerow(headers)
        f_csv.writerows(rows)

def get_accuracy_from_logits(logits, labels):
    probs = torch.sigmoid(logits.unsqueeze(-1))
    soft_probs = (probs > 0.5).long()
    acc = (soft_probs.squeeze() == labels).float().mean()
    return acc

def evaluate(net, criterion, dataloader, device):
    net.eval()
    mean_acc, mean_loss = 0, 0
    count = 0
    with torch.no_grad():
        for seq, attn_masks, segments_ids, labels in dataloader:
            seq, attn_masks, segments_ids, labels = seq.to(device), attn_masks.to(device),segments_ids.to(device), labels.to(device)

            #Obtaining the logits from the model
            logits = net(seq, attn_masks, segments_ids)
            mean_loss += criterion(logits.squeeze(-1), labels.float()).item()
            mean_acc += get_accuracy_from_logits(logits, labels)
            count += 1

    return mean_acc / count, mean_loss / count

######################################
#read test dataset
class SSTDatasetTEST(Dataset):

    def __init__(self, dataUrl, maxlen):
        # read data
        self.sentences = read_data(dataUrl, "", isTest = True)
        # make tokenizer
        self.tokenizer = AutoTokenizer.from_pretrained('digitalepidemiologylab/covid-twitter-bert')
        # longset input length
        self.maxlen = maxlen

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

    def __getitem__(self, index):
        #Selecting the sentence and label at the specified index in the data frame
        sentences = self.sentences[index]
        #Preprocessing the text to be suitable for BERT
        cnt = 0
        source_tweet = ""
        comment_tweets =  ""
        for sentence in sentences:
            if cnt == 0:
                cnt = 1
                source_tweet = sentence
            else:
                comment_tweets += (sentence + " ")
        tokens = self.tokenizer(source_tweet,
                                comment_tweets,
                                padding='max_length',
                                truncation=True,
                                max_length=self.maxlen) #Tokenize the sentence
        tokens_ids_tensor = torch.tensor(tokens['input_ids']) #Converting the list to a pytorch tensor

        #Obtaining the attention mask i.e a tensor containing 1s for no padded tokens and 0s for padded ones
        attn_mask = torch.tensor(tokens['attention_mask'])

        segments_ids = torch.tensor(tokens['token_type_ids'])

        return tokens_ids_tensor, attn_mask, segments_ids

def predict_rumour(net, test_set, device):

    net = net.eval()
    test_loader = DataLoader(test_set)

    predictions_lst = []
    with torch.no_grad():
        for seq, attn_masks, segments_ids in test_loader:
            seq, attn_masks, segments_ids = seq.to(device), attn_masks.to(device),segments_ids.to(device)
            logits = net(seq, attn_masks, segments_ids)
            probs = torch.sigmoid(logits)
            soft_prob = (probs > 0.5).long()
            if soft_prob.squeeze().item() == 0:
                predictions_lst.append(0)
            else:
                predictions_lst.append(1)
    return predictions_lst

if __name__ == '__main__':
    max_len = 10
    batch_size = 8
    num_epoch = 5
    #read local dataset
    test_set = SSTDatasetTEST(dataUrl = TEST_DATA_FILE,  maxlen = max_len)
    train_set = SSTDataset(dataUrl = TRAIN_DATA_FILE, labelUrl = TRAIN_DATA_LABEL, maxlen = max_len)
    dev_set = SSTDataset(dataUrl = DEV_DATA_FILE, labelUrl = DEV_DATA_LABEL,  maxlen = max_len)
    #Creating intsances of training and development dataloaders
    train_loader = DataLoader(train_set, batch_size = batch_size, num_workers = 2)
    dev_loader = DataLoader(dev_set, batch_size = batch_size, num_workers = 2)
    print("Done preprocessing training and development data.")

    print("Creating the sentiment classifier, initialised with pretrained BERT-BASE parameters...")
    # init network
    net = SentimentClassifier()
    # load decive
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    net = net.to(device)

    print("Done creating the sentiment classifier.")

    criterion = nn.BCEWithLogitsLoss()
    # Set training parameters
    opti = optim.Adam(net.parameters(), lr = 1e-5,betas=(0.9, 0.999), weight_decay=0.01)
    #warmup_scheduler = warmup.UntunedLinearWarmup(optimizer)

    train(net, criterion, opti, train_loader, dev_loader, test_set, num_epoch, device)


import torch
import torchvision.transforms as transforms
from PIL import Image
import time
import shutil
import cv2

start = time.time()
trans = transforms.ToTensor()
transGray = transforms.Grayscale()
images = []
labels = []
exs = 1536
for num in range(512):
    num += 1

    #shutil.copy("D:HTR(D)/512_tensor_ready_img/1/base" + str(num+exs) + ".png",  "D:HTR(D)/512_tensor_ready_version_2/1/base" + str(num+exs) + ".png")
    #image_cv = cv2.imread("D:HTR(D)/512_tensor_ready_img/1/base" + str(num+exs) + ".png")

    image = Image.open("C:/HTR(D)/512_tensor_ready_img/4/base" + str(num+exs) + ".png")

    #cv2.imshow("im", image_cv)
    #k = cv2.waitKey()

    #image = cv2.resize(image, (1025, 256))
    #cv2.imwrite("D:HTR(D)/512_tensor_ready_version_2/1.1/base" + str(num+exs) + ".png", image)

    #image = Image.open("D:HTR(D)/512_tensor_ready_img/1/base" + str(num+exs) + ".png")

    image = transGray(image)
    image = trans(image)

    #image.show()

    #print("base" + str(num+exs))
    images.append(image)

torch.save(images, "C:/HTR(D)/tensors/images_4.pt")
print(time.time() - start)


from get_team_stats import get_team_stats
from correct_name import correct_name
import json

def build_dict():
	with open('data/teams.json', 'r') as file:
		teams = json.load(file)
	for conf in teams:
		for t in teams[conf]:
			n = correct_name(teams[conf][t]['team'])
			if n != '':
				j = get_team_stats(n)
				j[n]['seed'] = teams[conf][t]['seed']
				with open(f'teams/{n}.json', 'w+', encoding='utf8') as file:
					file.write(json.dumps(j, ensure_ascii=False, indent =4))


# align all ckpts A, B, C... in ckpt_dir to a ckpt X
# compose permutations A -> X -> B and so forth
# compare error barrier of composition (vs A -> B)
from copy import deepcopy
import argparse
from itertools import permutations
from pathlib import Path
import torch
import numpy as np

from nnperm.align import WeightAlignment
from nnperm.error import get_barrier_stats
from nnperm.perm import PermutationSpec
from nnperm.utils import get_open_lth_ckpt, get_open_lth_data, device

## Setup
parser = argparse.ArgumentParser()
parser.add_argument('--ckpt_dir', required=True, type=Path)
parser.add_argument('--ckpt_pattern', required=True, type=str)
parser.add_argument('--save_file', required=True, type=Path)
parser.add_argument('--kernel', default="linear", type=str)
parser.add_argument('--barrier_resolution', default=25, type=int)
parser.add_argument('--n_train', default=10000, type=int)
parser.add_argument('--n_test', default=10000, type=int)
parser.add_argument('--n_paths', default=20, type=int)
parser.add_argument('--max_path_length', default=5, type=int)
parser.add_argument('--seed', default=42, type=int)
args = parser.parse_args()

ckpts = list(Path(args.ckpt_dir).glob(args.ckpt_pattern))

(model_hparams, dataset_hparams), model, params = get_open_lth_ckpt(ckpts[0])
if "resnet" in model_hparams.model_name:
    perm_spec = PermutationSpec.from_residual_model(params)
else:
    perm_spec = PermutationSpec.from_sequential_model(params)
train_dataloader, test_dataloader = get_open_lth_data(dataset_hparams, args.n_train, args.n_test)

def align(x, y):
    align_obj = WeightAlignment(
                perm_spec,
                kernel=args.kernel,
                init_perm=None,
                max_iter=100,
                seed=args.seed,
                order="random",
                verbose=False)
    p, _ = align_obj.fit(x, y)
    p = deepcopy(p)
    del align_obj
    return p

# 1. get pairwise permutations: rows=from, cols=to
perms = [[None] * len(ckpts) for _ in range(len(ckpts))]
for a, b in zip(*np.triu_indices(len(ckpts), 1)):
    print(f"Aligning {ckpts[a]}, {ckpts[b]}")
    _, _, params_a = get_open_lth_ckpt(ckpts[a])
    _, _, params_b = get_open_lth_ckpt(ckpts[b])
    perms[a][b] = align(params_b, params_a)
    perms[b][a] = align(params_a, params_b)

def barrier(a, b, is_train=False):
    return get_barrier_stats(model, train_dataloader if is_train else test_dataloader,
        a, b, resolution=args.barrier_resolution, reduction="mean", device=device())

# 2. get fixed points, error barriers for $k$-length paths composed of permutations
all_stats = []
for n in range(2, args.max_path_length + 1):  # need at least 2 to form a pair
    paths = list(permutations(range(len(ckpts)), n))
    # randomly choose args.n_paths
    paths = [paths[i] for i in np.random.permutation(len(paths))[:args.n_paths]]
    for path in paths:
        print(f"Barriers for path {path}")
        perm = perm_spec.get_identity_permutation(params)
        # 3. Apply composition of path permutation to the replicate
        for i, j in zip(path[:-1], path[1:]):
            perm = perm.compose(perms[i][j])
        _, _, params_a = get_open_lth_ckpt(ckpts[path[0]])
        _, _, params_b = get_open_lth_ckpt(ckpts[path[-1]])
        permuted_a = perm_spec.apply_permutation(params_a, perm)
        cycle_perm = perm.compose(perms[path[-1]][path[0]])
        cycle_a = perm_spec.apply_permutation(params_a, cycle_perm)
        stats = {
            "path": path,
            "path_train": barrier(params_b, permuted_a, True),
            "path_test": barrier(params_b, permuted_a, False),
            "cycle_train": barrier(params_a, cycle_a, True),
            "cycle_test": barrier(params_a, cycle_a, False),
            "fixed_points": cycle_perm.fixed_points(),
        }
        all_stats.append(stats)

args.save_file.parent.mkdir(parents=True, exist_ok=True)
torch.save({"ckpts": ckpts, "stats": all_stats}, args.save_file)
print(f"Saved to {args.save_file}")


"""User activity stats"""

import sqlite3, os
from functools import partial

from logs.log import db_logger
from .date_func import todays_date
from .tablenames import users_statistics_tablename, db_name

def create_userstats_table(tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name):
    """Creates user statistics table, if it doesn't exists.

    Args:
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()
    # Create table
    db_cursor.execute(f'''CREATE TABLE IF NOT EXISTS {tablename}
                      (user_id INT PRIMARY KEY,
                      first_usage DATE,
                      last_usage DATE,
                      commands_use INT DEFAULT 0,
                      stickers_send_to INT DEFAULT 0,
                      other_messages INT DEFAULT 0);''')
    # Save changes
    db_connection.commit()
    # Close the connection
    db_connection.close()

    db_logger.info(f'USERS DB. Table {tablename} is setup')

def add_user_on_start(user_id: int, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name):
    """Adds a row of user to table and sets both first and last usages to today's date.

    Args:
        user_id (int): user ID from TG.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()
    # Add a record
    db_cursor.execute(f'''INSERT INTO {tablename} (user_id, first_usage, last_usage)
                      VALUES ({user_id}, "{todays_date()}", "{todays_date()}")''')
    db_connection.commit()
    # Close connection
    db_connection.close()

    db_logger.info(f'USERS DB. User creation')

def user_exists(user_id: int, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> bool:
    """Checks if user exists in the table (if there is the same ID).

    Args:
        user_id (int): user TG ID.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.

    Returns:
        bool: True, if exists.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()
    # Add a record
    result = db_cursor.execute(f'''SELECT * FROM {tablename} WHERE user_id={user_id}''').fetchall()
    # Close connection
    db_connection.close()
    # Generate result
    if len(result) == 1:
        return True
    elif len(result) == 0:
        return False
    else:
        db_logger.error(f'More than one user with the ID of {user_id} in DB found')
        return True

def update_user_record(user_id: int, column_name: str, new_value: int | str, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> None:
    """Changes user record data in db.

    Args:
        user_id (int): user TG ID.
        column_name (str): name of the column to change.
        new_value (int | str): new value to write.
        tablename (str, optional): name or the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()

    # Update the data
    if type(new_value) == str:
        new_value = f'"{new_value}"'
    db_cursor.execute(f'''UPDATE {tablename} SET {column_name}={new_value} WHERE user_id={user_id};''')
    db_connection.commit()

    # Close connection
    db_connection.close()

    db_logger.info(f'USERS DB. User record update: {column_name} is set to {new_value}')

update_last_usage = partial(update_user_record, column_name='last_usage', new_value=todays_date())
update_commands_count = partial(update_user_record, column_name='commands_use')
update_stickers_count = partial(update_user_record, column_name='stickers_send_to')
update_other_messages_count = partial(update_user_record, column_name='other_messages')

def get_user_value(user_id: int, column_name: str, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> int | str:
    """Gets a specified column value from user record.

    Args:
        user_id (int): user TG ID.
        column_name (str): name of the column.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.

    Returns:
        int | str: current value of the specified column.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()

    # Update the data
    result = db_cursor.execute(f'''SELECT {column_name} FROM {tablename} WHERE user_id={user_id};''').fetchone()

    # Close connection
    db_connection.close()

    return result[0]

get_current_commands_count = partial(get_user_value, column_name='commands_use')
get_current_stickers_count = partial(get_user_value, column_name='stickers_send_to')
get_current_other_messages_count = partial(get_user_value, column_name='other_messages')

def add_command_use(user_id: int, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> None:
    """Gets current value of used commands, received from user, and writes current + 1

    Args:
        user_id (int): user TG ID.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    current_value = get_current_commands_count(user_id=user_id, tablename=tablename, db_filename=db_filename)
    new_value = current_value + 1
    update_commands_count(user_id=user_id, new_value=new_value, tablename=tablename, db_filename=db_filename)

def add_sticker_send(user_id: int, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> None:
    """Gets current value of stickers, sent to user, and writes current + 1

    Args:
        user_id (int): user TG ID.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    current_value = get_current_stickers_count(user_id=user_id, tablename=tablename, db_filename=db_filename)
    new_value = current_value + 1
    update_stickers_count(user_id=user_id, new_value=new_value, tablename=tablename, db_filename=db_filename)

def add_other_message(user_id: int, tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> None:
    """Gets current value of other messages, received from user, and writes current + 1

    Args:
        user_id (int): user TG ID.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.
    """
    current_value = get_current_other_messages_count(user_id=user_id, tablename=tablename, db_filename=db_filename)
    new_value = current_value + 1
    update_other_messages_count(user_id=user_id, new_value=new_value, tablename=tablename, db_filename=db_filename)

    """ Statistics """

def count_users(tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> int:
    """Counts users that are in the db.
    As all the rows are unique, is it enough to count the rows.

    Args:
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_name.

    Returns:
        int: number of users.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()

    # Gather data
    users = db_cursor.execute(f'''SELECT * FROM {tablename}''').fetchall()

    # Close connection
    db_connection.close()

    return len(users)

def count_stickers(column_name: str = 'stickers_send_to', tablename: str = users_statistics_tablename, db_filename: os.PathLike = db_name) -> int:
    """Sums the values of 'stickers_send_to' column, or any other specified.

    Args:
        column_name (str, optional): name of the column to sum. Defaults to 'stickers_send_to'.
        tablename (str, optional): name of the table. Defaults to users_statistics_tablename.
        db_filename (os.PathLike, optional): path to db file. Defaults to db_filename.

    Returns:
        int: result.
    """
    # Establish connection
    db_connection = sqlite3.connect(db_filename)
    db_cursor = db_connection.cursor()

    # Update the data
    result = db_cursor.execute(f'''SELECT SUM({column_name}) FROM {tablename}''').fetchone()

    # Close connection
    db_connection.close()

    return result[0]


from __future__ import annotations

from abc import ABC, abstractmethod
from random import choice
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from units import BaseUnit

class AbstractSkill(ABC):
    def __init__(self):
        self.name = 'Базовый'
        self.power: float = 0
        self.required_stamina: float = 0
        self.regen_count: int = 5

    @property
    def get_required_stamina(self):
        return self.required_stamina

    def use(self, attacker: BaseUnit, target: BaseUnit):
        if self.required_stamina > attacker._stamina:
            return (f"{attacker.get_name} попробовал применить {self.name} "
                    "но так сильно устал что ничего не получилось")
        return self.skill_effect(attacker, target)

    @abstractmethod
    def skill_effect(self, attacker: BaseUnit, target: BaseUnit) -> str:
        pass

class SkillKick(AbstractSkill):
    def __init__(self):
        self.name = 'Свирепый Пинок'
        self.power = 12
        self.required_stamina = 6
        self.regen_count = 5

    def skill_effect(self, attacker: BaseUnit, target: BaseUnit) -> str:
        full_damage = self.power * attacker._attack_mod
        caused_damage = target._take_damage(full_damage)

        if caused_damage == 0:
            return (f"{attacker._name} используя {self.name} "
                    f"наносит удар, но соперник уворачивается "
                    f"и не получает урона")
        else:
            return (f"{attacker._name} используя {self.name} "
                    f"сбивает соперника с ног и "
                    f"наносит {caused_damage:.1f} урона")

class SkillPrick(AbstractSkill):
    def __init__(self):
        self.name = 'Мощный Укол'
        self.power = 15
        self.required_stamina = 5
        self.regen_count = 4

    def skill_effect(self, attacker: BaseUnit, target: BaseUnit) -> str:
        full_damage = self.power * attacker._attack_mod
        caused_damage = target._take_damage(full_damage)

        if caused_damage == 0:
            return (f"{attacker._name} используя {self.name} "
                    f"наносит удар, но соперник уворачивается "
                    f"и не получает урона")
        else:
            return (f"{attacker._name} используя {self.name} "
                    f"пробивает {target._armor.name} соперника и "
                    f"наносит {caused_damage:.1f} урона")

class SkillPrayer(AbstractSkill):
    def __init__(self):
        self.name = 'Молитва Господу'
        self.power = 15
        self.required_stamina = 3
        self.regen_count = 3

    def skill_effect(self, attacker: BaseUnit, target: BaseUnit) -> str:
        full_heal = self.power * attacker._attack_mod
        caused_heal = attacker._get_heal(full_heal)

        return (f"{attacker._name} вместо атаки применил {self.name}, "
                f"получил благословение и восстановил {caused_heal:.1f} "
                f"жизненной силы")

def skill_factory(unit_type: str) -> AbstractSkill:
    "Выберает случайное доступное умение в зависимости от типа"

    if unit_type == 'warrior':
        skill = SkillKick
    elif unit_type == 'thief':
        skill = choice([SkillPrick, SkillKick])
    elif unit_type == 'priest':
        skill = SkillPrayer
    else:
        raise TypeError

    return skill()


#!/usr/bin/env python3

from __future__ import print_function, unicode_literals, division, absolute_import
import argparse
import cherrypy
import colibricore
import sys
import os

SCRIPTDIR = os.path.dirname(os.path.abspath(__file__))

def safe(s):
    return s.replace("'","`")

def processrelations(type, func,  pattern, threshold, nodes, edges, classdecoder, colors, relationtypes="",secondorderedges=False, reverse=False):
    if not relationtypes or type in relationtypes:
        for pattern2, count in func(pattern, threshold):
            nodeid= safe(type + pattern2.tostring(classdecoder))
            if not nodeid in nodes:
                nodes[nodeid] =  [nodeid, pattern2, count,type]
            edges.append( [nodeid, pattern, pattern2, type, count, reverse] )

    tmpnodeset = set()
    for nodeid,p,_,_ in nodes.values():
        if nodeid[0] == type:
            tmpnodeset.add(p)

    if secondorderedges:
        for p in tmpnodeset:
            if p != pattern:
                try:
                    for p2, count in func(p, threshold):
                        if p2 in tmpnodeset and p2 != pattern:
                            nodeid= safe(type + p2.tostring(classdecoder))
                            if not nodeid in nodes:
                                nodes[nodeid] =  [nodeid, p2, count,type]
                            edges.append( [nodeid, p, p2, type, count, False] )
                except KeyError:
                    continue

class Root:
    def __init__(self, patternmodel, classdecoder, classencoder, threshold):
        self.patternmodel = patternmodel
        self.classdecoder = classdecoder
        self.classencoder = classencoder
        self.threshold = threshold

    @cherrypy.expose
    def query(self, pattern, relationtypes="", threshold=0):
        if threshold == 0:
            threshold = self.threshold
        pattern = self.classencoder.buildpattern(pattern)
        if pattern in self.patternmodel:

            nodes = {}
            nodes['center'] = ['center', pattern, self.patternmodel.occurrencecount(pattern),'center' ]
            edges = []

            minnodesize = 2
            maxnodesize = 10
            minedgesize = 1
            maxedgesize = 10

            colors = {'center':'#ff0000', 'c': "#333" , 'p': "#666",'r': "#3e6442" ,'l': "#5e9865",'t': '#323288','R':'#2e7469','L':'#2e7469' }
            extra = {'c': "arrow: 'target'",'p':"arrow: 'source'", 'l':  "arrow: 'source'" ,'r':  "arrow: 'target'", 'L':  "arrow: 'source'" ,'R':  "arrow: 'target'", 't': "arrow: 'source'"}

            processrelations('c',self.patternmodel.getsubchildren, pattern, threshold, nodes, edges, self.classdecoder, colors, relationtypes,True,True)
            processrelations('p',self.patternmodel.getsubparents, pattern,  threshold, nodes, edges, self.classdecoder,  colors,relationtypes,True)
            processrelations('l',self.patternmodel.getleftneighbours, pattern,  threshold,nodes, edges, self.classdecoder,  colors,relationtypes,False, True)
            processrelations('r',self.patternmodel.getrightneighbours, pattern,  threshold,nodes, edges,self.classdecoder,  colors,relationtypes)
            processrelations('t',self.patternmodel.gettemplates, pattern,  threshold, nodes, edges,self.classdecoder,  colors,relationtypes,True)
            #processrelations('L',self.patternmodel.getleftcooc, pattern, nodes, edges, self.classdecoder,  colors,relationtypes)
            #processrelations('R',self.patternmodel.getrightcooc, pattern, nodes, edges,self.classdecoder,  colors,relationtypes)

            jscode = """
var i,
s,
N = 100,
E = 500,
g = {
    nodes: [],
    edges: []
};"""

            #jscode = " var sigRoot = document.getElementById('graph');\n sigInst = sigma(sigRoot);"
            #jscode += " sigInst.drawingProperties({ defaultLabelColor: '#222', defaultLabelSize: 14, defaultLabelHoverColor: '#000', labelThreshold: 6, font: 'Arial', edgeColor: 'source', defaultEdgeType: 'curve' });\n"
            #jscode += " sigInst.graphProperties({ minNodeSize: " + str(minnodesize) + ", maxNodeSize: " + str(maxnodesize) + ", minEdgeSize: " + str(minedgesize) + ", maxEdgeSize: " + str(maxedgesize) + " });\n"
            #jscode += " sigInst.mouseProperties({ maxRatio: 450, minRatio: .1, marginRatio: 1, zoomDelta: 0.1, dragDelta: 0.3, zoomMultiply: 1.5, inertia: 1.1 });\n"
            #jscode += " sigInst.bind('upnodes', function(event){  var q = event.content[0].substr(1); window.location.assign('/query/?pattern=' + q );});\n"

            for nodeid, p, count, type in nodes.values():
                s = safe(p.tostring(self.classdecoder))
                size = count
                color = colors[type]

                jscode += " g.nodes.push({id:'" +  nodeid + "',text: '" + safe(s) + "', label: '" + s + " (" + str(count) + ")', 'size':"+str(size)+",'cluster': '" + type + "', 'color': '" + color + "', 'x': Math.random(),'y': Math.random() });\n"

            for nodeid, frompattern,topattern, type, count, reverse in edges:
                if frompattern == pattern:
                    s_from = 'center'
                else:
                    s_from = safe(type + frompattern.tostring(self.classdecoder))
                s_to = nodeid
                s_edgeid = s_from + "_REL" + type + "_" + s_to
                color = colors[type]
                if type in extra:
                    e = ", " + extra[type]
                else:
                    e = ""
                size = count
                if reverse:
                    jscode += " g.edges.push({id: '" + s_edgeid + "', type: 'arrow',  source: '" +s_to  + "', target: '" +s_from  + "' ,size:" + str(size) + ", 'color':'" + color + "'" + e + " });\n"
                else:
                    jscode += " g.edges.push({id: '" + s_edgeid + "', type: 'arrow',  source: '" +s_from  + "', target: '" +s_to  + "' ,size:" + str(size) + ", 'color':'" + color + "'" + e + " });\n"

            jscode += "sigma.settings.labelThreshold = 4;\n";
            jscode += "sigma.settings.minNodeSize = " + str(minnodesize) + ";\n";
            jscode += "sigma.settings.maxNodeSize = " + str(maxnodesize) + ";\n";
            jscode += "sigma.settings.minEdgeSize = " + str(minedgesize) + ";\n";
            jscode += "sigma.settings.maxEdgeSize = " + str(maxedgesize) + ";\n";
            jscode += "sigma.settings.defaultEdgeType = 'arrow';\n";
            jscode += "s = new sigma({graph: g, container: 'graph'});"
            jscode += "s.startForceAtlas2({startingIterations: 25, iterationsPerRender: 0});\n"
            jscode += "s.bind('clickNode', function(e) { var q = e.data.node.text.replace('`',\"'\"); window.location.assign('../query/?pattern=' + q );});\n"
            jscode += "window.setTimeout(function(){ s.stopForceAtlas2();}, 10000);\n";
            jscode = "$(document).ready(function(){\n" + jscode + "\n});"
        else:
            jscode = ""

        return self.page("../",jscode)

    @cherrypy.expose
    def index(self):
        return self.page()

    def page(self, prefix="",jscode=""):
        html = "<title>Colibri PatternGraphView</title>"
        html += "<meta charset=\"utf-8\">"
        html += ""
        html += ""
        html += ""
        html += ""
        html += ""
        html += "<link rel=\"stylesheet\" href=\"" + prefix + "static/predictor.css\" type=\"text/css\" media=\"all\" />"
        html += ""
        html += '

Colibri Graph Viewer

'
        if jscode:
            html += "

"
        else:
            html += "

"
            html += "
Pattern not found
"
        html += "<form action=\"" + prefix + "query/\" method=\"post\"><input name=\"pattern\" /><input type=\"submit\"></form>
"
        return html

def main():
    parser = argparse.ArgumentParser(description="Colibri Graph View - Visualises a pattern model", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('-m','--modelfile', type=str,help="The Indexed Pattern Model to load", action='store',required=True)
    parser.add_argument('-c','--classfile', type=str,help="The class file", action='store',required=True)
    parser.add_argument('-p','--port', type=int,help="Port", action='store',default=8080,required=False)
    parser.add_argument('-t','--threshold', type=int,help="Threshold, consider only related patterns occuring at least this many times", action='store',default=2,required=False)
    args = parser.parse_args()

    print("Loading class encoder",file=sys.stderr)
    classencoder = colibricore.ClassEncoder(args.classfile)
    print("Loading class decoder",file=sys.stderr)
    classdecoder = colibricore.ClassDecoder(args.classfile)
    print("Loading pattern model",file=sys.stderr)
    patternmodel = colibricore.IndexedPatternModel(args.modelfile)

    config = {
        'global': {
            'server.socket_host': '0.0.0.0',
            'server.socket_port': args.port,
        },
        '/static': {
            'tools.staticdir.on'            : True,
            'tools.staticdir.dir'           : os.path.join(SCRIPTDIR, 'static'),
            'tools.staticdir.content_types' : {'html': 'application/octet-stream'}
        }
    }
    def fake_wait_for_occupied_port(host, port): return
    cherrypy.process.servers.wait_for_occupied_port = fake_wait_for_occupied_port
    cherrypy.quickstart(Root(patternmodel, classdecoder, classencoder, args.threshold), config=config)

if __name__ == '__main__':
    main()


# Code Release for ICLR-22 work
# 'Differentiable Gradient Sampling for Learning Implicit 3D Scene Reconstructions from a Single Image'
# Any question please contact Shizhan Zhu: zhshzhutah2@gmail.com
# Released on 04/25/2022.

# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

import numpy as np
import torch  # Routines for numpy and torch

def ELU02cam0(elu0):
    assert len(elu0) == 9
    ex = elu0[0]
    ey = elu0[1]
    ez = elu0[2]
    lx = elu0[3]
    ly = elu0[4]
    lz = elu0[5]
    ux = elu0[6]
    uy = elu0[7]
    uz = elu0[8]
    u = np.array([ux, uy, uz], dtype=np.float32)

    z = np.array([lx - ex, ly - ey, lz - ez], dtype=np.float32)
    z = z / np.linalg.norm(z)
    x = np.cross(z, u)
    y = np.cross(z, x)
    assert np.linalg.norm(x) > 0.
    assert np.linalg.norm(y) > 0.
    x = x / np.linalg.norm(x)
    y = y / np.linalg.norm(y)

    M = np.array([[x[0], x[1], x[2], -(x[0] * ex + x[1] * ey + x[2] * ez)],
                  [y[0], y[1], y[2], -(y[0] * ex + y[1] * ey + y[2] * ez)],
                  [z[0], z[1], z[2], -(z[0] * ex + z[1] * ey + z[2] * ez)],
                  [  0.,   0.,   0., 1.]], dtype=np.float32)

    assert M[-1, 0] == 0.
    assert M[-1, 1] == 0.
    assert M[-1, 2] == 0.
    assert M[-1, 3] == 1.
    return M  # which is cam0

def ELU2cam(elu):
    assert len(elu.shape) == 2 and elu.shape[1] == 9
    m = elu.shape[0]
    e = elu[:, :3]
    l = elu[:, 3:-3]
    u = elu[:, -3:]

    z = l - e
    z_norm = np.linalg.norm(z, ord=2, axis=1)
    # assert np.all(z_norm > 0)  # invalid cases will output nan
    z = z / z_norm[:, None]
    x = np.cross(z, u)
    y = np.cross(z, x)
    x_norm = np.linalg.norm(x, ord=2, axis=1)
    y_norm = np.linalg.norm(y, ord=2, axis=1)
    # assert np.all(x_norm > 0)
    # assert np.all(y_norm > 0)
    x = x / x_norm[:, None]
    y = y / y_norm[:, None]

    MList = [
        x[:, 0], x[:, 1], x[:, 2], -(x * e).sum(1),
        y[:, 0], y[:, 1], y[:, 2], -(y * e).sum(1),
        z[:, 0], z[:, 1], z[:, 2], -(z * e).sum(1),
        np.zeros((m, ), dtype=np.float32), np.zeros((m, ), dtype=np.float32),
        np.zeros((m, ), dtype=np.float32), np.ones((m, ), dtype=np.float32),
    ]
    M = np.stack(MList, 1).astype(np.float32).reshape((m, 4, 4))
    return M

modelViewLookAtRDF0 = ELU02cam0
# We always use cam0 to do: vertCam0 = np.matmul(vertWorld0, cam0[:3, :3].transpose()) + cam0[:3, -1]
# We always use cbm0 to d0: vertWorld0 = np.matmul(vertCam0, cbm0[:3, :3].transpose()) + cbm0[:3, -1]
# naming of cbm: camera back

def camSys2CamPerspSys0(pointCam0, focalLengthWidth, focalLengthHeight, winWidth, winHeight, zNear=1.e-6):
    assert len(pointCam0.shape) == 2 and pointCam0.shape[1] == 3
    assert type(focalLengthWidth) is float and type(focalLengthHeight) is float

    if type(pointCam0) is np.ndarray:
        point = pointCam0.copy()
        point[:, 0] = point[:, 0] / np.maximum(point[:, 2], zNear) * (float(focalLengthWidth) / winWidth * 2.)
        point[:, 1] = point[:, 1] / np.maximum(point[:, 2], zNear) * (float(focalLengthHeight) / winHeight * 2.)
        pointCamPersp0 = point
    elif type(pointCam0) is torch.Tensor:
        point = pointCam0.detach().clone()
        point[:, 0] = point[:, 0] / torch.clamp(point[:, 2], min=zNear) * (float(focalLengthWidth) / winWidth * 2.)
        point[:, 1] = point[:, 1] / torch.clamp(point[:, 2], min=zNear) * (float(focalLengthHeight) / winHeight * 2.)
        pointCamPersp0 = point
    else:
        raise TypeError('pointCam0 has a wrong type %s' % type(pointCam0))
    return pointCamPersp0

def camSys2CamPerspSysTHGPU(pointCam, focalLengthWidth, focalLengthHeight,
                            winWidth, winHeight, zNear=float(1.e-6)):
    return torch.stack([
        torch.div(pointCam[:, :, 0], torch.clamp(pointCam[:, :, 2], min=zNear)) *
                  (torch.div(focalLengthWidth, winWidth) * 2.)[:, None],
        torch.div(pointCam[:, :, 1], torch.clamp(pointCam[:, :, 2], min=zNear)) *
                  (torch.div(focalLengthHeight, winHeight) * 2.)[:, None],
        pointCam[:, :, 2],
    ], 2)

def camPerspSys2CamSys0(pointCamPersp0, focalLengthWidth, focalLengthHeight, winWidth, winHeight, zNear=1.e-6):
    assert len(pointCamPersp0.shape) == 2 and pointCamPersp0.shape[1] == 3
    assert type(focalLengthWidth) is float and type(focalLengthHeight) is float

    if type(pointCamPersp0) is np.ndarray:
        point = pointCamPersp0.copy()
        point[:, 0] = point[:, 0] / (float(focalLengthWidth) / winWidth * 2.) * np.maximum(point[:, 2], zNear)
        point[:, 1] = point[:, 1] / (float(focalLengthHeight) / winHeight * 2.) * np.maximum(point[:, 2], zNear)
        pointCam0 = point
    elif type(pointCamPersp0) is torch.Tensor:
        point = pointCamPersp0.detach().clone()
        point[:, 0] = point[:, 0] / (float(focalLengthWidth) / winWidth * 2.) * torch.clamp(point[:, 2], min=zNear)
        point[:, 1] = point[:, 1] / (float(focalLengthHeight) / winHeight * 2.) * torch.clamp(point[:, 2], min=zNear)
        pointCam0 = point
    else:
        raise TypeError('pointCam0 has a wrong type %s' % type(pointCamPersp0))
    return pointCam0

def worldSys2WorldNpone(pointWorld0, min, max):
    assert len(pointWorld0.shape) == 2 and pointWorld0.shape[1] == 3
    assert min.shape == (3, )
    assert max.shape == (3, )
    pointWorldNpone0 = (pointWorld0 - min[None, :]) / (max[None, :] - min[None, :]) * 2. - 1.
    return pointWorldNpone0

'''
Different dataset has different up / depth direction def, so avoid using this function.
Instead, implement according to this mode everytime when dealing with a different function.
def cbm02ELU0(cbmR0, cbmT0):
    assert abs(np.linalg.det(cbmR0) - 1.) < 1.e-4
    E0 = cbmT0.copy()
    tmp = np.dot(cbmR0, np.array([0., 0., 1.], dtype=np.float32) - 0.)  # minus 0 as the inverse translate
    lookDir0 = tmp / np.linalg.norm(tmp)
    L0 = E0 + 1. * lookDir0
    tmp = np.dot(cbmR0, np.array([0., -1., 0.], dtype=np.float32) - 0.)  # minus 0 as the inverse translate
    U0 = tmp / np.linalg.norm(tmp)
    U0Check = np.dot(U0, np.array([0., 0., 1.], dtype=np.float32)) > 0  # True if it is conventional
    return E0, L0, U0, U0Check
'''

# def getRotationMatrixBatchNP(rotationAxis, degrees):  # functional
#     return getRotationMatrixBatchTH(
#         torch.from_numpy(rotationAxis), torch.from_numpy(degrees)).detach().numpy()

def getRotationMatrixBatchTH(rotationAxis, degrees):   # functional
    # No Translation, single quaternion
    # Inputs:
    #   rotationsAxis: m * 3
    #   degrees: m  (Note this is degree representation, not radius representation!)
    # Outputs:
    #   Rs: m * 3 * 3
    # State Changes:
    #   None!

    assert len(rotationAxis.shape) == 2 and rotationAxis.shape[1] == 3
    assert len(degrees.shape) == 1 and rotationAxis.shape[0] == degrees.shape[0]

    norms = torch.norm(rotationAxis, p=2, dim=1)
    assert norms.min() > 0.
    normalized = torch.div(rotationAxis, norms[:, None])

    halfRadian = degrees * .5 * np.pi / 180.
    vCos = torch.cos(halfRadian)
    vSin = torch.sin(halfRadian)
    quat = torch.cat([vCos[:, None], vSin[:, None] * normalized], dim=1)
    rotMats = quat2matTH(quat)
    return rotMats

def getRotationMatrixBatchNP(rotationAxis, degrees, **kwargs):  # functional
    assert len(rotationAxis.shape) == 2 and rotationAxis.shape[1] == 3
    assert len(degrees.shape) == 1 and rotationAxis.shape[0] == degrees.shape[0]

    norms = np.linalg.norm(rotationAxis, ord=2, axis=1)
    assert norms.min() > 0.
    normalized = np.divide(rotationAxis, norms[:, None])

    halfRadian = degrees * .5 * np.pi / 180.
    vCos = np.cos(halfRadian)
    vSin = np.sin(halfRadian)
    quat = np.concatenate([vCos[:, None], vSin[:, None] * normalized], 1)
    rotMats = quat2matNP(quat)
    return rotMats

# def getRotationMatrixBatchNP(rotationsAxis, degrees, **kwargs):  # functional
#     cudaDevice = kwargs.get('cudaDevice', None)
#     rotationsAxis = torch.from_numpy(rotationsAxis)
#     degrees = torch.from_numpy(degrees)
#     if cudaDevice:
#         rotationsAxis = rotationsAxis.to(cudaDevice)
#         degrees = degrees.to(cudaDevice)
#     return getRotationMatrixBatchTH(
#         rotationsAxis, degrees,
#     ).detach().cpu().numpy()

def mat2quatNP(R):  # functional
    assert len(R.shape) == 3 and R.shape[1] == 3 and R.shape[2] == 3
    w = ((1. + R[:, 0, 0] + R[:, 1, 1] + R[:, 2, 2]) ** .5) * .5
    fwInverse = .25 / w  # 1/4w
    x = (R[:, 2, 1] - R[:, 1, 2]) * fwInverse
    y = (R[:, 0, 2] - R[:, 2, 0]) * fwInverse
    z = (R[:, 1, 0] - R[:, 0, 1]) * fwInverse
    q = np.stack([w, x, y, z], 1)
    return q

def quat2matTH(quat):  # functional
    assert len(quat.shape) == 2 and quat.shape[1] == 4

    norm_quat = quat
    norm_quat = norm_quat/norm_quat.norm(p=2, dim=1, keepdim=True)
    w, x, y, z = norm_quat[:,0], norm_quat[:,1], norm_quat[:,2], norm_quat[:,3]

    B = quat.size(0)

    w2, x2, y2, z2 = w.pow(2), x.pow(2), y.pow(2), z.pow(2)
    wx, wy, wz = w*x, w*y, w*z
    xy, xz, yz = x*y, x*z, y*z

    rotMats = torch.stack([w2 + x2 - y2 - z2, 2*xy - 2*wz, 2*wy + 2*xz,
                          2*wz + 2*xy, w2 - x2 + y2 - z2, 2*yz - 2*wx,
                          2*xz - 2*wy, 2*wx + 2*yz, w2 - x2 - y2 + z2], dim=1).view(B, 3, 3)
    return rotMats

def quat2matNP(quat):  # functional
    assert len(quat.shape) == 2 and quat.shape[1] == 4

    norm_quat = quat
    norm_quat = norm_quat / np.linalg.norm(norm_quat, ord=2, axis=1, keepdims=True)
    w, x, y, z = norm_quat[:, 0], norm_quat[:, 1], norm_quat[:, 2], norm_quat[:, 3]

    B = quat.shape[0]

    w2, x2, y2, z2 = w ** 2, x ** 2, y ** 2, z ** 2
    wx, wy, wz = w * x, w * y, w * z
    xy, xz, yz = x * y, x * z, y * z

    rotMats = np.stack([
        w2 + x2 - y2 - z2, 2 * xy - 2 * wz, 2 * wy + 2 * xz,
        2 * wz + 2 * xy, w2 - x2 + y2 - z2, 2 * yz - 2 * wx,
        2 * xz - 2 * wy, 2 * wx + 2 * yz, w2 - x2 - y2 + z2
    ], 1).reshape((B, 3, 3))
    return rotMats

if __name__ == '__main__':
    rep = 8
    aa = torch.tensor([0, 0, 1]).float()
    aa = torch.stack([aa for _ in range(rep)], 0)
    bb = torch.Tensor(range(rep)).float() * 360. / rep
    cc = getRotationMatrixBatchTHGPU(aa, bb)
    import ipdb
    ipdb.set_trace()
    print(1 + 1)


import numpy as np
import pytest
from turbulence_models.hole_clump import HoleClump

@pytest.mark.parametrize(("xmax", "vmax", "nx", "nv", "nu", "ne"), [
    (10.0, 11.0, 10, 11, 1.0, 1.0),
])
def test_hole_clump(xmax, vmax, nx, nv, nu, ne):
    model = HoleClump(xmax, vmax, nx, nv, nu, ne)
    rng = np.random.RandomState(0)
    finit = rng.randn(nx, nv)
    vinit = rng.randn(nx)
    einit = rng.randn(nx)
    result = model.solve((0, 1e-5), finit, vinit, einit)
    assert np.isfinite(result["y"]).all()
    model.to_xarray(result)