from __future__ import annotations

import asyncio
import datetime
import time
from typing import TYPE_CHECKING, List, Optional, Tuple, Union

import asyncpg
import discord
from discord.ext import commands

from utils import (
    AvatarsPageSource,
    AvatarView,
    FieldPageSource,
    Pager,
    format_bytes,
    human_timedelta,
    to_bytes,
    format_status,
    BlankException,
)

from ._base import CogBase

if TYPE_CHECKING:
    from bot import Bot
    from cogs.context import Context

class UserCommands(CogBase):
    @commands.command(name="avatar", aliases=("pfp", "avy", "av"))
    async def avatar(
        self,
        ctx: Context,
        *,
        user: Optional[Union[discord.Member, discord.User]] = commands.Author,
    ):
        """Gets the avatar of a user"""
        user = user or ctx.author

        embed = discord.Embed(
            color=self.bot.embedcolor
            if user.color == discord.Color.default()
            else user.color
        )
        embed.set_author(name=str(user), icon_url=user.display_avatar.url)

        embed.set_image(url=user.display_avatar.url)

        sql = """SELECT created_at FROM avatars WHERE user_id = $1 ORDER BY created_at DESC"""
        latest_avatar = await self.bot.pool.fetchval(sql, user.id)

        if latest_avatar:
            embed.timestamp = latest_avatar
            embed.set_footer(text="Avatar changed")

        await ctx.send(
            embed=embed,
            view=AvatarView(ctx, user, embed, user.display_avatar),
            check_ref=True,
        )

    @commands.command(name="avatars", aliases=("pfps", "avys", "avs"))
    async def avatars(
        self, ctx: Context, user: Union[discord.Member, discord.User] = commands.Author
    ):
        """Shows all of a users avatars"""
        sql = """SELECT * FROM avatars WHERE user_id = $1 ORDER BY created_at DESC"""
        results = await self.bot.pool.fetch(sql, user.id)

        if results == []:
            raise ValueError("User has no avatar history saved.")

        entries: List[Tuple[str, datetime.datetime, int]] = [
            (
                r["avatar"],
                r["created_at"],
                r["id"],
            )
            for r in results
        ]

        source = AvatarsPageSource(entries=entries)
        source.embed.color = (
            self.bot.embedcolor if user.color == discord.Color.default() else user.color
        )
        source.embed.title = f"Avatars for {user}"
        pager = Pager(source, ctx=ctx)
        await pager.start(ctx)

    @commands.command(name="banner")
    async def banner(self, ctx: Context, *, user: discord.User = commands.Author):
        """Shows a users banner"""

        user = await ctx.bot.fetch_user(user.id)
        if user.banner is None:
            raise TypeError("This user has no banner.")

        file = await user.banner.to_file(
            filename=f'banner.{"gif" if user.banner.is_animated() else "png"}'
        )
        embed = discord.Embed()
        embed.set_author(name=f"{str(user)}'s banner", icon_url=user.display_avatar.url)
        embed.set_image(
            url=f'attachment://banner.{"gif" if user.banner.is_animated() else "png"}'
        )
        await ctx.send(file=file, embed=embed)

    async def _index_member(self, guild: discord.Guild, member: discord.Member) -> bool:
        sql = """
        INSERT INTO member_join_logs (member_id, guild_id, time)
        SELECT $1, $2, $3
        WHERE NOT EXISTS (
            SELECT 1
            FROM member_join_logs
            WHERE member_id = $1 AND guild_id = $2 AND time = $3
        );
        """
        await self.bot.pool.execute(
            sql,
            member.id,
            guild.id,
            member.joined_at,
        )

        return True

    @commands.group(name="joins", invoke_without_command=True)
    async def joins(
        self,
        ctx: Context,
        *,
        user: Union[discord.Member, discord.User] = commands.Author,
    ):
        """Shows how many times a user joined a server

        Note: If they joined before I was added then I will not have any data for them."""

        guild = ctx.guild

        results: Optional[int] = await self.bot.pool.fetchval(
            "SELECT COUNT(member_id) FROM member_join_logs WHERE member_id = $1 AND guild_id = $2",
            user.id,
            guild.id,
        )

        if not results:
            if isinstance(user, discord.Member):
                results = await self._index_member(guild, user)

            if results:
                results = 1

            else:
                return await ctx.send(f"I have no join records for {user} in {guild}")

        await ctx.send(
            f"{user} has joined {guild} {results:,} time{'s' if results > 1 else ''}."
        )

    @commands.command(name="uptime")
    async def uptime(self, ctx: Context, *, member: Optional[discord.Member]):
        """Shows how long a user has been online."""
        bot = self.bot
        me = bot.user

        if me is None or bot.uptime is None:
            return

        if member is None or member and member.id == me.id:
            return await ctx.send(
                f"Hello, I have been awake for {human_timedelta(bot.uptime, suffix=False)}."
            )

        if "uptime" in await self.bot.redis.smembers(f"opted_out:{member.id}"):
            raise BlankException(f"Sorry, {member} has opted out from uptime logging.")

        results: Optional[datetime.datetime] = await bot.pool.fetchval(
            "SELECT time FROM uptime_logs WHERE user_id = $1", member.id
        )

        message = (
            f"{member} has been {format_status(member)} for {human_timedelta(results, suffix=False)}."
            if results
            else f"{member} has been {format_status(member)} as long as I can tell."
        )

        await ctx.send(message)

    @commands.command(name="usernames", aliases=("names",))
    async def usernames(self, ctx: Context, user: discord.User = commands.Author):

        results = await self.bot.pool.fetch(
            "SELECT * FROM username_logs WHERE user_id = $1 ORDER BY created_at DESC",
            user.id,
        )

        if results == []:
            await ctx.send(f"I have no username records for {user}.")
            return

        entries = [
            (
                r["username"],
                f'{discord.utils.format_dt(r["created_at"], "R")}  |  {discord.utils.format_dt(r["created_at"], "d")} | `ID: {r["id"]}`',
            )
            for r in results
        ]

        source = FieldPageSource(entries=entries)
        source.embed.color = self.bot.embedcolor
        source.embed.title = f"Usernames for {user}"
        pager = Pager(source, ctx=ctx)
        await pager.start(ctx)

    @commands.command(name="discrims", aliases=("discriminators",))
    async def discrims(self, ctx: Context, user: discord.User = commands.Author):
        """Shows all discriminators a user has had.

        This is the numbers after your username."""

        results = await self.bot.pool.fetch(
            "SELECT * FROM discrim_logs WHERE user_id = $1 ORDER BY created_at DESC",
            user.id,
        )

        if results == []:
            await ctx.send(f"I have no discriminator records for {user}")
            return

        entries = [
            (
                f'#{r["discrim"]}',
                f'{discord.utils.format_dt(r["created_at"], "R")}  |  {discord.utils.format_dt(r["created_at"], "d")} | `ID: {r["id"]}`',
            )
            for r in results
        ]

        source = FieldPageSource(entries=entries)
        source.embed.color = self.bot.embedcolor
        source.embed.title = f"Discriminators for {user}"
        pager = Pager(source, ctx=ctx)
        await pager.start(ctx)

    @commands.command(name="nicknames", aliases=("nicks",))
    async def nicknames(
        self,
        ctx: Context,
        *,
        user: discord.User = commands.Author,
    ):
        """Shows all nicknames a user has had in a guild."""
        if ctx.guild is None:
            return

        results = await self.bot.pool.fetch(
            "SELECT * FROM nickname_logs WHERE user_id = $1 AND guild_id = $2 ORDER BY created_at DESC",
            user.id,
            ctx.guild.id,
        )

        if results == []:
            await ctx.send(f"I have no nickname records for {user} in {ctx.guild}")
            return

        entries = [
            (
                r["nickname"],
                f'{discord.utils.format_dt(r["created_at"], "R")}  |  {discord.utils.format_dt(r["created_at"], "d")} | `ID: {r["id"]}`',
            )
            for r in results
        ]

        source = FieldPageSource(entries=entries)
        source.embed.title = f"Nicknames for {user} in {ctx.guild}"
        source.embed.color = self.bot.embedcolor
        pager = Pager(source, ctx=ctx)
        await pager.start(ctx)

    @commands.group(
        name="avatarhistory",
        aliases=("avyh", "pfph", "avh"),
        invoke_without_command=True,
    )
    async def avatar_history(
        self, ctx: Context, *, user: discord.User = commands.Author
    ):
        """Shows the avatar history of a user.

        This will only show the first 100, to view them all and in HD run the command `avatars`"""

        async with ctx.typing():
            sql = """
            SELECT * FROM avatars WHERE user_id = $1
            ORDER BY created_at DESC LIMIT 100
            """

            records: List[asyncpg.Record] = await self.bot.pool.fetch(
                sql,
                user.id,
            )

            if records == []:
                await ctx.send(f"{user} has no avatar history on record.")
                return

            avatars = await asyncio.gather(
                *[to_bytes(ctx.session, row["avatar"]) for row in records]
            )

            fp = await format_bytes(ctx.guild.filesize_limit, avatars)
            file = discord.File(
                fp,
                f"{user.id}_avatar_history.png",
            )

        if len(records) >= 100:
            first_avatar: datetime.datetime = await self.bot.pool.fetchval(
                """SELECT created_at FROM avatars WHERE user_id = $1 ORDER BY created_at ASC""",
                user.id,
            )
        else:
            first_avatar = records[-1]["created_at"]

        embed = discord.Embed(timestamp=first_avatar)
        embed.set_footer(text="First avatar saved")
        embed.set_author(
            name=f"{user}'s avatar history", icon_url=user.display_avatar.url
        )
        embed.set_image(url=f"attachment://{user.id}_avatar_history.png")

        await ctx.send(embed=embed, file=file)

    @avatar_history.command(name="server", aliases=("guild",))
    async def avatar_history_guild(
        self,
        ctx: Context,
        guild: Optional[discord.Guild] = None,
        *,
        member: discord.Member = commands.Author,
    ):
        """Shows the server avatar history of a user."""
        guild = guild or ctx.guild

        async with ctx.typing():
            sql = """
            SELECT * FROM guild_avatars WHERE member_id = $1 AND guild_id = $2
            ORDER BY created_at DESC LIMIT 100
            """

            fetch_start = time.perf_counter()
            records: List[asyncpg.Record] = await self.bot.pool.fetch(
                sql, member.id, guild.id
            )
            fetch_end = time.perf_counter()

            if records == []:
                raise ValueError(f"{member} has no server avatar history on record.")

            avatars = await asyncio.gather(
                *[to_bytes(ctx.session, row["avatar"]) for row in records]
            )

            gen_start = time.perf_counter()
            fp = await format_bytes(guild.filesize_limit, avatars)
            file = discord.File(
                fp,
                f"{member.id}_avatar_history.png",
            )
            gen_end = time.perf_counter()

        if len(records) == 100:
            sql = """SELECT created_at FROM guild_avatars WHERE member_id = $1 AND guild_id = $1 ORDER BY created_at ASC"""
            first_avatar: datetime.datetime = await self.bot.pool.fetchval(
                sql, member.id, guild.id
            )
        else:
            first_avatar = records[-1]["created_at"]

        embed = discord.Embed(timestamp=first_avatar)
        embed.set_footer(text="First avatar saved")
        embed.set_author(
            name=f"{member}'s guild avatar history", icon_url=member.display_avatar.url
        )
        embed.description = f"`Fetching  :` {round(fetch_end - fetch_start, 2)}s\n`Generating:` {round(gen_end - gen_start, 2)}s"
        embed.set_image(url=f"attachment://{member.id}_avatar_history.png")

        await ctx.send(embed=embed, file=file)


