import logging
from metadrive.constants import Semantics
import math
from typing import List, Dict

from panda3d.bullet import BulletBoxShape, BulletGhostNode
from panda3d.core import Vec3, LQuaternionf, Vec4, TextureStage, RigidBodyCombiner, \
    SamplerState, NodePath, Texture, Material

from metadrive.base_class.base_object import BaseObject
from metadrive.component.lane.abs_lane import AbstractLane
from metadrive.component.lane.point_lane import PointLane
from metadrive.component.road_network.node_road_network import NodeRoadNetwork
from metadrive.component.road_network.road import Road
from metadrive.constants import MetaDriveType, CamMask, PGLineType, PGLineColor, DrivableAreaProperty
from metadrive.engine.asset_loader import AssetLoader
from metadrive.engine.core.physics_world import PhysicsWorld
from metadrive.utils.coordinates_shift import panda_vector, panda_heading
from metadrive.utils.math import norm

logger = logging.getLogger(__name__)

class BaseBlock(BaseObject, DrivableAreaProperty):
    """
    Block is a driving area consisting of several roads
    Note: overriding the _sample() function to fill block_network/respawn_roads in subclass
    Call Block.construct_block() to add it to world
    """
    ID = "B"

    def __init__(
        self, block_index: int, global_network: NodeRoadNetwork, random_seed, ignore_intersection_checking=False
    ):
        super(BaseBlock, self).__init__(str(block_index) + self.ID, random_seed, escape_random_seed_assertion=True)
        # block information
        assert self.ID is not None, "Each Block must has its unique ID When define Block"
        assert len(self.ID) == 1, "Block ID must be a character "

        self.block_index = block_index
        self.ignore_intersection_checking = ignore_intersection_checking

        # each block contains its own road network and a global network
        self._global_network = global_network
        self.block_network = self.block_network_type()

        # a bounding box used to improve efficiency x_min, x_max, y_min, y_max
        self._bounding_box = None

        # used to spawn npc
        self._respawn_roads = []
        self._block_objects = None

        if self.render and not self.use_render_pipeline:
            self.ts_color = TextureStage("color")
            self.ts_normal = TextureStage("normal")
            self.ts_normal.setMode(TextureStage.M_normal)

            # Only maintain one copy of asset
            self.road_texture = self.loader.loadTexture(AssetLoader.file_path("textures", "sci", "new_color.png"))
            self.road_normal = self.loader.loadTexture(AssetLoader.file_path("textures", "sci", "normal.jpg"))
            self.road_texture.set_format(Texture.F_srgb)
            self.road_normal.set_format(Texture.F_srgb)
            self.road_texture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
            self.road_texture.setAnisotropicDegree(8)

            # # continuous line
            # self.lane_line_model = self.loader.loadModel(AssetLoader.file_path("models", "box.bam"))
            # self.lane_line_model.setPos(0, 0, -DrivableAreaProperty.LANE_LINE_GHOST_HEIGHT / 2)
            self.lane_line_texture = self.loader.loadTexture(AssetLoader.file_path("textures", "sci", "floor.jpg"))
            # self.lane_line_model.setScale(DrivableAreaProperty.STRIPE_LENGTH*4,
            #                                    DrivableAreaProperty.LANE_LINE_WIDTH,
            #                                    DrivableAreaProperty.LANE_LINE_THICKNESS)
            # # self.lane_line_normal = self.loader.loadTexture(
            # #     AssetLoader.file_path("textures", "sci", "floor_normal.jpg"))
            # # self.lane_line_texture.set_format(Texture.F_srgb)
            # # self.lane_line_normal.set_format(Texture.F_srgb)
            # self.lane_line_model.setTexture(self.ts_color, self.lane_line_texture)
            # # self.lane_line_model.setTexture(self.ts_normal, self.lane_line_normal)
            #
            # # # broken line
            # self.broken_lane_line_model = self.loader.loadModel(AssetLoader.file_path("models", "box.bam"))
            # self.broken_lane_line_model.setScale(DrivableAreaProperty.STRIPE_LENGTH,
            #                                           DrivableAreaProperty.LANE_LINE_WIDTH,
            #                                           DrivableAreaProperty.LANE_LINE_THICKNESS)
            # self.broken_lane_line_model.setPos(0, 0, -DrivableAreaProperty.LANE_LINE_GHOST_HEIGHT / 2)
            # self.broken_lane_line_model.setTexture(self.ts_color, self.lane_line_texture)

            # side
            self.side_texture = self.loader.loadTexture(AssetLoader.file_path("textures", "sidewalk", "color.png"))
            self.side_texture.set_format(Texture.F_srgb)
            self.side_texture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
            self.side_texture.setAnisotropicDegree(8)
            self.side_normal = self.loader.loadTexture(AssetLoader.file_path("textures", "sidewalk", "normal.png"))
            self.side_normal.set_format(Texture.F_srgb)
            self.sidewalk = self.loader.loadModel(AssetLoader.file_path("models", "box.bam"))
            self.sidewalk.setTwoSided(False)
            self.sidewalk.setTexture(self.ts_color, self.side_texture)
            # self.sidewalk = self.loader.loadModel(AssetLoader.file_path("models", "output.egg"))
            # self.sidewalk.setTexture(self.ts_normal, self.side_normal)

    def _sample_topology(self) -> bool:
        """
        Sample a new topology to fill self.block_network
        """
        raise NotImplementedError

    def construct_block(
        self,
        root_render_np: NodePath,
        physics_world: PhysicsWorld,
        extra_config: Dict = None,
        no_same_node=True,
        attach_to_world=True
    ) -> bool:
        """
        Randomly Construct a block, if overlap return False
        """
        self.sample_parameters()

        if not isinstance(self.origin, NodePath):
            self.origin = NodePath(self.name)
        # else:
        #     print("Origin already exists: ", self.origin)

        self._block_objects = []
        if extra_config:
            assert set(extra_config.keys()).issubset(self.PARAMETER_SPACE.parameters), \
                "Make sure the parameters' name are as same as what defined in pg_space.py"
            raw_config = self.get_config(copy=True)
            raw_config.update(extra_config)
            self.update_config(raw_config)
        self._clear_topology()
        success = self._sample_topology()
        self._global_network.add(self.block_network, no_same_node)

        self._create_in_world()
        self.attach_to_world(root_render_np, physics_world)

        if not attach_to_world:
            self.detach_from_world(physics_world)

        return success

    def destruct_block(self, physics_world: PhysicsWorld):
        self._clear_topology()
        self.detach_from_world(physics_world)

        self.origin.removeNode()
        self.origin = None

        self.dynamic_nodes.clear()
        self.static_nodes.clear()
        for obj in self._block_objects:
            obj.destroy()
        self._block_objects = None

    def construct_from_config(self, config: Dict, root_render_np: NodePath, physics_world: PhysicsWorld):
        success = self.construct_block(root_render_np, physics_world, config)
        return success

    def get_respawn_roads(self):
        return self._respawn_roads

    def get_respawn_lanes(self):
        """
        return a 2-dim array [[]] to keep the lane index
        """
        ret = []
        for road in self._respawn_roads:
            lanes = road.get_lanes(self.block_network)
            ret.append(lanes)
        return ret

    def get_intermediate_spawn_lanes(self):
        """Return all lanes that can be used to generate spawn intermediate vehicles."""
        raise NotImplementedError()

    def _add_one_respawn_road(self, respawn_road: Road):
        assert isinstance(respawn_road, Road), "Spawn roads list only accept Road Type"
        self._respawn_roads.append(respawn_road)

    def _clear_topology(self):
        if len(self._global_network.graph.keys()) > 0:
            self._global_network -= self.block_network
        self.block_network.graph.clear()
        self.PART_IDX = 0
        self.ROAD_IDX = 0
        self._respawn_roads.clear()

    """------------------------------------- For Render and Physics Calculation ---------------------------------- """

    def _create_in_world(self, skip=False):
        """
        Create NodePath and Geom node to perform both collision detection and render

        Note: Override the create_in_world() function instead of this one, since this method severing as a wrapper to
        help improve efficiency
        """
        self.lane_line_node_path = NodePath(RigidBodyCombiner(self.name + "_lane_line"))
        self.sidewalk_node_path = NodePath(RigidBodyCombiner(self.name + "_sidewalk"))
        self.lane_node_path = NodePath(RigidBodyCombiner(self.name + "_lane"))
        self.lane_vis_node_path = NodePath(RigidBodyCombiner(self.name + "_lane_vis"))

        self.sidewalk_node_path.setTag("type", Semantics.SIDEWALK.label)
        self.lane_vis_node_path.setTag("type", Semantics.ROAD.label)
        self.lane_line_node_path.setTag("type", Semantics.LANE_LINE.label)

        if skip:  # for debug
            pass
        else:
            self.create_in_world()

        self.lane_line_node_path.flattenStrong()
        self.lane_line_node_path.node().collect()

        self.sidewalk_node_path.flattenStrong()
        self.sidewalk_node_path.node().collect()
        self.sidewalk_node_path.hide(CamMask.ScreenshotCam)

        # only bodies reparent to this node
        self.lane_node_path.flattenStrong()
        self.lane_node_path.node().collect()

        self.lane_vis_node_path.flattenStrong()
        self.lane_vis_node_path.node().collect()
        self.lane_vis_node_path.hide(CamMask.DepthCam | CamMask.ScreenshotCam | CamMask.SemanticCam)

        self.origin.hide(CamMask.Shadow)

        self.sidewalk_node_path.reparentTo(self.origin)
        self.lane_line_node_path.reparentTo(self.origin)
        self.lane_node_path.reparentTo(self.origin)
        self.lane_vis_node_path.reparentTo(self.origin)
        try:
            self._bounding_box = self.block_network.get_bounding_box()
        except:
            if len(self.block_network.graph) > 0:
                logging.warning("Can not find bounding box for it")
            self._bounding_box = None, None, None, None

        self._node_path_list.append(self.sidewalk_node_path)
        self._node_path_list.append(self.lane_line_node_path)
        self._node_path_list.append(self.lane_node_path)
        self._node_path_list.append(self.lane_vis_node_path)

    def create_in_world(self):
        """
        Create lane in the panda3D world
        """
        raise NotImplementedError

    def add_body(self, physics_body):
        raise DeprecationWarning(
            "Different from common objects like vehicle/traffic sign, Block has several bodies!"
            "Therefore, you should create BulletBody and then add them to self.dynamics_nodes "
            "manually. See in construct() method"
        )

    def get_state(self) -> Dict:
        """
        The record of Block type is not same as other objects
        """
        return {}

    def set_state(self, state: Dict):
        """
        Block type can not set state currently
        """
        pass

    def _add_lane_line(self, lane: AbstractLane, colors: List[Vec4], contruct_two_side=True):
        raise DeprecationWarning("Leave for argoverse using")
        if isinstance(lane, PointLane):
            parent_np = self.lane_line_node_path
            lane_width = lane.width_at(0)
            for c, i in enumerate([-1, 1]):
                line_color = colors[c]
                acc_length = 0
                if lane.line_types[c] == PGLineType.CONTINUOUS:
                    for segment in lane.segment_property:
                        lane_start = lane.position(acc_length, i * lane_width / 2)
                        acc_length += segment["length"]
                        lane_end = lane.position(acc_length, i * lane_width / 2)
                        middle = (lane_start + lane_end) / 2
                        self._add_lane_line2bullet(
                            lane_start, lane_end, middle, parent_np, line_color, lane.line_types[c]
                        )

    def _add_box_body(self, lane_start, lane_end, middle, parent_np: NodePath, line_type, line_color):
        raise DeprecationWarning("Useless, currently")
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        if PGLineType.prohibit(line_type):
            node_name = MetaDriveType.LINE_SOLID_SINGLE_WHITE if line_color == PGLineColor.GREY else MetaDriveType.LINE_SOLID_SINGLE_YELLOW
        else:
            node_name = MetaDriveType.BROKEN_LINE
        body_node = BulletGhostNode(node_name)
        body_node.set_active(False)
        body_node.setKinematic(False)
        body_node.setStatic(True)
        body_np = parent_np.attachNewNode(body_node)

        self._node_path_list.append(body_np)

        shape = BulletBoxShape(
            Vec3(length / 2, DrivableAreaProperty.LANE_LINE_WIDTH / 2, DrivableAreaProperty.LANE_LINE_GHOST_HEIGHT)
        )
        body_np.node().addShape(shape)
        mask = DrivableAreaProperty.CONTINUOUS_COLLISION_MASK if line_type != PGLineType.BROKEN else DrivableAreaProperty.BROKEN_COLLISION_MASK
        body_np.node().setIntoCollideMask(mask)
        self.static_nodes.append(body_np.node())

        body_np.setPos(panda_vector(middle, DrivableAreaProperty.LANE_LINE_GHOST_HEIGHT / 2))
        direction_v = lane_end - lane_start
        # theta = -numpy.arctan2(direction_v[1], direction_v[0])
        theta = panda_heading(math.atan2(direction_v[1], direction_v[0]))

        body_np.setQuat(LQuaternionf(math.cos(theta / 2), 0, 0, math.sin(theta / 2)))

    @property
    def block_network_type(self):
        """
        There are two type of road network to describe the relation of all lanes, override this func to assign one when
        you are building your own block.
        return: roadnetwork
        """
        raise NotImplementedError

    def destroy(self):
        if self.block_network is not None:
            self.block_network.destroy()
            if self.block_network.graph is not None:
                self.block_network.graph.clear()
            self.block_network = None
        self.PART_IDX = 0
        self.ROAD_IDX = 0
        self._respawn_roads.clear()
        self._global_network = None
        super(BaseBlock, self).destroy()

    def __del__(self):
        self.destroy()
        logger.debug("{} is being deleted.".format(type(self)))

    @property
    def bounding_box(self):
        return self._bounding_box


