import os
import sys
import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler

class MyHandler(PatternMatchingEventHandler):
    patterns = ["*.*"]

    def process(self, event):
        """
        event.event_type
            'modified' | 'created' | 'moved' | 'deleted'
        event.is_directory
            True | False
        event.src_path
            path/to/observed/file
        """
        # the file will be processed there
        # print("event src path", event.src_path)  # print now only for debug
        # print("event type", event.event_type)  # print now only for debug
        subprocess.call(["rsync", "-avz", "--delete", "--exclude=.*", SOURCE, DEST])

    def on_modified(self, event):
       self.process(event)

    def on_created(self, event):
        self.process(event)

if __name__ == '__main__':
    SOURCE = ""
    DEST = ""

    if len(sys.argv) is 1 or len(sys.argv) > 3:
        print("------------------------------------------------------------------------------")
        print("Specify correct commandline arguments. Use 1 or 2 arguments:")
        print("")
        print(" Usage with 1 argument:")
        print("    Current directory will be used as source")
        print("    Specify destination as: /path/to/dest OR user@ip.adr:/path/to/dest")
        print("")
        print("Example: python projectsync.py user@10.10.10.10:/path/to/dest")
        print("")
        print(" Usage with 2 arguments:")
        print("    First arg: Path to source folder")
        print("    Second arg: Path to destination folder")
        print("")
        print("Example: python projectsync.py /path/to/source user@10.10.10.10:/path/to/dest")
        print("")
        print("To sync to remote destination use second argument of format:")
        print("username@ip.adress.of.host:/path/to/folder")
        print("Transfer via rsync, so destination computer should have your ssh key installed")
        print("------------------------------------------------------------------------------")
        exit()

    elif len(sys.argv) is 2:
        SOURCE = os.getcwd()
        if not SOURCE.endswith("/"):
            SOURCE = SOURCE + "/"
        DEST = sys.argv[1]
        if DEST.endswith("/"):
            DEST = DEST[:-1]

    elif len(sys.argv) is 3:
        SOURCE = sys.argv[1]
        if not SOURCE.endswith("/"):
            SOURCE = SOURCE + "/"
        DEST = sys.argv[2]
        if DEST.endswith("/"):
            DEST = DEST[:-1]

    print("Watcher will copy files from: %s" % SOURCE)
    print("Watcher will copy files to: %s" % DEST)
    print("")
    print("Running inital transfer of existing files.")
    subprocess.call(["rsync", "-avz", "--delete", "--exclude=.*", SOURCE, DEST])

    print("")
    print('Filewatcher started.')
    observer = Observer()
    observer.schedule(MyHandler(), path=SOURCE, recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()

    observer.join()


from dataclasses import dataclass
from datetime import datetime as date

@dataclass
class Employee:

    name: str
    salary: float
    phot_url: str | None = None
    __is_active: bool = True
    resignation_date: date | None = None
    register_date: date = date.now()

    @property
    def is_active(self) -> bool:
        return self.__is_active

    @is_active.setter
    def is_active(self, value: bool) -> None:
        self.__is_active = value


import argparse
import signal

import psutil
from fastapi import FastAPI

import sys
import os

# 添加项目路径进入环境变量，避免找不到模块
sys.path.append(os.path.split(os.path.abspath(os.path.dirname(__file__)))[0])

from starlette.middleware.cors import CORSMiddleware
from course_helper.routers import user, websocket, course, file

# 神奇地修复了CMD下颜色乱码的问题
os.system('')

def pid_lock():
    if os.path.exists('server.pid'):
        with open('server.pid') as f:
            pid = f.read()
            if psutil.pid_exists(int(pid)):
                sys.exit(0)
    with open('server.pid', 'w') as f:
        f.write(str(os.getpid()))

def close_server():
    if os.path.exists('server.pid'):
        with open('server.pid') as f:
            pid = f.read()
            # 虽然能结束进程，但是有莫名其妙的错误
            try:
                p = psutil.Process(int(pid))
                p.send_signal(signal.CTRL_C_EVENT)
            except:
                pass

# 命令行参数
parser = argparse.ArgumentParser(description='CourseHelper server!')
parser.add_argument('cmd', type=str, nargs='?', default='start', help='start (default), stop, restart')
args = parser.parse_args()

if args.cmd == 'stop':
    close_server()
    sys.exit(0)
elif args.cmd == 'restart':
    close_server()
    # 保证锁文件已清除
    if os.path.exists('server.pid'):
        os.remove('server.pid')

# 开启程序单实例锁
pid_lock()

app = FastAPI()

# 设置跨域传参
app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],  # 设置允许访问的域名 "*"，即为所有。
    allow_credentials=True,
    allow_methods=["*"],  # 设置允许跨域的http方法，比如 get、post、put等。
    allow_headers=["*"]  # 允许跨域的headers，可以用来鉴别来源等作用。
)

@app.on_event("startup")
async def __init():
    # WebSocket路由
    app.include_router(websocket.router, prefix="/websocket")
    # 用户路由
    app.include_router(user.router, prefix="/user")
    # 课程路由
    app.include_router(course.router, prefix="/course")
    # 文件路由
    app.include_router(file.router, prefix="/file")

@app.get('/')
async def hello_world():
    return 'Hello world'

if __name__ == "__main__":
    import uvicorn

    # noinspection PyTypeChecker
    uvicorn.run(app, host='127.0.0.1', port=6498)


import cv2
img = cv2.imread('image.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

faces = face_cascade.detectMultiScale(gray, 1.1, 4)
print('Number of detected faces:', len(faces))

if len(faces) > 0:
    for i, (x, y, w, h) in enumerate(faces):
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2)
        face = img[y:y + h, x:x + w]
        cv2.imshow(f"Cropped Face {i}", face)
        cv2.imwrite(f'face-{i}.jpg', face)
        print(f"face{i}.jpg is saved")

cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


r"""
This file implements Selling's algorithm in dimension $d \in \\{2,3\\}$, which decomposes a
symmetric positive definite matrix $D$, of dimension $d\leq 3$, in the form
$$
	D = \sum_{0\leq i < I} a_i e_i e_i^\top,
$$
where $a_i \geq 0$ and $e_i\in Z^d$ is a vector with integer coordinates,
and where $I = d(d+2)/2$.

Selling's decomposition is a central tool in the design of adaptive discretization schemes
for anisotropic partial differential equations, on Cartesian grids.
"""

import numpy as np
from itertools import cycle
from .LinearParallel import dot_VAV, perp, cross
from . import AutomaticDifferentiation as ad
cps = ad.cupy_support
samesize_int_t = ad.cupy_generic.samesize_int_t

iterMax2 = 100
iterMax3 = 100

# -------- Dimension based dispatch -----

def ObtuseSuperbase(m,sb=None):
	"""
	Input :
	- m : symmetric positive definite matrix, defined as an
	 array of shape $(d,d, n_1,...,n_k)$.
	- sb (optional) : initial guess for the obtuse superbase.

	Ouput : an m-obtuse superbase
	"""
	dim = len(m)
	if sb is None: sb = CanonicalSuperbase(m)
	if   dim==1: return _ObtuseSuperbase1(m,sb)
	elif dim==2: return _ObtuseSuperbase2(m,sb)
	elif dim==3: return _ObtuseSuperbase3(m,sb)
	else: raise ValueError("Selling's decomposition only applies in dimension <=3.")

def Decomposition(m,sb=None):
	r"""
	Use Selling's algorithm to decompose a tensor

	Input :
	- m : symmetric positive definite matrix, defined as an
	 array of shape $(d,d, n_1,...,n_k)$ where $d\leq 3$.
	- sb (optional) : superbase to use for the decomposition,
	 array of shape $(d,d+1, n_1,...,n_k)$.
	Output : the coefficients and offsets of the decomposition.
	"""

	# Strange bugs were observed when running the code below on the GPU with early cupy versions,
	# related with the array indexing pattern. Using a custom cuda kernel is faster and safer.
	if ad.cupy_generic.from_cupy(m):
		from . import Eikonal
		return Eikonal.VoronoiDecomposition(m,mode='gpu')

	dim = len(m)
	if sb is None: sb = ObtuseSuperbase(m,sb)
	if   dim==1: return _Decomposition1(m,sb)
	elif dim==2: return _Decomposition2(m,sb)
	elif dim==3: return _Decomposition3(m,sb)
	else: raise ValueError("Selling's decomposition only applies in dimension <=3.")

def GatherByOffset(T,Coefs,Offsets):
	"""
	Get the coefficient of each offset.
	This function is essentially used to make nice plots of how the superbase coefficients
	and offsets vary as the decomposed tensor varies.
	"""
	T,Coefs,Offsets = map(ad.cupy_generic.cupy_get,(T,Coefs,Offsets))
	TimeCoef = {};
	for (i,t) in enumerate(T):
		coefs = Coefs[:,i]
		offsets = Offsets[:,:,i]
		for (j,c) in enumerate(coefs):
			offset = tuple(offsets[:,j].astype(int))
			offset_m = tuple(-offsets[:,j].astype(int))
			if offset<offset_m:
				offset=offset_m
			if offset in TimeCoef:
				TimeCoef[offset][0].append(t)
				TimeCoef[offset][1].append(c)
			else:
				TimeCoef[offset] = ([t],[c])
	return TimeCoef

def CanonicalSuperbase(m):
	"""
	Returns a superbase with the same dimensions and array type as m.

	Output :
	 - m : array of shape $(d,d, n_1,...,n_k)$
	"""
	d=len(m); assert m.shape[1]==d
	shape=m.shape[2:]

	sb=cps.zeros_like(m,shape=(d,d+1,*shape))
	sb[:,0]=-1
	for i in range(d):
		sb[i,i+1]=1
	return sb

def SuperbasesForConditioning(cond,dim=2):
	"""
	Returns a family of superbases.
	For any positive definite matrix $M$ with condition number below the given bound,
	one of these superbases will be $M$-obtuse.
	(Condition number is the ratio of the largest to the smallest eigenvalue.)

	Input :
	 - cond (scalar) : the bound on the condition number.
	"""
	if   dim==1: return _SuperbasesForConditioning1(cond)
	elif dim==2: return _SuperbasesForConditioning2(cond)
	elif dim==3: return _SuperbasesForConditioning3(cond)
	else: raise ValueError("Selling's decomposition only applies in dimension <=3.")

# ------- One dimensional variant (trivial) ------

def _ObtuseSuperbase1(m,sb=None):
	return CanonicalSuperbase(m)

def _Decomposition1(m,sb):
	shape = m.shape[2:]
	offsets = cps.ones_like(m,shape=(1,1,*shape),dtype=samesize_int_t(m.dtype))
	coefs = m.reshape((1,*shape))
	return coefs,offsets

def _SuperbasesForConditioning1(cond):
	sb = CanonicalSuperbase(np.eye(1))
	return sb.reshape(sb.shape+(1,))

# ------- Two dimensional variant ------