import argparse
import glob
import os
import shutil
import subprocess  # noqa: S404
import sys
from collections import namedtuple
from types import MappingProxyType
from typing import Iterable, List, Optional

HOST_BUILD_CTX = '/tmp/magma_orc8r_build'  # noqa: S108
HOST_MAGMA_ROOT = '../../../.'
IMAGE_MAGMA_ROOT = os.path.join('src', 'magma')

GOLINT_FILE = '.golangci.yml'
TEST_RESULT_DIR = 'orc8r/cloud/test-results'

MODULES = (
    'orc8r',
    'lte',
    'feg',
    'cwf',
    'dp',
)

DEPLOYMENT_TO_MODULES = MappingProxyType({
    'all': MODULES,
    'orc8r': ('orc8r'),
    'fwa': ('orc8r', 'lte'),
    'ffwa': ('orc8r', 'lte', 'feg'),
    'cwf': ('orc8r', 'lte', 'feg', 'cwf'),
})

DEPLOYMENTS = DEPLOYMENT_TO_MODULES.keys()

EXTRA_COMPOSE_FILES = (
    'docker-compose.metrics.yml',
    # For now, logging is left out of the build because the fluentd daemonset
    # and forwarder pod shouldn't change very frequently - we can build and
    # push locally when they need to be updated.
    # We can integrate this into the CI pipeline if/when we see the need for it
    # 'docker-compose.logging.yml',
)

MagmaModule = namedtuple('MagmaModule', ['name', 'host_path'])

def main() -> None:
    """
    Run docker-compose script
    """
    _check_assumptions()

    args = _parse_args()
    mods = _get_modules(DEPLOYMENT_TO_MODULES[args.deployment])

    if not args.extras:
        _create_build_context(mods)

    if args.mount:
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'bash'])
        _down(args)
    elif args.generate:
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'make fullgen'])
        _down(args)
    elif args.lint:
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'make lint'])
        _down(args)
    elif args.tidy:
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'make tidy'])
        _down(args)
    elif args.precommit:
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'make precommit'])
        _down(args)
    elif args.coverage:
        _run(['up', '-d', 'postgres_test'])
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_mnt_vols(mods) + ['test', 'make cover'])
        _down(args)
    elif args.tests:
        _run(['up', '-d', 'postgres_test'])
        _run(['build', 'test'])
        _run(['run', '--rm'] + _get_test_result_vol() + ['test', 'make test'])
        _down(args)
    elif args.build_service:
        _run(['build', args.build_service])
    else:
        d_args = _get_default_file_args(args) + _get_default_build_args(args)
        _run(d_args)

def _check_assumptions():
    """Check assumptions about environment."""
    cwd = os.path.dirname(os.path.realpath(__file__))
    if cwd != os.getcwd():
        sys.exit("Must run from orc8r/cloud/docker directory")

    if 'PWD' not in os.environ:
        msg = (
            "$PWD environment variable must be set.\n"
            "Normally this is set by your shell. Try running without sudo, "
            "then try explicitly setting the PWD env var."
        )
        sys.exit(msg)

def _get_modules(mods: Iterable[str]) -> Iterable[MagmaModule]:
    """
    Read the modules config file and return all modules specified.
    """
    modules = []
    for m in mods:
        abspath = os.path.abspath(os.path.join(HOST_MAGMA_ROOT, m))
        module = MagmaModule(name=m, host_path=abspath)
        modules.append(module)
    return modules

def _create_build_context(modules: Iterable[MagmaModule]) -> None:
    """ Clear out the build context from the previous run """
    shutil.rmtree(HOST_BUILD_CTX, ignore_errors=True)
    os.mkdir(HOST_BUILD_CTX)

    print("Creating build context in '%s'..." % HOST_BUILD_CTX)
    for m in modules:
        _copy_module(m)

def _down(args: argparse.Namespace) -> None:
    if not args.up:
        _run(['down'])

def _run(cmd: List[str]) -> None:
    """ Run the required docker compose command """
    cmd = ['docker', 'compose', '--compatibility'] + cmd
    print("Running '%s'..." % ' '.join(cmd))
    try:
        subprocess.run(cmd, check=True)  # noqa: S603
    except subprocess.CalledProcessError as err:
        sys.exit(err.returncode)

def _get_mnt_vols(modules: Iterable[MagmaModule]) -> List[str]:
    """ Return the volumes argument for docker compose commands """
    vols = [
        # .golangci.yml file
        '-v', '%s:%s' % (
            os.path.abspath(os.path.join(HOST_MAGMA_ROOT, GOLINT_FILE)),
            os.path.join(os.sep, IMAGE_MAGMA_ROOT, GOLINT_FILE),
        ),
    ]
    # Per-module directory mounts
    for m in modules:
        vols.extend(['-v', '%s:%s' % (m.host_path, _get_module_image_dst(m))])
    return vols

def _get_test_result_vol() -> List[str]:
    """Return the volume argment to mount TEST_RESULT_DIR

    Returns:
        List[str]: -v command to mount TEST_RESULT_DIR
    """
    return [
        '-v', '%s:%s' % (
            os.path.abspath(os.path.join(HOST_MAGMA_ROOT, TEST_RESULT_DIR)),
            os.path.join(os.sep, IMAGE_MAGMA_ROOT, TEST_RESULT_DIR),
        ),
    ]

def _get_default_file_args(args: argparse.Namespace) -> List[str]:
    def make_file_args(fs: Optional[Iterable[str]] = None) -> List[str]:
        if fs is None:
            return []
        fs = ['docker-compose.yml'] + \
            list(fs) + ['docker-compose.override.yml']
        ret = []
        for f in fs:
            ret.extend(['-f', f])
        return ret

    if args.all:
        return make_file_args(EXTRA_COMPOSE_FILES)

    # Default implicitly to docker-compose.yml + docker-compose.override.yml
    return make_file_args()

def _get_default_build_args(args: argparse.Namespace) -> List[str]:
    mods = DEPLOYMENT_TO_MODULES[args.deployment]
    ret = [
        'build',
        '--build-arg', 'MAGMA_MODULES=%s' % ' '.join(mods),
    ]
    if args.nocache:
        ret.append('--no-cache')
    return ret

def _copy_module(module: MagmaModule) -> None:
    """ Copy module directory into the build context  """
    build_ctx = _get_module_host_dst(module)

    def copy_to_ctx(d: str) -> None:
        shutil.copytree(
            os.path.join(module.host_path, d),
            os.path.join(build_ctx, d),
        )

    if module.name == 'nms':
        copy_to_ctx('scripts')
    else:
        copy_to_ctx('cloud')

    # Orc8r module also has lib/ and gateway/
    if module.name == 'orc8r':
        copy_to_ctx('lib')
        copy_to_ctx('gateway')

    # Optionally copy cloud/configs/
    # Converts e.g. lte/cloud/configs/ to configs/lte/
    if os.path.isdir(os.path.join(module.host_path, 'cloud', 'configs')):
        shutil.copytree(
            os.path.join(module.host_path, 'cloud', 'configs'),
            os.path.join(HOST_BUILD_CTX, 'configs', module.name),
        )

    # Copy the go.mod file for caching the go downloads
    # Preserves relative paths between modules
    for f in glob.iglob(build_ctx + '/**/go.mod', recursive=True):
        gomod = f.replace(
            HOST_BUILD_CTX, os.path.join(HOST_BUILD_CTX, 'gomod'),
        )
        print(gomod)
        os.makedirs(os.path.dirname(gomod))
        shutil.copyfile(f, gomod)

def _get_module_image_dst(module: MagmaModule) -> str:
    """
    Given a path to a module on the host, return the intended destination
    in the final image.

    Parameters:
        module: Magma module

    Returns:
        str: destination in the final image
    """
    return os.path.join(os.sep, IMAGE_MAGMA_ROOT, module.name)

def _get_module_host_dst(module: MagmaModule) -> str:
    """
    Given a path to a module on the host, return the intended destination
    in the build context.

    Parameters:
        module: Magma module

    Returns:
        str: destination in the build context
    """
    return os.path.join(HOST_BUILD_CTX, IMAGE_MAGMA_ROOT, module.name)

