import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import datetime
import plotly.express as px
from PIL import Image

st.set_page_config(
    page_title="Supermarket Sales",
    page_icon="ðŸ“ˆ",
    layout="centered",
    initial_sidebar_state="expanded",
    menu_items={
        'Get Help': 'https://www.google.com',
        'Report a bug': "https://github.com/Andreean99?tab=repositories",
        'About': " Visualisasi dan Hipotesis Testing Supermarket Sales Milestone 1"
    }
)

st.sidebar.title('Select a Page')
selected = st.sidebar.selectbox('Page:', ['Data Visualisasi', 'Hipotesis Testing'])

if selected == 'Data Visualisasi':
    st.title('Data Visualisasi')

    PAYMENT_COLUMN = 'payment'
    PRODUCT_COLUMN = 'product line'
    TOTAL_COLUMN = 'total'
    GENDER_COLUMN = 'gender'
    GROSS_INCOME_COLUMN = 'gross income'
    CITY_COLUMN = 'city'
    DATE_COLUMN = 'date'
    TIME_COLUMN = 'time'
    CUSTOMER_TYPE_COLUMN = 'customer type'
    DATA_URL = ('supermarket_sales - Sheet1.csv')

    @st.cache_data
    def load_data(nrows):
        data = pd.read_csv(DATA_URL, nrows=nrows)
        lowercase = lambda x: str(x).lower()
        data.rename(lowercase, axis='columns', inplace=True)
        data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])
        return data

    data_load_state = st.text('Loading data...')
    data = load_data(10000)
    data_load_state.text("Done! (using st.cache)")

    if st.checkbox('Show raw data'):
        st.subheader('Raw data')
        st.write(data)

    st.subheader('Sebaran data gross income tiap kota')
    selected_city=st.selectbox('Pilih Kota', options=('Yangon', 'Naypyitaw', 'Mandalay'))
    fig1, ax1= plt.subplots(figsize=[8,5])
    sns.histplot(data[data[CITY_COLUMN]==selected_city][GROSS_INCOME_COLUMN])
    st.pyplot(fig1)

    average_yangon = data[data[CITY_COLUMN]=='Yangon'][[DATE_COLUMN,'gross income']].groupby(DATE_COLUMN).sum()
    average_naypyitaw = data[data[CITY_COLUMN]=='Naypyitaw'][[DATE_COLUMN,'gross income']].groupby(DATE_COLUMN).sum()
    average_mandalay = data[data[CITY_COLUMN]=='Mandalay'][[DATE_COLUMN,'gross income']].groupby(DATE_COLUMN).sum()

    st.subheader('Rata - rata Gross Income harian Yangon')
    st.line_chart(average_yangon)
    st.subheader('Rata - rata Gross Income harian Naypyitaw')
    st.line_chart(average_naypyitaw)
    st.subheader('Rata - rata Gross Income harian Mandalay')
    st.line_chart(average_mandalay)

    st.subheader('Total Pendapatan tiap kota')
    tipe = data.groupby(CITY_COLUMN)[TOTAL_COLUMN].sum()
    st.bar_chart(tipe)

    st.subheader('Jumlah pelanggan berdasarkan Gender')
    gen = data[GENDER_COLUMN].value_counts()
    st.bar_chart(gen)

    st.subheader('Jumlah tipe pelanggan berdasarkan gender')
    selected_type = st.radio(label='Pilih Gender', options=data[GENDER_COLUMN].unique())
    st.write('Female = Member : 261, Normal : 240')
    st.write('Male = Normal : 259, Member : 240 ')
    fig2, ax2= plt.subplots(figsize=[8,5])
    sns.histplot(data[data[GENDER_COLUMN]==selected_type][CUSTOMER_TYPE_COLUMN])
    st.pyplot(fig2)

    st.subheader('Total pembayaran berdasarkan Gender')
    st.write('Total pembayaran Female 167882, sedangkan Male 155083')
    gender_total = data.groupby(GENDER_COLUMN)[TOTAL_COLUMN].sum()
    fig3, ax3 = plt.subplots(figsize=[8,5])
    sns.barplot(x=gender_total.index,y=gender_total,orient='v')
    st.pyplot(fig3)

else :
    st.title('Hipotesis Testing')

    st.write('Berdasarkan hasil pengujian Hipotesis Testing, didapatkan p-value sebesar 0.5762514561129986 yang mana lebih besar dari alpha 0.05. Maka disimpulkan dengan rentang kepercayaan 95%, rata-rata gross income harian Yangon secara signifikan hampir sama dengan rata-rata gross income harian Naypyitaw, maka di simpulkan bahwa H0 gagal di tolak.')

    img = Image.open('hipotesis.png')

    st.subheader('H0 : Î¼ Gross Income Yangon   =  Gross Income Mandalay')
    st.subheader('H1 : Î¼ Gross Income Yangon  !=  Gross Income Mandalay')

    st.header('Plot Hipotesis testing')
    st.image(img, caption='Hipotesis Testing', width=400, use_column_width=True)

    st.write('Untuk pembuktian hipotesis testing pada gambar di atas bisa dilihat garis confidence interval berada diluar garis alternate hypotesis maka bisa di katakan bahwa H0 gagal di tolak dan bisa dikatakan Î¼ gross income harian Yangon secara signifikan hampir sama dengan Î¼ gross income harian Naypyitaw ')


import json

def add_countries(apps, schema_editor):
    """
    Read geojson file and add all countries to Country model
    """
    Country = apps.get_model("api", "Country")
    geojson_path = '../frontend/src/assets/countries.json'

    with open(geojson_path) as json_file:
        data = json.load(json_file)
        for feature in data['features']:
            country = feature['properties']['ADMIN']
            entry = Country(name=country)
            entry.save()


import sys
import argparse
import os
import re
from Bio import SeqIO
import numpy as npy
from mypyli import taxtree, kraken

def get_lengths(fasta_f):
    """ Returns as dict with the sequences and their lengths """
    contig_data = {}

    with open(fasta_f, 'rU') as IN:
        for record in SeqIO.parse(IN, "fasta"):
            length = len(record.seq)

            contig_data[record.id] = {'length': length}

    return contig_data

def get_taxonomic_classifications(contig_data, kraken_f, tree):
    """ Parses (currently) the kraken file from contigs and updates the hash with contig name: TaxNode, length
    """

    for krec in kraken.KrakenRecord.parse_kraken_file(kraken_f, iterate=True):
        if krec.classified:
            tax_node = tree.lookup_taxid(krec.taxid)
        else:
            tax_node = "unassigned"

        contig_data[krec.name].update({'taxonomy': tax_node})

def bin_sequences(contig_data, rank="genus", imerge=False):

    bins = {}
    for contig, data in contig_data.items():
        taxstring = data['taxonomy']

        if taxstring != "unassigned":
            taxstring = taxstring.get_tax_string(trim_to=rank)

        bins[taxstring] = bins.get(taxstring, []) + [contig]

    while imerge:
        print("   Running intelligerge...", file=sys.stderr)
        imerge = intellimerge(bins)

    print("\n\nBins\t#seqs\ttotal_bp")
    for bin in sorted(bins):
        bp = 0
        for header in bins[bin]:
            bp += contig_data[header]['length']
        print("\t".join([bin, str(len(bins[bin])), str(bp)]))

    return bins

def intellimerge(bins, minimum=10000):
    """
    Need to control for bins that get moved up from kingdom to nothing if thats possible"""

    modified = 0
    num_bins = len(bins)
    print(("num_bins", num_bins))
    for bin in sorted(bins.copy(), reverse=True):
        bp = 0
        for header in bins[bin]:
            bp += contig_data[header]['length']

        if bp < minimum:
            tax = bin.split("; ")

            if len(tax) == 1:
                continue
            else:
                new_bin = "; ".join(tax[:-1])
            old_bin = bins.pop(bin)
            #print(old_bin)
            bins[new_bin] = bins.get(new_bin, []) + old_bin

    return not num_bins == len(bins)

def write_fastas(bins, fasta_f, out):

    if not os.path.isdir(out):
        os.makedirs(out)

    # make lookup hash and initialize files
    lookup = {}
    for bin in bins:
        for contig in bins[bin]:
            lookup[contig] = bin

        #open("{}/{}.fasta".format(out, bin), 'w')
        open("{}/{}.fasta".format(out, bin.replace("; ", "-")), 'w')

    with open(fasta_f, 'rU') as IN:
        for record in SeqIO.parse(IN, "fasta"):
            bin = lookup[record.id]
            #SeqIO.write(record, open("{}/{}.fasta".format(out, bin), 'a'), "fasta")
            SeqIO.write(record, open("{}/{}.fasta".format(out, bin.replace("; ", "-")), 'a'), "fasta")

def try_to_change_name(sample, name):
    """ The SAM file has different header names than the FASTA file (ugh..) so this is an attempt to change the SAM headers to the FASTA headers without downloading the "map" file and requiring it as an argument.
    """

    #print((sample, name))

    prefix, suffix = sample.split("_")

    #print((prefix, suffix))

    name_digits = name.replace("scaffold", "")

    #print(("digits", name_digits))
    suffix = suffix[:-len(name_digits)]

    #print(("suf", suffix))
    suffix += name_digits

    #print(("new_suf", suffix))
    return "_".join([prefix, suffix])

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="""Writes a set of fasta files, one for each bin, using kraken's classification of contigs.""")

    parser.add_argument("-fasta", help="the fna file of contigs", required=True)
    parser.add_argument("-kraken", help="kraken contigs file", required=True)
    parser.add_argument("-out", help="directory to write binned fastas in", default="fasta_bins/")
    parser.add_argument("-tree", help="a pickled TaxTree object", required=True)
    args = parser.parse_args()

    print("\nGetting sequence lengths...", file=sys.stderr)
    contig_data = get_lengths(args.fasta)

    print("\nLoading TaxTree...", file=sys.stderr)
    # set up the tree to look up taxonomies
    tree = taxtree.TaxTree.load_tree(args.tree)

    print("\nAssigning taxonomy...", file=sys.stderr)
    get_taxonomic_classifications(contig_data, args.kraken, tree)

    print("\nBinning Sequences...\n", file=sys.stderr)
    bins = bin_sequences(contig_data, rank="genus", imerge=True)

    print("\nWritting fasta files...", file=sys.stderr)
    write_fastas(bins, args.fasta, args.out)


from __future__ import annotations

# system imports
import ast
import collections
import contextlib
import copy
import functools
import gettext
import importlib
import locale
import os
import pathlib
import re
import subprocess
import threading
import traceback
import typing
import sys
import urllib.parse
import webbrowser

# third part imports
import numpy.typing

# local libraries
from nion.swift.model import PlugInManager
from nion.swift.model import Profile
from nion.swift.model import Utility
from nion.swift import FacadeQueued
from nion.swift import Panel
from nion.ui import Declarative
from nion.ui import Dialog
from nion.ui import Widgets
from nion.utils import Converter
from nion.utils import Selection
from nion.utils import Geometry

if typing.TYPE_CHECKING:
    from nion.swift import DocumentController
    from nion.ui import DrawingContext
    from nion.ui import UserInterface

_NDArray = numpy.typing.NDArray[typing.Any]

_ = gettext.gettext

NO_DESCRIPTION_AVAILABLE_TEXT = _("*No description available*.")

