from os import getcwd

from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QDialog, QTableWidget, QTableWidgetItem, QDialogButtonBox, QMessageBox, QSpacerItem, \
    QFileDialog

from file import saveReportAsPdf
from reporter import Report

class Window:
    def showReport(self, report: Report, name):
        dialog = Dialog(700, 500, "Report")

        header = QtWidgets.QLabel()
        header.setFont(getFont(12))
        header.setText(report.decision)
        header.setWordWrap(True)

        model = QtWidgets.QLabel()
        model.setFont(getFont(10))
        model.setText("Model probability: {:.1%}".format(report.probability))
        model.setWordWrap(True)

        desc = QtWidgets.QLabel()
        desc.setFont(getFont(10))
        desc.setText(report.message)
        desc.setWordWrap(True)

        list = QtWidgets.QLabel()
        list.setFont(getFont(10))
        list.setText(createBulletList(report.significantParameters))
        list.setWordWrap(True)

        tableLabel = QtWidgets.QLabel()
        tableLabel.setFont(getFont(10))
        tableLabel.setContentsMargins(0, 20, 0, 0)
        tableLabel.setText("Table showing how each parameter affects the final result")
        tableLabel.setWordWrap(True)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
        dataToSave = {"decision": header.text(), "probability": model.text(), "message": report.message, "name": name,
                      "param": report.significantParameters, "table": report.reasoning,
                      "description": tableLabel.text()}
        buttonBox.accepted.connect(lambda: dialog.save(dataToSave))
        buttonBox.rejected.connect(dialog.reject)

        dialog.addWidget(header)
        dialog.addWidget(model)
        dialog.addWidget(desc)
        dialog.addWidget(list)
        dialog.addWidget(tableLabel)
        dialog.addWidget(createTable(report.reasoning))
        dialog.addWidget(buttonBox, alignment=QtCore.Qt.AlignBottom)
        dialog.showDialog()

    def showWarning(self, message, description):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Warning)
        msg.setText(message)

        msg.setInformativeText(description)
        msg.setWindowTitle("Warning")

        spacer = QSpacerItem(350, 30)
        layout = msg.layout()
        layout.addItem(spacer, 1, 0, 1, 0)

        msg.exec_()

class Dialog(QDialog):
    def __init__(self, width, height, title):
        super().__init__()
        self.setWindowTitle(title)
        self.resize(width, height)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)

        layoutWidget = QtWidgets.QWidget(self)
        layoutWidget.setFixedWidth(width)
        layoutWidget.setFixedHeight(height)
        self.verticalLayout = QtWidgets.QVBoxLayout(layoutWidget)
        self.verticalLayout.setContentsMargins(10, 10, 10, 10)

    def addWidget(self, widget: QtWidgets, alignment=None):
        if alignment is None:
            self.verticalLayout.addWidget(widget)
        else:
            self.verticalLayout.addWidget(widget, alignment=alignment)

    def save(self, data):
        file = QFileDialog.getSaveFileName(None, 'Save file', getcwd(), "Report pdf (*.pdf)")[0]
        if file is not None and file != '':
            saveReportAsPdf(file, data)

    def showDialog(self):
        self.exec_()

def createBulletList(elements):
    bulletList = "
"
    for a in elements:
        bulletList = bulletList + "
{}
".format(a)
    bulletList = bulletList + "
"
    return bulletList

def createTable(reasoning):
    rows = 3
    columns = 13
    redBackground = QtGui.QColor(214, 92, 92)
    greenBackground = QtGui.QColor(92, 214, 92)

    tableWidget = QTableWidget()
    tableWidget.setRowCount(rows)
    tableWidget.setFixedHeight(200)
    tableWidget.setColumnCount(columns)
    for i in range(columns):
        tableWidget.setColumnWidth(i, 80)

    columnNames = []
    index = 0
    for n in reasoning:
        columnNames.append(n.name)
        tableWidget.setItem(0, index, QTableWidgetItem("{:.3}".format(n.score)))
        tableWidget.setItem(1, index, QTableWidgetItem("{:.2%}".format(n.rate)))
        tableWidget.setItem(2, index, QTableWidgetItem("{}".format(n.patient_value)))
        if n.score > 0:
            for i in range(rows):
                tableWidget.item(i, index).setBackground(redBackground)
        elif n.score < 0:
            for i in range(rows):
                tableWidget.item(i, index).setBackground(greenBackground)

        index = index + 1

    tableWidget.setHorizontalHeaderLabels(columnNames)
    tableWidget.setVerticalHeaderLabels(["score", "rate", "patient"])
    return tableWidget

def getFont(size):
    font = QtGui.QFont()
    font.setPointSize(size)
    return font


lista = []
while True:
    lista.append(int(input('Digite um valor: ')))
    choice = str(input('Deseja continuar S/N: ')).strip().upper()[0]
    if choice in 'N':
        break
print(f'O total de números digitado foi de {len(lista)}.')
print(f'Os valores inverso foram {sorted(lista , reverse=True)}')
if 5 not in lista:
    print('O valor 5 não esta na lista.')
else:
    print('O valor 5 esta na lista.')


# -*- coding: utf-8 -*-
from .settings import INSTALLED_APPS
from .settings import MIDDLEWARE_CLASSES

DEBUG = True
DEPLOYMENT_MODE = 'local'
SITE_DOMAIN = '127.0.0.1'
# Port used when running locally
LOCAL_PORT = 8001

SITE_ROOT_URI = 'http://{0}:{1}/'.format(SITE_DOMAIN, LOCAL_PORT)
# For now, don't bother running locally over HTTPS
SITE_ROOT_URI_SECURE = 'https://{0}:{1}/'.format(SITE_DOMAIN, LOCAL_PORT)

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'mysite.server.wsgi.application'

PIPELINE_LESS_BINARY = '/usr/local/bin/lessc'

# When running locally just print emails to the console...
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
SITE_FROM_EMAIL = 'noreply@mysite.com'

# SESSION_COOKIE_DOMAIN = '.mysite.com'
# SESSION_ENGINE = 'django.contrib.sessions.backends.db'
CSRF_COOKIE_DOMAIN = '.mysite.com'

# By default, turn template caching off for local development so you can make
# template changes without having to restart the dev server.
# If you DO want template caching while running locally, simply copy
# TEMPLATE_LOADERS from settings.py to a my_settings.py
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader'
)

INTERNAL_IPS = ('127.0.0.1',)
INSTALLED_APPS += ('debug_toolbar',)
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)

from mysite.site_settings.local.database import *
from mysite.site_settings.local.social import *
from mysite.site_settings.local.logging import *
from mysite.site_settings.local.debug_toolbar import *

# Anyone on the team can create their own settings_mine.py if they'd like to
# override the standard local settings. This settings_mine.py is included
# in SVN ignore
try:
    from settings_mine import *
except ImportError:
    pass


#!/usr/bin/env python3
import pwd

from argparse import ArgumentParser

from os import chdir
from pathlib import PurePath, Path

from client_backend.fs_db_io import FSDatabase
from client_backend.fs_db_file import *
from client_backend.fs_db_users import *

from stat import S_IRWXU, S_IRWXG, S_IRWXO

FS_DB = FSDatabase('.fs_db_rdbsh')
ROOTFS_PATH = Path('setup/rootfs/')

# Should create root user (uid/gid = 0) & nobody user (uid/gid = 99)

def _to_db_path(path):
    try:
        if path.anchor:
            currentPath = Path().resolve()
            path = path.relative_to(currentPath)
        return PurePath("/").joinpath(path)
    except ValueError:
        print(f"Warning: Could not locate'{path}' in Relational Database File System Root ({ROOTFS_PATH} by default)")
        return None

def insertDataIntoDB(x, fs_db):
    print(f'Copying & Uploading: {x.as_posix()}')
    if x.is_symlink():
        SymbolicLink(fs_db, _to_db_path(x), create_if_missing=True, linked_path=_to_db_path(x.resolve(strict=False)))
    elif x.is_dir():
        Directory(fs_db, _to_db_path(x), create_if_missing=True)
        for x_child in x.iterdir():
            insertDataIntoDB(x_child, fs_db)
    elif x.is_file():
        db_file = RegularFile(fs_db, _to_db_path(x), create_if_missing=True, contents="")
        # NOTE: Unix doesn't return the original creator, so we just call the user the author
        # NOTE: Also API doesn't support changing the author
        # db_file.author = user
        user = User(fs_db, x.stat().st_uid, create_if_missing=True, user_name=x.owner())
        group = Group(fs_db, x.stat().st_gid, create_if_missing=True, group_name=x.group())
        db_file.owner = user
        db_file.group_owner = group
        db_file.permissions = x.stat().st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)
        with x.open('rb') as f:
            db_file.write(f.readlines())
    else:
        print('Warning: Encountered unsupported file type', x.as_posix())

if __name__ == "__main__":
    parser = ArgumentParser(description="Upload files to your MySQL File System")
    parser.add_argument("custom_rdb_fs_root",
        help=f"The path realtive to {ROOTFS_PATH} to upload from, otherwise upload from {ROOTFS_PATH} by default",
        nargs='?',
        default='.')

    args = parser.parse_args()

    chdir(Path(ROOTFS_PATH).joinpath(args.custom_rdb_fs_root))
    insertDataIntoDB(Path(), FS_DB)


'''
Author       : xujiawei
Date         : 2021-08-13 11:42:31
Description  : description
'''
import os

import yaml

# 默认配置，启动时输出到 default_config.yaml
default_config = {
    'server': {'host': '0.0.0.0', 'port': 9965},
    'picture': {'backup_days': 2, 'save_pic_dir': './data/captured', 'delay_before_capture_sec': 0.5, 'capture_count': 3, 'capture_interval_sec': 0.5},
    'video': {'save_video': False, 'backup_days': 2, 'save_video_dir': './data/video'},
    'record': {'backup_days': 180, 'save_record_dir': './data/csv'},
    'vehicle_type_recognization': {'url': 'http://0.0.0.0:7000/prediction/vehicle_type_recognization'},
    'vehicle_detection': {'enable': True, 'url': 'http://0.0.0.0:7000/prediction/vehicle_detection', 'min_vehicle_bottom_line': 0.75},
    'vehicle_class_classification': {'enable': True, 'url': 'http://0.0.0.0:7000/prediction/vehicle_class_classification'},
    'cockpit_height_classification': {'enable': True, 'url': 'http://0.0.0.0:7000/prediction/cockpit_height_classification'},
    'vehicle_type_agent_server': {'enable': True, 'url': 'http://127.0.0.1:9201', 'send_video': False},
    'lane': {'binding_gd_index': 3, 'reverse_lane': False, 'wait_for_vehplate_time_sec': 0, 'gd_delay_time_sec': 0},
    'camera': {'name': 'imx290_170', 'type': 'imx290', 'device': 0, 'rotate': 90, 'scale': 0.5, 'brightness_range': '(90, 150)', 'exposure_range': '(1, 80)', 'gain_range': '(0, 100)', 'auto_exposure_hour_range': '(0,0)', 'default_exposure': 10},
    'splicer': {'frame_width': 360, 'frame_height': 640, 'detect_vehicle_view': '(400, 620, 170, 260)', 'calc_offset_view': '(400, 620, 30, 330)', 'splice_x_pos': 170, 'min_detect_contour_size': 150, "detect_car_leave_by_video": False},
    'ui_server': {'url': 'http://127.0.0.1:5000'},
    'processes_message_queue_type': 'RedisMessageQueue'
}

