import json
import random
from typing import Optional

import discord
from discord import app_commands
from discord.ui import Button, View
from pydantic import ValidationError

from client import TextToImageClient
from enums import ErrorMessage, ErrorTitle, ModelEnum, ResponseStatusEnum, SchedulerType, WarningMessages
from schemas import ImageGenerationDiscordParams
from settings import discord_bot_settings, model_settings
from utils import (
    build_error_message,
    build_message,
    get_logger,
    get_req,
    get_results,
    get_twitter_url,
    get_tx_hash,
    get_tx_insight_url,
    individual_image_button,
    post_req,
    preprocess_data,
    re_generate_button,
)

GUILD = discord.Object(id=discord_bot_settings.guild_id)

logger = get_logger(__name__)

intents = discord.Intents.default()
client = TextToImageClient(intents=intents, guild=GUILD)

@client.tree.command(guild=GUILD, name="generate", description="Generate Image")
@app_commands.describe(
    prompt="Try adding increments to your prompt such as 'a photo of an astronaut riding a horse on mars'",
    steps="More steps can increase quality but will take longer to generate",
    seed="Random seed",
    width="Image width",
    height="Image Height",
    images="How many images you wish to generate",
    guidance_scale="How much the prompt will influence the results",
    model_id="name of diffusion model.",
    negative_prompt="prompt value that you do not want to see in the resulting image",
    scheduler_type="diffusers scheduler type",
)
@app_commands.choices(
    model_id=[
        app_commands.Choice(name="Stable Diffusion v2.1-768", value=ModelEnum.STABLE_DIFFUSION_V2_1_768),
        app_commands.Choice(name="Stable Diffusion v2.1", value=ModelEnum.STABLE_DIFFUSION_V2_1),
    ]
)
@app_commands.choices(
    scheduler_type=[
        app_commands.Choice(name="DDIM", value=SchedulerType.DDIM),
        app_commands.Choice(name="PNDM", value=SchedulerType.PNDM),
        app_commands.Choice(name="EulerDiscrete", value=SchedulerType.EULER_DISCRETE),
        app_commands.Choice(name="EulerAncestralDiscrete", value=SchedulerType.EULER_ANCESTRAL_DISCRETE),
        app_commands.Choice(name="HeunDiscrete", value=SchedulerType.HEUN_DISCRETE),
        app_commands.Choice(name="KDPM2Discrete", value=SchedulerType.K_DPM_2_DISCRETE),
        app_commands.Choice(name="KDPM2AncestralDiscrete", value=SchedulerType.K_DPM_2_ANCESTRAL_DISCRETE),
        app_commands.Choice(name="LMSDiscrete", value=SchedulerType.LMS_DISCRETE),
    ]
)
async def generate(
    interaction: discord.Interaction,
    prompt: str,
    steps: Optional[int] = 50,
    seed: Optional[int] = None,
    width: Optional[int] = 768,
    height: Optional[int] = 768,
    images: Optional[int] = 2,
    guidance_scale: Optional[float] = 7.0,
    model_id: Optional[app_commands.Choice[str]] = ModelEnum.STABLE_DIFFUSION_V2_1_768,
    negative_prompt: Optional[str] = "",
    scheduler_type: Optional[app_commands.Choice[str]] = SchedulerType.DDIM,
):
    logger.info(f"{interaction.user.name} generate image")
    model_endpoint = model_settings.endpoint
    user_id = str(interaction.user.id)
    guild_id = str(interaction.guild.id)
    channel_id = str(interaction.channel.id)
    message_id = "0"  # interaction.message.id
    model_id: ModelEnum = ModelEnum(model_id.value)
    scheduler_type: SchedulerType = SchedulerType(scheduler_type.value)
    logger.info(f"{user_id} {guild_id} {channel_id} {message_id}")
    try:
        if seed is None:
            seed = random.randint(0, 4294967295)
        try:
            image_generation_request, warning_message_list = preprocess_data(
                prompt=prompt,
                steps=steps,
                seed=seed,
                width=width,
                height=height,
                images=images,
                guidance_scale=guidance_scale,
                model_id=model_id.value,
                negative_prompt=negative_prompt,
                scheduler_type=scheduler_type.value,
            )
        except ValidationError as validation_error:
            error_message_list = []
            for error in json.loads(validation_error.json()):
                loc = error["loc"][0]
                msg = error["msg"]
                error_message_list.append(f"{loc} : {msg}")
            error_message = "\n".join(error_message_list)
            error_embed = build_error_message(title=ErrorTitle.INPUT_VALIDATION, description=error_message)
            logger.error(f"{interaction.user.name} ValidationError")
            await interaction.response.send_message(embed=error_embed)
            return
        except Exception as unknown_error:
            error_message = ErrorMessage.UNKNOWN
            error_message += f"Error: {unknown_error}"
            error_embed = build_error_message(title=ErrorTitle.UNKNOWN, description=error_message)
            await interaction.response.send_message(embed=error_embed)
            return
        logger.info(f"{interaction.user.name} generate image - request task")

        message_embed = build_message(
            title=f"Prompt: {image_generation_request.prompt}",
            description="",
            colour=discord.Colour.blue(),
        )
        mentions = discord.AllowedMentions(users=True)
        await interaction.response.send_message(
            embed=message_embed,
            allowed_mentions=mentions,
        )
    except Exception as unknown_error:
        error_message = ErrorMessage.UNKNOWN
        error_message += f"Error: {unknown_error}"
        error_embed = build_error_message(title=ErrorTitle.UNKNOWN, description=error_message)
        await interaction.response.send_message(embed=error_embed)
        return
    try:
        message = await interaction.original_response()
        message_id = str(message.id)
        discord_data = ImageGenerationDiscordParams(
            user_id=user_id,
            guild_id=guild_id,
            channel_id=channel_id,
            message_id=message_id,
        )
        request_data = {
            "discord": discord_data.dict(),
            "params": image_generation_request.dict(),
        }
        logger.info(f"Data : {request_data}")
        is_success, res = post_req(url=f"{model_endpoint}/generate", data=request_data)
        if is_success:
            task_id = res["task_id"]
            user_mention = interaction.user.mention
            message_embed = build_message(
                title=f"Prompt: {image_generation_request.prompt}",
                description=f"task_id: {task_id}\nmodel_id: {model_id}",
                colour=discord.Colour.blue(),
            )
            await interaction.edit_original_response(
                embed=message_embed,
                content=f"{user_mention} Your task is successfully requested.",
                allowed_mentions=mentions,
            )
            is_success, res = await get_results(
                url=f"{model_endpoint}/tasks/{task_id}/images",
                n=300,
                user=user_mention,
                interaction=interaction,
                message=message_embed,
            )
            if is_success:
                button_list = [
                    Button(label=f"#{i + 1}", style=discord.ButtonStyle.gray, row=0)
                    for i in range(image_generation_request.images)
                ]
                view = View(timeout=None)
                result = res["result"]
                for i in range(image_generation_request.images):
                    if result[str(i + 1)]["is_filtered"]:
                        button_list[i].callback = individual_image_button(
                            result[str(i + 1)]["origin_url"],
                            title=f"Prompt: {image_generation_request.prompt}",
                            description=f"task_id: {task_id}\nmodel_id: {model_id}",
                        )
                    else:
                        button_list[i].callback = individual_image_button(
                            result[str(i + 1)]["url"],
                            title=f"Prompt: {image_generation_request.prompt}",
                            description=f"task_id: {task_id}\nmodel_id: {model_id}",
                        )
                    view.add_item(button_list[i])
                re_gen_button = Button(label="ðŸ”„", style=discord.ButtonStyle.gray, row=0)
                re_gen_button.callback = re_generate_button(image_generation_request)
                view.add_item(re_gen_button)
                twitter_url = get_twitter_url(task_id=task_id)
                share_twitter_button = Button(
                    label="Share on Twitter", style=discord.ButtonStyle.gray, url=twitter_url, row=1
                )

                view.add_item(share_twitter_button)

                message_embed.set_image(url=result["grid"]["url"])
                if sum([each["is_filtered"] for each in result.values()]):
                    warning_message_list.append(WarningMessages.NSFW)
                content_message = f"{user_mention} Your task is completed."
                if len(warning_message_list) != 0:
                    warning_message_list.insert(0, f"model_id: {model_id}")
                    warning_message_list.insert(0, f"task_id: {task_id}")
                    message_embed.colour = discord.Colour.orange()
                    message_embed.description = "\n".join(warning_message_list)
                    await interaction.edit_original_response(
                        content=content_message,
                        embed=message_embed,
                        allowed_mentions=mentions,
                        view=view,
                    )
                else:
                    message_embed.colour = discord.Colour.green()
                    await interaction.edit_original_response(
                        content=content_message,
                        embed=message_embed,
                        allowed_mentions=mentions,
                        view=view,
                    )

                is_success, res = await get_tx_hash(url=f"{model_endpoint}/tasks/{task_id}/tx-hash", n=20)
                if is_success:
                    if res["status"] != ResponseStatusEnum.ERROR:
                        status = res["status"]
                        tx_hash = res["tx_hash"][status]
                        tx_insight_url = get_tx_insight_url(tx_hash)
                        insight_button = Button(
                            label="View on Insight", style=discord.ButtonStyle.gray, url=tx_insight_url, row=1
                        )
                        view.add_item(insight_button)

                        await interaction.edit_original_response(
                            content=content_message,
                            embed=message_embed,
                            allowed_mentions=mentions,
                            view=view,
                        )
                return
            else:
                if res:
                    error_embed = build_error_message(
                        title=ErrorTitle.UNKNOWN,
                        description=ErrorMessage.UNKNOWN,
                    )
                else:
                    error_embed = build_error_message(
                        title=ErrorTitle.TIMEOUT,
                        description=f"Your task cannot be generated because there are too many tasks on the server.\nIf you want to get your results late, let the community manager know your task id {task_id}.",
                    )
                    await interaction.edit_original_response(embed=error_embed)
                return
        else:
            error_message = "The request failed.\nPlease try again in a momentarily.\nIf the situation repeats, please let our community manager know."
            error_embed = build_error_message(title="Request Error", description=error_message)
            await interaction.edit_original_response(embed=error_embed)
    except Exception as unknown_error:
        error_message = ErrorMessage.UNKNOWN
        error_message += f"Error: {unknown_error}"
        error_embed = build_error_message(title="Unknown Error", description=error_message)
        await interaction.edit_original_response(embed=error_embed)