def pose_get_string_message_box(ui: UserInterface.UserInterface, message_column: UserInterface.BoxWidget, caption: str,
                                text: str, accepted_fn: typing.Callable[[str], None],
                                rejected_fn: typing.Optional[typing.Callable[[], None]] = None,
                                accepted_text: typing.Optional[str] = None,
                                rejected_text: typing.Optional[str] = None) -> UserInterface.BoxWidget:
    if accepted_text is None:
        accepted_text = _("OK")
    if rejected_text is None:
        rejected_text = _("Cancel")
    message_box_widget = ui.create_column_widget()  # properties={"stylesheet": "background: #FFD"}
    caption_row = ui.create_row_widget()
    caption_row.add_spacing(12)
    caption_row.add(ui.create_label_widget(caption))
    caption_row.add_stretch()
    inside_row = ui.create_row_widget()

    def reject_button_clicked() -> typing.Any:
        if callable(rejected_fn):
            rejected_fn()
        return False

    def accept_button_clicked() -> typing.Any:
        accepted_fn(string_edit_widget.text or str())
        return False

    string_edit_widget = ui.create_line_edit_widget()
    string_edit_widget.text = text
    string_edit_widget.on_return_pressed = accept_button_clicked
    string_edit_widget.on_escape_pressed = reject_button_clicked
    reject_button = ui.create_push_button_widget(rejected_text)
    reject_button.on_clicked = reject_button_clicked
    accepted_button = ui.create_push_button_widget(accepted_text)
    accepted_button.on_clicked = accept_button_clicked
    inside_row.add_spacing(12)
    inside_row.add(string_edit_widget)
    inside_row.add_spacing(12)
    inside_row.add(reject_button)
    inside_row.add_spacing(12)
    inside_row.add(accepted_button)
    inside_row.add_stretch()
    message_box_widget.add_spacing(6)
    message_box_widget.add(caption_row)
    message_box_widget.add_spacing(4)
    message_box_widget.add(inside_row)
    message_box_widget.add_spacing(4)
    message_column.add(message_box_widget)
    string_edit_widget.select_all()
    string_edit_widget.focused = True
    return message_box_widget

def pose_confirmation_message_box(ui: UserInterface.UserInterface, message_column: UserInterface.BoxWidget,
                                  caption: str, accepted_fn: typing.Callable[[], None],
                                  rejected_fn: typing.Optional[typing.Callable[[], None]] = None,
                                  accepted_text: typing.Optional[str] = None,
                                  rejected_text: typing.Optional[str] = None,
                                  display_rejected: bool = True) -> UserInterface.BoxWidget:
    if accepted_text is None:
        accepted_text = _("OK")
    if rejected_text is None:
        rejected_text = _("Cancel")
    message_box_widget = ui.create_column_widget()  # properties={"stylesheet": "background: #FFD"}

    def reject_button_clicked() -> typing.Any:
        if rejected_fn:
            rejected_fn()
        return False

    def accept_button_clicked() -> typing.Any:
        accepted_fn()
        return False

    reject_button = ui.create_push_button_widget(rejected_text)
    reject_button.on_clicked = reject_button_clicked
    accepted_button = ui.create_push_button_widget(accepted_text)
    accepted_button.on_clicked = accept_button_clicked
    caption_row = ui.create_row_widget()
    caption_row.add_spacing(12)
    caption_row.add(ui.create_label_widget(caption))
    if display_rejected:
        caption_row.add_spacing(12)
        caption_row.add(reject_button)
    caption_row.add_spacing(12)
    caption_row.add(accepted_button)
    caption_row.add_stretch()
    message_box_widget.add_spacing(6)
    message_box_widget.add(caption_row)
    message_box_widget.add_spacing(4)
    message_column.add(message_box_widget)
    return message_box_widget

class ScriptListItem:
    def __init__(self, full_path: str, indent: int = 0, indent_level: int = 0, show_dirname: bool = True) -> None:
        self.__full_path = os.path.abspath(full_path)
        self._exists = False
        self.indent = indent
        self.indent_level = indent_level
        self.show_dirname = show_dirname
        self.script_item: typing.Optional[Profile.ScriptItem] = None

    @property
    def full_path(self) -> str:
        return self.__full_path

    @property
    def basename(self) -> str:
        return os.path.basename(self.full_path)

    @property
    def dirname(self) -> str:
        return os.path.dirname(self.full_path)

    @property
    def exists(self) -> bool:
        return self._exists

    def check_existence(self) -> bool:
        self._exists = os.path.exists(self.full_path)
        return self._exists

    # Used by "sort"
    def __lt__(self, other: typing.Any) -> bool:
        if isinstance(other, FolderListItem):
            return False
        if isinstance(other, ScriptListItem):
            return locale.strxfrm(self.basename.casefold()) < locale.strxfrm(other.basename.casefold())
        return NotImplemented

class FolderListItem(ScriptListItem):

    def __init__(self, full_path: str, content: typing.Optional[typing.List[ScriptListItem]] = None, indent: int = 0,
                 indent_level: int = 0, show_dirname: bool = True):
        super().__init__(full_path, indent=indent, indent_level=indent_level, show_dirname=show_dirname)
        self.__content = content if content is not None else list()
        self.folder_closed = True

    @property
    def content(self) -> typing.List[ScriptListItem]:
        return self.__content

    def update_content_from_file_system(self, filter_pattern: typing.Optional[str] = None) -> None:
        if os.path.isdir(self.full_path):
            dirlist = os.listdir(self.full_path)
            filtered_items = list()
            for item in dirlist:
                if filter_pattern is None or re.search(filter_pattern, item):
                    indent_level = self.indent_level + 1
                    filtered_items.append(ScriptListItem(os.path.join(self.full_path, item), indent=indent_level * 20,
                                                         indent_level=indent_level, show_dirname=False))
            self.__content = filtered_items

    # Used by "sort"
    def __lt__(self, other: typing.Any) -> bool:
        if isinstance(other, FolderListItem):
            return locale.strxfrm(self.basename.casefold()) < locale.strxfrm(other.basename.casefold())
        if isinstance(other, ScriptListItem):
            return True
        return NotImplemented

def _build_sorted_scripts_list(scripts_list: typing.Sequence[typing.Any]) -> typing.Sequence[ScriptListItem]:
    filtered_items = []
    for item in scripts_list:
        if item.indent_level == 0:
            filtered_items.append(item)
    filtered_items.sort()
    set_items = []
    for item in filtered_items:
        set_items.append(item)
        if isinstance(item, FolderListItem):
            if not item.folder_closed:
                for content_item in sorted(item.content):
                    set_items.append(content_item)
    return set_items

def open_location(location: str) -> None:
    if sys.platform == "darwin":
        subprocess.Popen(["open", str(location)])
    elif sys.platform == 'win32':
        subprocess.run(['explorer', str(location)])
    elif sys.platform == 'linux':
        subprocess.check_call(['xdg-open', '--', str(location)])

class ScriptListCanvasItemDelegate(Widgets.ListCanvasItemDelegate):

    def __init__(self, ui: UserInterface.UserInterface, document_controller: DocumentController.DocumentController,
                 update_list_fn: typing.Callable[[], typing.Any]) -> None:
        super().__init__()
        self.__ui = ui
        self.__document_controller = document_controller
        self.__update_list_fn = update_list_fn

    @staticmethod
    def _closed_folder_icon_strings() -> typing.Tuple[str, str]:
        if sys.platform == "win32":
            triangle = "\N{BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED} "
        else:
            triangle = "\N{BLACK RIGHT-POINTING TRIANGLE} "
        return triangle, "\N{FILE FOLDER} "

    @staticmethod
    def _open_folder_icon_strings() -> typing.Tuple[str, str]:
        if sys.platform == "win32":
            triangle = "\N{BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED} "
        else:
            triangle = "\N{BLACK DOWN-POINTING TRIANGLE} "
        return triangle, "\N{OPEN FILE FOLDER} "

    @staticmethod
    def _file_icon_string() -> str:
        return "\N{PAGE FACING UP} "

    @staticmethod
    def _major_font_size() -> str:
        return "12px"

    @staticmethod
    def _minor_font_size() -> str:
        return "10px"

    @staticmethod
    def _major_font_color() -> str:
        return "#000"

    @staticmethod
    def _minor_font_color() -> str:
        return "#888"

    def mouse_pressed_in_item(self, mouse_index: int, pos: Geometry.IntPoint, modifiers: UserInterface.KeyboardModifiers) -> bool:
        display_item = self.items[mouse_index]
        width = self.__ui.get_font_metrics(self._major_font_size(), self._closed_folder_icon_strings()[0]).width
        if isinstance(display_item, FolderListItem) and display_item.indent - 4 < pos.x < display_item.indent + width + 2:
            display_item.folder_closed = not display_item.folder_closed
            if display_item.script_item:
                display_item.script_item.is_closed = not display_item.script_item.is_closed
            self.__update_list_fn()
            return True
        return False

    def context_menu_event(self, index: typing.Optional[int], x: int, y: int, gx: int, gy: int) -> bool:
        if index is not None:
            display_item = self.items[index]
            menu = self.__document_controller.create_context_menu()
            if isinstance(display_item, FolderListItem):
                menu.add_menu_item(_("Open Folder"), functools.partial(open_location, display_item.full_path))
            elif isinstance(display_item, ScriptListItem):
                menu = self.__document_controller.create_context_menu()
                menu.add_menu_item(_("Open Containing Folder"), functools.partial(open_location, display_item.dirname))
            menu.popup(gx, gy)
            return True
        return False

    def __calculate_indent(self, display_item: typing.Any) -> int:
        # An item that can cause an indent_level > 0 is always an open folder
        triangle_string, icon_string = self._open_folder_icon_strings()
        return round(4 + float(self.__ui.get_font_metrics(self._major_font_size(), triangle_string + icon_string).width * display_item.indent_level))

    def paint_item(self, drawing_context: DrawingContext.DrawingContext, display_item: typing.Any, rect: Geometry.IntRect, is_selected: bool) -> None:
        if isinstance(display_item, FolderListItem):
            if display_item.folder_closed:
                triangle_string, icon_string = self._closed_folder_icon_strings()
            else:
                triangle_string, icon_string = self._open_folder_icon_strings()
        else:
            triangle_string = str()
            icon_string = self._file_icon_string()

        icon_offset = self.__ui.get_font_metrics(self._major_font_size(), self._closed_folder_icon_strings()[0]).width
        icon_width = self.__ui.get_font_metrics(self._major_font_size(), icon_string).width

        if isinstance(display_item, ScriptListItem):
            with drawing_context.saver():

                drawing_context.fill_style = self._major_font_color()
                drawing_context.font = self._major_font_size()
                drawing_context.text_align = "left"
                drawing_context.text_baseline = "bottom"
                name_string = display_item.basename
                display_item.indent = self.__calculate_indent(display_item)
                drawing_context.fill_text(triangle_string, rect[0][1] + display_item.indent, rect[0][0] + 20 - 4)
                drawing_context.fill_text(icon_string + name_string, rect[0][1] + display_item.indent + icon_offset, rect[0][0] + 20 - 4)
                drawing_context.fill_style = self._minor_font_color()
                drawing_context.font = self._minor_font_color()
                name_width = self.__ui.get_font_metrics(self._major_font_size(), name_string).width
                if display_item.exists is not None and not display_item.exists:
                    type_str = "Folder" if type(display_item) is FolderListItem else "File"
                    drawing_context.fill_text(f"({type_str} not found)",
                                              rect[0][1] + 4 + display_item.indent + 4 + icon_offset + icon_width + name_width,
                                              rect[0][0] + 20 - 4)
                elif display_item.show_dirname:
                    drawing_context.fill_text(f"({display_item.dirname})",
                                              rect[0][1] + 4 + display_item.indent + 4 + icon_offset + icon_width + name_width,
                                              rect[0][0] + 20 - 4)

class ScriptCancelException(Exception):
    pass