def _parse_args() -> argparse.Namespace:
    """ Parse the command line args """

    # There are multiple ways to invoke finer-grained control over which
    # images are built.
    #
    # (1) How many images to build
    #
    # all: all images
    # default: images required for minimum functionality
    #   - excluding metrics images
    #   - including postgres, proxy, etc
    #
    # (2) Of the core orc8r images, which modules to build
    #
    # Defaults to all modules, but can be further specified by targeting a
    # deployment type.

    parser = argparse.ArgumentParser(description='Orc8r build tool')

    # Run something
    parser.add_argument(
        '--tests', '-t',
        action='store_true',
        help='Run unit tests',
    )
    parser.add_argument(
        '--mount', '-m',
        action='store_true',
        help='Mount the source code and create a bash shell',
    )
    parser.add_argument(
        '--generate', '-g',
        action='store_true',
        help='Mount the source code and regenerate generated files',
    )
    parser.add_argument(
        '--precommit', '-c',
        action='store_true',
        help='Mount the source code and run pre-commit checks',
    )
    parser.add_argument(
        '--lint', '-l',
        action='store_true',
        help='Mount the source code and run the linter',
    )
    parser.add_argument(
        '--tidy', '-i',
        action='store_true',
        help='Mount the source code and run go mod tidy',
    )
    parser.add_argument(
        '--coverage', '-o',
        action='store_true',
        help='Generate test coverage statistics',
    )

    # Build something
    parser.add_argument(
        '--all', '-a',
        action='store_true',
        help='Build all containers',
    )
    parser.add_argument(
        '--extras', '-e',
        action='store_true',
        help='Build extras (non-essential) images (i.e. no proxy or lte)',
    )
    parser.add_argument(
        '--deployment', '-d',
        action='store',
        default='all',
        help='Build deployment type: %s' % ','.join(DEPLOYMENTS),
    )
    parser.add_argument(
        '--build-service', '-b',
        help='Build particular service',
    )

    # How to do it
    parser.add_argument(
        '--nocache', '-n',
        action='store_true',
        help='Build the images with no Docker layer caching',
    )
    parser.add_argument(
        '--up', '-u',
        action='store_true',
        help='Leave containers up after running tests',
    )

    args = parser.parse_args()
    return args

if __name__ == '__main__':
    main()


# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument

import json
from pathlib import Path
from typing import Any, Iterable
from unittest.mock import AsyncMock, call
from uuid import UUID, uuid4

import pytest
from models_library.projects import NodesDict, ProjectID
from models_library.projects_networks import NetworksWithAliases
from models_library.projects_nodes import Node
from pydantic import BaseModel, PositiveInt
from pytest_mock.plugin import MockerFixture
from simcore_service_director_v2.modules.projects_networks import (
    _get_networks_with_aliases_for_default_network,
    _send_network_configuration_to_dynamic_sidecar,
)

# UTILS

class MockedCalls(BaseModel):
    detach: list[Any]
    attach: list[Any]

class Example(BaseModel):
    existing_networks_with_aliases: NetworksWithAliases
    new_networks_with_aliases: NetworksWithAliases
    expected_calls: MockedCalls

    @classmethod
    def using(
        cls,
        existing: dict[str, Any],
        new: dict[str, Any],
        detach: list[Any],
        attach: list[Any],
    ) -> "Example":
        return cls(
            existing_networks_with_aliases=NetworksWithAliases.parse_obj(existing),
            new_networks_with_aliases=NetworksWithAliases.parse_obj(new),
            expected_calls=MockedCalls(detach=detach, attach=attach),
        )

def _node_id(number: int) -> str:
    return f"{UUID(int=number)}"

def _node_alias(number: int) -> str:
    return f"node_alias_{number}"

def _network_name(number: int) -> str:
    return f"network_{number}"

@pytest.fixture
def examples_factory(mock_scheduler: AsyncMock, project_id: ProjectID) -> list[Example]:
    return [
        # nothing exists
        Example.using(
            existing={},
            new={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(2),
                }
            },
            detach=[],
            attach=[
                call.attach_project_network(
                    node_id=UUID(_node_id(2)),
                    project_network=_network_name(1),
                    network_alias=_node_alias(2),
                ),
                call.attach_project_network(
                    node_id=UUID(_node_id(1)),
                    project_network=_network_name(1),
                    network_alias=_node_alias(1),
                ),
            ],
        ),
        # with existing network, remove node 2
        Example.using(
            existing={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(2),
                }
            },
            new={
                _network_name(1): {
                    f"{_node_id(1)}": _node_alias(1),
                }
            },
            detach=[
                call.detach_project_network(
                    node_id=UUID(_node_id(2)),
                    project_network=_network_name(1),
                ),
            ],
            attach=[],
        ),
        # remove node 2 and add node 2 with different alias
        Example.using(
            existing={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(2),
                }
            },
            new={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(3),
                }
            },
            detach=[
                call.detach_project_network(
                    node_id=UUID(_node_id(2)),
                    project_network=_network_name(1),
                ),
            ],
            attach=[
                call.attach_project_network(
                    node_id=UUID(_node_id(2)),
                    project_network=_network_name(1),
                    network_alias=_node_alias(3),
                ),
            ],
        ),
        # nothing happens when updates with the same content
        Example.using(
            existing={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(2),
                }
            },
            new={
                _network_name(1): {
                    _node_id(1): _node_alias(1),
                    _node_id(2): _node_alias(2),
                }
            },
            detach=[],
            attach=[],
        ),
    ]

@pytest.fixture
def mock_scheduler() -> AsyncMock:
    return AsyncMock()

@pytest.fixture
def mock_director_v0_client() -> AsyncMock:
    return AsyncMock()

@pytest.fixture
def rabbitmq_client() -> AsyncMock:
    return AsyncMock()

@pytest.fixture
def project_id() -> ProjectID:
    return uuid4()

@pytest.fixture
def dy_workbench_with_networkable_labels(mocks_dir: Path) -> NodesDict:
    dy_workbench_template = mocks_dir / "fake_dy_workbench_template.json"
    assert dy_workbench_template.exists()

    dy_workbench = json.loads(dy_workbench_template.read_text())

    parsed_workbench: NodesDict = {}

    for node_uuid, node_data in dy_workbench.items():
        node_data["label"] = f"label_{uuid4()}"
        parsed_workbench[node_uuid] = Node.parse_obj(node_data)

    return parsed_workbench

@pytest.fixture
def fake_project_id() -> ProjectID:
    return uuid4()

@pytest.fixture
def user_id() -> PositiveInt:
    return 1

@pytest.fixture
def mock_docker_calls(mocker: MockerFixture) -> Iterable[dict[str, AsyncMock]]:
    requires_dynamic_sidecar_mock = AsyncMock()
    requires_dynamic_sidecar_mock.return_value = True
    class_base = "simcore_service_director_v2.modules.dynamic_sidecar.scheduler._task.DynamicSidecarsScheduler"
    mocked_items = {
        "attach": mocker.patch(f"{class_base}.attach_project_network", AsyncMock()),
        "detach": mocker.patch(f"{class_base}.detach_project_network", AsyncMock()),
        "requires_dynamic_sidecar": mocker.patch(
            "simcore_service_director_v2.modules.projects_networks.requires_dynamic_sidecar",
            requires_dynamic_sidecar_mock,
        ),
    }

    yield mocked_items

async def test_send_network_configuration_to_dynamic_sidecar(
    mock_scheduler: AsyncMock,
    project_id: ProjectID,
    examples_factory: list[Example],
    mock_docker_calls: dict[str, AsyncMock],
) -> None:
    for example in examples_factory:
        await _send_network_configuration_to_dynamic_sidecar(
            scheduler=mock_scheduler,
            project_id=project_id,
            new_networks_with_aliases=example.new_networks_with_aliases,
            existing_networks_with_aliases=example.existing_networks_with_aliases,
        )

        mock_scheduler.assert_has_calls(example.expected_calls.attach, any_order=True)
        mock_scheduler.assert_has_calls(example.expected_calls.detach, any_order=True)

async def test_get_networks_with_aliases_for_default_network_is_json_serializable(
    mock_director_v0_client: AsyncMock,
    fake_project_id: ProjectID,
    dy_workbench_with_networkable_labels: dict[str, Any],
    user_id: PositiveInt,
    rabbitmq_client: AsyncMock,
    mock_docker_calls: dict[str, AsyncMock],
) -> None:
    assert await _get_networks_with_aliases_for_default_network(
        project_id=fake_project_id,
        user_id=user_id,
        new_workbench=dy_workbench_with_networkable_labels,
        director_v0_client=mock_director_v0_client,
        rabbitmq_client=rabbitmq_client,
    )


import os
import sys
import mock
import unittest
import pkg_resources
from pybkick.kick import kick, main as kick_main, MissingSourceCode
from pybkick.pyboard import Pyboard

class TestKick(unittest.TestCase):
    """Test that we can kick code over to the PyBoard
    """

    def testBasicKick(self):
        test_data_path = pkg_resources.resource_filename(__name__, 'test_data')

        kick(
             port='/dev/ttyACM0',
             src=test_data_path,
             entry_point=None
        )

    def testKickFromCommandLine(self):
        test_data_path = pkg_resources.resource_filename(__name__, 'test_data')

        fake_argv = [sys.argv[0], '--src=%s' % test_data_path, '--dst=tmp']
        with mock.patch('sys.argv', fake_argv):
            fake_kick = mock.Mock()
            with mock.patch('pybkick.kick', fake_kick):
                kick_main()
                fake_kick.assert_called_once()

    def testKickMissingDirectory(self):
        missing_test_data_path = os.path.join(pkg_resources.resource_filename(__name__, 'test_data'), 'missing')

        with self.assertRaises(MissingSourceCode):
            kick(
                 port='/dev/ttyACM0',
                 src=missing_test_data_path,
                 dst='tmp',
                 entry_point=None
            )

    def testKickTestData(self):
        test_dir = pkg_resources.resource_filename(__name__, 'test_data')
        port = '/dev/ttyACM0'
        kick(port=port,
             src=test_dir
        )

        pb = Pyboard(port)
        with pb.raw_repl():
            for filename in ['a.txt', 'b.txt']:
                self.assertTrue(pb.file_exists(filename))
                pb.rm(filename)
                self.assertFalse(pb.file_exists(filename))


from flask import Flask
import os.path
app = Flask(__name__)

@app.route("/")
def hello():
    if os.path.exists('/volume/test'):
        return "Hello from pvc!"
    return "Hello World!"

if __name__ == "__main__":
    app.run()


import os
import random
from os import listdir
from os.path import splitext
from tqdm import tqdm
import numpy as np
import cv2
from utils.FileOperator import *

# img_tf_flip(r'E:\Project\Unet-vanilla\data\img_backup',r'E:\Project\Unet-vanilla\data\mask_backup')

# img_tf_flip(r'../data/backup/img', r'../data/backup/mask')
def dir_bit_or(img_dir, mask_dir,dst_dir):
    '''
    将CPU生成图所在文件夹与GPU生成图所在文件夹中所有的图对应地进行按位或操作
    :param img_dir: CPU生成图路径
    :param mask_dir: GPU生成图路径
    :return:
    '''
    img_ids = get_files_name(img_dir)
    mask_ids = get_files_name(mask_dir)
    length = len(img_ids)
    for i in tqdm(range(0, length)):
        img = cv2.imread(fr'{img_dir}/{img_ids[i]}.png')
        t,img = cv2.threshold(img,210,255,cv2.THRESH_BINARY)
        mask = cv2.imread(fr'{mask_dir}/{mask_ids[i]}.png')
        dst = cv2.bitwise_or(img, mask)
        pth = os.path.join(dst_dir,f'{img_ids[i]}_bitor.png')
        ret = cv2.imwrite(pth, dst)
        assert ret, 'save failed'