@client.tree.command(guild=GUILD, name="result", description="Get task result using task id")
@app_commands.describe(task_id="a task id string obtained when generating an image")
async def result(
    interaction: discord.Interaction,
    task_id: str,
):
    warning_message_list = []
    mentions = discord.AllowedMentions(users=True)
    model_endpoint = model_settings.endpoint
    try:
        user_mention = interaction.user.mention
        is_success, res = get_req(url=f"{model_endpoint}/tasks/{task_id}/images")
        if not is_success:
            error_embed = build_error_message(
                title=ErrorTitle.WRONG_TASK_ID,
                description=f"Requested task was not found. Your task id({task_id}) may be wrong. Please input correct task id.",
            )
            await interaction.response.send_message(embed=error_embed)
            return

        if res["status"] != ResponseStatusEnum.COMPLETED:
            message_embed = build_message(
                title="Task is not finished",
                description=f"Current status : {res['status']}",
                colour=discord.Colour.blue(),
            )
            message_embed.colour = discord.Colour.orange()
            await interaction.response.send_message(
                embed=message_embed,
                content=f"{user_mention} The result of requested task is below.",
                allowed_mentions=mentions,
            )
            return

        result = res["result"]

        is_success, request_params = get_req(url=f"{model_endpoint}/tasks/{task_id}/params")
        if not is_success:
            error_embed = build_error_message(
                title=ErrorTitle.WRONG_TASK_ID,
                description=f"Requested task was not found. Your task id({task_id}) may be wrong. Please input correct task id.",
            )
            await interaction.response.send_message(embed=error_embed)
            return

        button_list = [
            Button(label=f"#{i + 1}", style=discord.ButtonStyle.gray) for i in range(request_params["images"])
        ]
        view = View(timeout=None)
        for i in range(request_params["images"]):
            if result[str(i + 1)]["is_filtered"]:
                button_list[i].callback = individual_image_button(
                    result[str(i + 1)]["origin_url"],
                    title=f"Prompt: {request_params['prompt']}",
                    description=f"task id: {task_id}",
                )
            else:
                button_list[i].callback = individual_image_button(
                    result[str(i + 1)]["url"],
                    title=f"Prompt: {request_params['prompt']}",
                    description=f"task id: {task_id}",
                )
            view.add_item(button_list[i])

        message_embed = build_message(
            title=f"Prompt: {request_params['prompt']}",
            description=f"task_id: {task_id}",
            colour=discord.Colour.blue(),
        )
        message_embed.set_image(url=result["grid"]["url"])
        if sum([each["is_filtered"] for each in result.values()]):
            warning_message_list.append(WarningMessages.NSFW)

        if len(warning_message_list) != 0:
            warning_message_list.insert(0, f"task_id: {task_id}")
            message_embed.colour = discord.Colour.orange()
            message_embed.description = "\n".join(warning_message_list)
            await interaction.response.send_message(
                content=f"{user_mention} The result of requested task is below.",
                embed=message_embed,
                allowed_mentions=mentions,
                view=view,
            )
        else:
            content_message = f"{user_mention} The result of requested task is below."
            message_embed.colour = discord.Colour.green()
            await interaction.response.send_message(
                content=content_message,
                embed=message_embed,
                allowed_mentions=mentions,
                view=view,
            )
        return
    except Exception as unknown_error:
        error_message = ErrorMessage.UNKNOWN
        error_message += f"Error: {unknown_error}"
        error_embed = build_error_message(title="Unknown Error", description=error_message)
        await interaction.response.send_message(embed=error_embed)

@client.tree.command(guild=GUILD, name="params", description="Get task parameters using task id")
@app_commands.describe(task_id="a task id string obtained when generating an image")
async def params(
    interaction: discord.Interaction,
    task_id: str,
):
    mentions = discord.AllowedMentions(users=True)
    model_endpoint = model_settings.endpoint
    try:
        is_success, res = get_req(url=f"{model_endpoint}/tasks/{task_id}/params")
        if not is_success:
            error_embed = build_error_message(
                title=ErrorTitle.WRONG_TASK_ID,
                description=f"Requested task was not found. Your task id({task_id}) may be wrong. Please input correct task id.",
            )
            await interaction.response.send_message(embed=error_embed)
            return

        is_success, request_params = get_req(url=f"{model_endpoint}/tasks/{task_id}/params")
        if not is_success:
            error_embed = build_error_message(
                title=ErrorTitle.WRONG_TASK_ID,
                description=f"Requested task was not found. Your task id({task_id}) may be wrong. Please input correct task id.",
            )
            await interaction.response.send_message(embed=error_embed)
            return

        params_text = ""
        for param_name, param_val in request_params.items():
            params_text += f"> **{param_name}**\n> {param_val}\n"

        await interaction.response.send_message(
            content=params_text,
            allowed_mentions=mentions,
        )
        return
    except Exception as unknown_error:
        error_message = ErrorMessage.UNKNOWN
        error_message += f"Error: {unknown_error}"
        error_embed = build_error_message(title="Unknown Error", description=error_message)
        await interaction.response.send_message(embed=error_embed)

# TODO: Find Better way
@client.tree.command(guild=GUILD, name="help", description="Show help for bot")
async def help(interaction: discord.Interaction):
    generate_parameters = [
        {
            "name": "prompt",
            "value": "A description of what you'd like the machine to generate.",
            "condition": "required | string",
        },
        {
            "name": "steps",
            "value": "How many steps to spend generating (diffusing) your image.",
            "condition": "integer | min: 1 | max: 100 | default: 50",
        },
        {
            "name": "seed",
            "value": "The seed used to generate your image.",
            "condition": "integer | min: 0 | max: 4294967295 | default: random integer",
        },
        {
            "name": "width",
            "value": "The width of the generated image.",
            "condition": f"integer | min: {model_settings.image_minimum_size} | max: {model_settings.image_maximum_size} | default: 768",
        },
        {
            "name": "height",
            "value": "The height of the generated image.",
            "condition": f"integer | min: {model_settings.image_minimum_size} | max: {model_settings.image_maximum_size} | default: 768",
        },
        {
            "name": "images",
            "value": "How many images you wish to generate.",
            "condition": "integer | min: 1 | max: 4 | default: 2",
        },
        {
            "name": "guidance_scale",
            "value": "How much the image will be like your prompt. Higher values keep your image closer to your prompt.",
            "condition": "number | min: 0 | max: 20 | default: 7",
        },
        {
            "name": "model_id",
            "value": "name of diffusion model.",
            "condition": "string | default: `stable-diffusion-v2-1-768`",
        },
        {
            "name": "negative_prompt",
            "value": "negative prompting indicates which terms you do not want to see in the resulting image.",
            "condition": "string | default: ` `",
        },
        {
            "name": "scheduler_type",
            "value": "diffusers scheduler type",
            "condition": "string | default: `ddim`",
        },
    ]
    generate_title = "/generate"
    generate_info = "Generates images from text."
    generate_description = "\n>".join(
        [f" - `{each['name']}` \n> {each['value']}\n> {each['condition']}" for each in generate_parameters]
    )

    result_parameters = [
        {
            "name": "task_id",
            "value": "A task id string obtained when generating an image",
            "condition": "required | string",
        }
    ]
    result_title = "/result"
    result_info = "Shows generating results from task id."
    result_description = "\n>".join(
        [f" - `{each['name']}` \n> {each['value']}\n> {each['condition']}" for each in result_parameters]
    )

    params_parameters = [
        {
            "name": "task_id",
            "value": "A task id string obtained when generating an image",
            "condition": "required | string",
        }
    ]
    params_title = "/params"
    params_info = "Shows request parameters from task id."
    params_description = "\n>".join(
        [f" - `{each['name']}` \n> {each['value']}\n> {each['condition']}" for each in params_parameters]
    )

    content = f"**{generate_title}** \n {generate_info} \n>{generate_description}\n"
    content += f"**{result_title}** \n {result_info} \n>{result_description}\n"
    content += f"**{params_title}** \n {params_info} \n>{params_description}"
    await interaction.response.send_message(content=content)

client.run(discord_bot_settings.bot_token)


from collections import defaultdict
import csv
import gzip
import itertools
from pathlib import Path

import tqdm

from repodb.common import logger
from repodb.classes.nodes.disorder import Disorder
from repodb.classes.nodes.gene import Gene
from repodb.classes.edges.gene_associated_with_disorder import (
    GeneAssociatedWithDisorder,
)

class DisGeNetParser():
    def __init__(self, infile):
        self.infile = Path(infile)
        if not self.infile.exists():
            raise Exception(f'{self.infile} does not exist')

    def parse(self):
        # Create a map of UMLS identifiers to MONDO IDs
        umls_mondo = defaultdict(list)
        for item in Disorder.objects():
            for umls_id in [i for i in item.domainIds if i.startswith("umls.")]:
                umls_mondo[umls_id].append(item.primaryDomainId)

        # Create a set of valid gene IDs
        gene_ids = {i.primaryDomainId for i in Gene.objects()}

        with gzip.open(f"{self.infile}", "rt") as f:
            reader = csv.DictReader(f, delimiter="\t")
            for row in tqdm.tqdm(reader):
                gene_id = f"entrez.{row['geneId'].strip()}"
                disorder_id = f"umls.{row['diseaseId'].strip()}"

                # Get the gene -- should only be one, returned as an array.
                genes = [gene_id] if gene_id in gene_ids else []
                # Get the disorder -- probably one, could be multiple depending on UMLS mapping.
                disorders = umls_mondo.get(disorder_id, [])

                # For each pair.
                for g, d in itertools.product(genes, disorders):
                    # Query to see if a relationship is already recorded.
                    gawd = GeneAssociatedWithDisorder.objects(
                        sourceDomainId = g,
                        targetDomainId = d
                    )

                    if not gawd:
                        # Create it.
                        gawd = GeneAssociatedWithDisorder(
                            sourceDomainId = g, targetDomainId = d,
                            assertedBy=["disgenet"],
                            score=float(row["score"])
                        )
                        gawd.save()
                    else:
                        # Check that there is only one result.
                        assert len(gawd) == 1
                        gawd = gawd[0]

                        if gawd.score == None:
                            new_score = float(row["score"])
                        else:
                            # This indicates a collision -- select the highest scores
                            new_score = max([float(row["score"]), gawd.score])

                        # Update
                        gawd.modify(
                            add_to_set__assertedBy = "disgenet",
                            set__score = new_score
                            )


#!/usr/bin/python3
import sys
import argparse
import hmac
import http
import urllib
from urllib import parse
from http import client as httpclient

parser = argparse.ArgumentParser()
parser.add_argument('url')
parser.add_argument('secret')
args = parser.parse_args()

payload = sys.stdin.read().encode()

secret = args.secret.encode()
url = args.url

hmac_ = hmac.new(secret, payload, 'sha256')
digest= hmac_.hexdigest()

p = parse.urlparse(url)
Connection = httpclient.HTTPConnection if p.scheme == 'http' else http.client.HTTPSConnection
params = parse.urlencode({'payload':payload, 'hmac': digest})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
c = Connection(p.hostname, p.port)
try:
    c.request('POST', p.path, params, headers)
    r = c.getresponse()
    if r.status != 200:
        print(f"Failed: {r.status} {r.reason}\n{r.read().decode()}")
        sys.exit(2)
except Exception as e:
    print(f"Failed: {e}")
    sys.exit(1)

print(f"Successfully submitted job details to {url}")


import copy
import re
import time