class RunScriptDialog(Dialog.ActionDialog):

    def __init__(self, document_controller: "DocumentController.DocumentController"):
        ui = document_controller.ui
        super().__init__(ui, _("Scripts"), parent_window=document_controller, persistent_id="ScriptsDialog")

        self.ui = ui
        self.document_controller = document_controller

        app = typing.cast(typing.Any, self.document_controller.app)  # trick typing
        self.__profile: typing.Optional[Profile.Profile] = app.profile if app else None

        self.script_filter_pattern = "\\.py$"

        self.__cancelled = False

        self.__thread: typing.Optional[threading.Thread] = None

        properties = dict()
        properties["min-height"] = 180
        properties["min-width"] = 540

        self.__output_widget = self.ui.create_text_edit_widget(properties)
        self.__output_widget.set_text_font(Panel.Panel.get_monospace_text_font())
        self.__output_widget.set_line_height_proportional(Panel.Panel.get_monospace_proportional_line_height())

        self.__message_column = ui.create_column_widget()

        self.__message_column.add(self.__make_cancel_row())

        # load the list of script items
        items = []
        if self.__profile:
            for script_item in self.__profile.script_items:
                if isinstance(script_item, Profile.FileScriptItem):
                    script_list_item = ScriptListItem(str(script_item.path))
                    script_list_item.script_item = script_item
                    items.append(script_list_item)
                elif isinstance(script_item, Profile.FolderScriptItem):
                    folder_list_item = FolderListItem(str(script_item.folder_path))
                    folder_list_item.script_item = script_item
                    folder_list_item.folder_closed = script_item.is_closed
                    items.append(folder_list_item)

        self.__new_path_entries = []

        for item in items:
            if isinstance(item, FolderListItem):
                full_path = item.full_path
                self.__new_path_entries.append(full_path)
                if full_path not in sys.path:
                    sys.path.append(full_path)

        def update_script_description() -> None:
            indexes = self.scripts_list_widget.selected_items
            if len(indexes) == 1:
                script_item = self.scripts_list_widget.items[list(indexes)[0]]
                # Use "type" instead of "isinstance" to exclude subclasses from matching
                if type(script_item) is ScriptListItem:
                    script_path = pathlib.Path(script_item.full_path)
                    script_ast = None
                    if script_path.exists():
                        try:
                            with open(script_path) as f:
                                script = f.read()

                            script_ast = ast.parse(script, script_path.stem, 'exec')
                        except Exception as e:
                            pass
                        docstring = ast.get_docstring(script_ast) if script_ast else None
                        if docstring:
                            text_browser_widget.markdown = docstring
                        else:
                            text_browser_widget.markdown = NO_DESCRIPTION_AVAILABLE_TEXT

        def selected_changed(indexes: typing.AbstractSet[int]) -> None:
            run_button_widget.enabled = len(indexes) == 1
            update_script_description()

        def add_clicked() -> None:
            assert self.__profile
            add_dir = self.ui.get_persistent_string("import_directory", "")
            file_paths, filter_str, directory = self.get_file_paths_dialog(_("Add Scripts"), add_dir, "Python Files (*.py)", "Python Files (*.py)")
            if len(file_paths) > 0:
                self.ui.set_persistent_string("import_directory", directory)
                items = list(self.scripts_list_widget.items)
                for file_path_str in file_paths:
                    script_item = Profile.FileScriptItem(pathlib.Path(file_path_str))
                    self.__profile.append_script_item(script_item)
                    script_list_item = ScriptListItem(file_path_str)
                    script_list_item.script_item = script_item
                    items.append(script_list_item)
                self.update_scripts_list(items)

        def add_folder_clicked() -> None:
            assert self.__profile
            add_dir = self.ui.get_persistent_string("import_directory", "")
            existing_directory, directory = self.ui.get_existing_directory_dialog(_("Add Scripts Folder"), add_dir)
            if existing_directory:
                folder_list_item = FolderListItem(existing_directory)
                folder_list_item.update_content_from_file_system(filter_pattern=self.script_filter_pattern)
                full_path = folder_list_item.full_path
                if full_path not in sys.path:
                    sys.path.append(full_path)
                    self.__new_path_entries.append(full_path)
                items = list(self.scripts_list_widget.items)
                script_item = Profile.FolderScriptItem(pathlib.Path(existing_directory))
                self.__profile.append_script_item(script_item)
                folder_list_item.script_item = script_item
                items.append(folder_list_item)
                self.update_scripts_list(items)
            else:
                self.rebuild_scripts_list()

        def remove_clicked() -> None:
            assert self.__profile
            indexes = list(self.scripts_list_widget.selected_items)
            new_items = []
            for i, item in enumerate(self.scripts_list_widget.items):
                if i not in indexes:
                    new_items.append(item)
                elif item.script_item:
                    self.__profile.remove_script_item(item.script_item)
            self.update_scripts_list(new_items)

        def run_clicked() -> None:
            indexes = self.scripts_list_widget.selected_items
            if len(indexes) == 1:
                script_item = self.scripts_list_widget.items[list(indexes)[0]]
                script_item.check_existence()
                # Use "type" instead of "isinstance" to exclude subclasses from matching
                if type(script_item) is ScriptListItem and script_item.exists:
                    script_path = script_item.full_path
                    self.run_script(script_path)

        def item_selected(index: int) -> bool:
            run_clicked()
            return True

        def handle_anchor_clicked(anchor: str) -> bool:
            o = urllib.parse.urlparse(anchor)
            if o.scheme in ("http", "https"):
                webbrowser.open(anchor)
                return True
            return False

        self.scripts_list_widget = Widgets.ListWidget(ui, ScriptListCanvasItemDelegate(ui, document_controller,
                                                                                self.rebuild_scripts_list),
                                                      items=items, selection_style=Selection.Style.single_or_none,
                                                      border_color="#888",
                                                      properties={"min-height": 200, "min-width": 560,
                                                                  "size-policy-vertical": "expanding"})
        self.scripts_list_widget.on_selection_changed = selected_changed
        self.scripts_list_widget.on_item_selected = item_selected
        self.rebuild_scripts_list()

        add_button_widget = ui.create_push_button_widget(_("Add..."))
        add_button_widget.on_clicked = add_clicked

        add_folder_button_widget = ui.create_push_button_widget(_("Add Folder..."))
        add_folder_button_widget.on_clicked = add_folder_clicked

        remove_button_widget = ui.create_push_button_widget(_("Remove"))
        remove_button_widget.on_clicked = remove_clicked

        run_button_widget = ui.create_push_button_widget(_("Run"))
        run_button_widget.on_clicked = run_clicked
        run_button_widget.enabled = False

        list_widget_row = ui.create_row_widget()
        list_widget_row.add_spacing(8)
        list_widget_row.add(self.scripts_list_widget)
        list_widget_row.add_spacing(8)

        text_browser_widget = ui.create_text_browser_widget()
        text_browser_widget.markdown = NO_DESCRIPTION_AVAILABLE_TEXT
        text_browser_widget.on_anchor_clicked = handle_anchor_clicked

        description_row = ui.create_row_widget(properties={"height": 110})
        description_row.add_spacing(8)
        description_row.add(text_browser_widget)
        description_row.add_spacing(8)

        close_button_widget = ui.create_push_button_widget(_("Close"))
        close_button_widget.on_clicked = self.request_close

        button_row = ui.create_row_widget()
        button_row.add_spacing(12)
        button_row.add(add_button_widget)
        button_row.add_spacing(4)
        button_row.add(add_folder_button_widget)
        button_row.add_spacing(4)
        button_row.add(remove_button_widget)
        button_row.add_stretch()
        button_row.add(run_button_widget)
        button_row.add_spacing(12)

        select_column = ui.create_column_widget()
        select_column.add_spacing(8)
        select_column.add(list_widget_row)
        select_column.add_spacing(8)
        select_column.add(description_row)
        select_column.add_spacing(8)
        select_column.add(button_row)
        select_column.add_spacing(8)

        run_column = ui.create_column_widget()
        run_column.add(self.__output_widget)
        run_column.add_spacing(6)
        run_column.add(self.__message_column)

        self.__stack = ui.create_stack_widget()

        self.__stack.add(select_column)
        self.__stack.add(run_column)

        self.content.add(self.__stack)

        self.__sync_events: typing.Set[threading.Event] = set()

        self.__lock = threading.RLock()

        self.__q: typing.Deque[typing.Callable[[], None]] = collections.deque()
        self.__output_queue: typing.Deque[str] = collections.deque()

        self.__is_closed = False

    def close(self) -> None:
        self.__is_closed = True
        for sync_event in self.__sync_events:
            sync_event.set()
        if self.__thread:
            self.__thread.join()
        self.document_controller.clear_task("ui_" + str(id(self)))
        self.document_controller.clear_task("run_" + str(id(self)))
        self.document_controller.clear_task("show_" + str(id(self)))
        self.document_controller.clear_task("print_" + str(id(self)))
        super().close()

    @property
    def cancelled(self) -> bool:
        return self.__cancelled

    def update_scripts_list(self, new_scripts_list: typing.Sequence[typing.Any]) -> None:
        for item in new_scripts_list:
            if isinstance(item, FolderListItem):
                item.update_content_from_file_system(filter_pattern=self.script_filter_pattern)
        items = _build_sorted_scripts_list(new_scripts_list)
        for item in items:
            item.check_existence()
        self.scripts_list_widget.items = items

    def rebuild_scripts_list(self) -> None:
        self.update_scripts_list(self.scripts_list_widget.items)

    def __make_cancel_row(self) -> UserInterface.BoxWidget:
        def cancel_script() -> None:
            self.__cancelled = True

        cancel_button = self.ui.create_push_button_widget(_("Cancel"))
        cancel_button.on_clicked = cancel_script
        cancel_row = self.ui.create_row_widget()
        cancel_row.add_stretch()
        cancel_row.add(cancel_button)
        cancel_row.add_spacing(12)
        return cancel_row

    def run_script(self, script_path: str) -> None:
        # Reload modules that are in on of the script folders.
        current_modules = list(sys.modules.values())
        for module in current_modules:
            for path in self.__new_path_entries:
                try:
                    do_reload = os.path.abspath(module.__file__ or str())[:len(path)] == path
                except (AttributeError, ValueError, TypeError):
                    pass
                else:
                    try:
                        if do_reload:
                            importlib.reload(module)
                    except Exception:
                        self.print(traceback.format_exc())
                        self.__stack.current_index = 1
                        self.continue_after_parse_error(script_path)
                        return

        self.__output_widget.text = str()

        script_name = os.path.basename(script_path)

        self.title = os.path.splitext(script_name)[0]

        try:
            with open(script_path) as f:
                script = f.read()

            script_ast = ast.parse(script, script_name, 'exec')
        except Exception as e:
            self.print(str(e))
            self.__stack.current_index = 1
            self.continue_after_parse_error(script_path)
            return

        class AddCallFunctionNodeTransformer(ast.NodeTransformer):
            def __init__(self, func_id: str, arg_id: str) -> None:
                self.__func_id = func_id
                self.__arg_id = arg_id

            def visit_Module(self, node: typing.Any) -> typing.Any:
                name_expr = ast.Name(id=self.__func_id, ctx=ast.Load())
                arg_expr = ast.Name(id=self.__arg_id, ctx=ast.Load())
                call_expr = ast.Expr(value=ast.Call(func=name_expr, args=[arg_expr], keywords=[]))
                new_node = copy.deepcopy(node)
                new_node.body.append(call_expr)
                ast.fix_missing_locations(new_node)
                return new_node

        # if script_main exists, add a node to call it
        for node in script_ast.body:
            if getattr(node, "name", None) == "script_main":
                script_ast = AddCallFunctionNodeTransformer('script_main', 'api_broker').visit(script_ast)

        compiled = compile(script_ast, script_name, 'exec')

        def run_it(compiled: typing.Any, interactive_session: typing.Any) -> None:
            class APIBroker:
                def get_interactive(self, version: typing.Optional[str] = None) -> typing.Any:
                    actual_version = "1.0.0"
                    if Utility.compare_versions(version or str(), actual_version) > 0:
                        raise NotImplementedError("API requested version %s is greater than %s." % (version, actual_version))
                    return interactive_session

                def get_api(self, version: str, ui_version: typing.Optional[str] = None) -> typing.Any:
                    ui_version = ui_version if ui_version else "~1.0"
                    api = PlugInManager.api_broker_fn(version, ui_version)
                    queued_api = FacadeQueued.API(api, None)  # type: ignore
                    queued_api._queue_task = api.queue_task
                    return queued_api

                def get_ui(self, version: str) -> Declarative.DeclarativeUI:
                    actual_version = "1.0.0"
                    if Utility.compare_versions(version, actual_version) > 0:
                        raise NotImplementedError("API requested version %s is greater than %s." % (version, actual_version))
                    return Declarative.DeclarativeUI()
            try:
                g: typing.Dict[str, typing.Any] = dict()
                g["api_broker"] = APIBroker()
                g["print"] = self.print
                g["input"] = self.get_string

                print_fn = self.print
                self.__cancelled = False  # Reset cancelled flag to make "Run again" work after a script was cancelled

                class StdoutCatcher:
                    def __init__(self) -> None:
                        pass

                    def write(self, stuff: str) -> None:
                        print_fn(stuff.rstrip())

                    def flush(self) -> None:
                        pass

                stdout = StdoutCatcher()
                with contextlib.redirect_stdout(typing.cast(typing.Any, stdout)), contextlib.redirect_stderr(typing.cast(typing.Any, stdout)):
                    try:
                        exec(compiled, g)
                    except ScriptCancelException as e:
                        self.print(_("Script canceled by user."))
            except Exception:
                self.print("{}: {}".format(_("Error"), traceback.format_exc()))

        self.__stack.current_index = 1

        self.run(script_path, functools.partial(run_it, compiled))

    def continue_after_parse_error(self, script_path: str) -> None:
        def func_continue() -> None:
            result = self.confirm(_("Finished"), _("Run Again"), _("Close"))

            with self.__lock:
                if result:
                    self.__q.append(functools.partial(self.run_script, script_path))
                else:
                    self.__q.append(self.request_close)
                self.document_controller.add_task("run_" + str(id(self)), self.__handle_output_and_q)

        self.__thread = threading.Thread(target=func_continue)
        self.__thread.start()

    def run(self, script_path: str, func: typing.Callable[[RunScriptDialog], None]) -> None:
        def func_run(func: typing.Callable[[RunScriptDialog], None]) -> None:
            try:
                func(self)
            except Exception:
                pass

            if not self.__is_closed:
                result = self.confirm(_("Finished"), _("Run Again"), _("Close"))

                with self.__lock:
                    if result:
                        self.__q.append(functools.partial(self.run_script, script_path))
                    else:
                        self.__q.append(self.request_close)
                    self.document_controller.add_task("run_" + str(id(self)), self.__handle_output_and_q)

        self.__thread = threading.Thread(target=func_run, args=(func,))
        self.__thread.start()

    def __handle_output_and_q(self) -> None:
        func = None
        with self.__lock:
            while len(self.__output_queue) > 0:
                self.__output_widget.move_cursor_position("end")
                self.__output_widget.append_text(self.__output_queue.popleft())
            if len(self.__q) > 0:
                func = self.__q.popleft()
        if callable(func):
            func()

    def print(self, text: typing.Any) -> None:
        with self.__lock:
            self.__output_queue.append(str(text))
            self.document_controller.add_task("print_" + str(id(self)), self.__handle_output_and_q)

    def print_debug(self, text: typing.Any) -> None:
        self.print(text)

    def print_info(self, text: typing.Any) -> None:
        self.print(text)

    def print_warn(self, text: typing.Any) -> None:
        self.print(text)

    def get_string(self, prompt: str, default_str: typing.Optional[str] = None) -> typing.Optional[str]:
        """Return a string value that the user enters. Raises exception for cancel."""
        with self.sync_event() as accept_event:
            result = None

            def perform() -> None:
                def accepted(text: str) -> None:
                    nonlocal result
                    result = text
                    accept_event.set()

                def rejected() -> None:
                    accept_event.set()

                self.__message_column.remove_all()
                pose_get_string_message_box(self.ui, self.__message_column, prompt, str(default_str), accepted, rejected)

            with self.__lock:
                self.__q.append(perform)
                self.document_controller.add_task("ui_" + str(id(self)), self.__handle_output_and_q)
            accept_event.wait()
            if self.__is_closed:
                raise ScriptCancelException()

        def update_message_column() -> None:
            self.__message_column.remove_all()
            self.__message_column.add(self.__make_cancel_row())
        self.document_controller.add_task("ui_" + str(id(self)), update_message_column)
        if result is None:
            raise ScriptCancelException()
        return result

    def get_integer(self, prompt: str, default_value: int = 0) -> int:
        converter = Converter.IntegerToStringConverter()
        result = self.get_string(prompt, converter.convert(default_value))
        return converter.convert_back(result) or 0

    def get_float(self, prompt: str, default_value: float = 0, format_str: typing.Optional[str] = None) -> float:
        converter = Converter.FloatToStringConverter(format_str)
        result = self.get_string(prompt, converter.convert(default_value))
        return converter.convert_back(result) or 0.0

    def show_ndarray(self, data: _NDArray, title: typing.Optional[str] = None) -> None:
        with self.sync_event() as accept_event:

            def perform() -> None:
                result_display_panel = self.document_controller.next_result_display_panel()
                if result_display_panel:
                    data_item = self.document_controller.add_data(data, title)
                    display_item = self.document_controller.document_model.get_display_item_for_data_item(data_item)
                    result_display_panel.set_display_panel_display_item(display_item)
                    result_display_panel.request_focus()
                accept_event.set()

            with self.__lock:
                self.__q.append(perform)
                self.document_controller.add_task("show_" + str(id(self)), self.__handle_output_and_q)
            accept_event.wait()
            if self.__is_closed:
                raise ScriptCancelException()

    def __register_sync_event(self, sync_event: threading.Event) -> None:
        self.__sync_events.add(sync_event)

    def __unregister_sync_event(self, sync_event: threading.Event) -> None:
        self.__sync_events.remove(sync_event)

    @contextlib.contextmanager
    def sync_event(self) -> typing.Iterator[threading.Event]:
        sync_event = threading.Event()
        self.__register_sync_event(sync_event)
        yield sync_event
        self.__unregister_sync_event(sync_event)

    def __accept_reject(self, prompt: str, accepted_text: typing.Optional[str], rejected_text: typing.Optional[str], display_rejected: bool) -> bool:
        """Return a boolean value for accept/reject."""
        with self.sync_event() as accept_event:
            result = False

            def perform() -> None:
                def accepted() -> None:
                    nonlocal result
                    result = True
                    accept_event.set()

                def rejected() -> None:
                    nonlocal result
                    result = False
                    accept_event.set()

                self.__message_column.remove_all()
                pose_confirmation_message_box(self.ui, self.__message_column, prompt, accepted, rejected, accepted_text, rejected_text, display_rejected)
                # self.__message_column.add(self.__make_cancel_row())

            with self.__lock:
                self.__q.append(perform)
                self.document_controller.add_task("ui_" + str(id(self)), self.__handle_output_and_q)
            accept_event.wait()
            if self.__is_closed:
                raise ScriptCancelException()

        def update_message_column() -> None:
            self.__message_column.remove_all()
            self.__message_column.add(self.__make_cancel_row())
        self.document_controller.add_task("ui_" + str(id(self)), update_message_column)
        return result

    def confirm_ok_cancel(self, prompt: str) -> bool:
        return self.__accept_reject(prompt, _("OK"), _("Cancel"), True)

    def confirm_yes_no(self, prompt: str) -> bool:
        return self.__accept_reject(prompt, _("Yes"), _("No"), True)

    def confirm(self, prompt: str, accepted_text: str, rejected_text: str) -> bool:
        return self.__accept_reject(prompt, accepted_text, rejected_text, True)

    def alert(self, prompt: str, button_label: typing.Optional[str] = None) -> None:
        self.__accept_reject(prompt, button_label, None, False)