def copy_mask():
    '''
    复制mask
    :return:
    '''
    img_ids = get_files_name(r'..\data\masks-backup')
    length = len(img_ids)
    for i in tqdm(range(0, length)):
        # print(img_ids[i])
        img = cv2.imread(fr'../data/masks-backup/{img_ids[i]}.png')
        ret = cv2.imwrite(fr'../data/masks/{img_ids[i]}_scratch.png', img)
        assert ret, 'save failed'
        ret = cv2.imwrite(fr'../data/masks/{img_ids[i]}_stain.png', img)
        assert ret, 'save failed'
        ret = cv2.imwrite(fr'../data/masks/{img_ids[i]}_dot.png', img)
        # img = cv2.imread(fr'../data/masks-backup/background.png')
        # ret = cv2.imwrite(fr'../data/temp/{i}_background.png', img)
        assert ret, 'save failed'
        # print(i)
    print('done')

import PIL #'6.2.1'
import cv2 #'4.1.1'

def patchit(root_dir,dst_dir):
    auto_make_directory(dst_dir)
    file_paths = get_files_pth(root_dir)
    for pth in file_paths:
        img = cv2.imread(pth,0)

        auto_make_directory(dst_dir)
        _,img = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
        cv2.imwrite(os.path.join(dst_dir,os.path.basename(pth)),img, [cv2.IMWRITE_PNG_BILEVEL, 1])


from django.contrib import admin
app_name = 'admin'
# Register your models here.
#当前目录下models
from myapp.models import Grades, Students

#创建班级的时候同时创建2个学生
class StudentInfo(admin.TabularInline):
    model = Students
    extra = 2
@admin.register(Grades)
class GradesAdmin(admin.ModelAdmin):
    inlines = [StudentInfo,]
    list_display = ('pk', 'gname', 'gdate','ggirlnum','gboynum','isDelete',)
    list_filter = ('gname',)
    search_fields = ('gname',)
    list_per_page = 5
    #添加修改页属性
    fields = ('ggirlnum', 'gboynum', 'gname', 'gdate',)
   #fieldsets = []

@admin.register(Students)
class StudentsAdmin(admin.ModelAdmin):
    def gender(self):
        if self.sgender:
            return '男'
        else:
            return '女'
    #列名
    gender.short_description = '性别'
    list_display = ('pk', 'sname', 'sage',gender,'scontend', 'sgrade', 'isDelete',)
    list_per_page = 5
    #actions_on_top = Flase

#admin.site.register(Grades, GradesAdmin)
#admin.site.register(Students,StudentsAdmin)


import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

import argopandas as argo

wmos = [4902596, 4902597]

var_names = ['PRES', 'TEMP', 'PSAL', 'DOXY', 'CHLA', 'BBP700']

for wmo in wmos:
    ix   = argo.float(wmo).synthetic_prof
    up   = ix.subset_direction('asc')
    down = ix.subset_direction('desc')

    up['CYCLE']   = [int(f[-6:-3]) for f in up.file]
    down['CYCLE'] = [int(f[-7:-4]) for f in down.file]

    cycles = set(up.CYCLE.unique()).intersection(down.CYCLE.unique())

    for cycle in cycles:
        fig, ax  = plt.subplots()
        up_sub   = up.loc[up.CYCLE == cycle]
        down_sub = down.loc[down.CYCLE == cycle]

        up_data   = up_sub.levels
        down_data = down_sub.levels

        sns.lineplot(data=up_data, x='DOXY', y='PRES', sort=False, estimator=None, ax=ax)
        sns.lineplot(data=down_data, x='DOXY', y='PRES', sort=False, estimator=None, ax=ax)

        ax.set_ylim((200,0))


from string import ascii_lowercase

from behave import given, then
from toolium.utils.dataset import map_param

from common.utils import assert_arrays_equal, payload_to_table_format, replace_param

@given("there is {chore_types:d} chore type")
@given("there are {chore_types:d} chore types")
def step_create_chore_types(context, chore_types):
    for i in range(chore_types):
        raw_data = {
            "id": f"ct-{ascii_lowercase[i]}",
            "name": f"ct-{ascii_lowercase[i]}",
            "description": f"description{i+1}",
        }
        context.execute_steps(
            f"""
            Given I use the admin API key
            When I send a request to the Api resource "createChoreType" with body params
            {payload_to_table_format(raw_data)}
            Then the response status code is "200"
            And I clear the token
            """
        )

@then('the response contains the chores "{ids}"')
def step_response_contains_chores(context, ids):
    ids = replace_param(ids)
    if not ids:
        ids = []
    elif isinstance(ids, str):
        ids = list(map(int, ids.replace(" ", "").split(",")))
    elif isinstance(ids, int):
        ids = [ids]

    original = map_param("[CONF:examples.simple_chore_types]")
    res_json = context.res.json()

    for field_name in ("completed_at", "created_at"):
        for item in res_json:
            del item[field_name]

    expected = [original[x - 1] for x in ids]

    assert_arrays_equal(expected, res_json)


import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
# nodes=['A','B','C','D','E','F','1']

dataset = pd.read_csv("./topology.csv", header=None)
lenth = dataset.shape[0]
G=nx.Graph()
edges=[]
for i in range(lenth):
    edges.append((dataset.values[i, 0], dataset.values[i, 1]))

r=G.add_edges_from(edges)

# shortest_way=nx.shortest_path(G,"F","D")
# print(shortest_way)
#
# nx.draw(G, with_labels=True,node_color='r', node_size=50,)
# plt.show()

options = {"node_color": "red", "node_size": 300, "linewidths": 0, "width": 0.1, "with_labels": True}
pos = nx.spring_layout(G, random_state=1969)  # Seed for reproducible layout
nx.draw(G, pos, **options)
plt.show()