"""
Usage:
    token_array = Prism.parse(code, lang_key, return_all, assign_mode)

Return:
    A token list, like
    [
        {
            'type': 'assign-left',
            # order number of the tokens
            'no': 2,
            # the start position in the code
            'position': 12, #
            # the length of the token content
            'length': 17,
            'cotent': 'SHORT_DESCRIPTION',
            'alias': 'variable'
        }, ...
    ]

Parameters:
    [text]: string, code to be parsed
    [language]: string, language key
    [return_all]: boolean, to determine whether return all parsed tree, or just assignment expressions
    [assign_mode]: boolean, to determine whether return assign_right info or not
"""

RE_TYPE = re.compile('').__class__

def current_milli_time():
    return round(time.time() * 1000)

class Token:
    def __init__(self, token_type, content, alias=None, matched_str=None, position=None):
        self.type = token_type
        self.content = content
        self.alias = alias
        self.length = len(matched_str)
        self.position = position

    def __len__(self):
        return self.length

    @staticmethod
    def _text(content):
        if isinstance(content, list):
            s = ""
            for item in content:
                s += Token._text(item["content"])
            return s
        else:
            return content

    def toDict(self, assign_mode=False):
        return {
            "type": self.type,
            "content": Token._text(self.content) if assign_mode else self.content,
            "alias": self.alias,
            "length": self.length,
            "position": self.position
        }

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

class Node:
    def __init__(self, value=None, prev_sibling=None, next_sibling=None):
        self.value = value
        self.prev = prev_sibling
        self.next = next_sibling

class LinkedList:
    def __init__(self):
        head = Node()
        tail = Node(None, head, None)
        head.next = tail
        self.head = head
        self.tail = tail
        self.length = 0

class Prism:
    LanguagesPatterns = {}
    TokensOutputAdapter = {}
    AssignRightTokens = {}
    Plugins = {}

    class Util:
        uniqueId = 0

        @classmethod
        def getObjectId(cls, obj):
            if not ("__id" in obj):
                obj["__id"] = str(cls.uniqueId)
                cls.uniqueId += 1
            return obj["__id"]

    class Languages:
        # Traverse a language definition with Depth First Search
        @classmethod
        def DFS(cls, o, callback, key=None, visited=None):
            if visited is None:
                visited = {}
            keys = o.keys()
            getObjectId = Prism.Util.getObjectId
            for i in keys:
                callback(o, i, o[i], key or i)

                value: dict = o[i]
                obj_id = getObjectId(value)

                if visited.get(obj_id) is not None:
                    if isinstance(value, dict):
                        visited[obj_id] = True
                        cls.DFS(value, callback, None, visited)
                    elif isinstance(value, list):
                        visited[obj_id] = True
                        cls.DFS(value, callback, i, visited)

        @classmethod
        def insertBefore(cls, inside, before, insert, root=None):
            root = Prism.LanguagesPatterns if root is None else root
            grammar = root[inside]
            ret = {}
            keys = grammar.keys()
            for token in keys:
                if token is before:
                    for newToken in insert.keys():
                        ret[newToken] = insert[newToken]

                # Do not insert token which also occur in insert. See #1525
                if token not in insert:
                    ret[token] = grammar[token]

            old = root[inside]
            root[inside] = ret

            # type fo compatible
            def callback(obj, key, value, _type):
                if value is old and key is not inside:
                    obj[key] = ret

            cls.DFS(Prism.LanguagesPatterns, callback)

            return ret

        @staticmethod
        def extend(lang_id, ext_def):
            lang = copy.deepcopy(Prism.LanguagesPatterns[lang_id])
            lang.update(ext_def)
            return lang

    class Hooks:
        all = {}

        @classmethod
        def add(cls, name, callback):
            hooks = cls.all
            hooks[name] = [] if hooks[name] is None else hooks[name]
            hooks[name].push(callback)

        @classmethod
        def run(cls, name, env):
            callbacks = cls.all.get(name)

            if callbacks is None or len(callbacks) == 0:
                return
            for callback in callbacks:
                callback(env)

    @classmethod
    def _dft_rst_adapter(cls, env, language,assign_mode, return_all):
        right_allowed = Prism.AssignRightTokens.get(language)
        # default AssignRightTokens
        if right_allowed is None:
            right_allowed = {"operator": 1, "variable": 1, "unknown": 1, "regex": 1, "number": 1, "string": 1}

        def collect_assign_right(left_mark, temp_right):
            if temp_right is not None and len(temp_right) > 0:
                while len(temp_right) > 0 and \
                        (
                                temp_right[0]["type"] == "blank" or
                                (
                                        temp_right[0]["type"] == "operator"
                                        and (
                                                (temp_right[0]["content"][0]["content"] if isinstance(
                                                    temp_right[0]["content"], list) else temp_right[0][
                                                    "content"]) == "="
                                        )
                                )
                        ):
                    temp_right.pop(0)

                while len(temp_right) > 0 and \
                        (temp_right[len(temp_right) - 1]["type"] == "blank"):
                    temp_right.pop()

                if len(temp_right) > 0:
                    length = 0
                    content = ""
                    for t in temp_right:
                        t["merged"]=True
                        if isinstance(t["content"], list):
                            for i in t["content"]:
                                length += t["length"]
                                content += i["content"]
                        else:
                            length += t["length"]
                            content += t["content"]
                    left_mark["right"] = {
                        'type':'assign-right',
                        'content': content,
                        'length': length,
                        'position': temp_right[0]["position"],
                        'merged': len(temp_right)
                    }

        tokens = env["tokens"]

        if assign_mode:
            left_mark = None
            temp_right = None
            for token in tokens:
                collecting = left_mark is not None and temp_right is not None
                if token["type"] == "blank":
                    if collecting:
                        temp_right.append(token)
                    continue
                elif right_allowed.get(token["type"]) is not None:
                    if collecting:
                        temp_right.append(token)
                    continue
                else:
                    if collecting:
                        collect_assign_right(left_mark, temp_right)
                    left_mark = None
                    temp_right = None

                    if token["type"] == "assign-left":
                        left_mark = token
                        temp_right = []

            if left_mark is not None and temp_right is not None:
                collect_assign_right(left_mark, temp_right)

            adjusted = []
            for token in tokens:
                if token.get("merged") is None:
                    adjusted.append(token)
                    if token.get("right") is not None:
                        adjusted.append(token['right'])
                        del token['right']
            tokens = adjusted

        if not return_all:
            tokens = list(filter(lambda x: x["type"] == "assign-left" or x["type"] == "assign-right", tokens))

        return tokens

    @classmethod
    def parse(cls, text, language, return_all=True, assign_mode=True):
        """
        core parse function
        :param text: string, code to be parsed
        :param language: string, language key
        :param return_all: boolean, to determine whether return all parsed tree, or just assignment expressions
        :param assign_mode: boolean, to determine whether return assign_right info or not
        :return: token array
        """

        grammar = Prism.LanguagesPatterns.get(language)
        rst_filter = Prism.TokensOutputAdapter.get(language)
        if rst_filter is None:
            rst_filter = cls._dft_rst_adapter
        if grammar is None:
            return None

        start_time = current_milli_time()
        env = {
            "code": text,
            "grammar": grammar,
            "language": language
        }
        Prism.Hooks.run('before-tokenize', env)
        env["tokens"] = Prism.tokenize(text, grammar, 0, assign_mode)
        Prism.Hooks.run('after-tokenize', env)
        Prism.Hooks.run('complete', env)

        print(current_milli_time() - start_time, "ms")

        return rst_filter(env, language, assign_mode, return_all)

    @classmethod
    def tokenize(cls, text, grammar, start_pos=0, assign_mode=False):
        rest = grammar.get("rest")
        if rest is not None:
            for token in rest.keys():
                grammar[token] = rest.get(token)
            del grammar["rest"]

        tokenList = LinkedList()
        cls.addAfter(tokenList, tokenList.head, text)

        cls.matchGrammar(text, tokenList, grammar, tokenList.head, 0, None)

        return cls.toArray(tokenList, start_pos, assign_mode)

    @classmethod
    def addAfter(cls, lst, node, value):
        # assumes that node != list.tail && len(values) >= 0
        _next = node.next

        newNode = Node(value, node, _next)
        node.next = newNode
        _next.prev = newNode
        lst.length += 1

        return newNode

    @classmethod
    def removeRange(cls, lst, node, count):
        _next = node.next
        i = 0
        for i in range(0, count):
            if _next is not lst.tail:
                _next = _next.next
        node.next = _next
        _next.prev = node
        lst.length -= i

    @classmethod
    def toArray(cls, lst, start_pos=0, assign_mode=False):
        array = []
        node = lst.head.next
        _blank = re.compile(r"\S")
        while node is not lst.tail:
            array.append(node.value)
            node = node.next
        arr_len = len(array)
        for i in range(0, arr_len):
            if isinstance(array[i], str):
                array[i] = Token(
                    "unknown" if re.match(_blank, array[i]) is not None else "blank",
                    array[i],
                    None,
                    array[i],
                    (array[i - 1].position + array[i - 1].length) if isinstance(array[i - 1], Token)
                    else (
                        (array[i + 1].position + array[i + 1].length) if arr_len > i + 1 and isinstance(array[i + 1], Token)
                        else start_pos
                    )
                )
        return list(map(lambda x: x.toDict(assign_mode), array))

    @classmethod
    def matchPattern(cls, pattern, pos, text, lookbehind):
        index = -1
        match_str = None
        if text is not None:
            match = pattern.search(text, pos)
            if match is not None:
                index = match.regs[0][0]
                match_str = match[0]
                if lookbehind and len(match.regs) > 1:
                    # change the match to remove the text matched by the PrismParser lookbehind group
                    lookbehindLength = match.regs[1][1] - match.regs[1][0]
                    index += lookbehindLength
                    match_str = match_str[lookbehindLength:]

        return match_str, index

    @classmethod
    def matchGrammar(cls, text, token_list, grammar, start_node, start_pos, rematch=None):
        tail = token_list.tail
        items = grammar.items()
        for key, patterns in items:
            if not isinstance(patterns, list):
                grammar[key] = patterns = [patterns]

            for j, patternObj in enumerate(patterns):
                if rematch is not None and rematch.get("cause") == key + ',' + str(j):
                    return

                if not isinstance(patternObj, dict):
                    patterns[j] = patternObj = {
                        "pattern": patternObj
                    }

                inside = patternObj.get("inside")

                lookbehind = patternObj.get("lookbehind")
                lookbehind = False if lookbehind is None else lookbehind

                greedy = patternObj.get("greedy")
                greedy = False if greedy is None else greedy

                alias = patternObj.get("alias")

                __compiled__ = patternObj.get("__compiled__")

                if __compiled__ is None:
                    patternObj["__compiled__"] = True
                    if isinstance(patternObj.get("pattern"), str):
                        flag = 0 if patternObj.get("flag") is None else patternObj.get("flag")
                        patternObj["pattern"] = re.compile(patternObj.get("pattern"), flag)

                # get regex pattern
                pattern = patternObj.get("pattern")

                # if cant get pattern
                if not isinstance(pattern, RE_TYPE):
                    print("*** Not a valid pattern", grammar, key, j, patternObj)
                    continue

                currentNode = start_node
                pos = start_pos
                while currentNode is not tail:
                    if currentNode is start_node:
                        pass
                    else:
                        pos += len(currentNode.value)

                    currentNode = currentNode.next

                    if rematch is not None and pos >= rematch.get("reach"):
                        break

                    if token_list.length > len(text):
                        # Something went terribly wrong, ABORT, ABORT!
                        return

                    if isinstance(currentNode.value, Token):
                        continue

                    value = currentNode.value

                    removeCount = 1  # this is the to parameter of removeBetween

                    if greedy:
                        match_str, match_index = cls.matchPattern(pattern, pos, text, lookbehind)
                        if match_str is None:
                            break

                        pos_from = match_index
                        pos_to = match_index + len(match_str)
                        p = pos

                        # find the node that contains the match
                        p += len(currentNode.value)
                        while pos_from >= p:
                            currentNode = currentNode.next
                            p += len(currentNode.value)

                        # adjust pos (and p)
                        p -= len(currentNode.value)
                        pos = p

                        # the current node is a Token, then the match starts inside another Token, which is invalid
                        if isinstance(currentNode.value, Token):
                            continue

                        # find the last node which is affected by this match
                        k = currentNode
                        while k is not tail and (p < pos_to or isinstance(k.value, str)):
                            removeCount += 1
                            p += len(k.value)
                            k = k.next

                        removeCount -= 1

                        # replace with the new match
                        value = text[pos:p]
                        match_index -= pos
                    else:
                        match_str, match_index = cls.matchPattern(pattern, 0, value, lookbehind)
                        if match_str is None:
                            continue

                    pos_from = match_index

                    before = value[:pos_from]
                    after = value[pos_from + len(match_str):]

                    reach = pos + len(value)

                    if rematch is not None and reach > rematch.get("reach"):
                        rematch["reach"] = reach

                    removeFrom = currentNode.prev

                    if before:
                        removeFrom = cls.addAfter(token_list, removeFrom, before)
                        pos += len(before)

                    cls.removeRange(token_list, removeFrom, removeCount)

                    wrapped = Token(key, cls.tokenize(match_str, inside, pos) if inside else match_str,
                                    alias, match_str, pos)
                    currentNode = cls.addAfter(token_list, removeFrom, wrapped)

                    if after:
                        cls.addAfter(token_list, currentNode, after)

                    if removeCount > 1:
                        # at least one Token object was removed, so we have to do some rematching
                        # this can only happen if the current pattern is greedy

                        nestedRematch = {
                            "cause": key + ',' + str(j),
                            "reach": reach
                        }
                        cls.matchGrammar(text, token_list, grammar, currentNode.prev, pos, nestedRematch)

                        # the reach might have been extended because of the rematching
                        if rematch is not None and nestedRematch.get("reach") > rematch.get("reach"):
                            rematch["reach"] = nestedRematch.get("reach")