#
# @lc app=leetcode id=47 lang=python3
#
# [47] Permutations II
#

# @lc code=start
from functools import reduce

class Solution:
    def permuteUnique(self, nums: list[int]) -> list[list[int]]:
        return reduce(
            lambda perms, n: [
                p[:i] + [n] + p[i:] for p in perms for i in range((p + [n]).index(n) + 1)
            ],
            nums,
            [[]],
        )

# @lc code=end


import sys
import os
from xml.etree.ElementTree import ElementTree as ET
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
import xml.etree

import YoUtil

class MmcResource:
	def __init__(self,path):
		self.path = path
		self.res_id  = None
		self.node_list=list()
		self.io_list = list()
		self.general_list = list()
		self.virtual_list = list()
		self.gateway_list = list()

	def load(self):
		YoUtil.debug_print('loading ->', self.path)
		self.tree = ET()
		self.tree.parse(self.path)
		root = self.tree.getroot()
		xml_list = root.findall('GLOBAL_PARAMS/NAME')
		if xml_list != None:
			#YoUtil.debug_print('xml_list=',xml_list)
			for xml_name in xml_list:
				res_id =  xml_name.get('RES_ID')
				#YoUtil.debug_print('Res_ID=',res_id)
				if res_id != None:
					self.res_id =res_id
		xml_list = root.findall('MOTION_DEVICES/NODE')
		if xml_list != None:
			#YoUtil.debug_print('Nodes xml_list=',xml_list)
			for xml_node in xml_list:
				self.load_node(xml_node)

		xml_list = root.findall('IO_DEVICES/NODE')
		if xml_list != None:
			#YoUtil.debug_print('Nodes xml_list=',xml_list)
			for xml_node in xml_list:
				self.load_io(xml_node)

		xml_list = root.findall('GENERAL_DEVICES/NODE')
		if xml_list != None:
			#YoUtil.debug_print('Nodes xml_list=',xml_list)
			for xml_node in xml_list:
				self.load_general(xml_node)

		xml_list = root.findall('VIRTUAL_OBJECTS/VIRTUAL_OBJECT')
		if xml_list != None:
			#YoUtil.debug_print('Nodes xml_list=',xml_list)
			for xml_node in xml_list:
				self.load_virtual(xml_node)

	def load_node(self,xml_node):
		#YoUtil.debug_print('node->',xml_node)
		if xml_node != None:
			node = MmcNode(xml_node)
			self.node_list.append(node)

	def load_io(self,xml_node):
		#YoUtil.debug_print('node->',xml_node)
		if xml_node != None:
			node = MmcNode(xml_node)
			self.io_list.append(node)

	def load_general(self,xml_node):
		#YoUtil.debug_print('node->',xml_node)
		if xml_node != None:
			node = MmcNode(xml_node)
			self.general_list.append(node)

	def load_virtual(self,xml_node):
		#YoUtil.debug_print('node->',xml_node)
		if xml_node != None:
			node = virtual_object(xml_node)
			self.virtual_list.append(node)

	def print(self):
		print('MMCResource ->',self.path)
		print('RES_ID=',self.res_id)
		print('MOTION_DEVICES:')
		for node in self.node_list:
			print('\t',node.to_string())
		print('IO_DEVICES:')
		for node in self.io_list:
			print('\t',node.to_string())
		print('GENERAL_DEVICES:')
		for node in self.general_list:
			print('\t',node.to_string())
		print('VIRTUAL_OBJECTS:')
		for node in self.virtual_list:
			print('\t',node.to_string())
		print('SUBGATEWAY:')
		for node in self.gateway_list:
			print('\t',node.to_string())