config_file = os.path.abspath(os.path.join(os.path.dirname(__file__), '../config/default_config.yaml'))
special_config_file = os.path.abspath(os.path.join(os.path.dirname(__file__), '../config/special_config.yaml'))

def load(file_path):
    if os.path.exists(file_path):
        with open(file_path, 'r', encoding='utf8') as f:
            cfg = yaml.load(f, Loader=yaml.FullLoader)
    else:
        cfg = {}
    return cfg

def export(config, file_path):
    with open(file_path, 'w', encoding='utf8') as w:
        yaml.dump(config, w, default_flow_style=False)

def combine(older, newer):

    for k, v in newer.items():
        if not isinstance(v, dict):
            older[k] = newer[k]
        else:
            combine(older[k], newer[k])

    return older

export(default_config, config_file)
special_config = load(special_config_file)
config = combine(default_config, special_config)


from ray.rllib.algorithms.sac import SAC
from ray.tune.registry import register_env
from gym_cooking.environment.environment import GymCookingEnvironment

n_agents = 1
num_humans = 1
render = False

level = 'open_room_interaction2'
seed = 1
record = False
max_num_timesteps = 100
recipe = "CarrotBanana"
action_scheme = "scheme3"

env_config = {
    "level": level, "record": record, "max_steps": max_num_timesteps,
    "recipe": recipe, "action_scheme": action_scheme, "obs_spaces": ["feature_vector"],
    "ghost_agents": 1
}

def env_creator(env_conf):
    return GymCookingEnvironment(**env_config)  # return an env instance

register_env("my_env", env_creator)

config = {
    "env": "my_env",
    "num_workers": 0,
    "framework": "torch",
    "model": {
        "fcnet_hiddens": [128, 128],
        "fcnet_activation": "relu",
    },
    "evaluation_config": {
        "render_env": False,
    }
}

algo = SAC(config=config)

for _ in range(10000):
    stuff = algo.train()
    interest_keys = ["episode_reward_max", "episode_reward_min", "episode_reward_mean", "episode_len_mean",
                     "episodes_this_iter", "episodes_total", "num_agent_steps_sampled"]
    filtered_stuff = {k: stuff[k] for k in interest_keys}
    print(filtered_stuff)

algo.evaluate()


from optparse import OptionParser

import struct
import binascii
import time

class LogFileHeader(object):
    def __init__(self, log):
        s = struct.Struct('4s')
        self.MAGIC = int(binascii.hexlify(s.pack('ZKLG')), 16)
        s = struct.Struct('>i i q')
        (self.magic, self.version, self.dbid) = s.unpack(log.read(s.size))
    def isvalid(self):
        return self.magic == self.MAGIC

SESSIONCLOSE = -11
SESSIONCREATE = -10
ERROR = -1
NOTIFICATION = 0
CREATE = 1
DELETE = 2
EXISTS = 3
GETDATA = 4
SETDATA = 5
GETACL = 6
SETACL = 7
GETCHILDREN = 8
SYNC = 9
PING = 11
GETCHILDREN2 = 12
CHECK = 13
MULTI = 14
AUTH = 100
SETWATCHES = 101
SASL = 102

opcodes = {
    SESSIONCLOSE:'sessionclose',
    SESSIONCREATE:'sessioncreate',
    ERROR:'error',
    NOTIFICATION:'notification',
    CREATE:'create',
    DELETE:'delete',
    EXISTS:'exists',
    GETDATA:'getdata',
    SETDATA:'setdata',
    GETACL:'getacl',
    SETACL:'setacl',
    GETCHILDREN:'getchildren',
    SYNC:'sync',
    PING:'ping',
    GETCHILDREN2:'getchildren2',
    CHECK:'check',
    MULTI:'multi',
    AUTH:'auth',
    SETWATCHES:'setwatches',
    SASL:'sasl',
}

# endofstream
class EOS(Exception):
    pass

class UnknownType(Exception):
    def __init__(self, type):
        self.type = type
    def __str__(self):
        return "Unknown type %d" % self.type

class Txn(object):
    def __init__(self, log):
        s = struct.Struct('>q i')
        (self.crc, self.txn_len) = s.unpack(log.read(s.size))

        if self.txn_len == 0: raise EOS()

        self.header = h = TxnHeader(log)
        if h.type == CREATE:
            self.entry = TxnCreate(log)
        elif h.type == DELETE:
            self.entry = TxnDelete(log)
        elif h.type == SETDATA:
            self.entry = TxnSetData(log)
        elif h.type == SETACL:
            self.entry = TxnSetAcl(log)
        elif h.type == SESSIONCREATE:
            self.entry = TxnSessionCreate(log)
        elif h.type == SESSIONCLOSE:
            self.entry = TxnSessionClose(log)
        elif h.type == ERROR:
            self.entry = TxnError(log)
        else:
            raise(UnknownType(h.type))

        eor = log.read(1)
    def __str__(self):
        return "%s -- %s" % (self.header, self.entry)

class TxnHeader(object):
    def __init__(self, log):
        s = struct.Struct('>Q I Q Q i')
        (self.client_id, self.cxid, self.zxid, self.time,
         self.type) = s.unpack(log.read(s.size))
    def op2type(self, type):
        return opcodes[type]
    def __str__(self):
        return "%s (%3dms) sessionid 0x%x zxid 0x%x cxid 0x%x %s" % (
                  time.ctime(self.time/1000), self.time % 1000,
                  self.client_id, self.zxid, self.cxid,
                  self.op2type(self.type))

class TxnEntry(object):
    def readString(self, log):
        _len = self.readInt(log)
        s = struct.Struct(str(_len) + 's')
        _str = s.unpack(log.read(s.size))
        return _str

    def readData(self, log):
        _len = self.readInt(log)
        return log.read(_len)

    def readAcls(self, log):
        count = self.readInt(log)
        return [self.readAcl(log) for i in xrange(count)]

    def readAcl(self, log):
        return Acl(log)

    def readInt(self, log):
        s = struct.Struct('>i')
        (_int,) = s.unpack(log.read(s.size))
        return _int

    def readBool(self, log):
        s = struct.Struct('B')
        _bool = s.unpack(log.read(s.size))
        return _bool == 0

class Acl(TxnEntry):
    def __init__(self, log):
        self.perms = self.readInt(log)
        self.scheme = self.readString(log)
        self.id = self.readString(log)
    def __str__(self):
        return "Acl %s %s %x" % (self.scheme, self.id, self.perms)

class TxnError(TxnEntry):
    Ok = 0
    SystemError = -1
    RuntimeInconsistency = -2
    DataInconsistency = -3
    ConnectionLoss = -4
    MarshallingError = -5
    Unimplemented = -6
    OperationTimeout = -7
    BadArguments = -8
    APIError = -100
    NoNode = -101
    NoAuth = -102
    BadVersion = -103
    NoChildrenForEphemerals = -108
    NodeExists = -110
    NotEmpty = -111
    SessionExpired = -112
    InvalidCallback = -113
    InvalidACL = -114
    AuthFailed = -115
    SessionMoved = -118

    errorcodes = {
        Ok:'ok',
        SystemError:'systemerror',
        RuntimeInconsistency:'runtimeinconsistency',
        DataInconsistency:'datainconsistency',
        ConnectionLoss:'connectionloss',
        MarshallingError:'marshallingerror',
        Unimplemented:'unimplemented',
        OperationTimeout:'operationtimeout',
        BadArguments:'badarguments',
        APIError:'apierror',
        NoNode:'nonode',
        NoAuth:'noauth',
        BadVersion:'badversion',
        NoChildrenForEphemerals:'nochildrenforephemerals',
        NodeExists:'nodeexists',
        NotEmpty:'notempty',
        SessionExpired:'sessionexpired',
        InvalidCallback:'invalidcallback',
        InvalidACL:'invalidacl',
        AuthFailed:'authfailed',
        SessionMoved:'sessionmoved',
    }

    def __init__(self, log):
        self.err = self.readInt(log)
    def __str__(self):
        return "Error %s" % self.errorcodes[self.err]

class TxnCreate(TxnEntry):
    def __init__(self, log):
        self.path = self.readString(log)
        self.data = self.readData(log)
        self.acls = self.readAcls(log)
        self.ephemeral = self.readBool(log)
    def __str__(self):
        return "Create path %s data '%s' acls %s ephemeral %i" % (
                 self.path, self.data, self.acls, self.ephemeral)

class TxnDelete(TxnEntry):
    def __init__(self, log):
        self.path = self.readString(log)
    def __str__(self):
        return "Delete path %s" % self.path

class TxnSetData(TxnEntry):
    def __init__(self, log):
        self.path = self.readString(log)
        self.data = self.readData(log)
        self.version = self.readInt(log)
    def __str__(self):
        return "SetData path %s data '%s' version %i" % (self.path, self.data, self.version)

class TxnSetAcl(TxnEntry):
    def __init__(self, log):
        self.path = self.readString(log)
        self.acls = self.readAcls(log)
        self.version = self.readInt(log)
    def __str__(self):
        return "SetAcl path %s acls %s version %i" % (self.path, self.acls, self.version)

class TxnSessionCreate(TxnEntry):
    def __init__(self, log):
        self.timeout = self.readInt(log)
    def __str__(self):
        return "SessionCreate timeout %ims" % (self.timeout)

class TxnSessionClose(TxnEntry):
    def __init__(self, log):
        pass
    def __str__(self):
        return "SessionClose"