# We do everyone in parallel, without selection or early abort
def _ObtuseSuperbase2(m,sb):
	"""
		Use Selling's algorithm to compute an obtuse superbase.

		input : symmetric positive definite matrix m, dim=2
		input/output : superbase b (must be valid at startup)

		module variable : iterMax2, max number of iterations

		output : wether the algorithm succeeded
	"""
	iterReduced = 0
	for iter,(i,j,k) in zip(range(iterMax2), cycle([(0,1,2),(1,2,0),(2,0,1)]) ):
		# Test for a positive angle, and modify superbase if necessary
		acute = dot_VAV(sb[:,i],m,sb[:,j]) > 0
		if np.any(acute):
			sb[:,k,acute] = sb[:,i,acute]-sb[:,j,acute]
			sb[:,i,acute] = -sb[:,i,acute]
			iterReduced=0
		elif iterReduced<3: iterReduced+=1
		else: return sb

	raise ValueError(f"Selling's algorithm did not terminate in iterMax2={iterMax2} iterations")

# Produce the matrix decomposition
def _Decomposition2(m,sb):
	"""
		Use Selling's algorithm to decompose a tensor

		input : symmetric positive definite tensor
		output : coefficients, offsets
	"""
	shape = m.shape[2:]
	coef  = cps.zeros_like(m,shape=(3,*shape))
	for (i,j,k) in [(0,1,2),(1,2,0),(2,0,1)]:
		coef[i] = -dot_VAV(sb[:,j],m, sb[:,k])

	return coef,perp(sb).astype(samesize_int_t(coef.dtype))

def _SuperbasesForConditioning2(cond):
	"""
	Implementation is based on exploring the Stern-Brocot tree,
	with a stopping criterion based on the angle between consecutive vectors.
	"""

	mu = np.sqrt(cond)
	theta = np.pi/2. - np.arccos( 2/(mu+1./mu))

	u=np.array( (1,0) )
	l = [np.array( (-1,0) ),np.array( (0,1) )]
	m = []
	superbases =[]

	def angle(u,v): return np.arctan2(u[0]*v[1]-u[1]*v[0], u[0]*v[0]+u[1]*v[1])

	while l:
		v=l[-1]
		if angle(u,v)<=theta:
			m.append(u)
			u=v
			l.pop()
		else:
			l.append(u+v)
			superbases.append((u,v,-u-v))

	return np.array(superbases).transpose((2,1,0))

# ------- Three dimensional variant -------

# We do everyone in parallel, without selection or early abort
def _ObtuseSuperbase3(m,sb):
	"""
		Use Selling's algorithm to compute an obtuse superbase.

		input : symmetric positive definite matrix m, dim=3
		input/output : superbase b (must be valid at startup)

		module variable : iterMax3, max number of iterations

		output : wether the algorithm succeeded
	"""
#	This energy is reduced at each time step
#	def energy(): return sum([dot_VAV(sb[:,i],m,sb[:,i]) for i in range(4)])
#	Introducing a tolerance, for the positivity test, was not needed in our experiments
#	tol = 100*np.finfo(m.dtype).eps*trace(m)
#	if(np.any(tol<=0)): raise ValueError("Matrices must be positive definite (negative trace found)")

	iterReduced = 0
	sigma = cycle([(0,1,2,3),(0,2,1,3),(0,3,1,2),(1,2,0,3),(1,3,0,2),(2,3,0,1)])
	for iter,(i,j,k,l) in zip(range(iterMax3), sigma):
		# Test for a positive angle, and modify superbase if necessary
		acute = dot_VAV(sb[:,i],m,sb[:,j]) > 0
		if np.any(acute):
			sb[:,k,acute] += sb[:,i,acute]
			sb[:,l,acute] += sb[:,i,acute]
			sb[:,i,acute] = -sb[:,i,acute]
			iterReduced=0
		elif iterReduced<6: iterReduced+=1
		else: return sb
	raise ValueError(f"Selling's algorithm did not terminate in iterMax3={iterMax3} iterations")

def _Decomposition3(m,sb):
	"""
		Use Selling's algorithm to decompose a tensor

		input : symmetric positive definite tensor, d=3
		output : coefficients, offsets
	"""
	shape = m.shape[2:]

	coef   = cps.zeros_like(m,shape=(6,*shape))
	offset = cps.zeros_like(m,shape=(3,6,*shape))
	for iter,(i,j,k,l) in enumerate(
		[(0,1,2,3),(0,2,1,3),(0,3,1,2),(1,2,0,3),(1,3,0,2),(2,3,0,1)]):
		coef[iter] = -dot_VAV(sb[:,i],m, sb[:,j])
		offset[:,iter] = cross(sb[:,k], sb[:,l])

	return coef,offset.astype(samesize_int_t(coef.dtype))

def _SuperbasesForConditioning3(cond):
	raise ValueError("Sorry, _SuperbasesForConditioning3 is not implemented yet")


from pathlib import Path
import streamlit as st
import config
from utils_app import load_model, infer_uploaded_image, infer_uploaded_video
from streamlit_lottie import st_lottie
import requests
from feedback import feedback_ui
import json
from au import authenticate

def display_authentication_page():
    # Call the authenticate function from au.py
    authenticate()

 #--------------Lottie Animation Loader-------------------

def load_lottie_url(url:str):
        r = requests.get(url)
        if r.status_code != 200:
            return None
        return r.json()

def load_lottie_file(file_path:str):
    with open(file_path, "r") as file:
        return json.load(file)

def display_main_page():

    # st.image('images/banner.jpg', use_column_width=True)
        # Sidebar
    st.sidebar.header(" 🚀 YOLOv8 Models")

    model_type = st.sidebar.selectbox(
        "Select Model",
        config.DETECTION_MODEL_LIST_V8,
        key='models_selectbox'
    )

    confidence = float(st.sidebar.slider(
        "Select Model Confidence", 30, 100, 50)) / 100

    model_path = ""
    if model_type:
        model_path = Path(config.DETECTION_MODEL_DIR_V8, str(model_type))
    else:
        st.error("Please Select Model in Sidebar")

    #--------------- Load pretrained DL model------------

    try:
        model = load_model(model_path)
    except Exception as e:
        st.error(f"Unable to load model. Please check the specified path: {model_path}")

    #--------------Image/video options-------------------

    st.sidebar.header("🖼 Image/Video Upload")
    source_selectbox = st.sidebar.selectbox(
            "Select Source",
            config.SOURCES_LIST
        )

    uploaded_file = st.sidebar.file_uploader(label="Choose a file...")

    # Check if a file has been uploaded or instructions have been displayed before:
    if uploaded_file is None :

            st.session_state['instructions_displayed'] = True

            lottie = """
            <script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script>
            <lottie-player src="https://raw.githubusercontent.com/irinagetman1973/YOLO-Streamlit/main/animation_sphere.json" background="transparent" speed="1" style="width: 400px; height: 400px;" loop autoplay></lottie-player>
            """
            st.markdown("""
                <style>
                    iframe {
                        position: fixed;
                        top: 16rem;
                        bottom: 0;
                        left: 1205;
                        right: 0;
                        margin: auto;
                        z-index=-1;
                    }
                </style>
                """, unsafe_allow_html=True
            )

            st.components.v1.html(lottie, width=410, height=410)

            st.title("Welcome to the :green[**_YOLO_**] models evaluation app!")
            st.divider()

            col1, col2 = st.columns([0.6, 0.3])  # Create a 2-column layout with equal width for each column

            with col1:

                  # Title

                    # Step 1

                    st.write(":star: **Sign Up for Enhanced Features:**")
                    st.write ("Become a registered user to unlock advanced features like comparing YOLOv7 model performances, viewing statistics, and saving data as Excel sheets." )
                    st.divider()
                    st.subheader(" :green[How to start:] ")
                    st.write(":one: :blue[**Choose a YOLOv8 Model:**]")
                    st.write("""
                    In the sidebar, you'll find a dropdown box where you can select from different YOLOv8 models:
                    - :green[**8l:**] This model has a larger size and offers higher accuracy.
                    - :green[**8m:**] A medium-sized model offering a good balance between size, speed, and accuracy.
                    - :green[**8s:**] A smaller model, faster but with slightly lower accuracy.
                    - :green[**8x:**] An extended model with more layers, providing higher accuracy but at the cost of speed.
                    - :green[**8n:**] A nominal model that provides a balance between size and accuracy.
                    """)

                    st.divider()

                    # Step 2
                    st.write(":two: :blue[**Adjust Confidence Score:**]")
                    st.write("Adjust the confidence score using the slider in the sidebar. A higher confidence score will result in fewer detections but with higher certainty.")

                    st.divider()

                    # Step 3
                    st.write(":three: :blue[**Select Data Type:**]")
                    st.write("Choose the type of data you'd like the model to process: image or video from the dropdown box.")
                    st.divider()

                    # Step 4
                    st.write(":four: :blue[**Upload Your File:**]")
                    st.write("Use the file uploader to select the file from your local machine.")
                    st.divider()

                    st.write("Explore and have fun with real-time object detection! :green_heart:")

                    st.divider()

    if uploaded_file:
        if source_selectbox == config.SOURCES_LIST[0]:  # Image
            infer_uploaded_image(confidence, model, uploaded_file)
        elif source_selectbox == config.SOURCES_LIST[1]:  # Video
            infer_uploaded_video(confidence, model, uploaded_file)


import abc

from django.core.paginator import Paginator
from rest_framework.views import APIView
import rest_framework.renderers

from ..util.cache import ObjectCache
import halld.renderers
from .. import get_halld_config

class HALLDView(APIView, metaclass=abc.ABCMeta):
    renderer_classes = (
        rest_framework.renderers.TemplateHTMLRenderer,
        halld.renderers.HALJSONRenderer,
        halld.renderers.JSONLDRenderer,
    )

    def initial(self, request, *args, **kwargs):
        super().initial(request, *args, **kwargs)

        request.object_cache = ObjectCache(request.user)
        self.halld_config = get_halld_config()

    def get_paginator_and_page(self, objects):
        paginator = Paginator(objects, 100)
        try:
            page_num = int(self.request.GET.get('page'))
        except:
            page_num = 1
        return paginator, paginator.page(page_num)


# -*- coding: utf-8 -*-
from flask_json import json_response
from werkzeug.debug import get_current_traceback

from status_code_enum import StatusCodeEnum

class ErrorHandler(object):
    @classmethod
    def register(cls, app):
        exception_codes = list(
            map(
                lambda c: c,
                range(
                    StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR,
                    StatusCodeEnum.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED,
                ),
            )
        )
        [
            app.register_error_handler(code, ErrorHandler.handler)
            for code in exception_codes
        ]

    @staticmethod
    def handler(error):
        traceback = get_current_traceback(
            skip=1, show_hidden_frames=True, ignore_system_exceptions=True
        )
        return json_response(
            status_=StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR,
            exception={
                "message": "{} {}".format(traceback.exception, error.message),
                "type": traceback.exception_type,
                "description": traceback.plaintext,
            },
        )


from typing import NamedTuple
import unittest.mock as mock

import pytest

from pyunits.exceptions import UnitError
from pyunits.unit_type import UnitType, CastHandler
from pyunits.exceptions import CastError
from .helpers import MyType, MyStandardUnit, MyUnit, MyOtherType

class _OtherType(UnitType):
    """
    A dummy unit type to use for testing.
    """
    pass

