import sys
import time

from robodk import robodialogs

if robodialogs.ENABLE_QT:
    from PySide2 import QtWidgets, QtCore, QtGui

if robodialogs.ENABLE_TK:
    if sys.version_info[0] < 3:
        import Tkinter as tkinter
        import tkFileDialog as filedialog
        import tkMessageBox as messagebox
    else:
        import tkinter
        from tkinter import filedialog
        from tkinter import messagebox
"""
App/actions control utilities.

Use these to control your App's actions: run on click, run while checked, do not kill, etc.
"""

class RunApplication:
    """
    Class to detect when the terminate signal is emitted to stop an action.

    .. code-block:: python

        RUN = RunApplication()
        while RUN.Run():
            # your main loop to run until the terminate signal is detected
            ...

    """
    time_last = -1
    param_name = None
    RDK = None

    def __init__(self, rdk=None):
        if rdk is None:
            from robodk.robolink import Robolink
            self.RDK = Robolink()
        else:
            self.RDK = rdk

        self.time_last = time.time()
        if len(sys.argv) > 0:
            import os
            path = sys.argv[0]
            folder = os.path.basename(os.path.dirname(path))
            file = os.path.basename(path)
            if file.endswith(".py"):
                file = file[:-3]
            elif file.endswith(".exe"):
                file = file[:-4]

            self.param_name = file + "_" + folder
            self.RDK.setParam(self.param_name, "1")  # makes sure we can run the file separately in debug mode

    def Run(self):
        """
        Run callback.

        :return: True as long as the App is permitted to run.
        :rtype: bool
        """
        time_now = time.time()
        if time_now - self.time_last < 0.1:
            return True
        self.time_last = time_now
        if self.param_name is None:
            # Unknown start
            return True

        keep_running = not (self.RDK.getParam(self.param_name) == 0)
        return keep_running

def Unchecked():
    """
    Verify if the command "Unchecked" is present. In this case it means the action was just unchecked from RoboDK (applicable to checkable actions only).

    Example for a 'Checkable Action':

    .. code-block:: python

        def runmain():
            if roboapps.Unchecked():
                ActionUnchecked()
            else:
                roboapps.SkipKill()  # Optional, prevents RoboDK from force-killing the action after 2 seconds
                ActionChecked()

    .. seealso:: :func:`~robodk.roboapps.Checked`, :func:`~robodk.roboapps.SkipKill`, :func:`~robodk.roboapps.KeepChecked`
    """
    if len(sys.argv) >= 2:
        if "Unchecked" in sys.argv[1:]:
            return True

    return False

def Checked():
    """
    Verify if the command "Checked" is present. In this case it means the action was just checked from RoboDK (applicable to checkable actions only).

    Example for a 'Checkable Action':

    .. code-block:: python

        def runmain():
            if roboapps.Unchecked():
                ActionUnchecked()
            else:
                roboapps.SkipKill()  # Optional, prevents RoboDK from force-killing the action after 2 seconds
                ActionChecked()

    .. seealso:: :func:`~robodk.roboapps.Unchecked`, :func:`~robodk.roboapps.SkipKill`, :func:`~robodk.roboapps.KeepChecked`
    """
    if len(sys.argv) >= 2:
        if "Checked" in sys.argv[1:]:
            return True

    return False

def KeepChecked():
    """
    Keep an action checked even if the execution of the script completed (applicable to checkable actions only).

    Example for a 'Checkable Option':

    .. code-block:: python

        def runmain():
            if roboapps.Unchecked():
                ActionUnchecked()
            else:
                roboapps.KeepChecked()  # Important, prevents RoboDK from unchecking the action after it has completed
                ActionChecked()

    .. seealso:: :func:`~robodk.roboapps.Unchecked`, :func:`~robodk.roboapps.SkipKill`, :func:`~robodk.roboapps.KeepChecked`
    """
    print("App Setting: Keep checked")
    sys.stdout.flush()

def SkipKill():
    """
    For Checkable actions, this setting will tell RoboDK App loader to not kill the process a few seconds after the terminate function is called.
    This is needed if we want the user input to save the file. For example: The Record action from the Record App.

    Example for a 'Momentary Action':

    .. code-block:: python

        def runmain():
            if roboapps.Unchecked():
                roboapps.Exit()  # or sys.exit()
            else:
                roboapps.SkipKill()  # Optional, prevents RoboDK from force-killing the action after 2 seconds
                ActionChecked()

    .. seealso:: :func:`~robodk.roboapps.Unchecked`, :func:`~robodk.roboapps.Checked`, :func:`~robodk.roboapps.KeepChecked`
    """
    print("App Setting: Skip kill")
    sys.stdout.flush()

def Exit(exit_code=0):
    """
    Exit/close the action gracefully. If an error code is provided, RoboDK will display a trace to the user.
    """
    sys.exit(exit_code)

"""
General utilities
"""

def Str2FloatList(str_values, expected_nvalues=3):
    """
    Convert a string into a list of floats. It returns None if the array is smaller than the expected size.

    :param str_values: The string containing a list of floats
    :type str_values: list of str
    :param expected_nvalues: Expected number of values in the string list, defaults to 3
    :type expected_nvalues: int, optional

    :return: The list of floats
    :rtype: list of float
    """
    import re
    if str_values is None:
        return None

    values = re.findall("[-+]?\d+[\.]?\d*", str_values)
    valuesok = []
    for i in range(len(values)):
        try:
            valuesok.append(float(values[i]))
        except:
            return None

    if len(valuesok) < expected_nvalues:
        return None

    print('Read values: ' + repr(values))
    return valuesok

def Registry(varname, setvalue=None):
    """
    Read value from the registry or set a value. It will do so at HKEY_CURRENT_USER so no admin rights required.
    """
    from sys import platform as _platform
    if _platform == "linux" or _platform == "linux2":
        # Ubuntu, Linux or Debian
        return None
    elif _platform == "darwin":
        # MacOS
        #self.APPLICATION_DIR = "/Applications/RoboDK.app/Contents/MacOS/RoboDK"
        return None
    else:
        # Windows assumed
        if sys.version_info[0] < 3:
            import _winreg
        else:
            import winreg as _winreg

        def KeyExist(key, subkey, access) -> bool:
            try:
                hkey = _winreg.OpenKey(key, subkey, 0, access)
            except OSError as e:
                print(e)
                return None
            return hkey

        # Key settings
        access_flag = _winreg.KEY_READ if setvalue is None else _winreg.KEY_WRITE
        key = _winreg.HKEY_CURRENT_USER
        subkey = "SOFTWARE\\RoboDK"

        # Get the key or create a new one (unless we are reading the value)
        hKey = KeyExist(key, subkey, access_flag | _winreg.KEY_WOW64_64KEY)
        if hKey is None:
            hKey = KeyExist(key, subkey, access_flag | _winreg.KEY_WOW64_32KEY)
            if hKey is None and setvalue is not None:
                try:
                    hKey = _winreg.CreateKeyEx(key, subkey, 0, _winreg.KEY_WRITE | _winreg.KEY_WOW64_64KEY)
                except OSError as e:
                    print(e)
                    return None
            else:
                return None

        if setvalue is None:
            # Read the value.
            try:
                result = _winreg.QueryValueEx(hKey, varname)
                _winreg.CloseKey(hKey)
                return result[0]  # Return only the value from the resulting tuple (value, type_as_int).
            except _winreg.QueryValue as e:
                print(e)
                return None
        else:
            # Write the value
            try:
                _winreg.SetValueEx(hKey, varname, 0, _winreg.REG_SZ, str(setvalue))
                _winreg.CloseKey(hKey)
                return None
            except _winreg.SetValue as e:
                print(e)
                return None

"""
UI utilities (Qt and Tkinter utilities).

Use these to easily create GUI Apps, settings forms, using either Tkinter or Qt (PySide2).
"""

def value_to_widget(value, parent):
    """
    Convert a value to a widget (Tkinter or Qt).

    The widget is automatically created for supported types:
    - Base types: bool, int, float, str
    - list or tuple of base types
    - dropdown formatted as [int, [str, str, ...]]. e.g. [1, ['Option #1', 'Option #2']] where 1 means the default selected option is Option #2.
    - dictionary of supported types, where the key is the field's label. e.g. {'This is a bool!' : True}.

    :param value: The value to convert as a widget, and the initial value of the widget
    :type value: see supported types
    :param parent: Parent of the widget (Qt/Tkinter)

    :return: (widget, funcs) the widget, and a list of 'get' functions to retrieve the value of the widget
    :rtype: tuple of widget (Qt/Tkinter), callable

    .. seealso:: :func:`~robodk.roboapps.widget_to_value`
    """
    if robodialogs.ENABLE_QT:
        return value_to_qt_widget(value, parent)
    else:
        return value_to_tk_widget(value, parent)

def widget_to_value(funcs, original_value):
    """
    Retrieve the value from a widget's list of get functions.
    The original value is required to recreate the original format.

    :param funcs: list of get functions, see :func:`~robodk.roboapps.value_to_widget`
    :type funcs: list of callable
    :param original_value: The original value, see :func:`~robodk.roboapps.value_to_widget`

    :return: The value

    .. seealso:: :func:`~robodk.roboapps.value_to_widget`
    """
    value_list = [func() if callable(func) else func for func in funcs]

    def is_pod(value):
        # Plain old data (POD)
        return isinstance(value, (float, int, str, bool))

    def is_pod_list(value):
        # List or tuple of PODs
        if isinstance(value, list) and len(value) > 0 and all(is_pod(n) for n in value):
            return True
        return False

    def is_pod_tuple(value):
        # List or tuple of PODs
        if isinstance(value, tuple) and len(value) > 0 and all(is_pod(n) for n in value):
            return True
        return False

    def is_dropdown(value):
        # ComboBox with specified index as int [1, ['First line', 'Second line', 'Third line']]
        if type(value) is list and (len(value) == 2) and isinstance(value[0], int) and value[0] in range(len(value[1])) and all(isinstance(n, str) for n in value[1]):
            return True

        # ComboBox with specified index as str ['Second line', ['First line', 'Second line', 'Third line']]
        elif type(value) is list and (len(value) == 2) and isinstance(value[0], str) and value[0] in value[1] and all(isinstance(n, str) for n in value[1]):
            return True

        return False

    def is_pod_dict(value):
        # Dictionary of supported types, does not supported nested dictionaries
        if isinstance(value, dict):
            if len(value.keys()) > 0:
                if all(is_pod(n) or is_pod_list(n) or is_pod_tuple(n) or is_dropdown(n) for n in value.values()):
                    return True
                return True
        return False

    if is_pod(original_value):
        return value_list[0]

    elif is_pod_list(original_value):
        return list(value_list)

    elif is_pod_tuple(original_value):
        return tuple(value_list)

    elif is_dropdown(original_value):
        new_value = original_value
        new_value[0] = value_list[0]
        return new_value

    elif is_pod_dict(original_value):
        new_value = original_value
        for key, old_value in original_value.items():
            if is_pod(old_value):
                new_value[key] = value_list[0]
                value_list.pop(0)

            elif is_pod_list(old_value):
                new_value[key] = value_list[0:len(old_value)]
                value_list = value_list[len(old_value):]

            elif is_pod_tuple(old_value):
                new_value[key] = tuple(value_list[0:len(old_value)])
                value_list = value_list[len(old_value):]

            elif is_dropdown(old_value):
                new_value[key] = old_value
                new_value[key][0] = value_list[0]
                value_list.pop(0)
        return new_value

    return value_list

def get_robodk_theme(RDK=None):
    """
    Get RoboDK's active theme (Options->General->Theme)
    """
    if RDK is None:
        from robodk.robolink import Robolink
        RDK = Robolink()

    # These are indexes in the Theme dropdown of RoboDK (in case they change)
    themes = {
        0: 'Light',  # default is OS based
        1: 'Light',
        2: 'Dark',
        3: 'Windows',
        4: 'Windows XP',
        5: 'Windows Vista',
        6: 'Mac',
        7: 'Fusion',
        8: 'Android',
    }

    theme_idx = RDK.Command('Theme', '')
    return themes[int(theme_idx)]

"""
PySide2 / Qt utilities
"""