if __name__ == '__main__':
    usage = "usage: %prog [options] zookeeper_txnlog"
    parser = OptionParser(usage=usage)

    #parser.add_option("-c", "--count", dest="count", type="int",
    #                  default=3, help="ensemble size (default 3)")

    (options, args) = parser.parse_args()

    if len(args) != 1:
        parser.error("need log file")

    log = open(args[0], 'rb')
    log_header = LogFileHeader(log)
    if not log_header.isvalid():
        parser.error("Not a valid ZooKeeper transaction log")

    start = None
    try:
        while(True):
            txn = Txn(log)
            if not start:
                start = txn.header.time
                print("Log starts at %s and %ims" % (time.ctime(start/1000), start % 1000))
            diff = txn.header.time - start
            print("%09i,%03i %s" % (diff/1000, diff%1000, str(txn)[33:]))
    except Exception as e:
        print(e)

    log.close()


"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return  []

        output = []
        prev_layer = [root]

        while prev_layer:
            cur_layer = []
            output.append([])
            for node in prev_layer:
                output[-1].append(node.val)
                cur_layer.extend(node.children)

            prev_layer = cur_layer
        return output

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        queue = deque([root])
        output = []
        while queue:
            length = len(queue)
            output.append([])
            for _ in range(length):
                node = queue.popleft()
                output[-1].append(node.val)
                queue.extend(node.children)
        return output

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        def recursive(node, level):
            if len(results) == level:
                results.append([])
            results[level].append(node.val)
            for child in node.children:
                recursive(child, level + 1)

        results = []
        if root is not None:
            recursive(root, 0)
        return results


"""
Objects with validity checking for Google service account registration.
"""
from collections import Mapping
from fence.errors import NotFound

from fence.resources.google.utils import (
    get_registered_service_accounts_with_access,
    get_project_access_from_service_accounts,
    get_users_from_google_members,
    get_service_account_ids_from_google_members,
    is_google_managed_service_account,
)
from fence.resources.google.access_utils import (
    is_valid_service_account_type,
    service_account_has_external_access,
    is_service_account_from_google_project,
    get_google_project_membership,
    get_google_project_parent_org,
    get_google_project_valid_users_and_service_accounts,
    do_all_users_have_access_to_project,
    get_project_from_auth_id,
    get_google_project_number,
    get_service_account_policy,
    remove_white_listed_service_account_ids,
    is_org_whitelisted,
    is_user_member_of_google_project,
    is_user_member_of_all_google_projects,
)
from cirrus.google_cloud import GoogleCloudManager

from cdislogging import get_logger

logger = get_logger(__name__)

class ValidityInfo(Mapping):
    """
    A representation of validity of an item along with
    information about the validity.

    It's a dict-like object which can be evaulated as a boolean value.
    If the info is false-y, the validity of this object will evaluate to False.

    CAVEAT: None is allowed and will not make the validity False, this
            represents a validity check that was NOT run
            (e.g. we have no information)

    This means that you can nest ValidityInfo objects and
    the "valid" status of the parent object will always be updated when adding
    new validity information.
    """

    def __init__(self, default_validity=True):
        # innocent until proven guilty, default validity is True
        self._valid = default_validity
        self._info = {}

    def get(self, key, *args):
        return self._info.get(key, *args)

    def set(self, key, value):
        if not value and value is not None:
            self._valid = False
        self._info.__setitem__(key, value)

    def __setitem__(self, key, value):
        if not value and value is not None:
            self._valid = False
        self._info.__setitem__(key, value)

    def __contains__(self, key):
        return key in self._info

    def __iter__(self):
        for key, value in self._info.items():
            yield key, value

    def __getitem__(self, key):
        return self._info[key]

    def __delitem__(self, key):
        del self._info[key]

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

    def __bool__(self):
        return self._valid

    def __repr__(self):
        return str(self._info)

    def __str__(self):
        return str(self._info)

    def get_info(self):
        return self._info

