import urllib
from typing import Any, Optional
from functools import lru_cache

import requests

from starwhale.utils.retry import http_retry
from starwhale.base.uri.instance import Instance
from starwhale.base.uri.exceptions import UriTooShortException

class Project:
    id: str
    name: str
    instance: Instance
    path: str = ""

    def __init__(
        self,
        name: str = "",
        uri: Optional[str] = None,
        instance: Optional[Instance] = None,
    ) -> None:
        """

        :param name: When uri belongs to standalone, it is the name. When uri belongs to cloud, name is the id.
        :param uri: project uri, like "local/project/starwhale" "http://127.0.0.1:8000/project/sw:p-1"
        :param instance: instance object, default is the current selected.
        """
        if name and uri:
            raise Exception("name and uri can not both set")
        # init instance
        if "/" in name:
            uri = name
            name = ""
        self.instance = instance or Instance(uri=uri or "")

        if not name:
            # use project name in path, the path must at least contain project/{name}
            p = self.instance.path.split("/")
            if len(p) >= 2 and p[0] == "project":
                name = p[1]
                self.path = "/".join(p[2:])
            elif len(p) == 1:
                # Compatible with features of URI
                name = p[0]

        if not name:
            # use default project
            name = self.instance.info.get("current_project", "")
        if not name:
            raise Exception("can not init project with empty name")
        self.name = name
        # TODO check if project exists for local and remote
        if self.instance.is_cloud:
            # TODO check whether contains namespace in name(like 'sw:project')?
            self.id = (
                self.name
                if self.name.isdigit()
                else str(
                    get_remote_project_id(
                        self.instance.url, self.instance.token, self.name
                    )
                )
            )
        else:
            self.id = self.name

    @classmethod
    def parse_from_full_uri(cls, uri: str, ignore_rc_type: bool) -> "Project":
        """
        Parse project from full uri.
        we do not parse instance and project info from uri less than 5 parts.
        we prefer that users use `dataset copy mnist -dlp project` rather than `dataset copy project/dataset/mnist`.
        the second is difficult to write correctly at once and the semantics are not very clear.
        and the long uri usually copied from the website.
        """
        if "://" in uri:
            no_schema_uri = uri.split("://", 1)[-1]
        else:
            no_schema_uri = uri

        if "//" in no_schema_uri:
            raise Exception(f"wrong format uri({uri}) with '//'")

        parts = no_schema_uri.split("/")
        exp = len("local/project/self/dataset/mnist".split("/"))
        if ignore_rc_type:
            # ignore type in uri like dataset
            exp = exp - 1

        if len(parts) < exp:
            raise UriTooShortException(
                exp, len(parts), f"can not parse project info from {uri}"
            )
        return cls(uri=uri)

    @property
    def full_uri(self) -> str:
        return "/".join([self.instance.url, "project", self.id])

    def __str__(self) -> str:
        return self.full_uri

    def __repr__(self) -> str:
        return f"<Project {self.full_uri}>"

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Project):
            return False
        return self.full_uri == other.full_uri

@lru_cache(maxsize=None)
@http_retry
def get_remote_project_id(instance_uri: str, token: str, project: str) -> Any:
    resp = requests.get(
        urllib.parse.urljoin(instance_uri, f"/api/v1/project/{project}"),
        headers={
            "Content-Type": "application/json; charset=utf-8",
            "Authorization": token,
        },
        timeout=60,
    )
    resp.raise_for_status()
    return resp.json().get("data", {})["id"]


import logging
import math

from .geomsmesh import geompy
from .geomsmesh import smesh

from .putName import putName

def calculePointsAxiauxPipe_a(facesDefaut, centreFondFiss, wireFondFiss, \
                              lenSegPipe, \
                              nro_cas=None):
  """Maillage selon le rayon de courbure du fond de fissure"""

  logging.info('start')

  # Rayon de courbure maximal
  disfond = list()
  for filling in facesDefaut:
    disfond.append(geompy.MinDistance(centreFondFiss, filling))
  disfond.sort()

  texte = "rcourb: {}, lenSegPipe: {}".format(disfond[0], lenSegPipe)
  logging.info(texte)

  # Maillage 1D
  lgmin = lenSegPipe*0.25
  lgmax = lenSegPipe*1.5
  # la déflexion ets la distance maximale entre une arête du maillage et la courbe support
  nbSegQuart = 5 # on veut 5 segments min sur un quart de cercle
  alpha = math.pi/(4*nbSegQuart)
  deflexion = disfond[0]*(1.0 -math.cos(alpha))
  texte = "==> lgmin: {}, lgmax: {}, deflexion: {}".format(deflexion, lgmin, lgmax)
  logging.info(texte)

  meshFondFiss = smesh.Mesh(wireFondFiss)
  putName(meshFondFiss, "wireFondFiss", i_pref=nro_cas)
  algo1d = meshFondFiss.Segment()
  putName(algo1d.GetSubMesh(), "wireFondFiss", i_pref=nro_cas)
  hypo1d = algo1d.Adaptive(lgmin, lgmax, deflexion) # a ajuster selon la profondeur de la fissure
  putName(hypo1d, "Adaptive_wireFondFiss", i_pref=nro_cas)

  is_done = meshFondFiss.Compute()
  text = "calculePointsAxiauxPipe meshFondFiss.Compute"
  if is_done:
    logging.info(text)
  else:
    text = "Erreur au calcul du maillage.\n" + text
    logging.info(text)
    raise Exception(text)

  return meshFondFiss


from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QGraphicsScene, QGraphicsView, QGraphicsPixmapItem, QDialog
from PyQt5.QtGui import QPixmap, QPainter, QColor, QImage
from gui import Ui_MainWindow
import sys
import math as m
import numpy as np
import matplotlib.pyplot as plt
import cv2
import qimage2ndarray
from PIL import Image, ImageEnhance
import cv2
import numpy as np
# plt.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import pandas as pd
import matplotlib.patches as patches

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # for plot sequence
        self.figure_sequence = plt.figure()
        self.canvas_sequence = FigureCanvas(self.figure_sequence)
        self.ui.horizontalLayout_Sequence.addWidget(self.canvas_sequence)

        # for plot kspace
        self.figure_kspace = plt.figure()
        self.canvas_kspace = FigureCanvas(self.figure_kspace)
        self.ui.horizontalLayout_Kspace.addWidget(self.canvas_kspace)

        # for plot phantom generated
        # self.figure_phantom_Generated = plt.figure()
        # self.canvas_phantom_Generated = FigureCanvas(self.figure_phantom_Generated)
        # self.ui.horizontalLayout_phantom_generated.addWidget(self.canvas_phantom_Generated)

        # adding items to combobox
        self.ui.comboBox_property.addItems(
            ["Original", "T1", "T2", "SD"])

        # connect ui elements to functions
        self.ui.pushButton_Browse.clicked.connect(self.browse)
        self.ui.pushButton_Plot.clicked.connect(self.plot)
        # self.ui.pushButton_Run.clicked.connect(self.freqGradient)
        self.ui.comboBox_property.currentIndexChanged.connect(self.combobox)
        self.ui.label_view_img.mousePressEvent = self.getPixel

    # create a function to get the pixel value of the image
    def getPixel(self, event):
        try:
            # get image from combobox function and convert it to numpy array to get pixel value
            self.orgImg = qimage2ndarray.rgb_view(self.image_orignal)
            self.imgT1 = qimage2ndarray.rgb_view(self.t1(self.image))
            self.imgT2 = qimage2ndarray.rgb_view(self.t2(self.image))
            self.imgSD = qimage2ndarray.rgb_view(self.SD(self.image))

            currentWidth = self.ui.label_view_img.width()
            currentHeight = self.ui.label_view_img.height()

            x = int(((event.pos().x())*64) / currentWidth)
            y = int(((event.pos().y())*64) / currentHeight)

            self.ui.lineEdit_t1.setText(str(self.imgT1[x, y][1]))
            self.ui.lineEdit_t2.setText(str(self.imgT2[x, y][1]))
            self.ui.lineEdit_sd.setText(str(self.imgSD[x, y][1]))
        except Exception as e:
            print(e)

    def browse(self):
        try:
            loadImg = QFileDialog.getOpenFileName(self, 'Open file')
            self.image = cv2.imread(loadImg[0], 0)
            self.image = cv2.resize(self.image, (64, 64))
            # print(self.image.shape)
            self.rgbImage = cv2.cvtColor(self.image, cv2.COLOR_GRAY2RGB)
            self.M = self.rgbImage
            self.k_space = self.rgbImage
            self.image_orignal = qimage2ndarray.array2qimage(self.image)
            self.ui.label_view_img.setPixmap(QPixmap(self.image_orignal))
            # print(self.rgbImage)
            print(self.rgbImage[0][0])
            plt.imshow(self.image, cmap='gray')
            self.RF()

        except Exception as e:
            print(e)

    def Rz(self, theta):
        return np.matrix([[m.cos(theta), -m.sin(theta), 0],
                        [m.sin(theta), m.cos(theta), 0],
                        [0, 0, 1]])

    def RF(self):
        self.rgbImage = np.dot(self.Rx(m.radians(90)), self.rgbImage)
        self.phaseGradient()

    def phaseGradient(self):
        for i, phaseAngle in enumerate(self.decimal_range(0, 360, 5.625)):
            Rz_phase = self.Rz(m.radians(phaseAngle))
            for j in range(63):
                self.M[:, j] = np.dot(Rz_phase, self.rgbImage[:, j])
            self.freqGradient()

    def freqGradient(self):
        self.figure_kspace.clear()
        axs =   self.figure_kspace.add_subplot(111)
        axs.set_title("K-Space")
        axs.set_xlabel("Phase")
        axs.set_ylabel("Frequency")
        axs.imshow(self.k_space, cmap='gray')

        for i, freqAngle in enumerate(self.decimal_range(0, 360, 5.625)):
            Rz_freq = self.Rz(m.radians(freqAngle))
            PixelSummation = np.zeros(3)
            for j in range(63):
                self.M[:, j] = np.dot(Rz_freq, self.M[:, j])
                PixelSummation += self.M[:, j]
            self.k_space[i, :] = PixelSummation

        self.canvas_kspace.draw()
        self.canvas_kspace.flush_events()

    def Rx(self,theta):
        return np.matrix([[ 1          , 0           , 0],
                        [ 0, m.cos(theta),-m.sin(theta)],
                        [ 0, m.sin(theta), m.cos(theta)]])

    def decimal_range(start, stop, increment):
        while start < stop:
            yield start
            start += increment

    def plot(self):
        try:
            self.figure_sequence.clear()
            axs = self.figure_sequence.subplots(5, sharex=True)
            self.figure_sequence.suptitle('Sequence')

            x = np.linspace(-10, 10, 500)
            y1 = np.sinc(x)
            y2 = np.cos(x)
            y3 = np.tan(x)

            axs[0].plot(x, y1 ** 2)
            axs[0].set_ylabel('RF')
            axs[0].set_frame_on(False)
            axs[0].xaxis.set_visible(False)

            axs[1].plot(x, 0.3 * y2)
            axs[1].set_ylabel('GX')
            axs[1].set_frame_on(False)
            axs[1].xaxis.set_visible(False)

            axs[2].plot(x, 0.3 * y2)
            axs[2].set_ylabel('GY')
            axs[2].xaxis.set_visible(False)
            axs[2].set_frame_on(False)

            axs[3].plot(x, 0.3 * y2)
            axs[3].set_ylabel('GZ')
            axs[3].xaxis.set_visible(False)
            axs[3].set_frame_on(False)

            axs[4].plot(x, y3)
            axs[4].set_ylabel('Read Out')
            axs[4].set_frame_on(False)

            self.canvas_sequence.draw()
        except Exception as e:
            print(e)

    # combobox function  for selecting image property
    def combobox(self, index):
        try:
            if index == 0:
                self.ui.label_view_img.setPixmap(QPixmap(self.image_orignal))
            elif index == 1:
                self.ui.label_view_img.setPixmap(QPixmap(self.t1(self.image)))
            elif index == 2:
                self.ui.label_view_img.setPixmap(QPixmap(self.t2(self.image)))
            elif index == 3:
                self.ui.label_view_img.setPixmap(QPixmap(self.SD(self.image)))
            else:
                pass
        except Exception as e:
            print(e)

    # map range function from brain tissue properties to image pixel values
    def map_range(self, input_value):
        try:
            # 2500 is the max value of the property and 255 is the max pixel value
            output_value = input_value * (255 / 300)
            return output_value
        except Exception as e:
            print(e)

    def t1(self, in_image):
        try:
            in_image = cv2.resize(in_image, (256, 256))
            # Define the conditionals and corresponding values
            conditions = [
                in_image == 255,  # white matter
                in_image == 150,  # gray matter
                in_image == 90,   # fat
                in_image == 0     # water
            ]
            values = [self.map_range(500), self.map_range(
            800), self.map_range(250), self.map_range(3000)]

            # Apply the conditionals and assign values in a single step
            shepp_t1 = np.select(conditions, values,
                                 default=255).astype(np.uint8)

            # Convert image to qimage
            shepp_t1 = qimage2ndarray.array2qimage(shepp_t1)
            return shepp_t1
        except Exception as e:
            print(e)

    def t2(self, in_image):
        try:
            # Define the conditionals and corresponding values
            conditions = [
                in_image == 255,  # white matter
                in_image == 150,  # gray matter
                in_image == 90,   # fat
                in_image == 0     # water
            ]
            values = [self.map_range(80), self.map_range(
            100), self.map_range(55), self.map_range(2000)]

            # Apply the conditionals and assign values in a single step
            shepp_t2 = np.select(conditions, values,
                                 default=200).astype(np.uint8)

            # Convert image to qimage
            shepp_t2 = qimage2ndarray.array2qimage(shepp_t2)

            return shepp_t2
        except Exception as e:
            print(e)

    def SD(self, in_image):
        try:
            # Define the conditionals and corresponding values
            conditions = [
                in_image == 255,  # white matter
                in_image == 150,  # gray matter
                in_image == 90,   # fat
                in_image == 0     # water
            ]
            values = [self.map_range(0.1), self.map_range(
                0.2), self.map_range(0.5), self.map_range(0.7)]

            # Apply the conditionals and assign values in a single step
            shepp_SD = np.select(conditions, values,
                                 default=0.7).astype(np.uint8)

            # Convert image to qimage
            shepp_SD = qimage2ndarray.array2qimage(shepp_SD)

            return shepp_SD
        except Exception as e:
            print(e)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    application = ApplicationWindow()
    application.show()
    sys.exit(app.exec_())