class TestUnitType:
    """
    Tests for the unit_type class.
    """

    @classmethod
    @pytest.fixture
    def wrapped_unit(cls) -> MyType:
        """
        Wraps a unit class in our custom type decorator, to simulate the
        decorator being applied.
        :return: The wrapped unit class.
        """
        MyType.clear_interning_cache()
        return MyType.decorate(MyUnit)

    def test_wrapping(self, wrapped_unit: MyType) -> None:
        """
        Tests that it properly decorates a unit class.
        :param wrapped_unit: The decorated unit class.
        """
        # Arrange done in fixture.
        # Act.
        my_unit = wrapped_unit(10)

        # Assert.
        # The unit type should be correct.
        assert my_unit.type == wrapped_unit

    def test_wrapping_standard(self) -> None:
        """
        Tests that wrapping a standard unit works under normal conditions.
        """
        # Arrange.
        MyType.clear_interning_cache()
        # Make it look like we have no standard unit for this type.
        MyType._STANDARD_UNIT_CLASS = None

        # Act.
        # Perform the decoration.
        wrapped = MyType.decorate(MyStandardUnit)

        # Assert.
        # It should have set the standard unit.
        assert wrapped.standard_unit_class() == wrapped

    def test_wrapping_standard_twice(self) -> None:
        """
        Tests that it fails if we try to specify multiple standard units for a
        single UnitType.
        """
        # Arrange.
        MyType.clear_interning_cache()
        # Make it look like we have no standard unit for this type.
        MyType._STANDARD_UNIT_CLASS = None

        # Specify a standard unit.
        MyType.decorate(MyStandardUnit)

        # Act and assert.
        # Trying to specify another one should raise an exception.
        with pytest.raises(UnitError, match="already has standard"):
            MyType.decorate(MyStandardUnit)

    def test_as_type(self, wrapped_unit: MyType) -> None:
        """
        Tests that we can properly perform a cast using as_type().
        :param wrapped_unit: The decorated unit class.
        """
        # Arrange.
        # Create a new fake UnitType.
        other_type = mock.MagicMock()
        # Give it a name for easier debugging.
        other_type.__name__ = "OtherType"
        # A fake handler.
        handler = mock.Mock()

        # Register a cast for it.
        wrapped_unit.register_cast(other_type, handler)

        # A fake unit to convert.
        to_convert = MyUnit(wrapped_unit, 10)

        # Act.
        converted = wrapped_unit.as_type(to_convert, other_type)

        # Assert.
        # It should have called the handler.
        handler.assert_called_once_with(to_convert)
        assert converted == handler.return_value

    def test_as_type_invalid_cast(self, wrapped_unit: MyType) -> None:
        """
        Tests that as_type() will refuse to perform an invalid cast.
        :param wrapped_unit: The decorated unit class.
        """
        # Arrange.
        # Create a new fake UnitType.
        other_type = mock.MagicMock()
        # Give it a name for easier debugging.
        other_type.__name__ = "OtherType"

        # A fake unit to convert.
        to_convert = MyUnit(wrapped_unit, 10)

        # Act and assert.
        # Conversion should fail since no cast is registered.
        with pytest.raises(CastError):
            wrapped_unit.as_type(to_convert, other_type)

    def test_standard_unit_class_not_set(self) -> None:
        """
        Tests that getting the standard unit class fails when none was set.
        """
        # Arrange.
        MyType.clear_interning_cache()
        # Make it look like we have no standard unit for this type.
        MyType._STANDARD_UNIT_CLASS = None

        # Create a new instance.
        my_type = MyType.decorate(MyUnit)

        # Act and assert.
        with pytest.raises(UnitError, match="no standard"):
            my_type.standard_unit_class()

    def test_is_compatible(self, wrapped_unit: MyType) -> None:
        """
        Tests that is_compatible works under normal conditions.
        :param wrapped_unit: The decorated Unit class.
        """
        # Arrange.
        fake_unit_class = mock.Mock(spec=MyUnit)
        fake_unit_class.is_standard.return_value = False

        # Create an instance of another UnitType.
        other_type = MyOtherType.decorate(fake_unit_class)

        # Create another instance of the same unit type.
        same_type = MyType.decorate(fake_unit_class)

        # Act.
        compatible_with_other = wrapped_unit.is_compatible(other_type)
        compatible_with_same = wrapped_unit.is_compatible(same_type)

        # Assert.
        # It should not be compatible with the other type.
        assert not compatible_with_other
        # It should be compatible with the same type.
        assert compatible_with_same

    class TestCastHandler:
        """
        Tests for the CastHandler class.
        """

        class HandlerConfig(NamedTuple):
            """
            Configuration for tests.
            :param handler: The wrapped handler function under test.
            :param mock_function: The mocked function that we are wrapping.
            :param wrapper_class: The wrapping instance of CastHandler.
            :param mock_from_unit: The mocked Unit class that we are converting
            from.
            :param mock_to_unit: The mocked Unit class that we are converting
            to.
            """
            handler: CastHandler.WrappedHandler
            mock_function: mock.Mock
            wrapper_class: CastHandler
            mock_from_unit: mock.Mock
            mock_to_unit: mock.Mock

        @classmethod
        @pytest.fixture
        def config(cls) -> HandlerConfig:
            """
            Generates configuration for tests,
            :return: The HandlerConfig that it created.
            """
            MyType.clear_interning_cache()
            MyOtherType.clear_interning_cache()

            # Create the function to wrap.
            mock_function = mock.Mock()

            # Create fake unit classes.
            mock_from_unit = mock.MagicMock(spec=MyType.decorate(MyUnit))
            mock_from_unit.__name__ = "MockFromUnit"
            mock_to_unit = mock.MagicMock(spec=MyOtherType.decorate(MyUnit))
            mock_to_unit.__name__ = "MockToUnit"

            # Make it look like the two units are not compatible.
            mock_to_unit.is_compatible.return_value = False
            mock_from_unit.is_compatible.return_value = False

            # Create the wrapper instance.
            wrapper_class = CastHandler(mock_from_unit, mock_to_unit)
            # Wrap the function.
            wrapped_handler = wrapper_class(mock_function)

            return cls.HandlerConfig(handler=wrapped_handler,
                                     mock_function=mock_function,
                                     wrapper_class=wrapper_class,
                                     mock_from_unit=mock_from_unit,
                                     mock_to_unit=mock_to_unit)

        def test_init(self, config: HandlerConfig) -> None:
            """
            Tests that initializing the wrapper works correctly.
            :param config: The HandlerConfig to use for this test.
            """
            # Arrange and act done by fixture.
            # Assert.
            # It should have registered the cast.
            config.mock_from_unit.register_cast.assert_called_once_with(
                config.mock_to_unit.__class__, mock.ANY
            )

        def test_init_same_type(self, config: HandlerConfig) -> None:
            """
            Tests that trying to cast to the input type causes an error.
            :param config: The HandlerConfig to use for this test.
            """
            # Arrange.
            # Make it look like both units are the same type.
            config.mock_from_unit.is_compatible.return_value = True
            config.mock_to_unit.is_compatible.return_value = True

            # Act and assert.
            # Creating the wrapper should fail when both units are the same
            # type.
            with pytest.raises(CastError):
                CastHandler(config.mock_from_unit, config.mock_to_unit)

        def test_wrapped_call(self, config: HandlerConfig) -> None:
            """
            Tests that calling the wrapped handler function works as expected.
            :param config: The HandlerConfig to use for this test.
            """
            # Arrange.
            # Create a mock Unit to convert.
            mock_unit = mock.Mock(spec=MyUnit)

            # Act.
            # Try converting it.
            converted = config.handler(mock_unit)

            # Assert.
            # It should have made sure all the units were correct.
            config.mock_from_unit.assert_called_once_with(mock_unit)

            input_unit = config.mock_from_unit.return_value
            config.mock_function.assert_called_once_with(input_unit)

            raw_output = config.mock_function.return_value
            config.mock_to_unit.assert_called_once_with(raw_output)

            assert converted == config.mock_to_unit.return_value


import datetime as dt
from io import StringIO
from unittest import TestCase

import pandas as pd
import requests
from htimeseries import HTimeseries

from enhydris_api_client import EnhydrisApiClient

from . import (
    mock_session,
    test_timeseries_csv,
    test_timeseries_csv_bottom,
    test_timeseries_hts,
)

@mock_session(**{"get.return_value.text": test_timeseries_csv})
class ReadTsDataTestCase(TestCase):
    url = "http://example.com/api/stations/41/timeseriesgroups/42/timeseries/43/data/"

    def _read_tsdata(self, **extra_args):
        self.client = EnhydrisApiClient("http://example.com")
        return self.client.read_tsdata(41, 42, 43, **extra_args)

    def test_makes_request(self, m):
        self._read_tsdata()
        m.return_value.get.assert_called_once_with(
            self.url,
            params={
                "fmt": "hts",
                "start_date": None,
                "end_date": None,
                "timezone": "UTC",
            },
        )

    def test_returns_data(self, m):
        ahts = self._read_tsdata()
        pd.testing.assert_frame_equal(ahts.data, test_timeseries_hts.data)

    def test_uses_timezone(self, m):
        self._read_tsdata(timezone="UTC")
        m.return_value.get.assert_called_once_with(
            self.url,
            params={
                "fmt": "hts",
                "start_date": None,
                "end_date": None,
                "timezone": "UTC",
            },
        )

class ReadTsDataWithStartAndEndDateTestCase(TestCase):
    @mock_session(**{"get.return_value.text": test_timeseries_csv})
    def setUp(self, mock_requests_session):
        self.mock_requests_session = mock_requests_session
        self.client = EnhydrisApiClient("https://mydomain.com")

    def _make_request(self, start_tzinfo, end_tzinfo):
        self.data = self.client.read_tsdata(
            41,
            42,
            43,
            start_date=dt.datetime(2019, 6, 12, 0, 0, tzinfo=start_tzinfo),
            end_date=dt.datetime(2019, 6, 13, 15, 25, tzinfo=end_tzinfo),
        )

    def test_makes_request(self):
        self._make_request(dt.timezone.utc, dt.timezone.utc)
        self.mock_requests_session.return_value.get.assert_called_once_with(
            "https://mydomain.com/api/stations/41/timeseriesgroups/42/timeseries/43/"
            "data/",
            params={
                "fmt": "hts",
                "start_date": "2019-06-12T00:00:00",
                "end_date": "2019-06-13T15:25:00",
                "timezone": "UTC",
            },
        )

    def test_returns_data(self):
        self._make_request(dt.timezone.utc, dt.timezone.utc)
        pd.testing.assert_frame_equal(self.data.data, test_timeseries_hts.data)

    def test_checks_that_start_date_is_aware(self):
        with self.assertRaises(ValueError):
            self._make_request(None, dt.timezone.utc)

    def test_checks_that_end_date_is_aware(self):
        with self.assertRaises(ValueError):
            self._make_request(dt.timezone.utc, None)

class ReadEmptyTsDataTestCase(TestCase):
    @mock_session(**{"get.return_value.text": ""})
    def test_returns_data(self, mock_requests_session):
        self.client = EnhydrisApiClient("https://mydomain.com")
        self.data = self.client.read_tsdata(41, 42, 43)
        pd.testing.assert_frame_equal(self.data.data, HTimeseries().data)