class GoogleProjectValidity(ValidityInfo):
    """
    A representation of a Google Project's validity regarding service account
    registration for access to data.

    Example Usage and Information:

        project_validity = (
            GoogleProjectValidity(
                google_project_id='abc123',
                new_service_account='someaccount@something.com',
                new_service_account_access=['projectA', 'ProjectB']
            )
        )
        project_validity.check_validity(early_return=False)

        NOTE: project_validity can be evaluated as if it's a boolean and will
        be False if ANY of the values in the dict-like structure are False.
        In other words, a single invalid item will make the whole project
        invalid.

        An example of the dict-like structure with validity info is:

        {
            'monitor_has_access': True,
            'valid_parent_org': True,
            'valid_membership': True,
            'new_service_account': {
                'account@something.com': {
                    'valid_type': True,
                    'no_external_access': True,
                    'owned_by_project': True,
                    'exists': True
                },
            }
            'service_accounts': {
                'someaccount@something.com': {
                    'valid_type': None,
                    'no_external_access': True,
                    'owned_by_project': True,
                    'exists': True
                },
                'other_service_account_in_project@something.com': {
                    'valid_type': None,
                    'no_external_access': True,
                    'owned_by_project': True,
                    'exists': True
                }
            },
            'access': {
                'ProjectA': {
                    'exists': True,
                    'all_users_have_access': True
                },
                'ProjectB': {
                    'exists': True,
                    'all_users_have_access': True
                },
            }
        }
    """

    def __init__(
        self,
        google_project_id,
        new_service_account=None,
        new_service_account_access=None,
        user_id=None,
        google_cloud_manager=None,
        *args,
        **kwargs
    ):
        """
        Initialize

        Args:
            google_project_id (str): Google project identifier
            new_service_account (str, optional): an additional service account
                identifier (ex: email) to include when checking access. You can
                provide this without actually giving it access to check if
                access will be valid
            new_service_account_access (List(str), optional): List of
                Project.auth_ids to attempt to provide the new service account
                access to
            user_id (None, optional): User requesting validation. ONLY pass this if you
                want to check if the user is a member of this project.
        """
        self.google_project_id = google_project_id
        self.new_service_account = new_service_account
        self.new_service_account_access = new_service_account_access or []
        self.user_id = user_id
        self.google_cloud_manager = google_cloud_manager or GoogleCloudManager(
            google_project_id
        )

        super(GoogleProjectValidity, self).__init__(*args, **kwargs)

        # setup default values for error information, will get updated in
        # check_validity
        self._info["user_has_access"] = None
        self._info["monitor_has_access"] = None
        self._info["valid_parent_org"] = None
        self._info["valid_member_types"] = None
        self._info["members_exist_in_fence"] = None
        self._info["new_service_account"] = {}
        self._info["service_accounts"] = {}
        self._info["access"] = {}

    def check_validity(self, early_return=True, db=None):
        """
        Determine whether or not project is valid for registration. If
        early_return is False, this object will store information about the
        failure.

        Args:
            early_return (bool, optional): Description
        """

        self.google_cloud_manager.open()

        logger.debug(
            "Google Project with id: {}, "
            "new service account requested: {}, project access requested: {}, "
            "user requesting: {}".format(
                self.google_project_id,
                self.new_service_account,
                self.new_service_account_access,
                self.user_id,
            )
        )

        logger.debug(
            "Attempting to get project number "
            "for project id {}".format(self.google_project_id)
        )
        google_project_number = get_google_project_number(
            self.google_project_id, self.google_cloud_manager
        )
        has_access = bool(google_project_number)

        self.set("monitor_has_access", has_access)
        # always early return if we can't access the project
        if not has_access:
            logger.warning(
                "INVALID Fence's Monitoring service account does "
                "NOT have access in project id {}. Monitor needs access to continue "
                "checking project validity. Exiting early and determining invalid.".format(
                    self.google_project_id
                )
            )
            return

        logger.debug(
            "Retrieving project membership "
            "for project id {}".format(self.google_project_id)
        )
        membership = get_google_project_membership(
            self.google_project_id, self.google_cloud_manager
        )
        logger.debug(
            "Project Members: {}".format(
                str(
                    [
                        getattr(member, "email_id", "unknown_member_email")
                        for member in membership
                    ]
                )
            )
        )

        if self.user_id is not None:
            logger.debug(
                "Checking that user requesting, {}, is part of "
                "the Google Project with id {}".format(
                    self.user_id, self.google_project_id
                )
            )
            user_has_access = is_user_member_of_google_project(
                self.user_id, self.google_cloud_manager, membership=membership, db=db
            )
            self.set("user_has_access", user_has_access)
            if not user_has_access:
                # always early return if user isn't a member on the project
                logger.warning(
                    "INVALID User {} "
                    "for project id {}. User is not a member of the project so does not "
                    "have permission on the project.".format(
                        self.user_id, self.google_project_id
                    )
                )
                return

        logger.debug(
            "Retrieving Parent Organization "
            "for project id {} to make sure it's valid".format(self.google_project_id)
        )
        parent_org = get_google_project_parent_org(self.google_cloud_manager)
        valid_parent_org = True

        if parent_org:
            valid_parent_org = is_org_whitelisted(parent_org)

        self.set("valid_parent_org", valid_parent_org)

        if not valid_parent_org:
            logger.warning(
                "INVALID Parent Organization {} "
                "for project id {}. No parent org is allowed unless it's explicitly "
                "whitelisted in cfg.".format(parent_org, self.google_project_id)
            )
            if early_return:
                return

        logger.debug(
            "Determining if other users and service accounts on "
            "project id {} are valid.".format(self.google_project_id)
        )
        user_members = None
        service_account_members = []
        try:
            (
                user_members,
                service_account_members,
            ) = get_google_project_valid_users_and_service_accounts(
                self.google_project_id, self.google_cloud_manager, membership=membership
            )
            self.set("valid_member_types", True)
        except Exception:
            self.set("valid_member_types", False)
            logger.warning(
                "INVALID users and/or service accounts (SAs) on "
                "project id {}.".format(self.google_project_id)
            )
            if early_return:
                return

        logger.debug("Determining if valid users exist in fence.")
        # if we have valid members, we can check if they exist in fence
        users_in_project = None
        if user_members is not None:
            try:
                users_in_project = get_users_from_google_members(user_members, db=db)
                self.set("members_exist_in_fence", True)
            except Exception as e:
                self.set("members_exist_in_fence", False)
                logger.warning(
                    "INVALID user(s) do not exist in fence and thus, "
                    "we cannot determine their authZ info: {}.".format(e)
                )
                if early_return:
                    return

        # use a generic validityinfo object to hold all the service accounts
        # validity. then check all the service accounts. Top level will be
        # invalid if any service accounts are invalid
        new_service_account_validity = ValidityInfo()
        if self.new_service_account:
            service_account_validity_info = GoogleServiceAccountValidity(
                self.new_service_account,
                self.google_project_id,
                google_project_number=google_project_number,
                google_cloud_manager=self.google_cloud_manager,
            )

            service_account_id = str(self.new_service_account)

            logger.debug(
                "Google Project with id: {} and number: {}. "
                "Beginning validation on service account for registration {}".format(
                    self.google_project_id, google_project_number, service_account_id
                )
            )

            logger.debug(
                "Determining if the service account {} is google-managed.".format(
                    service_account_id
                )
            )
            # we do NOT need to check the service account type and external access
            # for google-managed accounts.
            if is_google_managed_service_account(service_account_id):
                logger.debug(
                    "GCP SA Validity -Service account {} IS google-managed. Therefore, "
                    "we do NOT need to check the SA Type or if it has external access.".format(
                        service_account_id
                    )
                )
                service_account_validity_info.check_validity(
                    early_return=early_return,
                    check_type=True,
                    check_policy_accessible=True,
                    check_external_access=False,
                )
            else:
                logger.debug(
                    "GCP SA Validity -Service account {} is NOT google-managed. Therefore, "
                    "we need to run all validation checks against it.".format(
                        service_account_id
                    )
                )
                service_account_validity_info.check_validity(
                    early_return=early_return,
                    check_type=True,
                    check_policy_accessible=True,
                    check_external_access=True,
                )

            # update project with error info from the service accounts
            new_service_account_validity.set(
                service_account_id, service_account_validity_info
            )

            if not service_account_validity_info:
                logger.warning("INVALID service account {}.".format(service_account_id))
                # if we need to return early for invalid SA, make sure to include
                # error details and invalidate the overall validity
                if early_return:
                    self.set("new_service_account", new_service_account_validity)
                    return

        self.set("new_service_account", new_service_account_validity)

        logger.debug(
            "Google Project with id: {} and number: {}. "
            "Beginning validation on project service accounts not requested for "
            "registration.".format(self.google_project_id, google_project_number)
        )

        service_accounts = get_service_account_ids_from_google_members(
            service_account_members
        )

        logger.debug("SAs on the project {}.".format(service_accounts))

        remove_white_listed_service_account_ids(service_accounts)

        # don't double check service account being registered
        if self.new_service_account:
            try:
                service_accounts.remove(self.new_service_account)
            except ValueError:
                logger.debug(
                    "Service Account requested for registration is not a "
                    "member of the Google project."
                )

        # use a generic validityinfo object to hold all the service accounts
        # validity. then check all the service accounts. Top level will be
        # invalid if any service accounts are invalid
        service_accounts_validity = ValidityInfo()
        for service_account in service_accounts:
            service_account_validity_info = self._get_project_sa_validity_info(
                service_account, google_project_number, early_return
            )

            # update project with error info from the service accounts
            service_accounts_validity.set(
                service_account, service_account_validity_info
            )

            if not service_account_validity_info and early_return:
                # if we need to return early for invalid SA, make sure to include
                # error details and invalidate the overall validity
                self.set("service_accounts", service_accounts_validity)
                return

        self.set("service_accounts", service_accounts_validity)

        logger.debug(
            "Checking data access for Google Project {}...".format(
                self.google_project_id
            )
        )

        # get the service accounts for the project to determine all the data
        # the project can access through the service accounts
        service_accounts = get_registered_service_accounts_with_access(
            self.google_project_id, db=db
        )

        # don't double check service account being updated if it was previously registered
        # in other words, this may be an update of existing access (from A&B to just A)
        # so we need to ONLY validate the new access (which happens below when the project
        # access list is extended with new access requested)
        if self.new_service_account:
            logger.debug(
                "Removing new/updated SA {} from list of existing SAs in order "
                "to only validate the newly requested access.".format(
                    self.new_service_account
                )
            )
            service_accounts = [
                sa
                for sa in service_accounts
                if sa.email.lower() != str(self.new_service_account).lower()
            ]

        service_account_project_access = get_project_access_from_service_accounts(
            service_accounts, db=db
        )

        logger.debug(
            "Registered SAs {} current have project access: {}".format(
                [sa.email for sa in service_accounts], service_account_project_access
            )
        )

        # use a generic validityinfo object to hold all the projects validity
        project_access_validities = ValidityInfo()

        # extend list with any provided access to test
        for provided_access in self.new_service_account_access:
            project = get_project_from_auth_id(provided_access)

            # if provided access doesn't exist, set error in project_validity
            if not project:
                logger.warning(
                    "INVALID project access requested. "
                    "Data Access with auth_id {} does not exist.".format(
                        provided_access
                    )
                )
                project_validity = ValidityInfo()
                project_validity.set("exists", False)
                project_validity.set("all_users_have_access", None)
                project_access_validities.set(str(provided_access), project_validity)
            else:
                service_account_project_access.append(project)

        logger.debug(
            "New project access requested (in addition to "
            "previous access): {}.".format(service_account_project_access)
        )

        # make sure all the users of the project actually have access to all
        # the data the service accounts have access to
        for project in service_account_project_access:
            project_validity = ValidityInfo()
            project_validity.set("exists", True)

            # if all the users exist in our db, we can check if they have valid
            # access
            logger.debug(
                "Checking that all users in project have "
                "access to project with id {}".format(
                    getattr(project, "id", "ERROR-could-not-get-project-id")
                )
            )
            valid_access = None
            if users_in_project:
                valid_access = do_all_users_have_access_to_project(
                    users_in_project, project.id, db=db
                )
                if not valid_access:
                    logger.warning(
                        "INVALID Some users do NOT have "
                        "access to project with id {}. users in project: {}".format(
                            getattr(project, "id", "ERROR-could-not-get-project-id"),
                            [
                                getattr(user, "username", "unknown_user")
                                for user in users_in_project
                            ],
                        )
                    )

            project_validity.set("all_users_have_access", valid_access)

            project_access_validities.set(str(project.auth_id), project_validity)

        self.set("access", project_access_validities)
        self.google_cloud_manager.close()
        return

    def _get_project_sa_validity_info(
        self, service_account, google_project_number, early_return
    ):
        service_account_id = str(service_account)

        service_account_validity_info = GoogleServiceAccountValidity(
            service_account,
            self.google_project_id,
            google_project_number=google_project_number,
            google_cloud_manager=self.google_cloud_manager,
        )

        logger.debug(
            "Google Project with id: {} and number: {}. "
            "Beginning validation on project service account {}".format(
                self.google_project_id, google_project_number, service_account_id
            )
        )

        logger.debug(
            "Determining if the service account {} is google-managed.".format(
                service_account_id
            )
        )

        # we do NOT need to check the service account type and external access
        # for google-managed accounts.
        if is_google_managed_service_account(service_account_id):
            logger.debug(
                "Service account {} IS google-managed. Therefore, "
                "we only need to detemine if it belongs.".format(service_account_id)
            )
            service_account_validity_info.check_validity(
                early_return=early_return,
                check_type=False,
                check_policy_accessible=False,
                check_external_access=False,
            )
        else:
            logger.debug(
                "Service account {} is NOT google-managed. Therefore, "
                "we need to run all validation checks against it.".format(
                    service_account_id
                )
            )
            service_account_validity_info.check_validity(
                early_return=early_return,
                check_type=True,
                check_policy_accessible=True,
                check_external_access=True,
            )

        return service_account_validity_info

class GoogleServiceAccountValidity(ValidityInfo):
    """
    A representation of a Google Service Accounts's validity regarding
    registration for access to data.

    Example Usage and Information:

        sa_validity = (
            GoogleServiceAccountValidity(
                account_id='some-service-account@something.com'
                google_project_id='abc123',
                google_project_number='123456789'
            )
        )
        sa_validity.check_validity(early_return=False)

        NOTE: sa_validity can be evaluated as if it's a boolean and will
        be False if ANY of the values in the dict-like structure are False.
        In other words, a single invalid item will make the whole project
        invalid.

        An example of the dict-like structure with validity info is:

        {
            'valid_type': True,
            'no_external_access': True,
            'owned_by_project': True,
            'exists': True
        }
    """

    def __init__(
        self,
        account_id,
        google_project_id,
        google_cloud_manager=None,
        google_project_number=None,
        *args,
        **kwargs
    ):
        self.account_id = account_id
        self.google_project_id = google_project_id

        # default to the given project id if not provided
        self.google_project_number = google_project_number or google_project_id
        self.google_cloud_manager = google_cloud_manager or GoogleCloudManager(
            google_project_id
        )
        super(GoogleServiceAccountValidity, self).__init__(*args, **kwargs)

        # setup default values for error information, will get updated in
        # check_validity
        self._info["owned_by_project"] = None
        self._info["valid_type"] = None
        self._info["no_external_access"] = None
        self._info["policy_accessible"] = None

    def check_validity(
        self,
        early_return=True,
        check_type=True,
        check_external_access=True,
        check_policy_accessible=True,
    ):
        logger.debug(
            "Validating Google Service Account {} for Google Project {}.".format(
                self.account_id, self.google_project_id
            )
        )

        self.google_cloud_manager.open()

        # check ownership
        logger.debug(
            "Determining if {} is owned by the Google Project.".format(self.account_id)
        )

        is_owned_by_google_project = is_service_account_from_google_project(
            self.account_id, self.google_project_id, self.google_project_number
        )
        self.set("owned_by_project", is_owned_by_google_project)
        if not is_owned_by_google_project:
            logger.warning(
                "INVALID SA {}, it is NOT owned by the Google Project {}.".format(
                    self.account_id, self.google_project_id
                )
            )
            if early_return:
                self.google_cloud_manager.close()
                return

        # select the GCM to use for the remainder of the checks
        # if the account is not owned by the google project then
        # it is invalid, however, if Fence has access to the SA's
        # project, we can still check the other conditions

        if is_owned_by_google_project:
            gcm = self.google_cloud_manager
        else:
            self.google_cloud_manager.close()
            try:
                # check to see if we can access the project the SA belongs to
                project_id = self.account_id.split("@")[-1].split(".")[0]
                gcm = GoogleCloudManager(project_id)
                gcm.open()
            except Exception:
                logger.debug(
                    "Could not access the Google Project for Service "
                    "Account {}. Unable to continue validity "
                    "checkingwithout access to the project, "
                    "early exit.".format(self.account_id)
                )
                return

        # check if the SA's policy is accessible
        policy_accessible = None
        sa_policy = None
        if check_policy_accessible:
            try:
                policy_accessible = True
                sa_policy = get_service_account_policy(self.account_id, gcm)
            except Exception:
                policy_accessible = False
                gcm.close()
                return
            finally:
                self.set("policy_accessible", policy_accessible)

        if check_external_access:
            if not policy_accessible:
                logger.warning(
                    "Invalid function use. External Access check requires "
                    "Service Account Policy & may fail if policy is not "
                    "accessible. If you want to check external access, make "
                    "sure you are also checking policy_accessible. "
                )
                gcm.close()
                return

            no_external_access = not (
                service_account_has_external_access(self.account_id, gcm, sa_policy)
            )
            self.set("no_external_access", no_external_access)
            if not no_external_access:
                logger.warning(
                    "INVALID SA {}, it has external access "
                    "(keys generated or roles on it).".format(self.account_id)
                )
                if early_return:
                    gcm.close()
                    return

        # check if the SA is an allowed type
        if check_type:
            if not policy_accessible:
                logger.warning(
                    "Policy access was not checked. If the service account's "
                    "policy is not accessible or the service account does not "
                    "exist, this check may fail."
                )
                # don't return early, we can still check type without checking
                # policy, however, if the SA doesn't exist, this will fail

            valid_type = is_valid_service_account_type(self.account_id, gcm)

            self.set("valid_type", valid_type)
            if not valid_type:
                logger.warning(
                    "INVALID SA {}, it is not a valid SA type.".format(self.account_id)
                )
                if early_return:
                    gcm.close()
                    return

        gcm.close()