"""fitnesspro URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import re_path, include

from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import re_path
from fitnessproapp import views

urlpatterns = [
    re_path('admin/', admin.site.urls),

    re_path(r'^$', views.login, name='login'),
    re_path(r'^Forgot_password$',views.Forgot_password, name='Forgot_password'),
    re_path(r'^index/$', views.index, name='index'),
    re_path(r'^User_profile/$',views.User_profile,name='User_profile'),
    re_path(r'^User_edit_profile/$',views.User_edit_profile,name='User_edit_profile'),
    re_path(r'^about/$', views.about, name='about'),
    re_path(r'^classes/$', views.classes, name='classes'),
    re_path(r'^train/$', views.train, name='train'),
    re_path(r'^selecttrainer/$', views.selecttrainer, name='selecttrainer'),
    re_path(r'^shedule/$', views.shedule, name='shedule'),
    re_path(r'^contact/$', views.contact, name='contact'),
    re_path(r'^signup/$', views.signup, name='signup'),
    re_path(r'^userpaymentpage/$', views.userpaymentpage, name='userpaymentpage'),
    re_path(r'^online_training/$', views.online_training, name='online_training'),
    re_path(r'^offline_training/$', views.offline_training, name='offline_training'),
    re_path(r'^onlin/$', views.onlin, name='onlin'),
    re_path(r'^onedit/(?P<i_id>[0-9]+)/$', views.onedit, name='onedit'),
    re_path(r'^onlineedit/(?P<oned_id>[0-9]+)/$', views.onlineedit, name='onlineedit'),
    re_path(r'^offlin/$', views.offlin, name='offlin'),
    re_path(r'^Usert_profile/$',views.Usert_profile,name='Usert_profile'),
    re_path(r'^Usert_edit_profile/$',views.Usert_edit_profile,name='Usert_edit_profile'),
    re_path(r'^offedit/(?P<i_id>[0-9]+)/$', views.offedit, name='offedit'),
    re_path(r'^offlineedit/(?P<offd_id>[0-9]+)/$', views.offlineedit, name='offlineedit'),
    re_path(r'^staffd/$', views.staffd, name='staffd'),
    re_path(r'^maint/$', views.maint, name='maint'),
    re_path(r'^admhome/$', views.admhome, name='admhome'),
    re_path(r'^admreg/$', views.admreg, name='admreg'),
    re_path(r'^admregedit/(?P<i_id>[0-9]+)/$', views.admregedit, name='admregedit'),
    re_path(r'^admregistration/(?P<reg_id>[0-9]+)/$', views.admregistration, name='admregistration'),
    re_path(r'^admintimetable/$', views.admintimetable, name='admintimetable'),
    re_path(r'^admin_view_timetable/$', views.admin_view_timetable, name='admin_view_timetable'),
    re_path(r'^admin_edit_timetable/(?P<i_id>[0-9]+)/$', views.admin_edit_timetable, name='admin_edit_timetable'),
    re_path(r'^admin_editpage/(?P<timet_id>[0-9]+)/$', views.admin_editpage, name='admin_editpage'),
    re_path(r'^delete_batch/(?P<p_id>[0-9]+)/$', views.delete_batch, name='delete_batch'),
    re_path(r'^admin_userpayment/$', views.admin_userpayment, name='admin_userpayment'),
    re_path(r'^admin_payment/$', views.admin_payment, name='admin_payment'),
    re_path(r'^admin_pay_page/$', views.admin_pay_page, name='admin_pay_page'),
    re_path(r'^Trainee_logout/$', views.Trainee_logout, name='Trainee_logout'),
    re_path(r'^Trainer_logout/$', views.Trainer_logout, name='Trainer_logout'),
    re_path(r'^SuperAdmin_logout/$', views.SuperAdmin_logout, name='SuperAdmin_logout'),

]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


import pygame
import random
import rospy
import math
from geometry_msgs.msg import TwistStamped
from geometry_msgs.msg import PoseStamped
from armf import armtakeoff

rospy.init_node('make_a_circle', anonymous=True)

current_pos = PoseStamped()

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()

    x_curser1 = 160
    y_curser1 = 240
    x_curser2 = 480
    y_curser2 = 240
    mode= ''
    count = 0
    radius = 10
    screen.fill((0, 0, 0))

    color_curser1 = (0,255,0)
    color_curser2 = (0,255,0)
    pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
    pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)

    arm = armtakeoff()
    arm.arm()
    arm.takeoff()

    while True:

        screen.fill((0, 0, 0))
        x_curser1 = 160
        y_curser1 = 240
        x_curser2 = 480
        y_curser2 = 240

        pressed = pygame.key.get_pressed()

        alt_held = pressed[pygame.K_LALT] or pressed[pygame.K_RALT]
        ctrl_held = pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]

        for event in pygame.event.get():

            # determin if X was clicked, or Ctrl+W or Alt+F4 was used
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w and ctrl_held:
                    return
                if event.key == pygame.K_F4 and alt_held:
                    return
                if event.key == pygame.K_ESCAPE:
                    return

                # determine if a letter key was pressed
                if event.key == pygame.K_w:
                    mode = 'up'
                elif event.key == pygame.K_s:
                    mode = 'down'
                elif event.key == pygame.K_d:
                    mode = 'right'
                elif event.key == pygame.K_a:
                    mode = 'left'
                elif event.key == pygame.K_SPACE:
                    mode = 'jump'
                elif event.key == pygame.K_q:
                    mode = 'yaw'
                elif event.key == pygame.K_e:
                    mode = 'yawri8'
                elif event.key == pygame.K_LCTRL:
                    mode = 'low'
                elif event.key == pygame.K_h:
                    mode = 'hold'

        color_curser1 = (255,0,0)
        color_curser2 = (255,0,0)
        color_curser3 = (0,0,255)
        color_curser4 = (0,0,255)

        pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
        pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)

        x_curser1,y_curser1,x_curser2,y_curser2 = curserControl(screen,x_curser1,y_curser1,x_curser2,y_curser2,mode,count,color_curser1,color_curser1,radius)

        pygame.draw.circle(screen, color_curser3, (x_curser1, y_curser1), radius)
        pygame.draw.circle(screen, color_curser4, (x_curser2, y_curser2), radius)

        pygame.display.flip()

        clock.tick(60)

def curserControl(screen,x_curser1,y_curser1,x_curser2,y_curser2,mode,count,color_curser1,color_curser2,radius):

    publish_velocity=rospy.Publisher('/mavros/setpoint_velocity/cmd_vel', TwistStamped,queue_size=20)
    vel=TwistStamped()

    if mode == 'up':

        vel.twist.linear.x= 0.8
        vel.twist.linear.z= 0
        publish_velocity.publish(vel)
        vel.twist.linear.x= 0
        y_curser1= y_curser1 -20
        pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
        print("up")
    elif mode == 'down':
        vel.twist.linear.x= -0.8
        vel.twist.linear.z= 0
        publish_velocity.publish(vel)
        vel.twist.linear.x= 0
        y_curser1= y_curser1 +20
        pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
        print("down")
    elif mode == 'right':
        vel.twist.linear.z= 0
        vel.twist.linear.y= -0.8
        publish_velocity.publish(vel)
        vel.twist.linear.y= 0
        x_curser1= x_curser1 +20
        pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
        print("right")
    elif mode == 'left':

        vel.twist.linear.y= 0.8
        vel.twist.linear.z= 0
        publish_velocity.publish(vel)
        vel.twist.linear.y= 0
        x_curser1= x_curser1 -20
        pygame.draw.circle(screen, color_curser1, (x_curser1, y_curser1), radius)
        print("left")
    elif mode == 'jump':

        vel.twist.linear.z= 1
        publish_velocity.publish(vel)
        vel.twist.linear.z= 0
        y_curser2= y_curser2 -20
        pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)

        print("jump")
    elif mode == 'low':

        vel.twist.linear.z= -0.5
        publish_velocity.publish(vel)
        vel.twist.linear.z= 0
        y_curser2= y_curser2 +20
        pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)
        print("low")

    elif mode == 'yaw':

        vel.twist.angular.z= 0.8
        vel.twist.linear.z= 0
        publish_velocity.publish(vel)
        vel.twist.linear.z= 0
        x_curser2= x_curser2 -20
        pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)
        print("yawleft")

    elif mode == 'yawri8':

        vel.twist.angular.z= -0.8
        vel.twist.linear.z= 0
        publish_velocity.publish(vel)
        vel.twist.linear.z= 0
        x_curser2= x_curser2 +20
        pygame.draw.circle(screen, color_curser2, (x_curser2, y_curser2), radius)
        print("yawri8")
    elif mode == 'hold':

        vel.twist.angular.z= 0
        publish_velocity.publish(vel)
        print("hold")

    return x_curser1, y_curser1 ,x_curser2, y_curser2

main()


import asyncio
from typing import *
from urllib.parse import urlencode
from datetime import datetime
from pprint import pformat as pf
import logging
logging.basicConfig(format='%(asctime)s %(message)s')
import jikanpy
from enum import Enum
from copy import copy, deepcopy
from pprint import pprint
import traceback

import aiohttp
import dotenv
import asyncio
from fuzzywuzzy import fuzz
from expiring_dict import ExpiringDict

from core import getLogger, stopwatch

log = getLogger(__name__)

class MALRatings(Enum):
    g = "G - All Ages"
    pg = "PG - Children"
    pg_13 = "PG-13 - Teens 13 or older"
    r = "R - 17+ (violence & profanity) "
    r_plus = "R+ - Mild Nudity 17+"
    rx = "Rx - Hentai 18+"

class MALTypes(Enum):
    ANIME = 1
    MANGA = 2

class MyAnimeListAIOClient:
    """Wrapper for MyAnimeList API Endpoint"""
    client_id: str = ""
    TTL = 60*60
    response_cache = ExpiringDict(ttl=TTL)

    def __init__(
        self,
        client_id: str = None,
    ):
        """A wrapper for the Non-user based mal api endpoints (-> no oauth needed)"""
        self.log = logging.getLogger(__name__)
        self.log.setLevel(logging.INFO)
        self._id = client_id or self.client_id or dotenv.dotenv_values()["ID"]
        if not self._id and not self.client_id:
            raise RuntimeError(
                "Client id has to be passed into the constructor or in the .env file under key `ID`. Consider calling `set_credentails`"
            )
        self._base_url = r"https://api.myanimelist.net/v2"
        self._session = None

    @classmethod
    def set_credentials(cls, client_id: str):
        """"set the client id"""
        cls.client_id = client_id

    @property
    def session(self) -> aiohttp.ClientSession:
        """Get AioHTTP session by creating it if it doesn't already exist"""
        if not self._session or self._session.closed:
            self._session = aiohttp.ClientSession()
        return self._session

    async def _make_request(
        self,
        endpoint: str,
        value: Optional[str] = None,
        optional_query: Dict[str, str] = None,
    ) -> Dict[str, Any]:
        query = None
        if value and not value.startswith("/"):
            value = "/" + value
        if optional_query:
            query = f"?{urlencode(optional_query)}"
        url = f"{self._base_url}/{endpoint}{value or ''}{query or ''}"
        async with self.session.get(url, headers=self.headers) as resp:
            json = await resp.json(encoding="utf-8")
        await self._session.close()
        self.log.debug(f"request: {url}")
        self.log.debug(f"response: {pf(json)}")
        if not resp.ok:
            raise RuntimeError(f"{url} returned status code {resp.status}")
        return json

    @property
    def headers(self) -> Dict[str, str]:
        if not self._id:
            raise RuntimeError("Client id has to be passed into the constructor or in the .env file under key `ID`")
        return {"X-MAL-CLIENT-ID": self._id}

    async def fetch_anime(
        self,
        id: int
    ) -> Dict[str, Any]:
        """fetch an Anime by it's ID

        Args:
        -----
        id : int
            the mal ID of that anime
        """
        fields = (
            "id,title,main_picture,alternative_titles,"
            "start_date,end_date,synopsis,mean,rank,popularity,"
            "num_list_users,num_scoring_users,nsfw,created_at,"
            "updated_at,media_type,status,genres,my_list_status,"
            "num_episodes,start_season,broadcast,source,"
            "average_episode_duration,rating,pictures,background,"
            "related_anime,related_manga,recommendations,studios,statistics,"
            "average_episode_duration,opening_themes,ending_themes"
        )
        resp = await self._make_request(
            endpoint="anime",
            value=str(id),
            optional_query={"fields": fields}
        )
        return resp

    async def _search(self):
        pass

    async def search_anime(self, query: str, include_nsfw=True, fallback: bool = False) -> Dict[str, Any]:
        """search for anime by name

        Args:
        -----
        query : str
            the query to search for
        include_nsfw : bool
            whether to include nsfw results
        fallback : bool
            whether or not to limit the query to 50 chars
        Returns:
        --------
        Dict[str, Any]
            the response json
        """
        try:
            resp = self.response_cache[query]
            return deepcopy(resp)
        except KeyError:
            pass
        fields = (
            "id,title,main_picture,alternative_titles,"
            "start_date,end_date,synopsis,mean,rank,popularity,"
            "num_list_users,num_scoring_users,nsfw,created_at,"
            "updated_at,media_type,status,genres,my_list_status,"
            "num_episodes,start_season,broadcast,source,"
            "average_episode_duration,rating,pictures,background,"
            "related_anime,related_manga,recommendations,studios,statistics,"
            "average_episode_duration,opening_themes,ending_themes"
        )
        a = datetime.now()
        kwargs = {"nsfw": "true" if include_nsfw else "false"}
        try:
            resp = await self._make_request(
                endpoint="anime",
                optional_query={
                    "q": query,
                    "fields":fields,
                    "limit":"50",
                    **kwargs
            })
        except RuntimeError as e:
            if fallback:
                log.warning(f"Error while fetching anime - title len = {len(query)}")
                log.warning(traceback.format_exc())
                return None
            else:
                log.warning(f"fallback search for title {query}")
                return await self.search_anime(query[:50], include_nsfw, True)
        log.info(f"fetched {len(resp['data'])} anime in {(datetime.now() - a).total_seconds():.2f}s")
        self.response_cache.ttl(query, deepcopy(resp), self.TTL)
        return deepcopy(resp)


#유기농 배추
from collections import deque
def bfs(x,y):
    queue = deque()
    queue.append((x,y))
    graph[x][y] = 0
    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<n and 0<=ny<m and graph[nx][ny] == 1:
                queue.append((nx,ny))
                graph[nx][ny] = 0
    return