# compatible with old version
Prism.util = Prism.Util
Prism.languages = Prism.Languages
Prism.plugins = Prism.Plugins
Prism.hooks = Prism.Hooks
Prism.Token = Token

__all__ = ["Prism"]


#1. 주어진 리스트를 통해 뒤 숫자가 나올 수 있는지 확인(A,B or 숫자)
#2. 숫자가 나올 수 있는 리스트라면 a,b 구하기
#3. (앞 수 * a + b)=뒷 수 => nlist[1]=nlist[0]*a+b
import sys

n=int(sys.stdin.readline())
nlist=list(map(int,sys.stdin.readline().split()))

if n==1:    #1개면 뒤에 숫자 예측 불가 -> 무조건 A
    print('A')
elif n==2:
    if nlist[0]==nlist[1]:
        print(nlist[0])
    else:   #서로 다른 2개면 뒤에 숫자 예측 불가 -> 무조건 A
        print('A')
else:   #a,b 구하기
    if nlist[1]==nlist[0]:  #1,2번째가 같은 수일 때 뒤 숫자들은 모두 이 숫자들과 같아야 됨.
        for i in range(2,len(nlist)):
            if (nlist[i]-nlist[i-1])!=0:    #하나라도 다르면 규칙X
                print('B')
                exit()
        else:
            print(nlist[-1])
    else:
        # a=nlist[1]-nlist[0]
        # b=nlist[1]-a*nlist[0]
        a=(nlist[2]-nlist[1])/(nlist[1]-nlist[0])
        if a!=int(a):   #a는 정수여야 함
            print('B')
            exit()
        b=nlist[1]-nlist[0]*a
        for i in range(2,len(nlist)):
            if nlist[i]!=(nlist[i-1]*a+b):
                print('B')
                break
        else:
            print(int(nlist[-1]*a+b))


import sys

def dynamicProgramming():
    maxNum = 0
    dp = [[0] * m for _ in range(n)]  # dp[i][j]는 i, j까지 이동했을 때 얻을 수 있는 가장 많은 금광값
    dp[0][0] = array[0][0]
    dp[1][0] = array[1][0]
    dp[2][0] = array[2][0]

    for i in range(1, m):  # 첫번째 열부터 비교
        for j in range(n):  # 첫번째 행부터 비교
            if j == 0:  # 가장 첫번째 행에 있다면 오른쪽과 오른쪽 아래 비교
                dp[j][i] = max(dp[j][i - 1] + array[j][i], dp[j + 1][i - 1] + array[j][i])
            elif j == n - 1:  # 가장 마지막 행에 있다면 오른쪽과 오른쪽 위 비교
                dp[j][i] = max(dp[j - 1][i - 1] + array[j][i], dp[j][i - 1] + array[j][i])
            else:  # 중간행에 있다면 오른쪽, 오른쪽 아래, 오른쪽 위 비교
                dp[j][i] = max(dp[j - 1][i - 1] + array[j][i], dp[j][i - 1] + array[j][i], dp[j + 1][i - 1] + array[j][i])

    # 가장 큰 값 추출
    for item in dp:
        for num in item:
            if num >= maxNum:
                maxNum = num
    return maxNum

T = int(sys.stdin.readline().strip())
for _ in range(T):
    n, m = map(int, sys.stdin.readline().split())
    data = list(map(int, sys.stdin.readline().split()))
    idx = 0
    array = [[0] * m for _ in range(n)]
    for i in range(n):
        for j in range(m):
            array[i][j] = data[idx]
            idx += 1
    result = dynamicProgramming()
    print(result)


"""
+===============================+
  ╦ ╦  ╔═╗  ╔╗╔  ╔═╗  ╔═╗  ╔╦╗
  ╠═╣  ║ ║  ║║║  ║╣   ╚═╗   ║
  ╩ ╩  ╚═╝  ╝╚╝  ╚═╝  ╚═╝   ╩
    MARKET - PEGGED - ASSETS
+===============================+

called by pricefeed_final.py to upload data matrix for HONEST MPA's to jsonbin.io

if you run this script solo it will create a new jsonbin the bin id

to view your jsonbin, visit:

https://api.jsonbin.io/b/<<< your bin id >>>/latest

litepresence2020
"""

# STANDARD PYTHON MODULES
from multiprocessing import Process, Value
import time

# THIRD PARTY MODULES
import requests

# HONEST PRICE FEED MODULES
from config_apikeys import config_apikeys

# GLOBAL USER DEFINED CONSTANTS
# get secret by creating account at jsonbin.io website
JSONBIN_SECRET = config_apikeys()["jsonbin"]["key"]
# get bin id by running this script
BIN_ID = config_apikeys()["jsonbin"]["id"]
# tag your bin, relevent to managing the jsonbin.io UI, must be ALL_CAPS_UNDERSCORES
BIN_NAME = "HONEST_MPA"
# These settings work... don't touch
ATTEMPTS = 3
TIMEOUT = 20

def create_jsonbin():
    """
    initialize a new jsonbin, logs the bin_id to terminal
    """
    url = "https://api.jsonbin.io/b"
    headers = {
        "Content-Type": "application/json",
        "secret-key": JSONBIN_SECRET,
        "name": BIN_NAME,
        "private": "false",
    }
    data = {"initialize": ""}
    method = "POST"
    execute_request(url, data, headers, method)

def update_jsonbin(data):
    """
    used by pricefeed_final to keep HONEST data matrix available live
    """
    url = f"https://api.jsonbin.io/b/{BIN_ID}"
    headers = {
        "Content-Type": "application/json",
        "secret-key": JSONBIN_SECRET,
        "versioning": "false",
    }
    method = "PUT"
    execute_request(url, data, headers, method)

def post_request(signal, url, data, headers, method):
    """
    perform the actual external request and print results
    """
    if method == "PUT":
        req = requests.put(url, json=data, headers=headers)
    elif method == "POST":
        req = requests.post(url, json=data, headers=headers)
    print(url, data, headers)
    print("\n", "jsonbin.io response:", "\n", req.text, "\n")
    signal.value = 1

def execute_request(url, data, headers, method):
    """
    multiprocess wrap, join, and timeout external request for durability
    """
    signal = Value("i", 0)
    i = 0
    while (i < ATTEMPTS) and not signal.value:
        i += 1
        print("")
        print("jsonbin.io authentication attempt:", i, time.ctime())
        child = Process(target=post_request, args=(signal, url, data, headers, method))
        child.daemon = False
        child.start()
        child.join(TIMEOUT)
        child.terminate()
        time.sleep(1)

def main():
    """
    if you run this script solo it will create a new jsonbin bin_id
    """
    create_jsonbin()

if __name__ == "__main__":

    main()


import tkinter

def split_by_chapter(book_file):
    chapter_split = book_file.split('Chapter ')  # Obviously not perfect, but works in many cases
    return chapter_split

def write_chapters_to_files(chapter_split):
    chap_num = 0
    for i in chapter_split:
        with open('ch' + str(chap_num) + '.txt', 'w') as w:
            w.write(i)
        chap_num += 1

def main():
    chosen_book_file = tkinter.filedialog.askopenfilename()
    with open(chosen_book_file, 'r') as r:
        book_file = r.read()

    chapter_split = split_by_chapter(book_file)
    write_chapters_to_files(chapter_split)

if __name__ == '__main__':
    main()


from typing import Optional, Dict, Any
import pendulum
from geopy.distance import distance as geopy_distance

from src.data_models import Configuration

