from typing import Any, Dict, List, Type, TypeVar, Union

import attr

from ..models.rest_rule_condition_groups import RestRuleConditionGroups
from ..models.rest_rule_rule_actions import RestRuleRuleActions
from ..types import UNSET, Unset

T = TypeVar("T", bound="RestRule")

@attr.s(auto_attribs=True)
class RestRule:
    """
    Attributes:
        name (str):
        fire_on (Union[Unset, str]):
        short_circuit (Union[Unset, bool]):
        priority (Union[Unset, int]):
        enabled (Union[Unset, bool]):
        condition_groups (Union[Unset, RestRuleConditionGroups]):
        rule_actions (Union[Unset, RestRuleRuleActions]):
    """

    name: str
    fire_on: Union[Unset, str] = UNSET
    short_circuit: Union[Unset, bool] = UNSET
    priority: Union[Unset, int] = UNSET
    enabled: Union[Unset, bool] = UNSET
    condition_groups: Union[Unset, RestRuleConditionGroups] = UNSET
    rule_actions: Union[Unset, RestRuleRuleActions] = UNSET
    additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        name = self.name
        fire_on = self.fire_on
        short_circuit = self.short_circuit
        priority = self.priority
        enabled = self.enabled
        condition_groups: Union[Unset, Dict[str, Any]] = UNSET
        if not isinstance(self.condition_groups, Unset):
            condition_groups = self.condition_groups.to_dict()

        rule_actions: Union[Unset, Dict[str, Any]] = UNSET
        if not isinstance(self.rule_actions, Unset):
            rule_actions = self.rule_actions.to_dict()

        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "name": name,
            }
        )
        if fire_on is not UNSET:
            field_dict["fireOn"] = fire_on
        if short_circuit is not UNSET:
            field_dict["shortCircuit"] = short_circuit
        if priority is not UNSET:
            field_dict["priority"] = priority
        if enabled is not UNSET:
            field_dict["enabled"] = enabled
        if condition_groups is not UNSET:
            field_dict["conditionGroups"] = condition_groups
        if rule_actions is not UNSET:
            field_dict["ruleActions"] = rule_actions

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        d = src_dict.copy()
        name = d.pop("name")

        fire_on = d.pop("fireOn", UNSET)

        short_circuit = d.pop("shortCircuit", UNSET)

        priority = d.pop("priority", UNSET)

        enabled = d.pop("enabled", UNSET)

        _condition_groups = d.pop("conditionGroups", UNSET)
        condition_groups: Union[Unset, RestRuleConditionGroups]
        if isinstance(_condition_groups, Unset):
            condition_groups = UNSET
        else:
            condition_groups = RestRuleConditionGroups.from_dict(_condition_groups)

        _rule_actions = d.pop("ruleActions", UNSET)
        rule_actions: Union[Unset, RestRuleRuleActions]
        if isinstance(_rule_actions, Unset):
            rule_actions = UNSET
        else:
            rule_actions = RestRuleRuleActions.from_dict(_rule_actions)

        rest_rule = cls(
            name=name,
            fire_on=fire_on,
            short_circuit=short_circuit,
            priority=priority,
            enabled=enabled,
            condition_groups=condition_groups,
            rule_actions=rule_actions,
        )

        rest_rule.additional_properties = d
        return rest_rule

    @property
    def additional_keys(self) -> List[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties


from app import app
from flask import jsonify
from app.tools.dbConnector import *
from app.tools import dbConnector

@app.route('/')
@app.route('/index')
def index():
	return "IT'S WORKING"

@app.route('/lol')
def index1():
	return "LOL"

@app.route('/data')
def names():
	data = {
		"names": ["John", "Jacob", "Julie", "Jennifer"]}
	return jsonify(data)

@app.route('/db/api/clear/', methods=['GET', 'POST'])
def clear():
	con = connect()
	tables = ['post', 'thread', 'forum', 'subscription', 'follower', 'user']
	dbConnector.execute(con, "SET global foreign_key_checks = 0;")
	for table in tables:
		dbConnector.execute(con, "TRUNCATE TABLE %s;" % table)
	dbConnector.execute(con, "SET global foreign_key_checks = 1;")
	con.close()
	return jsonify({
		"code": STATUS_CODE['OK'],
		"response": 'OK'})

@app.route('/db/api/status/', methods=['GET'])
def status():
	con = connect()
	response = []
	tables = ['user', 'thread', 'forum', 'post']

	for table in tables:
		currCount = len(dbConnector.select_query(con, 'SELECT id FROM ' + table, ()))
		response.append(currCount)

	statusResponse = {
		'user': response[0],
		'thread': response[1],
		'forum': response[2],
		'post': response[3]
	}

	con.close()

	stat = statusResponse
	return jsonify({
		"code": STATUS_CODE['OK'],
		"response": stat})


import binascii
import codecs

import logging

from construct import *

from regipy.exceptions import RegistryKeyNotFoundException
from regipy.hive_types import NTUSER_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime

logger = logging.getLogger(__name__)

WORD_WHEEL_QUERY_KEY_PATH = r'\Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery'

class WordWheelQueryPlugin(Plugin):
    NAME = 'word_wheel_query'
    DESCRIPTION = 'Parse the word wheel query artifact'
    COMPATIBLE_HIVE = NTUSER_HIVE_TYPE

    def run(self):
        try:
            subkey = self.registry_hive.get_key(WORD_WHEEL_QUERY_KEY_PATH)
        except RegistryKeyNotFoundException as ex:
            logger.error(f'Could not find {self.NAME} plugin data at: {WORD_WHEEL_QUERY_KEY_PATH}: {ex}')
            return None

        timestamp = convert_wintime(subkey.header.last_modified, as_json=self.as_json)

        mru_list_order = subkey.get_value('MRUListEx')

        # If this is the value, the list is empty
        if mru_list_order == 0xffffffff:
            return None

        for i, entry_name in enumerate(GreedyRange(Int32ul).parse(mru_list_order)):
            entry_value = subkey.get_value(str(entry_name))

            if not entry_value:
                continue

            self.entries.append({
                'last_write': timestamp,
                'mru_id': entry_name,
                'order': i,
                'name': CString('utf-16').parse(entry_value)
            })


# coding: utf-8

# ## 探索电影数据集
#
# 在这个项目中，你将尝试使用所学的知识，使用 `NumPy`、`Pandas`、`matplotlib`、`seaborn` 库中的函数，来对电影数据集进行探索。
#
# 下载数据集：
# [TMDb电影数据](https://s3.cn-north-1.amazonaws.com.cn/static-documents/nd101/explore+dataset/tmdb-movies.csv)
#

#
# 数据集各列名称的含义：
#

#

列名称	id	imdb_id	popularity	budget	revenue	original_title	cast	homepage	director	tagline	keywords	overview	runtime	genres	production_companies	release_date	vote_count	vote_average	release_year	budget_adj	revenue_adj

#
含义	编号	IMDB 编号	知名度	预算	票房	名称	主演	网站	导演	宣传词	关键词	简介	时常	类别	发行公司	发行日期	投票总数	投票均值	发行年份	预算（调整后）	票房（调整后）

#

#

# **请注意，你需要提交该报告导出的 `.html`、`.ipynb` 以及 `.py` 文件。**

#
#
# ---
#
# ---
#
# ## 第一节 数据的导入与处理
#
# 在这一部分，你需要编写代码，使用 Pandas 读取数据，并进行预处理。

#
# **任务1.1：** 导入库以及数据
#
# 1. 载入需要的库 `NumPy`、`Pandas`、`matplotlib`、`seaborn`。
# 2. 利用 `Pandas` 库，读取 `tmdb-movies.csv` 中的数据，保存为 `movie_data`。
#
# 提示：记得使用 notebook 中的魔法指令 `%matplotlib inline`，否则会导致你接下来无法打印出图像。

# In[1]:

# task 1
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb

get_ipython().run_line_magic('matplotlib', 'inline')

#task 2
movie_data = pd.read_csv('tmdb-movies.csv')

# ---
#
# **任务1.2: ** 了解数据
#
# 你会接触到各种各样的数据表，因此在读取之后，我们有必要通过一些简单的方法，来了解我们数据表是什么样子的。
#
# 1. 获取数据表的行列，并打印。
# 2. 使用 `.head()`、`.tail()`、`.sample()` 方法，观察、了解数据表的情况。
# 3. 使用 `.dtypes` 属性，来查看各列数据的数据类型。
# 4. 使用 `isnull()` 配合 `.any()` 等方法，来查看各列是否存在空值。
# 5. 使用 `.describe()` 方法，看看数据表中数值型的数据是怎么分布的。
#
#

# In[2]:

# task 1
print(movie_data.shape)

# task 2
movie_data.head(5)
movie_data.tail(5)
movie_data.sample(5)

#task 3
movie_data.dtypes

#task 4
movie_data.isnull().any()
movie_data.isnull().sum()

#task 5
movie_data.describe()

# ---
#
# **任务1.3: ** 清理数据
#
# 在真实的工作场景中，数据处理往往是最为费时费力的环节。但是幸运的是，我们提供给大家的 tmdb 数据集非常的“干净”，不需要大家做特别多的数据清洗以及处理工作。在这一步中，你的核心的工作主要是对数据表中的空值进行处理。你可以使用 `.fillna()` 来填补空值，当然也可以使用 `.dropna()` 来丢弃数据表中包含空值的某些行或者列。
#
# 任务：使用适当的方法来清理空值，并将得到的数据保存。

# In[3]:

movie_data = movie_data.fillna(method = 'ffill', axis = 0)
movie_data.isnull().sum().sum()

# ---
#
# ---
#
# ## 第二节 根据指定要求读取数据
#
#
# 相比 Excel 等数据分析软件，Pandas 的一大特长在于，能够轻松地基于复杂的逻辑选择合适的数据。因此，如何根据指定的要求，从数据表当获取适当的数据，是使用 Pandas 中非常重要的技能，也是本节重点考察大家的内容。
#
#

# ---
#
# **任务2.1: ** 简单读取
#
# 1. 读取数据表中名为 `id`、`popularity`、`budget`、`runtime`、`vote_average` 列的数据。
# 2. 读取数据表中前1～20行以及48、49行的数据。
# 3. 读取数据表中第50～60行的 `popularity` 那一列的数据。
#
# 要求：每一个语句只能用一行代码实现。

# In[4]:

# task 1
movie_data[['id','popularity','budget', 'runtime', 'vote_average']]

#task 2
movie_data.loc[list(range(20)) + list([47, 48])]

#task 3
movie_data[49:60]['popularity'];

# ---
#
# **任务2.2: **逻辑读取（Logical Indexing）
#
# 1. 读取数据表中 **`popularity` 大于5** 的所有数据。
# 2. 读取数据表中 **`popularity` 大于5** 的所有数据且**发行年份在1996年之后**的所有数据。
#
# 提示：Pandas 中的逻辑运算符如 `&`、`|`，分别代表`且`以及`或`。
#
# 要求：请使用 Logical Indexing实现。

# In[5]:

#task 1
movie_data[movie_data['popularity'] > 5]

#task 2
movie_data[(movie_data['popularity'] > 5) & (movie_data['release_year'] > 1996)];

# ---
#
# **任务2.3: **分组读取
#
# 1. 对 `release_year` 进行分组，使用 [`.agg`](http://pandas.pydata.org/pandas-docs/version/0.22/generated/pandas.core.groupby.DataFrameGroupBy.agg.html) 获得 `revenue` 的均值。
# 2. 对 `director` 进行分组，使用 [`.agg`](http://pandas.pydata.org/pandas-docs/version/0.22/generated/pandas.core.groupby.DataFrameGroupBy.agg.html) 获得 `popularity` 的均值，从高到低排列。
#
# 要求：使用 `Groupby` 命令实现。

# In[6]:

#task 1
movie_data.groupby('release_year').revenue.agg('mean').sort_values(ascending = False)

#task 2
movie_data.groupby('director').popularity.agg('mean').sort_values(ascending = False);

# ---
#
# ---
#
# ## 第三节 绘图与可视化
#
# 接着你要尝试对你的数据进行图像的绘制以及可视化。这一节最重要的是，你能够选择合适的图像，对特定的可视化目标进行可视化。所谓可视化的目标，是你希望从可视化的过程中，观察到怎样的信息以及变化。例如，观察票房随着时间的变化、哪个导演最受欢迎等。
#
#

#

可视化的目标	可以使用的图像

#
表示某一属性数据的分布	饼图、直方图、散点图

#
表示某一属性数据随着某一个变量变化	条形图、折线图、热力图

#
比较多个属性的数据之间的关系	散点图、小提琴图、堆积条形图、堆积折线图

#

#
# 在这个部分，你需要根据题目中问题，选择适当的可视化图像进行绘制，并进行相应的分析。对于选做题，他们具有一定的难度，你可以尝试挑战一下～

# **任务3.1：**对 `popularity` 最高的20名电影绘制其 `popularity` 值。

# In[7]:

# get top20 popularity movie index
popupar20 = movie_data['popularity'].sort_values(ascending = False).index[0:20]
# get a sub DataFrame of the top20 popularity movies
movie_popular20 = movie_data.loc[popupar20]

# draw a barplot to represent each movie's popularity
base_color = sb.color_palette()[1]
sb.barplot(data = movie_popular20, y = 'original_title', x = 'popularity', color = base_color)
plt.xlabel('Popularity')
plt.ylabel('Movie Title')
plt.title('Top 20 Movies by Popularity ')

# using pandas visulization
plt.figure();
movie_popular20.set_index(['original_title'])['popularity'].sort_values().plot(kind = 'barh', color = 'DarkBlue')
plt.xlabel('Popularity')
plt.ylabel('Movie Title')
plt.title('Top 20 Movies by Popularity ')

# ---
# **任务3.2：**分析电影净利润（票房-成本）随着年份变化的情况，并简单进行分析。

# In[8]:

#给数据集中添加profit列
movie_data['profit'] = movie_data['revenue'] - movie_data['budget']

#选择Pointplot, x轴为年份， y轴为利润的
plt.figure(figsize = [15,10])
sb.pointplot(data = movie_data, x = 'release_year', y = 'profit', color = base_color)
plt.xticks(rotation = 90)
plt.xlabel('Year')
plt.ylabel('Profit (10M $)')

'''
分析：
0. 图形中误差条很长，说明不同电影得表现差异很大
1. 1960~1972年间，平均利润较低 （1e7左右）
2. 1960~1990年间，平均利润基本保持上升趋势，1977年平均利润最高达到（3.5e7）
3. 1990~2015年间，平均利润基本平稳（2e7~3e7之间）
'''

# ---
#
# **[选做]任务3.3：**选择最多产的10位导演（电影数量最多的），绘制他们排行前3的三部电影的票房情况，并简要进行分析。

# In[9]:

# process movies with multiple directors
tmp = movie_data['director'].str.split('|',expand = True).stack().reset_index(level = 1, drop = True).rename('director')

#produce a new dataframe having splitted director with interested columns
movie_director_split = movie_data[['original_title', 'revenue']].join(tmp)

# list of top10 directors who produce most films in descending order
director_top10 = tmp.value_counts().nlargest(10).index

movie_top10dir_sub = movie_director_split.loc[movie_director_split['director'].isin(director_top10)]

# creat a list of revenue top 3 movies of top10 directors
top3_list = []
for direc in director_top10:
    idx_list = movie_top10dir_sub[movie_top10dir_sub['director'] == direc].revenue.sort_values(ascending = False).index[0:3]
    top3_list.extend(idx_list)

# use the above list to produce a sub dataframe containing only 30 movies which we are interested in
movie_top30_sub = movie_top10dir_sub.loc[top3_list]
movie_top30_sub = movie_top30_sub.set_index('original_title')

# draw separated plots of each director
_, axes = plt.subplots(ncols = 5, nrows = 2, figsize=(15, 12), sharey=True, tight_layout = True)
for direct, ax in zip(director_top10, axes.flat):
    movie_top30_sub[movie_top30_sub['director'] == direct].plot(kind = 'bar', ax = ax)
    ax.set_title(direct)
    ax.set_ylabel('Revenue')
    ax.set_xlabel('Movie Title')

# draw another swarm plot to represent all
plt.figure();
sb.swarmplot(data = movie_top30_sub, x = 'director', y = 'revenue')
plt.ylabel('Revenue (billion $)')
plt.xlabel('Director')
plt.xticks(rotation =90)

'''
分析：
0. Steven Spielberg top3 表现都很不错
1. Tim Burton top1 票房最好
2. 最高产的 Woody Allen top3综合表现最差
'''

# ---
#
# **[选做]任务3.4：**分析1968年~2015年六月电影的数量的变化。

# In[10]:

# condition of year
sel_y = (movie_data['release_year'] >= 1968) & (movie_data['release_year'] <= 2015)

# creat new column of month
month_list = []
for idx in range(movie_data.shape[0]):
    item_sep = movie_data['release_date'][idx].split('/')
    month = item_sep[0]
    month_list.append(month)

movie_data['month'] = month_list

# condition of month
sel_m = movie_data['month'] == '6'

# draw
movie_data[sel_y & sel_m]['release_year'].value_counts().sort_index().plot(kind='bar', figsize=(15, 8), color = 'DarkBlue')
plt.xlabel('Month June of each year')
plt.ylabel('Number of Movies')

# convert label to Year/Month format
loc, label = plt.xticks()

for each_label in label:
    each_label.set_text(each_label.get_text() + '/6')

plt.xticks(loc, label);

'''
分析：
0. 1968-1984 6月电影数量成上升趋势
1. 1985-2001 6月电影数量比较平均
2. 2002-2015 6月电影成爆发性增长趋势
'''

# ---
#
# **[选做]任务3.5：**分析1968年~2015年六月电影 `Comedy` 和 `Drama` 两类电影的数量的变化。

# In[11]:

pd.set_option('display.max_columns', 50)

#prepare a list to produce a new column 'genres_adj' which has four categories: Comedy, Drama, Comedy&Drama, Non C&D
genres_CD_list = []
for idx in range(movie_data.shape[0]):
    content = movie_data['genres'][idx]
    if content.find('Comedy') != -1:
        content_adj = 'Comedy'
    elif content.find('Drama') != -1:
        content_adj = 'Drama'
    elif content.find('Comedy') & content.find('Drama') != -1:
        content_adj = 'Comedy&Drama'
    else:
        content_adj = 'Non C&D'
    genres_CD_list.append(content_adj)

# add column 'genres_adj' to dataset
movie_data['genres_adj'] = genres_CD_list

# get sub dataframe by filtering year and month
movie_YandM_sub = movie_data[sel_y & sel_m]

# order by ascending natural year
new_order_h2 = movie_YandM_sub.groupby(['release_year']).size().index
type2 = pd.api.types.CategoricalDtype(ordered = True, categories = new_order_h2)
movie_YandM_sub['release_year'] = movie_YandM_sub['release_year'].astype(type2)

# get only 'Comedy' and 'Drama' in movie_data['genres_adj']
new_order_CD = ['Comedy', 'Drama']
CD_type = pd.api.types.CategoricalDtype(ordered = True, categories = new_order_CD)
movie_YandM_sub['genres_adj'] = movie_YandM_sub['genres_adj'].astype(CD_type)

#visulize via countplot (clustered bar chart)
plt.figure(figsize = [18, 5])
ax = sb.countplot(data = movie_YandM_sub, x = 'release_year', hue = 'genres_adj')
ax.legend(title = '')
plt.xticks(rotation = 90)
plt.xlabel('Release Year/June')
plt.ylabel('Number of Movies')

# convert label to Year/Month format
loc, label = plt.xticks()

for each_label in label:
    each_label.set_text(each_label.get_text() + '/6')

plt.xticks(loc, label);

'''
分析：
0. 整体上两种类型电影都是上升趋势
1. 1986-1974年Drama多于Comedy
2. 1975-1988年， 2000-2009 年Comedy迎来高增长，数量远大于Drama
3. 1989-1999年，2013-2015年两类电影数量相差不大
'''

# > 注意: 当你写完了所有的代码，并且回答了所有的问题。你就可以把你的 iPython Notebook 导出成 HTML 文件。你可以在菜单栏，这样导出**File -> Download as -> HTML (.html)、Python (.py)** 把导出的 HTML、python文件 和这个 iPython notebook 一起提交给审阅者。


import open3d as o3d
import numpy as np
import heapq

# print(o3d.__version__)

def import_mesh(file_path: str):
    """
    Imports stl file as Mesh

    Args:
        file_path (str): file path of stl file

    Returns:
        mesh (open3d.geometry.TriangleMesh): Mesh to be processed.
    """
    mesh = o3d.io.read_triangle_mesh(file_path)
    return mesh

def export_mesh(file_path: str, mesh):
    """
    Export a mesh to a given file path using the open3d library.

    Args:
        file_path (str): The file path where the mesh will be saved.

        mesh: The mesh to be exported.

    Returns:
        None
    """
    o3d.io.write_triangle_mesh(file_path, mesh)
    return

def clean_mesh(mesh):
    """
    Merge the close vertices of a mesh to remove noise.

    Args:
        mesh: The mesh to be cleaned.

    Returns:
        None
    """
    mesh.merge_close_vertices(0.01)
    return

def mesh_details(mesh) -> tuple:
    """
    Retrieve details of a mesh in the form of numpy arrays for vertices and triangles.

    Args:
        mesh: The mesh for which the details are to be extracted.

    Returns:
        tuple: A tuple of two numpy arrays. The first array contains the vertices of the mesh
        and the second array contains the triangles of the mesh.
    """
    return (np.asarray(mesh.vertices), np.asarray(mesh.triangles))

def visualize(entries, show_wireframe=False) -> None:
    """
    Visualize a single mesh or a list of meshes using the open3d library.

    Args:
        entries: The mesh/meshes to be visualized. It can be a single mesh or a list of meshes.

        show_wireframe (bool): A flag to show/hide the wireframe of the mesh/meshes.

    Returns:
        None
    """
    if type(entries) is not list:
        o3d.visualization.draw_geometries([entries], mesh_show_wireframe=show_wireframe)
    else:
        o3d.visualization.draw_geometries(entries, mesh_show_wireframe=show_wireframe)
        return

def get_mask(mesh, idx):
    """
    Create a mask array for a specific vertex of the mesh.

    Args:
        mesh: The mesh for which the mask is to be created.

        idx: The index of the vertex for which the mask is to be created.

    Returns:
        np.ndarray: A boolean mask array with True value for the given index and False for all
                    other vertices of the mesh.
    """
    mask = np.full(np.asarray(mesh.vertices).shape[0], False)
    mask[idx] = True
    return mask

def find_minimum(mesh, k: int = 1, idx_mask=[]):
    """
    Find the k number of vertices having minimum z-coordinate of a mesh.

    Args:
        mesh (open3d.geometry.TriangleMesh): The input mesh.

        k (int, optional):: The number of minimum vertices to be found.

        idx_mask (list, optional): A list of indices of vertices to be considered for finding minimum vertices.

    Returns:
        tuple: A tuple of two numpy arrays. The first array contains the indices of the minimum
               vertices and the second array contains the coordinates of the minimum vertices.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    idx_mask = set(idx_mask)
    # print(mesh_vertices_np, type(mesh.vertices))

    heap: list = []
    for i, vertex in enumerate(mesh_vertices_np):
        if len(idx_mask) == 0:
            heapq.heappush(heap, (vertex[2], i, vertex))

        elif len(idx_mask) > 0 and i in idx_mask:
            heapq.heappush(heap, (vertex[2], i, vertex))

    return np.array([idx for (_, idx, _) in heapq.nsmallest(k, heap)]).reshape((-1, 1)), np.array(
        [vertex for (_, _, vertex) in heapq.nsmallest(k, heap)]
    ).reshape((-1, 3))

def find_maximum(mesh, k: int = 1, idx_mask=[]):
    """
    Finds the maximum value(s) and corresponding index(s) in the z-coordinate of the mesh's vertices.

    Args:
        mesh (open3d.geometry.TriangleMesh): The input mesh.

        k (int, optional): The number of maximum values to return. Defaults to 1.

        idx_mask (list, optional): List of vertex indices to consider for the maximum search. Defaults to empty list.

    Returns:
        tuple: Two numpy arrays, one containing the index(s) of the maximum value(s) and the other containing
        the maximum value(s) in the z-coordinate of the mesh's vertices.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    idx_mask = set(idx_mask)
    # print(mesh_vertices_np, type(mesh.vertices))

    heap: list = []
    for i, vertex in enumerate(mesh_vertices_np):
        if len(idx_mask) == 0:
            heapq.heappush(heap, (vertex[2], i, vertex))

        elif len(idx_mask) > 0 and i in idx_mask:
            heapq.heappush(heap, (vertex[2], i, vertex))

    return np.array([idx for (_, idx, _) in heapq.nlargest(k, heap)]).reshape((-1, 1)), np.array(
        [vertex for (_, _, vertex) in heapq.nlargest(k, heap)]
    ).reshape((-1, 3))

def find_all_below(mesh, value: float, inclusive=False):
    """
    Finds all the vertices below the given value in the z-coordinate.

    Args:
        mesh (open3d.geometry.TriangleMesh): The input mesh.

        value (float): The value below which to find vertices.

        inclusive (bool, optional): Whether to include vertices with value equal to the given value. Defaults to False.

    Returns:
        tuple: Two numpy arrays, one containing the indices and the other containing the vertices that are below the
        given value in the z-coordinate.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    # print(mesh_vertices_np, type(mesh.vertices))

    idx = []
    res = []
    if inclusive:
        for v, vertex in enumerate(mesh_vertices_np):
            if vertex[2] <= value:
                idx.append(v)
                res.append(vertex)
    else:
        for v, vertex in enumerate(mesh_vertices_np):
            if vertex[2] < value:
                idx.append(v)
                res.append(vertex)
    return np.array(idx), np.array(res).reshape((-1, 3))

def find_all_above(mesh, value: float, inclusive=False):
    """
    Finds all the vertices above the given value in the z-coordinate.

    Args:
        mesh (open3d.geometry.TriangleMesh): The input mesh.

        value (float): The value above which to find vertices.

        inclusive (bool, optional): Whether to include vertices with value equal to the given value. Defaults to False.

    Returns:
        tuple: Two numpy arrays, one containing the indices and the other containing the vertices that are above the
        given value in the z-coordinate.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    # print(mesh_vertices_np, type(mesh.vertices))

    idx = []
    res = []
    if inclusive:
        for v, vertex in enumerate(mesh_vertices_np):
            if vertex[2] >= value:
                idx.append(v)
                res.append(vertex)
    else:
        for v, vertex in enumerate(mesh_vertices_np):
            if vertex[2] > value:
                idx.append(v)
                res.append(vertex)
    return np.array(idx), np.array(res).reshape((-1, 3))

def find_all_between(mesh, lower_value: float, higher_value: float) -> np.ndarray:
    """
    Returns a NumPy array of vertices whose z-coordinate is between the given lower and higher values.

    Args:
        mesh (open3d.geometry.TriangleMesh): A triangle mesh object.

        lower_value (float): The lower bound of the z-coordinate.

        higher_value (float): The higher bound of the z-coordinate.

    Returns:
        np.ndarray: A NumPy array of vertices whose z-coordinate is between the given lower and higher values.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    # print(mesh_vertices_np, type(mesh.vertices))

    res = []
    for vertex in mesh_vertices_np:
        if lower_value < vertex[2] < higher_value:
            res.append(vertex)
    return np.array(res).reshape((-1, 3))

def make_point_cloud(vertices, color):
    """
    Creates a point cloud object with the given vertices and color.

    Args:
        vertices (np.ndarray): A NumPy array of vertices.

        color (tuple): A tuple of RGB values (0-255).

    Returns:
        open3d.geometry.PointCloud: A point cloud object.
    """
    pc = o3d.geometry.PointCloud()
    pc.points = o3d.utility.Vector3dVector(vertices)
    pc.paint_uniform_color(np.array(color) / 255)
    return pc

def find_neighbors(mesh, index: int):
    """
    Returns the indices and coordinates of the neighboring vertices of the given vertex index.

    Args:
        mesh (open3d.geometry.TriangleMesh): A triangle mesh object.

        index (int): The index of the vertex.

    Returns:
        Tuple[np.ndarray, np.ndarray]: A tuple of two NumPy arrays
        representing the neighboring vertex indices and coordinates.
    """
    mesh_triangles_np = np.asarray(mesh.triangles)
    # print('Printing Tris')
    neighbors = set()
    for tri in mesh_triangles_np:
        if index in tri:
            for i in tri:
                neighbors.add(i)
    neighbors.remove(index)
    return np.array([*neighbors]), np.asarray(mesh.vertices)[np.array([*neighbors])]

def mesh_subdivision(mesh, iterations=1):
    """
    Returns a new triangle mesh object obtained by subdividing the given mesh.

    Args:
        mesh (open3d.geometry.TriangleMesh): A triangle mesh object.

        iterations (int): The number of times to subdivide the mesh.

    Returns:
        open3d.geometry.TriangleMesh: A new triangle mesh object obtained by subdividing the given mesh.
    """
    return mesh.subdivide_midpoint(number_of_iterations=iterations)

def calculate_bounds_height(mesh):
    """
    Returns the minimum z-coordinate of the vertices at the boundary of the given mesh.

    Args:
        mesh (open3d.geometry.TriangleMesh): A triangle mesh object.

    Returns:
        float: The minimum z-coordinate of the vertices at the boundary of the given mesh.
    """
    mesh_vertices_np = np.asarray(mesh.vertices)
    min_x_vertex = mesh_vertices_np[np.argmin(mesh_vertices_np[:, 0])]
    max_x_vertex = mesh_vertices_np[np.argmin(mesh_vertices_np[:, 0])]
    min_y_vertex = mesh_vertices_np[np.argmin(mesh_vertices_np[:, 1])]
    max_y_vertex = mesh_vertices_np[np.argmin(mesh_vertices_np[:, 1])]

    return min(min_x_vertex[2], max_x_vertex[2], min_y_vertex[2], max_y_vertex[2])

def find_accessible(mesh, rain_direction):
    """
    Returns the indices and coordinates of the vertices accessible by a given angle of particles' direction.

    Args:
        mesh (open3d.geometry.TriangleMesh): The mesh to check.

        rain_direction (numpy.ndarray): The direction angle of the rain as a numpy array of shape (3,).
            If direction is [0,0,0], every vertex is chosen.

    Returns:
        Tuple[np.ndarray, np.ndarray]: A tuple of two NumPy arrays
        representing the neighboring vertex indices and coordinates.
    """
    rain_direction = np.asarray(rain_direction)
    # if rain_direction[2] == 0:
    #     return np.array([]), np.array([])
    raycast_angle = rain_direction * -1
    # print(raycast_angle, type(rain_direction))
    mesh_vertices_np = np.asarray(mesh.vertices)

    angle_np = np.full(mesh_vertices_np.shape, raycast_angle)
    ray_np = np.append(mesh_vertices_np, angle_np, axis=1)

    rays = o3d.core.Tensor(ray_np, dtype=o3d.core.Dtype.Float32)
    # print('ray', rays)
    rays[:, 0] += 1e-6 * np.sign(raycast_angle[0])
    rays[:, 1] += 1e-6 * np.sign(raycast_angle[1])
    rays[:, 2] += 1e-6 * np.sign(raycast_angle[2])

    # print('ray added', rays)
    raycasting_scene = o3d.t.geometry.RaycastingScene()
    mesh_legacy = o3d.t.geometry.TriangleMesh.from_legacy(mesh)
    _ = raycasting_scene.add_triangles(mesh_legacy)
    collision = raycasting_scene.cast_rays(rays)

    idx = []
    res = []
    collisions_hit = collision['t_hit'].numpy()
    # print('hit', collisions_hit)

    for v, vertex in enumerate(mesh_vertices_np):
        if collisions_hit[v] == np.inf:
            idx.append(v)
            res.append(vertex)
    return np.array(idx), np.array(res).reshape((-1, 3))

def erode(mesh: o3d.geometry.TriangleMesh, iterations: int = 2, erosion_lifetime: int = 10, direction=None, verbose=[]):
    """
    Erodes the mesh using the particle deposition and erosion method.

    Args:
        mesh (open3d.geometry.TriangleMesh): The mesh to be eroded.

        iterations (int, optional): The number of iterations for the erosion process. Defaults to 2.

        erosion_lifetime (int, optional): The maximum number of times a vertex can be eroded. Defaults to 10.

        direction (numpy.ndarray, optional): The direction of the rain as a numpy array of shape (3,).
            If not provided, the vertex mask is calculated from the mesh's bounding box. Defaults to None.

        verbose (list[str], optional): A list of strings containing information to be printed.
            Possible strings include 'all', 'vertex_progression', 'vector_direction',
            'vector_angle', 'ray', 'ray_scene', 'mesh', and 'collision'.
            Defaults to an empty list.

    Returns:
        Tuple[np.ndarray, open3d.geometry.TriangleMesh]: A tuple containing the updated vertex
        indices and the eroded mesh.

    The `verbose` argument takes a list of strings that specify what information should be printed.
        - 'all': Prints all below.
        - 'vertex_progression': Prints information about vertex triples.
        - 'vector_direction': Prints information about vector directions.
        - 'vector_angle': Prints information about vector angles.
        - 'ray': Prints information about the ray being casted.
        - 'ray_scene': Prints information about the raycasting scene.
        - 'mesh': Prints information about the mesh.
        - 'collision': Prints information about the collision detection.
    """
    # total_vertex_count = np.asarray(mesh.vertices).shape[0]
    verbose = set(verbose)
    if len(verbose) > 0:
        print('Printing with Settings:', verbose)

    if direction is None:
        vertices_idx, vertices = find_all_above(mesh, calculate_bounds_height(mesh), True)
    else:
        vertices_idx, vertices = find_accessible(mesh, rain_direction=direction)

    set_vertices_idx = set()
    for idx in vertices_idx:
        set_vertices_idx.add(idx)
    # print('set', set_vertices_idx)

    # Create New Mesh
    new_mesh = o3d.geometry.TriangleMesh()
    new_vertices = np.asarray(mesh.vertices)
    new_triangles = np.asarray(mesh.triangles)
    updated_vertices = []

    new_mesh.vertices = o3d.utility.Vector3dVector(new_vertices)
    new_mesh.triangles = o3d.utility.Vector3iVector(new_triangles)

    mesh_max_height = find_maximum(mesh)[1][0, 2]
    rng = np.random.default_rng(10)

    for iter_no in range(iterations):
        v_idx_curr = int(vertices_idx[int(rng.random() * vertices.shape[0])])
        print('Iter: ', iter_no, ', V_idx: ', v_idx_curr)

        lifetime = 0
        strength = 0.5
        v_idx_prev = None

        while lifetime < erosion_lifetime:
            neighbors_idx, _ = find_neighbors(new_mesh, v_idx_curr)
            v_idx_next = int(find_minimum(new_mesh, 1, neighbors_idx)[0])

            if v_idx_next not in vertices_idx and direction is None:
                break

            if v_idx_prev:
                if 'vertex_progression' in verbose or 'all' in verbose:
                    print(
                        'Vertex Triples:',
                        v_idx_prev,
                        v_idx_curr,
                        v_idx_next,
                        type(new_vertices[v_idx_prev]),
                        new_vertices[v_idx_prev],
                        new_vertices[v_idx_curr],
                        new_vertices[v_idx_next],
                    )
                vector_1 = new_vertices[v_idx_curr] - new_vertices[v_idx_prev]
                vector_2 = new_vertices[v_idx_next] - new_vertices[v_idx_curr]
                direction_1 = np.sign(vector_1)
                direction_2 = np.sign(vector_2)
                if 'vector_direction' in verbose or 'all' in verbose:
                    print(vector_1, vector_2, direction_1, direction_2, np.dot(direction_1, direction_2))

                if vector_2[2] > 0:
                    break

                vector_1[2] = 0
                vector_2[2] = 0
                norm_vector_1 = np.linalg.norm(vector_1)
                norm_vector_2 = np.linalg.norm(vector_2)
                angle = np.arccos(np.clip(np.dot(vector_1, vector_2) / (norm_vector_1 * norm_vector_2), -1.0, 1.0))
                if 'vector_angle' in verbose or 'all' in verbose:
                    print(vector_1, vector_2, direction_1, direction_2, np.dot(direction_1, direction_2), angle)
                    # if angle < 0:
                    #     print('Negative angle Calculated', angle)
                if angle > np.pi / 2:
                    if 'vector_angle' in verbose or 'all' in verbose:
                        print('Angle found > PI / 2', angle)
                    break

            ray = o3d.core.Tensor([[*new_vertices[v_idx_curr], 0, 0, 1]], dtype=o3d.core.Dtype.Float32)
            if 'ray' in verbose or 'all' in verbose:
                print('ray:', ray, 'vertex:', new_vertices[v_idx_curr])

            ray[0, 2] += 1e-6
            if 'ray' in verbose or 'all' in verbose:
                print('updated ray:', ray, 'vertex:', new_vertices[v_idx_curr])

            raycasting_scene = o3d.t.geometry.RaycastingScene()
            if 'ray_scene' in verbose or 'all' in verbose:
                print('scene:', raycasting_scene)

            if 'mesh' in verbose or 'all' in verbose:
                print('new mesh', new_mesh, type(new_mesh))
            new_mesh_legacy = o3d.t.geometry.TriangleMesh.from_legacy(new_mesh)
            if 'mesh' in verbose or 'all' in verbose:
                print('new mesh legacy', new_mesh_legacy, type(new_mesh_legacy))

            mesh_id = raycasting_scene.add_triangles(new_mesh_legacy)
            if 'mesh' in verbose or 'all' in verbose:
                print('mesh_id:', mesh_id)

            collision = raycasting_scene.cast_rays(ray)
            if 'collision' in verbose or 'all' in verbose:
                print(
                    'collision t_hit:',
                    collision['t_hit'],
                    type(collision['t_hit']),
                    collision['t_hit'].numpy(),
                    type(collision['t_hit'].numpy()),
                )

            if collision['t_hit'].numpy()[0] == np.inf:
                new_vertices[v_idx_curr, 2] -= (
                    strength * abs(new_vertices[v_idx_next, 2] - new_vertices[v_idx_curr, 2]) / mesh_max_height
                )
            else:
                new_vertices[v_idx_curr, 2] += (
                    strength * abs(new_vertices[v_idx_next, 2] - new_vertices[v_idx_curr, 2]) / mesh_max_height
                )

            new_mesh.vertices = o3d.utility.Vector3dVector(new_vertices)
            updated_vertices.append(v_idx_curr)

            lifetime += 1
            strength *= 0.69
            v_idx_prev = v_idx_curr
            v_idx_curr = v_idx_next

    if len(verbose) > 0:
        print('')

    new_mesh.vertices = o3d.utility.Vector3dVector(new_vertices)
    new_mesh.triangles = o3d.utility.Vector3iVector(new_triangles)
    return np.array(updated_vertices), new_mesh


from fastapi import APIRouter
from ..redis.redis_client import rclient

router = APIRouter(prefix="/api/v1.0/ressources/devices",
                   tags=["devices"],
                   responses={404: {"description": "Not found"}}
                   )

@router.get("/")
async def devices():
    devices = []
    olt = rclient.json().get('olt-dasan')
    onus = rclient.json().get('onus-dasan')
    devices.append(olt)
    for onu in onus:
        devices.append(onu)
    return devices


import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
from matplotlib import cm
import numpy as np
import json

fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(0, 0, 0, marker="x", c="red")

with open("targets/pf_zusatz_v3.json") as jsonFile:
    jsonObject = json.load(jsonFile)
    jsonFile.close()
points = jsonObject["ModelData"]['points']

cnt = 1
for point in points:
    ax.scatter(point['x'], point['y'], point['z'], s=100)
    print(f"point_nr: {cnt} x: {point['x']}, y: {point['y']}, z: {point['z']}")
    cnt += 1

ax.set_title("Json points")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
plt.show()

def show_3d():
    shape_points = []
    for point in points:
        shape_points.append([point['x'], point['y'], point['z']])
    shape_points = np.array(shape_points)
    xs = shape_points[:, 0]
    ys = shape_points[:, 1]
    zs = shape_points[:, 2]
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    surf = ax.plot_trisurf(xs, ys, zs, cmap=cm.jet, linewidth=0)
    fig.colorbar(surf)
    ax.xaxis.set_major_locator(MaxNLocator(5))
    ax.yaxis.set_major_locator(MaxNLocator(6))
    ax.zaxis.set_major_locator(MaxNLocator(5))
    fig.tight_layout()
    plt.show()  # or:
    # fig.savefig('3D.png')

#show_3d()


from numpy.lib.function_base import select
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from django.conf import settings
from datetime import datetime
import json
import re
from persiantools.jdatetime import JalaliDateTime
from bs4 import BeautifulSoup

plt.style.use('fivethirtyeight')

def df_to_dict(df,group):
    try:
        nd = {
            'Date': [],
            'Open': [],
            'Close': [],
            'High': [],
            'Low': [],
        }
        if group == 'bourse':
            for i in range(len(df)):
                t = str(df['<DTYYYYMMDD>'].iloc[i])
                t = f'{t[:4]}/{t[4:6]}/{t[6:8]}'
                nd['Date'].append(t)
                nd['Open'].append(df['<OPEN>'].iloc[i])
                nd['Close'].append(df['<CLOSE>'].iloc[i])
                nd['High'].append(df['<HIGH>'].iloc[i])
                nd['Low'].append(df['<LOW>'].iloc[i])
        if group == 'crypto':
            for d in df:
                t = datetime.utcfromtimestamp(d[0])
                nd['Date'].append(t)
                nd['Open'].append(d[1])
                nd['Close'].append(d[2])
                nd['High'].append(d[3])
                nd['Low'].append(d[4])
        return nd
    except:
        return {}

def csv_df_validator(csv):
    name, path = csv['name'], csv['path']
    errors = {}
    if name.split('.')[-1] != 'csv' :
        errors['invalid_extension'] = True
    df = pd.read_csv(path)
    if len(df) < 100 :
        errors['row_length'] = True
    valids = ['Date', 'Close', 'Open', 'High', 'Low']
    if all(v not in df.columns for v in valids):
        errors['invalid_columns'] = True
    return errors

def to_jalali(date,point):
    if point == 'before':
        date = ''.join(date.split('/'))
        return JalaliDateTime.to_jalali(datetime(year=int(date[:4]),
                                                month=int(date[4:6]),
                                                day=int(date[6:8]))).strftime("%Y/%m/%d")
    elif point == 'after':
        if date.hour or date.minute or date.second:
            return JalaliDateTime.to_jalali(datetime(year=date.year,
                                                    month=date.month,
                                                    day=date.day,
                                                    hour=date.hour,
                                                    minute=date.minute,
                                                    second=date.second)).strftime("%Y/%m/%d - %H:%M:%S")
        else:
            return JalaliDateTime.to_jalali(datetime(year=date.year,
                                                    month=date.month,
                                                    day=date.day)).strftime("%Y/%m/%d")

def df_get_info(group, **kwargs):
    df = kwargs.get('df')
    path = kwargs.get('path')
    if path:
        df = pd.read_csv(path)
    info = {}
    if group == 'bourse':
        df = df[::-1].reset_index(drop=True)
        info = {
            'date': {
                'start': to_jalali(df['Date'].iloc[0],point='before'),
                'end': to_jalali(df['Date'].iloc[-1],point='before')
            },
            'rows': len(df)
         }
    if group == 'crypto':
        info = {
            'date': {
                'start': df['Date'].iloc[0],
                'end': df['Date'].iloc[-1]
            },
            'rows': len(df)
         }
    return info

def check_jalali_range(**kwargs):
    start = kwargs.get('start').split('/')
    end = kwargs.get('end').split('/')
    ggStart = JalaliDateTime(year=int(start[0]), month=int(start[1]), day=int(start[2])).to_gregorian()
    ggEnd =  JalaliDateTime(year=int(end[0]), month=int(end[1]), day=int(end[2])).to_gregorian()
    if ggStart >= ggEnd:
        return False
    return True

def df_by_date(df, **kwargs):
    start = kwargs.get('start').split('/')
    end = kwargs.get('end').split('/')
    ggStart = JalaliDateTime(year=int(start[0]), month=int(start[1]), day=int(start[2])).to_gregorian()
    ggEnd =  JalaliDateTime(year=int(end[0]), month=int(end[1]), day=int(end[2])).to_gregorian()
    df['Date'] = pd.DatetimeIndex(df['Date'])
    df = df[(df['Date'] >= ggStart) & (df['Date'] <= ggEnd)]
    df['Date'] = [d.strftime("%Y/%m/%d") for d in df['Date']]
    return df

from abc import ABC, abstractmethod

class Strategy(ABC):

    @abstractmethod
    def run(self) -> dict:
        pass

    def format(self) -> None:
        pass

class MACDCrossover(Strategy):
    table = []

    def __init__(self) -> None:
        pass

    def run(self, file) -> dict:
        try:
            self.file = file
            ticker = self.file['name']
            df = pd.read_csv(self.file['path'])
            df = df.set_index(pd.DatetimeIndex(df['Date']))
            fdf = pd.DataFrame()
            fdf['Close'] = df['Close']
            fdf['SMA30'] = fdf['Close'].rolling(window=30).mean()
            fdf['SMA100'] = fdf['Close'].rolling(window=100).mean()
            sigBuy, sigSell = [], []
            flag = -1
            for i in range(len(fdf)):
                if fdf['SMA30'][i] > fdf['SMA100'][i]:
                    if flag != -1:
                        sigBuy.append(fdf['Close'][i])
                        sigSell.append(np.nan)
                        flag = 1
                    else:
                        sigBuy.append(np.nan)
                elif fdf['SMA30'][i] < fdf['SMA100'][i]:
                    if flag != 0:
                        sigBuy.append(np.nan)
                        sigSell.append(fdf['Close'][i])
                        flag = 0
                    else:
                        sigSell.append(np.nan)
                        sigBuy.append(np.nan)
                else:
                    sigBuy.append(np.nan)
                    sigSell.append(np.nan)
            if not sigBuy and not sigSell:
                return {
                    'success': False
                }
            fdf['Buy'] = sigBuy
            fdf['Sell'] = sigSell
            fdf.to_csv(f"{settings.MEDIA_ROOT}/{ticker}_Signal.csv")
            self.format(df=fdf)
            plt.figure(figsize=(12.2, 6.1),dpi=80)
            plt.plot(fdf['Close'], label= ticker, alpha=0.5)
            plt.plot(fdf['SMA30'], label='SMA30', alpha=0.5)
            plt.plot(fdf['SMA100'], label='SMA100', alpha=0.5)
            plt.scatter(fdf.index, fdf['Buy'], label='Buy', marker='^', color='green')
            plt.scatter(fdf.index, fdf['Sell'], label='Sell', marker='v', color='red')
            plt.xlabel('Date')
            plt.ylabel('Close Price')
            plt.legend(loc='upper left')
            plt.tight_layout()
            plt.savefig(f"{settings.MEDIA_ROOT}/{ticker}_Signal.png")
            return {
                'success': True,
                'csv': settings.MEDIA_URL + f"{ticker}_Signal.csv",
                'img': settings.MEDIA_URL + f"{ticker}_Signal.png",
                'table': self.table
            }
        except:
            return {
                'success': False
            }

    def format(self,df) -> None:
        for i in range(len(df)):
            if pd.notna(df['Buy'].iloc[i]):
                self.table.append({
                    'type': 'خرید',
                    'date': to_jalali(df.index[i],point='after'),
                    'price': df['Buy'].iloc[i]
                })
            elif pd.notna(df['Sell'].iloc[i]):
                self.table.append({
                    'type': 'فروش',
                    'date': to_jalali(df.index[i],point='after'),
                    'price': df['Sell'].iloc[i]
                })

class RSI14(Strategy):
    table = []
    def __init__(self) -> None:
        pass

    def run(self,file) -> dict:
        try:
            self.file = file
            ticker = self.file['name']
            df = pd.read_csv(self.file['path'])
            df = df.set_index(pd.DatetimeIndex(df['Date']))
            fdf = pd.DataFrame()
            fdf['Close'] = df['Close']
            fdf['SMA200'] = fdf['Close'].rolling(window=200).mean()
            fdf['Price Change'] = fdf['Close'].pct_change()
            fdf['Up'] = fdf['Price Change'].apply(lambda x: x if x > 0 else 0)
            fdf['Down'] = fdf['Price Change'].apply(lambda x: abs(x) if x < 0 else 0)
            fdf['AvgUp'] = fdf['Up'].ewm(span=13).mean()
            fdf['AvgDown'] = fdf['Down'].ewm(span=13).mean()
            fdf = fdf.dropna()
            fdf['RS'] = fdf['AvgUp'] / fdf['AvgDown']
            fdf['RSI'] = fdf['RS'].apply(lambda x: 100 - (100/(x+1)))
            fdf.loc[(fdf['Close'] > fdf['SMA200']) & (fdf['RSI'] < 30), 'Buy'] = 'Yes'
            fdf.loc[(fdf['Close'] < fdf['SMA200']) | (fdf['RSI'] > 30), 'Buy'] = 'No'
            # Calc Signal Sell,Buy By RSI14
            sigBuy, sigSell = [], []
            for i in range(len(fdf)):
                if 'Yes' in fdf['Buy'].iloc[i]:
                    sigBuy.append(fdf.iloc[i + 1].name)
                    for j in range(1,11):
                        if fdf['RSI'].iloc[i + j] > 40:
                            sigSell.append(fdf.iloc[i + j + 1].name)
                            break
                        elif j == 10:
                            sigSell.append(fdf.iloc[i + j + 1].name)
            if not sigBuy and not sigSell:
                return {
                    'success': False
                }
            fdf.loc[sigSell, 'Sell'] = 'Yes'
            fdf.loc[set(fdf.index) - set(sigSell), 'Sell'] = 'No'
            fdf.to_csv(f"{settings.MEDIA_ROOT}/{ticker}_Signal.csv")
            self.format(df=fdf)
            plt.figure(figsize=(16.2, 8.1),dpi=80)
            plt.subplot(211)
            plt.plot(fdf['Close'], label= ticker, alpha=0.5)
            plt.plot(fdf['SMA200'], label= 'SMA200', alpha=0.5)
            plt.scatter(fdf.loc[sigBuy].index,fdf.loc[sigBuy]['Close'], marker='^', color='green')
            plt.scatter(fdf.loc[sigSell].index,fdf.loc[sigSell]['Close'], marker='v', color='red')
            plt.tick_params(labelbottom=False)
            plt.ylabel('Close Price')
            plt.legend(loc='upper left')
            plt.subplot(212)
            plt.plot(fdf['RSI'], label='RSI', alpha= 0.5, color='black', linewidth='2')
            plt.plot(fdf.index,np.ones(len(fdf))*30 , linestyle = '--', linewidth='2')
            plt.plot(fdf.index,np.ones(len(fdf))*70 , linestyle = '--', linewidth='2')
            plt.xticks(rotation=45)
            plt.xlabel('Date')
            plt.ylim(0,100)
            plt.legend(loc='upper left')
            plt.tight_layout()
            plt.savefig(f"{settings.MEDIA_ROOT}/{ticker}_Signal.png")
            return {
                'success': True,
                'csv': settings.MEDIA_URL + f"{ticker}_Signal.csv",
                'img': settings.MEDIA_URL + f"{ticker}_Signal.png",
                'table': self.table
            }
        except:
            return {
                'success': False
            }

    def format(self,df) -> None:
        for i in range(len(df)):
            if 'Yes' in df['Buy'].iloc[i]:
                self.table.append({
                    'type': 'خرید',
                    'date': to_jalali(df.index[i],point='after'),
                    'price': df['Close'].iloc[i]
                })
            elif 'Yes' in df['Sell'].iloc[i]:
                self.table.append({
                    'type': 'فروش',
                    'date': to_jalali(df.index[i],point='after'),
                    'price': df['Close'].iloc[i]
                })

class StrategyFactory():
    strategies = {
        'MACD Crossover': MACDCrossover,
        'RSI 14': RSI14
    }
    output = None

    def __init__(self) -> None:
        pass

    def create(self,strategy) -> Strategy:
        if self.strategies.get(strategy):
            self.output = self.strategies[strategy]()
            return self.output

def get_bourse_tickers():

    url = 'http://www.tsetmc.com/Loader.aspx?ParTree=111C1417'
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'html.parser')
    tickers = []
    body = soup.find('table')
    rows = body.find_all('tr')

    for row in rows:
        if rows.index(row) != 0:
            cols = row.find_all('td')
            inscode = cols[6].a['href'].strip()
            inscode = inscode[inscode.rfind('=') + 1:]
            ticker = {
                'inscode': inscode,
                'latinTicker': cols[4].text.strip(),
                'latinName': cols[5].text.strip(),
                'ticker': cols[6].text.strip(),
                'name': cols[7].text.strip()
            }
            tickers.append(ticker)
    return tickers


"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""
from collections import deque

class Solution:
    """
    @param root: A Tree
    @return: Level order a list of lists of integer
    """

    def levelOrder(self, root):
        # write your code here
        if root is None:
            return []
        queue = deque([root]) # 这里面必须要加方括号。
        res = []
        while queue:
            level = []
            for i in range(len(queue)):  # 注意queue在循环种变化， 但是len（queue）在第一次访问的时候就确定了
                root = queue.popleft() # 每一次拿出当前一级的一个点然后加入其对应的左右两个点
                level.append(root.val)
                if root.left:
                    queue.append(root.left)
                if root.right:
                    queue.append(root.right)
            res.append(level)
        return res

#BFS 用queue去实现。这个是后来写的， 比较好理解
from collections import deque
class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res  = []
        q = deque([root])
        while q:
            level = []
            while q:
                level.append(q.popleft())
            res.append([nd.val for nd in level])
            for node in level:
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        return res

Jiuzhang_practice/Binary Tree Level Order Traversal.py


import warnings

import scrapy

from scrapper import util
from scrapper.dbhandler import DBHandler

class TrackUserProfileSpider(scrapy.Spider):
    name = 'track_user_profile'
    start_urls = ['https://soundcloud.com/']

    def __init__(self):
        warnings.simplefilter("ignore")
        self.config = util.load_config()
        util.register_gcp_credential(self.config)
        self.dbhandler = DBHandler(self.config)

    def parse(self, response):
        user_infos = self.dbhandler.select_all_users()
        for user_info in user_infos:
            user_tracks = self.dbhandler.select_user_tracks(user_info[0])
            for user_track in user_tracks:
                self.dbhandler.update_track_user_profile(user_track[0], user_info[1], user_info[2])
                print(user_track[0], user_info[1], user_info[2])


import time
import tkinter as tk
from tkinter import BOTH, END, INSERT, ttk
from tkinter import filedialog as fd
from tkinter.messagebox import showinfo
from turtle import bgcolor
from typing import Callable
from functools import partial
import os
from typing_extensions import Self

from .gui_networking_handlers import NetworkingHandler

class Gui(tk.Tk):
    def __init__(self, title: str):
        super().__init__()

        self.title(title)
        self.geometry('600x400')
        self.resizable(False, False)
        self.style= ttk.Style()
        self.style.theme_use('clam')

        self._create_grid(row_num=6, col_num=2)

        self._select_file_btn = self._create_button(row=1,column=1, columnspan=2,
                                                    text='Select file', command=self._select_file)

        self._msg_received_text_box = self._create_text_box(row=0, column=0, rowspan=4, columnspan=1,
                                                            bg = "black", fg = "white")
        self._msg_send_entry_box = self._create_entry_box(row=4, column=0, rowspan=1, columnspan=1)
        self._sending_port_entry_box = self._create_entry_box(row=3, column=1)
        self._send_text_box_btn = self._create_button(row=5,column=0, text='Send text',
            command=partial(NetworkingHandler.handle_send_message, self._msg_send_entry_box))
        self._progress_bar = self._create_progress_bar(row=6,column=0,rowspan=1,columnspan=2)
        self._combobox = self._create_combobox(row=0,column=1, rowspan=1, columnspan=2)
        self._listener_port_entry_box = self._create_entry_box(row=2, column=1, rowspan=1, columnspan=1)
        self._listen_to_port_btn = self._create_button(row=2, column=2, text='Listen on port',
            command=partial(NetworkingHandler.handle_set_port, self._listener_port_entry_box, self._msg_received_text_box,self._combobox))
        self._connect_to_port_btn = self._create_button(row=3, column=2, text='Connect to port',
            command=partial(NetworkingHandler.handle_connect_to_port, self._sending_port_entry_box,self._msg_received_text_box))

        self._drop_connection_btn = self._create_button(row=4,column=1, rowspan=2, text='Drop connection with server',
                                                        command=NetworkingHandler.handle_stop_client)
        self._drop_listening_btn = self._create_button(row=4,column=2, rowspan=2, text='Drop listening on port',
                                                       command=NetworkingHandler.handle_stop_server)

    def _create_progress_bar(self,row, column, rowspan, columnspan):
        progress_bar = ttk.Progressbar(self,length=1000)
        progress_bar.grid(row=row,column=column, rowspan=rowspan, columnspan=columnspan, sticky='nsew')
        progress_bar['value'] = 0
        return progress_bar

    def _create_grid(self, row_num: int, col_num: int):
        for i in range(row_num):
            self.rowconfigure(i, weight=1)

        for i in range(col_num):
            self.columnconfigure(i, weight=1)

    def _create_button(self, row: int, column: int, rowspan: int = 1, columnspan: int = 1,
                       text: str = None, command: Callable[[], None] = None) ->  ttk.Button:
        button = ttk.Button(self, text=text, command=command)
        button.grid(row=row,column=column, rowspan=rowspan, columnspan=columnspan, sticky='nsew')
        return button

    def _create_entry_box(self, row: int, column: int, rowspan: int = 1, columnspan: int = 1,
                            bg: str = "white", fg: str = "black") -> tk.Entry:
        entry_box = tk.Entry(self, bg=bg, fg=fg)
        entry_box.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, sticky='nsew')
        return entry_box

    def _create_text_box(self, row: int, column: int, rowspan: int = 1, columnspan: int = 1,
                            bg: str = "white", fg: str = "black") -> tk.Text:
        text_box = tk.Text(self, bg=bg, fg=fg, height=10, width=25)
        text_box.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, sticky='nsew')
        return text_box

    def _create_combobox(self, row: int, column: int, rowspan: int = 1, columnspan: int = 1) -> ttk.Combobox:
        cipher_mode = ['ECB', 'CBC']
        self.style.configure("TCombobox", fieldbackground= "white", background= "white")
        combobox = ttk.Combobox(self, state="readonly", textvariable=cipher_mode[0] , values=(cipher_mode))
        combobox.set(cipher_mode[0])
        combobox.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, sticky='nsew')
        combobox.bind("<<ComboboxSelected>>", self._handler_focus_out)
        return combobox

    def _select_file(self):
        self._progress_bar['value'] = 0
        filetypes = (
            ('text files', '*.txt'),
            ('All files', '*.*')
        )

        filename = fd.askopenfilename(
            title='Open a file',
            initialdir=os.getcwd(),
            filetypes=filetypes)

        if not filename:
            return

        showinfo(
            title='Selected File',
            message=filename
        )
        NetworkingHandler.handle_send_file(filename,self._progress_bar)

    def _handler_focus_out(self, _):
        self.focus()


# -*- coding: utf-8 -*-
# @Time : 2023/6/16 22:39
# @Author : XULu
# @Email : xulu_lili@163.com
# @File : test.py
"""
@Description:
"""
import secrets
from Crypto.Cipher import AES

def encrypt(plaintext, key):
    """Encrypt the plaintext using the given AES key"""
    cipher = AES.new(key, AES.MODE_EAX)
    nonce = cipher.nonce
    ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode())
    return nonce + ciphertext + tag

def decrypt(ciphertext, key):
    """Decrypt the ciphertext using the given AES key"""
    nonce = ciphertext[:AES.block_size]
    tag = ciphertext[-AES.block_size:]
    ciphertext = ciphertext[AES.block_size:-AES.block_size]
    cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
    plaintext = cipher.decrypt(ciphertext).decode()
    try:
        cipher.verify(tag)
    except ValueError:
        raise ValueError("Invalid key or ciphertext")
    return plaintext

# 生成随机的 16 字节（128 位）AES 密钥
key = get_key()

# 加密和解密一个字符串
plaintext = "This is a secret message."
ciphertext = encrypt(plaintext, key)
decrypted_text = decrypt(ciphertext, key)

# 打印加密、解密前后的内容
print("Plaintext: ", plaintext)
print("Ciphertext: ", ciphertext)
print("Decrypted text: ", decrypted_text)


from django import forms
from aplicaciones.panel.models import Producto, MediaFiles, Categoria, EspecificacionProducto
from ajax_select.fields import AutoCompleteSelectMultipleField

class ProductoForm(forms.ModelForm):
    class Meta:
        model = Producto
        fields = '__all__'
    prod_fotos = AutoCompleteSelectMultipleField('mediaimg',required=False, help_text='Escriba nombre de la imagen a buscar')
    def __init__(self, *args, **kwargs):
        super(ProductoForm, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({'class': 'form-control'})

class MediaForm(forms.ModelForm):
    class Meta:
        model = MediaFiles
        fields = '__all__'
    def __init__(self, *args, **kwargs):
        super(MediaForm, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({'class': 'form-control'})

        self.fields['media_img'].widget.attrs.update({'@change': 'processFile($event)'})
        self.fields['short_name'].widget.attrs.update({'v-model': 'short_name'})

class CategoriaForm(forms.ModelForm):
    class Meta:
        model = Categoria
        fields = '__all__'
    def __init__(self, *args, **kwargs):
        super(CategoriaForm, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({'class': 'form-control'})
class EspeficicacionForm(forms.ModelForm):
    class Meta:
        model = EspecificacionProducto
        fields = ('esp_item','esp_especificacion')
    def __init__(self, *args, **kwargs):
        super(EspeficicacionForm, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({'class': 'form-control'})


import requests
from bs4 import BeautifulSoup
import openpyxl

locals = [[11, 1125], [12, 1216],[13,1308],[14,1410],[15,1505],[16,1605],[17,1705],[18,1801],[21,2144],[22,2218],[23,2314],[24,2416],[25,2515],[26,2622],[27,2724],[28,2822],[29,2902]]

fpath = r'C:\Users\SM-PC\Desktop\IPS\code\IPS_격리병동수\전국.xlsx'
wb = openpyxl.Workbook()
ws = wb.active  # 현재 활성화된 시트 선택
ws.cell(row=1, column=1).value = 'name'
ws.cell(row=1, column=2).value = 'loc'

row = 2
column = 3

for local in locals:
    city = local[0]
    last_num = local[1]

    for gu in range(int(str(city)+'01'), int(last_num)+1):
        response = requests.get(f'https://portal.nemc.or.kr:444/medi_info/dashboards/dash_total_emer_org_popup_for_egen.do?juso=&lon=&lat=&con=on&emogloca={city}&emogdstr={gu}&asort=A&asort=C&asort=D&rltmCd=O003&rltmCd=O004&rltmCd=O048&rltmCd=O049&rltmCd=O046&rltmCd=O047&rltmCd=O052&rltmCd=O053&rltmCd=O050&rltmCd=O051&rltmCd=O018&rltmCd=O025&rltmC19Cd=O054&rltmC19Cd=O055&rltmC19Cd=O056&rltmC19Cd=O057&rltmC19Cd=O058&rltmC19Cd=O059&afterSearch=map&theme=BLACK&refreshTime=60&spreadAllMsg=allClose&searchYn=Y')
        html = response.text
        soup = BeautifulSoup(html, 'html.parser')
        links = soup.find_all(class_="dash_box")
        # print(links)
        for link in links:
            column = 3
            name = link['data-emogdesc']
            print(name)
            ws.cell(row=row, column=1).value = name
            loc = link.find(class_='info').span.text
            print(loc)
            ws.cell(row=row, column=2).value = loc

            try:

                #link > div > div > table > tbody > tr  > td
                tds = link.find_all('td')
                for td in tds:
                    col = td.select_one('div:nth-child(1)').text
                    data = td.select_one('div:nth-child(2)').text
                    col = ''.join(col.split())
                    data = ''.join(data.split())
                    print(col, data)
                    print(column)
                    ws.cell(row=1, column=column).value = col
                    ws.cell(row=row, column=column).value = data
                    column = column + 1
                row = row + 1
            except:
                print(name+ loc + 'error발생----------------------------------------------------------------------')

wb.save(fpath)

IPS_최종_제출/코드/격리병상수_병원_데이터_크롤링.py

격리병상수_병원_데이터_크롤링.py


import argparse
import sys
import os
import logging

if __name__ == '__main__':
    # Add paths for packages
    cur_path = os.path.abspath(os.path.dirname(__file__))
    sys.path.insert(0, cur_path + "/..")
    logging.basicConfig(level=logging.WARNING)
else:
    logging.basicConfig(level=logging.DEBUG)

from sam.catalog_primitive import *
from sam.catalog_constraint import *

from src.sources.source_fromlist import SourceList
from src.sources.source_fromflatarray import SourceFromFlatArray
from src.filters.on_exchangeformat.filter_boundingbox import FilterBoundingBox
from src.filters.filter_on_op import OpSubPipelineFilter
from src.filters.on_exchangeformat.filter_moduloangle import FilterModuloAngle
from src.filters.utils.filter_log import FilterLog
from src.sinks.sink_slices import SinkSlices
from src.utils.to_dict import yaml_to_dict
from src.utils.flat_array import load_flat_array

from filtering_pipeline.factory import pipeline_factory
from experiments import EXCHANGE_PATH, NORMALIZATION_PATH
import logging

logger = logging.getLogger()

class ExperimentNormalization():

    def __init__(self, dataset='merged'):
        self.catalog_filters = {'SourceFromFlatArray': SourceFromFlatArray,
                                'OpSubPipelineFilter': OpSubPipelineFilter,
                                'SourceList': SourceList,
                                'FilterModuloAngle': FilterModuloAngle,
                                'SinkSlices': SinkSlices,
                                'FilterLog': FilterLog,
                                'FilterBoundingBox': FilterBoundingBox,
                                }
        self.d_conf = yaml_to_dict('config/conf_normalizationpip.yml')
        self.d_conf['FilterBoundingBox']['parms'] ={
            'request_coord': {
                'POINT' : ['x', 'y'],
                'LINE' : ['pnt1', 'pnt2'],
                'ARC' : ['pnt1', 'pnt2','center'],
                'CIRCLE' : 'center',
            },
            'request_length': {
                'ARC' : 'radius',
                'CIRCLE' : 'radius',
                # 'DISTANCE': 'distance_min',
                'LENGTH': 'length',
                'RADIUS': 'radius',
            }}

        self.d_conf['FilterModuloAngle']['parms']['request'] = {
                'ARC': ["angle_start","angle_end"],
                'ANGLE': "angle"
        }

        self.d_conf['SourceFromFlatArray']['parms']['file_path'] = EXCHANGE_PATH.format(dataset)
        self.d_conf['SinkSlices']['parms']['output_path'] = NORMALIZATION_PATH.format(dataset)

    def run_pipeline(self):
        pipeline = pipeline_factory(conf=self.d_conf, catalog_filter=self.catalog_filters)
        last_message = pipeline.execute()

        input_path = self.d_conf['SourceFromFlatArray']['parms']['file_path']
        input_data = load_flat_array(input_path)
        output_path = self.d_conf['SinkSlices']['parms']['output_path']
        output_data = load_flat_array(output_path)

        logger.info(f"Pipeline input is of length {len(input_data)}")
        logger.info(f"Pipeline output is of length {len(output_data)}")

        print(f"Pipeline input is of length {len(input_data)}")
        print(f"Pipeline output is of length {len(output_data)}")

def main():
    parser = argparse.ArgumentParser(description='Run Coarse pipeline')
    parser.add_argument('--dataset', help='train, validation or test')
    args = parser.parse_args()
    ExperimentNormalization(dataset=args.dataset).run_pipeline()

if __name__ == '__main__':
    main()


"""
Code for simulating, visualizing and manipulating additive and
multiplicative functionals.

@authors: Chase Coleman, Balint Skoze, Tom Sargent

"""

import numpy as np
import scipy as sp
import scipy.linalg as la
import quantecon as qe
import matplotlib.pyplot as plt
from scipy.stats import norm, lognorm

class AMF_LSS_VAR:
    """
    This class transforms an additive (multipilcative)
    functional into a QuantEcon linear state space system.
    """

    def __init__(self, A, B, D, F=None, nu=None):
        # Unpack required elements
        self.nx, self.nk = B.shape
        self.A, self.B = A, B

        # checking the dimension of D (extended from the scalar case)
        if len(D.shape) > 1 and D.shape[0] != 1:
            self.nm = D.shape[0]
            self.D = D
        elif len(D.shape) > 1 and D.shape[0] == 1:
            self.nm = 1
            self.D = D
        else:
            self.nm = 1
            self.D = np.expand_dims(D, 0)

        # Create space for additive decomposition
        self.add_decomp = None
        self.mult_decomp = None

        # Set F
        if not np.any(F):
            self.F = np.zeros((self.nk, 1))
        else:
            self.F = F

        # Set nu
        if not np.any(nu):
            self.nu = np.zeros((self.nm, 1))
        elif type(nu) == float:
            self.nu = np.asarray([[nu]])
        elif len(nu.shape) == 1:
            self.nu = np.expand_dims(nu, 1)
        else:
            self.nu = nu

        if self.nu.shape[0] != self.D.shape[0]:
            raise ValueError("The dimension of nu is inconsistent with D!")

        # Construct BIG state space representation
        self.lss = self.construct_ss()

    def construct_ss(self):
        """
        This creates the state space representation that can be passed
        into the quantecon LSS class.
        """
        # Pull out useful info
        nx, nk, nm = self.nx, self.nk, self.nm
        A, B, D, F, nu = self.A, self.B, self.D, self.F, self.nu
        if self.add_decomp:
            nu, H, g = self.add_decomp
        else:
            nu, H, g = self.additive_decomp()

        # Auxiliary blocks with 0's and 1's to fill out the lss matrices
        nx0c = np.zeros((nx, 1))
        nx0r = np.zeros(nx)
        nx1 = np.ones(nx)
        nk0 = np.zeros(nk)
        ny0c = np.zeros((nm, 1))
        ny0r = np.zeros(nm)
        ny1m = np.eye(nm)
        ny0m = np.zeros((nm, nm))
        nyx0m = np.zeros_like(D)

        # Build A matrix for LSS
        # Order of states is: [1, t, xt, yt, mt]
        A1 = np.hstack([1, 0, nx0r, ny0r, ny0r])            # Transition for 1
        A2 = np.hstack([1, 1, nx0r, ny0r, ny0r])            # Transition for t
        A3 = np.hstack([nx0c, nx0c, A, nyx0m.T, nyx0m.T])   # Transition for x_{t+1}
        A4 = np.hstack([nu, ny0c, D, ny1m, ny0m])           # Transition for y_{t+1}
        A5 = np.hstack([ny0c, ny0c, nyx0m, ny0m, ny1m])     # Transition for m_{t+1}
        Abar = np.vstack([A1, A2, A3, A4, A5])

        # Build B matrix for LSS
        Bbar = np.vstack([nk0, nk0, B, F, H])

        # Build G matrix for LSS
        # Order of observation is: [xt, yt, mt, st, tt]
        G1 = np.hstack([nx0c, nx0c, np.eye(nx), nyx0m.T, nyx0m.T])    # Selector for x_{t}
        G2 = np.hstack([ny0c, ny0c, nyx0m, ny1m, ny0m])               # Selector for y_{t}
        G3 = np.hstack([ny0c, ny0c, nyx0m, ny0m, ny1m])               # Selector for martingale
        G4 = np.hstack([ny0c, ny0c, -g, ny0m, ny0m])                  # Selector for stationary
        G5 = np.hstack([ny0c, nu, nyx0m, ny0m, ny0m])                 # Selector for trend
        Gbar = np.vstack([G1, G2, G3, G4, G5])

        # Build H matrix for LSS
        Hbar = np.zeros((Gbar.shape[0], nk))

        # Build LSS type
        x0 = np.hstack([1, 0, nx0r, ny0r, ny0r])
        S0 = np.zeros((len(x0), len(x0)))
        lss = qe.lss.LinearStateSpace(Abar, Bbar, Gbar, Hbar, mu_0=x0, Sigma_0=S0)

        return lss

    def additive_decomp(self):
        """
        Return values for the martingale decomposition
            - nu        : unconditional mean difference in Y
            - H         : coefficient for the (linear) martingale component (kappa_a)
            - g         : coefficient for the stationary component g(x)
            - Y_0       : it should be the function of X_0 (for now set it to 0.0)
        """
        I = np.identity(self.nx)
        A_res = la.solve(I - self.A, I)
        g = self.D @ A_res
        H = self.F + self.D @ A_res @ self.B

        return self.nu, H, g

    def multiplicative_decomp(self):
        """
        Return values for the multiplicative decomposition (Example 5.4.4.)
            - nu_tilde  : eigenvalue
            - H         : vector for the Jensen term
        """
        nu, H, g = self.additive_decomp()
        nu_tilde = nu + (.5)*np.expand_dims(np.diag(H @ H.T), 1)

        return nu_tilde, H, g

    def loglikelihood_path(self, x, y):
        A, B, D, F = self.A, self.B, self.D, self.F
        k, T = y.shape
        FF = F @ F.T
        FFinv = la.inv(FF)
        temp = y[:, 1:] - y[:, :-1] - D @ x[:, :-1]
        obs =  temp * FFinv * temp
        obssum = np.cumsum(obs)
        scalar = (np.log(la.det(FF)) + k*np.log(2*np.pi))*np.arange(1, T)

        return -(.5)*(obssum + scalar)

    def loglikelihood(self, x, y):
        llh = self.loglikelihood_path(x, y)

        return llh[-1]

    def plot_additive(self, T, npaths=25, show_trend=True):
        """
        Plots for the additive decomposition

        """
        # Pull out right sizes so we know how to increment
        nx, nk, nm = self.nx, self.nk, self.nm

        # Allocate space (nm is the number of additive functionals - we want npaths for each)
        mpath = np.empty((nm*npaths, T))
        mbounds = np.empty((nm*2, T))
        spath = np.empty((nm*npaths, T))
        sbounds = np.empty((nm*2, T))
        tpath = np.empty((nm*npaths, T))
        ypath = np.empty((nm*npaths, T))

        # Simulate for as long as we wanted
        moment_generator = self.lss.moment_sequence()
        # Pull out population moments
        for t in range (T):
            tmoms = next(moment_generator)
            ymeans = tmoms[1]
            yvar = tmoms[3]

            # Lower and upper bounds - for each additive functional
            for ii in range(nm):
                li, ui = ii*2, (ii+1)*2
                madd_dist = norm(ymeans[nx+nm+ii], np.sqrt(yvar[nx+nm+ii, nx+nm+ii]))
                mbounds[li:ui, t] = madd_dist.ppf([0.01, .99])

                sadd_dist = norm(ymeans[nx+2*nm+ii], np.sqrt(yvar[nx+2*nm+ii, nx+2*nm+ii]))
                sbounds[li:ui, t] = sadd_dist.ppf([0.01, .99])

        # Pull out paths
        for n in range(npaths):
            x, y = self.lss.simulate(T)
            for ii in range(nm):
                ypath[npaths*ii+n, :] = y[nx+ii, :]
                mpath[npaths*ii+n, :] = y[nx+nm + ii, :]
                spath[npaths*ii+n, :] = y[nx+2*nm + ii, :]
                tpath[npaths*ii+n, :] = y[nx+3*nm + ii, :]

        add_figs = []

        for ii in range(nm):
            li, ui = npaths*(ii), npaths*(ii+1)
            LI, UI = 2*(ii), 2*(ii+1)
            add_figs.append(self.plot_given_paths(T, ypath[li:ui,:], mpath[li:ui,:], spath[li:ui,:],
                                                  tpath[li:ui,:], mbounds[LI:UI,:], sbounds[LI:UI,:],
                                                  show_trend=show_trend))

            add_figs[ii].suptitle( r'Additive decomposition of $y_{%s}$' % str(ii+1), fontsize=14 )

        return add_figs

    def plot_multiplicative(self, T, npaths=25, show_trend=True):
        """
        Plots for the multiplicative decomposition

        """
        # Pull out right sizes so we know how to increment
        nx, nk, nm = self.nx, self.nk, self.nm
        # Matrices for the multiplicative decomposition
        nu_tilde, H, g = self.multiplicative_decomp()

        # Allocate space (nm is the number of functionals - we want npaths for each)
        mpath_mult = np.empty((nm*npaths, T))
        mbounds_mult = np.empty((nm*2, T))
        spath_mult = np.empty((nm*npaths, T))
        sbounds_mult = np.empty((nm*2, T))
        tpath_mult = np.empty((nm*npaths, T))
        ypath_mult = np.empty((nm*npaths, T))

        # Simulate for as long as we wanted
        moment_generator = self.lss.moment_sequence()
        # Pull out population moments
        for t in range (T):
            tmoms = next(moment_generator)
            ymeans = tmoms[1]
            yvar = tmoms[3]

            # Lower and upper bounds - for each multiplicative functional
            for ii in range(nm):
                li, ui = ii*2, (ii+1)*2
                Mdist = lognorm(np.asscalar(np.sqrt(yvar[nx+nm+ii, nx+nm+ii])),
                                scale=np.asscalar( np.exp( ymeans[nx+nm+ii]- \
                                                t*(.5)*np.expand_dims(np.diag(H @ H.T),1)[ii])))
                Sdist = lognorm(np.asscalar(np.sqrt(yvar[nx+2*nm+ii, nx+2*nm+ii])),
                                scale = np.asscalar( np.exp(-ymeans[nx+2*nm+ii])))
                mbounds_mult[li:ui, t] = Mdist.ppf([.01, .99])
                sbounds_mult[li:ui, t] = Sdist.ppf([.01, .99])

        # Pull out paths
        for n in range(npaths):
            x, y = self.lss.simulate(T)
            for ii in range(nm):
                ypath_mult[npaths*ii+n, :] = np.exp(y[nx+ii, :])
                mpath_mult[npaths*ii+n, :] = np.exp(y[nx+nm + ii, :] - np.arange(T)*(.5)*np.expand_dims(np.diag(H @ H.T),1)[ii])
                spath_mult[npaths*ii+n, :] = 1/np.exp(-y[nx+2*nm + ii, :])
                tpath_mult[npaths*ii+n, :] = np.exp(y[nx+3*nm + ii, :] + np.arange(T)*(.5)*np.expand_dims(np.diag(H @ H.T),1)[ii])

        mult_figs = []

        for ii in range(nm):
            li, ui = npaths*(ii), npaths*(ii+1)
            LI, UI = 2*(ii), 2*(ii+1)

            mult_figs.append(self.plot_given_paths(T, ypath_mult[li:ui,:], mpath_mult[li:ui,:],
                                                   spath_mult[li:ui,:], tpath_mult[li:ui,:],
                                                   mbounds_mult[LI:UI,:], sbounds_mult[LI:UI,:], 1,
                                                   show_trend=show_trend))
            mult_figs[ii].suptitle( r'Multiplicative decomposition of $y_{%s}$' % str(ii+1), fontsize=14)

        return mult_figs

    def plot_martingales(self, T, npaths=25):

        # Pull out right sizes so we know how to increment
        nx, nk, nm = self.nx, self.nk, self.nm
        # Matrices for the multiplicative decomposition
        nu_tilde, H, g = self.multiplicative_decomp()

        # Allocate space (nm is the number of functionals - we want npaths for each)
        mpath_mult = np.empty((nm*npaths, T))
        mbounds_mult = np.empty((nm*2, T))

        # Simulate for as long as we wanted
        moment_generator = self.lss.moment_sequence()
        # Pull out population moments
        for t in range (T):
            tmoms = next(moment_generator)
            ymeans = tmoms[1]
            yvar = tmoms[3]

            # Lower and upper bounds - for each functional
            for ii in range(nm):
                li, ui = ii*2, (ii+1)*2
                Mdist = lognorm(np.asscalar(np.sqrt(yvar[nx+nm+ii, nx+nm+ii])),
                                scale=np.asscalar( np.exp( ymeans[nx+nm+ii]- \
                                                t*(.5)*np.expand_dims(np.diag(H @ H.T),1)[ii])))
                mbounds_mult[li:ui, t] = Mdist.ppf([.01, .99])

        # Pull out paths
        for n in range(npaths):
            x, y = self.lss.simulate(T)
            for ii in range(nm):
                mpath_mult[npaths*ii+n, :] = np.exp(y[nx+nm + ii, :] - np.arange(T)*(.5)*np.expand_dims(np.diag(H @ H.T),1)[ii])

        mart_figs = []

        for ii in range(nm):
            li, ui = npaths*(ii), npaths*(ii+1)
            LI, UI = 2*(ii), 2*(ii+1)
            mart_figs.append(self.plot_martingale_paths(T, mpath_mult[li:ui,:],
                                                        mbounds_mult[LI:UI,:], horline=1))
            mart_figs[ii].suptitle(r'Martingale components for many paths of $y_{%s}$' % str(ii+1),
                                   fontsize=14)

        return mart_figs

    def plot_given_paths(self, T, ypath, mpath, spath, tpath, mbounds, sbounds, horline=0, show_trend = True):

        # Allocate space
        trange = np.arange(T)

        # Create figure
        fig, ax = plt.subplots(2, 2, sharey=True, figsize=(15, 8))

        # Plot all paths together
        ax[0, 0].plot(trange, ypath[0, :], label=r"$y_t$", color="k")
        ax[0, 0].plot(trange, mpath[0, :], label=r"$m_t$", color="m")
        ax[0, 0].plot(trange, spath[0, :], label=r"$s_t$", color="g")
        if show_trend:
            ax[0, 0].plot(trange, tpath[0, :], label=r"$t_t$", color="r")
        ax[0, 0].axhline(horline, color="k", linestyle = "-.")
        ax[0, 0].set_title("One Path of All Variables")
        ax[0, 0].legend(loc="top left")

        # Plot Martingale Component
        ax[0, 1].plot(trange, mpath[0, :], "m")
        ax[0, 1].plot(trange, mpath.T, alpha=0.45, color="m")
        ub = mbounds[1, :]
        lb = mbounds[0, :]
        ax[0, 1].fill_between(trange, lb, ub, alpha=0.25, color="m")
        ax[0, 1].set_title("Martingale Components for Many Paths")
        ax[0, 1].axhline(horline, color="k", linestyle = "-.")

        # Plot Stationary Component
        ax[1, 0].plot(spath[0, :], color="g")
        ax[1, 0].plot(spath.T, alpha=0.25, color="g")
        ub = sbounds[1, :]
        lb = sbounds[0, :]
        ax[1, 0].fill_between(trange, lb, ub, alpha=0.25, color="g")
        ax[1, 0].axhline(horline, color="k", linestyle = "-.")
        ax[1, 0].set_title("Stationary Components for Many Paths")

        # Plot Trend Component
        if show_trend:
            ax[1, 1].plot(tpath.T, color="r")
        ax[1, 1].set_title("Trend Components for Many Paths")
        ax[1, 1].axhline(horline, color="k", linestyle = "-.")

        return fig

    def plot_martingale_paths(self, T, mpath, mbounds, horline=1, show_trend = False):
        # Allocate space
        trange = np.arange(T)

        # Create figure
        fig, ax = plt.subplots(1,1, figsize=(10,6))

        # Plot Martingale Component
        ub = mbounds[1, :]
        lb = mbounds[0, :]
        ax.fill_between(trange, lb, ub, color="#ffccff")
        ax.axhline(horline, color="k", linestyle = "-.")
        ax.plot(trange, mpath.T, linewidth=0.25, color="#4c4c4c")

        return fig


import datetime as dt
import json

import pylicy

def mock_get_resources():
    return json.load(open('mock_api_tokens.json'))

def mock_get_datetime():
    return dt.datetime(year=2021, month=12, day=2, hour=0, minute=0)

class TokenAgePolicy(pylicy.Policy):
    """ Checks that a token is < 30 days since last rotation """
    name = 'token_age'

    async def __call__(self, resource, rule):
        rule_context = rule.context or {}
        max_rotation_time = rule_context.get('max_rotation_time', 30)
        warn_rotation_time = rule_context.get('warn_rotation_time', int(0.8 * max_rotation_time))

        time_since_rotation = mock_get_datetime() - dt.datetime.fromisoformat(resource.data['rotated_at'])

        if time_since_rotation > dt.timedelta(days=max_rotation_time):
            return pylicy.PolicyDecision(
                action=pylicy.PolicyDecisionAction.DENY,
                reason=f"Token has exceeded required timeframe for rotation ({max_rotation_time} days)",
                detail={'time_since_rotation': time_since_rotation.days},
            )
        elif time_since_rotation > dt.timedelta(days=warn_rotation_time):
            return pylicy.PolicyDecision(
                action=pylicy.PolicyDecisionAction.WARN,
                reason="Token needs to be rotated soon",
                detail={'time_since_rotation': time_since_rotation.days},
            )
        else:
            return pylicy.PolicyDecision(
                action=pylicy.PolicyDecisionAction.ALLOW,
                reason="Token has been rotated recently",
                detail={'time_since_rotation': time_since_rotation.days},
            )

class TokenNoWildcardPolicy(pylicy.Policy):
    """ Checks that token does not have wildcard perms """
    name = 'token_no_wildcard'

    async def __call__(self, resource, rule):
        invalid_policies = [scope for scope in resource.data['scopes'] if '*' in scope]

        if invalid_policies:
            return pylicy.PolicyDecision(
                action=pylicy.PolicyDecisionAction.DENY,
                reason="One or more policies has a wildcard",
                detail={'wildcard_policies': invalid_policies},
            )
        else:
            return pylicy.PolicyDecision(action=pylicy.PolicyDecisionAction.ALLOW)

if __name__ == '__main__':
    import asyncio
    import pprint
    policies = pylicy.Pylicy.from_yaml('./rules.yml')
    resources = mock_get_resources()
    result = asyncio.run(policies.apply_all([
        pylicy.Resource(id=rsrc['name'], data=rsrc['token']) for rsrc in resources
    ]))
    pprint.pprint(result)


import os
import django

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

from openpyxl import load_workbook
from parcels.models import Parcel

path = os.getcwd()
if 'cargas' in path:
    filepath = ''
else:
    filepath = 'cargas/'

wb = load_workbook(filename=filepath+"map-e.xlsx")

InicEst = wb['Entregas_N_Parcela']
Parcel.objects.all().delete()
for i, row in enumerate(InicEst):
    if i>0:
        Parcel.objects.update_or_create(
            value=row[2].value,
            datep=row[3].value,
            parcel=row[4].value,
            status=row[5].value,
            comment=row[6].value
            )


from sklearn.model_selection import train_test_split
import os
import nltk
import pandas as pd
import numpy as np
from nltk.corpus import stopwords
from matplotlib import pyplot as plt
from wordcloud import WordCloud
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences

def removing_stop_words_1(texts):
    # Removing stop words
    stop_words = set(stopwords.words('english'))
    for i, text in enumerate(texts):
        tokens = nltk.word_tokenize(text)
        sentence = [word for word in tokens if word not in stop_words]
        texts[i] = ' '.join(sentence)

# Removing and counting stop-words, and word frequency
def removing_stop_words(texts):
    # Removing stop words
    stop_words = set(stopwords.words('english'))
    count = 0
    whole_text = ''
    whole_text_sw = ''
    for i, text in enumerate(texts):
        tokens = nltk.word_tokenize(text)
        sentence = []
        whole_text_sw += ' '+text
        for word in tokens:
            if word not in stop_words:
                sentence.append(word)
            else:
                count += 1

        texts[i] = ' '.join(sentence)
        whole_text += ' '+texts[i]

    fdist1 = nltk.FreqDist(nltk.word_tokenize(whole_text))

    return count, fdist1, whole_text, whole_text_sw

def autolabel(rects, ax):
    # Attach a text label above each bar in *rects*, displaying its height.
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, -1),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom')

def plot_hist(x_train):
    print("min: {}, max: {}".format(min(x_train), max(x_train)))
    fig, ax = plt.subplots(figsize=(8, 4))

    # plot the cumulative histogram
    ax.plot(sorted(x_train,reverse=True))
    ax.set_yscale('log')
    ax.grid(True)
    ax.legend(loc='right')
    ax.set_xlabel("Palabras en el vocabulario")
    ax.set_ylabel('Procentage de ocurrencia')
    plt.title("Cuba Hotel Sentiment")
    plt.savefig('analysechs.eps', format='eps')
    plt.show()

def make_analysis(label_index,y_counter):
    fig, ax = plt.subplots()
    rect = ax.bar(label_index, y_counter.values(), width=0.5)
    ax.set_xlabel('Categorías')
    ax.set_ylabel('Ejemplos')
    autolabel(rect, ax)
    ax.set_xticks(label_index)
    ax.set_xticklabels(labels)
    plt.title("Cuba Hotel Sentiment")
    plt.savefig('analysebbcs1.eps', format='eps')
    plt.show()

    # Split dataset into train and test sets, 70% and 30% partitions
    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=12345)

    train = {'data': x_train, 'target': y_train}
    test = {'data': x_test, 'target': y_test}

    texts = train['data']
    removing_stop_words_1(texts)

    tokenizer = Tokenizer()
    tokenizer.fit_on_texts(texts)
    word_index = tokenizer.word_index

    labels_target = test['target']

    print("Number of instances for training: {}".format(len(texts)))

    print("Number of instances for testing: {}".format(len(test['data'])))

    count, wf_1, whole_text_1, whole_text_sw_1 = removing_stop_words(texts)
    count2, wf_2, whole_text_2, whole_text_sw_2 = removing_stop_words(test['data'])

    wf_texts_train = nltk.FreqDist(nltk.word_tokenize(whole_text_sw_1))
    # wf_texts_test = nltk.FreqDist(nltk.word_tokenize(whole_text_sw_1))
    plot_hist(tokenizer.word_counts.values())

    print("Amount of English stop-words for train set: {}".format(count))
    print("Amount of English stop-words for test set: {}".format(count2))
    print("Amount of English stop-words for test set: {}".format(count2 + count))

    print("Word frequency for training set:\n{}".format(wf_1))

    print("Cloud for trainig set")
    word_cloud = WordCloud(collocations=False, background_color='white').generate(whole_text_1)
    plt.imshow(word_cloud, interpolation='bilinear')
    plt.axis("off")
    plt.show()

    print("Word frequency for test set:\n{}".format(wf_2))

    print("Cloud for test set")
    word_cloud = WordCloud(collocations=False, background_color='white').generate(whole_text_2)
    plt.imshow(word_cloud, interpolation='bilinear')
    plt.axis("off")
    plt.show()

if __name__ == "__main__":
    os.chdir('../')
    wdir = os.getcwd()
    file_train = wdir + "/datasets/cuba_hotels_sentiment.xlsx"
    df = pd.read_excel(r'' + file_train, engine='openpyxl')
    print(df.iloc[0, 1])
    print(df.iloc[350, 2])
    print(df.shape)

    y = []
    X = []
    labels = ['1', '2', '3', '4', '5']
    label_index = [x for x in range(len(labels))]
    for i in range(df.shape[0]):
        whole_text = str(df.iloc[i, 0]) + ": " + str(df.iloc[i, 1])
        X.append(whole_text)
        y.append(str(df.iloc[i, 2] - 1))

    X_train, X_dev, y_train, y_dev = train_test_split(X, y, test_size=0.30, random_state=142)
    stt_train = {'input_text': X_train, 'target_text': y_train}
    stt_dev = {'input_text': X_dev, 'target_text': y_dev}

    y_counter={}
    for value in y:
        if value in y_counter.keys():
            y_counter[value]=y_counter[value]+1
        else:
            y_counter[value]=1

    make_analysis(label_index,y_counter)