"""Miscellaneous functions used for plotting gradient data"""
import gzip
import math
import os.path as op
import pickle

import nibabel as nib
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
from neuromaps.datasets import fetch_fslr
from nilearn import image, masking, plotting
from nilearn.plotting import plot_stat_map
from surfplot import Plot
from surfplot.utils import threshold

def plot_gradient(
    data_dir,
    grad_seg_fnames,
    grad_seg_labels=None,
    cmap="viridis",
    threshold_=None,
    color_range=None,
    views=None,
    title=False,
    layout="grid",
    cbar=False,
    out_dir=None,
    prefix="",
):
    prefix_sep = "" if prefix == "" else "_"
    if not prefix.endswith(prefix_sep):
        prefix = prefix + prefix_sep

    neuromaps_dir = op.join(data_dir, "neuromaps-data")
    surfaces = fetch_fslr(density="32k", data_dir=neuromaps_dir)

    lh, rh = surfaces["inflated"]
    sulc_lh, sulc_rh = surfaces["sulc"]

    for img_i, (grad_segment_lh, grad_segment_rh) in enumerate(grad_seg_fnames):
        if grad_seg_labels is None:
            base_name = op.basename(grad_segment_lh)
            firts_name = base_name.split("_")[0].split("-")[1]
            last_name = base_name.split("_")[1].split("-")[1]
            id_name = base_name.split("_")[2].split("-")[1]
            title_ = f"{firts_name}-{last_name}"
        else:
            title_ = grad_seg_labels[img_i]

        if out_dir is not None:
            out_file = op.join(out_dir, f"{prefix}{title_}.tiff")

        if not op.isfile(out_file):
            lh_grad = nib.load(grad_segment_lh).agg_data()
            rh_grad = nib.load(grad_segment_rh).agg_data()

            if threshold_ is not None:
                lh_grad = threshold(lh_grad, threshold_)
                rh_grad = threshold(rh_grad, threshold_)

            if views:
                p = Plot(surf_lh=lh, views=views, layout=layout)
                p.add_layer({"left": sulc_lh}, cmap="binary_r", cbar=False)
                p.add_layer({"left": lh_grad}, cmap=cmap, cbar=cbar, color_range=color_range)
            else:
                p = Plot(surf_lh=lh, surf_rh=rh, layout=layout)
                p.add_layer({"left": sulc_lh, "right": sulc_rh}, cmap="binary_r", cbar=False)
                p.add_layer(
                    {"left": lh_grad, "right": rh_grad},
                    cmap=cmap,
                    cbar=cbar,
                    color_range=color_range,
                )

            fig = p.build()

            if title:
                fig.axes[0].set_title(title_, pad=-3)

            if out_dir is not None:
                plt.savefig(out_file, bbox_inches="tight", dpi=500)

            plt.close()
            plt.clf()

def plot_subcortical_gradient(subcort_grad_fnames, cmap="viridis", threshold_=None):
    for subcort_grad_fname in subcort_grad_fnames:
        base_name = op.basename(subcort_grad_fname)
        firts_name = base_name.split("_")[0].split("-")[1]
        last_name = base_name.split("_")[1].split("-")[1]
        title_ = f"{firts_name}: {last_name}"

        plot_stat_map(
            subcort_grad_fname,
            draw_cross=False,
            cmap=cmap,
            threshold=threshold_,
            title=title_,
        )
        plt.show()

def plot_meta_maps(
    decoder_fn, map_idxs, threshold=2, model="decoder", colorbar=True, out_dir=None
):
    decoder_file = gzip.open(decoder_fn, "rb")
    decoder = pickle.load(decoder_file)
    if model == "decoder":
        meta_maps = decoder.images_
        features = [f.split("__")[-1] for f in decoder.features_]
        meta_maps_imgs = decoder.masker.inverse_transform(meta_maps[map_idxs, :])
    elif model == "gclda":
        topic_word_weights = decoder.p_word_g_topic_
        n_topics = topic_word_weights.shape[1]
        vocabulary = np.array(decoder.vocabulary)
        sorted_weights_idxs = np.argsort(-topic_word_weights, axis=0)
        top_tokens = [
            "_".join(vocabulary[sorted_weights_idxs[:, topic_i]][:3])
            for topic_i in range(n_topics)
        ]
        features = [f"{i + 1}_{top_tokens[i]}" for i in range(n_topics)]
        meta_maps_imgs = masking.unmask(decoder.p_voxel_g_topic_.T[map_idxs, :], decoder.mask)

    features_to_plot = np.array(features)[map_idxs]
    n_maps = len(map_idxs)
    for i_feature in range(n_maps):
        feature_img_3d = image.index_img(meta_maps_imgs, i_feature)
        plotting.plot_stat_map(
            feature_img_3d,
            draw_cross=False,
            colorbar=colorbar,
            annotate=False,
            threshold=threshold,
            title=features_to_plot[i_feature],
        )
        if out_dir is not None:
            out_file = op.join(out_dir, f"{features_to_plot[i_feature]}.tiff")
            plt.savefig(out_file, bbox_inches="tight", dpi=1000)

        plt.show()

def plot_top_words(model, feature_names, n_top_words, title):
    n_topics = len(model.components_)
    n_cols = 5
    n_rows = math.ceil(n_topics / n_cols)
    w = 30
    h = (w / 2) * n_rows
    fig, axes = plt.subplots(n_rows, n_cols, figsize=(w, h), sharex=True)
    axes = axes.flatten()
    for topic_idx, topic in enumerate(model.components_):
        top_features_ind = topic.argsort()[: -n_top_words - 1 : -1]
        top_features = [feature_names[i] for i in top_features_ind]
        weights = topic[top_features_ind]

        ax = axes[topic_idx]
        ax.barh(top_features, weights, height=0.7)
        ax.set_title(f"Topic {topic_idx +1}", fontdict={"fontsize": 30})
        ax.invert_yaxis()
        ax.tick_params(axis="both", which="major", labelsize=20)
        for i in "top right left".split():
            ax.spines[i].set_visible(False)
        fig.suptitle(title, fontsize=40)

    plt.subplots_adjust(top=0.977, bottom=0.05, wspace=0.90, hspace=0.1)
    plt.show()