class MmcNode:
	def __init__(self,xml_node):
		self.xml_node = xml_node
		self.name=None
		self.type=None
		self.id=None
		self.node_name = None
		self.node_offset=None
		self.subtype = None
		self.drive_type=None
		self.load()

	def load(self):
		pass
		self.name=self.xml_node.get('NAME')
		self.type=self.xml_node.get('TYPE')
		self.id=self.xml_node.get('ID')
		self.node_name = self.xml_node.get('NODE_NAME')
		self.node_offset = self.xml_node.get('NODE_OFFSET')
		self.subtype = self.xml_node.get('SUBTYPE')
		self.drive_type = self.xml_node.get('DRIVE_TYPE')

	def to_string(self):
		ret= 'Node Name='+self.name+'\tID='+self.id
		if self.node_name != None:
			ret = ret+'\tNode_Name='+self.node_name
		if self.node_offset != None:
			ret = ret+'\tNode_Offset='+self.node_offset
		if self.subtype != None:
			ret = ret+'\tSubtype='+self.subtype
		if self.drive_type != None:
			ret = ret+'\tDriveType='+self.drive_type
		return ret

class virtual_object:
	def __init__(self,xml_node):
		self.xml_node = xml_node
		self.name=None
		self.type=None
		self.id=None
		self.member_list = list()
		self.load()

	def load(self):
		pass
		self.name=self.xml_node.get('NAME')
		self.type=self.xml_node.get('TYPE')
		self.id=self.xml_node.get('ID')
		xml_list = self.xml_node.findall('MEMBER')
		if xml_list!= None:
			for xml_node in xml_list:
				member = virtual_object_member(xml_node)
				self.member_list.append(member)

	def to_string(self):
		ret= 'Virtual Name='+self.name+' ID='+self.id
		if self.type != None:
			ret = ret+'\ttype='+self.type
		if len(self.member_list) > 0:
			for member in self.member_list:
				ret+= '\n\t\t'+member.to_string()
		return ret

class virtual_object_member:
	def __init__(self,xml_node):
		self.xml_node = xml_node
		self.name=None
		self.type=None
		self.id=None
		self.index_in_group = None
		self.member_list = list()
		self.load()

	def load(self):
		pass
		self.name=self.xml_node.get('NAME')
		self.type=self.xml_node.get('TYPE')
		self.id=self.xml_node.get('ID')
		self.index_in_group = self.xml_node.get('INDEX_IN_GROUP')

	def to_string(self):
		ret= 'Member Name='+self.name
		if self.id != None:
			ret+=' ID='+self.id
		if self.type != None:
			ret = ret+'\ttype='+self.type
		if self.index_in_group != None:
			ret = ret+'\tIndex_in_group='+self.index_in_group

		return ret


# Author:Zhang Yuan
import MyPackage
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import seaborn as sns
import statsmodels.api as sm
from scipy import stats

#------------------------------------------------------------
__mypath__ = MyPackage.MyClass_Path.MyClass_Path("\\量化投资以Python为工具")  #路径类
myfile = MyPackage.MyClass_File.MyClass_File()  #文件操作类
myplt = MyPackage.MyClass_Plot.MyClass_Plot()  #直接绘图类(单个图窗)
myfig = MyPackage.MyClass_Plot.MyClass_Figure()  #对象式绘图类(可多个图窗)
mypltpro = MyPackage.MyClass_PlotPro.MyClass_PlotPro()  #Plot高级图系列
myfigpro = MyPackage.MyClass_PlotPro.MyClass_FigurePro()  #Figure高级图系列
mynp = MyPackage.MyClass_Array.MyClass_NumPy()  #多维数组类(整合Numpy)
mypd = MyPackage.MyClass_Array.MyClass_Pandas()  #矩阵数组类(整合Pandas)
mypdpro = MyPackage.MyClass_ArrayPro.MyClass_PandasPro()  #高级矩阵数组类
mytime = MyPackage.MyClass_Time.MyClass_Time()  #时间类
myDA = MyPackage.MyClass_DataAnalysis.MyClass_DataAnalysis()  #数据分析类
#MyPackage.MyClass_ToDefault.DefaultMatplotlibBackend()       #恢复默认设置(仅main主界面)
#------------------------------------------------------------
Path="C:\\Users\\i2011\\OneDrive\\Book_Code&Data\\量化投资以python为工具\\数据及源代码\\021"
Path2="C:\\Users\\i2011\\OneDrive\\Book_Code&Data\\量化投资以python为工具\\习题解答"

import pandas as pd
import pandas_datareader.data as web
import datetime as dt
import statsmodels.formula.api as smf
from statsmodels.api import add_constant
import statsmodels.api as sm
# 1.
wanke = web.DataReader('000002.SZ', 'yahoo', dt.datetime(2015, 1, 1), dt.datetime(2015, 12, 31))
gldc = web.DataReader('600185.SS', 'yahoo', dt.datetime(2015, 1, 1), dt.datetime(2015, 12, 31))
price = pd.concat([wanke.Close, gldc.Close], 1)
price.columns = ['wanke', 'geli']
ret = (price - price.shift(1)) / price.shift(1)
model = smf.ols('wanke~geli', data=ret).fit()
print(model.summary())

# 5.
zyhy = pd.read_table(Path2+'/Part3/004/problem21.txt',sep='\t', usecols=['zyhy', 'Date'], index_col='Date')
zyhy.index = pd.to_datetime(zyhy.index)

ret = (zyhy - zyhy.shift(1)) / zyhy.shift(1)

ThreeFactors = pd.read_table(Path2+'/Part3/004/ThreeFactors.txt',sep='\t', index_col='TradingDate')
ThreeFactors.index = pd.to_datetime(ThreeFactors.index)
ThrFac = ThreeFactors['2014']
ThrFac.columns
ThrFac = ThrFac.iloc[:, [2, 4, 6]]
dat = pd.concat([ret, ThrFac], 1).dropna()
dat = pd.concat([ret, ThrFac], 1)
model = smf.ols('zyhy~RiskPremium2+SMB2+HML2', data=dat).fit()
print(model.summary())
myDA.three_factors(dat.zyhy,dat.RiskPremium2,dat.SMB2,dat.HML2,False)

# 6.
zhongxin = pd.read_table(Path2+'/Part3/004/problem21.txt',sep='\t', usecols=['zhongxin', 'Date'], index_col='Date')
zhongxin.index = pd.to_datetime(zhongxin.index)
ret = (zhongxin - zhongxin.shift(1)) / zhongxin.shift(1)

ThreeFactors = pd.read_table(Path2+'/Part3/004/ThreeFactors.txt',sep='\t', index_col='TradingDate')
ThreeFactors.index = pd.to_datetime(ThreeFactors.index)
ThrFac = ThreeFactors['2014']
ThrFac = ThrFac.iloc[:, [2, 4, 6]]
dat = pd.concat([ret, ThrFac], 1)

model = smf.ols('zhongxin~RiskPremium2', data=dat).fit()
print(model.summary())

model2 = smf.ols('zhongxin~RiskPremium2+SMB2+HML2', data=dat).fit()
print(model2.summary())

ThrFac = ThreeFactors['2015-01']
preCAPM = model.predict(add_constant(ThrFac.RiskPremium2),transform=False)
preFactors = model2.predict(add_constant(ThrFac[['RiskPremium2', 'SMB2', 'HML2']]),transform=False)
preCAPM.plot()
preFactors.plot()
plt.show()

# 7.
codes = pd.read_csv(Path2+'/Part3/004/codes.csv', header=None, dtype=str)

ThreeFactors = pd.read_table(Path2+'/Part3/004/ThreeFactors.txt', sep='\t', index_col='TradingDate')

ThreeFactors.index = pd.to_datetime(ThreeFactors.index)

ThrFac = ThreeFactors['2014']

ThrFac = ThrFac.iloc[:, [2, 4, 6]]

def create_func(model):
    def cal_alpha(code, model_name=model):
        price = web.DataReader(code, 'yahoo', dt.datetime(2014, 1, 1), dt.datetime(2014, 12, 31)).Close
        ret = (price - price.shift(1)) / price.shift(1)
        ret.name = 'ret'
        dat = pd.concat([ret, ThrFac], 1)
        if model_name == 'CAPM':
            model = smf.ols('ret~RiskPremium2', data=dat).fit()
        elif model_name == 'factors':
            model = smf.ols('ret~RiskPremium2+SMB2+HML2', data=dat).fit()
        return (model.params[0])
    return (cal_alpha)

alpha_CAPM = list(map(create_func('CAPM'), codes[0].values))
alpha_CAPM2 = pd.Series(alpha_CAPM).sort(ascending=False, inplace=False)
alpha_CAPM2[:3]

alpha_factors = list(map(create_func('factors'), codes[0]))
alpha_factors2 = pd.Series(alpha_factors).sort(ascending=False, inplace=False)
alpha_factors2[:3]


from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required
from cage.forms import AddCageForm
from cage.models import Cage
from rabbit.models import Rabbit
from django.db.models import Count, F, Value
from farms.models import ProducerProfile
import os
from django.conf import settings
from PIL import Image
# Create your views here.
@login_required(login_url='login')
def add_cage(request):

    if request.method == 'POST':
        form = AddCageForm(request.POST, request.FILES)
        if form.is_valid():
            cage = form.save(commit=False)
            valid_user = ProducerProfile.objects.get(id=request.user.id, is_producer=True)
            if valid_user:
              cage.farm =valid_user
              cage.save()
            if cage:
                return redirect('add-rabbit')
    else:
        form=AddCageForm()
    return render(request,'Cage/AddCage.html',{
            'form' : form, 'error':'Inconsitencia en el llenado'
        })

def cage_details(request,id):
    pass

def delete_cage(request,id):
    cage_founded = Cage.objects.get(id=id)
    try:
        cage_founded.delete()
    except:
        pass
    return redirect('cage-list')

def cages_list(request):
    rabbits_per_cage = \
        Cage.objects.filter(farm=request.user.id, is_active=True).\
            annotate(rabbit_count=Count('rabbit')).\
            values('cage_title','rabbit_count')
    return render(request,
                  "Cage/CagesList.html",
                  {'cages':rabbits_per_cage})


import datetime as dt
import json

import requests
from flask import Flask, jsonify, request

# create your API token, and set it up in Postman collection as part of the Body section
API_TOKEN = "iamsecure"

app = Flask(__name__)

def get_city_coords(country: str, city: str):
    url = "https://geocoding-api.open-meteo.com/v1/search"

    params = {'name': city}

    response = requests.request("GET", url, params=params)
    status = response.status_code

    json_data = response.json()

    if json_data.get('error') == True:
        raise InvalidUsage(response.get('reason') or 'Unknown weather api errror', status_code=400)

    results = json_data.get("results")

    if results is None:
        raise InvalidUsage("Location not found", status_code=404)

    matching_cities = list(filter(lambda city: (city.get('country').lower() == country.lower()), results))

    if len(matching_cities) == 0:
        raise InvalidUsage("Location not found", status_code=404)

    matching_city = matching_cities[0]

    return (matching_city.get('latitude'), matching_city.get('longitude'))

def assign_dict_props(props, src: dict, dest: dict):
    for prop_name in props:
        dest[prop_name] = src.get(prop_name)

def get_weather(latitude: float, longitude: float, start_date: float, end_date: float):
    url = "https://archive-api.open-meteo.com/v1/archive"

    params = {
        'latitude': latitude,
        'longitude': longitude,
        'start_date': start_date,
        'end_date': end_date,
        'models': 'best_match',
        'daily': [
            'temperature_2m_max',
            'temperature_2m_min',
            'temperature_2m_mean',
            'precipitation_sum',
            'windspeed_10m_max'
        ],
        'hourly': [
           'relativehumidity_2m',
            'temperature_2m',
            'windspeed_10m'
        ],
        "timezone": "GMT"
    }

    response = requests.request("GET", url, params=params).json()

    if response.get('error') == True:
        raise InvalidUsage(response.get('reason') or 'Unknown weather api errror', status_code=400)

    result = {}

    assign_dict_props(['daily', 'daily_units', 'hourly', 'hourly_units'], response, result)

    return result

class InvalidUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv["message"] = self.message
        return rv

@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response

@app.route("/")
def home_page():
    return "

KMA L2: Python Saas.

"

def validate_required(field_names, obj: dict):
    for f_name in field_names:
        val = obj.get(f_name)
        if val is None or val == '':
            raise InvalidUsage(f"{f_name} is required", status_code=400)

@app.route(
    "/content/api/v1/integration/weather",
    methods=["POST"],
)
def weather_endpoint():
    json_data = request.get_json()

    if json_data.get("token") is None:
        raise InvalidUsage("token is required", status_code=400)

    token = json_data.get("token")

    if token != API_TOKEN:
        raise InvalidUsage("wrong API token", status_code=403)

    validate_required(["start_date", "end_date", "location", "requester_name"], json_data)

    start_date = json_data.get("start_date")
    end_date = json_data.get("end_date")
    requester_name = json_data.get('requester_name')
    location = json_data.get("location")

    if ":" not in location:
        raise InvalidUsage("Please provide location in format: 'Country:City'", status_code=400)

    country, city = location.split(':', 1)

    latitude, longitude = get_city_coords(country, city)

    weather_result = get_weather(latitude, longitude, start_date, end_date)

    return {
        'requester_name': requester_name,
        'start_date': start_date,
        'end_date': end_date,
        'weather': weather_result
    }


#!/bin/env python3
"""
Advent Of Code 2021 Day 5
"""

from __future__ import annotations

import sys
import time
import collections

from typing import Iterator

Point = collections.namedtuple('Point', ['x', 'y'])

def point_from_str(point_str: str) -> Point:
    return Point(int(point_str.split(',')[0]), int(point_str.split(',')[1]))

class Line:
    def __init__(self, start: Point, end: Point) -> None:
        self.start = start
        self.end = end
        self.delta_x = self.end.x - self.start.x
        self.delta_y = self.end.y - self.start.y
        self.is_45 = (self.delta_x and self.delta_y and
                      abs(self.delta_x) == abs(self.delta_y))

    def points_between(self) -> Iterator[Point]:
        if self.delta_x and self.delta_y and not self.is_45:
            # Diagonal not 45
            return

        num_steps = max(abs(self.delta_x), abs(self.delta_y))
        step_x = self.delta_x // num_steps
        step_y = self.delta_y // num_steps
        for i in range(num_steps + 1):
            yield Point(self.start.x + step_x * i, self.start.y + step_y * i)

    @classmethod
    def from_str(cls, line_str: str) -> Line:
        return cls(*[point_from_str(point_str)
                     for point_str in line_str.split(' -> ')])

def p1p2(input_file: str) -> tuple[int, int]:
    grid: dict[tuple[int, int], collections.Counter[str]] = \
                                   collections.defaultdict(collections.Counter)

    with open(input_file) as f:
        for line_str in f:
            line = Line.from_str(line_str)
            count = 'diag' if line.is_45 else 'h_and_v'
            for point in Line.from_str(line_str).points_between():
                grid[(point.x, point.y)].update({count: 1})

    results: list[int] = [0, 0]
    for counter in grid.values():
        if counter['h_and_v'] >= 2:
            results[0] += 1
            results[1] += 1
        elif (counter['h_and_v'] + counter['diag']) >= 2:
            results[1] += 1

    return (results[0], results[1])

def main(cli_args: list[str]) -> int:
    start = time.perf_counter()
    print(p1p2(cli_args[0]))
    stop = time.perf_counter()
    print(f"Elapsed: {stop - start:.6f}s")
    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))


# Tasks:

from question_model import Question
from data import question_data
from quiz_brain import QuizBrain

# Question bank is a list of question objects
question_bank = []

for question in question_data:
    # question text = question["text"]
    # question answer = question["answer"]
    # question object = Question(question["text"], question["answer"])
    #question_bank.append(Question(question["text"], question["answer"])) # For old question data set
    question_bank.append(Question(question["question"], question["correct_answer"])) # From opentdb

# test question bank
# print(question_bank[0].text)

quiz = QuizBrain(question_bank)

# Check if quiz game still has questions left
# keep asking the next question if there are
# questions left
while quiz.still_has_questions():
    quiz.next_question() # call for next question and prompt for user input

# Final print statements for the end of the quiz game
print("You have completed the quiz!")
print(f"Your final score was: {quiz.score}/{quiz.question_number}")


#!/usr/bin/env python
import sys
import rospy
import yaml
import argparse
from geometry_msgs.msg import Point32
from zone_marking.srv import mark_lines
from zone_marking.msg import segment, Lines

#This node reads in line information from a yaml file and then
#converts it to lines messages that can then be used to make
#line marking service calls every time an update is made

class lineClientNode:

    def __init__(self, params):
        lines_list = Lines()
        lines_temp = params['Lines']
        for line in params['Lines']:
            current_line = lines_temp[line]
            line_seg = segment()
            line_seg.name = current_line['Name']
            line_seg.thickness = current_line['Thickness']
            point_list = current_line['Points']
            for point in current_line['Points']:
                current_point = point_list[point]
                line_seg.points.append(Point32(x=current_point['x'], y=current_point['y'], z=current_point['z']))
            lines_list.segments.append(line_seg)
            print(lines_list)
        outcome = self.lineMarkingClient(lines_list)

    def lineMarkingClient(self, lines_list):
        rospy.wait_for_service('move_base/mark_lines')
        try:
            line_marking = rospy.ServiceProxy('move_base/mark_lines', mark_lines)
            resp1 = line_marking(lines_list)
            print('Request sent to server')
            return resp1.outcome.data

        except rospy.ServiceException as e:
            print("Service call failed: %s"%e)

def read_yaml(filename):
    with open(filename, 'r') as file:
        params = yaml.safe_load(file)
        return params

if __name__ == "__main__":
    rospy.myargv(argv=sys.argv)
    argv = rospy.myargv(argv=sys.argv)
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--line_data", type=str, help="path to a yaml file holding line information"
    )
    args = parser.parse_args(argv[1:])
    params = read_yaml(args.line_data)
    lineClientNode(params)


import sys
import os
import json
import torch
import numpy as np
import pandas as pd

path = "\\".join(os.path.abspath(__file__).split("\\")[:-2])
sys.path.insert(0, path)
from ModelAuthorConvolution.author_matrices import concatenate_abstracts
from models import MLP, BERT
from utils import check_running_file

# change according to the actual node embedding dimension
NODE_EMBEDDING_DIM = 64

def make_inputs_targets_list(graph_file="node_embeddings.json", targets_file="train.csv"):
    """ read author BERT embeddings and graph embeddings, concatenate them and
        return them as list, meanwhile, fill a list with targets so that inputs
        and targets are correctly aligned

        also fill a dictionnary with the author who are not in the train list
    """

    bert = BERT()
    bert_sentences = bert.load_sentences()      # dictionnary ob author abstracts embeddings
    print("loading node embeddings...")
    with open(graph_file, "r") as f:
        node_embeddings = json.load(f)
    print("done.")
    node_embeddings = {int(k):v for k, v in node_embeddings.items()}
    target_df = pd.read_csv(targets_file).set_index("authorID")
    test_dic = {}

    full_embeddings = []
    targets_list = []
    print("pulling embeddings...")
    for i, auth in enumerate(bert_sentences.keys()):
        if i % 10 == 0 and i > 0:
            print("{} authors processed".format(i))
        auth = int(auth)
        bert_embedding = bert.to_embedding(bert_sentences[auth])
        try:
            h_index = target_df.loc[auth]['h_index']
        except KeyError:
            try:
                test_dic[auth] = torch.tensor(bert_embedding + node_embeddings[auth])
                continue
            except KeyError:
                continue
        try:
            node_embedding = node_embeddings[auth]
        except KeyError:
            continue
        full_embeddings.append(torch.tensor(bert_embedding + node_embedding))
        targets_list.append(h_index)

    return (full_embeddings, targets_list), test_dic

def make_predictions(
    model,
    test_dic,
    input_file="test.csv",
    output_file="test_predictions.csv"
):
    """ create a csv file containing the author indexes and the h-index predictions associated """

    path_to_predictions = "ModelBert\\data"
    try:
        os.mkdir(path_to_predictions)
    except FileExistsError:
        pass

    preds = []
    df_test = pd.read_csv(input_file)
    for i, auth in enumerate(df_test['authorID']):
        if i % 20000 == 0 and i > 0:
            print("{} authors processed".format(i))
        emb = test_dic[auth]
        preds.append(model.predict(emb))
    preds = np.array(preds)
    df_test['h_index_pred'].update(pd.Series(np.round_(preds, decimals=3)))
    df_test.loc[:,["authorID","h_index_pred"]].to_csv(
        os.path.join(path_to_predictions, output_file), index=False
    )

if __name__ == "__main__":

    # whether to train the model or not
    TRAIN = True

    # whether to make predictions or not
    MAKE_PREDICTIONS = True

    # should run from "altegrad-2020"
    TO_RUN_FROM = "code"
    if not check_running_file(TO_RUN_FROM):
        raise OSError("the file should run from \"{}/\" folder".format(TO_RUN_FROM))

    # check if author_abstracts.txt file exists, else create it
    if not os.path.exists("author_abstracts.txt"):
        concatenate_abstracts()

    bert = BERT()

    node_embedding_dim = NODE_EMBEDDING_DIM
    bert_embedding_dim = bert.dimension
    embedding_dim = node_embedding_dim + bert_embedding_dim

    # launch network
    model = MLP(embedding_dim=embedding_dim, path_to_checkpoints="ModelBert\\checkpoints")
    if not model.existing_model():
        TRAIN = True

    # train model
    if TRAIN:
        (inputs_list, targets_list), test_dic = make_inputs_targets_list()
        print("fitting model")
        model.train()
        CHECKPOINT_FILE = "BERT_checkpoint_1.pt"
        model.fit(inputs_list, targets_list, n_epochs=40, batch_size=32, save_file=CHECKPOINT_FILE)

    else:
        TO_LOAD = "BERT_checkpoint_1.pt"
        model.load_model(load_file=TO_LOAD)
        print("successfully loaded {}".format(TO_LOAD))

    # build up the predictions and put it in a csv file
    CSV_OUTPUT = "test_predictions_1.csv"
    if MAKE_PREDICTIONS:
        model.eval()
        make_predictions(model, test_dic, output_file=CSV_OUTPUT)

    FILES_TO_TEST = [
        "test_predictions_1.csv"
    ]


import pygame
import random
import math
#Initialize the pygame
pygame.init()
#Create screen X,Y
screen = pygame.display.set_mode((800,650))
#Background
background = pygame.image.load('Screen Shot 2020-06-19 at 5.44.52 PM.png')
#Title
pygame.display.set_caption("Space Defense")
#Player
playerImage = pygame.image.load('spaceship.png')
spawnX = 370
spawnY = 480
CurrentPlayerX = spawnX
CurrentPlayerY = spawnY
playerX_Change = 0
playerY_Change = 0
def player(x,y):
    #Param image, coordinates
    screen.blit(playerImage, (x,y))
#Enemy
enemyImage = pygame.image.load('ufo.png')
enemyX = random.randint(0,800)
enemyY = 0
enemyX_Change = 0
def enemy(j,k):
    screen.blit(enemyImage, (j,k))

#Bullets
bulletImage = pygame.image.load('bullet.png')
bulletY = CurrentPlayerY
def shoot(w,z):
    screen.blit(bulletImage,(w,z))
explosionImage = pygame.image.load('explosion.png')
def explode(x,y):
    screen.blit(explosionImage,(x,y))