import numpy as np

def getNumDivisors(n):
	numDiv = 0
	for i in range(1, int(np.sqrt(n))+1):
		if n%i == 0 and n//i != i:
			numDiv += 2
		elif n%i == 0:
			numDiv += 1
	return numDiv

def getTriangleNum(n):
	return n*(n+1)//2

numDiv = 0
triNum = 50
while numDiv < 500:
	triNum += 1
	numDiv = getNumDivisors(getTriangleNum(triNum))
print(getTriangleNum(triNum))


import numpy as np
import argparse
import sys
import os
import random
import scipy
import colorsys

from itertools import islice
import matplotlib.pyplot as plt

sys.path.extend([
    os.path.join(os.getcwd(), 'pddlstream'), # Important to use absolute path when doing chdir
    os.path.join(os.getcwd(), 'ss-pybullet'),
])

from plan_tools.planner import PlanningWorld
from pybullet_tools.utils import set_pose, wait_for_user, set_camera_pose, draw_pose, get_pose, load_pybullet, \
    add_data_path, remove_body, get_bodies, set_color, apply_alpha, BLACK, RED, GREEN, spaced_colors, clip, multiply, \
    Pose, Euler, invert, unit_pose, get_image, get_camera, take_picture, save_image, wait_for_duration, read_pickle, \
    clip, create_box, create_cylinder, set_point, Point, add_line, tform_point, LockRenderer, approximate_as_prism, \
    WHITE, draw_point, GREY, randomize, INF, create_plane, safe_zip, point_from_pose, remove_handles
from plan_tools.samplers.pour import get_pour_feature, pour_path_from_parameter, is_valid_pour, get_bowl_from_pivot
from learn_tools.run_active import TRAIN_DATASETS, ACTIVE_DATASETS, TEST_DATASETS, BEST_DATASETS
from learn_tools.active_learner import BEST, STRADDLE, REJECTION, tail_confidence
from learn_tools.active_gp import get_parameters
from learn_tools.learner import FAILURE, SUCCESS, DEFAULT_INTERVAL, rescale, inclusive_range
from learn_tools.learnable_skill import read_data
#from learn_tools.collect_simulation import SKILL_COLLECTORS
from learn_tools.collectors.collect_pour import compute_fraction_filled, pour_score
from dimensions.common import load_cup_bowl

#BACKGROUND_COLOR = WHITE
BACKGROUND_COLOR = [0.9, 0.9, 1.0] # 229, 229, 255
GROUND_COLOR = 0.8*np.ones(3)

def create_world():
    world = PlanningWorld(task=None, use_robot=False, visualize=True, color=BACKGROUND_COLOR, shadows=False)
    add_data_path()
    environment = [
        #load_pybullet('models/short_floor.urdf'),
        #load_pybullet('plane.urdf', fixed_base=True),
        create_plane(color=GROUND_COLOR),
    ]
    set_camera_pose(camera_point=0.4*np.array([0, -1.0, 0.5]))
    #draw_pose(unit_pose(), length=1)
    return world

##################################################

def interpolate_hue(fraction, min_hue=0./3, max_hue=2./3):
    hue = (1 - fraction) * min_hue + fraction * max_hue
    return colorsys.hsv_to_rgb(hue, s=1, v=1)

def visualize_collected_pours(paths, num=6, save=True):
    result_from_bowl = {}
    for path in randomize(paths):
        results = read_data(path)
        print(path, len(results))
        for result in results:
            result_from_bowl.setdefault(result['feature']['bowl_type'], []).append(result)

    world = create_world()
    environment = get_bodies()
    #collector = SKILL_COLLECTORS['pour']
    print(get_camera())

    for bowl_type in sorted(result_from_bowl):
        # TODO: visualize same
        for body in get_bodies():
            if body not in environment:
                remove_body(body)
        print('Bowl type:', bowl_type)
        bowl_body = load_cup_bowl(bowl_type)
        bowl_pose = get_pose(bowl_body)

        results = result_from_bowl[bowl_type]
        results = randomize(results)

        score_cup_pose = []
        for i, result in enumerate(results):
            if num <= len(score_cup_pose):
                break
            feature = result['feature']
            parameter = result['parameter']
            score = result['score']
            if (score is None) or not result['execution'] or result['annotation']:
                continue
            cup_body = load_cup_bowl(feature['cup_type'])
            world.bodies[feature['bowl_name']] = bowl_body
            world.bodies[feature['cup_name']] = cup_body
            fraction = compute_fraction_filled(score)
            #value = collector.score_fn(feature, parameter, score)
            value = pour_score(feature, parameter, score)
            print(i, feature['cup_type'], fraction, value)
            path, _ = pour_path_from_parameter(world, feature, parameter)
            sort = fraction
            #sort = parameter['pitch']
            #sort = parameter['axis_in_bowl_z']
            score_cup_pose.append((sort, fraction, value, cup_body, path[0]))

        #order = score_cup_pose
        order = randomize(score_cup_pose)
        #order = sorted(score_cup_pose)
        angles = np.linspace(0, 2*np.pi, num=len(score_cup_pose), endpoint=False) # Halton
        for angle, (_, fraction, value, cup_body, pose) in zip(angles, order):
            #fraction = clip(fraction, min_value=0, max_value=1)
            value = clip(value, *DEFAULT_INTERVAL)
            fraction = rescale(value, DEFAULT_INTERVAL, new_interval=(0, 1))
            #color = (1 - fraction) * np.array(RED) + fraction * np.array(GREEN)
            color = interpolate_hue(fraction)
            set_color(cup_body, apply_alpha(color, alpha=0.25))
            #angle = random.uniform(-np.pi, np.pi)
            #angle = 0
            rotate_bowl = Pose(euler=Euler(yaw=angle))
            cup_pose = multiply(bowl_pose, invert(rotate_bowl), pose)
            set_pose(cup_body, cup_pose)
            #wait_for_user()
            #remove_body(cup_body)

        if save:
            #filename = os.path.join('workspace', '{}.png'.format(bowl_type))
            #save_image(filename, take_picture())  # [0, 255]
            #wait_for_duration(duration=0.5)
            # TODO: get window location
            #os.system("screencapture -R {},{},{},{} {}".format(
            #    275, 275, 500, 500, filename)) # -R<x,y,w,h> capture screen rect
            wait_for_user()
        remove_body(bowl_body)

##################################################

def add_obstacles():
    ceiling = create_box(w=0.2, l=0.2, h=0.01, color=RED)
    set_point(ceiling, Point(z=0.2))
    pole = create_cylinder(radius=0.025, height=0.1, color=RED)
    set_point(pole, Point(z=0.15))

def visualize_learned_pours(learner, bowl_type='blue_bowl', cup_type='red_cup', num_steps=None):
    learner.query_type = REJECTION # BEST | REJECTION | STRADDLE
    learner.validity_learner = None

    world = create_world()
    #add_obstacles()
    #environment = get_bodies()

    world.bodies[bowl_type] = load_cup_bowl(bowl_type)
    world.bodies[cup_type] = load_cup_bowl(cup_type)
    feature = get_pour_feature(world, bowl_type, cup_type)
    draw_pose(get_pose(world.get_body(bowl_type)), length=0.2)
    # TODO: sample different sizes

    print('Feature:', feature)
    for parameter in learner.parameter_generator(world, feature, valid=False):
        handles = []
        print('Parameter:', parameter)
        valid = is_valid_pour(world, feature, parameter)
        score = learner.score(feature, parameter)
        x = learner.func.x_from_feature_parameter(feature, parameter)
        [prediction] = learner.predict_x(np.array([x]), noise=True)
        print('Valid: {} | Mean: {:.3f} | Var: {:.3f} | Score: {:.3f}'.format(
            valid, prediction['mean'], prediction['variance'], score))

        #fraction = rescale(clip(prediction['mean'], *DEFAULT_INTERVAL), DEFAULT_INTERVAL, new_interval=(0, 1))
        #color = (1 - fraction) * np.array(RED) + fraction * np.array(GREEN)
        #set_color(world.get_body(cup_type), apply_alpha(color, alpha=0.25))
        # TODO: overlay many cups at different poses
        bowl_from_pivot = get_bowl_from_pivot(world, feature, parameter)
        #handles.extend(draw_pose(bowl_from_pivot))
        handles.extend(draw_point(point_from_pose(bowl_from_pivot), color=BLACK))

        # TODO: could label bowl, cup dimensions
        path, _ = pour_path_from_parameter(world, feature, parameter, cup_yaw=0)
        for p1, p2 in safe_zip(path[:-1], path[1:]):
            handles.append(add_line(point_from_pose(p1), point_from_pose(p2), color=RED))

        if num_steps is not None:
            path = path[:num_steps]
        for i, pose in enumerate(path[::-1]):
            #step_handles = draw_pose(pose, length=0.1)
            #step_handles = draw_point(point_from_pose(pose), color=BLACK)
            set_pose(world.get_body(cup_type), pose)
            print('Step {}/{}'.format(i+1, len(path)))
            wait_for_user()
            #remove_handles(step_handles)
        remove_handles(handles)