def plot_profile(data_df, metric, hue_order, cmap="tab20"):
    # sns.set(style="whitegrid")

    my_cmap = plt.get_cmap(cmap)
    n_segments = 30
    fig, axes = plt.subplots(n_segments, 2)
    fig.set_size_inches(15, 90)

    for seg_sol in range(n_segments):
        test_df = data_df[data_df["segment_solution"] == seg_sol + 3]
        sub_data_df = test_df.drop(columns=["segment_solution", "pvalue"])
        sub_data_df = sub_data_df.pivot_table(
            values=metric, index=sub_data_df["segment"], columns="method"
        )
        sub_data_df = sub_data_df.reindex(hue_order, axis=1)

        sub_data_df.plot.bar(
            rot=0,
            width=1,
            stacked=True,
            color=my_cmap.colors[: len(hue_order)],
            ax=axes[seg_sol, 0],
        )
        axes[seg_sol, 0].get_legend().remove()

        if seg_sol == 0:
            handles, labels = axes[0, 0].get_legend_handles_labels()

        test_df = test_df.reset_index()
        test_df["segment"] = test_df["segment"].astype(str)
        """
        sns.barplot(
            data=test_df,
            x="segment",
            y="max_corr",
            palette=cmap,
            hue="method",
            hue_order=hue_order,
            dodge=True,
            ax=axes[seg_sol , 1],
        )
        axes[seg_sol , 1].get_legend().remove()
        """
        # x = test_df["segment"]
        # y = test_df["max_corr"]
        # axes[seg_sol , 2].plot(x, y, 'o-')
        # axes[seg_sol , 2].get_legend().remove()
        sns.lineplot(
            data=test_df,
            x="segment",
            y=metric,
            palette=cmap,
            hue="method",
            hue_order=hue_order,
            marker="o",
            ax=axes[seg_sol, 1],
        )
        axes[seg_sol, 1].get_legend().remove()

        text_lst = []
        mean_lst = []
        for approach in hue_order:
            approach_df = test_df[test_df["method"] == approach]
            # print(approach_df)
            mean_corr = approach_df[metric]
            text_lst.append(f"{mean_corr.mean():.3f} ± {mean_corr.std():.3f}")
            mean_lst.append(mean_corr.mean())

        ax_handles, ax_labels = axes[seg_sol, 1].get_legend_handles_labels()
        sort_idx = np.argsort(-np.array(mean_lst))
        """
        axes[seg_sol, 1].legend(
            np.array(ax_handles)[sort_idx],
            np.array(text_lst)[sort_idx],
            loc="upper left",
            bbox_to_anchor=(1.04, 1.15),
            ncol=1,
        )
        """
    fig.legend(
        handles,
        labels,
        loc="lower center",
        ncol=6,
        bbox_to_anchor=(0.5, -0.01),
    )

    fig.tight_layout()
    # plt.savefig(op.join(result_dir, "gradient_segmentation", "Figures", "correlation_profile.png"), dpi=300, bbox_inches="tight")
    plt.show()

def plot_mean_profile(data_df, metric, hue_order, cmap="tab20"):
    # sns.set(style="whitegrid")

    fig, ax = plt.subplots(1, 1)
    fig.set_size_inches(3, 15)

    sns.lineplot(
        data=data_df,
        x=metric,
        y="segment_solution",
        palette=cmap,
        hue="method",
        hue_order=hue_order,
        sort=False,
        marker="o",
        ax=ax,
    )
    ax.get_legend().remove()
    # plt.savefig(op.join("./Fig", "mean_correlation_profile.eps"), bbox_inches="tight")
    plt.show()

def _get_twfrequencies(dset_nm, model_nm, n_top_terms, dec_data_dir):
    model_fn = op.join(dec_data_dir, f"{model_nm}_{dset_nm}_model.pkl.gz")
    model_file = gzip.open(model_fn, "rb")
    model_obj = pickle.load(model_file)

    topic_word_weights = (
        model_obj.p_word_g_topic_.T
        if model_nm == "gclda"
        else model_obj.distributions_["p_topic_g_word"]
    )

    n_topics = topic_word_weights.shape[0]
    sorted_weights_idxs = np.argsort(-topic_word_weights, axis=1)
    frequencies_lst = []
    for topic_i in range(n_topics):
        frequencies = topic_word_weights[topic_i, sorted_weights_idxs[topic_i, :]][
            :n_top_terms
        ].tolist()
        frequencies = [freq / np.max(frequencies) for freq in frequencies]
        frequencies = np.round(frequencies, 3).tolist()
        frequencies_lst.append(frequencies)

    return frequencies_lst


import torch
from torch import nn
import numpy as np
import torch.nn.functional as F

def inverse_sigmoid(epoch, k=20):
    return k / (k + np.exp(epoch/k))

class Encoder(nn.Module):

    def __init__(self, input_size, hidden_size, latent_dim, num_layers=1, bidirectional=True):
        super(Encoder, self).__init__()

        if bidirectional == True:
            num_directions = 2
        else:
            num_directions = 1

        self.hidden_size = hidden_size
        self.num_hidden = num_directions * num_layers
        self.lstm = nn.LSTM(batch_first=True,
                            input_size=input_size,
                            hidden_size=hidden_size,
                            num_layers=num_layers,
                            bidirectional=bidirectional)

        self.mu = nn.Linear(self.num_hidden * self.hidden_size, latent_dim)
        self.std = nn.Linear(self.num_hidden * self.hidden_size, latent_dim)
        self.norm = nn.LayerNorm(latent_dim, elementwise_affine=False)

    def forward(self, x):
        x, (h, c) = self.lstm(x)
        h = h.transpose(0, 1).reshape(-1, self.num_hidden * self.hidden_size)

        mu = self.norm(self.mu(h))
        std = nn.Softplus()(self.std(h))

        # reparam
        z = self.reparameterize(mu, std)

        return z, mu, std

    def reparameterize(self, mu, std):
        eps = torch.randn_like(std)

        return mu + (eps * std)

class Conductor(nn.Module):

    def __init__(self, input_size, hidden_size, device, num_layers=2, bar=4):
        super(Conductor, self).__init__()

        num_directions = 1

        self.bar = bar
        self.device = device

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_hidden = num_directions * num_layers

        self.norm = nn.BatchNorm1d(input_size)
        self.linear = nn.Linear(hidden_size, hidden_size)
        self.conductor = nn.LSTM(batch_first=True,
                                 input_size=input_size,
                                 hidden_size=hidden_size,
                                 num_layers=num_layers,
                                 bidirectional=False)

    def init_hidden(self, batch_size, z):
        h0 = z.repeat(self.num_hidden, 1, 1)
        c0 = z.repeat(self.num_hidden, 1, 1)

        return h0, c0

    def forward(self, z):
        batch_size = z.shape[0]
        h, c = self.init_hidden(batch_size, z)
        z = z.unsqueeze(1)

        # initialize
        feat = torch.zeros(batch_size, self.bar, self.hidden_size, device=self.device)

        # conductor
        z_input = z
        for i in range(self.bar):
            z_input, (h, c) = self.conductor(z_input, (h, c))
            feat[:, i, :] = z_input.squeeze()
            z_input = z

        feat = self.linear(feat)

        return feat

class Decoder(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers=2, bidirectional=False):
        super(Decoder, self).__init__()

        if bidirectional == True:
            num_directions = 2
        else:
            num_directions = 1

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
        self.num_hidden = num_directions * num_layers

        self.logits= nn.Linear(hidden_size, output_size)
        self.decoder = nn.LSTM(batch_first=True,
                               input_size=input_size+output_size,
                               hidden_size=hidden_size,
                               num_layers=num_layers,
                               bidirectional=bidirectional)

    def forward(self, x, h, c, z, temp=1):
        x = torch.cat((x, z.unsqueeze(1)), 2)

        x, (h, c) = self.decoder(x, (h, c))
        logits = self.logits(x) / temp
        prob = nn.Softmax(dim=2)(logits)
        out = torch.argmax(prob, 2)

        return out, prob, h, c

class MusicVAE(nn.Module):
    def __init__(self, args):
        super().__init__()
        self.encoder = Encoder(args.enc_input_size, args.enc_hidden_size, args.enc_latent_dim)
        self.conductor = Conductor(args.enc_latent_dim, args.con_hidden_size, args.device)
        self.decoder = Decoder(args.con_hidden_size, args.dec_hidden_size, args.dec_output_size)
        self.bar_units = args.bar_units
        self.num_hidden = self.decoder.num_hidden
        self.hidden_size = self.decoder.hidden_size
        self.output_size = self.decoder.output_size
        self.device = args.device

    def forward(self, x):
        seq_len = x.shape[0]
        latent_z, mu, std = self.encoder(x)
        feat = self.conductor(latent_z)
        x_train_inputs = torch.zeros((x.shape[0], 1, x.shape[2]), device=self.device)
        x_train_label = torch.zeros(x.shape[:-1], device=self.device)
        x_train_prob = torch.zeros(x.shape, device=self.device)
        for j in range(seq_len):
            bar_idx = j // self.bar_units
            bar_change_idx = j % self.bar_units
            z = feat[:, bar_idx, :]
            if bar_change_idx == 0:
                h = z.repeat(self.num_hidden, 1, int(self.hidden_size/z.shape[1]))
                c = z.repeat(self.num_hidden, 1, int(self.hidden_size/z.shape[1]))

            label, prob, h, c = self.decoder(x_train_inputs.to(self.device), h, c, z)

            x_train_label[:, j] = label.squeeze()
            x_train_prob[:, j, :] = prob.squeeze()
            x_train_inputs = x[:, j, :].unsqueeze(1)

        return x_train_prob, mu, std, x_train_label

    def generate(self, bar_units=16, seq_len=64, n=1):
        z = torch.empty((n, 512)).normal_(mean=0,std=1)
        feat = self.conductor(z.cuda())
        batch_size = n
        hidden_size = self.decoder.hidden_size
        output_size = self.decoder.output_size
        num_hidden = self.decoder.num_hidden

        inputs = torch.zeros((batch_size, 1, output_size), device=self.device)
        outputs = torch.zeros((batch_size, seq_len, output_size), device=self.device)
        for j in range(seq_len):
            bar_idx = j // bar_units
            bar_change_idx = j % bar_units

            z = feat[:, bar_idx, :]

            if bar_change_idx == 0:
                h = z.repeat(num_hidden, 1, int(hidden_size/z.shape[1]))
                c = z.repeat(num_hidden, 1, int(hidden_size/z.shape[1]))

            label, prob, h, c = self.decoder(inputs, h, c, z, temp=n)
            outputs[:, j, :] = prob.squeeze()

            inputs = F.one_hot(label, num_classes=output_size)

        return outputs.cpu().detach().numpy()


import requests
from bs4 import BeautifulSoup
from datetime import datetime
from pymongo import MongoClient

client = MongoClient(port=27017)
db = client.historical_data4

def get_coins(url):
    """this function get all coins list"""
    response = requests.get(url)
    coin_list = [i['id'] for i in response.json()]
    return coin_list

def get_csv(coin_id, end_date, start_date=20130428):
    """this function genrates will write into mongo
    db collections"""
    collection = db[coin_id]
    keys = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Market Cap']
    url = 'https://coinmarketcap.com/currencies/\
{0}/historical-data/?start={1}&end={2}'.format(coin_id, start_date, end_date)
    response = requests.get(url)
    html = response.content
    soup = BeautifulSoup(html, 'html.parser')
    table = soup.find('table', attrs={'class': 'table'})
    list_of_rows = []
    for row in table.findAll('tr')[1:]:
        list_of_cells = []
        for cell in row.findAll('td'):
            list_of_cells.append(cell.text)
        list_of_rows.append(dict(zip(keys, list_of_cells)))
    collection.insert(list_of_rows)