#Anything we want to persistently be in the game window has to go in the loop
#Keeping Game Loop running
shotX = 0
shotY = 0
fire = False
cantShoot = False
running = True
clearedWall = True
shot = False
while running:

    #Param red green and blue 255 max
    screen.fill((0,0,0))
    screen.blit(background,(0,0))
    for event in pygame.event.get():
        #QUIT refers to the quitting button
        if event.type == pygame.QUIT:
            running = False

        #If keystroke is pressed/ a key pressed down, check if left or right
        if event.type == pygame.KEYDOWN:
            #Check and restrict movement boundaries
            if CurrentPlayerX >= 735:
                CurrentPlayerX = 735
            if CurrentPlayerY >=635:
                CurrentPlayerY = 635
            if CurrentPlayerX <= 0:
                CurrentPlayerX = 0
            if CurrentPlayerY <= 0:
                CurrentPlayerY = 0

            #Movement, adjust coordinates according to keys pressed
            if event.key == pygame.K_a:
                playerX_Change = -4
            if event.key == pygame.K_d:
                playerX_Change = 4
            if event.key == pygame.K_w:
                playerY_Change =-4
            if event.key == pygame.K_s:
                playerY_Change = 4

            #Firing
            if event.key == pygame.K_SPACE and cantShoot == False:
                fire = True
                shotX = CurrentPlayerX+19
                shotY = CurrentPlayerY-15

        #Movement stops when keys go up
        if event.type == pygame.KEYUP:
            #Prevents movement stopping when keyup event occurs
            if event.key == pygame.K_a:
                if pygame.key.get_pressed()[pygame.K_d] == True:
                    playerX_Change = 4

                else:
                    playerX_Change = 0
            if event.key == pygame.K_d:
                if pygame.key.get_pressed()[pygame.K_a] == True:
                    playerX_Change = -4

                else:
                    playerX_Change = 0

            if event.key == pygame.K_s:
                if pygame.key.get_pressed()[pygame.K_w] == True:
                    playerY_Change = -4

                else:
                    playerY_Change = 0
            if event.key == pygame.K_w:
                if pygame.key.get_pressed()[pygame.K_s] == True:
                    playerY_Change = 4

                else:
                    playerY_Change = 0

    #Enemy movemement and boundaries

    if(clearedWall):
        enemyX_Change = 6
    if enemyX >= 735:
        clearedWall = False
        enemyY = enemyY+20
        enemyX_Change= -6

    if enemyX <= 0:
        enemyX_Change = 6
        enemyY = enemyY +20

    #Spawn coords playerX playerY
    CurrentPlayerX +=playerX_Change
    CurrentPlayerY +=playerY_Change
    player(CurrentPlayerX, CurrentPlayerY)

    if fire == True:
        shoot(shotX,shotY)
        shotY -= 20
        cantShoot = True
        if (shotY <= 0):
            cantShoot = False
    #Implementing collision with distance formula
    delta_x = (enemyX+30)-shotX
    delta_y = (enemyY-20)-shotY
    distance = 0

    if bulletY>0 :
        distance = math.sqrt(pow(delta_x,2)+(pow(delta_y,2)))
        #If there is a collision
        if distance <=30 and shot == False:
            shot = True
            explode(enemyX,enemyY)

    enemyX += enemyX_Change
    if shot == False:
        enemy(enemyX,enemyY)
    pygame.display.update()


import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc

from callbacks import register_callbacks_info

"""
-
"""

# from market_overview import body4
# Light theme: LUX, dark theme: DARKLY (enable darktheme in navbar)
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.LUX])
server = app.server
app.config['suppress_callback_exceptions'] = True

######################################################################################################################
#! Import function
######################################################################################################################
from functions import unique_firms
######################################################################################################################
#! Navbar and tabs
######################################################################################################################

# make dropdown for selecting firms
dropdown = dcc.Dropdown(
    options=unique_firms,
    value='de wassende maan',
    id='dropdown'
)

# make text input for selecting firms
# text_input = dbc.Input(id='input', type="search", placeholder="Search here",value='de wassende maan',
#                        debounce=True, className="flex-grow-1")

# make navigation bar
navbar = dbc.Navbar(
    dbc.Container(
        [
            html.A(
                # Use row and col to control vertical alignment of logo / brand
                dbc.Row(
                    [
                        dbc.Col(html.Div(html.Img(src='https://evpa.eu.com/uploads/images/Trividend.jpg', height="20px")), width=2 ),
                        dbc.Col(html.Div(dbc.NavbarBrand("Financial Dashboard Portfolio Trividend", className="ms-2",)), width=7),
                        dbc.Col(html.Div(dropdown), width=3),
                    ], justify='center',  className="ms-auto mt-md-0 flex-grow-1 flex-nowrap",
                ),  className="ms-auto mt-md-0 flex-grow-1 flex-nowrap", style={"textDecoration": "none"},
            ),
        ]
    ),
    color="white"
)

navbar2 = dbc.Navbar(
    dbc.Container(
        [
            html.A(
                # Use row and col to control vertical alignment of logo / brand
                dbc.Row(
                    [
                        dbc.Col(html.Img(src='https://evpa.eu.com/uploads/images/Trividend.jpg', height="30px")),
                        dbc.Col(dbc.NavbarBrand("Financial Dashboard Portfolio Trividend", className="ms-2",), width='auto'),
                    ],align="center",
                ),className="m-auto", style={"textDecoration": "none"}
            ),
        ],
    ),
    color="white",
)
######################################################################################################################
#! Body of tabs
######################################################################################################################
body1 = html.Div([
    dbc.Container(
        [
            navbar,
            dbc.Row(dbc.Col(html.H5('Algemene informatie posities', style={'text-align': 'center'}), width=12)),
            html.Hr(),
            dbc.Row(
                [
                    dbc.Col(html.Div(id='bedrijfsnaam'), width=6),
                    dbc.Col(html.Div(id='lening_tekst'), width=6, align='center'),
                ]),
            dbc.Row(
                [
                    dbc.Col(html.Div(id='participatie'), width=6),
                    dbc.Col(html.Div(id='lening_table'), width=6),
                ]),
            dbc.Row(
                [
                    dbc.Col(html.Div(id='geinvesteerd_bedrag'), width={"size": 6, "offset": 6}),
                ]),
            html.Br(),
            dbc.Row(
                [
                    dbc.Col(id='cijfer_table'),
                ]),
        ],
    )
])

body2 = html.Div(
    dbc.Container(
        [
            dbc.Row(dbc.Col(navbar2)),
            dbc.Row(dbc.Col(html.H5('Ratio informatie', style={'text-align': 'center'}), width=12)),
            html.Hr(),
            dbc.Row(dbc.Col(id='ratio_table'))
        ]
    )
)

body3 = html.Div(
    dbc.Container(
        [
            dbc.Row(dbc.Col(navbar2)),
            dbc.Row(dbc.Col(html.H5('Ratio Grafieken', style={'text-align': 'center'}), width=12)),
            html.Hr(),
            dbc.Row(dbc.Col(dcc.Graph(id='liquiditeitsgraph'))),
            dbc.Row(dbc.Col(dcc.Graph(id='rendabiliteitsgraph'))),
            dbc.Row(dbc.Col(dcc.Graph(id='structuurgraph'))),

        ]
    )
)
tabs = dbc.Tabs(
    [
        # dbc.Tab(body4, label='Market'),
        dbc.Tab(body1, label='Algemene informatie'),
        dbc.Tab(body2, label="Ratio's"),
        dbc.Tab(body3, label='Grafieken'),
    ]
)

app.layout = dbc.Container(tabs)

register_callbacks_info(app)
#######################################################################################################################

if __name__ == '__main__':
    app.run_server(debug=True)


import numpy as np
import gym
from gym import spaces

# Penalization
NOOP_PENALIZATION = 0.01

# Exit Points
STOP_LOSS = 0.01
TARGET = 0.015

# Operations
HOLD = 0
BUY = 1

class StopLossTargetEnv(gym.Env):

    def __init__(self, observation_size, features, prices):

        # Data
        self.__features = features
        self.__prices = prices

        # Spaces
        self.observation_space = spaces.Dict({
            'last_action': spaces.Discrete(2),
            'observation': spaces.Box(low=np.NINF, high=np.PINF, shape=(observation_size, features.shape[1]), dtype=np.float32)})
        self.action_space = spaces.Discrete(2)

        # Episode Management
        self.__start_tick = observation_size
        self.__end_tick = len(self.__prices)
        self.__current_tick = self.__end_tick

        # Position Management
        self.__current_action = HOLD
        self.__current_profit = 0
        self.__wins = 0
        self.__losses = 0

    def reset(self):

        # Reset the current action and current profit
        self.__current_action = HOLD
        self.__current_profit = 0
        self.__wins = 0
        self.__losses = 0

        # Reset the current tick pointer and return a new observation
        self.__current_tick = self.__start_tick

        return self.__get_observation()

    def step(self, action):

        # If current tick is over the last index in the feature array, the environment needs to be reset
        if self.__current_tick > self.__end_tick:
            raise Exception('The environment needs to be reset.')

        # Compute the step reward (Penalize the agent if it is stuck doing anything)
        step_reward = 0
        if self.__current_action == HOLD and action == BUY:
            self.__open_price = self.__prices[self.__current_tick]
            self.__stop_loss = self.__open_price * (1 - STOP_LOSS)
            self.__target = self.__open_price * (1 + TARGET)

            self.__current_action = BUY
        elif self.__current_action == BUY:
            current_price = self.__prices[self.__current_tick]

            if current_price < self.__stop_loss or current_price > self.__target:
                step_reward = current_price - self.__open_price
                self.__current_profit += step_reward
                self.__current_action = HOLD

                if step_reward > 0:
                    self.__wins += 1
                else:
                    self.__losses += 1
        elif self.__current_action == HOLD:
            step_reward = -NOOP_PENALIZATION

        # Generate the custom info array with the real and predicted values
        info = {
            'current_action': self.__current_action,
            'current_profit': self.__current_profit,
            'wins': self.__wins,
            'losses': self.__losses
        }

        # Increase the current tick pointer, check if the environment is fully processed, and get a new observation
        self.__current_tick += 1
        done = self.__current_tick >= self.__end_tick
        obs = self.__get_observation()

        # Returns the observation, the step reward, the status of the environment, and the custom information
        return obs, step_reward, done, info

    def action_masks(self):

        # Allow to BUY only if the current position is HOLD
        mask = np.ones(self.action_space.n, dtype=bool)
        mask[BUY] = self.__current_action == HOLD

        return mask

    def __get_observation(self):

        # If current tick over the last value in the feature array, the environment needs to be reset
        if self.__current_tick >= self.__end_tick:
            return None

        # Return the calculated observation
        return {
            'last_action': self.__current_action,
            'observation': self.__features[(self.__current_tick - self.__start_tick):self.__current_tick]
        }


#!/usr/bin/env python
"""
@brief:
Cette routine permet d'identifier des profils et de classer des points dans ces derniers
en fonction de la distance dans un semis de point shp à partir de la localisation d'un axe hydraulique
Tous les fichiers sont au format shp.

Les profils sont décrits de la rive gauche à la rive droite (l'axe définit l'amont et l'aval).
"""
import argparse
import fiona
from fiona.crs import from_epsg
import numpy as np
from shapely.geometry import LineString, Point, mapping
import sys

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("inname_point", help="Semis de point d'entree au format shp")
parser.add_argument("inname_axe", help="Axe hydraulique d'entree au format shp")
parser.add_argument("outname_profil", help="Fichier shp de sortie en LineStringZ")
group_points = parser.add_mutually_exclusive_group(required=True)
group_points.add_argument("--field_profil_id", help="champ contenant les n° de profils (flottants ou entiers)")
group_points.add_argument("--profil_max_dist", help="distance maximale pour regrouper les points par profils",
                          type=float)
args = parser.parse_args()

DIST_VECT_DIR_AXE = 1.0
FIELD = args.field_profil_id if args.field_profil_id is not None else 'Profil'