class ReadTsDataErrorTestCase(TestCase):
    @mock_session(**{"get.return_value.status_code": 404})
    def test_raises_exception_on_error(self, mock_requests_session):
        self.client = EnhydrisApiClient("https://mydomain.com")
        with self.assertRaises(requests.HTTPError):
            self.client.read_tsdata(41, 42, 43)

class PostTsDataTestCase(TestCase):
    @mock_session()
    def test_makes_request(self, mock_requests_session):
        client = EnhydrisApiClient("https://mydomain.com")
        if hasattr(test_timeseries_hts, "timezone"):
            del test_timeseries_hts.timezone
        client.post_tsdata(41, 42, 43, test_timeseries_hts)
        f = StringIO()
        test_timeseries_hts.data.to_csv(f, header=False)
        mock_requests_session.return_value.post.assert_called_once_with(
            "https://mydomain.com/api/stations/41/timeseriesgroups/42/timeseries/43/"
            "data/",
            data={"timeseries_records": f.getvalue(), "timezone": "UTC"},
        )

    @mock_session(**{"post.return_value.status_code": 404})
    def test_raises_exception_on_error(self, mock_requests_session):
        client = EnhydrisApiClient("https://mydomain.com")
        with self.assertRaises(requests.HTTPError):
            client.post_tsdata(41, 42, 43, test_timeseries_hts)

@mock_session(**{"get.return_value.text": test_timeseries_csv_bottom})
class GetTsEndDateTestCase(TestCase):
    url = "http://mydom.com/api/stations/41/timeseriesgroups/42/timeseries/43/bottom/"

    def _get_ts_end_date(self, **extra_args):
        self.client = EnhydrisApiClient("http://mydom.com")
        return self.client.get_ts_end_date(41, 42, 43, **extra_args)

    def test_makes_request(self, m):
        self._get_ts_end_date()
        m.return_value.get.assert_called_once_with(self.url, params={"timezone": "UTC"})

    def test_returns_date(self, m):
        result = self._get_ts_end_date()
        self.assertEqual(result, dt.datetime(2014, 1, 5, 8, 0))

    def test_uses_timezone(self, m):
        self._get_ts_end_date(timezone="Etc/GMT-2")
        m.return_value.get.assert_called_once_with(
            self.url, params={"timezone": "Etc/GMT-2"}
        )

class GetTsEndDateErrorTestCase(TestCase):
    @mock_session(**{"get.return_value.status_code": 404})
    def test_checks_response_code(self, mock_requests_session):
        client = EnhydrisApiClient("https://mydomain.com")
        with self.assertRaises(requests.HTTPError):
            client.get_ts_end_date(41, 42, 43)

class GetTsEndDateEmptyTestCase(TestCase):
    @mock_session(**{"get.return_value.text": ""})
    def test_returns_date(self, mock_requests_session):
        client = EnhydrisApiClient("https://mydomain.com")
        date = client.get_ts_end_date(41, 42, 43)
        self.assertIsNone(date)


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