##################################################

def visualize_vector_field(learner, bowl_type='blue_bowl', cup_type='red_cup',
                           num=500, delta=False, alpha=0.5):
    print(learner, len(learner.results))
    xx, yy, ww = learner.xx, learner.yy, learner.weights
    learner.hyperparameters = get_parameters(learner.model)
    print(learner.hyperparameters)
    learner.query_type = REJECTION  # BEST | REJECTION | STRADDLE

    world = create_world()
    world.bodies[bowl_type] = load_cup_bowl(bowl_type)
    world.bodies[cup_type] = load_cup_bowl(cup_type)
    feature = get_pour_feature(world, bowl_type, cup_type)
    set_point(world.bodies[cup_type], np.array([0.2, 0, 0]))

    # TODO: visualize training data as well
    # TODO: artificially limit training data to make a low-confidence region
    # TODO: visualize mean and var at the same time using intensity and hue
    print('Feature:', feature)
    with LockRenderer():
        #for parameter in islice(learner.parameter_generator(world, feature, valid=True), num):
        parameters = []
        while len(parameters) < num:
            parameter = learner.sample_parameter()
            # TODO: special color if invalid
            if is_valid_pour(world, feature, parameter):
                parameters.append(parameter)

    center, _ = approximate_as_prism(world.get_body(cup_type))
    bodies = []
    with LockRenderer():
        for parameter in parameters:
            path, _ = pour_path_from_parameter(world, feature, parameter)
            pose = path[0]
            body = create_cylinder(radius=0.001, height=0.02, color=apply_alpha(GREY, alpha))
            set_pose(body, multiply(pose, Pose(point=center)))
            bodies.append(body)

    #train_sizes = inclusive_range(10, 100, 1)
    #train_sizes = inclusive_range(10, 100, 10)
    #train_sizes = inclusive_range(100, 1000, 100)
    #train_sizes = [1000]
    train_sizes = [None]

    # training_poses = []
    # for result in learner.results[:train_sizes[-1]]:
    #     path, _ = pour_path_from_parameter(world, feature, result['parameter'])
    #     pose = path[0]
    #     training_poses.append(pose)

    # TODO: draw the example as well
    scores_per_size = []
    for train_size in train_sizes:
        if train_size is not None:
            learner.xx, learner.yy, learner.weights = xx[:train_size], yy[:train_size],  ww[:train_size]
            learner.retrain()
        X = np.array([learner.func.x_from_feature_parameter(feature, parameter) for parameter in parameters])
        predictions = learner.predict_x(X, noise=False) # Noise is just a constant
        scores_per_size.append([prediction['mean'] for prediction in predictions]) # mean | variance
        #scores_per_size.append([1./np.sqrt(prediction['variance']) for prediction in predictions])
        #scores_per_size.append([prediction['mean'] / np.sqrt(prediction['variance']) for prediction in predictions])
        #plt.hist(scores_per_size[-1])
        #plt.show()
        #scores_per_size.append([scipy.stats.norm.interval(alpha=0.95, loc=prediction['mean'],
        #                                                  scale=np.sqrt(prediction['variance']))[0]
        #                         for prediction in predictions]) # mean | variance
        # score = learner.score(feature, parameter)

    if delta:
        scores_per_size = [np.array(s2) - np.array(s1) for s1, s2 in zip(scores_per_size, scores_per_size[1:])]
        train_sizes = train_sizes[1:]

    all_scores = [score for scores in scores_per_size for score in scores]
    #interval = (min(all_scores), max(all_scores))
    interval = scipy.stats.norm.interval(alpha=0.95, loc=np.mean(all_scores), scale=np.std(all_scores))
    #interval = DEFAULT_INTERVAL
    print('Interval:', interval)
    print('Mean: {:.3f} | Stdev: {:.3f}'.format(np.mean(all_scores), np.std(all_scores)))

    #train_body = create_cylinder(radius=0.002, height=0.02, color=apply_alpha(BLACK, 1.0))
    for i, (train_size, scores) in enumerate(zip(train_sizes, scores_per_size)):
        print('Train size: {} | Average: {:.3f} | Min: {:.3f} | Max: {:.3f}'.format(
            train_size, np.mean(scores), min(scores), max(scores)))
        handles = []
        # TODO: visualize delta
        with LockRenderer():
            #if train_size is None:
            #    train_size = len(learner.results)
            #set_pose(train_body, multiply(training_poses[train_size-1], Pose(point=center)))
            #set_pose(world.bodies[cup_type], training_poses[train_size-1])
            for score, body in zip(scores, bodies):
                score = clip(score, *interval)
                fraction = rescale(score, interval, new_interval=(0, 1))
                color = interpolate_hue(fraction)
                #color = (1 - fraction) * np.array(RED) + fraction * np.array(GREEN) # TODO: convex combination
                set_color(body, apply_alpha(color, alpha))
                #set_pose(world.bodies[cup_type], pose)
                #draw_pose(pose, length=0.05)
                #handles.extend(draw_point(tform_point(pose, center), color=color))
                #extent = np.array([0, 0, 0.01])
                #start = tform_point(pose, center - extent/2)
                #end = tform_point(pose, center + extent/2)
                #handles.append(add_line(start, end, color=color, width=1))
        wait_for_duration(0.5)
        # TODO: test on boundaries
    wait_for_user()

##################################################

# python3 -m learn_tools.visualize_pours data/pour_19-11-22_13-08-55/gp_batch_k\=mlp_v\=true.pk3
# data/scoop_19-12-07_16-02-40/gp_batch_k=mlp_v=true.pk3

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('paths', nargs='*', help='Paths to the data.')
    args = parser.parse_args()

    if not args.paths:
        visualize_collected_pours(paths=BEST_DATASETS) # TRAIN_DATASETS | ACTIVE_DATASETS | TEST_DATASETS | BEST_DATASETS
    else:
        [path] = args.paths
        learner = read_pickle(path)
        visualize_learned_pours(learner)
        #visualize_vector_field(learner)

if __name__ == '__main__':
    main()


import random

# 指定a、b、c的值
import torch

from my_model import MyModel

a = 5
b = 7
c = 9
d = 6
# z = a * x + b * y + c
data = [(random.randint(1, 100), random.randint(1, 100), random.randint(1, 100)) for x, y, z in
        zip(range(1000), range(1000), range(1000))]
the_model = MyModel(3, 1)
the_model.load_state_dict(torch.load('best_model.pt'))
the_model.eval()
for x, y, z in data:
    w = a * x + b * y + c * z + d
    data = torch.tensor([x, y, z], dtype=torch.float32)
    pred_w = the_model(data)
    print(f'TRUE_W={w} | PRED_W={int(pred_w.item())}')

Solving equations using deep learning/make_data_and_val.py


"""
Radial profile of cooling time, mass weighted
"""
import yt
import ytree
import os
import sys
import matplotlib.pyplot as plt
import numpy as np

# macros
x = "seed1-bh-only-cooling-time-"
y = sys.argv[-1]  # plot  name
star_pos0 = [0.49030654, 0.50721054, 0.49178297] # found with smartstar-find.py

# load data
root_dir = "/home/sgordon/disk14/cirrus-runs-rsync/seed1-bh-only/270msun/BF-0.0078125"

# all ds
DD = []
ds1 = yt.load(os.path.join(root_dir, sys.argv[1])) # t = 124.760, before particle formation
label1 = sys.argv[1]
DD.append(ds1)
ds2 = yt.load(os.path.join(root_dir, sys.argv[2])) # later time
label2 = sys.argv[2]
DD.append(ds2)
if str(sys.argv[3]).startswith('DD'):
    ds3 = yt.load(os.path.join(root_dir, sys.argv[3])) # latest time
    label3 = sys.argv[3]
    DD.append(ds3)

# define dark_matter_mass field + add to all ds
def _t_cool_abs(field, data):
    return np.abs(data[("gas", "cooling_time")].in_units("s"))

for ds in DD:
    ds.add_field(("gas", "cooling_time_abs"), function=_t_cool_abs, units="s", sampling_type="cell") # need to define with units here.

""" Make Sphere of Most Massive Halo """

# Load seed1 merger tree of dataset (up to DD0118 in gas run)
a = ytree.load('/home/sgordon/disk14/pop3/gas+dm-L3/rockstar_halos/out_0.list')
a1 = ytree.load('/home/sgordon/disk14/pop3/gas+dm-L3/tree_810/tree_810.h5')
r_halo = a1[0]["virial_radius"].to('pc')
r = ds1.quan(r_halo.d, "pc") # virial radius

# Make initial sphere centred on the star at the time of formation with radius = 3 * virial radius
spheres = []
for i, ds in enumerate(DD):
    sphere = ds.sphere(star_pos0, 3*r)
    spheres.append(sphere)

""" Make Profile Plots weighted by cell mass """

all_fields = ["cell_mass", "matter_mass", "cooling_time", "cooling_time_abs"]
all_units = {"radius": "pc", "cell_mass": "Msun", "matter_mass": "Msun", "cooling_time_abs": "s", "cooling_time": "s"}

# Radial profile weighted by = 'cell_mass'
radial_profiles = []
for i, sp in enumerate(spheres):
    radial_profile = yt.create_profile(
        sp,
        "radius",
        all_fields,
        units=all_units,
        weight_field="cell_mass",
        accumulation=False,
        logs={"radius": True} # Set true for more bins
    )
    radial_profiles.append(radial_profile)

""" Plot """
plt.rcParams["font.family"] = "serif"
plt.rcParams['lines.linewidth'] = 2

font = {'family': 'serif',
        'color':  'black',
        'weight': 'normal',
        'size': 16,
        }

font2 = {'family': 'serif',
        'color':  'darkred',
        'weight': 'normal',
        'size': 14,
        }

plt.loglog(radial_profiles[0].x.value,
           radial_profiles[0][("gas","cooling_time_abs")],
           color='b', linestyle='solid', label=label1)
plt.loglog(radial_profiles[1].x.value,
           radial_profiles[1]["cooling_time_abs"],
           color='r', linestyle='solid', label=label2)
if str(sys.argv[3]).startswith('DD'):
    plt.loglog(radial_profiles[2].x[radial_profiles[2].used],
               radial_profiles[2]["cooling_time"][radial_profiles[2].used],
               color='r', linestyle='solid', label=label3)

plt.xlabel(r"r (pc)", fontdict=font)
plt.ylabel(r"t (s)", fontdict=font)

plt.legend(loc="lower left", fontsize=14,  ncol=1) # upper/lower