graph = []
dx = [-1,1, 0, 0]
dy = [0,0,-1,1]
t = int(input())
for _ in range(t):
    cnt = 0
    m, n, k = map(int, input().split())
    graph = [[0 for _ in  range(m)] for _ in range(n)]
    for _ in range(k):
        x, y =  map(int, input().split())
        graph[y][x] = 1
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 1:
                bfs(i,j)
                cnt += 1
    print(cnt)


"""
https://leetcode.com/problems/maximum-ice-cream-bars/
1833. Maximum Ice Cream Bars

It is a sweltering summer day, and a boy wants to buy some ice cream bars.
At the store, there are n ice cream bars. You are given an array costs of length n, where costs[i] is the price of the ith ice cream bar in coins. The boy initially has coins coins to spend, and he wants to buy as many ice cream bars as possible.
Return the maximum number of ice cream bars the boy can buy with coins coins.
Note: The boy can buy the ice cream bars in any order.
"""
from typing import List

class Solution:
    def maxIceCream(self, costs: List[int], coins: int) -> int:
        answer = 0
        freq = [0] * (max(costs) + 1)

        # Fill in the list of frequency
        # (each index is cost of icecream)
        for cost in costs:
            freq[cost] += 1

        for cost, amount in enumerate(freq):
            # If frequency is 0, skip it
            if freq[cost] == 0:
                continue
            # If cost * amount is less than coins,
            # simply decrease the coins by cost * amount
            if amount * cost <= coins:
                coins -= amount * cost
                answer += amount
                continue
            # At this point we cannot buy amount * cost
            # So coins // cost should be the amount of icecream we can buy
            answer += coins // cost
            # And don't forget to exist loop
            # (we can't buy icecreams anymore)
            break

        return answer


from sqlite3 import IntegrityError, Connection

import schema
from flask import g
from flask import request
from flask import Blueprint
from flask.views import MethodView
from werkzeug.exceptions import abort

from flaskr import settings
from flaskr.utils.auth import login_required
from flaskr.utils.db import get_db, get_all_posts, get_post, get_all_comments

bp_index = Blueprint("index", __name__, url_prefix='/api')
bp = Blueprint("post", __name__, url_prefix="/api/post")
bp_comment = Blueprint("comment", __name__, url_prefix='/api/comment')

class Index(MethodView):
    def get(self):
        """
        Get posts.
        :return json 200: List[Post]
        """
        return dict(posts=get_all_posts())

class Post(MethodView):
    def get(self):
        """
        Get posts.
        :return json 200: List[Post]
        """
        return dict(posts=get_all_posts())

    @staticmethod
    def post_schema(from_dict: dict) -> dict:
        try:
            data = schema.Schema({
                "title": schema.And(str, lambda x: settings.POST_TITLE_MIN_WORDS_LENGTH <= len(x) <= settings.POST_TITLE_MAX_WORDS_LENGTH),
                "body": schema.And(str, lambda x: settings.POST_BODY_MIN_WORDS_LENGTH <= len(x) <= settings.POST_BODY_MAX_WORDS_LENGTH)
            }).validate(from_dict)
        except schema.SchemaError:
            raise abort(400, "Wrong args.")
        else:
            return data

    @login_required
    def post(self):
        """
        Create a post
        :param form title: post title
        :param form body: post content text
        :return json 201: Post
        """
        data = self.post_schema(dict(request.form))

        db: Connection = get_db()

        try:
            with db:
                cur = db.cursor()
                cur.execute(
                    "INSERT INTO post (title, body, author_id) VALUES (?, ?, ?)",
                    (data['title'], data['body'], g.user["id"]),
                )
        except IntegrityError:
            raise abort(400, "Duplicated data")

        post = get_post(post_id=cur.lastrowid)
        return dict(post), 201

class PostId(MethodView):
    def get(self, post_id: int):
        """
        Get post by specific id
        :param int post_id: id of post
        :return json 200: Post
        """
        post = get_post(post_id=post_id)

        if post is None:
            abort(404, f"Post id {post_id} doesn't exist.")

        return post

def comment_schema(form_dict: dict) -> dict:
    try:
        data = schema.Schema({
            "body": schema.And(
                str,
                lambda x: settings.COMMENT_BODY_MIN_WORDS_LENGTH <= len(x) <= settings.COMMENT_BODY_MAX_WORDS_LENGTH
            )
        }).validate(form_dict)
    except schema.SchemaError:
        raise abort(400, "Wrong args.")
    else:
        return data

class PostIdComment(MethodView):
    def get(self, post_id: int):
        """
        Get all comments of a post
        :param: int post_id:
        :return json 200: {"comments": List[Comment]}
        """
        return dict(comments=get_all_comments(post_id=post_id))

    @login_required
    def post(self, post_id: int):
        """
        Add a comment to post
        :param int post_id:
        :param form body:  comment content text
        :return json 201: Post
        """
        data = comment_schema(dict(request.form))
        db = get_db()
        with db:
            cur = db.cursor()
            cur.execute("INSERT INTO comment (author_id, body, parent_id, post_id) VALUES (?, ?, ?, ?)",
                        (g.user['id'], data['body'], None, post_id))

        return get_post(post_id), 201

class CommentId(MethodView):
    def get(self, comment_id: int):
        """
        Get a comment.
        :param int comment_id:
        :return json 200: Comment
        """
        row = get_db().execute("SELECT id, post_id, created, body FROM comment WHERE id=?", (comment_id, )).fetchone()
        if not row:
            raise abort(400, f'Comment {comment_id} not found.')
        return dict(row)

class CommentIdComment(MethodView):
    @login_required
    def post(self, comment_id: int):
        """
        Add a comment of a comment.
        Login required
        :param int comment_id: id of comment
        :param form body: comment content text
        :param form body: comment content text
        :raise 401 Login required:
        :return json 201: Post
        """
        data = comment_schema(dict(request.form))
        db = get_db()
        comment = db.execute(
            "SELECT post_id FROM comment WHERE id=?",
            (comment_id, )
        ).fetchone()
        if not comment:
            raise abort(400, f"Comment not found.")

        with db:
            cur = db.cursor()
            cur.execute("INSERT INTO comment (author_id, body, parent_id, post_id) VALUES (?, ?, ?, ?)",
                        (g.user['id'], data['body'], comment_id, comment['post_id']))

        return get_post(comment['post_id']), 201

bp_index.add_url_rule('/', view_func=Index.as_view('Index'))
bp.add_url_rule('/<int:post_id>/comment', view_func=PostIdComment.as_view('PostIdComment'))
bp.add_url_rule('/<int:post_id>', view_func=PostId.as_view('PostId'))
bp.add_url_rule('/', view_func=Post.as_view('Post'))

bp_comment.add_url_rule('/<int:comment_id>/comment',
                        view_func=CommentIdComment.as_view('PostIdCommentIdComment'))
bp_comment.add_url_rule('/<int:comment_id>', view_func=CommentId.as_view('PostIdCommentId'))


# -*- coding:utf-8 -*-
my_name = "分数"
import pygame

pygame.init()
my_font = pygame.font.SysFont("simSun", 66)
name_surface = my_font.render(u'分数', True, (0, 0, 0), (255, 255, 255))

pygame.image.save(name_surface, "name.png")

enemy_hit_dict = dict()

score = 0

ENEMY_SCORE = 100

# enemy_hit_dict = pygame.sprite.groupcollide(enemy_group, hero.bullets, True, True)
# score += len(enemy_hit_dict) * ENEMY_SCORE;  # 计算得分
# enemy_hit_group.add(enemy_hit_dict)

screen = pygame.display.set_mode((480, 700))
bg = pygame.image.load("./images/background.png")
# 2、使用blit方法将背景绘制在屏幕的(0,0)位置
screen.blit(bg, (0, 0))
screen.blit(name_surface, (20, 20))
# 3、更新屏幕
pygame.display.update()


"""web URL Configuration"""

from django.conf.urls import include,url
from django.contrib import admin
from . import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),

	url(r'^$', views.index, name='index'),
    url(r'^pdx/(?P<pk>\w{0,50})/$', views.pdx, name="pdx"),
    url(r'^search/', views.search, name="search"),
    #url(r'^search/', include('haystack.urls')),
    url(r'^resources/', views.resources, name="resources"),
]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 11 10:56:48 2020