from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, BLOB, DateTime

base = declarative_base()

class ConfigNmap(base):
    __tablename__ = 'config_nmap'
    id = Column(Integer, primary_key=True)
    property = Column(String(255), nullable=False)
    value = Column(String(255), nullable=False)

class NmapReportsDHCPDiscover(base):
    __tablename__ = 'nmap_reports_dhcp_discover'
    id = Column(Integer, primary_key=True)
    time = Column(DateTime)
    report = Column(BLOB)

class NmapReportsSnifferDetect(base):
    __tablename__ = 'nmap_reports_sniffer_detect'
    id = Column(Integer, primary_key=True)
    time = Column(DateTime)
    report = Column(BLOB)

class NmapDiff(base):
    __tablename__ = 'nmap_diff'
    id = Column(Integer, primary_key=True)
    result = Column(BLOB)


import mcpi.minecraft as minecraft
import math

craft = minecraft.Minecraft.create()
cor = craft.player.getTilePos()

x=cor.x+2
y=cor.y
z=cor.z+2

# Создание модели зеркала (отражающей поверхности)
craft.setBlocks(x-5, y-1,z-5, x+10, y-1, z+5, 79)

# падающий луч света
for i in range(20):

    y1 = 0.5*i
    craft.setBlock(x+i, y+y1,z, 35,1)

# Отражённый луч света
for i in range(20):
    y1 = 0.5*i
    craft.setBlock(x-i, y+y1,z, 35,3)


from pathlib import Path
from experimaestro.compat import cached_property
import importlib
import os
import hashlib
import logging
import inspect
import json
from experimaestro.mkdocs.metaloader import Module
import pkg_resources
from typing import Iterable, Iterator, List, Dict
from .utils import CachedFile, downloadURL
from .settings import UserSettings, Settings

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from datamaestro.definitions import AbstractDataset

class Compression:
    @staticmethod
    def extension(definition):
        if not definition:
            return ""
        if definition == "gzip":
            return ".gz"

        raise Exception("Not handled compression definition: %s" % definition)

class Context:
    """
    Represents the application context
    """

    MAINDIR = Path(os.environ.get("DATAMAESTRO_DIR", "~/datamaestro")).expanduser()

    INSTANCE = None

    """Main settings"""

    def __init__(self, path: Path = None):
        assert not Context.INSTANCE

        Context.INSTANCE = self
        self._path = path or Context.MAINDIR
        self._dpath = Path(__file__).parents[1]
        self._repository = None
        # self.registry = Registry(self.datapath / "registry.yaml")
        self.keep_downloads = False
        self.traceback = False

        # Read global preferences
        self.settings = Settings.load(self._path / "settings.json")

        # Read user preferences
        path = Path("~").expanduser() / ".config" / "datamaestro" / "user.json"
        self.user_settings = UserSettings.load(path)

    @staticmethod
    def instance():
        if Context.INSTANCE is None:
            Context.INSTANCE = Context()
        return Context.INSTANCE

    @staticmethod
    def remote(host, pythonpath, datapath=None):
        """Create a remote context by connecting to a given host"""
        from experimaestro.rpyc import client

        client = client(hostname=host, pythonpath=pythonpath).__enter__()
        context = client.connection.modules.datamaestro.context.Context(datapath)
        return context

    @staticmethod
    def frompath(path: Path):
        context = Context.instance()

        class ContextManager:
            def __enter__(self):
                self.previous = Context.INSTANCE
                return context

            def __exit__(self, exc_type, exc_val, exc_tb):
                Context.INSTANCE = self.previous

        return ContextManager()

    @property
    def datapath(self):
        return self._path.joinpath("data")

    @property
    def cachepath(self) -> Path:
        return self._path.joinpath("cache")

    @cached_property
    def repositorymap(self) -> Dict[str, "Repository"]:
        return {
            repository.basemodule(): repository for repository in self.repositories()
        }

    def repositories(self) -> Iterable["Repository"]:
        """Returns an iterator over repositories"""
        for entry_point in pkg_resources.iter_entry_points("datamaestro.repositories"):
            yield entry_point.load().instance()

    def repository(self, repositoryid):
        if repositoryid is None:
            return None

        l = [
            x
            for x in pkg_resources.iter_entry_points(
                "datamaestro.repositories", repositoryid
            )
        ]
        if not l:
            raise Exception("No datasets repository named %s", repositoryid)
        if len(l) > 1:
            raise Exception(
                "Too many datasets repository named %s (%d)" % (repositoryid, len(l))
            )
        return l[0].load()(self)

    @property
    def running_test(self):
        return "PYTEST_CURRENT_TEST" in os.environ

    def datasets(self):
        """Returns an iterator over all files"""
        for repository in self.repositories():
            for dataset in repository:
                yield dataset

    def dataset(self, datasetid) -> "AbstractDataset":
        """Get a dataset by ID"""
        for repository in self.repositories():
            dataset = repository.search(datasetid)
            if dataset is not None:
                return dataset

        raise Exception("Dataset {} not found".format(datasetid))

    def downloadURL(self, url, size: int = None):
        """Downloads an URL

        Args:
            url (str): The URL to download
            size (str): The size if known (in bytes)
        """

        self.cachepath.mkdir(exist_ok=True)

        def getPaths(hasher):
            """Returns a cache file path"""
            path = self.cachepath.joinpath(hasher.hexdigest())
            urlpath = path.with_suffix(".url")
            dlpath = path.with_suffix(".dl")

            if urlpath.is_file():
                if urlpath.read_text() != url:
                    # TODO: do something better
                    raise Exception(
                        "Cached URL hash does not match. Clear cache to resolve"
                    )
            return urlpath, dlpath

        hasher = hashlib.sha256(json.dumps(url).encode("utf-8"))

        urlpath, dlpath = getPaths(hasher)
        urlpath.write_text(url)

        if dlpath.is_file():
            logging.debug("Using cached file %s for %s", dlpath, url)
        else:

            logging.info("Downloading %s", url)
            tmppath = dlpath.with_suffix(".tmp")

            downloadURL(url, tmppath, tmppath.is_file(), size=size)

            # Now, rename to original
            tmppath.rename(dlpath)

        return CachedFile(dlpath, keep=self.keep_downloads, others=[urlpath])

    def ask(self, question: str, options: Dict[str, str]):
        """Ask a question to the user"""
        print(question)
        answer = None
        while answer not in options:
            answer = input().strip().lower()
        return options[answer]

class ResolvablePath:
    """An object than can be resolved into a Path"""

    @staticmethod
    def resolve(context, path):
        if isinstance(path, ResolvablePath):
            return path(context)
        return Path(path)

    """Class that returns a path"""

    def __call__(self, context: Context) -> Path:
        raise NotImplementedError()

class DatafolderPath(ResolvablePath):
    def __init__(self, folderid, path):
        self.folderid = folderid
        self.path = path

    def __str__(self):
        return "datafolder-path({folderid}):{path}".format(**self.__dict__)

    def __call__(self, context: Context) -> Path:
        return Path(context.settings.datafolders[self.folderid]) / self.path