plt.tick_params(axis="x", which='minor', length = 4, direction="in")
plt.tick_params(axis="x", which='major', labelsize = 14,  width=2, length=7, direction="in")
# plt.yaxis.tick_right()
# plt.yaxis.set_label_position("right")
# plt.tick_params(axis="y", which='major', labelsize = 14)

plot_name = 'radial-profile-plot-' + str(x) + str(y) + '.pdf'
plt.savefig('plots/' + plot_name, dpi=100)
print("created ", plot_name)


import heapq
def solution(scoville,K):
    answer=0
    heapq.heapify(scoville)
    while scoville:
        x=heapq.heappop(scoville)
        if len(scoville)==0:
            if x<K:
                answer=-1
        else:
            if x<K:
                x1=heapq.heappop(scoville)
                y=x+(x1*2)
                answer+=1
                heapq.heappush(scoville,y)
    print(answer)
scoville=list(map(int,input().split()))
K=int(input())
solution(scoville,K)


"""
Custom dataset processing/generation functions should be added to this file
"""

import pathlib
from sklearn.datasets import fetch_20newsgroups

from tqdm.auto import tqdm

from .. import paths
from ..log import logger

__all__ = [
    'process_20_newsgroups'
]

def process_20_newsgroups(*, extract_dir='20_newsgroups',
                          metadata=None, unpack_dir=None,
                          opts={"subset":"all", "remove":"('headers', 'footers', 'quotes')"}):
    """
    Process 20 newsgroups into (data, target, metadata) format.

    Parameters
    ----------
    unpack_dir: path
        The interim parent directory the dataset files have been unpacked into.
    extract_dir: str
        Name of the directory of the unpacked files relative to the unpack_dir. Note that
    opts: dict default {"subset":"all", "remove"="('headers', 'footers', 'quotes')"}
        Options to pass to sklearn.datasets.fetch_20newsgroups.

    Returns
    -------
    A tuple:
        (data, target, additional_metadata)

    """
    if metadata is None:
        metadata = {}

    if unpack_dir is None:
        unpack_dir = paths['interim_data_path']
    else:
        unpack_dir = pathlib.Path(unpack_dir)
    data_dir = unpack_dir / f"{extract_dir}"

    news = fetch_20newsgroups(**opts)

    return news.data, news.target, metadata

{{ cookiecutter.repo_name }}/{{ cookiecutter.module_name }}/data/process_functions.py