def subset_data(data, id_profil):
    subdata = []
    for pt in data:
        if pt.id_profil == id_profil:
            subdata.append(pt)
    return subdata

def signe(number):
    """-1 if negative, 1 else"""
    try:
        return number/abs(number)
    except ZeroDivisionError:
        return 1

class Pt:
    def __init__(self, coord, id_profil):
        self.coord = coord
        self.geom = Point(self.coord)
        self.id_profil = id_profil
        self.abs_axe = geom_axe.project(self.geom)
        self.geom_proj = geom_axe.interpolate(self.abs_axe)
        self.dist = geom_axe.distance(self.geom)

    def __repr__(self):
        return "Pt: {}, ".format(self.id_profil) + str(self.coord)

class Profil:
    def __init__(self, id_profil, np_coord):
        self.id_profil = id_profil
        self.coord = np_coord
        if np_coord.shape[0] > 1:
            self.geom = LineString(np_coord)
        else:
            sys.exit("Profil #{} ne contient qu'un point !".format(id_profil))

    def __repr__(self):
        return "Profil {} ({} points)".format(self.id_profil, len(self.coord))

    def compute_Xt(self):
        Xt = np.sqrt(np.power(np.ediff1d(self.coord[:, 0], to_begin=0.), 2) +
                     np.power(np.ediff1d(self.coord[:, 1], to_begin=0.), 2))
        return Xt.cumsum()

# Axe hydraulique
coord = []
with fiona.open(args.inname_axe, 'r') as in_axe:
    for i, record in enumerate(in_axe):
        if i != 0:
            sys.exit("Le fichier d'axe contient plus qu'un objet")
        if record['geometry']['type'] == 'LineString':
            coord = record['geometry']['coordinates']
        else:
            sys.exit("Le fichier d'axe n'est pas de type `LineString`")
if not coord:
    sys.exit("Le fichier d'axe est vide")
geom_axe = LineString(coord)

# Points décrivant les profils en travers
data = []
with fiona.open(args.inname_point, 'r') as in_pts:
    if in_pts.schema['geometry'] != '3D Point':
        sys.exit("Le fichier de points n'est pas de type `3D Point` mais § %s" % in_pts.schema['geometry'])
    for record in in_pts:
        x, y, z = record['geometry']['coordinates']
        attr = None
        if args.field_profil_id is not None:
            try:
                attr = str(record['properties'][args.field_profil_id])
            except KeyError:
                sys.exit("L'attribut %s n'existe pas" % args.field_profil_id)
        pt = Pt((x, y, z), attr)
        data.append(pt)

# Regroupement par profil
if args.profil_max_dist is not None:
    # Avec un critère de "saut maximum" d'abscisse le long de l'axe
    data = sorted(data, key=lambda p: p.abs_axe)
    i_profil = 0
    prev_abs_axe = data[0].abs_axe
    for pt in data:
        if pt.abs_axe - prev_abs_axe > args.profil_max_dist:
            i_profil += 1
        pt.id_profil = i_profil
        prev_abs_axe = pt.abs_axe
else:
    # Avec l'attribut déjà lu précédemment
    pass

# Extraction de la liste des noms de profils
id_profils = []
for pt in data:
    if pt.id_profil not in id_profils:
        id_profils.append(pt.id_profil)

profils = []
for id_profil in sorted(id_profils):
    subdata = subset_data(data, id_profil)

    for pt in subdata:
        # Vecteur directeur axe au niveau de la projection du point
        pt_axe_avant = geom_axe.interpolate(pt.abs_axe - DIST_VECT_DIR_AXE)
        pt_axe_apres = geom_axe.interpolate(pt.abs_axe + DIST_VECT_DIR_AXE)
        dX_vect_dir_axe = pt_axe_apres.x - pt_axe_avant.x
        dY_vect_dir_axe = pt_axe_apres.y - pt_axe_avant.y

        # Vecteur de la projection au point
        dX_vect_norm_axe = pt.geom.x - pt.geom_proj.x
        dY_vect_norm_axe = pt.geom.y - pt.geom_proj.y

        det = dX_vect_dir_axe*dY_vect_norm_axe - dY_vect_dir_axe*dX_vect_norm_axe
        pt.dist = -signe(det)*pt.dist

    sorted_subdata = sorted(subdata, key=lambda p: p.dist)
    np_coord = np.array([pt.coord for pt in sorted_subdata])
    profil = Profil(id_profil, np_coord)
    profils.append(profil)

schema = {'geometry': '3D LineString', 'properties': {FIELD: 'str:32'}}
with fiona.open(args.outname_profil, 'w', 'ESRI Shapefile', schema, crs=from_epsg(3945)) as layer:
    for profil in profils:
        print("Profil #{}".format(profil))

        elem = {}
        elem['geometry'] = mapping(profil.geom)
        elem['properties'] = {FIELD: profil.id_profil}
        layer.write(elem)


from sqlalchemy import Column, String, DateTime, func, Index

from .base import Base

class FinmindTaiwanStockInfo(Base):
    __tablename__ = 'finmind_taiwan_stock_info'
    __table_args__ = (
        Index('idx_finmind_taiwan_stock_info_industry_category', 'industry_category'),
        Index('idx_finmind_taiwan_stock_info_type', 'type'),
    )

    stock_id = Column(String(32), nullable=False, primary_key=True)
    industry_category = Column(String(32), nullable=False, default='')
    stock_name = Column(String(60), nullable=False, default='')
    type = Column(String(32), nullable=False, default='')
    date = Column(String(10), nullable=False)

    created_at = Column(DateTime, nullable=False, server_default=func.now())
    updated_at = Column(DateTime, nullable=False, server_default=func.now(), onupdate=func.now())


import unittest

from marshmallow import ValidationError

from imgchkr_api.schemas import ValidateImageRequestSchema

class ValidateImageRequestSchemaTestCase(unittest.TestCase):
    def setUp(self) -> None:
        self._schema = ValidateImageRequestSchema()

    def test_valid_schema_passes(self) -> None:
        result = self._schema.load(
            {
                'assetPath': {
                    'location': 'location',
                    'path': 'path',
                },
                'notifications': {
                    'onStart': 'onStart',
                    'onSuccess': 'onSuccess',
                    'onFailure': 'onFailure',
                },
            }
        )
        assert result == {
            'asset_path': {
                'location': 'location',
                'path': 'path',
            },
            'notifications': {
                'on_start': 'onStart',
                'on_success': 'onSuccess',
                'on_failure': 'onFailure',
            },
        }

    def test_missing_urls_reported(self) -> None:
        with self.assertRaises(ValidationError) as exc_ctx:
            self._schema.load(
                {
                    'assetPath': {
                        'location': 'location',
                        'path': 'path',
                    },
                    'notifications': {
                        'onStart': 'onStart',
                    },
                }
            )
        assert exc_ctx.exception.messages_dict == {
            'notifications': {
                'onFailure': ['Missing data for required field.'],
                'onSuccess': ['Missing data for required field.'],
            }
        }


import numpy as np
import matplotlib.pylab as pl
import netCDF4 as nc

from microhh_tools import *    # available in MICROHH_DIR/python; copy to this directory

# Class to create a smooth stretched vertical grid
class Grid:
    def __init__(self, kmax, nloc1, nbuf1, dz1, dz2):
        dn         = 1./kmax
        n          = np.linspace(dn, 1.-dn, kmax)
        nloc1     *= dn
        nbuf1     *= dn
        dzdn1      = dz1/dn
        dzdn2      = dz2/dn

        dzdn       = dzdn1 + 0.5*(dzdn2-dzdn1)*(1. + np.tanh((n-nloc1)/nbuf1))
        self.dz    = dzdn*dn

        self.kmax  = kmax
        self.z     = np.zeros(self.dz.size)
        stretch    = np.zeros(self.dz.size)

        self.z[0]  = 0.5*self.dz[0]
        stretch[0] = 1.

        for k in range(1, self.kmax):
              self.z [k] = self.z[k-1] + 0.5*(self.dz[k-1]+self.dz[k])
              stretch[k] = self.dz[k]/self.dz[k-1]

        self.zh = np.insert(np.cumsum(self.dz), 0, 0)
        self.zsize = self.z[kmax-1] + 0.5*self.dz[kmax-1]
        print('kmax={0:}, zsize={1:.4f}'.format(kmax,self.zsize))

    def plot(self):
        pl.figure()
        pl.plot(self.z, self.dz, '-x')
        pl.xlabel('z (m)')
        pl.ylabel('dz (m)')

if __name__ == "__main__":
    pl.close('all')
    pl.ion()

    # MicroHH-mode (np.float32 (single) or np.float64 (double) precision)
    tf = np.float64

    # Read the .ini file
    ini = Read_namelist()

    # Settings sine hills (all in units [m])
    amplitude = 0.00254
    wavelength_x = 0.0508
    wavelength_y = 0
    z_offset = 0.002

    # Create stretched grid
    #grid = Grid(16, 40, 5, 0.0008, 0.0015)
    #grid = Grid(96, 40, 5, 0.0004, 0.0007)
    #grid = Grid(128, 40, 5, 0.0002, 0.0005373)
    grid = Grid(256, 122, 10, 0.0001, 0.000322)
    #grid = Grid(384, 180, 20, 0.00006, 0.00021831)
    grid.plot()

    print('Effective zsize = {}'.format(grid.zsize-z_offset-amplitude))

    # Write `zsize` and `ktot` back to .ini file
    replace_namelist_value('zsize', grid.zsize)
    replace_namelist_value('ktot',  grid.kmax)

    # Create initial profiles:
    z = grid.z
    u = 0.00137 * np.ones(z.size)
    b = z

    # Write the data to a .nc file for MicroHH
    float_type = 'f8' if tf==np.float64 else 'f4'

    nc_file = nc.Dataset("sine_input.nc", mode="w", datamodel="NETCDF4", clobber=True)
    nc_file.createDimension("z", grid.kmax)
    nc_z  = nc_file.createVariable("z" , float_type, ("z"))

    nc_group_init = nc_file.createGroup("init");
    nc_u  = nc_group_init.createVariable("u" , float_type, ("z"))
    nc_b  = nc_group_init.createVariable("b" , float_type, ("z"))

    nc_z[:] = grid.z [:]
    nc_u[:] = u[:]
    nc_b[:] = b[:]

    nc_file.close()

    # Create 2D height map
    dx = ini['grid']['xsize'] / ini['grid']['itot']
    dy = ini['grid']['ysize'] / ini['grid']['jtot']

    x  = np.arange(0.5*dx, ini['grid']['xsize'], dx)
    xh = np.arange(0, ini['grid']['xsize']+1e-9, dx)

    y  = np.arange(0.5*dy, ini['grid']['ysize'], dy)
    yh = np.arange(0, ini['grid']['ysize']+1e-9, dy)

    dem = np.zeros((ini['grid']['itot'], ini['grid']['jtot']), dtype=tf)

    for j in range(ini['grid']['jtot']):
        dem[:,j] = z_offset + amplitude + amplitude * np.sin(2*np.pi*x/wavelength_x)

    pl.figure()
    ax=pl.subplot(111, aspect='equal')
    pl.plot(x, dem[:,0])

    for k in range(z.size):
        pl.plot(xh, np.ones_like(xh)*grid.zh[k], 'k-', linewidth=0.5)
        pl.scatter(x, np.ones_like(x)*grid.z[k], s=1, color='r')
    for i in range(x.size):
        pl.plot(np.ones_like(grid.zh)*xh[i], grid.zh, 'k-', linewidth=0.5)

    dem.T.tofile('dem.0000000')

    # Create example spatially varying sbot files
    mask = dem > dem.mean()
    b    = np.zeros_like(dem)

    b[mask]  = -0.1
    b[~mask] = 0.1

    b.T.tofile('b_sbot.0000000')