"""
import dask.array as da
import dask.dataframe as dd

from ..data_hasher import DataHasher

class DaskDataHasher(DataHasher):

    def _iter_data(self, data):
        if isinstance(data, dd.DataFrame):
            yield from self._iter_dask_dataframe(data)
        elif isinstance(data, dd.Series):
            yield from self._iter_dask_dataframe(data.to_frame())
        elif isinstance(data, da.Array):
            yield from self._iter_dask_array(data)
        else:
            yield from super()._iter_data(data)

    @staticmethod
    def _iter_dask_dataframe(df):
        yield ','.join(map(str, df.columns.tolist())).encode('utf-8')

        # x = df.map_partitions(DataHasher._hash_pd_dataframe, meta=(None, 'u8')).compute()
        name = 'hashed'
        x = df.map_partitions(lambda part: DataHasher._hash_pd_dataframe(part).to_frame(name),
                              meta={name: 'u8'}).compute()
        yield x.values

    @staticmethod
    def _iter_dask_array(arr):
        if len(arr.shape) == 1:
            arr = arr.compute_chunk_sizes().reshape(-1, 1)
        x = arr.map_blocks(DataHasher._hash_ndarray, dtype='u8').compute()
        yield x


from itertools import combinations
groups = [[1,5],[2,7],[4,8],[3,6]]

def solution(n, groups):
    num = []
    cob = []
    answer = 0
    minnum = 10

    for i in range(len(groups)):
        num.append(i)

    for i in range(1, len(groups) + 1):
        cob.append(list(combinations(num,i)))

    for i in range(len(cob)):
        for j in range(len(cob[i])):
            lights = [0 for i in range(10)]
            for k in range(len(cob[i][j])):
                start = groups[cob[i][j][k]][0]
                end = groups[cob[i][j][k]][1]

                for l in range(start-1, end):
                    lights[l] = 1

                if minnum > lights.count(1):
                    minnum = lights.count(1)

    return answer

solution(10,groups)


from __future__ import division
import cv2
import numpy as np

def findObjects(img):
  # convert img to hsv
  hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

  # find the lower and upper values for the green color in the mask
  puregreen = np.uint8([[[0,255,0]]])
  hsv_green = cv2.cvtColor(puregreen, cv2.COLOR_BGR2HSV)
  lower_green = [hsv_green[0,0,0] - 30, 45, 45]
  upper_green = [hsv_green[0,0,0] + 30, 255, 255]
  # get mask
  green_mask = cv2.inRange(hsv, np.array(lower_green), np.array(upper_green))

  # extract hue, value and saturation
  h = hsv[:,:,0]/255.0
  v = hsv[:,:,1]/255.0
  s = hsv[:,:,2]/255.0

  # parameters for green color
  T1, T2, T3 = 0.2, 0.75, 0.2
  # find the specified greens
  green = ((abs(h - 0.33) < T1) & (v < T2) & (s > T3)).astype(float)

  # apply mask
  masked = cv2.bitwise_and(green,green,mask=green_mask)

  # erode image
  eroded = cv2.erode(masked, np.ones((15,15)))

  # dilate image
  result = cv2.dilate(eroded, np.ones((20, 20)))

  # set hue, value and saturation to the found values
  # when we do this the image is effectively a rgb img not hsv, and it is greyscaled (actually just black and white)
  # it is however not in the greyscale format (Dx, Dy) but rgb/hsv format (Dx, Dy, 3)
  hsv[:,:,0] = result*255.0
  hsv[:,:,1] = result*255.0
  hsv[:,:,2] = result*255.0

  return hsv

def findRectangles(img):
  def detectRectangle(cntAppr):
    (b_x, b_y, b_w, b_h) = cv2.boundingRect(cntAppr)

    aspect_ratio = b_w / b_h;
    # if aspect ratio is appr 1 shape is square (and we're looking for rects)
    if aspect_ratio >= 0.95 and aspect_ratio <= 1.05:
      return False

    b_area = b_w*b_h
    # if the contour area fills over around 60% of the bounding rect it is probably a weird-shaped-but-still-rectangle
    if b_area - cv2.contourArea(cntAppr) < b_area * 0.4:
      return True

    elif len(cntAppr) != 4:
      return False
    return True

  # convert img to grayscale
  # we know that this img is black and white already, so no need to threshold before
  # we do however need to convert to grayscale because the format is different
  gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
  # find contours in image
  contours, hierarchy = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

  validRectContours = []
  contourAreas = []
  # remove contours that are not rectangle-ish shaped
  for i in range(len(contours)):
    # instead of using the real contour we use an approximation with much fewer points
    # number of points in approximation is 4 if the shape is rect-shaped
    contours[i] = cv2.approxPolyDP(contours[i], 0.05*cv2.arcLength(contours[i], True), True)
    if (detectRectangle(contours[i])):
      validRectContours.append(contours[i])
      # store area to use in average contour size
      contourAreas.append(cv2.contourArea(contours[i]))

  if len(validRectContours) == 0:
    # No valid contours found
    return [], None

  validContours = []
  # Remove the found contours that are smaller than 1/7 of the largest contour found
  biggestObject = validRectContours[0]
  maxArea = max(contourAreas)
  for i in range(len(contourAreas)):
    if maxArea - contourAreas[i] < maxArea * 0.7:
      validContours.append(validRectContours[i])
    if maxArea == contourAreas[i]:
      biggestObject = validRectContours[i]

  return validContours, biggestObject


import gym

from baselines.cbdqn import basic
from baselines import logger

def callback(lcl, _glb):
    # stop training if reward exceeds 199
    is_solved = lcl['t'] > 100 and sum(lcl['episode_rewards'][-101:-1]) / 100 >= 199
    return is_solved

def main():
    logger.configure("./log/xp2")
    env = gym.make("CartPole-v0")
    nbins = 10
    model = basic.models.mlp(nbins,[64])
    act = basic.learn(
        env,
        q_func=model,
        lr=1e-3,
        max_timesteps=100000,
        buffer_size=50000,
        exploration_fraction=0.1,
        exploration_final_eps=0.02,
        print_freq=10,
        callback=callback,
        qmin = -20,
        qmax = 20,
        nbins=nbins
        )
    print("Saving model to cartpole_model.pkl")
    act.save("cartpole_model.pkl")

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
from jinja2 import Template
import sys

from config import env, run_path, root_path

def docker_setup() -> None:
    with env.prefixed('P2PMARKET_'):
        api_endpoint = env('API_ENDPOINT')
    assert api_endpoint, 'P2PMARKET_API_ENDPOINT needs to be set in main.env'
    with open(root_path/'docker-compose.jinja') as f:
        template = Template(f.read())
    with open(root_path/'docker-compose.yaml', 'w') as f:
        f.write(template.render(
            run_dir=run_path,
            api_endpoint=api_endpoint
        ))

def main() -> int:
    docker_setup()
    return 0

if __name__=="__main__":
    sys.exit(main())


import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px

st.title("Analyse Ventes")

df = pd.read_csv("Sales Data.csv",index_col="Order ID")
del df["Unnamed: 0"]

## --Sidebar--

st.sidebar.header("Filtres")
city = st.sidebar.multiselect(
	"Selectionner la ville",
	options=df["City"].unique(),
	default=df["City"].unique())

product = st.sidebar.selectbox(
	"Selectionner le produit",
	options=df["Product"].unique())

df_selection = df.query(
	"City == @city & Product == @product")

## --KPI--
total_sales = int(df_selection["Sales"].sum())
average_sale_by_transaction = round(df_selection["Sales"].mean(), 2)

#st.dataframe(df_selection)
st.markdown("""Key Metrics""")

kpi1, kpi2 = st.columns(2)

kpi1.metric(label=f"Ventes Totales de {product}",
			value=total_sales,
			delta=None)

kpi2.metric(label="Ventes moyennes par transaction",
			value=average_sale_by_transaction,
			delta=None)

## --Sales par heures--
sales_by_hour = df_selection.groupby(by="Hour").sum()["Sales"]
st.write(sales_by_hour)
fig_heure_vente= px.bar(
	sales_by_hour,
	x=sales_by_hour,
	y="Sales",
	title="<b>Ventes par heure</b>",
	)

#st.plotly_chart(fig_heure_vente)


# coding: utf-8
# Импортирует поддержку UTF-8.
from __future__ import unicode_literals

import string
# Импортируем модули для работы с JSON и логами.
import json
import logging

# Импортируем подмодули Flask для запуска веб-сервиса.
from flask import Flask, request, render_template
from flask_pymongo import PyMongo

# Импортируем функции из handlers.py
from handlers import dialog_handler

app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://localhost:27017/student_helper"
mongo = PyMongo(app)

logging.basicConfig(level=logging.DEBUG)

@app.route('/add-new-poem', methods=['POST', 'GET'])
def new_poem():
    if request.method == 'POST':
        author = request.form.get('author')
        name = request.form.get('name')
        lines = [line for line in request.form.get('user_text').split('\n') if line != '\n']
        text = []
        for ln in lines:
            words = [word.lower().strip(string.punctuation).strip("«»?!,.-—:;.,;()_+") for word in ln.split() if word != '']
            text.append(words)
        poem = {
            "author": author,
            "name": name,
            "text": text
        }
        poem_id = mongo.db.poems.insert_one(poem).inserted_id
        logging.info(text)
    return render_template("add-new-poem.html")

@app.route('/', methods=['POST'])
def main():
    # Функция получает тело запроса и возвращает ответ.
    logging.info('Request: %r', request.json)

    response = {
        "version": request.json['version'],
        "session": request.json['session'],
        "response": {
            "end_session": False
        }
    }

    dialog_handler(request.json, response)

    logging.info('Response: %r', response)

    return json.dumps(
        response,
        ensure_ascii=False,
        indent=2
    )

if __name__ == '__main__':
    app.run(debug=True, port=5000)


from sys import exit
from distutils.core import setup, Extension
from setuptools.command.test import test as TestCommand
from os.path import realpath, dirname, join as path_join
from sys import argv as sys_argv

mod_name = 'LossyQueue'
mod_name_dbg = mod_name + '_debug'

mod_dir = dirname(realpath(sys_argv[0]))
src_dir = '../src/'

compile_args = [f'-I{src_dir}', '-flto']
link_args = ['-flto', '-Wl,--version-script=symbols.map']
debug_cflags = ['-g3', '-O0', '-DDEBUG_MOD']
mod_common_args = {
    'sources': ['LossyQueue_mod.c', src_dir + 'SPMCQueue.c'],
    'extra_compile_args': compile_args,
    'extra_link_args': link_args
}
mod_debug_args = mod_common_args.copy()
mod_debug_args['extra_compile_args'] = mod_debug_args['extra_compile_args'] + debug_cflags

module1 = Extension(mod_name, **mod_common_args)
module2 = Extension(mod_name_dbg, **mod_debug_args)

class PyTest(TestCommand):
    user_options = [('pytest-args=', 'a', "Arguments to pass to pytest")]

    def initialize_options(self):
        TestCommand.initialize_options(self)
        self.pytest_args = []

    def run_tests(self):
        import pytest
        errno = pytest.main(self.pytest_args)
        exit(errno)

setup (name = 'SPMCQueue',
       version = '1.0',
       description = 'This is a package for LossyQueue module',
       ext_modules = [module1, module2],
       tests_require=['pytest'],
       cmdclass={'test': PyTest},
)


import urllib
import json
import requests
count=1
req=requests.get("http://meme-api.herokuapp.com/gimme")
json_data = json.loads(req.text)
imgs="memes-"+str(count)+".jpg"
print(imgs)
urllib.urlretrieve(json_data["url"],imgs)
print(imgs + "is saved")


from asyncio import get_event_loop, set_event_loop_policy, sleep

import uvloop
from simple_amqp import AmqpParameters

from simple_amqp_rpc import Service
from simple_amqp_rpc.asyncio import AsyncioAmqpRpc

set_event_loop_policy(uvloop.EventLoopPolicy())

class PingService:
    svc = Service('ping')

    @svc.rpc
    async def ping(self, name: str):
        return 'pong: {}'.format(name)

rpc_conn = AsyncioAmqpRpc(
    params=AmqpParameters(),
    route='ping',
)

ping_service = PingService()
rpc_conn \
    .add_svc(ping_service.svc, ping_service)

rpc_conn.configure()

loop = get_event_loop()

async def main():
    await rpc_conn.start()

    while True:
        await sleep(1)

loop.run_until_complete(main())


import json
import os
import subprocess
import time
import uuid

from zope.interface import implementer

from framework.base.internal_msgQ import InternalMsgQ
from framework.base.module_thread import SensorThread
from framework.base.sspl_constants import COMMON_CONFIGS, DATA_PATH
from framework.utils.conf_utils import (GLOBAL_CONF, SSPL_CONF, Conf,
    NODE_ID_KEY)
from framework.utils.service_logging import logger
from framework.utils.severity_reader import SeverityReader
from framework.utils.os_utils import OSUtils
# Modules that receive messages from this module
from message_handlers.node_data_msg_handler import NodeDataMsgHandler
from sensors.Iraid import IRAIDsensor
from framework.utils.store_factory import file_store

# Override default store
store = file_store

@implementer(IRAIDsensor)
class RAIDsensor(SensorThread, InternalMsgQ):

    SENSOR_NAME       = "RAIDsensor"
    PRIORITY          = 1
    RESOURCE_TYPE     = "node:os:raid_data"

    # Section and keys in configuration file
    RAIDSENSOR        = SENSOR_NAME.upper()
    RAID_STATUS_FILE  = 'RAID_status_file'

    RAID_CONF_FILE    = '/etc/mdadm.conf'
    RAID_DOWN_DRIVE_STATUS = [ { "status" : "Down/Missing" }, { "status" : "Down/Missing" } ]

    SYSTEM_INFORMATION = "SYSTEM_INFORMATION"

    prev_alert_type = {}
    alert_type = None

    # alerts
    FAULT_RESOLVED = "fault_resolved"
    FAULT = "fault"
    MISSING = "missing"
    INSERTION = "insertion"

    CACHE_DIR_NAME  = "server"

    # Dependency list
    DEPENDENCIES = {
                    "init": ["DiskMonitor"],
    }

    @staticmethod
    def name():
        """@return: name of the monitoring module."""
        return RAIDsensor.SENSOR_NAME

    @staticmethod
    def impact():
        """Returns impact of the module."""
        return "Server RAID disks can not be monitored."

    def __init__(self):
        super(RAIDsensor, self).__init__(self.SENSOR_NAME,
                                         self.PRIORITY)
        # Current RAID status information
        self._RAID_status = None

        # Location of hpi data directory populated by dcs-collector
        self._start_delay  = 10

        # Flag to indicate suspension of module
        self._suspended = False
        self.os_utils = OSUtils()

    def initialize(self, conf_reader, msgQlist, product):
        """initialize configuration reader and internal msg queues"""

        # Initialize ScheduledMonitorThread and InternalMsgQ
        super(RAIDsensor, self).initialize(conf_reader)

        # Initialize internal message queues for this module
        super(RAIDsensor, self).initialize_msgQ(msgQlist)

        self._RAID_status_file = self._get_RAID_status_file()
        logger.info(f"Monitoring RAID status file: {self._RAID_status_file}")

        # The status file contents
        self._RAID_status_contents = "N/A"

        # The mdX status line in the status file
        self._RAID_status = {}

        self._faulty_drive_list = {}

        self._faulty_device_list = set()

        self._drives = {}

        self._total_drives = {}

        self._devices = []

        self._missing_drv = {}

        self._prev_drive_dict = {}

        self.prev_alert_type = {}
        self._node_id = Conf.get(GLOBAL_CONF, NODE_ID_KEY,'SN01')

        # Allow systemd to process all the drives so we can map device name to serial numbers
        #time.sleep(120)

        cache_dir_path = os.path.join(DATA_PATH, self.CACHE_DIR_NAME)
        self.RAID_SENSOR_DATA_PATH = os.path.join(cache_dir_path,
                                        f'RAID_SENSOR_DATA_{self._node_id}')
        # Get the stored previous alert info
        self.persistent_raid_data = {}
        if os.path.isfile(self.RAID_SENSOR_DATA_PATH):
            self.persistent_raid_data = store.get(self.RAID_SENSOR_DATA_PATH)
        if self.persistent_raid_data:
            self._RAID_status_contents = self.persistent_raid_data['_RAID_status_contents']
            self._RAID_status = self.persistent_raid_data['_RAID_status']
            self._faulty_drive_list = self.persistent_raid_data['_faulty_drive_list']
            self._faulty_device_list = self.persistent_raid_data['_faulty_device_list']
            self._drives = self.persistent_raid_data['_drives']
            self._total_drives = self.persistent_raid_data['_total_drives']
            self._devices = self.persistent_raid_data['_devices']
            self._missing_drv = self.persistent_raid_data['_missing_drv']
            self._prev_drive_dict = self.persistent_raid_data['_prev_drive_dict']
            self.prev_alert_type = self.persistent_raid_data['prev_alert_type']
        else:
            self.persistent_raid_data = {
                '_RAID_status_contents' : self._RAID_status_contents,
                '_RAID_status' : self._RAID_status,
                '_faulty_drive_list' : self._faulty_drive_list,
                '_faulty_device_list' : self._faulty_device_list,
                '_drives' : self._drives,
                '_total_drives' : self._total_drives,
                '_devices' : self._devices,
                '_missing_drv' : self._missing_drv,
                '_prev_drive_dict' : self._prev_drive_dict,
                'prev_alert_type' : self.prev_alert_type,
            }
            store.put(self.persistent_raid_data, self.RAID_SENSOR_DATA_PATH)

        return True

    def read_data(self):
        """Return the Current RAID status information"""
        return self._RAID_status

    def run(self):
        """Run the sensor on its own thread"""

        # Do not proceed if module is suspended
        if self._suspended == True:
            self._scheduler.enter(30, self._priority, self.run, ())
            return

        # Check for debug mode being activated
        self._read_my_msgQ_noWait()

        # self._set_debug(True)
        # self._set_debug_persist(True)

        # Check for a change in status file and notify the node data msg handler
        self._notify_NodeDataMsgHandler()

        # Reset debug mode if persistence is not enabled
        self._disable_debug_if_persist_false()

        # Fire every 30 seconds to see if there's a change in RAID status file
        self._scheduler.enter(30, self._priority, self.run, ())

    def _notify_NodeDataMsgHandler(self):
        """See if the status files changed and notify node data message handler
            for generating JSON message"""
        self._drive_state_changed = False
        # resource_id for drive alerts
        resource_id = None
        if not os.path.isfile(self._RAID_status_file):
            logger.warn(f"status_file: {self._RAID_status_file} does not exist, ignoring.")
            return

        # Read in status and see if it has changed
        with open(self._RAID_status_file, "r") as datafile:
            status = datafile.read()

        # Do nothing if the RAID status file has not changed
        if self._RAID_status_contents == status:
            self._log_debug(f"_notify_NodeDataMsgHandler status unchanged, ignoring: {status}")
            return

        # Update the RAID status contents of file
        self._RAID_status_contents = status

        # Process mdstat file and send json msg to NodeDataMsgHandler
        md_device_list, drive_dict, drive_status_changed = self._process_mdstat()

        # checks mdadm conf file for missing raid array and send json message to NodeDataMsgHandler
        self._process_missing_md_devices(md_device_list, drive_dict)

        for device in md_device_list:
            if drive_dict:
                if len(drive_dict[device]) < self._total_drives[device] and \
                    device in self.prev_alert_type and self.prev_alert_type[device] != self.MISSING:
                    self.alert_type = self.MISSING
                    if device in self._prev_drive_dict:
                        missing_drive = set(self._prev_drive_dict[device]).difference(set(drive_dict[device]))
                        try:
                            missing_drive = "/dev/"+list(missing_drive)[0]
                        except IndexError:
                            missing_drive = "NA"
                    else:
                        missing_drive = "NA"
                    resource_id = device+":"+missing_drive
                    self._missing_drv = {"path": missing_drive, "serialNumber": "None"}
                    self._map_drive_status(device, drive_dict, "Missing")
                    self._drive_state_changed = True

                elif len(drive_dict[device]) >= self._total_drives[device] and \
                    device in self.prev_alert_type and self.prev_alert_type[device] == self.MISSING:
                    self.alert_type = self.INSERTION
                    resource_id = device+":/dev/"+drive_dict[device][0]
                    self._map_drive_status(device, drive_dict[device][0], "Down/Recovery")
                    self._drive_state_changed = True

                if self.alert_type is not None and self._drive_state_changed == True:
                    self._prev_drive_dict[device] = drive_dict[device]
                    self._send_json_msg(self.alert_type, resource_id, device, self._drives[device])

                if drive_status_changed[device]:
                    for drive in self._drives[device]:
                        if drive.get("identity") is not None:
                            drive_path = drive.get("identity").get("path")
                            drive_name = drive_path[5:]
                            resource_id = device+":/dev/"+drive_name
                            drive_status = drive.get("status")
                            if drive_status not in ["U", "UP"] and device in self._faulty_drive_list and \
                                drive_name not in self._faulty_drive_list[device] and \
                                self.prev_alert_type[device] != self.MISSING:
                                self.alert_type = self.FAULT
                                self._map_drive_status(device, drive_name, "Down")
                                self._drive_state_changed = True
                                self._faulty_drive_list[device][drive_name] = self.alert_type

                            elif drive_status in ["U", "UP", "Down/Recovery"] and device in self._faulty_drive_list and \
                                drive_name in self._faulty_drive_list[device]:
                                self.alert_type = self.FAULT_RESOLVED
                                self._map_drive_status(device, drive_name, "UP")
                                self._drive_state_changed = True
                                del self._faulty_drive_list[device][drive_name]

                            if self.alert_type is not None and self._drive_state_changed == True:
                                self._prev_drive_dict[device] = drive_dict[device]
                                self._send_json_msg(self.alert_type, resource_id, device, self._drives[device])

    def _process_mdstat(self):
        """Parse out status' and path info for each drive"""
        # Replace new line chars with spaces
        mdstat = self._RAID_status_contents.strip().split("\n")
        md_device_list = []
        drive_dict = {}
        monitored_device = mdstat
        drive_status_changed = {}
        self._devices.clear()
        # Array of optional identity json sections for drives in array
        self._identity = {}

        # Read in each line looking for a 'mdXXX' value
        md_line_parsed = False

        for line in monitored_device:
            # The line following the mdXXX : ... contains the [UU] status that we need
            if md_line_parsed is True:
                # Format is [x/y][UUUU____...]
                drive_status_changed[self._device] = self._parse_raid_status(line, self._device)
                # Reset in case their are multiple configs in file
                md_line_parsed = False

            # Break the  line apart into separate fields
            fields = line.split(" ")

            # Parse out status' and path info for each drive
            if "md" in fields[0]:
                self._device = f"/dev/{fields[0]}"
                self._devices.append(self._device)
                self._log_debug(f"md device found: {self._device}")
                md_device_list.append(self._device)
                drive_dict[self._device] = []
                if self._device not in self.prev_alert_type:
                    self.prev_alert_type[self._device] = None
                if self._device not in self._faulty_drive_list:
                    self._faulty_drive_list[self._device] = {}

                # Parse out raid drive paths if they're present
                self._identity[self._device] = {}
                for field in fields:
                    if "[" in field:
                        if field not in drive_dict[self._device]:
                            index = field.find("[")
                            drive_name = field[:index]
                            drive_dict[self._device].append(drive_name)
                        self._add_drive(field, self._device)
                md_line_parsed = True

        return md_device_list, drive_dict, drive_status_changed

    def _add_drive(self, field, device):
        """Adds a drive to the list"""
        first_bracket_index = field.find('[')

        # Parse out the drive path
        drive_path = f"/dev/{field[: first_bracket_index]}"

        # Parse out the drive index into [UU] status which is Device Role field
        detail_command = f"/usr/sbin/mdadm --examine {drive_path} | grep 'Device Role'"
        response, error = self._run_command(detail_command)

        if error:
            self._log_debug(f"_add_drive, Error retrieving drive index into status, example: [U_]: {str(error)}")
        try:
            drive_index = int(response.split(" ")[-1])
        except Exception as ae:
            self._log_debug(f"_add_drive, get drive_index error: {str(ae)}")
            return
        self._log_debug(f"_add_drive, drive index: {drive_index}, path: {drive_path}")

        # Create the json msg, serial number will be filled in by NodeDataMsgHandler
        identity_data = {
                        "path" : drive_path,
                        "serialNumber" : "None"
                        }
        self._identity[device][drive_index] = identity_data

    def _parse_raid_status(self, status_line, device):
        """Parses the status of each drive denoted by U & _
            for drive being Up or Down in raid
        """
        # Parse out x for total number of drives
        first_bracket_index = status_line.find('[')

        # If no '[' found, return
        if first_bracket_index == -1:
            return False

        self._total_drives[device] = int(status_line[first_bracket_index + 1])
        self._log_debug("_parse_raid_status, total_drives: %d" % self._total_drives[device])

        # Break the line apart into separate fields
        fields = status_line.split(" ")

        # The last field is the list of U & _
        status = fields[-1]
        self._log_debug("_parse_raid_status, status: %s, total drives: %d" %
                        (status, self._total_drives[device]))

        # Array of raid drives in json format based on schema
        self._drives[device] = []

        drive_index = 0
        while drive_index < self._total_drives[device]:
            # Create the json msg and append it to the list
            if self._identity.get(device).get(drive_index) is not None:
                path = self._identity.get(device).get(drive_index).get("path")
                drive_status_msg = {
                                 "status" : status[drive_index + 1],  # Move past '['
                                 "identity": {
                                    "path": path,
                                    "serialNumber": "None"
                                    }
                                }
            else:
               drive_status_msg = {"status" : status[drive_index + 1]}  # Move past '['

            self._log_debug(f"_parse_raid_status, drive_index: {drive_index}")
            self._log_debug(f"_parse_raid_status, drive_status_msg: {drive_status_msg}")
            self._drives[device].append(drive_status_msg)

            drive_index = drive_index + 1

        # See if the status line has changed, if not there's nothing to do
        if device in self._RAID_status and self._RAID_status[device] == status:
            self._log_debug(f"RAID status has not changed, ignoring: {status}")
            return False
        else:
            self._log_debug(f"RAID status has changed, old: {self._RAID_status}, new: {status}")
            self._RAID_status[device] = status

        return True

    def _process_missing_md_devices(self, md_device_list, drive_dict):
        """ checks the md raid configuration file, compares all it's
            entries with list of arrays from mdstat file and sends
            missing entry
        """

        if not os.path.isfile(self.RAID_CONF_FILE):
            logger.warn(f"_process_missing_md_devices, MDRaid configuration file {self.RAID_CONF_FILE} is missing")
            return

        conf_device_list = []
        with open(self.RAID_CONF_FILE, 'r') as raid_conf_file:
            raid_conf_data = raid_conf_file.read().strip().split("\n")
        for line in raid_conf_data:
            try:
                raid_conf_field = line.split(" ")
                if "#" not in raid_conf_field[0] and "ARRAY" in raid_conf_field[0] and \
                    "/md" in raid_conf_field[1]:
                    # Mapped the device i.e. /dev/md/1 and /dev/md1 will be the same device.
                    map_device = raid_conf_field[1].split('md/')
                    if len(map_device)>1:
                        conf_device_list.append(map_device[0]+'md'+map_device[1])
                    else:
                        conf_device_list.append(raid_conf_field[1])
            except Exception as ae:
                self._log_debug(f"_process_missing_md_devices, error retrieving raid entry    \
                 from {self.RAID_CONF_FILE} file: {str(ae)}")
                return

        # compare conf file raid array list with mdstat raid array list
        for device in conf_device_list:
            if device not in md_device_list and device not in self._faulty_device_list:
                # add that missing raid array entry into the list of raid devices
                self.alert_type = self.FAULT
                self._faulty_device_list.add(device)
                self._send_json_msg(self.alert_type, device, device, self.RAID_DOWN_DRIVE_STATUS)

            elif device in md_device_list and device in self._faulty_device_list:
                # add that missing raid array entry into the list of raid devices
                self.alert_type = self.FAULT_RESOLVED
                self._map_drive_status(device, drive_dict, "Down/Recovery")
                self._faulty_device_list.remove(device)
                self._send_json_msg(self.alert_type, device, device, self._drives[device])

    def _map_drive_status(self, device, drives, drv_status):
        for drv in self._drives[device]:
            if isinstance(drives, str):
                if drv["status"] not in ["U", "UP"] and drv["identity"]["path"] == '/dev/'+drives:
                    drv["status"] = drv_status
            else:
                for drive in drives[device]:
                    # Drive info is not available in missing case.
                    if drv_status == "Missing" and drv["status"] == "_":
                        drv["status"] = drv_status
                        drv["identity"] = self._missing_drv
                    elif drv["status"] not in ["U", "UP"] and drv["identity"]["path"] == '/dev/'+drive:
                        drv["status"] = drv_status

            if drv["status"] == "U":
                drv["status"] = "UP"

    def _send_json_msg(self, alert_type, resource_id, device, drives):
        """Transmit data to NodeDataMsgHandler to be processed and sent out"""

        epoch_time = str(int(time.time()))
        severity_reader = SeverityReader()
        severity = severity_reader.map_severity(alert_type)
        self._alert_id = self._get_alert_id(epoch_time)
        host_name = self.os_utils.get_fqdn()

        if alert_type == self.MISSING:
            description = "RAID array or drive from RAID array is missing."
        elif alert_type == self.FAULT:
            description = "RAID array or drive from RAID array is faulty."
        elif alert_type == self.INSERTION:
            description = "Inserted drive in RAID array."
        elif alert_type == self.FAULT_RESOLVED:
            description = "Fault for RAID array or RAID drive is resolved"
        else:
            description = "Raid array alert"

        info = {
                "resource_type": self.RESOURCE_TYPE,
                "resource_id": resource_id,
                "event_time": epoch_time,
                "description": description
               }
        specific_info = {
            "device": device,
            "drives": drives
                }

        internal_json_msg = json.dumps(
            {"sensor_request_type" : {
                "node_data": {
                    "status": "update",
                    "sensor_type" : "node:os:raid_data",
                    "host_id": host_name,
                    "alert_type": alert_type,
                    "alert_id": self._alert_id,
                    "severity": severity,
                    "info": info,
                    "specific_info": specific_info
                    }
                }
            })
        self.prev_alert_type[device] = alert_type
        self.alert_type = None

        # Send the event to node data message handler to generate json message and send out
        self._write_internal_msgQ(NodeDataMsgHandler.name(), internal_json_msg)
        # Save the state to Persistent Cache.
        self.persistent_raid_data = {
                '_RAID_status_contents' : self._RAID_status_contents,
                '_RAID_status' : self._RAID_status,
                '_faulty_drive_list' : self._faulty_drive_list,
                '_faulty_device_list' : self._faulty_device_list,
                '_drives' : self._drives,
                '_total_drives' : self._total_drives,
                '_devices' : self._devices,
                '_missing_drv' : self._missing_drv,
                '_prev_drive_dict' : self._prev_drive_dict,
                'prev_alert_type' : self.prev_alert_type,
            }
        store.put(self.persistent_raid_data, self.RAID_SENSOR_DATA_PATH)

    def _get_alert_id(self, epoch_time):
        """Returns alert id which is a combination of
        epoch_time and salt value
        """
        salt = str(uuid.uuid4().hex)
        alert_id = epoch_time + salt
        return alert_id
    def suspend(self):
        """Suspends the module thread. It should be non-blocking"""
        super(RAIDsensor, self).suspend()
        self._suspended = True

    def resume(self):
        """Resumes the module thread. It should be non-blocking"""
        super(RAIDsensor, self).resume()
        self._suspended = False

    def _run_command(self, command):
        """Run the command and get the response and error returned"""
        self._log_debug(f"_run_command: {command}")
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        response, error = process.communicate()

        if response:
            self._log_debug(f"_run_command, response: {str(response)}")
        if error:
            self._log_debug(f"_run_command: error: {str(error)}")

        return response.decode().rstrip('\n'), error.decode().rstrip('\n')

    def _get_RAID_status_file(self):
        """Retrieves the file containing the RAID status information"""
        return Conf.get(SSPL_CONF, f"{self.RAIDSENSOR}>{self.RAID_STATUS_FILE}",
                                                        '/proc/mdstat')
    def shutdown(self):
        """Clean up scheduler queue and gracefully shutdown thread"""
        super(RAIDsensor, self).shutdown()