class Datasets(Iterable["AbstractDataset"]):
    """A set of datasets contained within a Python module"""

    def __init__(self, module: Module):
        """Initialize with a module"""
        self.module = module
        self._title = None
        self._description = None

    @property
    def id(self):
        return ".".join(self.module.__name__.split(".", 2)[2:])

    @property
    def title(self):
        self._getdoc()
        return self._title

    @property
    def description(self):
        self._getdoc()
        return self._description

    def _getdoc(self):
        if self._title is not None:
            return

        if not self.module.__doc__:
            self._title = ""
            self._description = ""
            return

        intitle = True
        title = []
        description = []
        for line in self.module.__doc__.split("\n"):
            if line.strip() == "" and intitle:
                intitle = False
            else:
                (title if intitle else description).append(line)

        self._title = " ".join(title)
        self._description = "\n".join(description)

    def __iter__(self) -> Iterable["AbstractDataset"]:
        from .definitions import DatasetWrapper

        # Iterates over defined symbols
        for key, value in self.module.__dict__.items():
            # Ensures it is annotated
            if isinstance(value, DatasetWrapper):
                # Ensure it comes from the module
                if self.module.__name__ == value.t.__module__:
                    yield value

class Repository:
    """A repository regroup a set of datasets and their corresponding specific handlers (downloading, filtering, etc.)"""

    def __init__(self, context: Context):
        """Initialize a new repository

        :param context: The dataset main context
        :param basedir: The base directory of the repository
            (by default, the same as the repository class)
        """
        self.context = context
        p = inspect.getabsfile(self.__class__)
        self.basedir = Path(p).parent
        self.configdir = self.basedir.joinpath("config")
        self.id = self.__class__.NAMESPACE
        self.name = self.id
        self.module = self.__class__.__module__
        self.__class__.INSTANCE = self

    @classmethod
    def basemodule(cls):
        return cls.__module__

    @classmethod
    def instance(cls, context=None):
        try:
            return cls.__getattribute__(cls, "INSTANCE")
        except AttributeError:
            return cls(context if context else Context.instance())

    @classmethod
    def version(cls):
        from pkg_resources import get_distribution, DistributionNotFound

        try:
            return get_distribution(cls.__module__).version
        except DistributionNotFound:
            __version__ = None

    def __repr__(self):
        return "Repository(%s)" % self.basedir

    def __hash__(self):
        return self.basedir.__hash__()

    def __eq__(self, other):
        assert isinstance(other, Repository)
        return self.basedir == other.basedir

    def search(self, name: str):
        """Search for a dataset in the definitions"""
        logging.debug("Searching for %s in %s", name, self.configdir)

        candidates: List[str] = []
        components = name.split(".")
        path = self.configdir
        for i, c in enumerate(components):
            path = path / c

            if (path / "__init__.py").is_file():
                candidates.append(".".join(components[: i + 1]))

            if path.with_suffix(".py").is_file():
                candidates.append(".".join(components[: i + 1]))

            if not path.is_dir():
                break

        # Get the dataset
        for candidate in candidates[::-1]:
            logging.debug("Searching in module %s.config.%s", self.module, candidate)
            module = importlib.import_module("%s.config.%s" % (self.module, candidate))
            for value in Datasets(module):
                if name in value.aliases:
                    return value

        return None

    def datasets(self, candidate):
        try:
            module = importlib.import_module("%s.config.%s" % (self.module, candidate))
        except ModuleNotFoundError:
            return None
        return Datasets(module)

    def modules(self) -> Iterator["Module"]:
        """Iterates over all modules in this repository"""
        for _, fid, package in self._modules():
            try:
                module = importlib.import_module(package)
                yield Datasets(module)
            except Exception as e:
                import traceback

                traceback.print_exc()
                logging.error("Error while loading module %s: %s", package, e)

    def _modules(self):
        """Iterate over modules (without parsing them)"""
        for path in self.configdir.rglob("*.py"):
            try:
                relpath = path.relative_to(self.configdir)
                c = [p.name for p in relpath.parents][:-1][::-1]
                if path.name != "__init__.py":
                    c.append(path.stem)
                fid = ".".join(c)

                package = ".".join([self.module, "config", *c])

                yield self, fid, package
            except Exception as e:
                import traceback

                traceback.print_exc()
                logging.error("Error while reading definitions file %s: %s", path, e)

    def __iter__(self) -> Iterator["AbstractDataset"]:
        """Iterates over all datasets in this repository"""
        for datasets in self.modules():
            for dataset in datasets:
                yield dataset

    @property
    def generatedpath(self):
        return self.basedir.joinpath("generated")

    @property
    def datapath(self):
        return self.context.datapath.joinpath(self.id)

    @property
    def extrapath(self):
        """Path to the directory containing extra configuration files"""
        return self.basedir.joinpath("data")

def find_dataset(dataset_id: str):
    """Find a dataset given its id"""
    from .definitions import AbstractDataset

    return AbstractDataset.find(dataset_id)

def prepare_dataset(dataset_id: str):
    """Find a dataset given its id and download the resources"""
    from .definitions import AbstractDataset

    ds = AbstractDataset.find(dataset_id)
    return ds.prepare(download=True)

def get_dataset(dataset_id: str):
    """Find a dataset given its id"""
    from .definitions import AbstractDataset

    ds = AbstractDataset.find(dataset_id)
    return ds.prepare(download=False)


"""
 Author:     Henry, henrylu518@gmail.com
 Date:       May 8, 2015
 Problem:    Valid Palindrome
 Difficulty: Easy
 Source:     http://leetcode.com/onlinejudge#question_125
 Notes:
 Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
 For example,
 "A man, a plan, a canal: Panama" is a palindrome.
 "race a car" is not a palindrome.
 Note:
 Have you consider that the string might be empty? This is a good question to ask during an interview.
 For the purpose of this problem, we define empty string as valid palindrome.

 Solution: traverse from both side.
 """

class Solution:
    # @param {string} s
    # @return {boolean}
    def isPalindrome(self, s):
        i = 0
        j = len(s) - 1
        while j > i:
            while i < j and not s[i].isalnum(): i += 1
            while i < j and not s[j].isalnum(): j -= 1
            if s[i].lower() != s[j].lower(): return False
            i += 1
            j -= 1
        return True


from pymongo import MongoClient
import requests
from watson_service import WatsonService
from data_service import DataService

def main():

    data_service = DataService()
    news_journals = data_service.get_known_online_news_journals()

    news_journal_articles = []
    for news_journal in news_journals:
        try:
            articles_of_journal_over_timeframe = data_service.get_articles_by_new_journal_over_timeframe(news_journal['url'])

        except Exception as query_failure:
            print('source name, source id, resulted in xmany articles or none at all within the timeframe')

    source_articles_by_source_id = {}
    for news_source in news_sources:
        articles = data_service.get_articles_from_online_news_journal_by_url(news_source['url'])
        source_articles_by_source_id[news_source['_id']] = articles
        if 'docs' in source_articles_by_source_id.keys():
            for article in source_articles_by_source_id['docs']['source']['enriched']['url']:
                pass

    # find the best possible news across one or more sources the most both singularly about a topic and with an
    # interesting or strong perspective
                # want news that is unique due to its paring of strange characters doing odd things, expressing a strong
                # and unique opinion towards common actions performed by a character in novel way

    # Hierarchy of boxes model, where the color of the lies of each rectange can convey different information, same as the
    # spacing between the rectangles

        stop_here = ""
    stop_here = ""

    query_url = 'https://topics.mediacloud.org/api/collections/9139458/stories'
    parameters = {
        'snapshotId': '1477',
        'timespandId': '39849',
        'sort': 'inlink',
        'limit': '5000'
    }
    # response = requests.get(query_url, params=parameters)
    # stop_here = ""

    client = MongoClient('localhost', 27017)
    database = client['AkashicRecords']
    articles = database['historic_political_article_data']
    cbt = database['cleaned_breitbart_test']

    articles_found = []
    for article in articles.find():
        articles_found.append(article)

    cleaned_articles = []
    for article in articles_found:
        if len(article['entities']) > 5:
            article['entities'] = article['entities'][:5]

            stop_here = ""

    for article in articles_found:
        relation_by_sent_id = {}
        for relation in article['relations']:
            try:
                sent_id = hash(relation['sentence'])
                if 'subject' in relation.keys():
                    if 'object' in relation.keys():
                        pass
                if 'object' in relation.keys():
                    pass
            except Exception as e:
                print(e.args)

    # watson_service = WatsonService()

    # articles_found = data_service.pull_from_source('http://www.breitbart.com')
    cleaned_articles = data_service.clean_source_articles('breitbart.com', articles_found)
    cbt.insert_many(cleaned_articles)

    article_data_list = []
    for article in articles.find():
        article_element_types = []
        relevance_threshold = 0.80

        for entity in article['entities']:
            if entity['relevance'] > relevance_threshold:
                if 'knowledgeGraph' in entity.keys():
                    if 'typeHierarchy' in entity['knowledgeGraph'].keys():
                        article_element_types.append(entity['knowledgeGraph']['typeHierarchy'].split('/')[1:])

        for keyword in article['keywords']:
            if keyword['relevance'] > relevance_threshold:
                if 'knowledgeGraph' in keyword.keys():
                    if 'typeHierarchy' in keyword['knowledgeGraph'].keys():
                        article_element_types.append(keyword['knowledgeGraph']['typeHierarchy'].split('/')[1:])

        article_data_list.append(article_element_types)

    stop_here = ""

if __name__ == '__main__':
    main()


# Program for Connection Setup

# Depreciated

raise DeprecationWarning

import os
from Crypto.PublicKey import RSA
from Crypto import Random
import hashlib
from Crypto.Cipher import PKCS1_OAEP, AES
import select

from TSE import tse
from Flags import flags
from Chromos import Chromos
o = Chromos()