def add_calculated_fields(*,
                          current_item: Dict[str, Any],
                          initial_status,
                          current_status,
                          position_list,
                          lap_list,
                          total,
                          charging_process_list,
                          forecast,
                          configuration: Configuration,
                          current_item_index: Optional[int],
                          now_dt: pendulum.DateTime):
    """
    Add hardcoded calculated fields into current_item
    Note the prototype is the same for all calculated functions even if all inputs are not used

    :param current_item:
    :param initial_status:
    :param current_status:
    :param position_list:
    :param lap_list:
    :param total:
    :param charging_process_list:
    :param forecast:
    :param configuration:
    :param current_item_index:
    :param now_dt: time to calculate data for.
    :return:
    """
    initial_odo = initial_status['odometer'] if 'odometer' in initial_status else None
    current_odo = current_item['odometer'] if 'odometer' in current_item else None
    start_time = configuration.start_time
    end_time = configuration.start_time.add(hours=configuration.hours)

    current_item['distance'] = current_odo - initial_odo if current_odo is not None and initial_odo is not None else None

    current_item['air_distance'] = geopy_distance(
        (configuration.start_latitude, configuration.start_longitude),
        (current_item['latitude'], current_item['longitude'])
        ).km if 'latitude' in current_item and current_item['latitude'] is not None \
                and 'longitude' in current_item and current_item['longitude'] is not None else None

    current_item['start_time'] = start_time
    current_item['end_time'] = end_time

    current_item['time_since_start'] = pendulum.period(start_time, now_dt, True) \
        if now_dt >= start_time else pendulum.period(now_dt, now_dt, True)
    current_item['time_to_end'] = pendulum.period(now_dt, end_time, True) \
        if now_dt <= end_time else pendulum.period(now_dt, now_dt, True)

    current_item['slow_data_age'] = pendulum.period(current_item['slow_data_date'], now_dt) \
        if current_item and 'slow_data_date' in current_item and current_item['slow_data_date'] else None
    current_item['fast_data_age'] = pendulum.period(current_item['fast_data_date'], now_dt) \
        if current_item and 'fast_data_date' in current_item and current_item['fast_data_date'] else None

    current_item['lap_number'] = lap_list[-1]['lap_id'] if lap_list else None


#!/usr/bin/env python3
from sys import argv

def kvadrat(x):
    a = float(x)
    print(' При стороне квадрата: ', a)
    print(' Периметр квадрата: ', 4 * a)
    print(' Площадь квадрата: ', round(a * a, 5))
    b = a * 2**(1/2)
    print(' Диагональ квадрата: ', round(b, 3))

if len(argv) > 1:
    kvadrat(argv[1])
else:
    x = input('Введите сторону квадрата:  ')
    kvadrat(x)


#!/usr/bin/env python

import logging
from urllib.parse import urljoin

from atomic_utils import (
    PYCON_TW_ROOT_URL,
    query_text,
    parse_out_href_gen,
    is_relative_href,
    is_visited_or_mark,
)

# https://docs.python.org/3.6/library/logging.html#logrecord-attributes
logging.basicConfig(
    format=(
        '%(asctime)s\t'
        #'%(name)s\t'
        '%(levelname)s\t'
        #'%(processName)s\t'
        '%(threadName)s\t'
        #'%(module)s:'
        '%(funcName)s:%(lineno)d\t'
        '%(message)s'
    ),
    level=logging.DEBUG
)
l = logging.getLogger('channel_operators')

# make distinguishing and debuggable objects
RUNNING = ['running']
TO_RETURN = ['to_return']

def init_url_q(url_q):
    is_visited_or_mark(PYCON_TW_ROOT_URL)
    url_q.put(PYCON_TW_ROOT_URL)

def put_text_q(url_q, text_q, run_q):

    while True:

        # the below get and put should be synced
        # but for the readability, keep as it is

        l.info(f'url_q: {url_q.qsize()}')
        url = url_q.get()
        l.info(f'url_q.get() -> {url}')

        run_q.put(RUNNING)
        l.info('run_q.put(RUNNING)')

        if url is TO_RETURN:
            url_q.put(TO_RETURN)  # broadcast to siblings
            l.info('return')
            return

        text = query_text(url)
        text_q.put(text)

        run_q.get()
        l.info('run_q.get()')

def put_url_q(text_q, url_q, run_q):

    while True:

        l.info(f'text_q: {text_q.qsize()}')
        text = text_q.get()
        l.info(f'len(text_q.get()) -> {len(text)}')

        run_q.put(RUNNING)
        l.info('run_q.put(RUNNING)')

        if text is TO_RETURN:
            text_q.put(TO_RETURN)
            l.info('return')
            return

        href_gen = parse_out_href_gen(text)

        for href in href_gen:

            if not is_relative_href(href):
                continue

            url = urljoin(PYCON_TW_ROOT_URL, href)
            if is_visited_or_mark(url):
                continue

            url_q.put(url)

        l.info(f'url_q: {url_q.qsize()}')
        l.info(f'run_q: {run_q.qsize()}')
        if url_q.qsize() == 0 and run_q.qsize() == 1:
            url_q.put(TO_RETURN)
            text_q.put(TO_RETURN)
            l.info('url_q.put(TO_RETURN)')
            l.info('text_q.put(TO_RETURN)')

        run_q.get()
        l.info('run_q.get()')


import sys

import shapefile

from .utils import Command, FeatureLoader, create_connection, filename_to_table_name

def shp_field_to_sql_type(field):
    if field[1] == "L":
        return "INTEGER"
    if field[1] == "F":
        return "FLOAT"
    if field[1] == "N":
        if field[3] == 0:
            return "INTEGER"
        return "FLOAT"
    return "TEXT"

def shp_to_spatialite(
    sqlite_db,
    shp_file,
    table_name=None,
    spatialite_extension=None,
    srid=4326,
    pk=None,
    write_mode=None,
):
    """Load a SHP file into a SpatiaLite database

    Args:
        sqlite_db (str): Name of the SQLite database file
        shp_file (str): Path to a SHP file to import
        table_name (str, optional): Custom table name.
            Default: ``None`` (use the SHP file name)
        spatialite_extension (str, optional): Path to mod_spatialite extension. In most
            cases the spatialite extension can be automatically detected and loaded.
            If not you can manully pass a path to the .so .dylib or .dll file.
            Default: ``None`` (attempt to load automatically)
        srid (int, optional): Spatial Reference ID (SRID).
            Default: ``4326``
        pk (Union[str, list, tuple], optional): Field (str) or fields (list/tuple) to
            use as a primary key.
            Default: ``None`` (no primary key)
        write_mode (str, optional): By default we assume the target table does not
            already exist. Pass 'replace' or 'append' to overwrite or append to an
            existing table.
            Default: ``None`` (assume the table doesn't already exist)

    Returns:
        ``None``

    Raises:
        DataImportError
    """
    db = create_connection(sqlite_db, spatialite_extension)
    sf = shapefile.Reader(shp_file)
    features = [rec.__geo_interface__ for rec in sf.shapeRecords()]
    columns = {
        f[0]: shp_field_to_sql_type(f) for f in sf.fields if f[0] != "DeletionFlag"
    }
    columns["geometry"] = features[0]["geometry"]["type"].upper()
    name = table_name or filename_to_table_name(shp_file)
    loader = FeatureLoader(db, features, name, srid, pk, columns, write_mode)
    loader.load()
    db.conn.close()

cli = Command(shp_to_spatialite, "SHP")

def main():
    args = cli.parse_args(sys.argv[1:])
    cli.invoke(
        paths=args.paths,
        dbname=args.dbname,
        table=args.table,
        primary_key=args.primary_key,
        write_mode=args.write_mode,
        srid=args.srid,
        spatialite_extension=args.spatialite_extension,
    )


#!/usr/bin/env python3

import csv
import glob
import warnings
from typing import List, Tuple
from KaSaAn.core import KappaSnapshot

def find_snapshots(directory: str, prefix: str) -> List[str]:
    """Get the file names of snapshots in specified directory that fit the pattern [dir][prefix][number].ka"""
    if directory[-1] != '/':
        directory += '/'
    snap_names = glob.glob(directory + prefix + '*.ka')
    return snap_names

def process_snapshots(snap_names: List[str], verbosity: bool) -> Tuple[dict, dict, dict]:
    """For each snapshot, get size distribution, number of complexes, size of largest complex."""
    # For each snapshot, get the size distribution & update the results dictionary {size: abundance}
    # Also get the number of complexes in that snapshot and save it to another dictionary {snapshot name: number of complexes}
    cum_dist = {}
    total_complexes = {}
    lc_size = {}
    snap_num = len(snap_names)
    for snap_index, snap_name in enumerate(snap_names):
        if verbosity:
            print('Now parsing file <{}>, {} of {}, {:.2%}'.format(
                snap_name, snap_index, snap_num, snap_index/snap_num), end='\r')
        current_snapshot = KappaSnapshot(snap_name)
        total_complexes[snap_name] = sum(current_snapshot.get_all_abundances())
        lc_size[snap_name] = current_snapshot.get_largest_complexes()[0].get_size_of_complex()
        size_dist = current_snapshot.get_size_distribution()
        for key in size_dist.keys():
            if key in cum_dist:
                cum_dist[key] += size_dist[key]
            else:
                cum_dist[key] = size_dist[key]
    return cum_dist, total_complexes, lc_size

def save_cumulative(cum_dist, base_directory, snap_prefix, verbosity) -> int:
    """Save the cumulative distribution to file"""
    cum_dist_file_name = base_directory + snap_prefix + 'distribution_cumulative.csv'
    with open(cum_dist_file_name, 'w') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(['Size', 'Cumulative Abundance'])
        for key, value in cum_dist.items():
            writer.writerow([key, value])
    if verbosity:
        print('Cumulative distribution written to file: ' + cum_dist_file_name)
    return 0

def save_mean(cum_dist, base_directory, snap_prefix, verbosity, snap_num) -> int:
    """Save the mean distribution to file"""
    mean_dist_file_name = base_directory + snap_prefix + 'distribution_mean.csv'
    with open(mean_dist_file_name, 'w') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(['Size', 'Mean Abundance'])
        for key, value in cum_dist.items():
            writer.writerow([key, value / snap_num])
    if verbosity:
        print('Mean distribution written to file: ' + mean_dist_file_name)
    return 0

def save_complex_numbers(total_complexes, base_directory, snap_prefix, verbosity) -> int:
    """Save the number of complexes in each snapshot to a file"""
    num_species_file_name = base_directory + snap_prefix + 'total_complexes.csv'
    with open(num_species_file_name, 'w') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(['Snapshot Name', 'Number of complexes'])
        for key, value in total_complexes.items():
            writer.writerow([key, value])
    if verbosity:
        print('Distribution of number of complexes written to file: ' + num_species_file_name)
    return 0

def save_largest_complex(lc_size, base_directory, snap_prefix, verbosity) -> int:
    """Save the largest-complex statistics to file"""
    largest_complex_stats_file_name = base_directory + snap_prefix + 'largest_complex_stats.csv'
    with open(largest_complex_stats_file_name, 'w') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(['Snapshot Number', 'Largest Complex(es) Size'])
        for key, value in lc_size.items():
            writer.writerow([key, value])
    if verbosity:
        print('Largest complex sizes written to file: ' + largest_complex_stats_file_name)
    return 0

def prefixed_snapshot_analyzer(base_directory: str, snap_prefix: str, verbosity: bool):
    """Process snapshots located in a directory, grouped by their prefix. Obtain key statistics about them."""
    # get snapshot names
    snap_names = find_snapshots(base_directory, snap_prefix)
    snap_num = len(snap_names)
    if verbosity:
        print("Found " + str(snap_num) + " snapshots in " + base_directory + ' with prefix <' + snap_prefix + '>')
    if snap_num < 2:
        warnings.warn('Found less than 2 snapshots.')
    # process snapshots
    cum_dist, total_complexes, lc_size = process_snapshots(snap_names, verbosity)
    # save to files
    save_cumulative(cum_dist, base_directory, snap_prefix, verbosity)
    save_mean(cum_dist, base_directory, snap_prefix, verbosity, snap_num)
    save_complex_numbers(total_complexes, base_directory, snap_prefix, verbosity)
    save_largest_complex(lc_size, base_directory, snap_prefix, verbosity)