current_date = datetime.today().strftime('%Y%m%d')
coins = get_coins('https://api.coinmarketcap.com/v1/ticker/?limit=1')
print ("there are %d coins..", len(coins))
for coin in coins:
    get_csv(coin, current_date)
print("Success all the coins data has been saved....")


import questionary
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from BrokerManager import server as broker_manager
from BrokerManagerReadOnly import server as broker_manager_readonly
import sys

def create_app():
	app = Flask(__name__)

	answer = questionary.select(
		"Which Server do you want to start?",
		choices=["Broker Manager Primary", "Broker Manager Secondary"]
		).ask()

	if answer=="Broker Manager Primary":
		app.register_blueprint(broker_manager)

	if answer=="Broker Manager Secondary":
		app.register_blueprint(broker_manager_readonly)

	return app

port = 5000
if len(sys.argv)>1:
	port = int(sys.argv[1])

if __name__ == '__main__':
    create_app().run(host='0.0.0.0', port=port, debug=True, use_reloader=False)


import pygame
import random

class boss(pygame.sprite.Sprite):

    def __init__(self, game):
        super().__init__()
        self.game = game
        self.health = 350
        self.max_health = 350
        self.attack = 6
        self.image = pygame.image.load('assets/BOSS T.png')
        self.image = pygame.transform.scale(self.image, (500, 500))
        self.rect = self.image.get_rect()
        self.rect.x = 800
        self.rect.y = 200
        self.velocity = 0.01

    def update_health_bar(self, surface):
        #dessiner la bar de vie
        pygame.draw.rect(surface, (255, 0, 0), [self.rect.x + 15, self.rect.y - 20, self.max_health, 5])
        pygame.draw.rect(surface, (111, 210, 46), [self.rect.x + 15, self.rect.y - 20, self.health, 5])

    def forward (self):
        if not self.game.check_collision(self, self.game.all_players):
            self.rect.x -= self.velocity
        #si le monstre est en collision avec J
        else :
            self.game.player.damage(self.attack)

    def damage(self, amount):
        #infliger les degats
        self.health -= amount
        #verifier si son nouveau nombre de pv <= 0
        if self.health <= 0 :
            #reaparaitre comme un nouveau monstre
            self.rect.x = 1000 + random.randint(0, 300)
            self.health = self.max_health
            self.velocity = random.randint(0, 2)
            # ajout du score
            self.game.score += 50


import re
# from urllib.parse import urlparse
# from urllib.parse import urljoin
# from urllib.parse import urldefrag
import urllib
import time
from datetime import datetime
from urllib.robotparser import RobotFileParser
import queue
import random
import socket

import csv
import lxml.html

DEFAULT_AGENT = 'wswp'
DEFAULT_DELAY = 5
DEFAULT_RETRIES = 1
DEFAULT_TIMEOUT = 60

# 链接爬虫
def link_crawler(seed_url, link_regex=None, delay=5, max_depth=-1, max_urls=-1, user_agent='wswp', proxies=None, num_retries=1, scrape_callback=None, cache=None):
    """Crawl from the given seed URL following links matched by link_regex
    """
    # the queue of URL's that still need to be crawled
    crawl_queue = [seed_url]
    # the URL's that have been seen and at what depth
    seen = {seed_url: 0}
    # track how many URL's have been downloaded
    num_urls = 0
    rp = get_robots(seed_url)
    D = Downloader(delay=delay, user_agent=user_agent, proxies=proxies, num_retries=num_retries, cache=cache)
    while crawl_queue:
        url = crawl_queue.pop()
        depth = seen[url]
        # check url passes robots.txt restrictions
        if rp.can_fetch(user_agent, url):
            html = D(url)
            links = []
            if scrape_callback:
                links.extend(scrape_callback(url, html) or [])
            # 避免爬虫陷进
            if depth != max_depth:
                # can still crawl further
                if link_regex:
                    # filter for links matching our regular expression
                    links.extend(link for link in get_links(html) if re.match(link_regex, link))

                for link in links:
                    link = normalize(seed_url, link)
                    # check whether already crawled this link
                    if link not in seen:
                        seen[link] = depth + 1
                        # check link is within same domain
                        if same_domain(seed_url, link):
                            # success! add this new link to queue
                            crawl_queue.append(link)

            # check whether have reached downloaded maximum
            num_urls += 1
            if num_urls == max_urls:
                break
        else:
            print('Blocked by robots.txt:'+ url)

# 下载限速
class Throttle:
    """Throttle downloading by sleeping between requests to same domain
    """

    def __init__(self, delay):
        # amount of delay between downloads for each domain
        self.delay = delay
        # timestamp of when a domain was last accessed
        self.domains = {}

    def wait(self, url):
        domain = urllib.parse.urlparse(url).netloc
        last_accessed = self.domains.get(domain)

        if self.delay > 0 and last_accessed is not None:
            sleep_secs = self.delay - (datetime.now() - last_accessed).seconds
            if sleep_secs > 0:
                time.sleep(sleep_secs)
        self.domains[domain] = datetime.now()

# 下载网页
class Downloader:
    def __init__(self, delay=DEFAULT_DELAY, user_agent=DEFAULT_AGENT, proxies=None, num_retries=DEFAULT_RETRIES, timeout=DEFAULT_TIMEOUT, opener=None, cache=None):
        socket.setdefaulttimeout(timeout)
        self.throttle = Throttle(delay)
        self.user_agent = user_agent
        self.proxies = proxies
        self.num_retries = num_retries
        self.opener = opener
        self.cache = cache

    def __call__(self, url):
        result = None
        # 如果有缓存,不限速
        if self.cache:
            try:
                result=self.cache[url]
            except KeyError:
                pass
            else:
                if self.num_retries > 0 and 500 <= result['code'] < 600:
                    result = None
        if result is None:
            # result was not loaded from cache so still need to download
            self.throttle.wait(url)
            proxy = random.choice(self.proxies) if self.proxies else None
            headers = {'User-agent': self.user_agent}
            result = self.download(url, headers, proxy=proxy, num_retries=self.num_retries)
            if self.cache:
                # save result to cache
                self.cache[url] = result
        return result['html']

    def download(self, url, headers, proxy, num_retries, data=None):
        print('Downloading:', url)
        request = urllib.request.Request(url, data, headers)
        opener = urllib.request.build_opener()
        # 支持代理
        if proxy:
            proxy_params = {urllib.parse.urlparse(url).scheme: proxy}
            opener.add_handler(urllib.request.ProxyHandler(proxy_params))
        try:
            response = opener.open(request)
            html = response.read()
            code = response.code
        except Exception as e:
            print('Download error:', e.reason)
            html = ''
            if hasattr(e, 'code'):
                code = e.code
                if num_retries > 0 and 500 <= code < 600:
                    # retry 5XX HTTP errors
                    return self._get(url, headers, proxy, num_retries - 1, data)
            else:
                code = None
        return {'html': html, 'code': code}

def normalize(seed_url, link):
    """Normalize this URL by removing hash and adding domain
    """
    link, _ = urllib.parse.urldefrag(link)  # remove hash to avoid duplicates
    return urllib.parse.urljoin(seed_url, link)

def same_domain(url1, url2):
    """Return True if both URL's belong to same domain
    """
    return urllib.parse.urlparse(url1).netloc == urllib.parse.urlparse(url2).netloc

# 解析robotx.txt
def get_robots(url):
    """Initialize robots parser for this domain
    """
    rp = RobotFileParser()
    rp.set_url(urllib.parse.urljoin(url, '/robots.txt'))
    rp.read()
    return rp

def get_links(html):
    """Return a list of links from html
    """
    # a regular expression to extract all links from the webpage
    webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE)
    # list of all links from the webpage
    html = html.decode('utf-8')
    return webpage_regex.findall(html)

# 抓取回调的回调类,把得到的数据存到csv表格里
class ScrapeCallback:
    def __init__(self):
        self.writer = csv.writer(open('countries.csv', 'w'))
        self.fields = ('area', 'population', 'iso', 'country', 'capital', 'continent', 'tld', 'currency_code', 'currency_name', 'phone', 'postal_code_format', 'postal_code_regex', 'languages', 'neighbours')
        self.writer.writerow(self.fields)

    def __call__(self, url, html):
        if re.search('/view/', url):

            tree = lxml.html.fromstring(html)
            row = []
            for field in self.fields:
                row.append(tree.cssselect('table > tr#places_{}__row > td.w2p_fw'.format(field))[0].text_content())
            self.writer.writerow(row)

if __name__ == '__main__':
    link_crawler('http://example.webscraping.com/', '/(index|view)', delay=0, num_retries=1,max_depth=1,scrape_callback=ScrapeCallback())
    link_crawler('https://www.lagou.com/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91?px=new&city=%E6%9D%AD%E5%B7%9E#order', delay=0, num_retries=1,max_depth=1,scrape_callback=ScrapeCallback())


import abc
import json
from typing import Any, Dict, List, NoReturn, Optional, Tuple, Union, final

from erniebot_agent.agents.base import BaseAgent
from erniebot_agent.agents.callback.callback_manager import CallbackManager
from erniebot_agent.agents.callback.default import get_default_callbacks
from erniebot_agent.agents.callback.handlers.base import CallbackHandler
from erniebot_agent.agents.mixins import GradioMixin
from erniebot_agent.agents.schema import AgentResponse, LLMResponse, ToolResponse
from erniebot_agent.chat_models.erniebot import BaseERNIEBot
from erniebot_agent.file import GlobalFileManagerHandler
from erniebot_agent.file.base import File
from erniebot_agent.file.file_manager import FileManager
from erniebot_agent.memory import Memory, WholeMemory
from erniebot_agent.memory.messages import Message, SystemMessage
from erniebot_agent.tools.base import BaseTool
from erniebot_agent.tools.tool_manager import ToolManager
from erniebot_agent.utils.exceptions import FileError

_PLUGINS_WO_FILE_IO: Tuple[str] = ("eChart",)