if robodialogs.ENABLE_QT:

    def get_qt_app(robodk_icon=True, robodk_theme=True, RDK=None):
        """
        Get the QApplication instance.

        Note: If RoboDK is not running, The RoboDK theme is not applied.

        :param bool robodk_icon: Applies the RoboDK logo, defaults to True
        :param bool robodk_theme: Applies the current RoboDK theme, defaults to True
        :param robolink.Robolink RDK: Link to the running RoboDK instance for the theme, defaults to None

        :return: The QApplication instance
        :rtype: :class:`PySide2.QtWidgets.QApplication`
        """

        app = QtWidgets.QApplication.instance()
        if app is None:
            QtWidgets.QApplication.setAttribute(QtCore.Qt.ApplicationAttribute.AA_EnableHighDpiScaling, True)
            QtWidgets.QApplication.setAttribute(QtCore.Qt.ApplicationAttribute.AA_DisableWindowContextHelpButton, True)
            app = QtWidgets.QApplication([])

        if robodk_icon:
            from robodk import robolink
            icon_path = robolink.getPathIcon()
            from os import path
            if path.exists(icon_path):
                if sys.platform.startswith('win'):
                    import ctypes
                    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(str(app))  # Enable the taskbar icon
                app_icon = QtGui.QIcon(icon_path)
                app.setWindowIcon(app_icon)

        if robodk_theme:
            if RDK is None:
                RDK = robolink.Robolink(robodk_path='')  # If no running instance of RoboDK is found, do not instantiate RoboDK
            try:
                if RDK._is_connected():
                    set_qt_theme(app, RDK)
            except:
                pass

        return app

    def set_qt_theme(app, RDK=None):
        """Set a Qt application theme to match RoboDK's theme.

        :param app: The QApplication
        :type app: :class:`PySide2.QtWidgets.QApplication`
        """
        # RoboDK theme : Qt theme
        qt_theme_map = {
            #'Light': None,  # light is default Qt theme
            'Dark': 'Fusion',
            'Windows': 'Windows',
            'Windows XP': 'windowsxp',
            'Windows Vista': 'windowsvista',
            'Fusion': 'Fusion',
        }

        rdk_theme = get_robodk_theme(RDK)
        qt_themes = QtWidgets.QStyleFactory.keys()

        if rdk_theme in qt_theme_map and qt_theme_map[rdk_theme] in qt_themes:
            qt_theme = qt_theme_map[rdk_theme]
        #elif qt_themes:
        #    qt_theme = qt_themes[0]
        else:
            return

        app.setStyle(QtWidgets.QStyleFactory.create(qt_theme))

        if rdk_theme == 'Dark':
            darkPalette = QtGui.QPalette()
            darkColor = QtGui.QColor(45, 45, 45)
            disabledColor = QtGui.QColor(127, 127, 127)
            darkPalette.setColor(QtGui.QPalette.ColorRole.Window, darkColor)
            darkPalette.setColor(QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("white"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.Base, QtGui.QColor(18, 18, 18))
            darkPalette.setColor(QtGui.QPalette.ColorRole.AlternateBase, darkColor)
            darkPalette.setColor(QtGui.QPalette.ColorRole.ToolTipBase, QtGui.QColor("black"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.ToolTipText, QtGui.QColor("white"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.Text, QtGui.QColor("white"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.BrightText, QtGui.QColor("white"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.Button, darkColor)
            darkPalette.setColor(QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor("white"))
            darkPalette.setColor(QtGui.QPalette.ColorRole.Link, QtGui.QColor(42, 130, 218))
            darkPalette.setColor(QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(42, 130, 218))
            darkPalette.setColor(QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor("black"))

            darkPalette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Text, disabledColor)
            darkPalette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, disabledColor)
            darkPalette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.HighlightedText, disabledColor)
            darkPalette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.WindowText, disabledColor)

            app.setPalette(darkPalette)

    def get_qt_robodk_icon(icon_name, RDK=None):
        """
        Retrieve a RoboDK icon by name, such as robot, tool and frame icons (requires Qt module).

        :param str icon_name: The name of the icon
        :return: a QImage of the icon if it succeeds, else None
        :rtype: :class:`PySide2.QtGui.QImage`

        .. seealso:: :func:`~robodk.roboapps.get_qt_robodk_icons`
        """
        if RDK is None:
            from robodk.robolink import Robolink
            RDK = Robolink()

        if 'Addin Manager' in RDK.Command('PluginsList'):
            img_hex = RDK.PluginCommand('Addin Manager', 'IconGet', icon_name)
        else:
            img_hex = RDK.PluginCommand('App Loader', 'IconGet', icon_name)
        if type(img_hex) is not str or img_hex == '':
            return None

        byte_array = QtCore.QByteArray.fromHex(img_hex.encode())
        image = QtGui.QImage()  # QImage does not require a QApplication instance, as appose to QPixmap
        if not image.loadFromData(byte_array):
            return None
        return image

    def get_qt_robodk_icons(RDK=None):
        """
        Retrieve a dictionary of available RoboDK icons, such as robot, tool and frame icons (requires Qt module).

        :return: a dictionary of QImage of available icons
        :rtype: dict of :class:`PySide2.QtGui.QImage`

        .. seealso:: :func:`~robodk.roboapps.get_qt_robodk_icon`
        """
        if RDK is None:
            from robodk.robolink import Robolink
            RDK = Robolink()

        tree_icons = [
            "station",
            "frame",
            "object",
            "robot",
            'mechanism',
            "tcp",
            "target",
            "targetjoint",
            "nodeprogram",
            "nodemachining",
            "nodemachining_printing",
            "nodemachining_curves",
            "nodemachining_milling",
            "nodemachining_points",
            "python",
            "folder",
            "notes",
            "curve",
            "point",
            "surface",
        ]

        sim_icons = [
            'play',
            'pause',
            'stop',
            'fastfwd',
            'start',
            'end',
        ]

        edit_icons = [
            'edit-copy',
            'edit-cut',
            'edit-paste',
            'edit',
            'loopno',
            'loopyes',
            'redo',
            'undo',
            'save',
            'saveas',
            'config',
            'configure',
            'newfile',
            'newfile_online',
            'newstation',
        ]

        mouse_icons = [
            'cursormoveframe',
            'cursormoveobject',
            'cursorpan',
            'cursorselectrectangle',
            'cursorsnone',
            'cursorsrotate',
            'cursorzoom',
        ]

        program_icons = [
            'inschangespeed',
            'inschangezone',
            'inscode',
            'inscomment',
            'insevent',
            'insmanageio',
            'insmoveC',
            'insmoveJ',
            'insmoveL',
            'insprint',
            'insprogcall',
            'instimer',
        ]

        view_icons = [
            'view-axometric',
            'view-bottom',
            'view-front',
            'view-fullscreen',
            'view-isometric',
            'view-left',
            'view-rear',
            'view-right',
            'view-rotate-left',
            'view-rotate-right',
            'view-top',
        ]

        action_icons = [
            'add',
            'plus',
            'minus',
            'yes',
            'no',
            'close',
            'replace',
            'information',
            'questionmark',
            'warning',
            'snapshot',
            'workspace',
            'anchor',
            'connect',
            'export',
            'package',
        ]

        icons = {}
        for name in tree_icons + sim_icons + edit_icons + mouse_icons + program_icons + view_icons + action_icons:
            icon = get_qt_robodk_icon(name, RDK)
            if not icon:
                continue
            icons[name] = icon
        return icons

    def value_to_qt_widget(value, parent=None):
        """
        Convert a value to a widget. For instance, a float into a QDoubleSpinBox, a bool into a QCheckBox.

        The widget is automatically created for supported types:
        - bool, int, float, str (base types)
        - list or tuple of base types
        - dropdown formatted as [int, [str, str, ...]] i.e. [1, ['Option #1', 'Option #2']] where 1 means the default selected option is Option #2.
        - dictionary of supported values, formatted as {label:value}

        :return: (widget, funcs) the widget, and a list of get functions to retrieve the value of the widget
        """
        widget = None
        func = []
        value_type = type(value)

        if value_type is float:
            widget = QtWidgets.QDoubleSpinBox(parent)
            import decimal
            decimals = min(4, max(2, abs(decimal.Decimal(str(value)).as_tuple().exponent)))  # Default to 2, up to 4
            widget.setDecimals(decimals)
            widget.setRange(-9999999., 9999999.)
            widget.setValue(value)
            func = [widget.value]

        elif value_type is int:
            widget = QtWidgets.QSpinBox(parent)
            widget.setRange(-9999999, 9999999)
            widget.setValue(value)
            func = [widget.value]

        elif value_type is str:
            widget = QtWidgets.QLineEdit(parent)
            widget.setText(value)
            func = [widget.text]

        elif value_type is bool:
            widget = QtWidgets.QCheckBox("Activate", parent)
            widget.setChecked(value)
            func = [widget.isChecked]

        # List or tuple of PODs
        elif value_type in [list, tuple] and len(value) > 0 and all(isinstance(n, (float, int, str, bool)) for n in value):
            h_layout = QtWidgets.QHBoxLayout()
            h_layout.setSpacing(0)
            h_layout.setContentsMargins(0, 0, 0, 0)
            h_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
            for v in value:
                f_widget, f_func = value_to_qt_widget(v, None)
                func.extend(f_func)
                h_layout.addWidget(f_widget)
            widget = QtWidgets.QWidget(parent)
            widget.setLayout(h_layout)

        # ComboBox with specified index as int [1, ['First line', 'Second line', 'Third line']]
        elif value_type is list and (len(value) == 2) and isinstance(value[0], int) and value[0] in range(len(value[1])) and all(isinstance(n, str) for n in value[1]):
            index = value[0]
            options = value[1]
            widget = QtWidgets.QComboBox(parent)
            widget.addItems(options)
            widget.setCurrentIndex(index)
            func = [widget.currentIndex]

        # ComboBox with specified index as str ['Second line', ['First line', 'Second line', 'Third line']]
        elif value_type is list and (len(value) == 2) and isinstance(value[0], str) and value[0] in value[1] and all(isinstance(n, str) for n in value[1]):
            index = value[1].index(value[0])
            options = value[1]
            widget = QtWidgets.QComboBox(parent)
            widget.addItems(options)
            widget.setCurrentIndex(index)
            func = [widget.currentIndex]  # str index will be replaced with int index once saved

        # Dictionary of label:value
        elif value_type is dict:
            f_layout = QtWidgets.QFormLayout()
            f_layout.setVerticalSpacing(1)
            f_layout.setHorizontalSpacing(10)
            f_layout.setContentsMargins(0, 0, 0, 0)
            f_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)

            for key, val in value.items():

                if key.endswith('$') and key.startswith('$'):
                    # Section separator
                    label = QtWidgets.QLabel()
                    label.setText(f'[  {key[1:-1]}  ]'.upper())
                    label.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignBottom)
                    spacing = 0
                    if f_layout.rowCount() > 0:
                        spacing += 15
                    label.setContentsMargins(0, spacing, 0, 5)
                    func.extend([key])
                    f_layout.addRow(label)
                    continue

                label = QtWidgets.QLabel(key)
                f_widget, f_func = value_to_qt_widget(val)
                func.extend(f_func)
                f_layout.addRow(label, f_widget)

            widget = QtWidgets.QWidget(parent)
            widget.setLayout(f_layout)

        return widget, func

"""
Tkinter utilities
"""