from ete3 import Tree
import os
import sys

thedir = [f for f in os.listdir('.') if os.path.isfile(f)]

out = open('failed_tree_filter', 'w')

for thing in thedir:
	if '_AA.fasta.aligned.consensus.aliscore.NI' in thing:

		treefile = thing.split('_')[0] + '_fasttree.tre'

		cmd = './FastTree -wag ' + thing + ' > ' + treefile
		os.system(cmd)

		t = Tree(treefile)

		myleaves = []

		for leaf in t:
			myleaves.append(leaf.name)

		if 'jgi' in myleaves:
			t.set_outgroup ( t&"jgi" )
		elif 'PATELLO-Nacellidae-Cellana-tramoserica' in myleaves:
			t.set_outgroup ( t&"PATELLO-Nacellidae-Cellana-tramoserica" )
		elif 'PATELLO-Lottiidae-Cellana-tramosevica' in myleaves:
			t.set_outgroup ( t&"PATELLO-Lottiidae-Cellana-tramosevica" )
		else:
			l = [myleaves.index(i) for i in myleaves if 'VETI-' in i]
			t.set_outgroup ( t&myleaves[l[0]] )

		leaves = []
		leaves2 = []

		for leaf in t:
			if 'HETERO' in leaf.name:
				leaves2.append(leaf.name)
			elif 'CAENO' in leaf.name:
				if 'CAENO-Litiopidae-Phasianella-ventricosa' in leaf.name:
					continue
				elif 'CAENO-Turridae-Vexitomina-garrardi' in leaf.name:
					leaves2.append(leaf.name)
				else:
					leaves.append(leaf.name)
					leaves2.append(leaf.name)