def calculate(n):
    return sum([ n // (5**i) for i in range(1, 12) ])

def solve(n):
    lo=1
    hi=10**10
    while lo < hi:
        mid = (lo + hi) // 2
        result = calculate(mid)
        if result >= n:
            hi = mid
        else:
            lo = mid + 1

    check = calculate(lo) == n
    return lo if check else -1

print(solve(int(input())))


from setuptools import setup, find_packages
from codecs import open
from os import path

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

with open(path.join(here, 'README.lst'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='Oculi',
    version='0.1.0',
    description='Picamera control and motion detect frontend',
    long_description=long_description,
    author='Jun Tan',
    author_email='jforce716@gmail.com',
    classifier=[
        'Development Status :: 3 - Alpha',
        'Topic :: PiCamera :: Application :: Motion detect',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3.6'
    ],
    keywords='PiCamera, montion detect',
    packages=find_packages(where='./oculi'),
    install_requires=['flask', 'picamera', 'Pillow']
)


import torch
import torchtext
import pandas as pd
from natsort import natsorted
import os, pickle,random
from glob import glob

def get_latest_model(model_path):
    model_list = glob(os.path.join(model_path, '*.pth'))
    if len(model_list) <=0:
        print('No Model Found!!!')
        return None
    model_list = natsorted(model_list)

    return model_list[-1]

class DateDataset(torchtext.data.Dataset):
    def __init__(self, data_filename, fields, strip_flag=False, **kwargs):
        # fields: [('id', ID), ('text', TEXT), ('label', LABEL)]
        examples = []
        train_data = pd.read_csv(data_filename, header=None, delimiter='_' )
        if len(fields)==2:
            inputs, targets = train_data[0].tolist(), train_data[1].tolist()

            for line in zip(inputs,targets):
                if strip_flag: line = [l.strip() for l in line]
                examples.append(torchtext.data.Example.fromlist(line, fields))
        else:
            inputs = train_data[0].tolist()
            for line in inputs:
                if strip_flag: line = line.strip()
                examples.append(torchtext.data.Example.fromlist([line], fields))

        super(DateDataset, self).__init__(examples, fields, **kwargs)

def load_data(data_filename,vocab_filename, fields,strip_flag, train_flag=False,batch_size=32,device=None):
    if device is None: device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    train_data = DateDataset(data_filename, fields,strip_flag)

    TEXT = fields[0][1]

    # vocab --> pickle파일
    if (not (os.path.exists(vocab_filename))):
        TEXT.build_vocab(train_data, min_freq=1, max_size=100)   # build_vocab 단계를 거처야, 단어가 숫자로 mapping된다.
        # inference를 대비하여 vocab를 저장해 두어야 한다.
        with open(vocab_filename, 'wb') as f:
            pickle.dump(TEXT.vocab, f)

    else:
        with open(vocab_filename,'rb') as f:
            TEXT.vocab = pickle.load(f)

    vocab_size = len(TEXT.vocab)
    print('단어 집합의 크기 : {}'.format(vocab_size))

    print(dict(TEXT.vocab.stoi))  # 단어 dict   ----> inference를 대비해서 저장해 두어야 함.

    if not train_flag:
        return train_data, TEXT

    # vocab 생성 후, 쪼개기...
    train_data, valid_data = train_data.split(split_ratio=0.9,random_state=random.seed(100))
    print('train size: ', len(train_data), 'valid size: ', len(valid_data))

    train_loader = torchtext.data.Iterator(dataset=train_data, batch_size = batch_size,shuffle=True,device=device)
    valid_loader = torchtext.data.Iterator(dataset=valid_data, batch_size = len(valid_data),shuffle=False,device=device)

    return train_loader, valid_loader, TEXT

def load_data_test():
    #TEXT = torchtext.data.Field(sequential=True, tokenize=list,batch_first=True,include_lengths=False,lower=True)
    TEXT = torchtext.data.Field(sequential=True, tokenize=list,batch_first=False,include_lengths=False,init_token='<sos>',eos_token='<eos>',lower=True)  # src, target 모두에 sos,eos가 붇는다.
    fields = [('src',TEXT),('target',TEXT)]

    train_loader, valid_loader, TEXT = load_data(data_filename='date.txt',vocab_filename = 'vocab.pickle', fields=fields,
                                                 strip_flag= True,train_flag=True,batch_size=4)

    vocab_size = len(TEXT.vocab)

    for i, d in enumerate(train_loader):
        print(d.src.shape, d.target.shape, d.src, d.target)
        if i>2: break

if __name__ == '__main__':
    load_data_test()


from itertools import chain

from lxml.builder import ElementMaker
try:
    from django.core.urlresolvers import reverse
except ImportError:
    from django.urls import reverse
from django.shortcuts import get_object_or_404

from eoxserver.core.config import get_eoxserver_config
from eoxserver.core.util.xmltools import (
    XMLEncoder, NameSpace, NameSpaceMap
)
from eoxserver.resources.coverages import models
from eoxserver.services.opensearch.formats import get_formats
from eoxserver.services.opensearch.extensions import get_extensions
from eoxserver.services.opensearch.config import OpenSearchConfigReader

class OpenSearch11DescriptionEncoder(XMLEncoder):
    content_type = "application/opensearchdescription+xml"

    def __init__(self, search_extensions):
        ns_os = NameSpace("http://a9.com/-/spec/opensearch/1.1/", None)
        self.ns_param = ns_param = NameSpace(
            "http://a9.com/-/spec/opensearch/extensions/parameters/1.0/",
            "parameters"
        )
        ns_atom = NameSpace("http://www.w3.org/2005/Atom", "atom")
        nsmap = NameSpaceMap(ns_os, ns_param, ns_atom)
        for search_extension in search_extensions:
            nsmap.add(search_extension.namespace)
        self.OS = ElementMaker(namespace=ns_os.uri, nsmap=nsmap)
        self.PARAM = ElementMaker(namespace=ns_param.uri, nsmap=nsmap)
        self.ATOM = ElementMaker(namespace=ns_atom.uri, nsmap=nsmap)
        self.search_extensions = search_extensions

    def encode_description(self, request, collection, result_formats):
        """ Encode an OpenSearch 1.1 description document.
        """
        OS = self.OS
        description = OS("OpenSearchDescription",
            OS("ShortName",
                collection.identifier if collection is not None else ""
            ),
            OS("Description")
        )
        for method in ("GET", "POST"):
            description.extend([
                self.encode_url(
                    request, collection, result_format, method
                )
                for result_format in result_formats
            ])
        description.extend([
            OS("Contact"),
            OS("Tags", "CEOS-OS-BP-V1.1/L1"),
            OS("LongName"),
            OS("Developer"),
            OS("Attribution"),
            OS("SyndicationRight", "open"),
            OS("AdultContent"),
            OS("Language"),
            OS("InputEncoding"),
            OS("OutputEncoding")
        ])
        return description

    def encode_url(self, request, collection, result_format, method):
        """ Encode a single opensearch URL, either for a specific collection, or
            the whole service.
        """
        if collection is not None:
            search_url = reverse("opensearch:collection:search",
                kwargs={
                    "collection_id": collection.identifier,
                    "format_name": result_format.name
                }
            )
        else:
            search_url = reverse("opensearch:search",
                kwargs={
                    "format_name": result_format.name
                }
            )

        conf = OpenSearchConfigReader(get_eoxserver_config())
        search_url = request.build_absolute_uri(search_url)

        default_parameters = (
            dict(name="q", type="searchTerms", profiles=[
            ]),
            dict(name="count", type="count", min=0, max=conf.max_count),
            dict(name="startIndex", type="startIndex", min=0),
        )

        parameters = list(chain(default_parameters, *[
            [
                dict(parameter, **{"namespace": search_extension.namespace})
                for parameter in search_extension.get_schema(
                    collection,
                    models.Collection if collection is None else models.Product
                )
            ] for search_extension in self.search_extensions
        ]))

        query_template = "&".join(
            "%s={%s%s%s%s}" % (
                parameter["name"],
                parameter["namespace"].prefix
                if "namespace" in parameter else "",
                ":" if "namespace" in parameter else "",
                parameter["type"],
                "?" if parameter.get("optional", True) else ""
            )
            for parameter in parameters
        )

        url = self.OS("Url", *[
                self.encode_parameter(parameter, parameter.get("namespace"))
                for parameter in parameters
            ],
            type=result_format.mimetype,
            template="%s?%s" % (search_url, query_template)
            if method == "GET" else search_url,
            rel="results" if collection is not None else "collection", ** {
                self.ns_param("method"): method,
                self.ns_param("enctype"): "application/x-www-form-urlencoded",
                "indexOffset": "0"
            }
        )

        return url

    def encode_parameter(self, parameter, namespace):
        options = parameter.pop("options", [])
        profiles = parameter.pop("profiles", [])

        attributes = {"name": parameter["name"]}
        if namespace:
            attributes["value"] = "{%s:%s}" % (
                namespace.prefix, parameter.pop("type")
            )
        else:
            attributes["value"] = "{%s}" % parameter.pop("type")

        if 'min' in parameter:
            attributes['minInclusive'] = str(parameter['min'])

        if 'max' in parameter:
            attributes['maxInclusive'] = str(parameter['max'])

        pattern = parameter.get("pattern")
        if pattern:
            attributes["pattern"] = pattern

        return self.PARAM("Parameter", *[
            self.PARAM("Option", value=option, label=option)
            for option in options
        ] + [
            self.ATOM("link",
                rel="profile", href=profile["href"], title=profile["title"]
            )
            for profile in profiles
        ], minimum="0" if parameter.get("optional", True) else "1", maximum="1",
            **attributes
        )

class OpenSearch11DescriptionHandler(object):
    def handle(self, request, collection_id=None):
        collection = None
        if collection_id:
            collection = get_object_or_404(models.Collection,
                identifier=collection_id
            )

        encoder = OpenSearch11DescriptionEncoder([
            extension() for extension in get_extensions()
        ])
        return (
            encoder.serialize(
                encoder.encode_description(
                    request, collection, [format_() for format_ in get_formats()]
                )
            ),
            encoder.content_type
        )


"""Implements the Perceptron & Adaline Learning Algorithm
Author: Rajan Subramanian
"""

from __future__ import annotations

from typing import Optional

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from marketlearn.learning.linear_models.base import NeuralBase
from numpy.typing import NDArray

class Perceptron(NeuralBase):
    """Implements the Perceptron Learning Algorithm"""

    def __init__(self, eta: float = 0.01, niter: int = 50, bias: bool = True):
        self.eta = eta
        self.niter = niter
        self.bias = bias
        self.thetas = None
        self.weights = None
        self.degree = 1

    def _fit_batch(self, X: NDArray, y: NDArray) -> Perceptron:
        """fits training data

        Parameters
        ----------
        X : np.ndarray, shape=(n_samples, p_features)
            n_samples is number of instances i.e rows
            p_features is number of features (dimension of data)
        y : np.ndarray
            response variable

        Returns
        -------
        Perception
            object with fitted parameters
        """
        # Add bias unit to design matrix
        degree, bias = self.degree, self.bias
        X = self.make_polynomial(X, degree, bias)

        # Initialize weights to 0
        self.thetas = np.zeros(X.shape[1])
        weights = {}
        index = -1
        converged = False

        while not converged:
            index += 1
            prev_weights = self.thetas.copy()
            # for each example in training set
            for xi, target in zip(X, y):
                # update weights if there are misclassifications
                if target != self.predict(xi):
                    self.thetas += target * xi

            weights[index] = self.thetas.copy()
            if (prev_weights == self.thetas).all():
                converged = True
        self.weights = pd.DataFrame.from_dict(
            weights, orient="index", columns=["bias", "weight1", "weight2"]
        )
        return self

    def _fit_online(self, X: NDArray, y: NDArray) -> Perceptron:
        R = (np.sum(np.abs(X) ** 2, axis=-1) ** (0.5)).max()
        bias = 0
        # Initialize weights to 0
        self.thetas = np.zeros(X.shape[1] + 1)
        mistakes = 0
        mistakes_from_previous_iteration = 0
        while True:
            for xi, target in zip(X, y):
                if target * (self.net_input(xi, self.thetas[1:]) + bias) <= 0:
                    self.thetas[1:] += self.eta * target * xi
                    bias += self.eta * target * R * R
                    mistakes += 1
            if mistakes_from_previous_iteration == mistakes:
                break
            mistakes_from_previous_iteration = mistakes

        self.thetas[0] = bias
        return self

    def fit(self, X: NDArray, y: NDArray, learner="batch") -> Perceptron:
        msg = "Incorrect learner type, supports one of batch or online"
        if learner == "batch":
            return self._fit_batch(X, y)
        elif learner == "online":
            return self._fit_online(X, y)
        else:
            raise LookupError(msg)

    def predict(self, X: NDArray, thetas: Optional[NDArray] = None) -> int:
        """Activation function to determine if neuron should fire or not

        Parameters
        ----------
        X : np.ndarray
            design matrix that includes the bias
        thetas : Union[np.ndarray, None], optional
            weights from fitting, by default None

        Returns
        -------
        np.ndarray
            predictions
        """
        if thetas is None:
            return 1 if self.net_input(X, self.thetas) >= 0 else -1
        return 1 if self.net_input(X, thetas) >= 0 else -1

    def plot_decision_boundary(self, inputs, targets, weights):
        for input, target in zip(inputs, targets):
            plt.plot(input[0], input[1], "ro" if (target == 1.0) else "bo")

        slope = -weights[1] / weights[2]
        intercept = -weights[0] / weights[2]
        for i in np.linspace(np.amin(inputs[:, :1]), np.amax(inputs[:, :1])):
            y = (slope * i) + intercept
            plt.plot(i, y, "ko")

class Adaline(NeuralBase):
    """Implements the Adaptive Linear Neuron by Bernard Widrow
    via Batch Gradient Descent

    Notes:
        - The cost function is given by J(w) = 1/2 ||(yi - yhat)||
    """

    def __init__(self, eta: float = 0.01, niter: int = 50, bias: bool = True):
        """Default Constructor used to initialize the Adaline model"""
        self.eta = eta
        self.niter = niter
        self.cost = []
        self.bias = bias
        self.thetas = None
        self.degree = 1

    def fit(self, X: NDArray, y: NDArray) -> Adaline:
        """fits training data via batch gradient descent

        Parameters
        ----------
        X : np.ndarray, shape=(n_samples, p_features)
            n_samples is number of instances i.e rows
            p_features is number of features (dimension of data)
        y : np.ndarray
            response variable

        Returns
        -------
        Perception
            object with fitted parameters
        """
        # add bias + weights for each neuron
        self.thetas = np.zeros(shape=1 + X.shape[1])

        # Add bias unit to design matrix
        degree = self.degree
        X = self.make_polynomial(X, degree=degree, bias=True)

        for _ in range(self.niter):
            error = y - self.activation(self.net_input(X, self.thetas))
            self.thetas += self.eta * np.transpose(X).dot(error)
            self.cost.append((error.transpose() @ error) / 2.0)
        return self

    def activation(self, X: NDArray) -> NDArray:
        """Computes the linear activation function
        given by f(w'x) = w'x

        Parameters
        ----------
        X : np.ndarray
            output from the netinput function

        Returns
        -------
        np.ndarray
            activation function
        """
        return X

    def predict(self, X: NDArray, thetas: Optional[NDArray]) -> float:
        """Computes the class label after activation

        Parameters
        ----------
        X : np.ndarray
            [description]
        thetas : Union[np.ndarray, None], optional
            [description], by default None
        """
        if thetas is None:
            if self.activation(self.net_input(X, self.thetas)) >= 0.0:
                return 1
            else:
                return -1
        else:
            return 1 if self.activation(self.net_input(X, thetas)) >= 0.0 else -1


"""
This module handles daily brief processing.
"""

import logging
import datetime
from typing import Dict, Any

import pyttsx3

from server.api.weather import fetch_weather
from server.api.news import fetch_news_headlines
from server.api.covid import fetch_covid_data

__speech_engine = pyttsx3.init()

def daily_brief(alarm_info: Dict[str, Any]):
    """
    Gives the user a brief of the current weather, the top news, and the local covid infection rate.
    """

    logging.info("Daily brief initiated on %s.", datetime.datetime.now())

    alarm_title = alarm_info["title"]

    brief_message = f"""
    Hello! This is a scheduled daily brief titled: {alarm_title}.
    {__covid_brief()}
    {__weather_brief() if alarm_info["include_weather"] else ""}
    {__news_brief() if alarm_info["include_news"] else ""}
    This is the end of your briefing. Have a nice day.
    """

    logging.info("brief message: %s", brief_message)
    __speech_engine.say(brief_message)
    __speech_engine.runAndWait()

def __covid_brief() -> str:
    """
    Generates a brief message about the latest covid19 data.
    """

    try:
        (
            is_latest_covid_data_available,
            _,
            new_cases,
            cumulative_cases,
            new_deaths,
            cumulative_deaths,
        ) = fetch_covid_data()

        return f"""
        First, some Covid-19 update.
        {'Today, ' if is_latest_covid_data_available else 'Latest data is not available, so previous data will be recapped.'}
        In England, there are {new_cases} number of new cases,
        and unfortunately {new_deaths} people lost their battle against Covid19.
        In total, there are {cumulative_cases} number of cases,
        and {cumulative_deaths} lives are lost in this pandemic.
        """
    except:
        return "Unfortunately an error occurred when getting latest covid data."

def __weather_brief() -> str:
    """
    Generates a brief message about the current weather.
    """

    weather = fetch_weather(lat=50.718410, long=-3.533899)

    return f"""
    Currently in your location, expect {weather['weather'][0]['description']}.
    The temperature is {weather['main']['temp']}.
    """

def __news_brief() -> str:
    """
    Generates a brief message of latest news headlines.
    """

    news = fetch_news_headlines(country="gb")

    if len(news) == 0:
        return "There are no top news for you right now."

    return "Also, here are some top news headlines for you.\n" + "\n".join(
        [f"{article['title']}; " for article in news]
    )


# Future developments can include getting total wallet (including tokens) or tracking multiple wallets
import requests

params = {
    'collection': 'the-wanderers',
    'limit': 1
}

r = requests.get("https://api.opensea.io/api/v1/assets", params=params)

print(r.json())
# def current_price():
#
# if __name__ == "__main__":
#     print("Hello World")
# input opensea link or api call results
# pull all NFTs from a single wallet
# create webapp to list individual prices of each NFT and total price at end
# compare last sold price and current lowest listing price and take the min of both values
# return min