import matplotlib.pyplot as plt

def plot_indicators_empirical_analysis(all_sorted_intervals):
    """

    :param all_sorted_intervals: all created time intervals
    """

    spam_x = []
    spam_y = []
    non_x = []
    non_y = []
    counter = 0
    for interval in all_sorted_intervals:
        if interval.spam_label:
            spam_x.append(counter)
            spam_y.append(interval.density)
        else:
            non_y.append(interval.density)
            non_x.append(counter)

        counter += 1

    plt.scatter(spam_x, spam_y, c='red')
    plt.scatter(non_x, non_y, c='green')
    plt.xlabel('Interval')
    plt.ylabel('Density')
    plt.show()


import numpy as np
import pickle

from abc import ABC
from keras.layers import Input, Dense, TimeDistributed
from keras.layers import LeakyReLU, Dropout, Bidirectional
from keras.layers import GRU, LSTM
from keras.models import Model
from keras.models import load_model

from modules.constants import Constants
from modules.word_embedding import WordEmbedding
from modules.summarizer.metrics import precision, recall, f1
from modules.summarizer.preprocessor import Preprocessor
from modules.utils.text_util import split_to_sentences

class BaseModel(ABC):
    def __init__(self):
        self._model = None
        print('[SUMMARIZER] Initializing Model')

    def train(self, x_train: np.ndarray, y_train: np.ndarray, x_val: np.ndarray, y_val: np.ndarray, log_path: str):
        history = self._model.fit(
            x_train,
            y_train,
            epochs=100,
            validation_data=(x_val, y_val)
        )
        logfile = open(Constants.MODEL_PATH + log_path, 'wb+')
        pickle.dump(history.history, logfile)

    def predict(self, x: np.ndarray) -> np.ndarray:
        return self._model.predict(x)

    def summarize(self, sentences: [str], word_embedding: WordEmbedding, n_sentence: int = 0) -> [str]:
        last_sentence_idx = len(sentences) - 1

        sentences_vector = Preprocessor.preprocess_text(sentences, word_embedding)
        model_predictions = self.predict(sentences_vector)

        predictions = model_predictions[0]

        index_confidence_list = []
        for idx, prediction in enumerate(predictions):
            index_confidence_list.append((idx, prediction[1]))

        selected_indices = []

        if n_sentence > 0:
            n = 0
            index_confidence_list.sort(key=lambda x: x[1], reverse=True)
            while n < n_sentence:
                if index_confidence_list[n][0] <= last_sentence_idx:
                    selected_indices.append(index_confidence_list[n][0])
                    n += 1
                else:
                    n += 1
                    n_sentence += 1
            selected_indices.sort()
        else:  # Use threshold
            for idx, confidence in index_confidence_list:
                if confidence > Constants.MODEL_THRESHOLD and idx < last_sentence_idx:
                    selected_indices.append(idx)

        summary = []
        for selected_index in selected_indices:
            summary.append(sentences[selected_index])

        return summary

    def evaluate(self, x_test: np.ndarray, y_test: np.ndarray) -> (float, float, float):
        loss, accuracy_score, precision_score, recall_score, f1_score = self._model.evaluate(x_test, y_test)
        return loss, accuracy_score, precision_score, recall_score, f1_score

    def save(self, model_name: str):
        self._model.save(Constants.MODEL_PATH + '{}.h5'.format(model_name))
        print('[SUMMARIZER] Model saved to {}'.format(Constants.MODEL_PATH + '{}.h5'.format(model_name)))

    def load(self, model_name: str):
        self._model = load_model(Constants.MODEL_PATH + '{}.h5'.format(model_name), custom_objects={'precision': precision, 'recall': recall, 'f1': f1})
        print('[SUMMARIZER] Model {} loaded'.format(model_name))

class FFNNModel(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.WORD_EMBEDDING_DIMENSION,))

        hidden_1 = Dense(256)(inputs)
        actvfn_1 = LeakyReLU(alpha=0.1)(hidden_1)
        drpout_1 = Dropout(0.5)(actvfn_1)

        hidden_2 = Dense(128)(drpout_1)
        actvfn_2 = LeakyReLU(alpha=0.1)(hidden_2)
        drpout_2 = Dropout(0.5)(actvfn_2)

        predictions = Dense(2, activation='softmax')(drpout_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )

class FFNNSeq(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.MAXIMUM_SENTENCE_LENGTH, Constants.WORD_EMBEDDING_DIMENSION,))

        input_dropout = Dropout(0.5)(inputs)

        hidden_1 = Dense(256)(input_dropout)
        actvfn_1 = LeakyReLU(alpha=0.1)(hidden_1)
        drpout_1 = Dropout(0.5)(actvfn_1)

        hidden_2 = Dense(128)(drpout_1)
        actvfn_2 = LeakyReLU(alpha=0.1)(hidden_2)
        drpout_2 = Dropout(0.5)(actvfn_2)

        predictions = TimeDistributed(Dense(
            2,
            activation='softmax'
        ))(actvfn_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )

class GRUModel(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.MAXIMUM_SENTENCE_LENGTH, Constants.WORD_EMBEDDING_DIMENSION,))

        input_dropout = Dropout(0.5)(inputs)

        gru_1 = GRU(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        )(input_dropout)

        gru_2 = GRU(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        )(gru_1)

        predictions = TimeDistributed(Dense(
            2,
            activation='softmax'
        ))(gru_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )

class LSTMModel(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.MAXIMUM_SENTENCE_LENGTH, Constants.WORD_EMBEDDING_DIMENSION,))

        input_dropout = Dropout(0.5)(inputs)

        lstm_1 = LSTM(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        )(input_dropout)

        lstm_2 = LSTM(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        )(lstm_1)

        predictions = TimeDistributed(Dense(
            2,
            activation='softmax'
        ))(lstm_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )

class BiGRUModel(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.MAXIMUM_SENTENCE_LENGTH, Constants.WORD_EMBEDDING_DIMENSION,))

        input_dropout = Dropout(0.5)(inputs)

        bigru_1 = Bidirectional(GRU(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        ))(input_dropout)

        bigru_2 = Bidirectional(GRU(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        ))(bigru_1)

        predictions = TimeDistributed(Dense(
            2,
            activation='softmax'
        ))(bigru_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )

class BiLSTMModel(BaseModel):
    def __init__(self):
        super().__init__()
        inputs = Input(shape=(Constants.MAXIMUM_SENTENCE_LENGTH, Constants.WORD_EMBEDDING_DIMENSION,))

        input_dropout = Dropout(0.5)(inputs)

        bilstm_1 = Bidirectional(LSTM(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        ))(input_dropout)

        bilstm_2 = Bidirectional(LSTM(
            64,
            dropout=0.5,
            recurrent_dropout=0.5,
            return_sequences=True
        ))(bilstm_1)

        predictions = TimeDistributed(Dense(
            2,
            activation='softmax'
        ))(bilstm_2)

        self._model = Model(inputs=inputs, outputs=predictions)
        self._model.summary()

        self._model.compile(
            optimizer='adam',
            loss='categorical_crossentropy',
            metrics=['accuracy', precision, recall, f1]
        )


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

def exist(board, word):
    ROWS, COLS = len(board), len(board[0])
    visited = [[False for _ in range(COLS)] for _ in range(ROWS)]

    def dfs(row, col, searchIdx):
        if searchIdx == len(word):
            return True
        if not 0 <= row < ROWS or not 0 <= col < COLS or visited[row][col] or board[row][col] != word[searchIdx]:
            return False

        visited[row][col] = True

        for direction in DIRECTIONS:
            if dfs(row + direction[0], col + direction[1], searchIdx + 1):
                return True

        visited[row][col] = False

    for row in range(ROWS):
        for col in range(COLS):
            if board[row][col] == word[0]:
                if dfs(row, col, 0):
                    return True
            else:
                continue

    return False


import requests
from flask import Flask, render_template
from bs4 import BeautifulSoup

file = "kari-sakib-lab-report.txt"
url = "https://climate.nasa.gov/effects/"

def convert_tag_to_str_list(lst):
    new_lst = []
    for i in lst:
        new_lst.append(str(i))
    return new_lst

def scraper(url):
    r = requests.get(url)
    soup = BeautifulSoup(r.text)
    data_headings = ["Climate Change Effect", "How It Happens"]
    data_findings = [x for x in range(2)]
    text_headings = convert_tag_to_str_list(soup.findAll('h2'))
    text_desc = convert_tag_to_str_list(soup.find('aside'))
    text_desc = text_desc[-2:-1]
    text_desc = text_desc[0][109:-11]
    heading = []
    for i in text_headings:
        if i.startswith('<h2 class='):
            heading.append(i)
    heading = heading[0][27:-6]
    data_findings[0] = heading
    data_findings[1] = text_desc

    return data_findings[0], data_findings[1]

app = Flask(__name__)

@app.route('/')
def home():
    return render_template("base.html")

@app.route('/data')
def data():
    return scraper(url)

@app.route('/form')
def data():
    return render_template("form.html")

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


#coding:utf-8
from __future__ import print_function

import os
import sys
# sys.path.append('../')
import time
import cv2
# import rospy
import math
import pickle
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.animation as animation
import matplotlib.image as mpimg
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
from multiprocessing import Process
from concurrent.futures import ProcessPoolExecutor

import data_manager
import utility as utils
import settings as sets

GENERATE_ANIM_WITH_IMAGE = False

class Line:
    x = []
    y = []