#			if 'VETI' in leaf.name or 'CAENO-Litiopidae-Phasianella-ventricosa' in leaf.name:
#				leaves.append(leaf.name)
#			else:
#				continue

				#if 'CAENO-Turridae-Vexitomina-garrardi' in leaf.name or 'CAENO-Litiopidae-Phasianella-ventricosa' in leaf.name:
				#	continue
				#else:
				#	leaves.append(leaf.name)

		if t.check_monophyly(values=leaves, target_attr="name")[1] == 'monophyletic' or t.check_monophyly(values=leaves2, target_attr="name")[1] == 'monophyletic':
			continue
		else:
			out.write(thing + '\n')


import shutil
import os
import psutil
import time

dir = os.environ["APPDATA"] + "\\.tlauncher"
dir2 = os.environ["APPDATA"]+"\\Roaming"

def find_process_pid(process_name):
    for process in psutil.process_iter():
        if process.name() == process_name:
            return process.pid

def start():
    pid = find_process_pid("javaw.exe")
    if pid == None:
        os.startfile("TLauncher.exe")
        print("Запускаю лаунчер...")
        time.sleep(20)
        pid = find_process_pid("javaw.exe")
        print("Готово")
        print("Id процесса:"+ str(pid))
        delete(pid)
    else:
        print("Лаунчер уже запущен")
        print("Id процесса:"+ str(pid))
        delete(pid)

def delete(pid):
    exist = 1
    while exist == 1:
        if psutil.pid_exists(pid) == False:
            print("Майнкрафт закрыт!")
            exist = 0
    print("Удаление конфигов...")
    path = os.path.join(os.path.abspath(os.path.dirname(dir2)), '.tlauncher')
    shutil.rmtree(path)
    print("Готово")

try:
    print("Копирование конфигов...")
    shutil.copytree(r".tlauncher", dir)
    print("Готово")
    start()
except PermissionError:
    print("Вы Gay")
    print("Завершение работы")
except FileNotFoundError:
    print("Нет файла")
    print("Завершение работы")
except FileExistsError:
    print("Файл Существует")
    start()


from flask import request, jsonify
from mcsite import app, mongo

from bson.json_util import dumps
from bson.objectid import ObjectId

@app.route('/book', methods=['POST'])
def create_book():
  data = request.get_json()

  if not data:
    return jsonify({'message': 'Book not sent!'})

  try:
    collection = mongo.db.books
    collection.insert(data)
  except:
    return jsonify({'message': 'Insert error!'})

  return jsonify({'message': 'Book created!'})

@app.route('/book', methods=['GET'])
def get_all_books():
  books = mongo.db.books.find()
  resp = dumps(books)

  if not resp:
    return jsonify({'message': 'No books!'})

  return resp

@app.route('/book/<book_id>', methods=['GET'])
def get_book(book_id):
  book = mongo.db.books.find_one({'_id':ObjectId(book_id)})
  resp = dumps(book)

  if not resp:
    return jsonify({'message': 'No books!'})

  return resp

@app.route('/book/<book_id>', methods=['PUT'])
def update_book(book_id):
  data = request.get_json()
  title = data['title']
  author = data['author']

  if not title and not author:
    return jsonify({'message': 'No books!'})

  mongo.db.books.update_one({'_id':ObjectId(book_id)}, {'$set':{'title': title, 'author':author}})

  return jsonify({'message': 'Book Updated!'})

@app.route('/book/<book_id>', methods=['DELETE'])
def delete_book(book_id):

  mongo.db.books.delete_one({'_id':ObjectId(book_id)})

  return jsonify({'message': 'Book Deleted!'})


import os
import base64
import pandas as pd
import librosa
import tempfile
import numpy as np
import streamlit as st

def extract_features(file_path):
    y, sr = librosa.load(file_path, duration=30)
    chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)
    rmse = librosa.feature.rms(y=y)
    spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr)
    spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr)
    rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
    zcr = librosa.feature.zero_crossing_rate(y)
    mfcc = librosa.feature.mfcc(y=y, sr=sr)
    features = {'filename': os.path.basename(file_path),
                'chroma_stft': chroma_stft.mean(),
                'rmse': rmse.mean(),
                'spectral_centroid': spec_cent.mean(),
                'spectral_bandwidth': spec_bw.mean(),
                'rolloff': rolloff.mean(),
                'zero_crossing_rate': zcr.mean()}
    for i, c in enumerate(mfcc):
        features[f'mfcc{i + 1}'] = c.mean()
    return features

def download_csv(data):
    csv_file = data.to_csv(index=False)
    b64 = base64.b64encode(csv_file.encode()).decode()
    href = f'Download CSV file'
    return href

@st.cache
def convert_df(df):
    # IMPORTANT: Cache the conversion to prevent computation on every rerun
    return df.to_csv().encode('utf-8')

def chart_data(features_df):
    # st.write(features_df.columns)

    cols = st.multiselect('select columns:', features_df.columns, default=[])

    # st.write('You selected:', cols)

    # show dataframe with the selected columns
    st.write(features_df[cols])

    chart_data = pd.DataFrame(
    features_df,
    # features_df._get_value( features_df[cols]),
    columns=cols)

    return st.bar_chart(chart_data)

def main():
    st.title("Audio Feature Extraction App")

    # Add a file uploader and folder path input field
    file = st.file_uploader("Upload an audio file (.wav or .mp3)", type=["wav", "mp3"])
    folder = st.text_input("Enter a folder path containing audio files")

    # Check if a file is uploaded or folder path is entered
    if file is not None:
        # Save the file to a temporary location
        with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
            tmp_file.write(file.read())
            file_path = tmp_file.name

        features = extract_features(file_path)
        features_df = pd.DataFrame(features, index=[0])
        st.write(features_df)
        features_df.to_csv('audio_features.csv', index=False)

        # Remove the temporary file
        os.remove(file_path)
    elif folder:
        # Extract features for all audio files in folder
        audio_files = [f for f in os.listdir(folder) if f.endswith('.wav') or f.endswith('.mp3')]
        all_features = []
        for audio_file in audio_files:
            file_path = os.path.join(folder, audio_file)
            features = extract_features(file_path)
            all_features.append(features)
        features_df = pd.DataFrame(all_features)
        st.write(features_df)

        chart_data(features_df)

        csv = convert_df(features_df)
        st.download_button(
        label="Download CSV Data",
        data=csv,
        file_name='features_df.csv',
        mime='text/csv',
         )
        # st.markdown(download_csv(features_df), unsafe_allow_html=True)
        features_df.to_csv('audio_features.csv', index=False)
    else:
        st.write("Please upload an audio file or enter a folder path")

if __name__ == '__main__':
    main()


from django.urls import path
from .views import inicio,another_view, numero_random, numero_,mi_plantilla

urlpatterns =  [
    path('',inicio),
    path('otra-vista/',another_view),
    path('r/',numero_random),
    path('n/<int:numero>',numero_),
    path('mp/',mi_plantilla),

]


from google.colab import drive
from google.colab import files
files.upload()
drive.mount('/content/drive')
def eval(dict1):
  s=""
  if type(dict1['lhs'])==dict:
    t=eval(dict1['lhs'])
    s=s+' '+t
  else:
      t=str(dict1['lhs'])
      s=s+''+t

  s=s+''+dict1['op']

  if type(dict1['rhs'])==dict:
      t=eval(dict1['rhs'])
      s=s+' '+t
  else:
      t=str(dict1['rhs'])
      s=s+''+t
  return s