if robodialogs.ENABLE_TK:

    def get_tk_app(robodk_icon=True, robodk_theme=True, RDK=None):
        """
        Get the QApplication instance.

        :param bool robodk_icon: Applies the RoboDK logo, defaults to True
        :param bool robodk_theme: Applies the current RoboDK theme, defaults to True
        :param robolink.Robolink RDK: Link to the running RoboDK instance for the theme, defaults to None

        :return: The QApplication instance
        :rtype: :class:`PySide2.QtWidgets.QApplication`
        """

        app = tkinter.Tk()
        app.withdraw()  # Use app.deiconify() to show the app, if needed

        # Center the app in the screen
        app.update_idletasks()
        xp = (app.winfo_screenwidth() // 2) - (app.winfo_width() // 2)
        yp = (app.winfo_screenheight() // 2) - (app.winfo_height() // 2)
        app.geometry(f'+{xp}+{yp}')
        app.update_idletasks()

        if robodk_icon:
            from robodk import robolink
            icon_path = robolink.getPathIcon()
            from os import path
            if path.exists(icon_path):
                if sys.platform.startswith('win'):
                    import ctypes
                    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(str(app))  # Enable the taskbar icon
                app.iconbitmap(default=icon_path)

        if robodk_theme:
            pass  # TODO: Use tkk to apply styling globally

        return app

    def value_to_tk_widget(value, frame):
        """
        Convert a value to a widget. For instance, a float into a Spinbox, a bool into a Checkbutton.

        The widget is automatically created for supported types:
        - bool, int, float, str (base types)
        - list or tuple of base types
        - dropdown formatted as [int, [str, str, ...]] i.e. [1, ['Option #1', 'Option #2']] where 1 means the default selected option is Option #2.
        - dictionary of supported values, formatted as {label:value}

        :return: (widget, funcs) the widget, and a list of get functions to retrieve the value of the widget
        """
        widget = None
        func = []
        value_type = type(value)

        if value_type is float:
            tkvar = tkinter.DoubleVar(value=value)
            func = [tkvar.get]
            import decimal
            decimals = min(4, max(2, abs(decimal.Decimal(str(value)).as_tuple().exponent)))  # Default to 2, up to 4
            widget = tkinter.Spinbox(frame, from_=-9999999, to=9999999, textvariable=tkvar, format=f"%.{decimals}f")

        elif value_type is int:
            tkvar = tkinter.IntVar(value=value)
            func = [tkvar.get]
            widget = tkinter.Spinbox(frame, from_=-9999999, to=9999999, textvariable=tkvar)

        elif value_type is str:
            tkvar = tkinter.StringVar(value=value)
            func = [tkvar.get]
            widget = tkinter.Entry(frame, textvariable=tkvar)

        elif value_type is bool:
            tkvar = tkinter.BooleanVar(value=value)
            func = [tkvar.get]
            widget = tkinter.Checkbutton(frame, text="Activate", variable=tkvar)

        # List or tuple of PODs
        elif value_type in [list, tuple] and len(value) > 0 and all(isinstance(n, (float, int, str, bool)) for n in value):
            widget = tkinter.Frame(frame)  # simple sub-container
            idcol = -1
            for v in value:
                idcol += 1
                f_widget, f_func = value_to_tk_widget(v, widget)
                f_widget.grid(row=0, column=idcol, sticky=tkinter.NSEW)
                func.extend(f_func)
                widget.grid_columnconfigure(idcol, weight=1)

        # ComboBox with specified index as int [1, ['First line', 'Second line', 'Third line']]
        elif value_type is list and (len(value) == 2) and isinstance(value[0], int) and value[0] in range(len(value[1])) and all(isinstance(n, str) for n in value[1]):
            index = value[0]
            options = value[1]
            tkvar = tkinter.StringVar(value=options[index])
            widget = tkinter.OptionMenu(frame, tkvar, *options)
            func = [tkvar.get]

        # ComboBox with specified index as str ['Second line', ['First line', 'Second line', 'Third line']]
        elif value_type is list and (len(value) == 2) and isinstance(value[0], str) and value[0] in value[1] and all(isinstance(n, str) for n in value[1]):
            index = value[0].index(value[0])
            options = value[1]
            tkvar = tkinter.StringVar(value=options[index])
            widget = tkinter.OptionMenu(frame, tkvar, *options)
            func = [tkvar.get]

        # Dictionary of label:value
        elif value_type is dict:

            widget = tkinter.Frame(frame)  # simple sub-container
            for i, (key, val) in enumerate(value.items()):

                if key.endswith('$') and key.startswith('$'):
                    # Section separator
                    label = tkinter.Label(widget, text=f'[  {key[1:-1]}  ]'.upper(), anchor='w')
                    label.grid(row=i, columnspan=2, sticky=tkinter.W + tkinter.S)
                    func.extend([key])
                    continue

                label_name = tkinter.Label(widget, text=key, anchor='w')
                label_name.grid(row=i, column=0, sticky=tkinter.NSEW)
                f_widget, f_func = value_to_tk_widget(val, widget)
                f_widget.grid(row=i, column=1, sticky=tkinter.W if type(f_widget) is tkinter.Checkbutton else tkinter.NSEW)
                func.extend(f_func)

        return widget, func

class AppSettings:
    """
    Generic application settings class to save and load settings to a RoboDK station with a built-in UI.

    :param str settings_param: RoboDK parameter used to store this app settings. It should be unique if you have more than one App setting.

    Example:

        .. code-block:: python

            class Settings(AppSettings):

                def __init__(self, settings_param='My-App-Settings'):
                    super().__init__(settings_param=settings_param)

                    # List the variable names you would like to save and their default values.
                    # Variables that start with underscore (_) will not be saved.
                    self.BOOL = True
                    self.INT = 123456
                    self.FLOAT = 0.123456789
                    self.STRING = 'Text'
                    self.INT_LIST = [1, 2, 3]
                    self.FLOAT_LIST = [1.0, 2.0, 3.0]
                    self.STRING_LIST = ['First line', 'Second line', 'Third line']
                    self.MIXED_LIST = [False, 1, '2']
                    self.INT_TUPLE = (1, 2, 3)
                    self.DROPDOWN = [1, ['First line', 'Second line', 'Third line']]
                    self.DICT = {'This is a string': 'Text', 'This is a float': 0.0}

                    # Variable names when displayed on the user interface (detailed descriptions).
                    # Create this dictionary in the same order that you want to display it.
                    # If AppSettings._FIELDS_UI is not provided, all variables of this class will be used displayed with their attribute name.
                    # Fields within dollar signs (i.e. $abc$) are used as section headers.
                    from collections import OrderedDict
                    self._FIELDS_UI = OrderedDict()
                    self._FIELDS_UI['SECTION_1'] = '$This is a section$'
                    self._FIELDS_UI['BOOL'] = 'This is a bool'
                    self._FIELDS_UI['INT'] = 'This is an int'
                    self._FIELDS_UI['FLOAT'] = 'This is a float'
                    self._FIELDS_UI['STRING'] = 'This is a string'
                    self._FIELDS_UI['INT_LIST'] = 'This is an int list'
                    self._FIELDS_UI['FLOAT_LIST'] = 'This is a float list'
                    self._FIELDS_UI['STRING_LIST'] = 'This is a string list'
                    self._FIELDS_UI['MIXED_LIST'] = 'This is a mixed list'
                    self._FIELDS_UI['INT_TUPLE'] = 'This is an int tuple'
                    self._FIELDS_UI['SECTION_2'] = '$This is another section$'
                    self._FIELDS_UI['DROPDOWN'] = 'This is a dropdown'
                    self._FIELDS_UI['DICT'] = 'This is a dictionary'

                S = Settings()
                S.Load()  # Load previously saved settings from RoboDK
                S.ShowUI('Settings for my App')

                print(S.BOOL)

    """

    def __init__(self, settings_param='App-Settings'):
        self._ATTRIBS_SAVE = None  #: Optional, specific list of attributes names to save (default use all attributes that does not start with "_")
        self._FIELDS_UI = None  #: Optional, specific list of attributes description for the UI (default use attribute names)
        self._SETTINGS_PARAM = settings_param  #: Optional, settings name (any settings with the same name will override the other on save)
        self._ATTRIBS_SKIP_DEFAULT = []  #: Optional, specific list of attributes not to restore when restoring defaults (default use all attributes that does not start with "_")

    def CopyFrom(self, other):
        """
        Copy settings from another AppSettings instance.

        :param robodk.roboapps.AppSettings other: The other AppSettings instance
        """
        attr = self.getAttribs()
        for a in attr:
            if hasattr(other, a):
                setattr(self, a, getattr(other, a))

    def SetDefaults(self):
        """
        Set defaults settings.
        Attributes in 'AppSettings._ATTRIBS_SKIP_DEFAULT', if defined, are ignored.
        """
        # save in local variables
        for var in self._ATTRIBS_SKIP_DEFAULT:
            exec('%s=self.%s' % (var, var))

        defaults = type(self)()
        self.CopyFrom(defaults)

        # restore from local vars
        for var in self._ATTRIBS_SKIP_DEFAULT:
            exec('self.%s=%s' % (var, var))

    def GetDefaults(self):
        """Get the default settings."""
        base = type(self)()
        defaults = {}
        for a in self.getAttribs():
            if hasattr(base, a):
                defaults[a] = getattr(base, a)
        return defaults

    def getAttribs(self):
        """
        Get the list of all attributes (settings).
        Attributes that starts with '_' are ignored.

        :return: all attributes
        :rtype: list of str
        """
        return [a for a in dir(self) if (not callable(getattr(self, a)) and not a.startswith("_"))]

    def _getAttribsSave(self):
        """
        Get the list of savable attributes (savable settings).
        Attributes not in 'AppSettings._ATTRIBS_SAVE', if defined, are ignored.

        :return: savable attributes
        :rtype: list of str
        """
        if type(self._ATTRIBS_SAVE) is list:
            return [a for a in self._ATTRIBS_SAVE if hasattr(self, a)]
        return self.getAttribs()

    def _getFieldsUI(self):
        """
        Get dictionary fields to be displayed in the UI.
        Fields in 'AppSettings._FIELDS_UI', if defined, are used in priority.
        Otherwise, the attribute name is used.

        :return: dictionary of field label and their value
        :rtype: dict
        """
        from collections import OrderedDict
        if type(self._FIELDS_UI) is dict or type(self._FIELDS_UI) is OrderedDict:
            return self._FIELDS_UI

        attribs = None
        if type(self._FIELDS_UI) is list:
            attribs = self._FIELDS_UI
        else:
            attribs = self.getAttribs()

        fields = OrderedDict()
        for a in attribs:
            fields[a] = a.replace('_', ' ')

        return fields

    def get(self, attrib, default_value=None):
        """Get attribute value by key, otherwise it returns None"""
        if hasattr(self, attrib):
            return getattr(self, attrib)
        return default_value

    def Save(self, rdk=None, autorecover=False):
        """
        Save the class attributes as a RoboDK binary parameter in the specified station.
        If the station is not provided, it uses the active station.

        :param rdk: Station to save to, defaults to None
        :type rdk: Robolink, optional
        :param autorecover: Create a backup in the station, defaults to False
        :type autorecover: bool, optional
        """
        # Save the class attributes as a string
        # Use a dictionary and the str/eval buit-in conversion
        attribs_list = self._getAttribsSave()
        if len(attribs_list) <= 0:
            print("Saving skipped")
            return

        print("Saving data to RoboDK station...")
        dict_data = {}

        # Important! We must save this but not show it in the UI
        for key in attribs_list:
            dict_data[key] = getattr(self, key)

        # Protocol tips: https://docs.python.org/3/library/pickle.html
        import pickle
        bytes_data = pickle.dumps(dict_data, protocol=2)  # protocol=2: bynary, compatible with python 2.3 and later
        if rdk is None:
            from robodk.robolink import Robolink
            rdk = Robolink()

        param_val = self._SETTINGS_PARAM
        param_backup = param_val + "-Backup"

        if autorecover:
            rdk.setParam(param_backup, bytes_data)

        else:
            rdk.setParam(param_val, bytes_data)
            rdk.setParam(param_backup, b'')

    def Load(self, rdk=None):
        """
        Load the class attributes from a RoboDK binary parameter.
        If the station is not provided, it uses the active station.

        :param rdk: Station to load from, defaults to None
        :type rdk: Robolink, optional

        :return: True if it succeeds, else false.
        """
        # Use a dictionary and the str/eval buit-in conversion
        attribs_list = self._getAttribsSave()
        #if len(attribs_list) == 0:
        #    print("Load settings: No attributes to load")
        #    return False

        print("Loading data from RoboDK station...")
        if rdk is None:
            from robodk.robolink import Robolink
            rdk = Robolink()

        param_backup = self._SETTINGS_PARAM
        param_backup += "-Backup"

        bytes_data = rdk.getParam(param_backup, False)
        if len(bytes_data) > 0:
            from robodk.robodialogs import ShowMessageYesNoCancel
            result = ShowMessageYesNoCancel("Something went wrong with the last settings.\nRecover lost data?", "Auto recover")
            if result is None:
                return False

            elif not result:
                bytes_data = b''

            # Clear backup data
            rdk.setParam(param_backup, b'', False)

        if len(bytes_data) <= 0:
            bytes_data = rdk.getParam(self._SETTINGS_PARAM, False)

        if len(bytes_data) <= 0:
            print("Load settings: No data for " + self._SETTINGS_PARAM)
            return False

        import pickle
        saved_dict = pickle.loads(bytes_data)
        for key in saved_dict.keys():
            if key == '_FIELDS_UI':
                continue

            # if we have a list of attributes that we want, load it only if it is in the list
            if len(attribs_list) == 0 or (key not in attribs_list and key != '_FIELDS_UI'):
                print("Obsolete variable saved (will be deleted): " + key)

            else:
                value = saved_dict[key]
                setattr(self, key, value)

        return True

    def Erase(self, rdk=None):
        """Completely erase the stored settings and its backup from RoboDK."""

        print("Erasing data from RoboDK station...")
        if rdk is None:
            from robodk.robolink import Robolink
            rdk = Robolink()

        param_val = self._SETTINGS_PARAM
        param_backup = param_val + "-Backup"
        rdk.setParam(param_val, b'')
        rdk.setParam(param_backup, b'')

    def ShowUI(self, windowtitle=None, embed=False, show_default_button=True, actions=None, *args, **kwargs):
        """
        Show the Apps Settings in a GUI.

        :param str windowtitle: Window title, defaults to the Settings name
        :param bool embed: Embed the settings window in RoboDK, defaults to False
        :param bool show_default_button: Set to true to add a Default button to reset the fields, defaults to True
        :param actions: List of optional action callbacks to add as buttons, formatted as [(str, callable), ...]. e.g. [("Button #1", action_1), ("Button #2", action_2)]
        :type actions: list of tuples of str, callable

        :return: False if the user cancelled, else True.
        """
        from robodk.robodialogs import InputDialog

        if not windowtitle:
            windowtitle = self._SETTINGS_PARAM

        # Attributes to be displayed, as specified by the user.
        # This will either be field's description, or field's values
        attrib_desc = self._getFieldsUI()

        # Get the values of the attributes to display
        attrib_value = {}
        for attrib, desc in attrib_desc.items():
            if desc.endswith('$') and desc.startswith('$'):
                # Section header
                attrib_value[attrib] = desc
            elif hasattr(self, attrib):
                attrib_value[attrib] = getattr(self, attrib)
            else:
                print(f"Unable to find attribute {attrib}")

        # Get the default values of the class, if the user tries to restore them
        attrib_defaults = self.GetDefaults()

        # Put everything in the expected format for InputDialog
        desc_value = {attrib_desc[attrib]: attrib_value[attrib] for attrib in attrib_value}
        desc_default = {attrib_desc[attrib]: attrib_defaults[attrib] if attrib in attrib_defaults else attrib_value[attrib] for attrib in attrib_value}

        # Show the dialog to the user
        fields_value = InputDialog(msg='', value=desc_value, title=windowtitle, default_button=show_default_button, default_value=desc_default, embed=embed, actions=actions)
        if fields_value is None:
            # User cancelled
            return False

        # Apply the new values
        desc_value_inv = {v: k for k, v in attrib_desc.items()}
        for desc, value in fields_value.items():
            if desc.endswith('$') and desc.startswith('$'):
                # Section header
                continue
            attrib = desc_value_inv[desc]
            setattr(self, attrib, value)

        # And store them to the station
        self.Save()
        return True

def ShowExample():

    class SettingsExample(AppSettings):

        def __init__(self, settings_param='App-Settings-Example'):
            super(SettingsExample, self).__init__(settings_param=settings_param)

            # List the variable names you would like to save and their default values.
            # Variables that start with underscore (_) will not be saved.
            # Important: Try to avoid default None type! If None is used as default value, it will attempt to treat it as a float with a value of -1.
            self.BOOL = True
            self.INT = 123456
            self.FLOAT = 0.123456789
            self.STRING = 'Text'
            self.INT_LIST = [1, 2, 3]  # 3 numbers minimum!
            self.FLOAT_LIST = [1.0, 2.0, 3.0]  # 3 numbers minimum!
            self.STRING_LIST = ['First line', 'Second line', 'Third line']
            self.MIXED_LIST = [False, 1, '2']
            self.INT_TUPLE = (1, 2, 3)
            self.DROPDOWN = [1, ['First line', 'Second line', 'Third line']]
            self.DICT = {'This is a string': 'Text', 'This is a float': 0.0}

            # Variable names when displayed on the user interface (detailed descriptions).
            # Create this dictionary in the same order that you want to display it.
            # If AppSettings._FIELDS_UI is not provided, all variables of this class will be used and displayed as is (unless they start with '_').
            # Fields within dollar signs (i.e. $abc$) are used as section headers.
            from collections import OrderedDict
            self._FIELDS_UI = OrderedDict()
            self._FIELDS_UI['SECTION_1'] = '$This is a section$'
            self._FIELDS_UI['BOOL'] = 'This is a bool'
            self._FIELDS_UI['INT'] = 'This is an int'
            self._FIELDS_UI['FLOAT'] = 'This is a float'
            self._FIELDS_UI['STRING'] = 'This is a string'
            self._FIELDS_UI['INT_LIST'] = 'This is an int list'
            self._FIELDS_UI['FLOAT_LIST'] = 'This is a float list'
            self._FIELDS_UI['STRING_LIST'] = 'This is a string list'
            self._FIELDS_UI['MIXED_LIST'] = 'This is a mixed list'
            self._FIELDS_UI['INT_TUPLE'] = 'This is an int tuple'
            self._FIELDS_UI['SECTION_2'] = '$This is another section$'
            self._FIELDS_UI['DROPDOWN'] = 'This is a dropdown'
            self._FIELDS_UI['DICT'] = 'This is a dictionary'

        def ShowUI(self, *args, **kwargs):

            def showMessage():
                from robodk import robodialogs
                robodialogs.ShowMessageYesNo('Are you enjoying RoboDK?')

            def showIcons():
                icons = get_qt_robodk_icons()
                if icons:
                    icon_widget = QtWidgets.QWidget()
                    icon_layout = QtWidgets.QFormLayout(icon_widget)
                    for icon_name, icon_image in icons.items():
                        icon_label = QtWidgets.QLabel(icon_name)
                        icon_label.setPixmap(QtGui.QPixmap.fromImage(icon_image).scaledToHeight(32, QtCore.Qt.TransformationMode.SmoothTransformation))
                        icon_layout.addRow(icon_name, icon_label)
                    icon_widget.adjustSize()

                    scroll_widget = QtWidgets.QScrollArea()
                    scroll_widget.setFrameShape(QtWidgets.QFrame.NoFrame)
                    scroll_widget.setWidgetResizable(True)
                    scroll_widget.setWidget(icon_widget)
                    scroll_widget.setMinimumWidth(icon_widget.minimumWidth() + 20)

                    icon_window = QtWidgets.QDialog()
                    icon_window.setWindowTitle('RoboDK Icons')
                    icon_window.setWindowFlag(QtCore.Qt.WindowType.WindowStaysOnTopHint, True)
                    icon_window.setLayout(QtWidgets.QVBoxLayout())
                    icon_window.layout().addWidget(scroll_widget)
                    icon_window.exec_()
                else:
                    from robodk import robodialogs
                    robodialogs.ShowMessage('No icons to display! Is the plug-in enabled?')

            actions = [("Show a Yes/No Message", showMessage), ("Show RoboDK Icons", showIcons)]

            return super(SettingsExample, self).ShowUI(actions=actions, *args, **kwargs)

    S = SettingsExample()
    S.Load()  # Load previously stored settings in the station
    S.ShowUI('App Settings Example')  # Show the UI to the user. It would automatically save/discard on close
    S.INT = -123456  # Manually change a value
    S.Save()  # Manually save it
    S.Erase()  # Remove all data from the station

def runmain():

    ShowExample()

    if robodialogs.ENABLE_QT:
        robodialogs.ENABLE_QT = False
        ShowExample()

if __name__ == "__main__":
    runmain()


# -*- coding: utf-8 -*-
#
# Sage documentation build configuration file, created by
# sphinx-quickstart on Thu Aug 21 20:15:55 2008.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os
from sage.env import SAGE_DOC
sys.path.append(SAGE_DOC)
from common.conf import *

# settings for the intersphinx extension:

ref_src = os.path.join(SAGE_DOC, 'en', 'reference')
ref_out = os.path.join(SAGE_DOC, 'output', 'html', 'en', 'reference')
intersphinx_mapping[ref_out] = None

for doc in os.listdir(ref_src):
    if os.path.exists(os.path.join(ref_src, doc, 'index.rst')):
        intersphinx_mapping[os.path.join(ref_out, doc)] = None

# General information about the project.
project = u"Sage Reference Manual"
name = "reference"

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
html_title = project + " v"+release

html_short_title = u'Sage Reference v' + release

# Output file base name for HTML help builder.
htmlhelp_basename = name

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
  ('index', name + '.tex', u'Sage Reference Manual',
   u'The Sage Development Team', 'manual'),
]

latex_elements['preamble'] += r'''
% One-column index
\makeatletter
\renewenvironment{theindex}{
  \chapter*{\indexname}
  \markboth{\MakeUppercase\indexname}{\MakeUppercase\indexname}
  \setlength{\parskip}{0.1em}
  \relax
  \let\item\@idxitem
}{}
\makeatother
'''

#Ignore all .rst in the _sage subdirectory
exclude_trees = exclude_trees + ['_sage']

multidocs_is_master = True

# List of subdocs
multidocs_subdoc_list = [
    'algebras',
    'arithgroup',
    'calculus',
    'categories',
    'cmd',
    'coding',
    'coercion',
    'combinat',
    'constants',
    'cryptography',
    'databases',
    'finance',
    'finite_rings',
    'function_fields',
    'functions',
    'games',
    'geometry',
    'graphs',
    'groups',
    'hecke',
    'history_and_license',
    'homology',
    'interfaces',
    'lfunctions',
    'libs',
    'logic',
    'matrices',
    'misc',
    'modabvar',
    'modfrm',
    'modmisc',
    'modsym',
    'modules',
    'monoids',
    'notebook',
    'number_fields',
    'numerical',
    'padics',
    'parallel',
    'plane_curves',
    'plot3d',
    'plotting',
    'polynomial_rings',
    'power_series',
    'probability',
    'quadratic_forms',
    'quat_algebras',
    'rings',
    'rings_numerical',
    'rings_standard',
    'sat',
    'schemes',
    'semirings',
    'stats',
    'structure',
    'tensor'
    ]

# List of directories, relative to source directory, that shouldn't be
# searched for source files.
exclude_trees += multidocs_subdoc_list + [
    'sage', 'sagenb', 'options'
    ]


#Part 2
#link to github repo: https://github.com/akashjorss/Greenhouse_emissions_viz

import pandas as pd
import streamlit as st
import altair as alt
data = pd.read_csv("https://raw.githubusercontent.com/akashjorss/Greenhouse_emissions_viz/master/green_house.csv")

#A slider filter for year
select_year = alt.selection_single(
	name='select', fields=['Year'], init={'Year': 2018}, #here use min(Year)
	bind=alt.binding_range(min=1990, max=2018, step=1) #use here min and max
)

# A dropdown filter: filters for x axis and y axis
emission_type = data['Pollutant'].unique()
emission_dropdown = alt.binding_select(options=emission_type)
emission_select = alt.selection_single(
	fields=['Pollutant'], bind=emission_dropdown, name="Emission type", init={'Pollutant': 'Carbon dioxide'}
)

#data = data[data.Country.isin(countries[:10])]
data = data[data.VAR == 'TOTAL']
data = data[data.Country != 'OECD - Total']
data = data[data.Country != 'OECD - Europe']
data = data[data.Country != 'European Union (28 countries)']
#st.write(data.head(10))

#Make a bar chart with log scale, showing different emissions
bar_chart = alt.Chart(data[data.Pollutant=='Greenhouse gases']).mark_bar(
	opacity=0.5).transform_filter( #[data.Country.isin(countries)]
		'datum.Country != null'
	).encode(
	alt.X('Country:N',
			title='Country'),
	alt.Y('Value:Q',
			scale=alt.Scale(type='log', domain=[1, 10000000]),
			axis=alt.Axis(tickCount=5, grid=False),
			title='Emission Value (in Tonnes of CO2 equivalent)'),
	alt.Tooltip('Country:N')
).properties(width=600, height=500,
		title="Greenhouse gases emissions by Top 10 countries"
).add_selection(select_year).transform_filter(select_year
).transform_window(
    rank='rank(Value)',
    sort=[alt.SortField('Value', order='descending')]
).transform_filter(
    (alt.datum.rank < 11)
)

st.altair_chart(bar_chart)

"""
We use bar-chart for plotting emission by top countries.
Transformat window and and transform filter was chosen to
to select these 10 countries automatically and they changed over time.
The slider filters the year. From the first sight, it looks like
there is not much difference in the emissions of top 10 countries,
and that it doesn't change over time.

This chart is misleading because

1. It is ambiguous. y axis is total emission of green house gases.
It is the sum of green house gases emitted by each country
in that year. Different gases are harmful in different quantities.
There is no normalization between gases.

2. The y axis is on the log scale. So it appears that different
countries emit almost the same amount of greenhouse gases. Thus
ignoring the fact that United States emit 10 times more than
United Kingdom. To suppress the difference in emissions:

	i. The y axis scale starts from 1 and the

	ii. bars are not sorted

	iii. Countries are not color coded

3. Also, the emissions are not normalized by per capita, which
completely ignores the size of the country.

4. The title subtley suggests that being top 10 is positive
"""

# Compare the gas emissions

area_chart = alt.Chart(data).mark_area(opacity=0.5,
	interpolate='monotone').encode(
    alt.X("Year:O"),
    alt.Y("sum(Value):Q", stack=None,
    	title='Yearly emission (in Tonnes of CO2 equivalent)'),
    alt.Color("Pollutant:N"),
    alt.Tooltip("Pollutant:N")
).transform_filter(
	alt.datum.Pollutant != 'Greenhouse gases'
).properties(height = 400, width=800,
	title="Major pollutants causing greenhouse effect")

st.altair_chart(area_chart)

"""
We use transparent area charts to visualise the emission
of different gases over time. Since altair doesn't have support
for pie chart yet, area charts are the next best thing to compare
quantities in a time series setting. At first sight, due to large quantity of CO2
being released, the viewer thinks that CO2 is the most significant
pollutant, and compared to it rest of the pollutants are insignificant.
The above chart is misleading:

1. The title introduces the bias. It would indicate that more major the pollutant is,
the more area it will have on chart

2. Plots the literal number of gas emissions, without taking
into account the effects of different gases in different
quantities. For example, Hydrofluorocarbons deplete ozone layer
and is effective in even small quantities, and CO2 can be tolerated
in much larger quantities relative to HFC. But this chart
draws the attention of the viewer to CO2, more than the other gases
which are potentially much more harmful.
"""


from typing import Tuple

import torch
import torch.nn as nn

from openspeech.modules.pointwise_conv1d import PointwiseConv1d
from openspeech.modules.quartznet_subblock import QuartzNetSubBlock

class QuartzNetBlock(nn.Module):
    r"""
    QuartzNet’s design is based on the Jasper architecture, which is a convolutional model trained with
    Connectionist Temporal Classification (CTC) loss. The main novelty in QuartzNet’s architecture is that QuartzNet
    replaced the 1D convolutions with 1D time-channel separable convolutions, an implementation of depthwise separable
    convolutions.

    Inputs: inputs, input_lengths
        inputs (torch.FloatTensor): tensor contains input sequence vector
        input_lengths (torch.LongTensor): tensor contains sequence lengths

    Returns: output, output_lengths
        (torch.FloatTensor, torch.LongTensor)

        * output (torch.FloatTensor): tensor contains output sequence vector
        * output_lengths (torch.LongTensor): tensor contains output sequence lengths
    """
    supported_activations = {
        "hardtanh": nn.Hardtanh(0, 20, inplace=True),
        "relu": nn.ReLU(inplace=True),
        "elu": nn.ELU(inplace=True),
        "leaky_relu": nn.LeakyReLU(inplace=True),
        "gelu": nn.GELU(),
    }

    def __init__(
        self,
        num_sub_blocks: int,
        in_channels: int,
        out_channels: int,
        kernel_size: int,
        bias: bool = True,
    ) -> None:
        super(QuartzNetBlock, self).__init__()
        padding = self._get_same_padding(kernel_size, stride=1, dilation=1)
        self.layers = nn.ModuleList(
            [
                QuartzNetSubBlock(
                    in_channels=in_channels if i == 0 else out_channels,
                    out_channels=out_channels,
                    kernel_size=kernel_size,
                    padding=padding,
                    bias=bias,
                )
                for i in range(num_sub_blocks)
            ]
        )
        self.conv1x1 = PointwiseConv1d(in_channels, out_channels)
        self.batch_norm = nn.BatchNorm1d(out_channels, eps=1e-3, momentum=0.1)

    def _get_same_padding(self, kernel_size: int, stride: int, dilation: int):
        if stride > 1 and dilation > 1:
            raise ValueError("Only stride OR dilation may be greater than 1")
        return (kernel_size // 2) * dilation

    def forward(self, inputs: torch.Tensor, input_lengths: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
        r"""
        Forward propagate of QuartzNet block.

        Inputs: inputs, input_lengths
            inputs (torch.FloatTensor): tensor contains input sequence vector
            input_lengths (torch.LongTensor): tensor contains sequence lengths

        Returns: output, output_lengths
            (torch.FloatTensor, torch.LongTensor)

            * output (torch.FloatTensor): tensor contains output sequence vector
            * output_lengths (torch.LongTensor): tensor contains output sequence lengths
        """
        residual = self.batch_norm(self.conv1x1(inputs))

        for layer in self.layers[:-1]:
            inputs, input_lengths = layer(inputs, input_lengths)

        outputs, output_lengths = self.layers[-1](inputs, input_lengths, residual)

        return outputs, output_lengths


# -*- coding: utf-8 -*-
"""
@author: yuan_xin
@contact: yuanxin9997@qq.com
@file: ReadData.py
@time: 2022/3/21 16:21
@description:
"""
import csv
import datetime
import os
import numpy as np
from utils import Parameter

demand_file_name = 'demand.csv'
qos_file_name = 'qos.csv'
site_bandwidth_file_name = 'site_bandwidth.csv'
config_file_name = 'config.ini'

class Customer:
    """申明客户节点类"""

    def __init__(self, name):

        self.name = name  # 客户姓名
        self.mtime = []  # 时刻列表，内部元素为时间类型（datetime类型）
        self.demand = []  # 带宽需求，内部元素为int类型

    def check_equality(self):
        """mtime和demand列表长度应相同"""
        assert len(self.mtime) == len(self.demand)

class Site:
    """申明边缘节点类"""

    def __init__(self, name, band_width):

        self.name = name  # 节点名称
        self.band_width = band_width  # 节点带宽大小

def read_data():
    """
    从data目录读取数据，并转换为内部可读取数据
    :return: cus_list: 客户类对象列表
    :return: sit_list: 边缘节点类对象列表
    :return: qos_dict: 边缘节点和客户之间的时延字典，键(site_name, customer_name)，值qos_value
    :return qos_const: 客户节点和边缘节点之间的网络质量
    """
    cus_list = []  # 客户类对象列表
    sit_list = []  # 边缘节点类对象列表
    qos_dict = {}  # 边缘节点和客户之间的时延字典，键(site_name, customer_name)，值qos_value

    parameter = Parameter()
    parameter.produce_path()

    # 需求数据（客户节点数据）
    with open(os.path.join(parameter.data_path, demand_file_name), mode='r', encoding='utf-8') as f:
        results = list(csv.reader(f))
        first_line = results[0]
        for cus in first_line[1:]:
            cus_list.append(
                Customer(cus)
            )
        for demand in results[1:]:
            # mtime = int(time.mktime(time.strptime(demand[0], "%Y-%m-%dT%H:%M")))
            mtime = datetime.datetime.strptime(demand[0], "%Y-%m-%dT%H:%M")
            for i in range(len(demand[1:])):
                cus_list[i].mtime.append(mtime)
                cus_list[i].demand.append(int(demand[i + 1]))
    for cus in cus_list:
        cus.check_equality()
    print("\n需求数据（客户节点数据）读取成功！规模：{}个客户节点！".format(len(cus_list)))
    print("每个客户包含的时刻数量：{}！".format(len(cus_list[0].mtime)))

    # 边缘节点数据
    with open(os.path.join(parameter.data_path, site_bandwidth_file_name), mode='r', encoding='utf-8') as f:
        site_info = csv.reader(f)
        site_info.__next__()  # 跳过表头
        for site in site_info:
            site_name = site[0]
            band_width = int(site[1])
            assert band_width >= 0
            sit_list.append(
                Site(site_name, band_width)
            )
    print("\n边缘节点数据读取成功！规模：{}个边缘节点！".format(len(sit_list)))

    # 网络时延数据
    qos_data = np.loadtxt(
        os.path.join(parameter.data_path, qos_file_name),
        dtype='float',
        delimiter=',',
        skiprows=1,
        usecols=(i for i in range(1, len(cus_list) + 1)),
        encoding='utf-8'
    )
    with open(os.path.join(parameter.data_path, qos_file_name), mode='r', encoding='utf-8') as f:
        qos_results = list(csv.reader(f))
        cus_name = qos_results[0][1:]
        for i in range(len(qos_results[1:])):
            site_name = qos_results[1:][i][0]
            for j in range(len(cus_name)):
                qos_dict[site_name, cus_name[j]] = int(qos_data[i][j])
    print("\n网络时延数据读取成功！")

    # 读取QoS约束上限
    with open(os.path.join(parameter.data_path, config_file_name), mode='r', encoding="utf-8") as f:
        lines = f.readlines()
        qos_const = int(lines[1].replace('qos_constraint=', ''))
    print("\nQoS约束上限数据读取成功！为{}！".format(qos_const))

    return cus_list, sit_list, qos_dict, qos_const

if __name__ == '__main__':
    print(read_data())


class Solution(object):
    def characterReplacement(self, s, k):
        """
        Classic Sliding Window
        """

        count = {}
        m = start = result = 0

        for end in range(len(s)):
            count[s[end]] = count.get(s[end], 0) + 1
            m = max(m, count[s[end]])

            # end - start + 1 is the len of the substring
            # if no of letters != m (the rep letter) > k the move window
            if end - start + 1 - m > k:
                count[s[start]] -= 1
                start += 1

            result = max(result, end - start + 1)

        return result


import re

from jinja2 import Environment

from ..schema import (
    Cardinality,
    GraphObjectShape,
    GraphSchema,
    PresentRelationship,
    PropertyType,
)
from .schema_printer import SchemaPrinter

NODE_TYPE_DEF_TEMPLATE = """
{% set node_type = ensure_camel_case(shape.object_type.type) %}
type {{ node_type }} @exclude(operations: [CREATE, DELETE, UPDATE]) @pageOptions{limit: {default: 10}} {% if node_type != shape.object_type.type %} @node(labels: ["{{ shape.object_type.type }}"]) {% endif %} {
    # Node Properties
{% for property in shape.properties.properties.values() %}
    {{ property.name }}: {{ field_mappings[property.type] }}
{% endfor %}
    # Inbound Relationships
{% for rel in inbound_relationships %}
    {% if rel.to_side_cardinality == Cardinality.MANY %}
    {{ in_relationship_to_camel(rel.relationship_type, rel.from_object_type) }}: [{{ ensure_camel_case(rel.from_object_type.type) }}!]!
        @relationship(type: "{{ rel.relationship_type }}", direction: IN, properties: "{{ unique_rel_type_name(rel) }}")
    {% else %}
    {{ in_relationship_to_camel(rel.relationship_type, rel.from_object_type) }}: {{ ensure_camel_case(rel.from_object_type.type) }}
        @relationship(type: "{{ rel.relationship_type }}", direction: IN, properties: "{{ unique_rel_type_name(rel) }}")
    {% endif %}
{% endfor %}
    # Outbound Relationships
{% for rel in outbound_relationships %}
    {% if rel.from_side_cardinality == Cardinality.MANY %}
    {{ out_relationship_to_camel(rel.relationship_type, rel.to_object_type) }}: [{{ensure_camel_case( rel.to_object_type.type) }}!]!
        @relationship(type: "{{ rel.relationship_type }}", direction: OUT, properties: "{{ unique_rel_type_name(rel) }}")
    {% else %}
    {{ out_relationship_to_camel(rel.relationship_type, rel.to_object_type) }}: {{ensure_camel_case( rel.to_object_type.type) }}
        @relationship(type: "{{ rel.relationship_type }}", direction: OUT, properties: "{{ unique_rel_type_name(rel) }}")
    {% endif %}
{% endfor %}
}
"""

RELATIONSHIP_DEF_TEMPLATE = """
interface {{ unique_rel_type_name_from_shape(rel) }} @relationshipProperties {
{% for property in rel.properties.properties.values() %}
    {{ property.name }}: {{ field_mappings[property.type] }}
{% endfor %}
}
"""

SNAKE_CASE_REGEX = re.compile(r"^[a-z0-9]+(_[a-z0-9]+)*$")

PROPERTY_TYPE_TO_GRAPQHL_TYPES = {
    PropertyType.STRING: "String",
    PropertyType.DATETIME: "LocalDateTime",
    PropertyType.INTEGER: "BigInt",
    PropertyType.BOOLEAN: "Boolean",
    PropertyType.FLOAT: "Float",
}

def unique_rel_type_name_from_shape(rel: GraphObjectShape):
    rel_type = rel.object_type.type
    return "".join(p.title() for p in rel_type.lower().split("_"))

def unique_rel_type_name(rel: PresentRelationship):
    rel_type = ensure_camel_case(rel.relationship_type.type)
    return "".join(p.title() for p in rel_type.lower().split("_"))

def ensure_camel_case(possible_snake_case):
    if SNAKE_CASE_REGEX.match(possible_snake_case):
        splits = possible_snake_case.split("_")
        return "".join(t.title() for t in splits)
    return possible_snake_case

def in_relationship_to_camel(relationship, other_node):
    splits = str(relationship).lower().split("_")
    other_node = ensure_camel_case(str(other_node))
    return other_node[0].lower() + other_node[1:] + "".join((t.title() for t in splits))

def out_relationship_to_camel(relationship, other_node):
    splits = str(relationship).lower().split("_")
    other_node = ensure_camel_case(str(other_node))
    return splits[0] + "".join((t.title() for t in splits[1:])) + other_node

class GraphQLSchemaPrinter(SchemaPrinter, alias="graphql"):
    def __init__(self) -> None:
        environment = Environment()
        environment.globals.update(
            {
                item.__name__: item
                for item in (
                    Cardinality,
                    in_relationship_to_camel,
                    out_relationship_to_camel,
                    ensure_camel_case,
                    unique_rel_type_name,
                    unique_rel_type_name_from_shape,
                )
            }
        )

        self.node_template = environment.from_string(NODE_TYPE_DEF_TEMPLATE)
        self.rel_template = environment.from_string(RELATIONSHIP_DEF_TEMPLATE)

    def render_node_schema(self, schema: GraphSchema) -> str:
        representation = ""
        for node_shape in sorted(
            schema.known_node_types(), key=lambda k: k.object_type.type
        ):
            all_inbound_rels = [
                r
                for r in schema.relationships
                if r.to_object_type == node_shape.object_type
            ]
            all_outbound_rels = [
                r
                for r in schema.relationships
                if r.from_object_type == node_shape.object_type
            ]
            representation += self.node_template.render(
                shape=node_shape,
                field_mappings=PROPERTY_TYPE_TO_GRAPQHL_TYPES,
                inbound_relationships=all_inbound_rels,
                outbound_relationships=all_outbound_rels,
            )
        return representation

    def render_relationship_schema(self, schema: GraphSchema) -> str:
        return "".join(
            self.rel_template.render(
                rel=rel, field_mappings=PROPERTY_TYPE_TO_GRAPQHL_TYPES
            )
            for rel in schema.known_relationship_types()
        )

    def print_schema_to_string(self, schema: GraphSchema) -> str:
        representation = self.render_node_schema(schema)
        representation += self.render_relationship_schema(schema)
        return representation + "\n"


import folium

from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.utils.timezone import localtime

from .models import Pokemon, PokemonEntity

MOSCOW_CENTER = [55.751244, 37.618423]
DEFAULT_IMAGE_URL = (
    'https://vignette.wikia.nocookie.net/pokemon/images/6/6e/%21.png/revision'
    '/latest/fixed-aspect-ratio-down/width/240/height/240?cb=20130525215832'
    '&fill=transparent'
)

def add_pokemon(folium_map, lat, lon, image_url=DEFAULT_IMAGE_URL):
    icon = folium.features.CustomIcon(
        image_url,
        icon_size=(50, 50),
    )
    folium.Marker(
        [lat, lon],
        # Warning! `tooltip` attribute is disabled intentionally
        # to fix strange folium cyrillic encoding bug
        icon=icon,
    ).add_to(folium_map)

def get_pokemon_notes(request, pokemon_objects) -> dict:
    pokemon_img_url = request.build_absolute_uri('/media/' + str(pokemon_objects.image))

    pokemon = {
        'pokemon_id': pokemon_objects.id,
        'title_ru': pokemon_objects.title,
        'title_en': pokemon_objects.title_en,
        'title_jp': pokemon_objects.title_jp,
        'description': pokemon_objects.description,
        'img_url': pokemon_img_url,
    }

    return pokemon

def show_all_pokemons(request):
    pokemons = Pokemon.objects.all()
    pokemons_on_page = []
    folium_map = folium.Map(location=MOSCOW_CENTER, zoom_start=12)
    now_at = localtime().now()
    pokemon_entities = PokemonEntity.objects.filter(
        appeared_at__date__lt=now_at,
        disappeared_at__date__gt=now_at,
    ).values('lat', 'long')

    for pokemon in pokemons:
        pokemon_notes = get_pokemon_notes(request, pokemon)
        pokemons_on_page.append(pokemon_notes)

        for pokemon_entity in pokemon_entities.filter(pokemon=pokemon):
            add_pokemon(
                folium_map,
                pokemon_entity['lat'],
                pokemon_entity['long'],
                pokemon_notes['img_url'],
            )

    return render(request, 'mainpage.html', context={
        'map': folium_map._repr_html_(),
        'pokemons': pokemons_on_page,
    })

def show_pokemon(request, pokemon_id):
    pokemon = get_object_or_404(Pokemon, id=pokemon_id)
    pokemon_notes = get_pokemon_notes(request, pokemon)
    now_at = localtime().now()
    pokemon_entities = PokemonEntity.objects.filter(
        pokemon=pokemon,
        appeared_at__date__lt=now_at,
        disappeared_at__date__gt=now_at,
    ).values('lat', 'long')
    folium_map = folium.Map(location=MOSCOW_CENTER, zoom_start=12)

    for pokemon_entity in pokemon_entities:
        add_pokemon(
            folium_map,
            pokemon_entity['lat'],
            pokemon_entity['long'],
            pokemon_notes['img_url'],
        )
    if pokemon.next_evolution:
        pokemon_notes['next_evolution'] = get_pokemon_notes(request, pokemon.next_evolution)

    try:
        parent_pokemon = pokemon.previous_evolutions.get()
        pokemon_notes['previous_evolution'] = get_pokemon_notes(request, parent_pokemon)
    except Pokemon.DoesNotExist:
        pokemon_notes['previous_evolution'] = None

    return render(request, 'pokemon.html', context={
        'map': folium_map._repr_html_(), 'pokemon': pokemon_notes
    })


# 함수 내부에 불필요한 print문이 있는 경우 오답으로 처리가 됩니다.
def is_position_safe(N, M, position):
    x, y = position
    move = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    nx, ny = x + move[M][0], y + move[M][1]
    if 0 <= nx < N and 0 <= ny < N :
        return True
    else :
        return False
    # 여기에 코드를 작성하여 함수를 완성합니다.

# 아래의 코드를 수정하거나 새롭게 추가하지 않습니다.
########## 코드 변경 금지 ############
if __name__ == '__main__':
    print(is_position_safe(3, 1, (0, 0)))  # True
    print(is_position_safe(3, 0, (0, 0)))  # False


from gen_and_dis import make_generator, make_discriminator
from dataset import mnist_dl
from config import configs
from create import create_noise
import numpy as np
import torch
import torch.nn as nn

input_real, label = next(iter(mnist_dl))
input_real = input_real.view(configs['batch_size'], -1)

torch.manual_seed(configs['torch_manual_seed'])

mode_z = configs['mode_z']

input_z = create_noise(configs['batch_size'], configs['z_size'], mode_z)

print('input_z shape : ', input_z.shape)
print('input_real shape: ', input_real.shape)

gen_model = make_generator(
    input_size=configs['z_size'],
    num_hidden_layers=configs['gen_hidden_layers'],
    num_hidden_units=configs['gen_hidden_size'],
    num_output_units=np.prod(configs['image_size'])
)

disc_model = make_discriminator(
    input_size=np.prod(configs['image_size']),
    num_hidden_layers=configs['disc_hidden_layers'],
    num_hidden_units=configs['disc_hidden_size']
)

g_output = gen_model(input_z)
print('Output of generator shape : ', g_output.shape)

d_proba_real = disc_model(input_real)
d_proba_fake = disc_model(g_output)

print('Output of discriminator shape on real : ', d_proba_real.shape)
print('Output of discriminator shape on fake : ', d_proba_fake.shape)

loss_fn = nn.BCELoss()

g_labels_real = torch.ones_like(d_proba_real)
g_loss = loss_fn(d_proba_fake, g_labels_real)
print(f'Generator Loss : {g_loss:.4f}')

d_labels_real = torch.ones_like(d_proba_real)
d_labels_fake = torch.zeros_like(d_proba_fake)

d_loss_real = loss_fn(d_labels_real, d_proba_real)
d_loss_fake = loss_fn(d_labels_fake, d_proba_fake)

print(f'Discriminator Loss for real : {d_loss_real:.4f}, for fake : {d_loss_fake:.4f}')

from torchviz import make_dot

make_dot(g_output, params=dict(list(gen_model.named_parameters()))).render(filename="gen_model",directory="C:/Users/psvka/OneDrive/Desktop/code/GAN/Vanilla_GAN/imgs", format="png")


from neuromap import InteractiveGraph
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx

nodes = np.array(['A', 'B', 'C', 'D', 'E', 'F', 'G'])
edges = np.array([['A', 'B'], ['A', 'C'], ['B', 'D'], ['B', 'E'], ['C', 'F'], ['C', 'G']])
midpos = []
pos = np.array([[0, 0], [-2, 1], [2, 1], [-3, 2], [-1, 2], [1, 2], [3, 2]])
labels = [1, 4, 9, 16, 25, 36, 49]
sizes = [500, 500, 500, 500, 500, 500, 500]
pygments = {'A': 'red', 'C':'green'}
images = {'B': 'miku.png', 'E': 'iggraph.png'}
imsizes = {'B': 0.2, 'E': 0.1}

G = nx.DiGraph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
nx.set_node_attributes(G, dict(zip(G.nodes(), pos.astype(float))), 'pos')
nx.set_node_attributes(G, dict(zip(G.nodes(), sizes)), 'size')

IG = InteractiveGraph(G)
IG.update_nodes()
IG.update_midnodes()
IG.labels = labels
IG.sizes = {x: y for x, y in zip(nodes, sizes)}
IG.pygments = ['lightblue' if n not in pygments else pygments[n] for n in nodes]
IG.images = images
IG.imsizes = imsizes
IG.refresh()
plt.show()


import telebot

TOKEN = '5877590294:AAHP1lANVCByyY7HGXwvCEoXA3DH6YowYRg'
CHAT_ID = '-100691258066'

bot = telebot.TeleBot(TOKEN)

@bot.message_handler(commands=['start'])
def start_message(message):
    bot.send_message(message.chat.id, 'Привет! Я твой помощник на этом сайте.')

@bot.message_handler(content_types=['text'])
def send_message(message):
    bot.send_message(CHAT_ID, message.text)

bot.polling(none_stop=True)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Utilities related to Matplotlib
-------------------------------
"""
import numpy as np

##############
# Matplotlib #
##############

def mplSetPubFont(size=8, usetex=True):
    """very basic mpl set font for publication-quality figures"""
    from matplotlib import rc
    rc('font', **{'family': 'sans-serif',
                  'sans-serif': ['Helvetica'],
                  'size': size})
    rc('text', usetex=usetex)

def get_colors(nlevels, colormap=None):
    """get a given number of colors from a colormap"""
    if colormap is None:
        from matplotlib.pyplot import cm
        colormap = cm.rainbow
    return colormap(np.linspace(0, 1, nlevels))


import pygame
import sys

pygame.init()

pencere = pygame.display.set_mode((1000,700), pygame.SWSURFACE)
pygame.display.set_caption("Işık Ve Renkler")

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    pygame.display.flip()


import PIL.Image
import open3d as op
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib_scalebar.scalebar import ScaleBar
import datetime
from PIL import Image, ImageDraw, ImageFont
import time

def groundPlans(meshFileName):
    initTime = time.time()

    #input mesh
    mes = op.io.read_triangle_mesh(meshFileName)

    #boundary coordinates
    mi = mes.get_min_bound()
    ma = mes.get_max_bound()

    #midpoints of boundaries
    xav = (mi[0] + ma[0]) / 2
    yav = (mi[1] + ma[1]) / 2
    zav = (mi[2] + ma[2]) / 2

    #crop volume coordinates
    P5 = [mi[0], mi[1], mi[2]]
    P6 = [ma[0], mi[1], zav]
    P7 = [mi[0], ma[1], mi[2]]
    P8 = [ma[0], ma[1], zav]

    #clipping plane processing
    pol = op.visualization.SelectionPolygonVolume()
    bp = np.array([P5, P6, P8, P7])
    bp = bp.astype("float64")
    pol.orthogonal_axis = "XY"
    pol.axis_max = np.max(bp[:, 2])
    pol.axis_min = np.min(bp[:, 2])
    bp[:, 2] = 0
    pol.bounding_polygon = op.utility.Vector3dVector(bp)

    #remesh after clipping
    mes = pol.crop_triangle_mesh(mes)
    l = np.asarray(mes.vertices)
    mes.compute_vertex_normals()

    #visualiser
    vis = op.visualization.Visualizer()
    vis.create_window()
    vis.add_geometry(mes)
    ctr = vis.get_view_control()
    ctr.change_field_of_view(step=-90.0)
    ctr.set_zoom(0.35)
    imaget = "GroundPlan.png"
    for i in range(100):
        vis.poll_events()
        vis.update_renderer()
        vis.capture_screen_image(imaget)
    vis.destroy_window()

    plt.figure()
    image = plt.imread(imaget)
    plt.imshow(image)
    plt.tick_params(axis="x", which="both", bottom=False, top=False, labelbottom=False)
    plt.tick_params(axis="y", which="both", left=False, right=False, labelleft=False)

    xmin, xmax = plt.xlim()
    ymin, ymax = plt.ylim()

    plt.title("Ground Plan")
    d = datetime.date.today().strftime("%Y-%m-%d")
    plt.text(xmin - 200, ymax - 90, d, size="smaller")

    plt.xlim([xmin - 200, xmax + 200])
    plt.ylim([ymin + 150, ymax - 150])
    scalebar = ScaleBar(1 / 260, location="lower right")  # 1 pixel = 0.2 meter
    plt.gca().add_artist(scalebar)
    plt.savefig("preGroundPlan.tif", format="tif", dpi=300)

    im = Image.open(r"preGroundPlan.tif")

    width, height = im.size
    left = int(0.1 * width)
    right = int(0.92 * width)
    top = int(0.15 * height)
    bot = int(0.85 * height)
    im2 = im.crop((left, top, right, bot))
    fontsize = 30
    font = ImageFont.truetype("arial.ttf", fontsize)

    #elevation e1 line
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((300, 900, 1350, 900), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((300, 900, 312.5, 875), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((325, 900, 312.5, 875), fill=128, width=3)
    drawBot.text((310, 900), "E1", fill=(0, 0, 0), font=font)

    # elevation e2 line
    drawtop = ImageDraw.Draw(im2)
    drawtop.line((300, 150, 1350, 150), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((300, 150, 312.5, 175), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((325, 150, 312.5, 175), fill=128, width=3)
    drawBot.text((300, 120), "E3", fill=(0, 0, 0), font=font)

    # elevation e3 line
    drawleft = ImageDraw.Draw(im2)
    drawleft.line((125, 200, 125, 825), fill=128, width=3)
    drawleft = ImageDraw.Draw(im2)
    drawleft.line((125, 200, 150, 212.5), fill=128, width=3)
    drawleft = ImageDraw.Draw(im2)
    drawleft.line((125, 225, 150, 212.5), fill=128, width=3)
    drawBot.text((85, 200), "E4", fill=(0, 0, 0), font=font)

    # elevation e4 line
    drawright = ImageDraw.Draw(im2)
    drawright.line((1400, 200, 1400, 825), fill=128, width=3)
    drawleft.line((1400, 200, 1375, 212.5), fill=128, width=3)
    drawleft = ImageDraw.Draw(im2)
    drawleft.line((1400, 225, 1375, 212.5), fill=128, width=3)
    drawBot.text((1410, 200), "E2", fill=(0, 0, 0), font=font)

    # s1 line
    drawBot = ImageDraw.Draw(im2)
    relbot = 275
    drawBot.line((300 - 50, 900 - relbot, 1350, 900 - relbot), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((300 - 50, 900 - relbot, 312.5 - 50, 875 - relbot), fill=128, width=3)
    drawBot = ImageDraw.Draw(im2)
    drawBot.line((325 - 50, 900 - relbot, 312.5 - 50, 875 - relbot), fill=128, width=3)
    drawBot.text((300 - 50, 900 - relbot), "S1", fill=(0, 0, 0), font=font)

    #s2 line
    drawright = ImageDraw.Draw(im2)
    relrig = 600
    drawright.line((1400 - relrig, 200, 1400 - relrig, 825), fill=128, width=3)
    drawleft.line((1400 - relrig, 200, 1375 - relrig, 212.5), fill=128, width=3)
    drawleft = ImageDraw.Draw(im2)
    drawleft.line((1400 - relrig, 225, 1375 - relrig, 212.5), fill=128, width=3)
    drawBot.text((1410 - relrig, 200), "S2", fill=(0, 0, 0), font=font)

    im2.save("liner.png")

    im2.save("GroundPlan.tif")

    endTime = time.time()
    print("The runtime for a ground plan is: ", endTime - initTime, "sec")


import numpy as np
import matplotlib.pyplot as plt
import math
import scipy.special as S

data1='/Users/LJ/gas_kinematicsdat.txt'
gas=[]
f=open(data1,'r')
f.seek(0)
for i in range(4194304):
 List=f.readline().strip().split()
 gas.append(List)

x_sun=8.3*np.cos(153./180.*np.pi)
y_sun=8.3*np.sin(153./180.*np.pi)
v_sun=210.
v_sun_x=-v_sun*np.sin(27./180.*np.pi)
v_sun_y=-v_sun*np.cos(27./180.*np.pi)
l=[]

for i in range(4194304):
 if np.sqrt((float(gas[i][0])**2+float(gas[i][1])**2))>=14.5:
  c=0
  l.append(c)
 if np.sqrt((float(gas[i][0])**2+float(gas[i][1])**2))<14.5:
  if float(gas[i][1])>(y_sun/x_sun)*float(gas[i][0]) and abs(float(gas[i][1])-(y_sun/x_sun)*float(gas[i][0]))>10**(-6):
   c=-1*math.acos((x_sun**2+y_sun**2-x_sun*float(gas[i][0])-y_sun*float(gas[i][1]))/(np.sqrt(x_sun**2+y_sun**2)*np.sqrt((float(gas[i][0])-x_sun)**2+(float(gas[i][1])-y_sun)**2)))*180/np.pi
   l.append(c)
  if float(gas[i][1])<(y_sun/x_sun)*float(gas[i][0]) and abs(float(gas[i][1])-(y_sun/x_sun)*float(gas[i][0]))>10**(-6):
   c=1*math.acos((x_sun**2+y_sun**2-x_sun*float(gas[i][0])-y_sun*float(gas[i][1]))/(np.sqrt(x_sun**2+y_sun**2)*np.sqrt((float(gas[i][0])-x_sun)**2+(float(gas[i][1])-y_sun)**2)))*180/np.pi
   l.append(c)
  if abs(float(gas[i][1])-(y_sun/x_sun)*float(gas[i][0]))<=10**(-6):
   c=0
   l.append(c)

#print l

v_los=[]
omega_b=33.
tmp_r=np.zeros(4194304)
e_los_x=np.zeros(4194304)
e_los_y=np.zeros(4194304)
velocity_x=np.zeros(4194304)
velocity_y=np.zeros(4194304)
v_los_tmp=np.zeros(4194304)
v_los_sun=np.zeros(4194304)

for k in range(4194304):
 if np.sqrt((float(gas[k][0])**2+float(gas[k][1])**2))<14.5:
  tmp_r[k]=np.sqrt((float(gas[k][0])-x_sun)**2+(float(gas[k][1])-y_sun)**2)
  e_los_x[k]=(float(gas[k][0])-x_sun)/tmp_r[k]
  e_los_y[k]=(float(gas[k][1])-y_sun)/tmp_r[k]
  v_los_tmp[k]=float(gas[k][3])*e_los_x[k]+float(gas[k][4])*e_los_y[k]
  v_los_sun[k]=v_sun_x*e_los_x[k]+v_sun_y*e_los_y[k]
  c=v_los_tmp[k]-v_los_sun[k]
  v_los.append(c)
 if np.sqrt((float(gas[k][0])**2+float(gas[k][1])**2))>=14.5:
  c=0
  v_los.append(c)
#fig=plt.figure()
#plt.plot(l,v_los,'.')
#plt.xlim(-90.0,90.0)
#plt.show()

l=np.asarray(l)
v_los=np.asarray(v_los)

R1=[]
R2=[]
v1=[]
v2=[]

for j in range(900):
 index1=np.where((l>=-90.0+0.1*j) & (l<-90.0+0.1*(j+1)))
 index2=np.where(v_los==min(v_los[index1]))
 R=abs(8.3*np.sin(l[index2]/180.*np.pi))
 R1.append(R)
 #v=v_sun*np.sin(l[index2]*np.pi/180)-v_los[index2]
 v=v_los[index2]+v_sun*np.sin(l[index2]*np.pi/180)
 v1.append(-v)

#fig=plt.figure()
#plt.plot(R1,v1,'.')
#plt.show()

R2=[]
v2=[]
for n in range(900):
 index3=np.where((l>=0.0+0.1*n) & (l<0.0+0.1*(n+1)))
 index4=np.where(v_los==max(v_los[index3]))
 R=abs(8.3*np.sin(l[index4]/180.*np.pi))
 R2.append(R)
 v=v_los[index4]+v_sun*np.sin(l[index4]*np.pi/180)
 v2.append(v)

#fig=plt.figure()
#plt.plot(R2,v2,'.r')
#plt.show()

data2='/Users/LJ/potential_M80fit_15kpc.txt'
star=[]
f=open(data2,'r')
f.seek(0)
for k in range(2250000):
 List=f.readline().strip().split()
 star.append(List)

x_star=[]
y_star=[]
ax2=[]
ay2=[]
R_star=[]
v_star=[]

for h in range(2250000):
 x_star.append(star[h][0])
 y_star.append(star[h][1])
 ax2.append(star[h][6])
 ay2.append(star[h][7])

for h in range(2250000):
 R_star1=np.sqrt(float(x_star[h])*float(x_star[h])+float(y_star[h])*float(y_star[h]))
 R_star.append(R_star1)
 a1=np.sqrt(float(ax2[h])*float(ax2[h])+float(ay2[h])*float(ay2[h]))
 v11=np.sqrt(a1*R_star1)
 v_star.append(v11)

vt=[]

Mbh=3.5*10**7
eps=0.01
gconst=4.302*10**(-6)

par1=2.7856e-11
par2=1.34497e-12
coeff1=-3.65269e8
coeff2=-2.20803e8
const1=S.gamma(0.4)*(1.0-S.gammainc(0.4,(par1)*0.0))*coeff1
const2=S.gamma(0.4)*(1.0-S.gammainc(0.4,(par2)*0.0))*coeff2
mass2light=2.

for g in range(2250000):
 vbh2=gconst*Mbh*float(R_star[g])**2/((eps**2+float(R_star[g])**2)**1.5)
 tmp1_x=mass2light*0.5*(S.gamma(0.4)*(1.0-S.gammainc(0.4,(par1)*((float(R_star[g])*1000.)**5)))*(coeff1)-const1)
 tmp2_x=mass2light*0.5*(S.gamma(0.4)*(1.0-S.gammainc(0.4,(par2)*((float(R_star[g])*1000.)**5)))*(coeff2)-const2)
 vnb2=4.302*(tmp1_x+tmp2_x)/(float(R_star[g])*1.0e6)

 barmass=1.0*10**10
 a=9.0
 vlongbar2=gconst*barmass*float(R_star[g])/((float(R_star[g])+a)**2)
 vt1=np.sqrt((float(v_star[g]))**2+vbh2+vnb2+vlongbar2)
 vt.append(vt1)

R_plot=[]
vt_plot=[]
for q in range(2250000):
 if float(x_star[q])==0.1000595E-01:
  R_plot.append(float(R_star[q]))
  vt_plot.append(float(vt[q]))

fig=plt.figure()
plt.plot(R_plot,vt_plot,label="$true-RC$")
plt.plot(R1,v1,'.r',label="$gas--90-RC$")
plt.plot(R2,v2,'.g',label="$gas-90-RC$")
plt.xlabel("Radius(kpc)")
plt.ylabel("Velocity(km/s)")
plt.title("Rotation Curves")
plt.xlim(0.0,9.0)
plt.legend()
plt.show()


from django.conf.urls import patterns, include, url
from views import *

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'armadopc.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^$', inicio),
    url(r'^inicio1/$', inicio1),
    url(r'^logeo/$', logeo),
    url(r'^inicio2/$',inicio2),

)


import fnmatch
import os
import platform
import subprocess
import sys

from distutils import cmd
from distutils import log
from setuptools import find_packages
from setuptools import setup
from setuptools.command import install
from setuptools.command import test

PLATFORM_SUFFIXES = {
    'Linux': 'linux',
    'Windows': 'win64',
    'Darwin': 'macos',
}
DEFAULT_HEADERS_DIR = '~/.mujoco/mujoco200_{}/include'.format(
    PLATFORM_SUFFIXES[platform.system()])

# Relative paths to the binding generator script and the output directory.
AUTOWRAP_PATH = 'dm_control/autowrap/autowrap.py'
MJBINDINGS_DIR = 'dm_control/mujoco/wrapper/mjbindings'

# We specify the header filenames explicitly rather than listing the contents
# of the `HEADERS_DIR` at runtime, since it will probably contain other stuff
# (e.g. `glfw.h`).
HEADER_FILENAMES = [
    'mjdata.h',
    'mjmodel.h',
    'mjrender.h',
    'mjui.h',
    'mjvisualize.h',
    'mjxmacro.h',
    'mujoco.h',
]

def _initialize_mjbindings_options(cmd_instance):
  """Set default values for options relating to `build_mjbindings`."""
  # A default value must be assigned to each user option here.
  cmd_instance.inplace = 0
  cmd_instance.headers_dir = DEFAULT_HEADERS_DIR

def _finalize_mjbindings_options(cmd_instance):
  """Post-process options relating to `build_mjbindings`."""
  headers_dir = os.path.expanduser(cmd_instance.headers_dir)
  header_paths = []
  for filename in HEADER_FILENAMES:
    full_path = os.path.join(headers_dir, filename)
    if not os.path.exists(full_path):
      raise IOError('Header file {!r} does not exist.'.format(full_path))
    header_paths.append(full_path)
  cmd_instance.header_paths = ' '.join(header_paths)

class BuildMJBindingsCommand(cmd.Command):
  """Runs `autowrap.py` to generate the low-level ctypes bindings for MuJoCo."""
  description = __doc__
  user_options = [
      # The format is (long option, short option, description).
      ('headers-dir=', None,
       'Path to directory containing MuJoCo headers.'),
      ('inplace=', None,
       'Place generated files in source directory rather than `build-lib`.'),
  ]
  boolean_options = ['inplace']

  def initialize_options(self):
    _initialize_mjbindings_options(self)

  def finalize_options(self):
    _finalize_mjbindings_options(self)

  def run(self):
    cwd = os.path.realpath(os.curdir)
    if self.inplace:
      dist_root = cwd
    else:
      build_cmd = self.get_finalized_command('build')
      dist_root = os.path.realpath(build_cmd.build_lib)
    output_dir = os.path.join(dist_root, MJBINDINGS_DIR)
    command = [
        sys.executable or 'python',
        AUTOWRAP_PATH,
        '--header_paths={}'.format(self.header_paths),
        '--output_dir={}'.format(output_dir)
    ]
    self.announce('Running command: {}'.format(command), level=log.DEBUG)
    try:
      # Prepend the current directory to $PYTHONPATH so that internal imports
      # in `autowrap` can succeed before we've installed anything.
      old_environ = os.environ.copy()
      new_pythonpath = [cwd]
      if 'PYTHONPATH' in old_environ:
        new_pythonpath.append(old_environ['PYTHONPATH'])
      os.environ['PYTHONPATH'] = ':'.join(new_pythonpath)
      subprocess.check_call(command)
    finally:
      os.environ = old_environ

class InstallCommand(install.install):
  """Runs 'build_mjbindings' before installation."""

  user_options = (
      install.install.user_options + BuildMJBindingsCommand.user_options)
  boolean_options = (
      install.install.boolean_options + BuildMJBindingsCommand.boolean_options)

  def initialize_options(self):
    install.install.initialize_options(self)
    _initialize_mjbindings_options(self)

  def finalize_options(self):
    install.install.finalize_options(self)
    _finalize_mjbindings_options(self)

  def run(self):
    self.reinitialize_command('build_mjbindings',
                              inplace=self.inplace,
                              headers_dir=self.headers_dir)
    self.run_command('build_mjbindings')
    install.install.run(self)

class TestCommand(test.test):
  """Prepends path to generated sources before running unit tests."""

  def run(self):
    # Generate ctypes bindings in-place so that they can be imported in tests.
    self.reinitialize_command('build_mjbindings', inplace=1)
    self.run_command('build_mjbindings')
    test.test.run(self)

def find_data_files(package_dir, patterns):
  """Recursively finds files whose names match the given shell patterns."""
  paths = set()
  for directory, _, filenames in os.walk(package_dir):
    for pattern in patterns:
      for filename in fnmatch.filter(filenames, pattern):
        # NB: paths must be relative to the package directory.
        relative_dirpath = os.path.relpath(directory, package_dir)
        paths.add(os.path.join(relative_dirpath, filename))
  return list(paths)

setup(
    name='dm_control',
    version='0.0.301472480',
    description='Continuous control environments and MuJoCo Python bindings.',
    author='DeepMind',
    license='Apache License, Version 2.0',
    keywords='machine learning control physics MuJoCo AI',
    install_requires=[
        'absl-py>=0.7.0',
        'enum34; python_version < "3.4"',
        'dm-env',
        'dm-tree != 0.1.2',
        'future',
        'futures; python_version == "2.7"',
        'glfw',
        'lxml',
        'numpy',
        'pyopengl >= 3.1.4',
        'pyparsing',
        'setuptools',
        'scipy',
        'six',
    ],
    extras_require={
        'locomotion_mazes': ['labmaze'],
    },
    tests_require=[
        'mock',
        'nose',
        'pillow',
    ],
    test_suite='nose.collector',
    packages=find_packages(),
    package_data={
        'dm_control': find_data_files(package_dir='dm_control',
                                      patterns=['*.amc', '*.msh', '*.png',
                                                '*.skn', '*.stl', '*.xml']),
    },
    cmdclass={
        'build_mjbindings': BuildMJBindingsCommand,
        'install': InstallCommand,
        'test': TestCommand,
    },
    entry_points={},
)


def cercado(cabecas, pes):
    c = (pes - 2 * cabecas) / 2
    p = cabecas - c
    return p,c

total_cabecas = int(input("Digite o total de Cabeças: "))
total_pes = int(input("Digite o total de pés: "))

patos, coelhos = cercado(total_cabecas, total_pes)

print(f"O total de coelhos é {coelhos}, o total de patos é {patos}")


exp = str(input('Digite sua expressão: '))
pilha = []
for i in exp:
    if i =='(':
        pilha.append(i)
    elif i ==')':
        if len(pilha)>0:
            pilha.pop()
        else:
            pilha.append(i)
if len(pilha)==0:
    print('Expressão válida')
else:
    print('Expressão inválida')


import os
import environ

ROOT_DIR = environ.Path()
HOME_DIR = os.environ['HOME']
TEMPLATES_ENVIRONMENT = os.path.join(ROOT_DIR, '')
CONFIG_FILES_DIRECTORY = ROOT_DIR.path('conf')
HOSTS_FILE = 'hosts.yaml'
SSH_CONFIG = '~/.ssh/config'
LOGLEVEL = 'DEBUG'
LIST_MERGE_KEY = 'merged_list'
HUAWEI_REGEX_RUNNING_SEARCH = '(?<=#\r\n).*return'
CISCO_REGEX_RUNNING_SEARCH = 'hostname.*end'
JUNIPER_REGEX_RUNNING_SEARCH = '(?<=;\r\n)system.*}'
EXPECT_LIST_ERRORS = ['Error.+',
        '% Invalid.+',
        '.+^.+',
        '% Incomplete.+',
        '% Unknown.+',
        'bad command.+',
        'failure.+',
        ]
CFG_FILR_NAME = 'gitlab.cfg'
HUAWEI_REMOTE_FILE_PATCH = CFG_FILR_NAME
CISCO_REMOTE_FILE_PATCH = 'disk0:/' + CFG_FILR_NAME
JUNIPER_REMOTE_FILE_PATCH = CFG_FILR_NAME

HUAWEI_GET_RUN =['screen-length 0 temporary',
                'display current-configuration',
                    ]
CISCO_GET_RUN = ['terminal length 0',
                'sh run',
                    ]
JUNIPER_GET_RUN = ['set cli screen-length 0',
                'show configuration',
                    ]

HUAWEI_GET_DIFF = ['screen-length 0 temporary',
                'sys',
                'load configuration file {} replace'.format(HUAWEI_REMOTE_FILE_PATCH),
                'display configuration candidate merge',
                    ]
CISCO_GET_DIFF = ['terminal length 0',
                'conf t',
                'load {}'.format(CISCO_REMOTE_FILE_PATCH),
                'show configuration',
                    ]
JUNIPER_GET_DIFF = ['set cli screen-length 0',
                'config',
                'load override {}'.format(JUNIPER_REMOTE_FILE_PATCH),
                'commit',
                'exit',
                    ]

HUAWEI_PUSH_CONFIG = ['screen-length 0 temporary',
                'sys',
                'load configuration file {} replace'.format(HUAWEI_REMOTE_FILE_PATCH),
                'display configuration replace failed',
                'commit',
                'run save',
                'y',
                    ]
CISCO_PUSH_CONFIG = ['terminal length 0',
                'conf t',
                'load {}'.format(CISCO_REMOTE_FILE_PATCH),
                'commit replace comment make by pnba',
                'y',
                    ]
JUNIPER_PUSH_CONFIG = ['set cli screen-length 0',
                'config',
                'load override {}'.format(JUNIPER_REMOTE_FILE_PATCH),
                'commit',
                'exit',
                    ]