@author: alexanderfalk
"""

import itertools
import time
import sys

class ThreeOPT:

    def __init__(self, computed_solution, time_limit=60):
        self.solution = computed_solution
        self.time_limit = time_limit

    def construct(self, time_left):
        return self.algorithm(time_left)

    def algorithm(self, start_time):
        for index, route in enumerate(self.solution.routes):
            segments = self.tour_segments(route)
            for i, j, k in segments:
                self.solution.routes[index] = self.improvement(route, i, j, k)

                t1 = time.time() # End time
                if t1 - start_time > self.time_limit:
                    sys.stdout.write("Time Expired\n")
                    return self.solution

        return self.solution

    def distance(self, i, j):
        return self.solution.instance.pre_distance(i, j)

    def tour_segments(self, route):
        indices = [index for index in range(len(route))]
        return list(itertools.combinations(indices, r = 3))

    def improvement(self, route, i, j, k):
        A, B, C, D, E, F = route[i-1], route[i], route[j-1], route[j], route[k-1], route[k % len(route)]
        dist0 = self.distance(A, B) + self.distance(C, D) + self.distance(E, F)
        dist1 = self.distance(A, C) + self.distance(B, D) + self.distance(E, F)
        dist2 = self.distance(A, B) + self.distance(C, E) + self.distance(D, F)
        dist3 = self.distance(A, D) + self.distance(E, B) + self.distance(C, F)
        dist4 = self.distance(F, B) + self.distance(C, D) + self.distance(E, A)

        if dist0 > dist1:
            route[i:j] = reversed(route[i:j])

        elif dist0 > dist2:
            route[j:k] = reversed(route[j:k])

        elif dist0 > dist4:
            route[i:k] = reversed(route[i:k])

        elif dist0 > dist3:
            route[i:k] = route[j:k] + route[i:j]

        return route


# THIS FILE IS SAFE TO EDIT. It will not be overwritten when rerunning go-raml.

from flask import jsonify, request
import sqlite3

def books_postHandler():
    connection = sqlite3.connect("BookStore")
    cursor=connection.cursor()
    inputs = request.get_json()
    cursor.execute("CREATE TABLE IF NOT EXISTS BookStore (BookId INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT,subTitle TEXT,authors TEXT)")
    cursor.execute("INSERT INTO BookStore VALUES(NULL,?,?,?)", (inputs["title"],inputs["subTitle"],inputs["authors"]))
    connection.commit()
    connection.close()
    return jsonify("successfully")


"""
Запуск класса с датасетами твитов и генома ВИЧ
"""
import Hyperbolic
import numpy as np
import Levenshtein as Lev
import pandas as pd
from grad_descent import MSE
import draw

"""
ТВИТЫ
"""
positive = np.array(pd.read_csv(
    r'twitter_data/positive.csv', sep=';', usecols=[3], names=['text']))
negative = np.array(pd.read_csv(
    r'twitter_data/negative.csv', sep=';', usecols=[3], names=['text']))

# positive_90 = np.array(
#     positive[positive['text'].apply(lambda text: len(text) == 90)])
# negative_90 = np.array(
#     negative[negative['text'].apply(lambda text: len(text) == 90)])

size = 50
dataset = np.concatenate((positive[np.random.choice(
    len(positive), size)], negative[np.random.choice(len(negative), size)]))

perm = np.random.permutation(2*size)
ran = np.array(range(2*size))
map = {perm[i]: ran[i] for i in range(2*size)}

dataset = dataset[perm]

distance = np.zeros((2*size, 2*size), dtype=float)

for i in range(2*size):
    for j in range(2*size):
        distance[i, j] = Lev.distance(dataset[i, 0], dataset[j, 0])

distance = distance / 10.

H = Hyperbolic.Hyperbolic(graph=distance, dimension=2, maxiter=1000, batch=1.)
print("MSE %f" % MSE(H.point_coordinates, distance))

draw.draw(H.point_coordinates, distance,
          draw_edges=False, map=map, annotate=False)

"""
Геном вич
"""

# lst = np.array([]).reshape(0, 0)
# for i in range(100):
#     f = open(rf'data/sequence ({i}).txt', 'r')
#     string = f.read().replace("\n", "")
#     tmp = list(string.encode())
#     if i == 0:
#         lst = np.array(tmp).reshape(1, -1)
#     else:
#         lst = np.vstack((lst, np.array(tmp).reshape(1, -1)))
# # создал пустой интовый массив для расстояний
# distance = np.zeros((100, 100), dtype=float)
# # заполнил его правильными значениями
# for i in range(100):
#     for j in range(100):
#         distance[i, j] = (lst[i] != lst[j]).sum()

# distance = distance / 3.
# H = Hyperbolic.Hyperbolic(graph=distance, dimension=2, maxiter=100, batch=0.1)
# draw.draw(H.point_coordinates, distance, True, annotate=False)


import geoip2.database
"""
Requirements:
    geoip2
    use this page to download the db:
      https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en
"""
# This creates a Reader object. You should use the same object
# across multiple requests as creation of it is expensive.
with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader:

    # Replace "city" with the method corresponding to the database
    # that you are using, e.g., "country".
    response = reader.city('203.0.113.0')
    print(
        response.country.iso_code +
        response.country.name +
        response.country.names['zh-CN'] +
        response.subdivisions.most_specific.name +
        response.subdivisions.most_specific.iso_code +
        response.city.name +
        response.postal.code +
        response.location.latitude +
        response.location.longitude +
        response.traits.network, sep="\n"
    )

""


import cv2
import numpy as np
import matplotlib.pyplot as plt

def viz2(img, regions, rooms, all_ctrs):
    all_ctrs_img = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)

    cv2.drawContours(all_ctrs_img, all_ctrs, -1, (0, 255, 0), 3)

    filtered_ctrs_img = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
    for region in regions + rooms:
        cv2.drawContours(filtered_ctrs_img, [region], -1, (0, 255, 0), 3)

    f, ax = plt.subplots(1, 2, figsize=(20, 14))

    ax[0].imshow(all_ctrs_img)
    ax[0].axis('off')
    ax[0].set_title('All contours simplified')

    ax[1].imshow(filtered_ctrs_img)
    ax[1].axis('off')
    ax[1].set_title('All contours filtered and simplified')

    f.savefig('fig2.jpg')
    return


"""
a very simple MNIST classifier
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import sys

from tensorflow.examples.tutorials.mnist import input_data

import tensorflow as tf

FLAGS = None

def main(_):
	#import data
	mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

	#create nodes for the input images and target output classes
	x = tf.placeholder(tf.float32, shape=[None, 784])
	y_ = tf.placeholder(tf.float32, shape=[None, 10])

	#define the weights w and biases b for model
	W = tf.Variable(tf.zeros([784, 10]))
	b = tf.Variable(tf.zeros([10]))

	#implement regression model
	#multiply the vectorized input images x by the weight matrix W, add the bias b
	y = tf.matmul(x, W) + b

	#specify a loss function
	cross_entropy = tf.reduce_mean(
		tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

	#train the model
	#minimize cross entropy using gradient descent with a learning rate of 0.5
	train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

	sess = tf.InteractiveSession()

	#initialize variable with specified values
	tf.global_variables_initializer().run()

	#run the training procedure
	for _ in range(1000):
		batch = mnist.train.next_batch(100)
		sess.run(train_step, feed_dict={x: batch[0], y_: batch[1]})

	#evaluate the model
	correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
	accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
	print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

if __name__ == '__main__':
	parser = argparse.ArgumentParser()
	parser.add_argument('--data_dir', type=str, default='d:/Workspace/tensorflow/MNIST_data',
						help='Directory for storing input data')
	FLAGS, unparsed = parser.parse_known_args()
	tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)


import math
import numpy as np
from scipy.special import expit

class LogReg():
    def __init__(self, lambda_1=0.0, lambda_2=1.0, gd_type='full',
                 tolerance=1e-4, max_iter=1000, w0=None, alpha=1e-3):
        """
        lambda_1: L1 regularization param
        lambda_2: L2 regularization param
        gd_type: 'full' or 'stochastic'
        tolerance: for stopping gradient descent
        max_iter: maximum number of steps in gradient descent
        w0: np.array of shape (d) - init weights
        alpha: learning rate
        """
        self.lambda_1 = lambda_1
        self.lambda_2 = lambda_2
        self.gd_type = gd_type
        self.tolerance = tolerance
        self.max_iter = max_iter
        self.w0 = w0
        self.alpha = alpha
        self.w = None
        self.loss_history = None

    def fit(self, X, y):
        """
        X: np.array of shape (l, d)
        y: np.array of shape (l)
        ---
        output: self
        """
        self.loss_history = []
        count = 0
        self.w = np.ones((len(X[0]),))
        while np.linalg.norm(self.w - self.w0) > self.tolerance or count < self.max_iter:
            count += 1
            self.w = self.w0
            if self.gd_type == 'stochastic':
                i = random.randint(0, len(y))
                grad = self.calc_gradient(X[i, :], np.array(y[i]))
            else:
                grad = self.calc_gradient(X, y)
            self.w = self.w0 - self.alpha * grad
            loss = self.calc_loss(X, y)
            self.loss_history.append(loss)
            self.w0 = self.w
        return self

    def predict_proba(self, X):
        """
        X: np.array of shape (l, d)
        ---
        output: np.array of shape (l, 2) where
        first column has probabilities of -1
        second column has probabilities of +1
        """
        if self.w is None:
            raise Exception('Not trained yet')
        pred = expit(np.dot(X, self.w))
        return pred

    def calc_gradient(self, X, y):
        """
        X: np.array of shape (l, d) (l can be equal to 1 if stochastic)
        y: np.array of shape (l)
        ---
        output: np.array of shape (d)
        """
        tm1 = expit(-y * np.dot(X, self.w))
        tm2 = y[:, np.newaxis] * X
        tm3 = tm1[:, np.newaxis] * tm2
        tm4 = -np.sum(tm3, axis=0)
        grad = tm4 / X.shape[0] + self.lambda_2 * self.w
        return grad

    def calc_loss(self, X, y):
        """
        X: np.array of shape (l, d)
        y: np.array of shape (l)
        ---
        output: float
        """
        n = X.shape[0]
        tm1 = np.logaddexp(0, -y * np.dot(X, self.w))
        reg = self.lambda_2 * np.sum(self.w ** 2) / 2
        loss = (1 / n) * np.sum(tm1, axis=0) + reg
        return loss


from sklearn.preprocessing import StandardScaler
file_name2 = 'data2.csv'
df = pd.read_csv(file_name2)
df['race_date'] = pd.to_datetime(df['race_date']).dt.date
# 情報不足行を削除
df = df.dropna(subset=['past_time_sec1', 'past_time_sec2', 'past_time_sec3',
                       'past_time_sec4', 'past_time_sec5']).reset_index(drop=True)

# レースID付与

def set_race_id(params):
    param_list = params.split('_')
    race_date, place, race_num = param_list[0], param_list[1], param_list[2],
    return f'{race_date}{place}{race_num}'

df['tmp'] = df['race_date'].astype(
    str) + '_' + df['place'].astype(str) + '_' + df['race_num'].astype(str)
df['race_id'] = df['tmp'].map(set_race_id)
df = df.drop(columns=['tmp'])

# 予測に使用しない列を削除（必要に応じて変更）
df = df.drop(columns=['horse', 'jockey', 'race_num', 'stable',
                    'race_name', 'rank', 'pop',  'gap', 'tansho', 'win1', 'time_sec'])

# ダミー列定義（One-Hot変換対象）
dummy_columns = ['sex', 'place', 'course_type', 'course_lr', 'weather', 'ground', 'past_course_type1', 'past_course_lr1', 'past_weather1', 'past_ground1', 'past_gap1', 'past_course_type2', 'past_course_lr2', 'past_weather2', 'past_ground2', 'past_gap2',
                'past_course_type3', 'past_course_lr3', 'past_weather3', 'past_ground3', 'past_gap3', 'past_course_type4', 'past_course_lr4', 'past_weather4', 'past_ground4', 'past_gap4', 'past_course_type5', 'past_course_lr5', 'past_weather5', 'past_ground5', 'past_gap5']

# ダミー化
df_dummy = df[dummy_columns]
df_dummy = pd.get_dummies(df_dummy, dummy_na=True)
df_main = df.drop(columns=dummy_columns)

# 標準化前に必要な情報を退避
df_main['kitaichi'] = df_main['win3'] * df_main['fukusho']
train_kitaichi = df_main.pop('kitaichi')
train_labels = df_main.pop('win3')
train_date = df_main.pop('race_date')
train_raceids = df_main.pop('race_id')
df_main = df_main.drop(columns=['fukusho'])