class Connection():

    def __init__(self, conn):
        self.server_keys_path = "./SKeys/"
        self.client_keys_path = "./CKeys/"

        self.conn = conn
        self.timeout = 2
        return

    def load_keys(self, path, prefix='')->None:
        path = ''.join([path, '/', prefix])
        if(os.path.isfile(path +"public.key") is False or os.path.isfile(path + "private.key") is False): self.generate_key(path, prefix)
        with open(''.join([path, "public.key",]), 'r') as f:
            public = f.read().encode()
        with open(''.join([path, "private.key"]), 'r') as f:
            private = f.read().encode()
        return public, private

    def load_key(self, keypath):
        f = open(keypath, "r")
        key = f.read().encode()
        f.close()
        return key

    def generate_key(self, path, prefix):
        random = Random.new().read
        RSAKey = RSA.generate(1024, random)

        public = RSAKey.publickey().exportKey()
        private = RSAKey.exportKey()

        with open(path + prefix + "public.key", "w") as f:
            f.write(public.decode())
            f.flush()
        with open(path + prefix + "private.key", "w") as f:
            f.write(private.decode())
            f.flush()

        o.info_y("RSA Keys Generated! ")

        return True

    def rand_gen(self, n):
        return str(int.from_bytes(os.urandom(n), byteorder='big'))

    def ret_hash(self, __data):
        return hashlib.md5(__data).hexdigest().encode()

    def ret_enc(self, __key):
        __RSAKey = RSA.importKey(__key)
        return PKCS1_OAEP.new(__RSAKey)

    def connection_setting_server(self, username):
        SPub, SPri = self.load_keys(self.server_keys_path)
        hashSPub = self.ret_hash(SPub)
        rs, _, _ = select.select([self.conn], [], [], self.timeout)
        if(rs):
            data = self.conn.recv(4096)
            __data_splt_temp = data.split(b':0:')
            if(__data_splt_temp == [data] or len(__data_splt_temp) < 2): return False, 0, []

            CPub = __data_splt_temp[0]
            tmp_hashSPub = __data_splt_temp[1]
            if(tmp_hashSPub==hashSPub):
                session = self.rand_gen(8).encode()
                __aes = os.urandom(16)  # AES Key
                __enc = tse.Key(aeskey=__aes)   # Transport Security Encryption
                re_auth = __enc.exportKey().encode() # TSE

                hashCPub = self.ret_hash(CPub)
                encryptor = self.ret_enc(CPub)

                self.conn.sendall(b''.join([encryptor.encrypt(b''.join([hashCPub, b':0:', session, b':0:', __aes])), b':0:', re_auth]))

                session = self.ret_hash(session)
                re_auth = self.ret_hash(re_auth)

                rs, _, _ = select.select([self.conn], [], [], self.timeout)
                if(rs):
                    Get = self.conn.recv(4096).split(b':0:')

                    tmp_session = Get[0]
                    tmp_re_auth = Get[1]

                    if(tmp_session == session):
                        # print("session matched")
                        if(tmp_re_auth == re_auth):
                            # print("re_auth matched")
                            # Exchange Usernames
                            encryptor = self.ret_enc(CPub)
                            self.conn.sendall(encryptor.encrypt(''.join([flags.USERNAME_PREFIX_POSTFIX, str(username), flags.USERNAME_PREFIX_POSTFIX]).encode()))

                            decryptor = self.ret_enc(SPri)
                            data = self.conn.recv(4096)
                            data = decryptor.decrypt(data)

                            __susername = data.split(flags.USERNAME_PREFIX_POSTFIX.encode())[1].decode()
                            print(__susername)

                            return True, __enc, CPub, __susername
        print('Failed!')
        return False, 0, []

    def connection_setting_client(self, username):
        CPub, CPri = self.load_keys(self.client_keys_path, "client_")
        if(os.path.isfile(self.client_keys_path + "public.key")==False):
            o.error_info("Server Public Key Not Found! ")
            raise FileNotFoundError

        SPub = self.load_key(self.client_keys_path + "public.key")

        hashSPub = self.ret_hash(SPub)
        hashCPub = self.ret_hash(CPub)

        self.conn.sendall(CPub + b':0:' + hashSPub)

        rs, _, _ = select.select([self.conn], [], [], self.timeout)
        if(rs):
            Get = self.conn.recv(4096)

            __cget_array = Get.split(b':0:')
            Get = __cget_array[0]
            re_auth = __cget_array[1]

            decryptor = self.ret_enc(CPri)
            Get = decryptor.decrypt(Get)

            __cget_array = Get.split(b':0:')

            tmp_hashCPub = __cget_array[0]
            session = __cget_array[1]
            __aes = __cget_array[2]

            if(tmp_hashCPub == hashCPub):
                __enckey = re_auth.decode()
                session = self.ret_hash(session)
                re_auth = self.ret_hash(re_auth)

                self.conn.sendall(b''.join([session, b':0:', re_auth]))

                # Exchange Usernames and UIDs
                encryptor = self.ret_enc(SPub)
                self.conn.sendall(encryptor.encrypt(''.join([flags.USERNAME_PREFIX_POSTFIX, str(username), flags.USERNAME_PREFIX_POSTFIX]).encode()))

                decryptor = self.ret_enc(CPri)
                data = self.conn.recv(4096)
                data = decryptor.decrypt(data)

                __susername = data.split(flags.USERNAME_PREFIX_POSTFIX.encode())[1].decode()
                print(__susername)

                return True, tse.Key(aeskey=__aes, key=__enckey), __susername
        print('Failed!')
        return False, None, ''

    pass


# -*- encoding: UTF-8 -*-
##############################################################################

from openerp import fields, api
from openerp.addons.field_secure import models  # @UnresolvedImport
import logging
_logger = logging.getLogger(__name__)

AVAILABLE_PRIORITIES = [
    ('0', 'Bad'),
    ('1', 'Below Average'),
    ('2', 'Average'),
    ('3', 'Good'),
    ('4', 'Excellent')
]

class hr_applicant(models.SecureModel):
    _inherit = "hr.applicant"

    salary_expected_secure = fields.Secure(
        string='Expected Salary',
        security="_password_security",
        help="Salary Expected by Applicant")
    salary_proposed_secure = fields.Secure(
        string='Proposed Salary',
        security="_password_security",
        help="Salary Proposed by the Organization")
    partner_name = fields.Char("Applicant's Name", track_visibility="onchange")
    email_from = fields.Char('Email', size=128,
                             help="These people will receive email.",
                             track_visibility="onchange")
    partner_mobile = fields.Char('Mobile', size=32,
                                 track_visibility="onchange")
    type_id = fields.Many2one('hr.recruitment.degree', 'Degree',
                              track_visibility="onchange")
    date_action = fields.Date('Next Action Date', track_visibility="onchange")
    title_action = fields.Char('Next Action', size=64,
                               track_visibility="onchange")
    priority = fields.Selection(AVAILABLE_PRIORITIES, 'Appreciation',
                                track_visibility="onchange")
    source_id = fields.Many2one('hr.recruitment.source', 'Source',
                                track_visibility="onchange")
    reference = fields.Char('Referred By', track_visibility="onchange")
    job_id = fields.Many2one('hr.job', 'Applied Job',
                             track_visibility="onchange")
    availability = fields.Integer(
        'Availability', help="The number of days in which the applicant will "
        "be available to start working", track_visibility="onchange")
    categ_ids = fields.Many2many('hr.applicant_category', string='Tags',
                                 track_visibility="onchange")
    description = fields.Text('Description', track_visibility="onchange")

    @api.model
    def create(self, vals):
        """
        Override function
        Calculate Subject = {Applied Job} - {Applicants name}
        """
        job_obj = self.env['hr.job']
        job_name = ''
        if vals.get('job_id'):
            job_name = job_obj.browse(vals['job_id']).name
        vals['name'] = job_name and job_name + ' - ' + vals['partner_name'] \
            or vals['partner_name']
        return super(hr_applicant, self).create(vals)

    @api.multi
    def write(self, vals):
        """
        Override function
        Calculate Subject = {Applied Job} - {Applicants name}
        """
        if 'job_id' not in vals and 'partner_name' not in vals:
            # Nothing change
            return super(hr_applicant, self).write(vals)

        job_obj = self.env['hr.job']
        if 'job_id' in vals and 'partner_name' in vals:
            # change job and applicant name
            # update all applicant at the same time
            job_name = ''
            if vals.get('job_id'):
                job_name = job_obj.browse(vals['job_id']).name
            vals['name'] = job_name and job_name + ' - ' \
                + vals['partner_name'] \
                or vals['partner_name']
            return super(hr_applicant, self).write(vals)
        else:
            # change job or partner_name
            if 'job_id' in vals:
                # Only change job name
                job_name = ''
                if vals['job_id']:
                    job_name = job_obj.browse(vals['job_id']).name
                for app in self:
                    pos = app.name.find('-')
                    vals['name'] = job_name and job_name + ' - ' + \
                        (pos > -1 and app.name[pos + 2:] or app.name) \
                        or app.name[pos + 2:]
                    super(hr_applicant, app).write(vals)
            elif 'partner_name' in vals:
                # On change the application name
                for app in self:
                    pos = app.name.find('-')
                    vals['name'] = (pos > -1 and app.name[: pos + 2] or '') + \
                        vals['partner_name']
                    super(hr_applicant, app).write(vals)
        return True

    @api.multi
    def _password_security(self):
        """
            Only the followers of the application can read/update/delete the
            Propose Salary/Suggested Salary.
        """
        is_allow = False
        for rec in self:
            if self.env.user.partner_id.id in rec.message_follower_ids.ids:
                is_allow = True
            else:
                is_allow = False
                break
        return is_allow

    @api.model
    def _get_applicants_of_followers(self, user_id):
        filter_ids = []
        current_user = self.env["res.partner"].search(
            [('user_id', '=', user_id)])
        self._cr.execute(""" SELECT id FROM hr_applicant """)
        datas = [data[0] for data in self._cr.fetchall()]
        for rec in self.browse(datas):
            if current_user in rec.message_follower_ids:
                filter_ids.append(rec.id)
        if filter_ids:
            return [('id', 'in', filter_ids)]
        else:
            return [('id', 'in', [])]

    @api.model
    def search(self, args, offset=0, limit=None, order=None, count=False):
        uid = self._context.get('uid', self._uid)
        if self.message_follower_ids and \
                uid in self.message_follower_ids.ids:
            args.extend(self._get_applicants_of_followers(uid))
        return super(hr_applicant, self).search(
            args, offset=offset, limit=limit, order=order, count=count)

    @api.cr_uid_ids_context
    def message_track(self, cr, uid, ids, tracked_fields,
                      initial_values, context=None):
        def convert_for_display(value, col_info):
            if not value and col_info['type'] == 'boolean':
                return 'False'
            if not value:
                return ''
            if col_info['type'] == 'many2one':
                return value.name_get()[0][1]
            if col_info['type'] == 'selection':
                return dict(col_info['selection'])[value]
            if col_info['type'] == 'many2many':
                str1 = ', '.join([v.name_get()[0][1] for v in value])
                return str1
            return value

        def format_message(message_description, tracked_values):
            message = ''
            if message_description:
                message = '%s' % message_description
            for name, change in tracked_values.items():
                old_values = change.get('old_value')
                if isinstance(old_values, int):
                    old_values = str(old_values)
                list_old_values = \
                    [item.strip().encode('utf-8')
                     for item in old_values.strip('[]').split(',')]

                new_values = change.get('new_value')
                if isinstance(new_values, int):
                    new_values = str(new_values)
                list_new_values = \
                    [item.strip().encode('utf-8')
                     for item in new_values.strip('[]').split(',')]

                vals = []
                for x in list_old_values:
                    if x not in list_new_values:
                        vals.append(x.decode('utf-8'))
                if vals:
                    message +=\
                        '
     • Removed %s: ' %\
                        change.get('col_info')
                    message += '%s