class Agent(GradioMixin, BaseAgent[BaseERNIEBot]):
    """The base class for agents.

    Typically, this is the class that a custom agent class should inherit from.
    A class inheriting from this class must implement how the agent orchestates
    the components to complete tasks.

    Attributes:
        llm: The LLM that the agent uses.
        memory: The message storage that keeps the chat history.
    """

    llm: BaseERNIEBot
    memory: Memory

    def __init__(
        self,
        llm: BaseERNIEBot,
        tools: Union[ToolManager, List[BaseTool]],
        *,
        memory: Optional[Memory] = None,
        system_message: Optional[SystemMessage] = None,
        callbacks: Optional[Union[CallbackManager, List[CallbackHandler]]] = None,
        file_manager: Optional[FileManager] = None,
        plugins: Optional[List[str]] = None,
    ) -> None:
        """Initialize an agent.

        Args:
            llm: An LLM for the agent to use.
            tools: A list of tools for the agent to use.
            memory: A memory object that equips the agent to remember chat
                history. If not specified, a new WholeMemory object will be instantiated.
            system_message: A message that tells the LLM how to interpret the
                conversations. If `None`, the system message contained in
                `memory` will be used.
            callbacks: A list of callback handlers for the agent to use. If
                `None`, a default list of callbacks will be used.
            file_manager: A file manager for the agent to interact with files.
                If `None`, a global file manager that can be shared among
                different components will be implicitly created and used.
            plugins: A list of names of the plugins for the agent to use. If
                `None`, the agent will use a default list of plugins. Set
                `plugins` to `[]` to disable the use of plugins.
        """
        super().__init__()
        self.llm = llm
        if isinstance(tools, ToolManager):
            self._tool_manager = tools
        else:
            self._tool_manager = ToolManager(tools)

        if memory is None:
            self.memory = WholeMemory()
        else:
            self.memory = memory

        if system_message:
            self.system_message = system_message
        else:
            self.system_message = self.memory.get_system_message()
        if callbacks is None:
            callbacks = get_default_callbacks()
        if isinstance(callbacks, CallbackManager):
            self._callback_manager = callbacks
        else:
            self._callback_manager = CallbackManager(callbacks)
        self._file_manager = file_manager
        self._plugins = plugins
        self._init_file_needs_url()

    @final
    async def run(self, prompt: str, files: Optional[List[File]] = None) -> AgentResponse:
        """Run the agent asynchronously.

        Args:
            prompt: A natural language text describing the task that the agent
                should perform.
            files: A list of files that the agent can use to perform the task.

        Returns:
            Response from the agent.
        """
        if files:
            await self._ensure_managed_files(files)
        await self._callback_manager.on_run_start(agent=self, prompt=prompt)
        agent_resp = await self._run(prompt, files)
        await self._callback_manager.on_run_end(agent=self, response=agent_resp)
        return agent_resp

    @final
    async def run_tool(self, tool_name: str, tool_args: str) -> ToolResponse:
        """Run the specified tool asynchronously.

        Args:
            tool_name: The name of the tool to run.
            tool_args: The tool arguments in JSON format.

        Returns:
            Response from the tool.
        """
        tool = self._tool_manager.get_tool(tool_name)
        await self._callback_manager.on_tool_start(agent=self, tool=tool, input_args=tool_args)
        try:
            tool_resp = await self._run_tool(tool, tool_args)
        except (Exception, KeyboardInterrupt) as e:
            await self._callback_manager.on_tool_error(agent=self, tool=tool, error=e)
            raise
        await self._callback_manager.on_tool_end(agent=self, tool=tool, response=tool_resp)
        return tool_resp

    @final
    async def run_llm(self, messages: List[Message], **opts: Any) -> LLMResponse:
        """Run the LLM asynchronously.

        Args:
            messages: The input messages.
            **opts: Options to pass to the LLM.

        Returns:
            Response from the LLM.
        """
        await self._callback_manager.on_llm_start(agent=self, llm=self.llm, messages=messages)
        try:
            llm_resp = await self._run_llm(messages, **opts)
        except (Exception, KeyboardInterrupt) as e:
            await self._callback_manager.on_llm_error(agent=self, llm=self.llm, error=e)
            raise
        await self._callback_manager.on_llm_end(agent=self, llm=self.llm, response=llm_resp)
        return llm_resp

    def load_tool(self, tool: BaseTool) -> None:
        """Load a tool into the agent.

        Args:
            tool: The tool to load.
        """
        self._tool_manager.add_tool(tool)

    def unload_tool(self, tool: BaseTool) -> None:
        """Unload a tool from the agent.

        Args:
            tool: The tool to unload.
        """
        self._tool_manager.remove_tool(tool)

    def get_tools(self) -> List[BaseTool]:
        """Get the tools that the agent can choose from."""
        return self._tool_manager.get_tools()

    def reset_memory(self) -> None:
        """Clear the chat history."""
        self.memory.clear_chat_history()

    async def get_file_manager(self) -> FileManager:
        if self._file_manager is None:
            file_manager = await GlobalFileManagerHandler().get()
        else:
            file_manager = self._file_manager
        return file_manager

    @abc.abstractmethod
    async def _run(self, prompt: str, files: Optional[List[File]] = None) -> AgentResponse:
        """Run the agent asynchronously without invoking callbacks.

        This method is called in `run`.
        """
        raise NotImplementedError

    async def _run_tool(self, tool: BaseTool, tool_args: str) -> ToolResponse:
        """Run the given tool asynchronously without invoking callbacks.

        This method is called in `run_tool`.
        """
        parsed_tool_args = self._parse_tool_args(tool_args)
        file_manager = await self.get_file_manager()
        # XXX: Sniffing is less efficient and probably unnecessary.
        # Can we make a protocol to statically recognize file inputs and outputs
        # or can we have the tools introspect about this?
        input_files = file_manager.sniff_and_extract_files_from_list(list(parsed_tool_args.values()))
        tool_ret = await tool(**parsed_tool_args)
        if isinstance(tool_ret, dict):
            output_files = file_manager.sniff_and_extract_files_from_list(list(tool_ret.values()))
        else:
            output_files = []
        tool_ret_json = json.dumps(tool_ret, ensure_ascii=False)
        return ToolResponse(json=tool_ret_json, input_files=input_files, output_files=output_files)

    async def _run_llm(self, messages: List[Message], functions=None, **opts: Any) -> LLMResponse:
        """Run the LLM asynchronously without invoking callbacks.

        This method is called in `run_llm`.
        """
        llm_ret = await self.llm.chat(messages, functions=functions, stream=False, **opts)
        return LLMResponse(message=llm_ret)

    def _init_file_needs_url(self):
        self.file_needs_url = False

        if self._plugins:
            for plugin in self._plugins:
                if plugin not in _PLUGINS_WO_FILE_IO:
                    self.file_needs_url = True

    def _parse_tool_args(self, tool_args: str) -> Dict[str, Any]:
        try:
            args_dict = json.loads(tool_args)
        except json.JSONDecodeError:
            raise ValueError(f"`tool_args` cannot be parsed as JSON. `tool_args`: {tool_args}")

        if not isinstance(args_dict, dict):
            raise ValueError(f"`tool_args` cannot be interpreted as a dict. `tool_args`: {tool_args}")
        return args_dict

    async def _ensure_managed_files(self, files: List[File]) -> None:
        def _raise_exception(file: File) -> NoReturn:
            raise FileError(f"{repr(file)} is not managed by the file manager of the agent.")

        file_manager = await self.get_file_manager()
        for file in files:
            try:
                managed_file = file_manager.look_up_file_by_id(file.id)
            except FileError:
                _raise_exception(file)
            if file is not managed_file:
                _raise_exception(file)