df_main = df_main.astype(float)
standard_file = 'standard.csv'
df_main.to_csv(standard_file, index=False)
# 標準化

ss = StandardScaler()
df_main = pd.DataFrame(ss.fit_transform(
    df_main), columns=df_main.columns, index=df_main.index)

# ダミー列とマージ
df = pd.concat([df_main, df_dummy], axis=1)

df['kitaichi'] = train_kitaichi.values
df['win3'] = train_labels.values
df['race_date'] = train_date.values
df['race_id'] = train_raceids.values
file_name3 = 'data3.csv'
df.to_csv(file_name3, index=False)


from . learningTasks import RandomForest

import os
import luigi
import numpy as np
import logging

# import the proper nifty version
try:
    import nifty.graph.rag as nrag
except ImportError:
    try:
        import nifty_with_cplex.graph.rag as nrag
    except ImportError:
        import nifty_with_gurobi.graph.rag as nrag

from .dataTasks import StackedRegionAdjacencyGraph, InputData
from .tools import config_logger, run_decorator
from .featureTasks import RegionNodeFeatures
from .customTargets import HDF5DataTarget, FolderTarget
from .pipelineParameter import PipelineParameter

# init the workflow logger
workflow_logger = logging.getLogger(__name__)
config_logger(workflow_logger)

class DefectNodeGroundtruth(luigi.Task):

    pathToSeg = luigi.Parameter()
    pathToDefectGt = luigi.Parameter()

    def requires(self):
        return{
            "rag": StackedRegionAdjacencyGraph(self.pathToSeg),
            "defect_gt": InputData(self.pathToDefectGt, dtype='uint8')
        }

    @run_decorator
    def run(self):
        inp = self.input()
        rag = inp['rag'].read()
        defect_gt = inp['defect_gt']
        defect_gt.open()

        node_labels = nrag.gridRagAccumulateLabels(rag, defect_gt.get())
        assert (np.unique(node_labels) == np.array([0, 1])).all(), str(np.unique(node_labels))
        self.output().write(node_labels)

    def output(self):
        seg_file = os.path.split(self.pathToSeg)[1][:-3]
        save_path = "DefectNodeGroundtruth_%s.h5" % seg_file
        return HDF5DataTarget(save_path)

class LearnDefectRandomForest(luigi.Task):

    pathsToSeg = luigi.ListParameter()
    pathsToDefectGt = luigi.ListParameter()

    def requires(self):
        assert len(self.pathsToSeg) == len(self.pathsToGt)
        n_inputs = len(self.pathsToSeg)
        inputs = PipelineParameter().inputs

        if n_inputs == 1:
            raw_path = inputs['data'][0]
            return {
                'gt': DefectNodeGroundtruth(self.pathsToSeg[0], self.pathsToDefectGt[0]),
                'feats': RegionNodeFeatures(self.pathsToSeg[0], raw_path)
            }
        else:
            inp_paths = inputs['data']
            assert n_inputs % inp_paths == 0
            inp_per_seg = len(inp_paths) // n_inputs
            return {
                'gt': [DefectNodeGroundtruth(self.pathsToSeg[i], self.pathsToDefectGt[i]) for i in range(n_inputs)],
                'feats': [RegionNodeFeatures(self.pathToSeg[i], inp_paths[inp_per_seg * i]) for i in range(n_inputs)]
            }

    @run_decorator
    def run(self):
        if(self.pathsToSeg) > 1:
            self._learn_defect_rf_multi_input()
        else:
            self._learn_defect_rf_single_input()

    def _learn_defect_rf_multi_input(self):
        inp = self.input()
        gts = inp['gt']
        feats = inp['feats']
        assert len(gts) == len(feats)
        features = []
        labels = []
        for i, gt in enumerate(gts):
            this_gt = gt.read()
            this_feats = feats[i].read([0, 0], feats[i].shape)
            assert len(this_gt) == len(this_feats), "%i, %i" % (len(this_gt), len(this_feats))
            features.append(this_feats)
            labels.append(this_gt)
        features = np.concatenate(features, axis=0)
        labels = np.concatenate(labels, axis=0)
        rf = RandomForest(
            features, labels,
            n_trees=PipelineParameter().nTrees,
            n_threads=PipelineParameter().nThreads
        )
        rf.write(str(self.output().path), 'rf')

    def _learn_defect_rf_single_input(self):
        inp = self.input()
        gt = inp['gt'].read()
        feats = inp['feats']
        feats = feats.readSubarray([0, 0], feats.shape)
        assert len(gt) == len(feats), "%i, %i" % (len(gt), len(feats))
        rf = RandomForest(
            feats, gt,
            n_trees=PipelineParameter().nTrees,
            n_threads=PipelineParameter().nThreads
        )
        rf.write(str(self.output().path), 'rf')

    def output(self):
        save_path = 'LearnDefectRandomForest_%s' % (
            'multi_input' if len(self.pathsToSeg) > 1 else 'single_input',
        )
        return FolderTarget(save_path)


#Long Short-Term Memory
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error

dataset_train = pd.read_csv('files/Salestrain.csv')
plt.plot(dataset_train, color='blue', label='Vendas')
plt.title('Vendas')
plt.xlabel('Tempo')
plt.ylabel('Vendas')
plt.legend()
plt.show()

sc = MinMaxScaler(feature_range=(0, 1))
trainning_set_scaled = sc.fit_transform(dataset_train)

X_train = []
y_train = []

for i in range(90, len(trainning_set_scaled)):
    data = trainning_set_scaled[i-90:i, 0]
    X_train.append(data)
    y_train.append(trainning_set_scaled[i,0])

X_train = np.array(X_train.reshape(-1,90,1))
y_train = np.array(y_train)

model = Sequential()
model.add(LSTM(units=100, return_sequences=True, input_shape=(X_train.shape[1],1)))
model.add(Dropout(0.2))
model.add(LSTM(units=100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=100))
model.add(Dropout(0.2))
model.add(Dense(units=1))

model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X_train, y_train, epochs=300, batch_size=1)

dataset_test = pd.read_csv('files/Salestest.csv')

train_values = dataset_train['data'].values
test_values = dataset_test['data'].values
total_values = np.concatenate((train_values, test_values), axis=0)
time_index = range(len(total_values))

plt.plot(time_index[:len(train_values)], color='blue', label='Vendas - Treinamento')
plt.plot(time_index[len(test_values):], color='red', label='Vendas - Teste')
plt.title('Vendas')
plt.xlabel('Tempo')
plt.ylabel('Vendas')
plt.legend()
plt.show()

dataset_test_anomalies = dataset_test.copy()
dataset_test_anomalies.loc[:9, 'data'] = 90
dataset_test_anomalies.loc[10:34, 'data'] = np.random.uniform(100,200,size=(25,))
dataset_test_anomalies.loc[35:, 'data'] = 90

plt.plot(dataset_test, color='blue', label='Vendas')
plt.plot(dataset_test_anomalies, color='red', label='Vendas com anomalias')
plt.title('Vendas')
plt.xlabel('Tempo')
plt.ylabel('Vendas')
plt.legend()
plt.show()

dataset_total = pd.concat((dataset_train['data'], dataset_test['data']), axis=0)
inputs = dataset_total[len(dataset_total)-len(dataset_test-90):]
inputs = pd.DataFrame(inputs, columns=['data'])
inputs = sc.transform(inputs)

dataset_total_anomalies = pd.concat((dataset_train['data'], dataset_test_anomalies['data']), axis=0)
inputs_anomalies = dataset_total_anomalies[len(dataset_total_anomalies)-len(dataset_test_anomalies-90):]
inputs_anomalies = pd.DataFrame(inputs_anomalies, columns=['data'])
inputs_anomalies = sc.transform(inputs_anomalies)

X_test = []
X_test_anomalies = []
for i in range(90, len(inputs)):
    X_test.append(inputs[i-90:i,0])
    X_test_anomalies.append(inputs_anomalies[i-90:i,0])

X_test, X_test_anomalies = np.array(X_test), np.array(X_test_anomalies)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
X_test_anomalies = np.reshape(X_test_anomalies, (X_test_anomalies.shape[0], X_test_anomalies.shape[1], 1))

prediced_sales = model.predict(X_test)
prediced_sales = sc.inverse_transform(prediced_sales)
prediced_sales_anomalies = model.predict(X_test_anomalies)
prediced_sales_anomalies = sc.inverse_transform(prediced_sales_anomalies)

mean_squared_error_test = mean_squared_error(test_values, prediced_sales)
mean_squared_error_anomalies = mean_squared_error(test_values, prediced_sales_anomalies)

print(f'MSE normal data: ', mean_squared_error_test)
print(f'MSE data with anomalies: ', mean_squared_error_anomalies)

plt.plot(test_values, color='blue', label='Valores reais')
plt.plot(prediced_sales_anomalies, colo='red', label='Previsões com anomalias')
plt.plot(prediced_sales, color='green', label='Previsões')
plt.title('Previsões com anomalias, sem anomalias e valores reais')
plt.xlabel('Tempo')
plt.ylabel('Vendas')
plt.legend()
plt.show()


import urllib3
import requests
from bs4 import BeautifulSoup
from csv import writer
import csv
import pandas as pd

url = 'https://www.mubawab.tn/fr/cc/immobilier-a-louer-all:o:i:sc:houses-for-rent:p:' + str(1)
page = requests.get(url)

soup = BeautifulSoup(page.content, 'html.parser')
lists  = soup.find_all('li', class_='listingBox w100')
for list in lists:
            estate_local = list.find('h3', class_='listingH3').text.split()[-1].strip()
            estate_type = "Maison"
            estate_surface = getattr(list.find('h4', class_='listingH4 floatR'),'text', None)
            estate_piece = list.find('h4', class_='listingH4 floatR').text.split()[0].strip()
            estate_price = getattr(list.find("span", class_= "priceTag hardShadow float-right floatL yellowBg"),'text', None)
            if (str(estate_price)=='None'):
                estate_price = getattr(list.find("span", class_= "priceTag hardShadow float-right floatL"),'text', None)
            info = [estate_local, estate_type, estate_surface, estate_piece, str(estate_price)]
            print(info)


from django.urls import path, include

from . import views

app_name = 'api'

employment = [
    path('', views.EmploymentListEmployee.as_view(), name='list'),
]

employee = [
    path('<int:pk>/employment/', include((employment, 'employment'))),
]

urlpatterns = [
    path('employee/', include((employee, 'employee'))),
]