' % ', '.join(vals)

                vals = []
                for x in list_new_values:
                    if x not in list_old_values:
                        vals.append(x.decode('utf-8'))
                if vals:
                    message +=\
                        '
     • Added %s: ' %\
                        change.get('col_info')
                    message += '%s
' % ', '.join(vals)
            return message

        if not tracked_fields:
            return True

        for browse_record in self.browse(cr, uid, ids, context=context):
            initial = initial_values[browse_record.id]
            changes = set()
            tracked_values = {}

            # generate tracked_values data structure: {'col_name': {col_info,
            # new_value, old_value}}
            for col_name, col_info in tracked_fields.items():
                field = self._fields[col_name]
                initial_value = initial[col_name]
                record_value = getattr(browse_record, col_name)

                if record_value == initial_value and\
                        getattr(field, 'track_visibility', None) == 'always':
                    tracked_values[col_name] = dict(
                        col_info=col_info['string'],
                        new_value=convert_for_display(record_value, col_info),
                    )
                # because browse null != False
                elif record_value != initial_value and\
                        (record_value or initial_value):
                    if getattr(field, 'track_visibility', None) in\
                            ['always', 'onchange']:
                        tracked_values[col_name] = dict(
                            col_info=col_info['string'],
                            old_value=convert_for_display(
                                initial_value, col_info),
                            new_value=convert_for_display(
                                record_value, col_info),
                        )
                    if col_name in tracked_fields:
                        changes.add(col_name)
            if not changes:
                continue

            # find subtypes and post messages or log if no subtype found
            subtypes = []
            # By passing this key, that allows to let the subtype empty and so
            # don't sent email because partners_to_notify from
            # mail_message._notify will be empty
            if not context.get('mail_track_log_only'):
                for field, track_info in self._track.items():
                    if field not in changes:
                        continue
                    for subtype, method in track_info.items():
                        if method(self, cr, uid, browse_record, context):
                            subtypes.append(subtype)

            posted = False
            for subtype in subtypes:
                subtype_rec = self.pool.get('ir.model.data').xmlid_to_object(
                    cr, uid, subtype, context=context)
                if not (subtype_rec and subtype_rec.exists()):
                    _logger.debug('subtype %s not found' % subtype)
                    continue
                message = format_message(
                    subtype_rec.description if subtype_rec.description else
                    subtype_rec.name, tracked_values)
                self.message_post(
                    cr, uid, browse_record.id, body=message,
                    subtype=subtype, context=context)
                posted = True
            if not posted:
                message = format_message('', tracked_values)
                self.message_post(
                    cr, uid, browse_record.id,
                    body=message, context=context)
        return True


from collections import deque
n=int(input())
sea=[list(map(int,input().split())) for _ in range(n)]

d=[(1,0),(-1,0),(0,1),(0,-1)]

def bfs(q,shark):
    global cnt
    checklist=[]
    checkpoint=n**2
    while q:
        x,y,t=q.popleft()
        if t>checkpoint:
            sea[shark[0]][shark[1]]=0
            checklist.sort()
            sea[checklist[0][0]][checklist[0][1]]=9
            cnt+=1
            return t
        for dx,dy in d:
            nx=x+dx
            ny=y+dy
            if 0<=nx<n and 0<=ny<n and not v[nx][ny]:
                if sea[nx][ny]==0 or sea[nx][ny]==size:
                    v[nx][ny]=True
                    q.append((nx,ny,t+1))
                elif sea[nx][ny]<size:
                    checkpoint=t
                    checklist.append((nx,ny))

    if checklist:
        sea[shark[0]][shark[1]]=0
        checklist.sort()
        sea[checklist[0][0]][checklist[0][1]]=9
        cnt+=1
        return t+1

    return False