file=open('/content/drive/My Drive/Colab Notebooks/data.txt',"r")
data=json.load(file)
print(eval(data))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Apr  5 14:45:37 2019

@author: ciaran

I wrote this as a blade of grass got stuck in the drone camera lens

So had to crop everything

"""

#from PIL import  Image
from glob2 import glob
from os import path, mkdir
import argparse
from subprocess import call
from joblib import Parallel, delayed
from shutil import rmtree
from skimage.io import imread#, imsave
from skimage.util import crop
from scipy.misc import bytescale
import imageio

parser = argparse.ArgumentParser()

parser.add_argument("-fld", "--inF", type=str, required=True,
                    help="path to folder of images to be cropped")

parser.add_argument("-o", "--oot", type=str, required=True,
                     help="path to folder for cropped images")

parser.add_argument("-nt", "--noT", type=int, required=False, default=-1,
                    help="no of tiles at a time")

args = parser.parse_args()

imList = glob(path.join(path.abspath(args.inF), '*.tif'))

outFolder = args.oot

if path.exists(outFolder):
    rmtree(outFolder)

mkdir(outFolder)

def clipper(i, outFolder):

#for i in imList:
    hd, tl = path.split(i)
    im = imread(i)
    cropped = crop(im, ((120, 0), (0, 0), (0,0)), copy=False)
    img8 = bytescale(cropped)

#    cropped =im.crop((120, 0, 1227, 909))
    outFile = path.join(outFolder, tl)
#    cropped.save(outFile)
    imageio.imwrite(outFile, img8)

    cmd = ["exiftool", "-tagsFromFile", i,  "-file:all", "-iptc:all",
           "-exif:all",  "-xmp", "-Composite:all", outFile,
           "-overwrite_original"]
    call(cmd)

if args.noT == 1:
    [clipper(img, outFolder) for img in imList]
else:
    Parallel(n_jobs=args.noT, verbose=2)(delayed(clipper)(img,
            outFolder) for img in imList)

# load exif data


import sys

from PyQt5.QtCore import Qt, QRectF, QPointF, QSize, pyqtSignal, QObject
from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen, QPixmap
from PyQt5.QtWidgets import QGraphicsRectItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem

class Selector(QGraphicsRectItem):
    handle_top_left = 1
    handle_top_middle = 2
    handle_top_right = 3
    handle_middle_left = 4
    handle_middle_right = 5
    handle_bottom_left = 6
    handle_bottom_middle = 7
    handle_bottom_right = 8

    handle_cursors = {
        handle_top_left: Qt.SizeFDiagCursor,
        handle_top_middle: Qt.SizeVerCursor,
        handle_top_right: Qt.SizeBDiagCursor,
        handle_middle_left: Qt.SizeHorCursor,
        handle_middle_right: Qt.SizeHorCursor,
        handle_bottom_left: Qt.SizeBDiagCursor,
        handle_bottom_middle: Qt.SizeVerCursor,
        handle_bottom_right: Qt.SizeFDiagCursor,
    }

    def __init__(self, *args, rgb=(255, 0, 0), handle_size=+8.0, handle_space=-4.0, aspect_ratio=None):
        """
        Initialize the shape.
        """
        super().__init__(*args)

        self.handle_size = handle_size
        self.handle_space = handle_space

        self.handles = {}
        self.handle_selected = None
        self.mouse_press_pos = None
        self.mouse_press_rect = None
        self.aspect_ratio = aspect_ratio
        self.rgb = rgb
        self.setAcceptHoverEvents(True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        self.setFlag(QGraphicsItem.ItemIsFocusable, True)
        self.updateHandlesPos()

        self.text_size = self.rect().height() / 15

    def handleAt(self, point):
        """
        Returns the resize handle below the given point.
        """
        for k, v, in self.handles.items():
            if v.contains(point):
                return k
        return None

    def hoverMoveEvent(self, move_event):
        """
        Executed when the mouse moves over the shape (NOT PRESSED).
        """
        if self.isSelected():
            handle = self.handleAt(move_event.pos())
            cursor = Qt.ArrowCursor if handle is None else self.handle_cursors[handle]
            self.setCursor(cursor)
        super().hoverMoveEvent(move_event)

    def hoverLeaveEvent(self, move_event):
        """
        Executed when the mouse leaves the shape (NOT PRESSED).
        """
        self.setCursor(Qt.ArrowCursor)
        super().hoverLeaveEvent(move_event)

    def mousePressEvent(self, mouse_event):
        """
        Executed when the mouse is pressed on the item.
        """
        self.handle_selected = self.handleAt(mouse_event.pos())
        if self.handle_selected:
            self.mouse_press_pos = mouse_event.pos()
            self.mouse_press_rect = self.boundingRect()
        super().mousePressEvent(mouse_event)

    def mouseMoveEvent(self, mouse_event):
        """
        Executed when the mouse is being moved over the item while being pressed.
        """
        if self.handle_selected is not None:
            self.interactiveResize(mouse_event.pos())
        else:
            super().mouseMoveEvent(mouse_event)

    def mouseReleaseEvent(self, mouse_event):
        """
        Executed when the mouse is released from the item.
        """
        super().mouseReleaseEvent(mouse_event)
        self.handle_selected = None
        self.mouse_press_pos = None
        self.mouse_press_rect = None
        self.update()

    def boundingRect(self):
        """
        Returns the bounding rect of the shape (including the resize handles).
        """
        o = self.handle_size + self.handle_space
        return self.rect().adjusted(-o, -o, o, o)

    def updateHandlesPos(self):
        """
        Update current resize handles according to the shape size and position.
        """
        s = self.handle_size
        b = self.boundingRect()
        self.handles[self.handle_top_left] = QRectF(b.left(), b.top(), s, s)
        self.handles[self.handle_top_middle] = QRectF(b.center().x() - s / 2, b.top(), s, s)
        self.handles[self.handle_top_right] = QRectF(b.right() - s, b.top(), s, s)
        self.handles[self.handle_middle_left] = QRectF(b.left(), b.center().y() - s / 2, s, s)
        self.handles[self.handle_middle_right] = QRectF(b.right() - s, b.center().y() - s / 2, s, s)
        self.handles[self.handle_bottom_left] = QRectF(b.left(), b.bottom() - s, s, s)
        self.handles[self.handle_bottom_middle] = QRectF(b.center().x() - s / 2, b.bottom() - s, s, s)
        self.handles[self.handle_bottom_right] = QRectF(b.right() - s, b.bottom() - s, s, s)

    def interactiveResize(self, mouse_pos):
        """
        Perform shape interactive resize.
        """
        offset = self.handle_size + self.handle_space
        bounding_rect = self.boundingRect()
        rect = self.rect()
        diff = QPointF(0, 0)

        self.prepareGeometryChange()

        if self.handle_selected == self.handle_top_left:

            from_x = self.mouse_press_rect.left()
            from_y = self.mouse_press_rect.top()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setX(to_x - from_x)
            diff.setY(to_y - from_y)
            bounding_rect.setLeft(to_x)
            bounding_rect.setTop(to_y)
            rect.setLeft(bounding_rect.left() + offset)
            rect.setTop(bounding_rect.top() + offset)

        elif self.handle_selected == self.handle_top_middle:

            from_y = self.mouse_press_rect.top()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setY(to_y - from_y)
            bounding_rect.setTop(to_y)
            rect.setTop(bounding_rect.top() + offset)

        elif self.handle_selected == self.handle_top_right:

            from_x = self.mouse_press_rect.right()
            from_y = self.mouse_press_rect.top()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setX(to_x - from_x)
            diff.setY(to_y - from_y)
            bounding_rect.setRight(to_x)
            bounding_rect.setTop(to_y)
            rect.setRight(bounding_rect.right() - offset)
            rect.setTop(bounding_rect.top() + offset)

        elif self.handle_selected == self.handle_middle_left:

            from_x = self.mouse_press_rect.left()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            diff.setX(to_x - from_x)
            bounding_rect.setLeft(to_x)
            rect.setLeft(bounding_rect.left() + offset)

        elif self.handle_selected == self.handle_middle_right:
            from_x = self.mouse_press_rect.right()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            diff.setX(to_x - from_x)
            bounding_rect.setRight(to_x)
            rect.setRight(bounding_rect.right() - offset)

        elif self.handle_selected == self.handle_bottom_left:

            from_x = self.mouse_press_rect.left()
            from_y = self.mouse_press_rect.bottom()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setX(to_x - from_x)
            diff.setY(to_y - from_y)
            bounding_rect.setLeft(to_x)
            bounding_rect.setBottom(to_y)
            rect.setLeft(bounding_rect.left() + offset)
            rect.setBottom(bounding_rect.bottom() - offset)

        elif self.handle_selected == self.handle_bottom_middle:

            from_y = self.mouse_press_rect.bottom()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setY(to_y - from_y)
            bounding_rect.setBottom(to_y)
            rect.setBottom(bounding_rect.bottom() - offset)

        elif self.handle_selected == self.handle_bottom_right:

            from_x = self.mouse_press_rect.right()
            from_y = self.mouse_press_rect.bottom()
            to_x = from_x + mouse_pos.x() - self.mouse_press_pos.x()
            to_y = from_y + mouse_pos.y() - self.mouse_press_pos.y()
            diff.setX(to_x - from_x)
            diff.setY(to_y - from_y)
            bounding_rect.setRight(to_x)
            bounding_rect.setBottom(to_y)
            rect.setRight(bounding_rect.right() - offset)
            rect.setBottom(bounding_rect.bottom() - offset)

        if self.aspect_ratio:
            rect.setHeight(rect.width() / self.aspect_ratio)

        self.setRect(rect)

        self.updateHandlesPos()

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        """
        path = QPainterPath()
        path.addRect(self.rect())
        if self.isSelected():
            for shape in self.handles.values():
                path.addEllipse(shape)
        return path

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the graphic view.
        """

        painter.setBrush(QBrush(QColor(*self.rgb, 100)))
        painter.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
        painter.drawRect(self.rect())

        painter.setRenderHint(QPainter.Antialiasing)
        painter.setBrush(QBrush(QColor(*self.rgb, 255)))
        painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        for handle, rect in self.handles.items():
            if self.handle_selected is None or handle == self.handle_selected:
                painter.drawEllipse(rect)

        font = painter.font()
        font.setPointSize(self.text_size)
        painter.setFont(font)

        text_padding = self.text_size / 2

        painter.drawText(
            self.rect().x() + self.text_size + text_padding,
            self.rect().y() + self.text_size + text_padding,
            f'( {self.rect().width():.2f} x {self.rect().height():.2f} )'
        )

    def itemChange(self, change, value):
        scene = self.scene()
        if scene and QGraphicsItem.ItemPositionHasChanged == change:
            scene.on_item_position_change(self, change, value)
        if scene and QGraphicsItem.ItemScaleHasChanged == change:
            scene.on_item_scale_changed(self, change, value)
        return super(Selector, self).itemChange(change, value)

def main():
    app = QApplication(sys.argv)

    grview = QGraphicsView()
    scene = QGraphicsScene()
    scene.setSceneRect(0, 0, 680, 459)

    scene.addPixmap(QPixmap('01.png'))
    grview.setScene(scene)

    item = Selector(0, 0, 300, 150)
    scene.addItem(item)

    grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
    grview.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()