"""Client library for sending events to the data processing system.

This is for use with the event collector system. Events generally track
something that happens in production that we want to instrument for planning
and analytical purposes.

Events are serialized and put onto a message queue on the same server. These
serialized events are then consumed and published to the remote event collector
by a separate daemon.

See also: https://github.com/reddit/event-collector

"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import calendar
import json
import time
import uuid

from . import MAX_EVENT_SIZE, MAX_QUEUE_SIZE
from baseplate.message_queue import MessageQueue, TimedOutError

class Event(object):
    """An event."""
    def __init__(self, topic, event_type, timestamp=None, id=None):
        self.topic = topic
        self.event_type = event_type
        if timestamp:
            if timestamp.tzinfo and timestamp.utcoffset().total_seconds() != 0:
                raise ValueError("Timestamps must be in UTC")
            self.timestamp = calendar.timegm(timestamp.timetuple()) * 1000
        else:
            self.timestamp = time.time() * 1000
        self.id = id or uuid.uuid4()
        self.payload = {}

    def get_field(self, key, obfuscated=False):
        """Get the value of a field in the event.

        If the field is not present, :py:data:`None` is returned.

        :param str key: The name of the field.
        :param bool obfuscated: Whether to look for the field in the obfuscated
            payload.

        """

        if not obfuscated:
            payload = self.payload
        else:
            payload = self.payload.get("obfuscated_data", {})
        return payload.get(key, None)

    def set_field(self, key, value, obfuscate=False):
        """Set the value for a field in the event.

        :param str key: The name of the field.
        :param value: The value to set the field to. Should be JSON
            serializable.
        :param bool obfuscate: Whether or not to put the field in the obfuscated
            section. This is used for sensitive info like IP addresses that must
            be treated with care.

        """

        # There's no need to send null/empty values, the collector will act
        # the same whether they're sent or not. Zeros are important though,
        # so we can't use a simple boolean truth check here.
        if value is None or value == "":
            return

        if not obfuscate:
            self.payload[key] = value
        else:
            obfuscated_payload = self.payload.setdefault("obfuscated_data", {})
            obfuscated_payload[key] = value

    def serialize(self):
        return json.dumps({
            "event_topic": self.topic,
            "event_type": self.event_type,
            "event_ts": int(self.timestamp),
            "uuid": str(self.id),
            "payload": self.payload,
        })

class EventError(Exception):
    """Base class for event related exceptions."""
    pass

class EventTooLargeError(EventError):
    """Raised when a serialized event is too large to send."""
    def __init__(self, size):
        super(EventTooLargeError, self).__init__(
            "Event is too large to send (%d bytes)" % size)

class EventQueueFullError(EventError):
    """Raised when the queue of events is full.

    This usually indicates that the event publisher is having trouble talking
    to the event collector.

    """
    def __init__(self):
        super(EventQueueFullError, self).__init__("The event queue is full.")

class EventQueue(object):
    """A queue to transfer events to the publisher."""

    def __init__(self, name):
        self.queue = MessageQueue(
            "/events-" + name,
            max_messages=MAX_QUEUE_SIZE,
            max_message_size=MAX_EVENT_SIZE,
        )

    def put(self, event):
        """Add an event to the queue.

        The queue is local to the server this code is run on. The event
        publisher on the server will take these events and send them to the
        collector.

        :param baseplate.events.Event event: The event to send.
        :raises: :py:exc:`EventTooLargeError` The serialized event is too large.
        :raises: :py:exc:`EventQueueFullError` The queue is full. Events are
            not being published fast enough.

        """
        serialized = event.serialize()
        if len(serialized) > MAX_EVENT_SIZE:
            raise EventTooLargeError(len(serialized))

        try:
            self.queue.put(serialized, timeout=0)
        except TimedOutError:
            raise EventQueueFullError


# Built-In Python
import time
from pathlib import Path
import pickle
import random
import logging

# Third-Party
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
from fire import Fire

# Custom
from .population import Population
from .flips import Flips, Flip

class History:
    def __init__(self):
        self.moneyStamps = []
        self.numFlips = []
        self.populationDfs = []

        self.stats = pd.DataFrame(columns=['numFlips', 'money', 'total', 'max', 'min', 'mean', 'median'])\
            .set_index('numFlips', drop=False)

    def __repr__(self):
        return f"<{self.__class__.__name__} | Entries: {len(self)}>"

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

    def add(self, population: Population, numFlips: int):
        self.moneyStamps.append(population.getMoneyStamp())
        self.numFlips.append(numFlips)
        self.populationDfs.append(population.toDf())

    def getStatsOverTime(self, includeTopX=True, logProgress=False):
        df = self.stats
        new_data = []
        if len(self):
            start_flip = len(df)
            for i in tqdm(range(start_flip, len(self)), desc=f'Converting History to df', disable=not logProgress):
                # A DataFrame representing the population after a given number of flips (self.numFlips[i])
                row = self.populationDfs[i]
                # Converting the df to a single row, so it can be a part of the full history df
                row_data = {
                    'numFlips': self.numFlips[i],
                    'money': row.money.values,  # This will be a numpy array, saved in a single cell of the df
                    'total': row.money.sum(),
                    'max': row.money.max(),
                    'min': row.money.min(),
                    'mean': row.money.mean(),
                    'median': row.money.median()
                }
                if includeTopX:
                    # Split the People into bins by
                    money: np.ndarray = row.money.values
                    money[::-1].sort()
                    num_per_percent = round(len(money) * 0.1)
                    _split = np.array_split(money, num_per_percent)
                    use_indices = includeTopX if isinstance(includeTopX, list) else list(range(0, 100))
                    for idx, top_x_range in enumerate(_split):
                        if idx in use_indices:
                            row_data[f"top_{idx}_to_{idx+1}_percent_wealth"] = top_x_range.sum() / row.money.sum() * 100

                new_data.append(row_data)
            new_df = pd.DataFrame(new_data)
            df = pd.concat([self.stats, new_df])
            self.stats = df
        return self.stats

    def save(self, filepath, includeTopX=True):
        df = self.getStatsOverTime(includeTopX=includeTopX)
        df.to_pickle(str(filepath))

class CoinFlipper:
    def __init__(self, population: Population, dollarsPerFlip: int = 1, allowDebt: bool = False, brokeIsOut=True,
                 selectionStyle: str = 'random', cacheDir='flipperCache/cli'):
        self.population = population
        self.dollarsPerFlip = int(dollarsPerFlip)
        self.allowDebt = allowDebt
        self.brokeIsOut = brokeIsOut
        self.selectionStyle = selectionStyle

        self.cacheDir = Path(cacheDir)
        self.flips: Flips = Flips()
        self.history: History = History()
        self.history.add(self.population, numFlips=len(self.flips))

    def __repr__(self):
        return f"<{self.__class__.__name__}>"

    def descriptiveFilepath(self, directory: Path = '.'):
        directory = Path(directory)
        return directory.joinpath(f'people_{len(self.population)}_start_{self.population[0].startMoney}_'
                                  f'bet_{self.dollarsPerFlip}_debt_{self.allowDebt}_'
                                  f'flips_{len(self.flips)}.pickle')

    @property
    def numFlips(self):
        return len(self.flips)

    def flip(self, num: int = 1, saveEvery=0, plotEvery=0, plotKind='topXPercentRanges', logProgress=False,
             saveHistory=True, closePlt=True):
        """Flip a coin some number of times and settle the bets"""
        for i in tqdm(range(num), total=num, unit='flips', desc='Flipping Coins', disable=not logProgress):
            self.flipOnce()

            if saveHistory:
                self.history.add(self.population, numFlips=len(self.flips))

            if saveEvery and len(self.flips) > 0 and len(self.flips) % saveEvery == 0:
                filepath = self.descriptiveFilepath(self.cacheDir)
                self.save(filepath, history=True)
            if plotEvery and len(self.flips) % plotEvery == 0:
                self.population.plot(t=0.1, keepAx=True, kind=plotKind,
                                     title=f'Population after {i + 1:,} flips (Total: ${self.population.totalMoney:,})')
        if closePlt:
            plt.close()

    def flipOnce(self):
        # Pick 2 random people from the group to "flip" against each other
        p1, p2 = self.getPeople(2)
        winner = random.choice([p1, p2])
        loser = p1 if winner == p2 else p2
        # Since both are random selections, we just assume the "first" one was the winner
        flip = Flip(winner=winner, loser=loser, bet=self.dollarsPerFlip)
        # Log the flip
        self.flips.append(flip)

        if loser.has(self.dollarsPerFlip) or self.allowDebt:
            flip.settleBet()

    def getPeople(self, n):
        pop = self.population.getPeopleWithMoreThan(0) if self.brokeIsOut else self.population
        if self.selectionStyle == 'random':
            return pop.pickRandoms(n)
        elif self.selectionStyle == 'sequential':
            if self.brokeIsOut:
                raise Exception(f'Can not use sequential selection when brokeIsOut is set to True.')
            nex = [pop.next(loop=True) for _ in range(n)]
            return nex
        else:
            raise Exception(f"Unknown selectionStyle: {self.selectionStyle}")

    def save(self, filepath, history=True, includeTopX=True):
        filepath = Path(filepath)
        if filepath.is_dir() or not filepath.suffix:
            filepath = self.descriptiveFilepath(filepath)
        filepath.parent.mkdir(parents=True, exist_ok=True)

        with open(str(filepath), 'wb') as pf:
            pickle.dump(self, pf)

        if history:
            self.history.save(filepath.with_stem(f"{filepath.stem}_history"), includeTopX=includeTopX)

    @classmethod
    def load(cls, filepath):
        filepath = Path(filepath)
        if filepath.exists():
            flipper: cls
            with open(str(filepath), 'rb') as pf:
                try:
                    flipper = pickle.load(pf)
                except (EOFError, pickle.UnpicklingError):
                    filepath.unlink(missing_ok=True)
                    raise EOFError(f"There was a problem loading {filepath}. It has been deleted.")

            if len(flipper.history) > 0 and flipper.history.stats.empty:
                # TODO: History cached stats do not seem to be loaded here...
                # This is a tmp solution until I can dig into the pickling / unpickling procedures
                history_path = filepath.with_stem(f'{filepath.stem}_history')
                if history_path.exists():
                    logging.debug(
                        'Warning: FlipperManager history stats were not loaded correctly. Manually loading now')
                    flipper.history.stats = pd.read_pickle(str(history_path))
            return flipper
        else:
            raise Exception(f"Filepath does not exist")

def flipCoins(numFlips=10_000, numPeople=1000, startMoney=100, dollarsPerFlip=1, allowDebt=False,
              plot=False, plotEvery=100, saveHistory=False, showResults=True, plotKind='topXPercentRanges',
              useCache=False):

    people = Population([])
    people.add(numPeople, startMoney)

    flipper = CoinFlipper(people, dollarsPerFlip, allowDebt)
    flipper.flip(numFlips, saveEvery=0, plotEvery=plotEvery if plot else 0, logProgress=True, saveHistory=saveHistory,
                 plotKind=plotKind, closePlt=False)

    if useCache:
        cache_dir = Path('flipperCache/cli')
        flipper_path = cache_dir.joinpath(
            f'people_{numPeople}_start_{startMoney}_bet_{dollarsPerFlip}_debt_{allowDebt}_'
            f'flips_{numFlips}.pickle')
        flipper.save(flipper_path)

    if showResults:
        print()
        print('Results:')
        print(flipper.population.getStatsByTopXRanges())

    print('Done flipping!')
    if plot:
        flipper.population.plot(kind=plotKind, keepAx=True,
                                title=f'Population after {len(flipper.flips):,} flips '
                                      f'(Total: ${flipper.population.totalMoney:,})')

    if len(flipper.history):
        flipper.history.getStatsOverTime()

if __name__ == '__main__':
    Fire(flipCoins)


import pandas as pd
import numpy as np
import streamlit as st
import plotly.express as px
from sklearn.datasets import fetch_california_housing
from sklearn.metrics import mean_squared_error

def main(verbosity=False):
    cal_housing = fetch_california_housing()
    df = pd.DataFrame(cal_housing.data, columns=cal_housing.feature_names)
    y = cal_housing.target

    X = df['MedInc']

    st.dataframe(X)
    st.dataframe(y)

    beta, y_pred = my_reg(X, y)

    st.dataframe(y_pred)

    res_df = pd.DataFrame(dict(X=X, y=y, y_pred=y_pred))

    fig = px.scatter(res_df, x="X", y=["y", 'y_pred'])

    st.plotly_chart(fig, use_container_width=True)

    st.latex(fr"Price = {beta[1]:.4f} \times MedInc + {beta[0]:.4f}")
    st.write(f'You do loss  : {mean_squared_error(y, y_pred)}')

def my_reg(X, y, verbose=False):
    print("-------- start --------")
    # My formula : y = Θ(1-e^-(y-b0-b1*x)^2)
    beta = np.random.random(2)
    alpha = 0.002
    n_max_iter = 10000
    theta = 0.001

    for it in range(n_max_iter):
        y_pred: np.ndarray = beta[0] + beta[1] * X

        g_b0 = (-2 * theta * (y - y_pred) * np.exp(-1 * (y - y_pred) ** 2)).sum()
        g_b1 = (-2 * theta * X * (y - y_pred) * np.exp(-1 * (y - y_pred) ** 2)).sum()
        print(f"({it}) beta: {beta}, gradient: {g_b0} {g_b1}")

        beta_prev = np.copy(beta)

        beta[0] = beta[0] - alpha * g_b0
        beta[1] = beta[1] - alpha * g_b1

        if np.linalg.norm(beta - beta_prev) < alpha/100:
            print(f"I do early stoping at iteration {it}")
            break
    print(f'You do loss  : {mean_squared_error(y, y_pred)}')
    return beta, y_pred

if __name__ == '__main__':
    main(st.sidebar.checkbox("verbosity"))


from setuptools import setup
import os
import sys
import codecs

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

def read(*parts):
    # intentionally *not* adding an encoding option to open
    return codecs.open(os.path.join(here, *parts), 'r').read()

install_requires = [
    "virtualenv==15.1.0",
    "requests>=2.9.1,<3.0.0",
]

if sys.version_info[:2] == (2, 6):
    install_requires += [
        'argparse',
    ]

setup(
    name='cloudify-agent-packager',
    version='5.0.11',
    url='https://github.com/cloudify-cosmo/cloudify-agent-packager',
    author='Cloudify',
    author_email='cosmo-admin@cloudify.co',
    license='LICENSE',
    platforms='All',
    description='Creates Cloudify Agent Packages',
    long_description=read('README.md'),
    packages=['agent_packager'],
    entry_points={
        'console_scripts': [
            'cfy-ap = agent_packager.cli:main',
        ]
    },
    install_requires=install_requires,
    include_package_data=True
)


import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np

x = np.linspace(0,2,201)
y = np.linspace(0,1,101)

xy, yx = np.meshgrid(x,y)

ims = []

tmin, tmax = 0, 0.02

h = 1e-3

fig = plt.figure()

for i in range(int(np.ceil((tmax-tmin)/h))):
    plt.pcolormesh(xy,yx,np.sin(xy+np.pi*i*h)+np.cos(yx+np.pi*i*h),
                  cmap='RdBu_r')
    plt.show()
    plt.pause(0.01)
    plt.clf()


import os
import datetime
from jira import JIRA

class JiraIssueReporterHandler(object):

    def __init__(self, jiraURL, username, api_token, projectKey):
        self.options = {'server': jiraURL}
        # self.server = jiraURL
        self.auth = (username, api_token)
        self.projectKey = projectKey
        # self.customField_Test_Method = customField_TestMethod

    def get_jira_client(self):
        return JIRA(self.options, basic_auth=self.auth)

    def create_new_bug(self, summary, description):
        jira = self.get_jira_client()
        new_bug = None
        try:
            # Create new issue with issue type is Bug
            new_bug = jira.create_issue(project=self.projectKey, summary=summary,
                                        description=description, issuetype={'name': 'Bug'})

        except Exception as ex:
            print(ex)
        finally:
            if new_bug:
                return new_bug.key
        return None

    def add_bug_comment(self, bug_id, comment):
        jira = self.get_jira_client()
        try:
            bug = jira.issue(bug_id)
            # comment = "This issue is still {color:red}*FAILING*{color}"

            # Add comment
            jira.add_comment(bug, comment)

        except Exception as ex:
            print(ex)

    def get_issue_status(self, issue_id):
        jira = self.get_jira_client()
        try:
            issue = jira.issue(issue_id)
            status = issue.fields.status.name
            return status

        except Exception as ex:
            print(ex)

    def mark_issue_status(self, issue_id, status):
        jira = self.get_jira_client()
        try:
            issue = jira.issue(issue_id)
            transitions = jira.transitions(issue)
            for transition in transitions:
                if transition['name'] == status:
                    jira.transition_issue(issue, transition['id'])
                    break

        except Exception as ex:
            print(ex)

    def get_today(self):
        return datetime.datetime.now().strftime("%Y-%m-%d-%H:%M:%S")


from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    # path('', views.TaskListView.as_view(), name='home'),
    # path('add/', views.TaskCreateView.as_view(), name='add'),
    path('detail/<int:pk>/', views.TaskDetailView.as_view(), name='detail'),
    path('delete/<int:pk>/', views.TaskDeleteView.as_view(), name='delete'),
    path('update/<int:pk>', views.TaskUpdateView.as_view(), name='update')
]


import json
import yaml

def refs_to_dict(filename):
    data = yaml.load(open(filename), Loader=yaml.CLoader)
    return {elem['id']: elem['title'] for elem in data.get('references', [])}

refs = {elem['id']: elem['title'] for elem in json.load(open('wg21/data/csl.json'))}
refs.update(refs_to_dict('md/wg21_fmt.yaml'))
refs.update(refs_to_dict('md/early.yaml'))

print(json.dumps(refs, indent=4))


#! /usr/bin/env python3

# pylint: disable=missing-module-docstring,missing-function-docstring

from . import std_headers
from .utils import Object

def customHeaderIdentificationHandler(header):
    """
    A couple of headers don't fit into the target identification heuristics
    we have implemented in CppSourceDepsParser. We need custom handler to
    identify the corresponding targets for those headers.
    """
    return None

def getDefaultConfigs():
    configs = Object()
    # These top level directories are not source code directory. Build system
    # should ignore them. DepG should not visit these directories to generate
    # targets. Hence top level directories like `build/`, `third_party`,
    # `tools` etc. should be forbidden.
    configs.FORBIDDEN_PATHS = set([])

    # Ignored paths are different from forbidden paths. These paths will be ignored
    # by default. However if these paths are explicitly chosen, they will work as
    # usual. For example, we don't want to build the code in experimental
    # directories if someone choose to build root directory. However the
    # code in experimental should be compliable if the 'experimental' directory is
    # explicitly chosen.
    configs.IGNORED_PATHS = set(["experimental"])

    configs.CPP_HEADER_EXTENSIONS = ("-inl.hpp", ".hpp", ".h")
    configs.CPP_SOURCE_EXTENSIONS = (".cpp", ".cc", ".c")
    configs.PROTO_HEADER_EXTENSION = ".pb.h"
    configs.GRPC_HEADER_EXTENSION = ".grpc.pb.h"
    configs.PROTO_EXTENSION = ".proto"
    configs.TEST_FILE_EXTENSION = "_test.cpp"

    configs.IGNORED_HEADERS = set(["options.pb.h"])

    configs.INCLUDE_PATHS = [ "." ]

    configs.IGNORE_EXISTANCE = set([])

    configs.CACHE_DIRECTORY = "build/.depg/cache"

    configs.BUILD_FILE_NAME = "BUILD"

    configs.THIRD_PARTY_TARGET_BUILD_FILES = []
    configs.HEADER_PREFIXES_MAP = None

    configs.GTEST_MAIN_TARGET = None # "testing/gtest/gtest_with_glog_main"

    configs.SYS_STD_HEADERS = set(std_headers.STD_HEADERS) | set(std_headers.SYSTEM_HEADERS)

    configs.CUSTOM_HEADER_IDENTIFICATION_HANDLER = customHeaderIdentificationHandler

    # DepG doesn't recompute the deps of a C++ source file if the content of file have not changed.
    # However if it is supposed to depend on external factors (for example change in header-prefix
    # declaration of third-party targets), we would like to re-generate it.
    # In that case we must compute the checksum of those dependency content and
    # set to `configs.DEPG_DEPS_CACHE_CHECKSUM`.
    configs.DEPG_DEPS_CACHE_CHECKSUM = None

    return configs


# type: ignore
from functools import cached_property
from dataclasses import dataclass, field
from pathlib import Path

@dataclass
class File:
    path: Path
    size: int

@dataclass
class Dir:
    path: Path
    files: list[File] = field(repr=False, default_factory=list)
    dirs: list["Dir"] = field(repr=False, default_factory=list)

    @cached_property
    def size(self):
        return sum(item.size for item in (*self.files, *self.dirs))

with open("input") as f:
    lines = [line.strip() for line in f]

root = Path('/')
fs = {root: Dir(root)}
cwd = root
for line in lines[1:]:
    if line.startswith('$'):
        parts = line.split()
        cmd = parts[1]
        if cmd != 'cd':
            continue
        arg = parts[2]
        if arg == '..':
            cwd = cwd.parent
        else:
            cwd /= arg
    else:
        size, fname = line.split()
        path = cwd / fname
        if size == 'dir':
            file = Dir(path)
            fs[cwd].dirs.append(file)
        else:
            file = File(path, int(size))
            fs[cwd].files.append(file)

        fs[path] = file

print("Part 1:", sum(f.size for f in fs.values() if isinstance(f, Dir) and f.size <= 100000))

total = 7e7
need = 3e7
have = total - fs[root].size
for thing in sorted((f for f in fs.values() if isinstance(f, Dir)), key=lambda x: x.size):
    if have + thing.size >= need:
        print("Part 2:", thing.size)
        break


from django.shortcuts import render, redirect
from .models import Reply
from review.models import Review
from .forms import ReplyForm
from django.contrib import messages
from django.core.exceptions import PermissionDenied

def Reply(request, pk):
    """ Model for staff to reply to user reviews on menu """
    review = Review.objects.get(id=pk)
    form = ReplyForm()
    # nun-staff access lead to 403 page
    if not request.user.is_staff:
        raise PermissionDenied()

    if request.method == 'POST':
        form = ReplyForm(request.POST, request.FILES)
        if form.is_valid():
            reply = form.save(commit=False)
            reply.user = request.user
            reply.review = review
            reply.save()
            # flash message
            messages.success(
                request, 'Your successfully replied to the review!')
        return redirect('item-reviews', menu_id=review.menu_item.id)

    context = {
        'form': form,
        'review_id': review.id,
        'review': review
    }

    return render(request, 'reply/reply.html', context)


from os import environ, listdir
from os.path import join, isfile, getmtime
from dataclasses import dataclass, field
import json
import time
import traceback
from datetime import datetime,timezone
savedGamePath = environ['USERPROFILE'] + "\Saved Games\Frontier Developments\Elite Dangerous"
@dataclass
class mission:
    id: int
    localisedName: str = ''
    reward: int = 0
    wing: bool = False
    def __hash__(self) -> int:
        return hash(self.id)
    def __eq__(self, __o: object) -> bool:
        return self.id == __o.id
@dataclass
class Journal:
    @dataclass
    class log:
        path: str = ''
        version: str = ''
        latestUpdate: float = 0.0
        updateInterval: float = 0.0
        raw: str = ''
    @dataclass
    class ship:
        model: str = ''
        name: str = ''
        ident: str = ''
        fuel: float = 0.0
        fuelCap: float = 0.0
        fuelLevel: int = 100 # round((fuel/fuelCap)*100) %
        isScooping: bool = False
        hull: float = 0.0
        cargoCap: int = 0
        jumpRange: float = 0.0
        modules: list = field(default_factory=list)
    @dataclass
    class nav:
        navRoutes: list = field(default_factory=list)
        location: str = ''
        lastTarget: str = ''
        target: str = ''
        targetStarClass: str = ''
        remainingJumps: int = 0
        dockedStation: str = ''
    status: str = ''
    signs: set = field(default_factory=set) # unique signs
    missions: set[mission] = field(default_factory=set)
journal = Journal()
# STATUS: normal,undocking,docking,startUndock,startDock,docked,startJump,finishJump,supercruise
def getNavRoute(routePath=None):
    if not routePath:
        routePath = savedGamePath+r"\NavRoute.json"
    pass # WIP

def getLatestLogPath(logPath=None):
    if not logPath:
        logPath = savedGamePath
    logsList = [join(logPath, f) for f in listdir(logPath) if isfile(join(logPath, f)) and f.startswith('Journal.')]
    if not logsList:
        return None
    latestLog = max(logsList, key=getmtime)
    return latestLog

UTC_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
latestLogLine = 0
def parseLogs(logPath=None,logger=None) -> Journal:
    global latestLogLine, journal
    if not logPath:
        logPath = getLatestLogPath()
    try:
        linesRead = 0
        with open(logPath, 'r', encoding='utf-8') as f:
            for line in f:
                journal.log.path = logPath
                logJson = json.loads(line)
                logEvent = logJson['event']
                # Event Filters start
                if logEvent == "FSSSignalDiscovered" or \
                   logEvent == "Friends" or \
                   logEvent == "Powerplay" or \
                   logEvent == "NpcCrewPaidWage" or \
                   logEvent == "MissionRedirected" or \
                   logEvent == "Statistics" or \
                   logEvent == "Materials":
                   continue
                # Event Filters end
                linesRead += 1
                if linesRead>latestLogLine:
                    logTime = datetime.strptime(logJson['timestamp'],UTC_FORMAT).replace(tzinfo=timezone.utc) # change to UTC time
                    logTime = logTime.timestamp()
                    if logTime>=journal.log.latestUpdate: # should update
                        latestLogLine += 1
                        journal.log.latestUpdate=logTime
                        journal.log.updateInterval = time.time()-logTime
                        journal.log.raw = logJson
                        # print(logEvent+' ')
                        # print(logTime)
                        if logEvent == 'Fileheader':
                            journal.log.version = 'Odyssey' if logJson['Odyssey'] else 'Horizons'

                        elif logEvent == 'Loadout':
                            journal.ship.model = logJson['Ship']
                            journal.ship.name = logJson['ShipName']
                            journal.ship.ident = logJson['ShipIdent']
                            journal.ship.hull = logJson['HullHealth']
                            journal.ship.fuelCap = logJson['FuelCapacity']['Main']
                            journal.ship.cargoCap = logJson['CargoCapacity']
                            journal.ship.jumpRange = logJson['MaxJumpRange']
                            journal.ship.modules = logJson['Modules']

                        elif logEvent == 'RefuelAll' or logEvent == 'RefuelPartial':
                            journal.ship.fuel += logJson['Amount']
                            journal.ship.fuelLevel = round((journal.ship.fuel/journal.ship.fuelCap)*100)
                        elif logEvent == 'FuelScoop':
                            journal.ship.fuel += logJson['Scooped']
                            journal.ship.fuelLevel = round((journal.ship.fuel/journal.ship.fuelCap)*100)
                            if journal.log.updateInterval <= 10 and journal.ship.fuelLevel < 99: journal.ship.isScooping = True
                            else: journal.ship.isScooping = False

                        elif ((logEvent == 'ReceiveText' and 'AttackDutyStart' in logJson['Message']) or logEvent == 'Interdicted' or logEvent == 'UnderAttack' or (logEvent == 'Music' and (logJson['MusicTrack'] == 'Interdiction' or logJson['MusicTrack'] == 'Combat_Dogfight'))) and journal.log.updateInterval <= 30: # May be interdicted!
                            journal.signs.add('UnderAttack')
                        elif logEvent == 'Scanned' and journal.log.updateInterval <= 30 : # logged within 30 seconds
                            journal.signs.add('Scanned')
                        elif logEvent == 'Resurrect' or logEvent == 'LoadGame' or logEvent == 'Shutdown': # Ship destroyed / Reload the game
                            if 'UnderAttack' in journal.signs: journal.signs.remove('UnderAttack')
                            if 'Scanned' in journal.signs: journal.signs.remove('Scanned')

                        elif logEvent == 'Music': # music playing
                            if logJson['MusicTrack'] == 'DestinationFromHyperspace' and journal.nav.target is not None: # Finish multi-hop route
                                journal.nav.target = journal.nav.lastTarget = None
                            elif logJson['MusicTrack'] == 'MainMenu': journal.status = 'MainMenu'
                            elif logJson['MusicTrack'] == 'DockingComputer':
                                if journal.status == 'startUndock': journal.status = 'undocking'
                                elif journal.status == 'startDock': journal.status = 'docking'

                        elif logEvent == 'DockingRequested': journal.status = 'startDock'

                        elif logEvent == 'Docked':
                            journal.status = 'Docked'
                            journal.nav.dockedStation = logJson['StationName']

                        elif logEvent == 'StartJump':
                            if logJson['JumpType'] == 'Hyperspace' and 'StarSystem' in logJson:
                                journal.status = 'startJump'
                                journal.nav.location = logJson['StarSystem']
                                journal.nav.lastTarget = logJson['StarSystem']
                                journal.nav.targetStarClass = logJson['StarClass']
                            elif logJson['JumpType'] == 'Supercruise':
                                journal.status = 'supercruise'

                        elif logEvent == 'SupercruiseEntry': journal.status = 'supercruise'

                        elif logEvent == 'SupercruiseExit' or logEvent == 'DockingCancelled': journal.status = 'normal'

                        elif logEvent == 'Undocked': journal.status = 'normal'

                        elif logEvent == 'FSDTarget':
                            if logJson['Name'] == journal.nav.location : journal.nav.target = None
                            else:
                                journal.nav.target = logJson['Name']
                                if 'RemainingJumpsInRoute' in logJson: # Multi-Hop
                                    journal.nav.remainingJumps = logJson['RemainingJumpsInRoute']
                                else : journal.nav.remainingJumps = 1 # single hop

                        elif logEvent == 'FSDJump':
                            journal.ship.fuel = logJson['FuelLevel']
                            journal.ship.fuelLevel = round((journal.ship.fuel/journal.ship.fuelCap)*100)
                            if journal.nav.lastTarget == logJson['StarSystem']:
                                journal.nav.lastTarget = None
                                journal.status = 'finishJump'
                                if journal.nav.target == logJson['StarSystem'] and journal.nav.remainingJumps == 0 :
                                    journal.nav.targetStarClass = None
                                    journal.nav.target = None # Finish route

                        elif (logEvent == 'Location' or logEvent == 'FSDJump') and 'StarSystem' in logJson:
                            journal.nav.location = logJson['StarSystem']

                        elif logEvent == 'MissionAccepted': # Add to Mission List
                            journal.missions.add(mission(id=logJson['MissionID'],localisedName=logJson['LocalisedName'],reward=logJson['Reward'],wing=logJson['Wing']))
                        elif (logEvent == 'MissionAbandoned' or logEvent == 'MissionCompleted' or logEvent == 'MissionFailed' )and mission(id=logJson['MissionID']) in journal.missions:
                            journal.missions.remove(mission(id=logJson['MissionID']))

                    if journal.status != 'Docked' and journal.nav.dockedStation is not None: journal.nav.dockedStation = None
    except IOError as e:
        if logger: logger.warn("Error in reading journal logs "+e)
        else:
            print("Error in reading journal logs "+e)
            traceback.print_exc()
    return journal

if __name__ == '__main__': # Test
    # parseLogs()
    # print(getLatestLogPath())
    # print(journal['status'])
    # print(journal['location'])
    # print(journal['dockedStation'])
    # print(journal['target'])
    # print(journal['missions'])
    # print(journal['isUnderAttack'])
    # print(journal['isBeingScanned'])
    jn = parseLogs()
    print(jn.nav.targetStarClass)


import matplotlib
from matplotlib import pyplot as plt
import numpy as np
import cv2 as cv

import IO
import api

# >>> Przykładowe zadanie i proces wykonania na podstawie zestawu Artroom2 <<<
# Korzystając z metody StereoSGBM udostępnionej przez bibliotekę OpenCV wyznacz mapę rozbieżności oraz mapę głębi.
# Dobierz odpowiednie parametry metody StereoSGBM.
# Porównaj otrzymane wyniki z referencyjnymi wartościami rozbieżności zapisanymi w formacie PFM

IMG_LEFT = r"./Artroom2/im0.png"
IMG_RIGHT = r"./Artroom2/im1.png"
img_left = cv.imread(IMG_LEFT)
img_right = cv.imread(IMG_RIGHT)

doffs = 0
baseline = 529.50
f = 1734.04         # Focal z macierzy
width = 1920
height = 1080
ndisp = 190
x = 830
y = 530

# Convert to grey
img_left = cv.cvtColor(img_left, cv.COLOR_BGR2GRAY)
img_right = cv.cvtColor(img_right, cv.COLOR_BGR2GRAY)

# Filtering for smoother
filter_size = 5
kernel = np.ones((filter_size, filter_size), np.float32) / (filter_size * filter_size)
img_left = cv.filter2D(img_left, -1, kernel)
img_right = cv.filter2D(img_right, -1, kernel)

# Obliczanie dysparycji z danych przy pomocy SGBM
disp = api.calculate_disparity_with_SGBM(img_left, img_right, max_disparity=ndisp, window_size=2)
for i in range(len(disp)):
    for j in range(len(disp[i])):
        disp[i][j] = api.clamp(0, 255, disp[i][j])

# Odczytanie dysparycji do porównania
ref_disp = cv.imread(r"./Artroom2/disp0.pfm", cv.IMREAD_UNCHANGED)
ref_disp = np.asarray(ref_disp)
ref_disp = ref_disp / 256

matplotlib.pyplot.imshow(disp)
plt.show()
cv.imwrite("Artroom2/Results/Zad 1/disparity.png", disp)
IO.save_disp_to_json(disp, "Artroom2/Results/Zad 1/disparity_data.json")
print(f"Zad 1 - Wartość dysparycji wyznaczonej przez StereoSGBM dla [{x},{y}]: {disp[y][x]}")

matplotlib.pyplot.imshow(ref_disp)
plt.show()
cv.imwrite("Artroom2/Results/Zad 1/ref_disparity.png", ref_disp)
IO.save_disp_to_json(ref_disp, "Artroom2/Results/Zad 1/ref_disparity_data.json")
print(f"Zad 1 - Wartość dysparycji referencyjnej dla [{x},{y}]: {ref_disp[y][x]}")

# Obliczanie głębi na podstawie uzyskanych dysparycji
depth = api.calculate_depth_with_disparity(disp, f, baseline, doffs)
ref_depth = api.calculate_depth_with_disparity(ref_disp, f, baseline, doffs)

matplotlib.pyplot.imshow(depth)
plt.show()
cv.imwrite("Artroom2/Results/Zad 1/depth.png", depth / 255)
print(f"Zad 2 - Wartość depth wyznaczonej przez StereoSGBM dla [{x},{y}]: {depth[y][x]}")

matplotlib.pyplot.imshow(ref_depth)
plt.show()
cv.imwrite("Artroom2/Results/Zad 1/ref_depth.png", ref_depth)
print(f"Zad 2 - Wartość depth referencyjnej dla [{x},{y}]: {ref_depth[y][x]}")


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

import random
import pymongo
client = pymongo.MongoClient('112.74.106.159', 27017)
db = client.develop

#获取useragent池
get_info = db.userAgents.find()
USER_AGENTS = [i['userAgent'] for i in get_info]

class MyUserAgent(object):
	def process_request(self, request, spider):
		request.headers.setdefault('User-Agent', random.choice(USER_AGENTS))