cnt=0
size=2
ans=0
while True:
    v=[[False]*n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if sea[i][j]==9:
                q=deque([(i,j,0)])
                v[i][j]=True
                shark=(i,j)
    tmp=bfs(q,shark)
    if not tmp:
        break
    ans+=tmp
    if cnt==size:
        size+=1
        cnt=0

print(ans)


from flask import Flask, jsonify, request, render_template
from datetime import datetime
from db import despesas, tipos_de_pagamento, categorias, Pagamento, Categoria

app = Flask(__name__)

# criar os tipos de pagamento // importada do banco de dados
# criar as categorias // importada do banco de dados

# pagina inicial
@app.route('/', methods=['GET'])
def pagina_inicial():
    return render_template('index.html')

# listar todas as despesas do mes vigente
@app.route('/api/despesas', methods=['GET'])
def get_despesas():
    lista = []
    total = 0
    for despesa in despesas:
        if despesa.get('data').month == datetime.today().month:
            lista.append(despesa)
            total += despesa.get('valor')
    return jsonify({'data': lista, 'total': total, 'success': True})

# listar todas as depesas totais
@app.route('/api/despesasTotais', methods=['GET'])
def get_todas_despesas():
    return jsonify({'data':despesas, 'success': True})

# listas despesas por categoria
@app.route('/api/despesas/<categoria>', methods=['GET'])
def get_por_categoria(categoria):
    lista = []
    for despesa in despesas:
        if despesa.get('categoria') == categoria:
            lista.append(despesa)
    return jsonify({'data': lista, 'success': True})

# adicionar despesa
@app.route('/api/add/despesa', methods=['POST'])
def cadastrar_despesa():
    despesa = request.get_json()

    id = despesa['id'] # get id
    valor = despesa['valor'] # get valor
    descricao = despesa['descricao'] # get descricao

    for index, pagamento in enumerate(tipos_de_pagamento): # converte o pagamento
        if despesa['pagamento'] == pagamento.nome:
            pagamento = tipos_de_pagamento[index]

    for index, categoria in enumerate(categorias): # converte a categoria
        if despesa['categoria'] == categoria.nome:
            categoria = categorias[index]

    data = datetime.strptime(despesa['data'], '%d/%m/%y').date() # converte em data

    nova_despesa = {
        'id': id,
        'valor': valor,
        'descricao': descricao,
        'pagamento': pagamento.nome,
        'categoria': categoria.nome,
        'data': data
    }

    despesas.append(nova_despesa)

    return jsonify({'data': despesas, 'success': True})

# adicionar tipo de pagamento
@app.route('/api/add/pagamento', methods=['POST'])
def cadastrar_pagamento():
    pagamento = request.get_json()

    id = pagamento['id']
    nome = pagamento['nome']

    novo_pagamento = Pagamento(id, nome)

    tipos_de_pagamento.append(novo_pagamento)

    return jsonify({'data': f'Pagamento adicionado: {novo_pagamento.id} - {novo_pagamento.nome}',
                    'success': True})

# adicionar nova categoria de compra
@app.route('/api/add/categoria', methods=['POST'])
def cadastrar_categoria():
    categoria = request.get_json()

    id = categoria['id']
    nome = categoria['nome']
    descricao = categoria['descricao']

    nova_categoria = Categoria(id, nome, descricao)

    categorias.append(nova_categoria)

    return jsonify({'data': f'Categoria adicionada: {nova_categoria.id} - {nova_categoria.nome} - {nova_categoria.descricao}',
                   'success': True})

# listar tipos de pagamentos
@app.route('/api/pagamentos', methods=['GET'])
def mostrar_pagamentos():
    lista = []
    for value in tipos_de_pagamento:
        lista.append({'id': value.id,
                      'nome': value.nome})

    return jsonify({'data': lista, 'success': True})

# listar categorias e suas descricoes
@app.route('/api/categorias', methods=['GET'])
def mostrar_categorias():
    lista = []
    for value in categorias:
        lista.append({'id': value.id,
                      'nome': value.nome,
                      'descricao': value.descricao})

    return jsonify({'data': lista, 'success': True})

app.run(port=5000, host='localhost', debug=True)


# O(log(n))

# The guess API is already defined for you.
# @param num, your guess
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:

class Solution:
    def guessNumber(self, n: int) -> int:
        start = 0
        end = n + 1
        while start < end:
            midpoint = start + ((end - start) // 2)
            res = guess(midpoint)
            if res == 0:
                return midpoint
            elif res > 0:
                start = midpoint + 1
            else:
                end = midpoint
        return None


"""

This problem was asked by Facebook.
Given a list of integers, return the largest product that can be made by multiplying any three integers.
For example, if the list is [-10, -10, 5, 2], we should return 500, since that's  -10 * -10 * 5.
You can assume the list has at least three integers.

"""

import numpy as np
trip=[-10, 10,5,2]
stat=np.prod(trip)
if stat>0:print(np.prod(sorted([abs(j) for j in trip],reverse=True)[:3]))
else:print(np.prod(sorted(trip,reverse=True)[:3]))

"""
import pandas as pd
import itertools
df=pd.DataFrame(itertools.permutations([-10,-10,5,2], 3))
s=df[0]*df[1]*df[2]
print(s.max())
"""
#print(len(list(itertools.permutations([4,5,8,9],3))))


# stanford_corenlp 所在的路径，绝对路径
stanford_corenlp = "D:\stanford-corenlp-full-2018-10-05"

expect_train_file_num = 287227
expect_test_file_num = 11490
expect_val_file_num = 13368

# 正常情况下，一个文件对应一个样本，但是有些文件中没有文章，或者没有摘要，就去掉了

expect_train_sample_num = 287113
expect_test_sample_num = 11490
expect_val_sample_num = 13368

SPECIAL_TOKEN = ['<pad>','<unk>','<start>','<stop>']

dm_single_close_quote = u'\u2019' # unicode
dm_double_close_quote = u'\u201d'
END_TOKENS = ['.', '!', '?', '...', "'", "`", '"', dm_single_close_quote, dm_double_close_quote, ")"] # acceptable ways to end a sentence

hidden_dim = 256
embed_dim = 128


MOD = 10 ** 9 + 7

def solve(N, A):
    A.sort()
    two = [0] * (N + 1)
    for i in range(N + 1):
        two[i] = 2 ** i

    ans = 0
    for i in range(N):
        l = i
        r = N-i-1
        now = two[r]
        if r != 0:
            now += two[r-1] * r
        now *= two[l]
        now *= A[i]
        ans += now

    ans *= two[N]

    return ans % MOD

    return 0

N = int(input())
A = list(map(int, input().split()))

print(solve(N, A))

# n = int(input())
# ccc = list(map(int, input().split()))
# ccc.sort()
# MOD = 10 ** 9 + 7
# ans = 0
# others = pow(4, n - 1, MOD)
# for i, c in enumerate(ccc):
#     ans = (ans + others * c * (n - i + 1)) % MOD
# print(ans)


from mxnet.gluon.data import dataset, DataLoader
import numpy as np
import mxnet.ndarray as ndarray
from utils.augmentations import *

class MyTransform:
    def __init__(self, im, opts):
        if opts.is_val:
            transforms_list_idx = [0, 14, 1]
        else:
            transforms_list_idx = [0, ] + [opts.transforms_list_idx[j]
                                           for j in np.random.choice(opts.transforms_list_idx.__len__(),
                                                                     opts.transforms_list_idx.__len__(), replace=False)] \
                                  + [14, 1, ]
        self.to_norm = not opts.already_normed
        self.norm_thr = opts.norm_thr
        self.nsee = opts.num_slices_each_end
        self.label_in_last_channel = opts.label_in_last_channel
        self.max_angle = opts.max_angle
        self.coor_maps = opts.coor_maps
        self.is_val = opts.is_val
        self.zdim = opts.zdim
        self.mid_len_ratio = opts.mid_len_ratio
        self.translate_ratio = opts.translate_ratio
        self.mean_scaling = opts.mean_scaling
        self.crop_size_list = opts.crop_size_list
        self.crop_size = opts.crop_size
        self.use_ADC = opts.use_ADC
        self.cov = opts.center_translation_cov
        self.transforms_dict = {
            'sample_slices': sample_slices,  # 0
            'concat_coor_maps': concat_coor_maps,  # concat_coor_maps index must be 0  # 1
            'rand_scale': rand_scale,  # 2
            'drop_out': drop_out,  # 3
            'contrast_norm': contrast_norm,  # 4
            'deform': deform,  # 5
            'modify_values': modify_values,  # 6
            'Gauss_blur': Gauss_blur,  # 7
            'add_Gauss_noise': add_noise,  # 8
            'rand_translate': rand_translate,  # 9
            'rand_rot': rand_rot,  # 10
            'rand_fliplr': rand_fliplr,  # 11
            'center_crop_and_scale': None,  # 12
            'swap_channels': swap_channels,  # 13
            'crop_and_resize': crop_and_resize,  # 14
            'rand_flipud': rand_flipud, # 15
        }
        self.transforms_list = list(self.transforms_dict.keys())
        self.transforms_list = [self.transforms_list[i] for i in transforms_list_idx]
        self.im = im

    def random_transform(self):
        for fn in self.transforms_list:
            self.im = self.transforms_dict[fn](self)
        return self.im

class MyDataset(dataset.Dataset):
    """A dataset that combines multiple dataset-like objects, e.g.
    Datasets, lists, arrays, etc.

    The i-th sample is defined as `(x1[i], x2[i], ...)`.

    Parameters
    ----------
    *args : one or more dataset-like objects
        The data arrays.
    """
    def __init__(self, opts, *args):
        assert len(args) > 0, "Needs at least 1 arrays"
        self._length = len(args[0])
        self._data = []
        self.opts = opts
        for i, data in enumerate(args):
            assert len(data) == self._length, \
                "All arrays must have the same length; array[0] has length %d " \
                "while array[%d] has %d." % (self._length, i+1, len(data))
            if isinstance(data, ndarray.NDArray) and len(data.shape) == 1:
                data = data.asnumpy()
            self._data.append(data)

    def __getitem__(self, idx):
        if len(self._data) == 1:
            return MyTransform(self._data[0][idx], self.opts).random_transform()
        else:
            return tuple(MyTransform(data[idx], self.opts).random_transform() for data in self._data)

    def __len__(self):
        return self._length

if __name__ == "__main__":
    x = np.zeros(shape=(5, 2, 10, 30, 30))

    d = MyDataset(x)
    data_loader = DataLoader(d, batch_size=2)

    for b in data_loader:
        print(b[0].shape)


import os
import random
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris, load_breast_cancer, load_wine, make_blobs
from sklearn.model_selection import train_test_split

project_dir = os.path.dirname(os.getcwd())

# This file describes utility functions for loading and creating (dummy) datasets.

def load(subsample_train_frac=None, prop_train=None, prop_test=None, is_iid=True, verbose=None):
    # This is where we locate the .csv files and read them as pandas dataframes.
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df_train, df_test = train_test_split(df, test_size=prop_test)
    # print(df.columns)
    if verbose:
        print(df.head())
    return df_train, df_test

def load_data(dataset=None, is_iid=True, num_devices=3, split_train_test=False, prop_test=None, dims=2, samples=100,
              clusters=3, verbose=False):
    eligible_datasets = ['iris', 'breast cancer', 'wine', 'heart disease', 'forest types', 'blobs', 'dummy']
    if dataset not in eligible_datasets:
        print("No dataset was requested or the requested dataset could not be retrieved.")
        print("Defaulting to generating blobs...")
        return create_blobs(dims=dims, samples=samples, clusters=clusters, split_train_test=split_train_test,
                            prop_test=prop_test, is_iid=is_iid, num_devices=num_devices, verbose=verbose)
    else:
        if dataset == 'iris':
            iris = load_iris()
            df = pd.DataFrame(iris.data, columns=iris.feature_names)
            labels = iris.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'breast cancer':
            breast_cancer = load_breast_cancer()
            df = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
            labels = breast_cancer.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'wine':
            wine = load_wine()
            df = pd.DataFrame(wine.data, columns=wine.feature_names)
            labels = wine.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'heart disease':
            df = pd.read_csv("data/heart_disease_cleveland.csv")  # not sure how to retrieve just labels here...
            # this implementation does not use split_data for now, because it would require us to extract labels.
            if split_train_test and prop_test is not None:
                df_train, df_test = train_test_split(df, test_size=prop_test)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            elif split_train_test:
                df_train, df_test = train_test_split(df, test_size=.2)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            else:
                return np.array_split(df, num_devices)

        if dataset == 'forest types':
            cur_file = os.path.abspath(os.path.dirname(__file__))
            covtype_file = os.path.join(cur_file, 'data/forest_covertypes.csv')
            df = pd.read_csv(covtype_file)
            labels = df['Cover_Type']
            df = df.drop('Cover_Type', axis=1)
            print(df.shape)
            # this implementation does not use split_data for now, because it would require us to extract labels.
            if split_train_test and prop_test is not None:
                df_train, df_test = train_test_split(df, test_size=prop_test)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            elif split_train_test:
                df_train, df_test = train_test_split(df, test_size=.2)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            else:
                return np.array_split(df.to_numpy(), num_devices), np.array_split(labels.to_numpy(), num_devices)

        if dataset == 'dummy':
            clients_per_cluster = num_devices//clusters
            data, _ = create_dummy_data(dims=dims, clients_per_cluster=clients_per_cluster,
                                        samples_each=samples//num_devices, clusters=clusters, verbose=True)
            print(len(data))
            return data, _

        else:  # default case
            print("Generating blobs...")
            create_blobs(dims=dims, samples=samples, clusters=clusters, split_train_test=split_train_test,
                         prop_test=prop_test, is_iid=is_iid, num_devices=num_devices, verbose=verbose)

def split_data(df, labels, num_devices, split_train_test=False, prop_test=None, is_iid=True):
    if not is_iid:
        if split_train_test:
            if prop_test is not None:
                prop = prop_test
            else:
                prop = .2
            num_test = int(prop * len(df))
            order_train = np.argsort(labels[num_test:])
            order_test = np.argsort(labels[:num_test])
            df_train = df[order_train]
            df_test = df[order_test]
            exp_train_per_device = round(len(df_train)/num_devices)
            exp_test_per_device = round(len(df_test)/num_devices)
            range_sizes_train = range(exp_train_per_device - exp_train_per_device//4,
                                      exp_train_per_device + exp_train_per_device//4)
            range_sizes_test = range(exp_test_per_device - exp_test_per_device//4,
                                     exp_test_per_device + exp_test_per_device//4)
            rand_sizes_train = [random.choice(range_sizes_train)]
            rand_sizes_test = [random.choice(range_sizes_test)]
            for i in range(1, num_devices):
                rand_sizes_train.append(random.choice(range_sizes_train) + rand_sizes_train[i - 1])
                rand_sizes_test.append(random.choice(range_sizes_test) + rand_sizes_test[i - 1])
            return np.split(df_test, rand_sizes_test), np.split(df_train, rand_sizes_train), \
                np.split(labels[:num_test][order_test], rand_sizes_test), \
                np.split(labels[num_test:][order_train], rand_sizes_train)  # test, train, y_test, y_train
        else:
            order = np.argsort(labels)
            exp_records_per_device = round(len(df)/num_devices)
            range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                                exp_records_per_device + exp_records_per_device//4)
            rand_sizes = [random.choice(range_sizes)]
            for i in range(1, num_devices):
                rand_sizes.append(random.choice(range_sizes) + rand_sizes[i-1])
            return np.split(df[order], rand_sizes), np.split(labels[order], rand_sizes)  # X, y
    elif is_iid:
        if split_train_test:
            if prop_test is not None:
                prop = prop_test
            else:
                prop = .2
            num_test = int(prop * len(df))
            exp_train_per_device = round((len(df)-num_test)/num_devices)
            exp_test_per_device = round(num_test/num_devices)
            range_sizes_train = range(exp_train_per_device - exp_train_per_device//4,
                                      exp_train_per_device + exp_train_per_device//4)
            range_sizes_test = range(exp_test_per_device - exp_test_per_device//4,
                                     exp_test_per_device + exp_test_per_device//4)
            rand_sizes_train = [random.choice(range_sizes_train)]
            rand_sizes_test = [random.choice(range_sizes_test)]
            for i in range(1, num_devices):
                rand_sizes_train.append(random.choice(range_sizes_train) + rand_sizes_train[i-1])
                rand_sizes_test.append(random.choice(range_sizes_test) + rand_sizes_test[i-1])
            return np.split(df[:num_test], rand_sizes_test[:-1]), np.split(df[num_test:], rand_sizes_train[:-1]), \
                np.split(labels[:num_test], rand_sizes_test), np.split(labels[num_test:], rand_sizes_train)
            # test, train, y_test, y_train
        else:
            exp_records_per_device = round(len(df) / num_devices)
            range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                                exp_records_per_device + exp_records_per_device//4)
            rand_sizes = [random.choice(range_sizes)]
            for i in range(1, num_devices):
                rand_sizes.append(random.choice(range_sizes) + rand_sizes[i-1])
            return np.split(df, rand_sizes), np.split(labels, rand_sizes)  # X, y
    else:  # this case should never be reached, but we include it anyway
        exp_records_per_device = round(len(df) / num_devices)
        range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                            exp_records_per_device + exp_records_per_device//4)
        rand_sizes = []
        for i in range(num_devices):
            rand_sizes.append(random.choice(range_sizes))
        return np.split(df, rand_sizes), np.split(labels, rand_sizes)  # X, y

# Function that returns the bounds (min, max) for each dimension in dataset df. Expects df to be a np.array.
# Should be a matrix describing n records having i features (dimensions).
def obtain_bounds(df):
    min_vals = df.min(axis=0)
    max_vals = df.max(axis=0)
    if isinstance(min_vals, pd.Series):
        min_vals = min_vals.to_numpy()
    if isinstance(max_vals, pd.Series):
        max_vals = max_vals.to_numpy()
    return min_vals.flatten(), max_vals.flatten()

def obtain_bounds_multiple(dfs):
    min_vals, max_vals = obtain_bounds(np.asarray(dfs[0]))
    for df in dfs[1:]:
        min_vals_df, max_vals_df = obtain_bounds(df)
        for dim in range(len(min_vals)):
            if min_vals_df[dim] < min_vals[dim]:
                min_vals[dim] = min_vals_df[dim]
            if max_vals_df[dim] > max_vals[dim]:
                max_vals[dim] = max_vals_df[dim]
    if isinstance(min_vals, pd.Series):
        min_vals = min_vals.to_numpy()
    if isinstance(max_vals, pd.Series):
        max_vals = max_vals.to_numpy()
    return min_vals, max_vals

def create_dummy_data(dims=1, clients_per_cluster=10, samples_each=10, clusters=10, scale=.5, verbose=False):
    np.random.seed(42)  # 42, 420, 4200, 42000, 420000 = 5 runs.
    num_clients = clients_per_cluster * clusters
    print(f"Number of clients set to: {num_clients}.")
    # create gaussian data set, per client one mean
    means = np.arange(1, clusters + 1)
    means = np.tile(A=means, reps=clients_per_cluster)
    noise = np.random.normal(loc=0.0, scale=scale, size=(num_clients, samples_each, dims))
    data = np.expand_dims(np.expand_dims(means, axis=1), axis=2) + noise
    if verbose:
        # print(means)
        # print(noise)
        print("dummy data shape: ", data.shape)
    data = [data[i] for i in range(num_clients)]
    return data, means

# Function to create blobs that are very clearly structured as clusters.
# Can already obtain train and test sets from this within this function.
def create_blobs(dims=2, samples=100, clusters=3, split_train_test=False, prop_test=None, is_iid=True, num_devices=3,
                 verbose=False):
    X, y = make_blobs(n_samples=samples, centers=clusters, n_features=dims, random_state=42)

    if verbose:
        print(X.shape)
        print(len(y), y)

    return split_data(X, y, num_devices, split_train_test, prop_test, is_iid)


#coding:utf-8
import os
import codecs
import math
from operator import itemgetter
from deal_config import caption,domain,catlist,catnamelist,catnamedict,project
postdict={}
#该篇日志对应发表时间
tagdict={}
#该篇日志对应标签字符串
catdict={}
#该篇日志对应中文分类名称字符串

for catpage in catlist:
	tmppage=codecs.open('./'+project+'/category/'+catpage+'.html','w','utf-8')
	head = codecs.open('./template/head.html','r','utf-8')
	for tmp in head:
		#tmp = head.readline()
		tmppage.write(tmp)
	head.close()
	tmppage.close()
#创建各个分类页，并写入头部模板

catalog = codecs.open('catalog.txt','r','utf-8')

i=0
name=""
for line in catalog:
	line = line.strip()
	if len(line)>0:
		if i==0:
			date=int(line)
			i=i+1
		elif i==1:
			name=(line.split(':')[1])
			i=i+1
		elif i==2:
			tagstr=""
			if len(line.split(':')) >1 and line.split(':')[1] !="":
				tagstr = line.split(':')[1]
			i=i+1
		elif i==3:
			cat=line.split(':')[1]
			i=0
			postdict[name]=date
			tagdict[name]=tagstr
			catdict[name]=cat

postdict=sorted(postdict.items(), key=itemgetter(1), reverse=True)
print (postdict)
#对所有文章按照发表时间从新到旧排序，新的排在最前

postcnt=len(postdict)
lastpage = math.ceil(postcnt/6)

pagenum=0;

while(postcnt>0):
	maxcnt = min(6,postcnt)
	postcnt = postcnt-maxcnt
	if pagenum==0:
		page = codecs.open('./'+project+'/index.html','w','utf-8')
	else:
		page = codecs.open('./'+project+'/page{0}.html'.format(pagenum),'w','utf-8')
	head = codecs.open('./template/head.html','r','utf-8')
	for tmp in head:
		#tmp = head.readline()
		page.write(tmp)
	head.close()

	for i in range(pagenum*6,pagenum*6+maxcnt):
		postname=postdict[i][0]
		catname = catnamedict[catdict[postname]]
		catpage = codecs.open('./'+project+'/category/'+catname+'.html','a','utf-8')
		page.write('\n
\n'.format(i))
		catpage.write('\n
\n'.format(i))

		shortpost = codecs.open('./shortpost/{0}.html'.format(postdict[i][0]),'r','utf-8')

		for line in shortpost:
			page.write(line)
			catpage.write(line)
		shortpost.close()

		page.write('\n
\n')
		catpage.write('\n
\n')
		catpage.close()
	if pagenum >0:
		if pagenum==1:
			page.write('
← Prev
')
		else:
			page.write('
← Prev
'.format(pagenum-1))
	if pagenum<lastpage-1:
		page.write('
Older →
'.format(pagenum+1))
	foot = codecs.open('./template/foot.html','r','utf-8')
	for line in foot:
		page.write(line)

	page.close()
	pagenum=pagenum+1
	foot.close()

for catpage in catlist:
	tmppage=codecs.open('./'+project+'/category/'+catpage+'.html','a','utf-8')
	foot = codecs.open('./template/foot.html','r','utf-8')
	for line in foot:
		#tmp = head.readline()
		tmppage.write(line)
	foot.close()
	tmppage.close()


# python3 통과
import sys
sys.stdin=open('../input.txt','r')
def BFS(now,fire):
    cnt=0
    while now:
        new_fire=[]
        new_now=[]
        cnt+=1
        for k in fire:
            i,j=k
            if i<h-1 and building[i+1][j]=='.':building[i+1][j]='*';new_fire.append((i+1,j))
            if i>0 and building[i-1][j]=='.':building[i-1][j]='*';new_fire.append((i-1,j))
            if j<w-1 and building[i][j+1]=='.':building[i][j+1]='*';new_fire.append((i,j+1))
            if j>0 and building[i][j-1]=='.':building[i][j-1]='*';new_fire.append((i,j-1))
        for k in now:
            i,j=k
            if i==0 or j==0 or i==h-1 or j==w-1:print(cnt);return
            if i<h-1 and building[i+1][j]=='.':building[i+1][j]='@';new_now.append((i+1,j))
            if i>0 and building[i-1][j]=='.':building[i-1][j]='@';new_now.append((i-1,j))
            if j<w-1 and building[i][j+1]=='.':building[i][j+1]='@';new_now.append((i,j+1))
            if j>0 and building[i][j-1]=='.':building[i][j-1]='@';new_now.append((i,j-1))
        now=new_now
        fire=new_fire
    print('IMPOSSIBLE')
for _ in range(int(input())):
    w,h=map(int,input().split())
    building=[]
    now=[]
    fire=[]
    for i in range(h):
        building.append([*input()])
        for j in range(w):
            if building[i][j]=='@':now.append([i,j])
            elif building[i][j]=='*':fire.append([i,j])
    BFS(now,fire)


game_369 = ['3', '6', '9']

def game(number):
    result = [0] * number
    for i in range(1, number+1):
        game_ct = 0
        for num in str(i):
            if num in game_369:
                game_ct += 1
        if game_ct == 0:
            result[i - 1] = i
        else:
            result[i - 1] = '-' * game_ct
    return result

N = int(input())
print(*game(N))


from flask import Flask
from app.extensions import db, migrate, login_manager
from app.user import user

def create_app():
    app = Flask(__name__)
    app.config.from_pyfile('config.py')

    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)

    app.register_blueprint(user, url_prefix='/user')

    return app


# coding: utf-8

# In[1]:

import requests
import json
from pprint import pprint
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# In[2]:

def view_imdb_data_votes(season_number,episode_number):
    url="http://www.omdbapi.com/?t="
    season="&Season="+str(season_number)
    episode="&Episode="+str(episode_number)
    api_key="&apikey=7329004f"
    response=requests.get(url+"Game of Thrones" +season+episode+api_key)
    data=response.json()
    return data["imdbVotes"]

# In[3]:

def view_imdb_data_ratings(season_number,episode_number):
    url="http://www.omdbapi.com/?t="
    season="&Season="+str(season_number)
    episode="&Episode="+str(episode_number)
    api_key="&apikey=7329004f"
    response=requests.get(url+"Game of Thrones" +season+episode+api_key)
    data=response.json()
    return data["imdbRating"]

# In[4]:

#season_one votes
season_one=[]
for y in range(11):
        try:
            season_one.append(view_imdb_data_votes(1,y))
        except:
                continue

# In[5]:

season_one
for i in range(len(season_one)):
    season_one[i]=int(season_one[i])

# In[6]:

#season_two
season_two=[]
for y in range(11):
        try:
            season_two.append(view_imdb_data_votes(2,y))
        except:
                continue

# In[7]:

season_two
for i in range(len(season_two)):
    season_two[i]=int(season_two[i])

# In[8]:

#season_three
season_three=[]
for y in range(11):
    try:
        season_three.append(view_imdb_data_votes(3,y))
    except:
        continue

# In[9]:

season_three
for i in range(len(season_three)):
    season_three[i]=int(season_three[i])

# In[10]:

#season_four
season_four=[]
for y in range(11):
    try:
        season_four.append(view_imdb_data_votes(4,y))
    except:
        continue

# In[11]:

season_four
for i in range(len(season_four)):
    season_four[i]=int(season_four[i])

# In[12]:

#season_five
season_five=[]
for y in range(11):
    try:
        season_five.append(view_imdb_data_votes(5,y))
    except:
        continue

# In[13]:

season_five
for i in range(len(season_five)):
    season_five[i]=int(season_five[i])

# In[14]:

#season 6
season_six=[]
for y in range(11):
    try:
        season_six.append(view_imdb_data_votes(6,y))
    except:
        continue

# In[15]:

season_six
for i in range(len(season_six)):
    season_six[i]=int(season_six[i])

# In[16]:

#season 7
season_seven=[]
for y in range(8):
        try:
            season_seven.append(view_imdb_data_votes(7,y))
        except:
            continue

# In[17]:

for i in range(len(season_seven)):
    season_seven[i]=int(season_seven[i])

# In[18]:

votes_df=pd.DataFrame({"Season 1":season_one,
                        "Season 2":season_two,
                         "Season 3":season_three,
                          "Season 4":season_four,
                          "Season 5":season_five,
                          "Season 6":season_six,
                          })

# In[19]:

votes_df_season_seven=pd.DataFrame({"Season 7":season_seven})

# In[20]:

#now for the ratings
season_one_ratings=[]
for y in range(11):
        try:
            season_one_ratings.append(view_imdb_data_ratings(1,y))
        except:
            continue

# In[21]:

season_one_ratings
for i in range(len(season_one_ratings)):
    season_one_ratings[i]=float(season_one_ratings[i])

# In[22]:

season_two_ratings=[]
for y in range(11):
    try:
        season_two_ratings.append(view_imdb_data_ratings(2,y))
    except:
        continue

# In[23]:

season_two_ratings
for i in range(len(season_two_ratings)):
    season_two_ratings[i]=float(season_two_ratings[i])

# In[24]:

season_three_ratings=[]
for y in range(11):
    try:
        season_three_ratings.append(view_imdb_data_ratings(3,y))
    except:
        continue

# In[25]:

season_three_ratings
for i in range(len(season_three_ratings)):
    season_three_ratings[i]=float(season_three_ratings[i])

# In[26]:

season_four_ratings=[]
for y in range(11):
    try:
        season_four_ratings.append(view_imdb_data_ratings(4,y))
    except:
        continue

# In[27]:

season_four_ratings
for i in range(len(season_four_ratings)):
    season_four_ratings[i]=float(season_four_ratings[i])

# In[28]:

season_five_ratings=[]
for y in range(11):
    try:
        season_five_ratings.append(view_imdb_data_ratings(5,y))
    except:
        continue

# In[29]:

season_five_ratings
for i in range(len(season_five_ratings)):
    season_five_ratings[i]=float(season_five_ratings[i])

# In[30]:

season_six_ratings=[]
for y in range(11):
    try:
        season_six_ratings.append(view_imdb_data_ratings(6,y))
    except:
        continue

# In[31]:

season_six_ratings
for i in range(len(season_six_ratings)):
    season_six_ratings[i]=float(season_six_ratings[i])

# In[32]:

season_seven_ratings=[]
for y in range(8):
    try:
        season_seven_ratings.append(view_imdb_data_ratings(7,y))
    except:
        continue

# In[33]:

for i in range(len(season_seven_ratings)):
    season_seven_ratings[i]=float(season_seven_ratings[i])

# In[34]:

ratings_df=pd.DataFrame({"Season 1":season_one_ratings,
                         "Season 2":season_two_ratings,
                          "Season 3":season_three_ratings,
                          "Season 4":season_four_ratings,
                          "Season 5":season_five_ratings,
                          "Season 6":season_six_ratings,
                           })

# In[35]:

ratings_season_seven_df=pd.DataFrame({"Season 7":season_seven_ratings})

# In[36]:

x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7","Ep.8","Ep.9","Ep.10"]
y_axis=ratings_df["Season 1"]
plt.plot(x_axis,y_axis, label="Season 1",color="black")
y_axis=ratings_df["Season 2"]
plt.plot(x_axis,y_axis, label="Season 2", color="lightcoral")
y_axis=ratings_df["Season 3"]
plt.plot(x_axis,y_axis, label="Season 3", color="lightskyblue")
y_axis=ratings_df["Season 4"]
plt.plot(x_axis,y_axis, label="Season 4", color="red")
y_axis=ratings_df["Season 5"]
plt.plot(x_axis,y_axis, label="Season 5", color="darkblue")
y_axis=ratings_df["Season 6"]
plt.plot(x_axis,y_axis, label="Season 6", color="green")
x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7"]
y_axis=ratings_season_seven_df
plt.plot(x_axis,y_axis, label="Season 7", color="orange")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.title("Ratings Per Episode in Each Season")
plt.xlabel("Episode")
plt.ylabel("Rating Score")
plt.savefig("RatingsPerEpisodeinEachSeason")
plt.show()

# In[37]:

x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7","Ep.8","Ep.9","Ep.10"]
y_axis=votes_df["Season 1"]
plt.plot(x_axis,y_axis, label="Season 1",color="black")
y_axis=votes_df["Season 2"]
plt.plot(x_axis,y_axis, label="Season 2",color="lightcoral")
y_axis=votes_df["Season 3"]
plt.plot(x_axis,y_axis, label="Season 3",color="lightskyblue")
y_axis=votes_df["Season 4"]
plt.plot(x_axis,y_axis, label="Season 4",color="red")
y_axis=votes_df["Season 5"]
plt.plot(x_axis,y_axis, label="Season 5",color="purple")
y_axis=votes_df["Season 6"]
plt.plot(x_axis,y_axis, label="Season 6",color="green")
x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7"]
y_axis=votes_df_season_seven
plt.plot(x_axis,y_axis, label="Season 7",color="darkblue")
plt.title("IMdB votes per Episode by Season")
plt.xlabel("Episode Number")
plt.ylabel("Number of Votes Per Episode ")
plt.plot(x_axis,y_axis)
plt.legend()
plt.savefig("IMdBvotesperEpisodebySeason")
plt.show()

# In[38]:

avg_rating_season_one=ratings_df["Season 1"].mean()
avg_rating_season_two=ratings_df["Season 2"].mean()
avg_rating_season_three=ratings_df["Season 3"].mean()
avg_rating_season_four=ratings_df["Season 4"].mean()
avg_rating_season_five=ratings_df["Season 5"].mean()
avg_rating_season_six=ratings_df["Season 6"].mean()
avg_rating_season_seven=ratings_season_seven_df.mean()

# In[39]:

x_axis=["Season 1"]
y_axis=avg_rating_season_one
plt.bar(x_axis,y_axis)
x_axis=["Season 2"]
y_axis=avg_rating_season_two
plt.bar(x_axis,y_axis)
x_axis=["Season 3"]
y_axis=avg_rating_season_three
plt.bar(x_axis,y_axis)
x_axis=["Season 4"]
y_axis=avg_rating_season_four
plt.bar(x_axis,y_axis)
x_axis=["Season 5"]
y_axis=avg_rating_season_five
plt.bar(x_axis,y_axis)
x_axis=["Season 6"]
y_axis=avg_rating_season_six
plt.bar(x_axis,y_axis)
x_axis=["Season 7"]
y_axis=avg_rating_season_seven
plt.bar(x_axis,y_axis)
plt.ylim(6.0,10.0)
plt.title("Average Ratings Per Season")
plt.xlabel("Season")
plt.ylabel("Average Rating")
plt.xticks(rotation=45)
plt.savefig("AverageRatingsPerSeason")
plt.show()

# In[40]:

avg_votes_season_one=votes_df["Season 1"].mean()
avg_votes_season_two=votes_df["Season 2"].mean()
avg_votes_season_three=votes_df["Season 3"].mean()
avg_votes_season_four=votes_df["Season 4"].mean()
avg_votes_season_five=votes_df["Season 5"].mean()
avg_votes_season_six=votes_df["Season 6"].mean()
avg_votes_season_seven=votes_df_season_seven.mean()

# In[41]:

x_axis="Season 1"
y_axis=avg_votes_season_one
plt.bar(x_axis,y_axis)
x_axis="Season 2"
y_axis=avg_votes_season_two
plt.bar(x_axis,y_axis)
x_axis="Season 3"
y_axis=avg_votes_season_three
plt.bar(x_axis,y_axis)
x_axis="Season 4"
y_axis=avg_votes_season_four
plt.bar(x_axis,y_axis)
x_axis="Season 5"
y_axis=avg_votes_season_five
plt.bar(x_axis,y_axis)
x_axis="Season 6"
y_axis=avg_votes_season_six
plt.bar(x_axis,y_axis)
x_axis="Season 7"
y_axis=avg_votes_season_seven
plt.bar(x_axis,y_axis)
plt.xticks(rotation=45)
plt.title("Average Votes per Season")
plt.xlabel("Season")
plt.ylabel("Average Number of Votes")
plt.savefig("AverageVotesperSeason")
plt.show()


class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []

        # Define mapping of digits to letters
        mappings = {
            '2': 'abc',
            '3': 'def',
            '4': 'ghi',
            '5': 'jkl',
            '6': 'mno',
            '7': 'pqrs',
            '8': 'tuv',
            '9': 'wxyz'
        }

        # Define recursive function to generate letter combinations
        def generate_combinations(digits, current_combination):
            if not digits:
                # Base case: no more digits to process, add current combination to result
                result.append(current_combination)
            else:
                # Recursive case: process next digit and add all possible letter combinations
                for letter in mappings[digits[0]]:
                    generate_combinations(digits[1:], current_combination + letter)

        # Initialize result list and call recursive function to generate letter combinations
        result = []
        generate_combinations(digits, '')

        return result

Letter Combinations of a Phone Number.py


import pandas as pd
items = pd.read_csv('items.csv',sep = ',')
signup = pd.read_csv('signup.csv',sep = ',')

# 第一步连接两个表，默认内连接就可以
df = pd.merge(left = items,right = signup,on = 'item_id')

# 限定同时满足两个条件，注意item_name是javelin，题目里写错了多了一个n,坑死了！之前复制一直报错
df1 = df[(df['department'] == 'functional')&(df['item_name'] == 'javelin')]

print(df1[['employee_id','name','sex']].reset_index(drop = True))
# 注意重置索引
# reset_index用来重置索引，因为有时候对dataframe做处理后索引可能是乱的。
# drop=True就是把原来的索引index列去掉，重置index。
# drop=False就是保留原来的索引，添加重置的index。
# 两者的区别就是有没有把原来的index去掉


"""
power or exponential of a number base by another number exp is
obtained by recursively multiplying the same number base , exp number of times

"""

def power(base, exp):
  # contraint case
  assert isinstance(base,int) and base >= 0 and int(base) == base,f'Base {base} should be a positive integer'
  assert isinstance(exp,int) and exp >= 0 and int(exp) == exp,f'Exponent {exp} should be a positive integer'
  # base case
  if exp == 0:
    return 1
  if exp == 1:
    return base
  # recursive case
  return base * power(base,exp-1)

if __name__ == "__main__":
  cases = [(6,0),(1,3),(3,1),(4,2),(3.2,2),(2,3.4),(4, -1),('s','s')]
  for i,j in cases:
    try:
      print(f'{i} to the power of {j} is {power(i,j)}')
    except AssertionError as msg:
      print(msg)
  print('Program completed')