'''
Animation
'''
class Animation_():
    def __init__(self):
        # Data
        self.DataManager = None

        # Animation
        self.fig0 = plt.figure(figsize=(9, 6))
        # self.fig0 = plt.figure(figsize=(6, 6))

        self.fig0.canvas.draw()
        # self.fig0.suptitle("ObjectVisualizer")
        self.ax0 = [self.fig0.add_subplot(1, 1, 1),]

        if GENERATE_ANIM_WITH_IMAGE:
            self.fig0 = plt.figure(figsize=(10, 6), facecolor='#e7e7e7')
            self.fig0.canvas.draw()
            # self.fig0.suptitle("ObjectVisualizer")
            self.ax0 = [self.fig0.add_subplot(1, 2, 1),
                        self.fig0.add_subplot(2, 2, 2),
                        self.fig0.add_subplot(2, 2, 4)]

        # Plot planning result
        # self.fig1, self.ax1 = plt.subplots(nrows=4, sharex=True, figsize=(8, 6))
        self.rect_0 = patches.Rectangle((0-4.8/2+1.0, 0-1.8/2), 4.8, 1.8, angle=0, ec='r', fill=True, fc="r")  # ego-vehicle (ROH=1.0mとする)
        self.rect_1 = patches.Rectangle((0-4.8/2, 0-1.8/2), 4.8, 1.8, angle=0, ec='b', fill=False)          # surrounding vehicle

        # Buffering data
        self.nav_sec_time = None
        self.decounter_BEV = 0
        self.map_name = None

        # EgoWalker initial data
        self.ego_pos_x, self.ego_pos_y = 0.0, 0.0

    def calc_rectangle_point(self, theta, length, width):
        # print(theta)
        R = np.sqrt(np.power(length, 2) + np.power(width, 2))/2.0
        ang = -np.pi/2.0 + theta + np.arctan2(width/2.0, length/2.0)
        x = R*np.cos(ang)
        y = R*np.sin(ang)
        return x, y

    def LPF_matrix(self, ur, tau, dt):
        out_LPF = np.zeros_like(ur)
        for i in range(1, ur.shape[0]):
            out_LPF[i] = out_LPF[i-1] + ((ur[i] - out_LPF[i-1]) * dt / tau)
        return out_LPF

    def LPF(self, ur, ur_pre, tau, dt):
        out_LPF = ur_pre + ((ur - ur_pre) * dt / tau)
        return out_LPF

    def search_neaerst_idx(self, mat, val):
        idx = np.abs(mat - val).argmin()
        # print(idx)
        return idx

    def load_map_lane_info(self, map_name):
        self.lane_info = []
        fname = 'map/map_lane_info_' + map_name + '.pkl'
        with open(fname, mode="rb") as f:
            self.lane_info = pickle.load(f)
        # print(self.lane_info)

    def plot_lane_info(self):
        for lane in self.lane_info:
            self.ax0[0].plot(lane.y, lane.x, color='darkslategrey', markersize=1)

    """
    For save animation
    """
    def output_image(self, savedir, iter):
        # print("Saving Animation: " + str(iter) +
        #       "/" + str(self.DataManager.data_size))
        print("\rSaving Image: " + str(iter) +
              "/" + str(self.DataManager.data_size), end="")
        LabelName = ["Lateral"]

        for idx_fig in range(len(LabelName)):
            self.ax0[idx_fig].clear()

        # self.fig0.suptitle("ObjectVisualizer" + "\n" +
        #                     'Seq:' + str('{:d}'.format(iter)) + "[-]" +
        #                    "\n"
        #                    )
        self.fig0.suptitle(
                        'Frame:' + str('{:d}'.format(iter)) + "[-]" +
                        "\n"
                        )

        """
            Geometry information
        """
        self.plot_lane_info()

        """
            Object information
        """
        # ===  物標情報 === #
        if (self.DataManager.logdata_all_objects[iter]):
            cnt = 0
            self.obj_rects = [self.rect_1 for _ in range(
                len(self.DataManager.logdata_all_objects[iter]))]

            for obj in self.DataManager.logdata_all_objects[iter]:
                # print(obj.object_type, obj.pose.x, obj.pose.y, obj.pose.yaw)
                # === Title ===
                if (obj.object_id == 600):
                    # self.fig0.suptitle("ObjectVisualizer" + "\n" +
                    #     'Seq:' + str('{:d}'.format(obj.seq_id)) + "[-]" +
                    #     "\n"
                    #     )
                    self.fig0.suptitle(
                        'Frame:' + str('{:d}'.format(obj.seq_id)) + "[-]" +
                        "\n"
                        )

                # === Animation ===
                if (obj.object_id == 99999):
                    pass
                else:
                    label_name = "Obj" + str(obj.object_id)
                    # pose
                    self.ax0[0].plot(
                        obj.pose.y, obj.pose.x,  ".-b", label=label_name)

                    # future trajectory
                    # if obj.object_type == "vehicle*":
                    if 'vehicle' in obj.object_type:
                        idx = 0

                        # rectangle
                        # Calculate rectangle origin
                        rect_origin_x = (-obj.length/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        - (-obj.width/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.x
                        rect_origin_y = (-obj.length/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + (-obj.width/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.y
                        self.ax0[0].add_patch(patches.Rectangle((rect_origin_y, rect_origin_x),
                                                                 obj.width, obj.length,
                                                                 angle=-obj.pose.yaw,
                                                                 ec='b', fill=False))
                    elif 'walker' in obj.object_type:
                        if obj.object_id == 600:
                            self.ego_pos_x = obj.pose.x
                            self.ego_pos_y = obj.pose.y
                            # print("Obtained VR ego-walker object information", self.ego_pos_x, self.ego_pos_y)

                        self.ax0[0].plot(obj.pose.y, obj.pose.x,  ".-r", label=label_name)
                        # rectangle
                        width, length = obj.width, obj.length
                        # Calculate rectangle origin
                        rect_origin_x = (-obj.length/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        - (-obj.width/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.x
                        rect_origin_y = (-obj.length/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + (-obj.width/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.y
                        self.ax0[0].add_patch(patches.Rectangle((rect_origin_y, rect_origin_x),
                                                                 width, length,
                                                                 angle=-obj.pose.yaw,
                                                                 ec='r', fill=False))
                        # Draw arrow
                        arrow_length = 2.0
                        dy = arrow_length * np.sin(obj.pose.yaw*np.pi/180.0)
                        dx = arrow_length * np.cos(obj.pose.yaw*np.pi/180.0)
                        self.ax0[0].arrow(obj.pose.y, obj.pose.x, dy, dx, head_width=0.1, fc='r', ec='r')
                    else:
                        idx = 0
                        prob_cut_in = False
                        fc_color = 'b'
                        # rectangle
                        width, length = obj.width, obj.length
                        # Calculate rectangle origin
                        rect_origin_x = (-obj.length/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        - (-obj.width/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.x
                        rect_origin_y = (-obj.length/2) * np.sin(obj.pose.yaw*np.pi/180.0) \
                                        + (-obj.width/2) * np.cos(obj.pose.yaw*np.pi/180.0) \
                                        + obj.pose.y
                        self.ax0[0].add_patch(patches.Rectangle((rect_origin_y, rect_origin_x),
                                                                 width, length,
                                                                angle=-obj.pose.yaw, ec='b',
                                                                fill=prob_cut_in, fc=fc_color))

                        if (obj.object_id == 2612):
                            print(obj.bbox_bottom_right)

                        # self.obj_rects[cnt] = patches.Rectangle((obj.pose.y - obj.width/2, obj.pose.x - obj.length/2),
                        #                                         obj.width, obj.length, angle=0, ec='b', fill=False)

                    # Information
                    self.ax0[0].text(obj.pose.y, obj.pose.x,
                                        (" ObjID:" + str(int(obj.object_id))
                                        + "\n Loc:[" + str('{:.2f}'.format(obj.pose.x)) + ", " + str('{:.2f}'.format(obj.pose.y)) + "] [m]" +
                                        "\n Yaw:[" + str('{:.2f}'.format(obj.pose.yaw)) + "] [deg]" + "\n"
                                    # "\n StopFlag:" + str(obj.stop_vehicle_flag) + ""
                                        ))
                    # plt.pause(0.000001)

                # # Plot Figure (Rectangle)
                # self.plot0 = self.ax0[0].add_patch(self.rect_0)
                # for it in self.obj_rects:
                #     self.ax0[0].add_patch(it)

        # self.ax0[0].add_patch(rect_ego)
        # self.ax0[0].plot(traj[:, 1], traj[:, 0], ".-r", label="wide path")
        self.ax0[0].set_xlim(self.ego_pos_y-10.0, self.ego_pos_y+10.0)
        self.ax0[0].set_ylim(self.ego_pos_x-10.0, self.ego_pos_x+10.0)
        # self.ax0[0].grid(True, zorder=10)
        self.ax0[0].grid(False)
        # self.ax0[0].set_xlabel("Lateral position[m]")
        # self.ax0[0].set_ylabel("Longitudinal position[m]")
        self.ax0[0].set_aspect("equal")

        self.ax0[0].axis("off")
        self.ax0[0].set_facecolor('#e7e7e7')

        # plt.pause(1)

        plt.savefig(f'{savedir}/{iter:05d}.png', format="png", dpi=300)

    def get_map_name(self, data):
        map_name = None
        for obj in data:
            if obj.object_id == 600:
                map_name = obj.map_name
                print("map_name: ", map_name)
                break
        return map_name

    def save_animation(self, savedir, DataManager):
        # Set DataManager information
        self.DataManager = DataManager
        self.map_name = self.get_map_name(self.DataManager.logdata_all_objects[1])
        self.load_map_lane_info(self.map_name)        # ### BEV Image ###

        # Loop animation
        # ani = animation.FuncAnimation(
        #     self.fig0, self.update_anim, interval=1, frames=DataManager.data_size)
        print("save dir:", savedir)

        # === Single Processing ===
        for frame in range(DataManager.data_size):
            self.output_image(savedir, frame)

        # with ProcessPoolExecutor(max_workers=10) as executor:
        #     for frame in range(DataManager.data_size):
        #         executor.submit(self.output_image, savedir, frame)

def execute(target_date, target_dir_name, target_dir, fpath):
    # === Create instance ===
    DataManager = data_manager.DataManager_()
    animator = Animation_()
    target_file_name = fpath.replace(target_dir + '/' + target_dir_name, "")
    # print(target_file_name)
    file_name_list = target_file_name.split('/')
    savedir_supplement = ""
    for i in range(len(file_name_list)):
        if (i >= len(file_name_list)-1):
            pass
        else:
            savedir_supplement = savedir_supplement + file_name_list[i] + '/'

    # === Make output directory ===
    output_dir = f'{target_dir}/{target_dir_name}{savedir_supplement}image/'
    os.makedirs(output_dir, exist_ok=True)

    # === Load timesync info ===
    timesync_info_dir = f'{target_dir}/{target_dir_name}{savedir_supplement}'
    timesync_info = np.loadtxt(f'{timesync_info_dir}timesync_result.csv')

    print(timesync_info)

    # === Load data and generate images ===
    try:
        DataManager.set_logfile_dir(target_date, target_dir_name, target_file_name)
        DataManager.set_image_data_dir(target_date, target_dir_name)
        DataManager.read_logdata()
        # DataManager.load_BEV_images()
        # DataManager.load_RGB_images()

        # Generate image
        animator.save_animation(output_dir, DataManager)
        print("\n[INFO]Finished genrating animation:", fpath, " \n")

        # Deinit
        del DataManager, animator

    except Exception as e:
        print("Error occured:", e)
        pass

if __name__ == "__main__":
    DataManager = data_manager.DataManager_()

    # target_date = '230201'
    # target_date = '230420'
    # target_date = '230427'
    # target_date = '230511'
    # target_date = '230608'
    # target_date = '230724'
    target_date = '230817'
    target_dir_name = ''

    # Obtain csv filename lists
    target_dir = DataManager.LOGDATA_ROOT + '/' + target_date
    fpath_list = utils.get_csv_file_list(target_dir)

    # TODO:Debug:
    # Change date to 8 digits
    date_8digits = f'{sets.LOGDATE[2:6]}20{sets.LOGDATE[:2]}'
    print(date_8digits)
    time_6digits = f'{sets.LOGDIR[4:10]}'

    fpath = f'{sets.SIMDATA_ROOT_DIR}{sets.LOGDATE}{sets.LOGDIR}logdata_{date_8digits}_{time_6digits}.csv'
    print(fpath)
    execute(target_date, target_dir_name, target_dir, fpath)

    # # Single processing
    # for fpath in fpath_list:
    #     execute(target_date, target_dir_name, target_dir, fpath)

    # # Multi-processing
    # processes = []

    # with ProcessPoolExecutor(max_workers=20) as executor:
    #     for fpath in fpath_list:
    #         print("Start multi-processing")
    #         executor.submit(execute, target_date, target_dir_name, target_dir, fpath)


#     # Create an app that supports multiple Shopping Lists.
#     # Each SHopping list will contain multiple items.

# create_list = []
# import sys
# from create_list import create_list
# from add_item import add_item
shopping_lists = {
        "Kroger": ["egg", "milk", "bread", "juice"],
        "Walmart": ["lightbulb", "toy", "snacks"],
        "Target" : ["shampoo", "clothes", "energy drink"]
}

def main():
    print("""SHOPPING LIST
Select a number for the action you would like to do

1. Create shopping list
2. Add item to shopping list
3. Remove item from shopping list
4. Clear shopping list
5. Exit
""")

    selection = input("Make your selection: ")

    if selection == "1":
        while True:
            store_name = input("Store Name: ")
            if store_name not in shopping_lists:
                shopping_lists[store_name] = []
                print(f"List added: {store_name}")
                print(shopping_lists)
                break
            else:
                print(f"List with name '{store_name}' already exists")
    else:
        print("You did not make a valid selection.")

    if selection == "2":
        while True:
            add_item = input("Name of the item: ")
            if add_item not in shopping_lists[{}]:
                add_item.append = [{}]
                print(f"Item added. {add_item} ")
                print(add_item)
                break
            else:
                print(f"List with name '{add_item}' already exists ")

main()

# def add_item ():
#     item = input("Enter the item you wish to add to the shopping list: ")
#     shopping_list.append(item)
#     print(item + " has been added to the shopping list. ")

# def remove_item ():
#     item = input("Enter the item you would like to remove from the shopping list: ")
#     shopping_list.remove(item)
#     print(item + " has been removed from the shopping list. ")


import sys, pygame, random

class enemy(pygame.sprite.Sprite):
    def __init__(self, posX, posY):
        super().__init__()

        randomEntity = []
        randomEntity = [pygame.image.load("../assets/spaceinvader1.png").convert_alpha(), pygame.image.load("../assets/spaceinvader2.png").convert_alpha(), pygame.image.load("../assets/spaceinvader3.png").convert_alpha()]
        self.entity = randomEntity[random.randint(0,2)]
        self.entity = pygame.transform.scale(self.entity, (87,63))
        self.rect = self.entity.get_rect()
        self.rect = self.rect.move(posX, posY)
        self.speed = [0, random.randint(2,3)]
        self.mask = pygame.mask.from_surface(self.entity)
        self.moveDirection = 5
class enemyList:
    def __init__(self):
        self.enemyArray = []
        self.moveDir = 5
        self.spawnY = 100
    def createEnemy(self,wave):
        x = 0
        y = 100
        for x in range(0, wave):
            self.enemyArray.append(enemy(x*100, self.spawnY))
            if len(self.enemyArray)%10 == 0:
                self.spawnY += 100
        self.spawnY = 100
    def moveAll(self, bulletArray, player):
        x = 0
        for x in self.enemyArray:
            x.rect = x.rect.move(x.moveDirection, 0)
            if(x.rect.right >= 1080):
                x.moveDirection = -5
            if(x.rect.left <= 0):
                x.moveDirection = 5
            y = 0
            for y in bulletArray:
                offset_x = x.rect.right - y.rect.left
                offset_y = y.rect.bottom - x.rect.bottom
                if(x.mask.overlap_area(y.mask, (offset_x, offset_y))):
                    self.enemyArray.remove(x)
                    player.score += 110

                    if player.score >= player.highscore:
                        player.highscore = player.score
                    bulletArray.remove(y)


RES = WIDTH, HEIGHT = 1600, 900
FPS = 60
SCROLL_SPEED = 8

# bird
BIRD_POS = WIDTH // 4, HEIGHT // 4
BIRD_SCALE = 1.5
BIRD_AN = 150
GRAVITY = 1
JUMP = -16
BIRD_ANGLE = 25

# ground
GROUND_HEIGHT = HEIGHT // 12
GROUND_Y = HEIGHT - GROUND_HEIGHT

# pipes
PIPES_WIDTH = 150
PIPES_HEIGHT = HEIGHT
DIST_BETWEEN_PIPES = 650
GAP_HEIGHT = 320
HALF_GAP_BETWEEN_PIPES = GAP_HEIGHT // 2


# Создайте 2 экземпляра данного класса. У каждого
# экземпляра вызовите оба параметра описанные в этом классе.
#  Для обоих экземпляров вызовите метод **climb**

class Monkey:
    max_age = 12
    loves_bananas = True

    def climb(self):
	    print('I am climbing the tree')

c = Monkey()
p = Monkey()
c.climb()
print(c.max_age)
print(c.loves_bananas)
p.climb()
print(p.max_age)
print(p.loves_bananas)


import torch
import torch.nn as nn
import torch.nn.functional as F
import math
import time

def timeit(x, func, iter=10):
    torch.cuda.synchronize()
    start = time.time()
    for _ in range(iter):
        y = func(x)
    torch.cuda.synchronize()
    runtime = (time.time()-start)/iter
    return runtime

class HOGLayer(nn.Module):
    def __init__(self, nbins=10, pool=8, max_angle=math.pi, stride=1, padding=1, dilation=1):
        super(HOGLayer, self).__init__()
        self.nbins = nbins
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.pool = pool
        self.max_angle = max_angle
        mat = torch.FloatTensor([[1, 0, -1],
                                [2, 0, -2],
                                [1, 0, -1]])
        mat = torch.cat((mat[None], mat.t()[None]), dim=0)
        self.register_buffer("weight", mat[:,None,:,:])
        self.pooler = nn.AvgPool2d(pool, stride=pool, padding=0, ceil_mode=False, count_include_pad=True)

    def forward(self, x):
        with torch.no_grad():
            gxy = F.conv2d(x, self.weight, None, self.stride,
                            self.padding, self.dilation, 1)
            #2. Mag/ Phase
            mag = gxy.norm(dim=1)
            norm = mag[:,None,:,:]
            phase = torch.atan2(gxy[:,0,:,:], gxy[:,1,:,:])

            #3. Binning Mag with linear interpolation
            phase_int = phase / self.max_angle * self.nbins
            phase_int = phase_int[:,None,:,:]

            n, c, h, w = gxy.shape
            out = torch.zeros((n, self.nbins, h, w), dtype=torch.float, device=gxy.device)
            out.scatter_(1, phase_int.floor().long()%self.nbins, norm)
            out.scatter_add_(1, phase_int.ceil().long()%self.nbins, 1 - norm)

            return self.pooler(out)

class HOGLayerMoreComplicated(nn.Module):
    def __init__(self, nbins=10, pool=8, max_angle=math.pi, stride=1, padding=1, dilation=1,
                 mean_in=False, max_out=False):
        super(HOGLayerMoreComplicated, self).__init__()
        self.nbins = nbins
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.pool = pool
        self.max_angle = max_angle
        self.max_out = max_out
        self.mean_in = mean_in

        mat = torch.FloatTensor([[1, 0, -1],
                                 [2, 0, -2],
                                 [1, 0, -1]])
        mat = torch.cat((mat[None], mat.t()[None]), dim=0)
        self.register_buffer("weight", mat[:,None,:,:])
        self.pooler = nn.AvgPool2d(pool, stride=pool, padding=0, ceil_mode=False, count_include_pad=True)

    def forward(self, x):
        if self.mean_in:
            return self.forward_v1(x)
        else:
            return self.forward_v2(x)

    def forward_v1(self, x):
        if x.size(1) > 1:
            x = x.mean(dim=1)[:,None,:,:]

        gxy = F.conv2d(x, self.weight, None, self.stride,
                       self.padding, self.dilation, 1)
        # 2. Mag/ Phase
        mag = gxy.norm(dim=1)
        norm = mag[:, None, :, :]
        phase = torch.atan2(gxy[:, 0, :, :], gxy[:, 1, :, :])

        # 3. Binning Mag with linear interpolation
        phase_int = phase / self.max_angle * self.nbins
        phase_int = phase_int[:, None, :, :]

        n, c, h, w = gxy.shape
        out = torch.zeros((n, self.nbins, h, w), dtype=torch.float, device=gxy.device)
        out.scatter_(1, phase_int.floor().long() % self.nbins, norm)
        out.scatter_add_(1, phase_int.ceil().long() % self.nbins, 1 - norm)

        return self.pooler(out)

    def forward_v2(self, x):
        batch_size, in_channels, height, width = x.shape
        weight = self.weight.repeat(3, 1, 1, 1)
        gxy = F.conv2d(x, weight, None, self.stride,
                        self.padding, self.dilation, groups=in_channels)

        gxy = gxy.view(batch_size, in_channels, 2, height, width)

        if self.max_out:
            gxy = gxy.max(dim=1)[0][:,None,:,:,:]

        #2. Mag/ Phase
        mags = gxy.norm(dim=2)
        norms = mags[:,:,None,:,:]
        phases = torch.atan2(gxy[:,:,0,:,:], gxy[:,:,1,:,:])

        #3. Binning Mag with linear interpolation
        phases_int = phases / self.max_angle * self.nbins
        phases_int = phases_int[:,:,None,:,:]

        out = torch.zeros((batch_size, in_channels, self.nbins, height, width),
                          dtype=torch.float, device=gxy.device)
        out.scatter_(2, phases_int.floor().long()%self.nbins, norms)
        out.scatter_add_(2, phases_int.ceil().long()%self.nbins, 1 - norms)

        out = out.view(batch_size, in_channels * self.nbins, height, width)
        out = torch.cat((self.pooler(out), self.pooler(x)), dim=1)

        return out

if __name__ == '__main__':
    import cv2
    cuda = True

    path = '/home/etienneperot/Pictures/pencils.jpg'
    im = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

    x = torch.from_numpy(im)[None, None]
    if cuda:
        x = x.cuda().float()
    else:
        x = x.float()

    hog = HOGLayer(nbins=12, pool=2)
    if cuda:
        hog = hog.cuda()

    y = hog(x)

    y2 = y.cpu().numpy()
    bin = 0
    while 1:
        im = y2[0, bin]
        im = (im-im.min())/(im.max()-im.min())
        print('bin: ', bin, ' ang: ', float(bin)/hog.nbins * 180.0)
        cv2.imshow('bin', im)
        cv2.waitKey()
        bin = (bin + 1) % hog.nbins