#!/usr/bin/env python
"""A simple program, which can track the currently played media."""

# Exception handling is not critical in this use case, we'll want to just
# proceed everytime.
# pylint: disable=W0702

import argparse
import asyncio
import ctypes
import datetime
import json
import http.server
import os
import sys
import typing
import urllib.request
import unidecode

if sys.platform == "linux":  # --- Linux Implementation: DBus (dbus-python) -- #
    import dbus

    async def get_current_media_info() -> typing.Optional[dict]:
        """Queries information about the currently played media."""
        session_bus = dbus.SessionBus()
        instance = ""
        for name in session_bus.list_names():
            if "org.mpris.MediaPlayer2" in name:
                instance = name
                break
        proxy = session_bus.get_object(instance, "/org/mpris/MediaPlayer2")
        iface = dbus.Interface(proxy, "org.freedesktop.DBus.Properties")
        properties = iface.GetAll("org.mpris.MediaPlayer2.Player")

        if properties["PlaybackStatus"] not in ("Playing", "Paused"):
            return {"Playing": False}
        paused = properties["PlaybackStatus"] == "Paused"

        title = "Unknown"
        artist = ""
        length = 0
        position = 0
        for field in properties["Metadata"]:
            if "title" in field or "Title" in field:
                title = properties["Metadata"][field]
            elif "artist" in field or "Artist" in field:
                artist = properties["Metadata"][field]
                if isinstance(artist, dbus.Array):
                    artist = artist[0]
            elif "length" in field or "Length" in field:
                length = properties["Metadata"][field] // 1000000
                if "Position" in properties:
                    position = properties["Position"] // 1000000
        return {
            "Playing": True,
            "Paused": paused,
            "Artist": artist,
            "Title": title,
            "Position": position,
            "Length": length,
        }

    async def go_to_previous() -> None:
        """Jumps to the previous track."""
        call_dbus_command("Previous")

    async def toggle_play_pause() -> None:
        """Plays or pauses the current track."""
        call_dbus_command("PlayPause")

    async def go_to_next() -> None:
        """Jumps to the next track."""
        call_dbus_command("Next")

    async def seek_backward_5sec() -> None:
        """Seeks forward 5 seconds, if available."""
        call_dbus_command("Seek", -5000000)

    async def seek_forward_5sec() -> None:
        """Seeks forward 5 seconds, if available."""
        call_dbus_command("Seek", +5000000)

    def call_dbus_command(command: str, argument: typing.Any = None) -> None:
        """Calls a single DBus command."""
        session_bus = dbus.SessionBus()
        instance = ""
        for name in session_bus.list_names():
            if "org.mpris.MediaPlayer2" in name:
                instance = name
                break
        proxy = session_bus.get_object(instance, "/org/mpris/MediaPlayer2")
        method = proxy.get_dbus_method(
            command, dbus_interface="org.mpris.MediaPlayer2.Player"
        )
        # Here only the method call is needed, not its result, the whole
        # conditional is only used to handle the optional argument.
        # pylint: disable-next=W0106
        method(argument) if argument is not None else method()

    def set_console_title(title: str) -> None:
        """Sets the console title of the terminal."""
        print(f"\33]0;{title}\a", end="", flush=True)

elif sys.platform == "win32":  # --- Windows Implementation: WinRT (winsdk) -- #
    # This module is only available on Windows.
    # pylint: disable-next=E0401
    from winsdk.windows.media.control import (
        GlobalSystemMediaTransportControlsSessionManager as MediaManager,
    )

    async def get_current_media_info() -> typing.Optional[dict]:
        """Queries information about the currently played media."""
        sessions = await MediaManager.request_async()
        session = sessions.get_current_session()
        if session:
            media = await session.try_get_media_properties_async()
            media = {
                attribute: media.__getattribute__(attribute)
                for attribute in dir(media)
                if attribute[0] != "_"
            }
            timeline = session.get_timeline_properties()
            timeline = {
                attribute: timeline.__getattribute__(attribute)
                for attribute in dir(timeline)
                if attribute[0] != "_"
            }
            playback = session.get_playback_info()
            playback = {
                attribute: playback.__getattribute__(attribute)
                for attribute in dir(playback)
                if attribute[0] != "_"
            }
            now = datetime.datetime.now(datetime.timezone.utc)
            position = now - timeline["last_updated_time"] + timeline["position"]
            if playback["playback_status"] not in (4, 5):
                return {"Playing": False}
            return {
                "Playing": True,
                "Paused": playback["playback_status"] == 5,
                "Artist": media["artist"],
                "Title": media["title"],
                "Position": int(position.total_seconds()),
                "Length": int(timeline["end_time"].total_seconds()),
            }
        return {"Playing": False}

    async def go_to_previous() -> None:
        """Jumps to the previous track."""
        sessions = await MediaManager.request_async()
        session = sessions.get_current_session()
        if session:
            await session.try_skip_previous_async()

    async def toggle_play_pause() -> None:
        """Plays or pauses the current track."""
        sessions = await MediaManager.request_async()
        session = sessions.get_current_session()
        if session:
            await session.try_toggle_play_pause_async()

    async def go_to_next() -> None:
        """Jumps to the next track."""
        sessions = await MediaManager.request_async()
        session = sessions.get_current_session()
        if session:
            await session.try_skip_next_async()

    async def seek_backward_5sec() -> None:
        """Seeks forward 5 seconds, if available."""
        await relative_seek(datetime.timedelta(seconds=-5))

    async def seek_forward_5sec() -> None:
        """Seeks forward 5 seconds, if available."""
        await relative_seek(datetime.timedelta(seconds=+5))

    async def relative_seek(delta: datetime.timedelta) -> None:
        """Does relative seeking."""
        sessions = await MediaManager.request_async()
        session = sessions.get_current_session()
        if session:
            timeline = session.get_timeline_properties()
            timeline = {
                attribute: timeline.__getattribute__(attribute)
                for attribute in dir(timeline)
                if attribute[0] != "_"
            }
            now = datetime.datetime.now(datetime.timezone.utc)
            position = now - timeline["last_updated_time"] + timeline["position"]
            position += delta
            ticks = int(position.total_seconds()) * 10000000
            await session.try_change_playback_position_async(ticks)

    def set_console_title(title: str) -> None:
        """Sets the console title of the terminal."""
        ctypes.windll.kernel32.SetConsoleTitleW(title)

# Long lines may occur in the HTML skeleton, this should not be checked by the
# static analysis tool.
# pylint: disable=C0301
BUILTIN_HTML_PAGE = (
    "<!doctype html>\n"
    '\n'
    "  \n"
    '    <meta charset="utf-8" />\n'
    "    <title>mediacontrol Client</title>\n"
    '    <link rel="icon" href="https://fav.farm/ðŸ�°" />\n'
    '    <link rel="preconnect" href="https://fonts.googleapis.com" />\n'
    '    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />\n'
    '    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,700" />\n'
    '    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@1,400;1,700" />\n'
    '    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400" />\n'
    '    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" />\n'
    "    \n"
    "  \n"
    "  \n"
    "    \n"
    '

\n'
    '      0:00\n'
    '      <progress id="progress"></progress>\n'
    '      0:00\n'
    "
\n"
    "      \n"
    '        \n'
    "      \n"
    "      \n"
    '        \n'
    "      \n"
    "      \n"
    '        \n'
    "      \n"
    "      \n"
    '        \n'
    "      \n"
    "      \n"
    '        \n'
    "      \n"
    "      \n'
    '        \n'
    "      \n"
    '
\n'
    "
\n"
    "      \n"
    '        Lyrics are ripped from AZLyrics.\n'
    "        The website uses the\n"
    '        Montserrat\n'
    "        and\n"
    '        Roboto Mono\n'
    "        fonts, hosted on\n"
    '        Google Fonts, and the\n'
    '        Font Awesome\n'
    "        font. The interface and backend is provided by the\n"
    "        mediacontrol software. For the best experience, use a\n"
    "        WebKit-based web browser. For private use only.\n"
    "      \n"
    "      \n"
    "    \n"
    "  \n"
    "\n"
)
# pylint: enable=C0301

class MediaQueryHandler(http.server.BaseHTTPRequestHandler):
    """Handler for media queries through HTTP."""

    def _send_status(self, code: int, description: str) -> None:
        head = f"HTTP/1.1 {str(code)} {description}\n".encode("utf-8")
        try:
            self.wfile.write(head)
            self.wfile.write(b"Server: Media Query Service\n")
            self.wfile.write(b"Connection: close\n\n")
        except:
            pass

    def _send_content(self, content: str):
        header = (
            "HTTP/1.1 200 OK\n"
            "Server: Media Query Service\n"
            f"Content-Type: text/html\n"
            f"Content-Length: {len(content)}\n"
            "Connection: close\n"
            "\n"
        )
        try:
            self.wfile.write(header.encode("utf-8"))
            self.wfile.write(content.encode("utf-8"))
        except:
            pass

    # This method name is fixed as it is an overridden callback function.
    # pylint: disable-next=C0103
    def do_HEAD(self) -> None:
        """Handles HEAD requests."""
        self._send_status(404, "Not Found")

    # This method name is fixed as it is an overridden callback function.
    # pylint: disable-next=C0103
    def do_GET(self) -> None:
        """Handles GET requests."""
        if self.server.verbose:
            print(f" --- Incoming request; path='{self.path}'")

        if self.path == "/get":
            content = parse_artist_and_title(asyncio.run(get_current_media_info()))
            if self.server.verbose:
                print(f" --- Fetched current media info; info='{content}'")
            self._send_content(json.dumps(content))
        elif self.path == "/previous":
            asyncio.run(go_to_previous())
            self._send_status(200, "OK")
        elif self.path == "/seekback":
            asyncio.run(seek_backward_5sec())
            self._send_status(200, "OK")
        elif self.path == "/playpause":
            asyncio.run(toggle_play_pause())
            self._send_status(200, "OK")
        elif self.path == "/seekforward":
            asyncio.run(seek_forward_5sec())
            self._send_status(200, "OK")
        elif self.path == "/next":
            asyncio.run(go_to_next())
            self._send_status(200, "OK")
        elif self.path == "/lyrics":
            content = get_lyrics_for_track(
                parse_artist_and_title(asyncio.run(get_current_media_info())),
                self.server.verbose,
            )
            self._send_content(content)
        elif self.path == "/":
            self._send_content(BUILTIN_HTML_PAGE)
        else:
            self._send_status(404, "Not Found")

def main() -> None:
    """Entry point of the program."""
    try:
        program = "mediacontrol"
        description = "server for media control through http"
        parser = argparse.ArgumentParser(description=description, prog=program)
        parser.add_argument(
            "-p",
            "--port",
            type=int,
            default=42069,
            metavar="PORT",
            help="define a custom port number (default is 42069)",
        )
        parser.add_argument(
            "-v",
            "--verbose",
            action="store_true",
            default=False,
            help="verbose mode, debug messages are emitted",
        )

        duck_bw = (
            "                                \n"
            "                                \n"
            "            â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“          \n"
            "          â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“        \n"
            "          â–“â–“â–“â–“â–“â–“  â–’â–’â–“â–“â–“â–“â–‘â–‘â–‘â–‘â–‘â–‘  \n"
            "          â–“â–“â–“â–“â–“â–“    â–“â–“â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘  \n"
            "          â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–‘â–‘â–‘â–‘â–‘â–‘    \n"
            "          â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–’â–’      \n"
            "  â–“â–“â–“â–“      â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–’â–’    \n"
            "  â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–’â–’â–“â–“â–’â–’â–’â–’  \n"
            "  â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–’â–’â–’â–’â–’â–’  \n"
            "  â–’â–’â–“â–“â–“â–“â–’â–’â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–‘â–‘â–’â–’â–’â–’â–’â–’  \n"
            "    â–’â–’â–“â–“â–’â–’â–“â–“â–“â–“â–“â–“â–“â–“â–‘â–‘â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’  \n"
            "    â–’â–’â–’â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’    \n"
            "      â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’      \n"
            "          â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’          \n"
            "                                \n"
            "                                \n"
        )

        duck_color = (
            "\n"
            "            \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[0m\n"
            "          \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[0m\n"
            "          \x1B[33;1mâ–“â–“â–“â–“â–“â–“\x1B[0m  \x1B[37;1mâ–“â–“"
            "\x1B[33;1mâ–“â–“â–“â–“\x1B[33;2mâ–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "          \x1B[33;1mâ–“â–“â–“â–“â–“â–“\x1B[0m    "
            "\x1B[33;1mâ–“â–“\x1B[33;2mâ–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "          \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[33;2mâ–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "          \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[33mâ–’â–’\x1B[0m\n"
            "  \x1B[33;1mâ–“â–“â–“â–“\x1B[0m      \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“"
            "\x1B[33mâ–’â–’\x1B[0m\n"
            "  \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[33mâ–’â–’\x1B[33;1mâ–“â–“"
            "\x1B[33mâ–’â–’â–’â–’\x1B[0m\n"
            "  \x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“\x1B[33mâ–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "  \x1B[33mâ–’â–’\x1B[33;1mâ–“â–“â–“â–“\x1B[33mâ–’â–’\x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“"
            "\x1B[33;2mâ–’â–’\x1B[0m\x1B[33mâ–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "    \x1B[33mâ–’â–’\x1B[33;1mâ–“â–“\x1B[33mâ–’â–’\x1B[33;1mâ–“â–“â–“â–“â–“â–“â–“â–“"
            "\x1B[33;2mâ–’â–’â–’â–’\x1B[0m\x1B[33mâ–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "    \x1B[33mâ–’â–’â–’â–’â–’â–’\x1B[33;2mâ–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m"
            "\x1B[33mâ–’â–’â–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "      \x1B[33mâ–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "          \x1B[33mâ–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’\x1B[0m\n"
            "\n"
        )

        selected_duck = duck_bw
        if "TERM" in os.environ and "color" in os.environ["TERM"]:
            selected_duck = duck_color
        if "WT_SESSION" in os.environ:
            selected_duck = duck_color

        arguments = vars(parser.parse_args())
        set_console_title("mediacontrol Server")
        port = arguments["port"]
        server = http.server.HTTPServer(("", port), MediaQueryHandler)
        server.verbose = arguments["verbose"]
        print(
            selected_duck + " >>> Media control server started! Quack!\n"
            f" >>> Listening on port {port}!"
        )
        server.serve_forever()
    except KeyboardInterrupt:
        print("")
        print(" >>> Goodbye!")

def parse_artist_and_title(state: dict) -> dict:
    """Parses artist and title from the metadata."""
    if not state["Playing"]:
        return state
    if state["Artist"] == "" and "â€¢" in state["Title"]:
        state["Artist"] = state["Title"].split("â€¢")[1].strip()
        state["Title"] = state["Title"].split("â€¢")[0].strip()
    elif state["Artist"] == "" and " - " in state["Title"]:
        state["Artist"] = state["Title"].split(" - ")[0].strip()
        state["Title"] = state["Title"].split(" - ")[1].strip()
    if "," in state["Artist"]:
        state["Artist"] = state["Artist"].split(",")[0]
    if " - " in state["Title"]:
        state["Title"] = state["Title"].split(" - ")[0].strip()
    if state["Artist"].endswith(" - Topic"):
        state["Artist"] = state["Artist"][:-8]
    return state

def get_lyrics_for_track(state: dict, verbose: bool) -> str:
    """Retrieves the lyrics of a song from AZLyrics."""

    def replace_known_artist(field: str) -> str:
        """Replaces known artists."""
        known = {
            "ELO": "Electric Light Orchestra",
            "Jimi Hendrix Experience": "Jimi Hendrix",
        }
        return known[field] if field in known else field

    def replace_known_title(field: str) -> str:
        """Replaces known titles."""
        known = {
            "B********": "BÃ¼ckstabÃ¼",
            "Why Don't You Do Right": "Why Don't You Do Right (Get Me Some Money Too)",
            "I-E-A-I-E-I-O": "I-E-A-I-A-I-O",
            "Foxy Lady": "Foxey Lady",
        }
        return known[field] if field in known else field

    def filter_special(field: str) -> str:
        """Filters special characters from a string."""
        specials = "/'\" (),.?!-_Ã¤Ã¡Ã«Ã©Ã³Ã¶Å‘ÃºÃ¼Å±ÃŸ[*]"
        return "".join(c for c in field if c not in specials).lower()

    try:
        artist = state["Artist"]
        title = state["Title"]
        if artist.startswith("The "):
            artist = artist[4:]
        artist = filter_special(replace_known_artist(unidecode.unidecode(artist)))
        title = filter_special(replace_known_title(title))
        url = f"http://www.azlyrics.com/lyrics/{str(artist)}/{str(title)}.html"
        if verbose:
            print(
                f" --- Fetching lyrics for current track; "
                f"artist='{state['Artist']}' "
                f"title='{state['Title']}' "
                f"url='{url}' "
            )
        with urllib.request.urlopen(url) as page:
            content = page.read().decode("utf-8")
        content = content[content.find("
\r\n") + 3 :]
        content = content[: content.find("
")]
        return content
    except:
        if verbose:
            print(f" --- Failed to fetch lyrics for current track; url='{url}'")
        return "Lyrics are unavailable for this track."

if __name__ == "__main__":
    main()


# Definition for singly-linked list:
# class ListNode(object):
#   def __init__(self, x):
#     self.value = x
#     self.next = None
#

# Note: Your solution should have O(n) time complexity,
# where n is the number of element in l,
# and O(1) additional space complexity.

def reverse(l,k):
    # size test
    p = l
    s = 1
    while s < k:
        if p.next == None:
            return l, p
        s += 1
        p = p.next
    pointer = l
    front = l
    c = 1
    while c < k:
        c += 1
        n = pointer.next
        nn = n.next
        pointer.next = nn
        n.next = front
        front = n
    return front, pointer # returns head and tail
def reverseNodesInKGroups(l, k):
    pointer = l
    c = 0
    finalHead = l
    prevTail = None
    while pointer != None and pointer.next != None:
        head, tail = reverse(pointer,k)
        pointer = tail
        if prevTail == None:
            finalHead = head
            prevTail = tail
        else:
            prevTail.next = head
            prevTail = tail
        pointer = pointer.next
    return finalHead


#!/usr/bin/python3
"""Module to claculate the perimeter of the island described in grid"""

def island_perimeter(grid):
    """method to calculate the perimeter of grid"""
    perimeter = 2
    for y in range(len(grid)):
        for x in range(len(grid[y])):
            if grid[y][x] == 1:
                    perimeter += 2
    return perimeter


def freeRange(rowID, csvDict):
    if not rowID:
        return None
    index = int(rowID)
    # if the given lot is not in the randomized set, step backwards to find
    # the first extant lot in this range
    # if it's more than 8 lots before we find one then this lot doesn't exist
    # here, it's in ItemLotParam_enemy
    # testing shows that there are two specific lots, 449020002 and 449020012
    # that are the non-hostile large Living Jars in Jarburg that are always
    # handled in ItemLotParam_enemy, and every time I ran it no more than one
    # other random lot ended up handled this way.  considering the number of
    # lots available, I don't see a need to do a completely separate set of CSV
    # handling code just for a bare few lots, two of which are basically NPCs
    # that can break Jar-Bairn's quest so for now any lots not in
    # ItemLotParam_map gets treated as an unavailable lot.
    searched = 0
    while searched < 9 and index > 0 and str(index) not in csvDict:
        searched += 1
        index -= 1
    if searched >= 9:
        return None
    # if this CSV has a lot flag column (itemLotParam_*), make sure we have a
    # nonzero lot flag
    lotFlag = None
    if "getItemFlagId" in csvDict[str(index)]:
        # if the lot flag is 0 (random drops), then walk back through the
        # connected lots until we hit an entry with one
        lotFlag = csvDict[str(index)]["getItemFlagId"]
        # this loop doesn't seem to fail with an empty row lookup, so for now
        # we'll leave it like this, but there probably should be some checking
        # here
        while lotFlag == "0":
            index -= 1
            lotFlag = csvDict[str(index)]["getItemFlagId"]
    # step forward through the connected lots until we find a free space
    while str(index) in csvDict:
        # if it's a shop lot and there's a visibility flag, save it
        if "eventFlag_forRelease" in csvDict[str(index)] and \
                csvDict[str(index)]["eventFlag_forRelease"] != 0:
            lotFlag = csvDict[str(index)]["eventFlag_forRelease"]
        index += 1
    firstID = index
    # step through spaces until we hit another lot or get ten free spaces
    # upping this to 20 to allow for bigger lot ranges
    while str(index) not in csvDict and index < firstID + 21:
        index += 1
    # we want to make sure we don't use the space just before the next lot so
    # that we don't connect lots together and get erroneous pickups
    lastID = index - 2
    if lastID < firstID:
        return None
    returnDict = {
        "freeLotID": str(firstID),
        "freeLotLength": str(lastID - firstID + 1),
    }
    if lotFlag:
        returnDict["lotFlag"] = lotFlag
    return returnDict


import os
from lxml import objectify

from openlp.core.ui.wizard import WizardStrings
from .songimport import SongImport

class PowerPraiseImport(SongImport):
    """
    The :class:`PowerpraiseImport` class provides OpenLP with the
    ability to import Powerpraise song files.
    """
    def do_import(self):
        self.import_wizard.progress_bar.setMaximum(len(self.import_source))
        for file_path in self.import_source:
            if self.stop_import_flag:
                return
            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
            root = objectify.parse(open(file_path, 'rb')).getroot()
            self.process_song(root)

    def process_song(self, root):
        self.set_defaults()
        self.title = str(root.general.title)
        verse_order_list = []
        verse_count = {}
        for item in root.order.item:
            verse_order_list.append(str(item))
        for part in root.songtext.part:
            original_verse_def = part.get('caption')
            # There are some predefined verse defitions in PowerPraise, try to parse these
            if original_verse_def.startswith("Strophe") or original_verse_def.startswith("Teil"):
                verse_def = 'v'
            elif original_verse_def.startswith("Refrain"):
                verse_def = 'c'
            elif original_verse_def.startswith("Bridge"):
                verse_def = 'b'
            elif original_verse_def.startswith("Schluss"):
                verse_def = 'e'
            else:
                verse_def = 'o'
            verse_count[verse_def] = verse_count.get(verse_def, 0) + 1
            verse_def = '%s%d' % (verse_def, verse_count[verse_def])
            verse_text = []
            for slide in part.slide:
                if not hasattr(slide, 'line'):
                    continue  # No content
                for line in slide.line:
                    verse_text.append(str(line))
            self.add_verse('\n'.join(verse_text), verse_def)
            # Update verse name in verse order list
            for i in range(len(verse_order_list)):
                if verse_order_list[i].lower() == original_verse_def.lower():
                    verse_order_list[i] = verse_def

        self.verse_order_list = verse_order_list
        if not self.finish():
            self.log_error(self.import_source)


class Solution:
    def findRedundantConnection(self, edges):
        """
        :type edges: List[List[int]]
        :rtype: List[int]
        """
        N = len(edges)
        cc = dict()  # connected components
        for i in range(N):
            cc[i + 1] = {i + 1}

        for u, v in edges:
            if cc[u] == cc[v]:
                return [u, v]
            update = cc[u] | cc[v]
            for w in update:
                cc[w] = update

fn = Solution().findRedundantConnection

print(fn([[1, 2], [1, 3], [2, 3]]))
print(fn([[1, 2], [2, 3], [3, 4], [1, 4], [1, 5]]))


"""
Check whether the primer sequences are in the sequenes.
"""

import logging
import re

# pylint: disable=C0103
# Invalid constant name
logger = logging.getLogger('pipe.primer')

def primer(configs, seqs):
    """Primer check.

    Check whether any of the primer sequences appear in the contig. The primer
    sequences are defined in Primer -> primers options.
    """
    # Logging
    logger.info('Checking primers')

    # Forward
    primers_fwd = re.split(';\n?', configs['primers'])

    # Reverse complement (translate then reverse the order)
    table = str.maketrans('ATGC', 'TACG')
    primers_rev = [p.translate(table)[::-1] for p in primers_fwd]

    # All the primer sequences
    primers = primers_fwd + primers_rev

    # Query data dict (qseqid -> SeqRecord)
    qry = seqs.qry

    # Search primer sequences in all contigs
    for qseqid in qry:
        primers_found = []
        for p in primers:
            indx = qry[qseqid].seq.find(p)
            if indx != -1:
                primers_found.append("{}({})".format(p, indx+1))

        if primers_found:
            seqs.call[qseqid]['primer'] = "Yes"
        else:
            seqs.call[qseqid]['primer'] = "No"

        seqs.info[qseqid]['primer'] = primers_found

    with open(configs['file_out'], 'w') as fh_o:
        # Header
        print("Contig ID\tSequence\tPrimer", file=fh_o)

        for qid in seqs.qids:
            print("{}\t{}\t{}".format(qid,
                                      ";".join(seqs.info[qid]['primer']),
                                      seqs.call[qid]['primer']),
                  file=fh_o)


##############################################################################
# The program do not nothing special, only show moving square
##############################################################################
import tkinter,random

#init
##########################################
width,height = 400,400
canvas = tkinter.Canvas(width=width, height=height)
canvas.pack()

#make square
##########################################
def square_move():
    if status == "on":
        global direction
        x1,y1,x2,y2 = canvas.coords(square)
        if y1 <= 0:
            direction = 1
        elif y1+ (size) >= height:
            direction = -1
        canvas.move(square, 0,direction*5)
    canvas.after(10, square_move)

def square_color():
    if status == "on":
        color = "#{:06x}".format(random.randrange(256**3))
        canvas.itemconfig(square,fill = color)
    canvas.after(500,square_color)

direction= 1
size=30
x1,y1= width/2-(size/2),height/2-(size/2)
x2,y2 = width/2+(size/2),height/2+(size/2)

square = canvas.create_rectangle(x1,y1,x2,y2,width=0,fill= "black")

#action on click
##########################################
status = "off"
def B1_press(event):
    global status
    if status == "off":
        status = "on"
    else:
        status = "off"

#action
##########################################
square_color()
square_move()
canvas.bind('<ButtonPress-1>', B1_press)

canvas.mainloop()


#Escreva um algoritmo que leia dois números e imprima o resultado da divisão do primeiro pelo
#segundo. Caso não for possível, mostre a mensagem “DIVISAO IMPOSSIVEL”.

n = int(input("Quantos casos você vai digitar? "))
for i in range (n):
    x = int(input("Entre com o numerador: "))
    y = int(input("Entre com o denominador: "))
    resultado = 0
    if y == 0:
        print("DIVISÃO IMPOSSIVEL")
    else:
        resultado = x / y
        print(f"DIVISÃO: {resultado:.2f}")


from linked_list.linked_list import LinkedList
def kthFromEnd(self,k):
    """
    This method return the node’s value that is k places from the tail of the linked list.
    argument: a number, k, as a parameter.

    """
    current =self.head
    length = 1
    while current.next:
        length += 1
        current = current.next
    current = self.head
    if k < 0:
        raise Exception("k must be non-negative number")
    elif k >= length:
        raise Exception('Index out of range')
    value = length-k-1
    for i in range(length):
        if i == value:
            result=current.value
            return result
        current = current.next

LinkedList.kthFromEnd=kthFromEnd
if __name__ =="__main__":
    print("razzan")
    ll =LinkedList()
    ll2 =LinkedList()
    ll.append(1)
    ll.append(3)
    ll.append(5)
    ll.append(7)
    print(ll.__str__())
    x=ll.kthFromEnd(0)
    print(x)
    ll2.insert(2)
    ll2.insert(4)
    ll2.insert(6)
    ll2.insert(8)
    ll2.insert(10)
    ll2.insert(12)


import random

# CORES
red = '\033[1:31m'
green = '\033[1:32m'
blue = '\033[1:34m'
gray = '\033[1:37m'
cls = '\033[m'
yellow = '\033[1m'
yellow = '\033[93m'

def vencer_jogo():
    global game
    global m_escondida

    w = 0
    e = 0
    while w < 10:
        while e < 10:
            if m_escondida[w][e] != 'M':
                game[w + 1][e + 1] = m_escondida[w][e]
            e += 1
        e = 0
        w += 1

def checar(x, z):
    global game
    global m_escondida

    if m_escondida[x][z] != 'M' and game[x + 1][z + 1] == '#':
        if m_escondida[x][z] != '.':
            game[x + 1][z + 1] = m_escondida[x][z]
        else:
            game[x + 1][z + 1] = m_escondida[x][z]
            abrir_mesa(x, z)

def abrir_mesa(t, y):
    global game
    global m_escondida

    if t - 1 > -1:
        if y - 1 > -1:
            checar((t - 1), (y - 1))
        if y + 1 < 10:
            checar((t - 1), (y + 1))
        checar((t - 1), y)

    if y - 1 > -1:
        checar(t, (y - 1))
    if y + 1 < 10:
        checar(t, (y + 1))

    if t + 1 < 10:
        if y - 1 > -1:
            checar((t + 1), (y - 1))
        if y + 1 < 10:
            checar((t + 1), (y + 1))
        checar((t + 1), y)

game = [0, '#', '#', '#', '#', '#', '#', '#', '#', '#', '#']
m_escondida = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

t = 0

while t < 11:
    if t == 0:
        game[t] = [red, '   ', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    else:
        if t != 10:
            game[t] = [blue, str(t) + '  ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#']
        else:
            game[t] = [blue, str(t) + ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#']
    t += 1

t = 0
while t < 10:
    m_escondida[t] = ['!', '!', '!', '!', '!', '!', '!', '!', '!', '!']
    t += 1

t = 0
while t < 11:
    if t == 0:
        print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
              game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
        print()
    else:
        print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
              game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
    t += 1

print()
jogada_escolhida = input("Ponha as coordenadas separadas por Coluna:linha ")
print()

player_coordenadas = jogada_escolhida.split(':')
player_coordenadas[0] = int(player_coordenadas[0]) - 1
player_coordenadas[1] = int(player_coordenadas[1]) - 1

m_escondida[player_coordenadas[0]][player_coordenadas[1]] = '.'

# makes sure no minas around first pick

if player_coordenadas[0] - 1 > -1:
    if player_coordenadas[1] - 1 > -1:
        m_escondida[player_coordenadas[0] - 1][player_coordenadas[1] - 1] = 'c'
    m_escondida[player_coordenadas[0] - 1][player_coordenadas[1]] = 'c'
    if player_coordenadas[1] + 1 < 10:
        m_escondida[player_coordenadas[0] - 1][player_coordenadas[1] + 1] = 'c'

if player_coordenadas[1] - 1 > -1:
    m_escondida[player_coordenadas[0]][player_coordenadas[1] - 1] = 'c'
if player_coordenadas[1] + 1 < 10:
    m_escondida[player_coordenadas[0]][player_coordenadas[1] + 1] = 'c'

if player_coordenadas[0] + 1 < 10:
    if player_coordenadas[1] - 1 > -1:
        m_escondida[player_coordenadas[0] + 1][player_coordenadas[1] - 1] = 'c'
    m_escondida[player_coordenadas[0] + 1][player_coordenadas[1]] = 'c'
    if player_coordenadas[1] + 1 < 10:
        m_escondida[player_coordenadas[0] + 1][player_coordenadas[1] + 1] = 'c'

t = random.randint(0, 9)
y = random.randint(0, 9)

minas = 10  # when this changes change the other one too

while minas != 0:
    if (m_escondida[t][y] != '.') and (m_escondida[t][y] != 'M') and (m_escondida[t][y] != 'c'):
        m_escondida[t][y] = 'M'
        minas -= 1
    t = random.randint(0, 9)
    y = random.randint(0, 9)

minas = 10  # resets it for later use. change the one above too

# makes every none mine space except first point a point for number insrt algorithm to check
t = 0
y = 0
while t < 10:
    while y < 10:
        if (m_escondida[t][y] != '.') and (m_escondida[t][y] != 'M') and (m_escondida[t][y] != 'c'):
            m_escondida[t][y] = 'c'
        y += 1
    t += 1
    y = 0

# number insert algorithm for m_escondida board
t = 0
y = 0
mina_contador = 0
while t < 10:
    while y < 10:
        if (m_escondida[t][y] == 'c'):
            if t - 1 > -1:
                if y - 1 > -1:
                    if m_escondida[t - 1][y - 1] == 'M':
                        mina_contador += 1
                if y + 1 < 10:
                    if m_escondida[t - 1][y + 1] == 'M':
                        mina_contador += 1
                if m_escondida[t - 1][y] == 'M':
                    mina_contador += 1

            if y - 1 > -1:
                if m_escondida[t][y - 1] == 'M':
                    mina_contador += 1
            if y + 1 < 10:
                if m_escondida[t][y + 1] == 'M':
                    mina_contador += 1

            if t + 1 < 10:
                if y - 1 > -1:
                    if m_escondida[t + 1][y - 1] == 'M':
                        mina_contador += 1
                if y + 1 < 10:
                    if m_escondida[t + 1][y + 1] == 'M':
                        mina_contador += 1
                if m_escondida[t + 1][y] == 'M':
                    mina_contador += 1

            if mina_contador == 0:
                m_escondida[t][y] = '.'
            else:
                m_escondida[t][y] = mina_contador
                mina_contador = 0

        y += 1
    t += 1
    y = 0

# starting the game
abrir_mesa(player_coordenadas[0], player_coordenadas[1])

t = 0
while t < 11:
    if t == 0:
        print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
              game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
        print()
    else:
        print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
              game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
    t += 1

# playing the game
jogo = True
win = False

while jogo:
    print()
    jogada_escolhida = input("Ponha as coordenadas separadas C : L")
    print()

    if jogada_escolhida == 'kabum':
        t = 0
        while t < 10:
            print(m_escondida[t][0], ' ', m_escondida[t][1], ' ', m_escondida[t][2], ' ', m_escondida[t][3], ' ', m_escondida[t][4], ' ',
                  m_escondida[t][5], ' ', m_escondida[t][6], ' ', m_escondida[t][7], ' ', m_escondida[t][8], ' ', m_escondida[t][9])
            t += 1
        jogada_escolhida = input("Ponha as coordenadas separadas por :")
    elif jogada_escolhida == 'I am a total piece of shit, gg I win':
        jogada_escolhida = input("Você ganha no proximo acerto!")
        vencer_jogo()

    player_coordenadas = jogada_escolhida.split(':')
    player_coordenadas[0] = int(player_coordenadas[0]) - 1
    player_coordenadas[1] = int(player_coordenadas[1]) - 1

    if m_escondida[player_coordenadas[0]][player_coordenadas[1]] == 'M':
        jogo = False
        game[player_coordenadas[0] + 1][player_coordenadas[1] + 1] = m_escondida[player_coordenadas[0]][player_coordenadas[1]]
    elif m_escondida[player_coordenadas[0]][player_coordenadas[1]] == '.':
        game[player_coordenadas[0] + 1][player_coordenadas[1] + 1] = m_escondida[player_coordenadas[0]][player_coordenadas[1]]
        abrir_mesa(player_coordenadas[0], player_coordenadas[1])
    else:
        game[player_coordenadas[0] + 1][player_coordenadas[1] + 1] = m_escondida[player_coordenadas[0]][player_coordenadas[1]]

    t = 0
    while t < 11:
        if t == 0:
            print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
                  game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
            print()
        else:
            print(game[t][0], ' ', game[t][1], ' ', game[t][2], ' ', game[t][3], ' ', game[t][4], ' ', game[t][5], ' ',
                  game[t][6], ' ', game[t][7], ' ', game[t][8], ' ', game[t][9], ' ', game[t][10])
        t += 1

    print()

    NumberOSpaces = 0
    x = 1
    p = 1
    while x < 11:
        while p < 11:
            if game[x][p] == '#':
                NumberOSpaces += 1
            p += 1
        p = 1
        x += 1

    if NumberOSpaces == minas:
        win = True
        jogo = False

if win == True:
    print("\n\n\nVocê ganhou, parabéns, você é especial!")
else:
    print("\n\n\nVocê perdeu, era uma mina.")

print()
print()
input()


import torch
import numpy as np
import pandas as pd
import sacred
from datetime import datetime
import h5py
import feature.util as util

dataset_ex = sacred.Experiment("dataset")

@dataset_ex.config
def config():
    # Path to reference genome FASTA
    reference_fasta = "/users/amtseng/genomes/hg38.fasta"

    # Path to chromosome sizes
    chrom_sizes_tsv = "/users/amtseng/genomes/hg38.canon.chrom.sizes"

    # The size of DNA sequences to fetch as input sequences
    input_length = 1346

    # The size of profiles to fetch for each coordinate
    profile_length = 1000

    # One-hot encoding has this depth
    input_depth = 4

    # Whether or not to perform reverse complement augmentation
    revcomp = True

    # Maximum size of jitter to the input for augmentation; set to 0 to disable
    jitter_size = 128

    # Batch size; will be multiplied by two if reverse complementation is done
    batch_size = 64

    # Sample X negatives randomly from the genome for every positive example
    negative_ratio = 1

    # Use this stride when tiling coordinates across a peak
    peak_tiling_stride = 25

    # Amount of dataset for each task to keep; can be a set number of peaks, or
    # a fraction (if < 1); set to None to keep everything
    peak_retention = None

    # Number of workers for the data loader
    num_workers = 10

    # Negative seed (for selecting negatives)
    negative_seed = None

    # Jitter seed (for applying random jitter to peaks)
    jitter_seed = None

    # Shuffle seed (for shuffling data points)
    shuffle_seed = None

class GenomeIntervalSampler:
    """
    Samples a random interval from the genome. The sampling is performed
    uniformly at random (i.e. longer chromosomes are more likely to be sampled
    from).
    Arguments:
        `chrom_sizes_tsv`: path to 2-column TSV listing sizes of each chromosome
        `sample_length`: length of sampled sequence
        `chroms_keep`: an iterable of chromosomes that specifies which
            chromosomes to keep from the sizes; sampling will only occur from
            these chromosomes
    """
    def __init__(
        self, chrom_sizes_tsv, sample_length, chroms_keep=None, seed=None
    ):
        self.sample_length = sample_length

        # Create DataFrame of chromosome sizes
        chrom_table = self._import_chrom_sizes(chrom_sizes_tsv)
        if chroms_keep:
            chrom_table = chrom_table[chrom_table["chrom"].isin(chroms_keep)]
        # Cut off sizes to avoid overrunning ends of chromosome
        chrom_table["max_size"] -= sample_length
        chrom_table["weight"] = \
            chrom_table["max_size"] / chrom_table["max_size"].sum()
        self.chrom_table = chrom_table

        self.rng = np.random.RandomState(seed)

    def _import_chrom_sizes(self, chrom_sizes_tsv):
        """
        Imports a TSV of chromosome sizes, mapping chromosome to maximum size.
        Arguments:
            `chrom_sizes_tsv`: a 2-column TSV mapping chromosome name to size
        Returns a Pandas DataFrame
        """
        return pd.read_csv(
            chrom_sizes_tsv, sep="\t", header=None, names=["chrom", "max_size"]
        )

    def sample_intervals(self, num_intervals):
        """
        Returns a 2D NumPy array of randomly sampled coordinates. Returns
        `num_intervals` intervals, uniformly randomly sampled from the genome.
        """
        chrom_sample = self.chrom_table.sample(
            n=num_intervals,
            replace=True,
            weights=self.chrom_table["weight"],
            random_state=self.rng
        )
        chrom_sample["start"] = (
            self.rng.rand(num_intervals) * chrom_sample["max_size"]
        ).astype(int)
        chrom_sample["end"] = chrom_sample["start"] + self.sample_length

        return chrom_sample[["chrom", "start", "end"]].values.astype(object)

class CoordsToVals:
    """
    From an HDF5 file that maps genomic coordinates to profiles, this creates an
    object that maps a list of coordinates to a NumPy array of profiles.
    Arguments:
        `hdf5_path`: path to HDF5 containing profiles; this HDF5 must have a
            separate dataset for each chromosome, and it is expected to return
            profiles of shape O x P x S, where O is the profile size, P is the
            number of profile tracks, and S is for the strands in each track
        `profile_size`: for each genomic coordinate, center it and pad it on
            both sides to this length to get the final profile; if this is
            smaller than the coordinate interval given, then the interval will
            be cut to this size by centering
    """
    def __init__(self, hdf5_path, profile_size):
        self.hdf5_path = hdf5_path
        self.profile_size = profile_size

    def _resize_interval(start, end, size):
        """
        Resizes the interval by centering and trimming/padding to the given
        size.
        """
        center = int(0.5 * (start + end))
        half_size = int(0.5 * size)
        left = center - half_size
        right = left + size
        return left, right

    def _get_profile(self, chrom, start, end, hdf5_reader):
        """
        Fetches the profile for the given coordinates, with an instantiated
        HDF5 reader. Returns the profile as a NumPy array of numbers. This may
        pad or cut from the center to a specified length.
        """
        if self.profile_size:
            start, end = CoordsToVals._resize_interval(
                start, end, self.profile_size
            )
        return hdf5_reader[chrom][start:end]

    def _get_ndarray(self, coords):
        """
        From an iterable of coordinates, retrieves a values for that coordinate.
        This will be a 4D NumPy array of corresponding profile values.
        Note that all coordinate intervals need to be of the same length (after
        padding).
        """
        with h5py.File(self.hdf5_path, "r") as reader:
            profiles = np.stack([
                self._get_profile(chrom, start, end, reader) \
                for chrom, start, end in coords
            ])
        return profiles

    def __call__(self, coords):
        return self._get_ndarray(coords)

class SamplingCoordsBatcher(torch.utils.data.sampler.Sampler):
    """
    Creates a batch producer that batches positive coordinates and samples
    negative coordinates. Each batch will have some positives and negatives
    according to `neg_ratio`. When multiple sets of positive coordinates are
    given, the coordinates are all pooled together and drawn from uniformly.
    Arguments:
        `pos_coords_beds`: list of paths to gzipped BED files containing the
            sets of positive coordinates for various tasks; these BED files
            should be in ENCODE NarrowPeak format
        `batch_size`: number of samples per batch
        `neg_ratio`: number of negatives to select for each positive example
        `jitter`: maximum random amount to jitter each positive coordinate
            example by
        `chrom_sizes_tsv`: path to 2-column TSV listing sizes of each chromosome
        `sample_length`: length of sampled sequence
        `genome_sampler`: a GenomeIntervalSampler instance, which samples
            intervals randomly from the genome
        `chroms_keep`: if specified, only considers this set of chromosomes from
            the coordinate BEDs
        `peak_retention`: if specified, keeps only this amount of peaks (taking
            most confident peaks preferentially); can be a fraction of the
            original BED file (if value is < 1), or a number of peaks (if value
            is >= 1)
        `return_peaks`: if True, returns the peaks and summits sampled from the
            peak set as a B x 3 array
        `shuffle_before_epoch`: Whether or not to shuffle all examples before
            each epoch
    """
    def __init__(
        self, pos_coords_beds, batch_size, neg_ratio, jitter, chrom_sizes_tsv,
        sample_length, genome_sampler, chroms_keep=None, peak_retention=None,
        return_peaks=False, shuffle_before_epoch=False, jitter_seed=None,
        shuffle_seed=None
    ):
        self.batch_size = batch_size
        self.neg_ratio = neg_ratio
        self.jitter = jitter
        self.genome_sampler = genome_sampler
        self.return_peaks = return_peaks
        self.shuffle_before_epoch = shuffle_before_epoch

        chrom_sizes_table = self._import_chrom_sizes(chrom_sizes_tsv)

        all_pos_table = []
        for i, pos_coords_bed in enumerate(pos_coords_beds):
            peaks_table = self._import_peaks(pos_coords_bed)
            coords = self._format_peaks_table(
                peaks_table, chroms_keep, peak_retention, sample_length, jitter,
                chrom_sizes_table
            )

            # Add in the status column
            coords = np.concatenate(
                [coords, np.tile(i + 1, (len(coords), 1))], axis=1
            )  # Shape: _ x 7

            all_pos_table.append(coords)

        self.all_pos_table = np.concatenate(all_pos_table)  # Shape: N x 7
        self.num_total_pos = len(self.all_pos_table)

        # Number of positives and negatives per batch
        self.neg_per_batch = int(batch_size * neg_ratio / (neg_ratio + 1))
        self.pos_per_batch = batch_size - self.neg_per_batch

        if shuffle_before_epoch:
            self.shuffle_rng = np.random.RandomState(shuffle_seed)

        if self.jitter:
            self.jitter_rng = np.random.RandomState(jitter_seed)

    def _import_peaks(self, peaks_bed):
        """
        Imports a peaks BED file in NarrowPeak format as a Pandas DataFrame.
        Arguments:
            `peaks_bed`: a BED file (gzipped or not) containing peaks in
                ENCODE NarrowPeak format
        Returns a Pandas DataFrame
        """
        return pd.read_csv(
            peaks_bed, sep="\t", header=None,  # Infer compression
            names=[
                "chrom", "peak_start", "peak_end", "name", "score",
                "strand", "signal", "pval", "qval", "summit_offset"
            ]
        )

    def _import_chrom_sizes(self, chrom_sizes_tsv):
        """
        Imports a TSV of chromosome sizes, mapping chromosome to maximum size.
        Arguments:
            `chrom_sizes_tsv`: a 2-column TSV mapping chromosome name to size
        Returns a Pandas DataFrame
        """
        return pd.read_csv(
            chrom_sizes_tsv, sep="\t", header=None, names=["chrom", "max_size"]
        )

    def _format_peaks_table(
        self, peaks_table, chroms_keep, peak_retention, sample_length, jitter,
        chrom_sizes_table
    ):
        """
        Takes a table of imported peaks and formats it. This function performs
        the following tasks:
        1. Optionally filters peaks to only retain a subset of chromosomes
        2. Optionally cuts down the set of peaks to a subset of high-confidence
            peaks
        3. Computes the intervals for inputs being centered around the summits
        4. Drops any intervals that would overrun chromosome boundaries
        Arguments:
            `peaks_table`: a table imported by `_import_peaks`
            `chrom_sizes_table`: a table imported by `_import_chrom_sizes`
        Returns an N x 6 array, where columns 1-3 are the coordinate of the
        input samples centered at summits, columns 4-5 are the original peak
        location, and column 6 is the summit location.
        """
        if chroms_keep:
            # Keep only chromosomes specified
            peaks_table = peaks_table[peaks_table["chrom"].isin(chroms_keep)]

        if peak_retention is not None:
            # Sort coordinates by confidence first
            peaks_table = peaks_table.sort_values(by="signal", ascending=False)
            # Keep only a subset of the peaks in the table
            keep_num = int(len(peaks_table) * peak_retention) if \
                peak_retention < 1 else peak_retention
            peaks_table = peaks_table.head(keep_num)

        # Expand the coordinates to be of size `sample_length`, centered
        # around the summits
        peaks_table["start"] = peaks_table["peak_start"] + \
            peaks_table["summit_offset"] - (sample_length // 2)
        peaks_table["end"] = peaks_table["start"] + sample_length

        # Toss out any coordinates that (with jittering) may go past
        # chromosome boundaries
        # Add in the maximum size column
        peaks_table = peaks_table.merge(chrom_sizes_table, on="chrom")
        # Keep only coordinates that won't overrun the ends
        left_mask = peaks_table["start"] - jitter >= 0
        right_mask = peaks_table["end"] + jitter < peaks_table["max_size"]
        peaks_table = peaks_table.loc[left_mask & right_mask]

        # Compute the summit location from offset and peak start
        peaks_table["summit"] = peaks_table["peak_start"] + \
            peaks_table["summit_offset"]

        # Extract the columns desired
        coords = peaks_table[[
            "chrom", "start", "end", "peak_start", "peak_end", "summit"
        ]].values.astype(object)

        return coords

    def __getitem__(self, index):
        """
        Fetches a full batch of positive and negative coordinates by filling the
        batch with some positive coordinates, and sampling randomly from the
        rest of the genome for the negatives. Returns a B x 3 2D NumPy array of
        coordinates, along with a parallel B-array of status. Status is 0
        for negatives, and [1, n] for positives, where the status is 1 plus the
        index of the coordinate BED file it came from.
        This method may also perform jittering for dataset augmentation.
        If `return_peaks` was specified at object creation-time, also return a
        B x 3 2D NumPy array containing the peak information for the original
        peaks, consisting of the peak boundaries and the summit location
        (respectively); for negative samples drawn from the
        GenomeIntervalSampler, these values are all -1.
        """
        pos_table = self.all_pos_table[
            index * self.pos_per_batch : (index + 1) * self.pos_per_batch
        ]
        pos_coords, pos_peaks, pos_statuses = \
            pos_table[:, :3], pos_table[:, 3:6], pos_table[:, 6]

        # If specified, apply random jitter to each positive coordinate
        if self.jitter:
            jitter_vals = self.jitter_rng.randint(
                -self.jitter, self.jitter + 1, size=len(pos_coords)
            )
            pos_coords[:, 1] += jitter_vals
            pos_coords[:, 2] += jitter_vals

        # Fetch the negatives to fill out the batch
        if self.neg_per_batch:
            neg_coords = self.genome_sampler.sample_intervals(
                self.neg_per_batch
            )
        else:
            neg_coords = np.empty(shape=(0, 3), dtype=object)

        # At this point, `pos_coords` and `neg_coords` are both _ x 3
        # Concatenate the coordinates together
        coords = np.concatenate([pos_coords, neg_coords], axis=0)

        # Concatenate the statuses together; status for negatives is just 0
        status = np.concatenate(
            [pos_statuses, np.zeros(len(neg_coords))]  # Col 7
        ).astype(int)

        if self.return_peaks:
            # Concatenate the peaks together; peaks for negatives is all -1
            neg_peaks = np.full((len(neg_coords), 3), -1)
            peaks = np.concatenate([pos_peaks, neg_peaks])
            return coords, status, peaks
        else:
            return coords, status

    def __len__(self):
        return int(np.ceil(self.num_total_pos / float(self.pos_per_batch)))

    def on_epoch_start(self):
        if self.shuffle_before_epoch:
            perm = self.shuffle_rng.permutation(self.num_total_pos)
            self.all_pos_table = self.all_pos_table[perm]

class SummitCenteringCoordsBatcher(SamplingCoordsBatcher):
    """
    Creates a batch producer that batches positive coordinates only, each one
    centered at a summit.
    Arguments:
        `pos_coords_beds`: list of paths to gzipped BED files containing the
            sets of positive coordinates for various tasks
        `batch_size`: number of samples per batch
        `chroms_keep`: if specified, only considers this set of chromosomes from
            the coordinate BEDs
        `chrom_sizes_tsv`: path to 2-column TSV listing sizes of each chromosome
        `sample_length`: length of sampled sequence
        `return_peaks`: if True, returns the peaks and summits sampled from the
            peak set as a B x 3 array
        `shuffle_before_epoch`: Whether or not to shuffle all examples before
            each epoch
    """
    def __init__(
        self, pos_coords_beds, batch_size, chrom_sizes_tsv, sample_length,
        chroms_keep=None, return_peaks=False, shuffle_before_epoch=False,
        shuffle_seed=None
    ):
        # Same as a normal SamplingCoordsBatcher, but with no negatives and no
        # jitter, since the coordinates in the positive coordinate BEDs are
        # already centered at the summits
        super().__init__(
            pos_coords_beds=pos_coords_beds,
            batch_size=batch_size,
            neg_ratio=0,
            jitter=0,
            chrom_sizes_tsv=chrom_sizes_tsv,
            sample_length=sample_length,
            genome_sampler=None,
            chroms_keep=chroms_keep,
            return_peaks=return_peaks,
            shuffle_before_epoch=shuffle_before_epoch,
            shuffle_seed=shuffle_seed
        )

class PeakTilingCoordsBatcher(SamplingCoordsBatcher):
    """
    Creates a batch producer that batches positive coordinates only, where the
    coordinates are tiled such that all coordinate centers overlap with a peak.
    Arguments:
        `pos_coords_beds`: list of paths to gzipped BED files containing the
            sets of positive coordinates for various tasks
        `stride`: amount of stride when tiling the coordinates
        `batch_size`: number of samples per batch
        `chrom_sizes_tsv`: path to 2-column TSV listing sizes of each chromosome
        `sample_length`: length of sampled sequence
        `chroms_keep`: if specified, only considers this set of chromosomes from
            the coordinate BEDs
        `return_peaks`: if True, returns the peaks and summits sampled from the
            peak set as a B x 3 array
        `shuffle_before_epoch`: Whether or not to shuffle all examples before
            each epoch
    """
    def __init__(
        self, pos_coords_beds, stride, batch_size, chrom_sizes_tsv,
        sample_length, chroms_keep=None, return_peaks=False,
        shuffle_before_epoch=False, shuffle_seed=None
    ):
        # Similar to normal SamplingCoordsBatcher, but with no negatives and no
        # jitter; initialization is similar, but replicate the peaks so that
        # there are many summits tiled across each peak
        self.batch_size = batch_size
        self.jitter = 0
        self.chroms_keep = chroms_keep
        self.return_peaks = return_peaks
        self.shuffle_before_epoch = shuffle_before_epoch

        chrom_sizes_table = self._import_chrom_sizes(chrom_sizes_tsv)

        def tile_peaks(row):
            peak_start, peak_end = row[1], row[2]
            summit_offsets = np.arange(0, peak_end - peak_start, stride)
            num_expand = len(summit_offsets)
            row_expand = np.tile(row, (num_expand, 1))
            row_expand[:, -1] = summit_offsets
            return row_expand

        all_pos_table = []
        for i, pos_coords_bed in enumerate(pos_coords_beds):
            peaks_table = self._import_peaks(pos_coords_bed)

            # Formatting peaks table will expand the peaks to the right sample
            # length and filter for anything that overruns the chromosome
            # boundaries, so perform replication before
            peaks_values = peaks_table.values
            expanded_peaks_values = np.concatenate([
                tile_peaks(row) for row in peaks_values
            ], axis=0)
            expanded_peaks_table = pd.DataFrame.from_records(
                expanded_peaks_values, columns=list(peaks_table)
            )

            # Now format peaks table into N x 6 array
            coords = self._format_peaks_table(
                expanded_peaks_table, chroms_keep, None, sample_length, 0,
                chrom_sizes_table
            )

            # Add in the status column
            coords = np.concatenate(
                [coords, np.tile(i + 1, (len(coords), 1))], axis=1
            )  # Shape: _ x 7

            all_pos_table.append(coords)

        self.all_pos_table = np.concatenate(all_pos_table)  # Shape: N x 7
        self.num_total_pos = len(self.all_pos_table)

        # Number of positives and negatives per batch
        self.num_coords = len(self.all_pos_table)
        self.neg_per_batch = 0
        self.pos_per_batch = self.batch_size

        if shuffle_before_epoch:
            self.shuffle_rng = np.random.RandomState(shuffle_seed)

class CoordDataset(torch.utils.data.IterableDataset):
    """
    Generates single samples of a one-hot encoded sequence and value.
    Arguments:
        `coords_batcher (CoordsDownsampler): maps indices to batches of
            coordinates (split into positive and negative binding)
        `coords_to_seq (CoordsToSeq)`: maps coordinates to 1-hot encoded
            sequences
        `coords_to_vals (CoordsToVals)`: instantiated CoordsToVals object,
            mapping coordinates to profiles
        `revcomp`: whether or not to perform revcomp to the batch; this will
            double the batch size implicitly
        `return_coords`: if True, along with the 1-hot encoded sequences and
            values, the batch also returns the set of coordinates used for the
            batch, and the peak/summit locations for the positive examples
    """
    def __init__(
        self, coords_batcher, coords_to_seq, coords_to_vals, revcomp=False,
        return_coords=False
    ):
        self.coords_batcher = coords_batcher
        self.coords_to_seq = coords_to_seq
        self.coords_to_vals = coords_to_vals
        self.revcomp = revcomp
        self.return_coords = return_coords

        # The dataset returns coordinates iff the batcher returns peak info
        assert coords_batcher.return_peaks == return_coords

    def get_batch(self, index):
        """
        Returns a batch, which consists of an B x I x 4 NumPy array of 1-hot
        encoded sequence (I is the length of the input sequence), the associated
        profiles, and a 1D length-B NumPy array of statuses. The profiles will
        be a B x P x O x S array of profiles. O is the profile length, P is the
        number of tracks returned, and S is the number of strands per track (1
        or 2). Coordinates and peaks may also be returned as a B x 3 array.
        """
        # Get batch of coordinates for this index
        if self.return_coords:
            coords, status, peaks = self.coords_batcher[index]
        else:
            coords, status = self.coords_batcher[index]

        # Map this batch of coordinates to 1-hot encoded sequences
        seqs = self.coords_to_seq(coords, revcomp=self.revcomp)

        # Map this batch of coordinates to the associated values
        profiles = self.coords_to_vals(coords)

        # Profiles are returned as B x O x P x S, so transpose to get
        # B x P x O x S
        profiles = np.swapaxes(profiles, 1, 2)

        # If reverse complementation was done, double sizes of everything else
        if self.revcomp:
            profiles = np.concatenate(
                # To reverse complement, we must swap the strands AND the
                # directionality of each strand (i.e. we are assigning the other
                # strand to be the plus strand, but still 5' to 3'). If the
                # profiles are unstranded, then flipping the last axis will do
                # nothing
                [profiles, np.flip(profiles, axis=(2, 3))]
            )
            status = np.concatenate([status, status])

        if self.return_coords:
            if self.revcomp:
                coords_ret = np.concatenate([coords, coords])
                peaks_ret = np.concatenate([peaks, peaks])
            else:
                coords_ret, peaks_ret = coords, peaks
            return seqs, profiles, status, coords_ret, peaks_ret
        else:
            return seqs, profiles, status

    def __iter__(self):
        """
        Returns an iterator over the batches. If the dataset iterator is called
        from multiple workers, each worker will be give a shard of the full
        range.
        """
        worker_info = torch.utils.data.get_worker_info()
        num_batches = len(self.coords_batcher)
        if worker_info is None:
            # In single-processing mode
            start, end = 0, num_batches
        else:
            worker_id = worker_info.id
            num_workers = worker_info.num_workers
            shard_size = int(np.ceil(num_batches / num_workers))
            start = shard_size * worker_id
            end = min(start + shard_size, num_batches)
        return (self.get_batch(i) for i in range(start, end))

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

    def on_epoch_start(self):
        """
        This should be called manually before the beginning of every epoch (i.e.
        before the iteration begins).
        """
        self.coords_batcher.on_epoch_start()

@dataset_ex.capture
def create_data_loader(
    peaks_bed_paths, profile_hdf5_path, sampling_type, batch_size,
    reference_fasta, chrom_sizes_tsv, input_length, profile_length,
    negative_ratio, peak_tiling_stride, peak_retention, num_workers, revcomp,
    jitter_size, negative_seed, shuffle_seed, jitter_seed, chrom_set=None,
    shuffle=True, return_coords=False
):
    """
    Creates an IterableDataset object, which iterates through batches of
    coordinates and returns profiles for the coordinates.
    Arguments:
        `peaks_bed_paths`: a list of paths to gzipped 6-column BED files
            containing coordinates of positive-binding coordinates
        `profile_hdf5_path`: path to HDF5 containing reads mapped to each
            coordinate; this HDF5 must be organized by chromosome, with each
            dataset being L x S x 2, where L is the length of the chromosome,
            S is the number of tracks stored, and 2 is for each strand
        `sampling_type`: one of ("SamplingCoordsBatcher",
            "SummitCenteringCoordsBatcher", or "PeakTilingCoordsBatcher"), which
            corresponds to sampling positive and negative regions, taking only
            positive regions centered around summits, and taking only positive
            regions tiled across peaks
        `chrom_set`: a list of chromosomes to restrict to for the positives and
            sampled negatives; defaults to all coordinates in the given BEDs and
            sampling over the entire genome
        `shuffle`: if specified, shuffle the coordinates before each epoch
        `return_coords`: if specified, also return the underlying coordinates
            and peak data along with the profiles in each batch
    """
    assert sampling_type in (
            "SamplingCoordsBatcher", "SummitCenteringCoordsBatcher",
            "PeakTilingCoordsBatcher"
    )

    # Maps set of coordinates to profiles
    coords_to_vals = CoordsToVals(profile_hdf5_path, profile_length)

    if sampling_type == "SamplingCoordsBatcher":
        # Randomly samples from genome
        genome_sampler = GenomeIntervalSampler(
            chrom_sizes_tsv, input_length, chroms_keep=chrom_set,
            seed=negative_seed
        )
        # Yields batches of positive and negative coordinates
        coords_batcher = SamplingCoordsBatcher(
            peaks_bed_paths, batch_size, negative_ratio, jitter_size,
            chrom_sizes_tsv, input_length, genome_sampler,
            chroms_keep=chrom_set, peak_retention=peak_retention,
            return_peaks=return_coords, shuffle_before_epoch=shuffle,
            jitter_seed=jitter_seed, shuffle_seed=shuffle_seed
        )
    elif sampling_type == "SummitCenteringCoordsBatcher":
        # Yields batches of positive coordinates, centered at summits
        coords_batcher = SummitCenteringCoordsBatcher(
            peaks_bed_paths, batch_size, chrom_sizes_tsv, input_length,
            chroms_keep=chrom_set, return_peaks=return_coords,
            shuffle_before_epoch=shuffle, shuffle_seed=shuffle_seed
        )
    else:
        # Yields batches of positive coordinates, tiled across peaks
        coords_batcher = PeakTilingCoordsBatcher(
            peaks_bed_paths, peak_tiling_stride, batch_size, chrom_sizes_tsv,
            input_length, chroms_keep=chrom_set, return_peaks=return_coords,
            shuffle_before_epoch=shuffle, shuffle_seed=shuffle_seed
        )

    # Maps set of coordinates to 1-hot encoding, padded
    coords_to_seq = util.CoordsToSeq(
        reference_fasta, center_size_to_use=input_length
    )

    # Dataset
    dataset = CoordDataset(
        coords_batcher, coords_to_seq, coords_to_vals, revcomp=revcomp,
        return_coords=return_coords
    )

    # Dataset loader: dataset is iterable and already returns batches
    loader = torch.utils.data.DataLoader(
        dataset, batch_size=None, num_workers=num_workers,
        collate_fn=lambda x: x
    )

    return loader

data = None
loader = None
@dataset_ex.automain
def main():
    global data, loader
    import os
    import tqdm
    import json
    import matplotlib.pyplot as plt

    paths_json_path = "/users/amtseng/att_priors/data/processed/ENCODE_TFChIP/profile/config/SPI1/SPI1_training_paths.json"
    with open(paths_json_path, "r") as f:
        paths_json = json.load(f)
    peak_beds = paths_json["peak_beds"]
    profile_hdf5 = paths_json["profile_hdf5"]

    splits_json_path = "/users/amtseng/att_priors/data/processed/chrom_splits.json"
    with open(splits_json_path, "r") as f:
        splits_json = json.load(f)
    train_chroms, val_chroms, test_chroms = \
        splits_json["1"]["train"], splits_json["1"]["val"], \
        splits_json["1"]["test"]

    loader = create_data_loader(
        peak_beds, profile_hdf5, "SamplingCoordsBatcher",
        return_coords=True, chrom_set=val_chroms,
        jitter_size=128, jitter_seed=123, peak_retention=0.1,
        shuffle_seed=123, negative_seed=123
    )
    loader.dataset.on_epoch_start()

    start_time = datetime.now()
    for batch in tqdm.tqdm(loader, total=len(loader.dataset)):
        data = batch
    end_time = datetime.now()
    print("Time: %ds" % (end_time - start_time).seconds)

    k = 2
    rc_k = int(len(data[0]) / 2) + k

    seqs, profiles, statuses, coords, peaks = data

    seq, prof, status = seqs[k], profiles[k], statuses[k]
    rc_seq, rc_prof, rc_status = \
        seqs[rc_k], profiles[rc_k], statuses[rc_k]

    coord, peak = coords[k], peaks[k]
    rc_coord, rc_peak = coords[rc_k], peaks[rc_k]

    def print_one_hot_seq(one_hot):
        s = util.one_hot_to_seq(one_hot)
        print(s[:20] + "..." + s[-20:])

    print_one_hot_seq(seq)
    print_one_hot_seq(rc_seq)

    print(status, rc_status)

    print(coord, rc_coord)
    print(peak, rc_peak)

    task_ind = 0
    num_strands = prof.shape[2]
    fig, ax = plt.subplots(2, 1)
    for i in range(num_strands):
        ax[0].plot(prof[task_ind][:, i])
        ax[1].plot(rc_prof[task_ind][:, i])
    plt.show()


class Solution:

    def longestCommonSubsequence(self, text1: str, text2: str) -> int:

        self.text1 = text1
        self.text2 = text2
        self.len1= len(text1)
        self.len2 =len(text2)
        self.dp = [[None]*(self.len2+1) for _ in range(self.len1+1)]

        for c in range(self.len2+1):
            self.dp[-1][c] = 0

        for r in range(self.len1+1):
            self.dp[r][-1] = 0

        for r in range(self.len1-1,-1,-1):
            for c in range(self.len2-1,-1,-1):
                if self.text1[r] == self.text2[c]:
                    self.dp[r][c] = 1+self.dp[r+1][c+1]
                else:
                    self.dp[r][c] = max(self.dp[r+1][c],self.dp[r][c+1])

        return self.dp[0][0]


import os
from IPython.display import display, Image

root = '../notMNIST_small'
data_folders = [os.path.join(root, d) for d in sorted(os.listdir(root))]
folder = data_folders[0]

# Display 10 images in notebook
for file in os.listdir(folder)[:10]:
    display(Image(filename=os.path.join(folder, file)))


import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm
import pickle
import argparse
import torch.nn.functional as F
from sklearn.model_selection import train_test_split
import numpy as np
import itertools
from base_model import Model

# Take available models, evaluate RMSE on random sample of dataset
# Slow_fusion x [vanilla_rnn lstm lstmn transformer_abs]
def eval(model, data, device):
    criterion = nn.MSELoss()
    rmse = 0
    i = 0
    model.eval()
    with torch.no_grad():
        for ex, rt_score in data:
            i += 1
            out = model(ex.to(device))
            rmse_i = criterion(out.squeeze(), rt_score.to(device))
            rmse += rmse_i.item()

    return (rmse/i) ** 0.5

def eval_model(img_net, seq_net, device, data):
    model = Model(img_net, seq_net).to(device)
    model_name = f"SEQ_{img_net}_IMG_{seq_net}"
    model_path = f"./trained_models_new/{model_name}_checkpoint.pt"
    print("LOADING MODEL")
    model.load_state_dict(torch.load(model_path, map_location=device))
    print("MODEL LOADED - EVAL STARTING")
    return eval(model, data, device)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-d", "--device", type=str, required=True)
    args = parser.parse_args()

    device = torch.device(args.device)

    chunked_data = pickle.load(open("./converter/trailers_chunked.p", "rb"))
    data = pickle.load(open("./converter/trailers_normal.p", "rb"))
    labels = pickle.load(open("./converter/scores.p", "rb"))
    chunked_data, data, labels = list(map(lambda x: torch.from_numpy(x).float(), (chunked_data, data, labels)))

    chunked_data = list(zip(chunked_data, labels))
    data = list(zip(data, labels))

    hold_seq_fixed = "lstm"
    cnn_options = ['early_fusion', 'late_fusion', 'slow_fusion', 'vanilla_cnn']

    results = []

    for cnn in cnn_options:
        chunked_needed = cnn in frozenset(["slow_fusion", "early_fusion", "late_fusion"])
        res = eval_model(cnn, hold_seq_fixed, device, chunked_data if chunked_needed else data)
        results.append(((cnn, hold_seq_fixed), res))

    cnn_f = "slow_fusion"
    seq_v = ["vanilla_rnn", "lstm", "lstmn", "transformer_abs", "lstm_stack"]
    for seq in seq_v:
        chunked_needed = cnn_f in frozenset(["slow_fusion", "early_fusion", "late_fusion"])
        res = eval_model(cnn_f, seq, device, chunked_data if chunked_needed else data)
        results.append(((cnn_f, seq), res))

    pickle.dump(results, open(f"./results.p", "wb"))

if __name__ == "__main__" : main()


#!/usr/bin/python

import sys
import config
import os.path
import dependency
from optparse import OptionParser

def run(files):
    for input_filename in files:
        f = config.get_current_file(input_filename, '.pre')
        if os.path.isfile(f):
            os.remove(f)

        f = config.get_current_file(input_filename, '.norm')
        if os.path.isfile(f):
            os.remove(f)

        f = config.get_current_file(input_filename, '.sort')
        if os.path.isfile(f):
            os.remove(f)

        f = config.get_current_file(input_filename, '.pv')
        if os.path.isfile(f):
            os.remove(f)

        f = config.get_current_file(input_filename, '.cat_pv')
        if os.path.isfile(f):
            os.remove(f)

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option('-c', '--column',
        help='Column to sum', type=int, default=4)

    options, arguments = parser.parse_args()

    # Filename on the command line have precedence over configuration
    files = config.input_files
    if arguments:
        files = arguments

    run(files)


import random
import configargparse
import numpy as np
import tensorflow as tf
import os
import logging
import json
import glob
import zipfile

def set_random_seed(args):
    if args.seed == None:
        args.seed = random.randint(0, 2 ** 31 - 1)
    tf.set_random_seed(args.seed)
    np.random.seed(args.seed)
    random.seed(args.seed)
    print("random seed: " + str(args.seed))

def get_var_list(name_list):
    layer_vars = []
    for name in name_list:
        layer_vars.append([var for var in tf.global_variables() if name in var.name])
    layer_vars = [var for layer in layer_vars for var in layer]
    return layer_vars

def initial_logger(args, dump_code=True):
    if not os.path.exists(args.logDir):
        os.makedirs(args.logDir)

    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    fh = logging.FileHandler(args.logDir + r'/training_log.txt')
    fh.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    logger.addHandler(ch)
    logger.addHandler(fh)

    if dump_code:
        logger.info("Dump current source code...")
        current_path = os.path.dirname(os.path.abspath(__file__))
        dump_files = glob.glob(os.path.join(current_path, '*.py'))
        dump_files = dump_files + glob.glob(os.path.join(os.path.join(os.path.dirname(current_path),"preprocess"), '*.py'))
        zf = zipfile.ZipFile(os.path.join(args.logDir, 'source_code.zip'), mode='w')
        try:
            for f in dump_files:
                zf.write(f)
        finally:
            zf.close()

    logger.info('----Settings:-------')
    args_train = vars(args)
    for key in args_train:
        logger.info('---{}:{}----'.format(key, args_train[key]))
    with open(args.logDir + r'/params.json', 'w') as f:
        json.dump(args_train, f)

    return logger

def restore_model(sess, saver, checkpoint, args):
    if checkpoint is not None:
        args.logger.info('Restore {}'.format(checkpoint))
        if args.checkpoint_step is not None:
            ckpt = os.path.join(checkpoint, "%s.tfmodel" % args.checkpoint_step)
        else:
            ckpt = tf.train.latest_checkpoint(checkpoint)
        print('Restore {}.'.format(ckpt))
        saver.restore(sess, ckpt)
        return True
    else:
        args.logger.info('[ERROR] Restore failed {}.'.format(checkpoint))
        return False

## support "--X True/False" in command line
def str2bool(v):
    if isinstance(v, bool):
        return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise configargparse.ArgumentTypeError('Boolean value expected.')


# The following comments couldn't be translated into the new config version:

#! /bin/env cmsRun

import FWCore.ParameterSet.Config as cms

process = cms.Process("validation")
process.load("DQMServices.Components.DQMEnvironment_cfi")

#keep the logging output to a nice level
process.load("FWCore.MessageLogger.MessageLogger_cfi")

process.load("DQMServices.Core.DQM_cfg")

process.load("RecoBTag.Configuration.RecoBTag_cff")

process.load("Validation.RecoB.bTagAnalysis_cfi")

process.load("PhysicsTools.JetMCAlgos.CaloJetsMCFlavour_cfi")
process.bTagValidation.jetMCSrc = 'IC5byValAlgo'
process.bTagValidation.allHistograms = True
process.bTagValidation.fastMC = True
process.bTagValidation.ptRecJetMin = 15.0
process.bTagCommonBlock.ptRecJetMin = 15.0

process.maxEvents = cms.untracked.PSet(
    input = cms.untracked.int32(1000)
)
process.source = cms.Source("PoolSource",
    fileNames = cms.untracked.vstring()
)

process.plots = cms.Path(process.myPartons* process.iterativeCone5Flavour * process.bTagValidation*process.dqmSaver)
process.dqmEnv.subSystemFolder = 'BTAG'
process.dqmSaver.producer = 'DQM'
process.dqmSaver.workflow = '/POG/BTAG/BJET'
process.dqmSaver.convention = 'RelVal'

## this defines the input files
from HiggsAnalysis.VBFHiggsToZZto2l2b.Data.PYTHIA6_SM_H_ZZ_qqll_mH150_10TeV_RECO_IDEAL_legnaro_cfi import *
# this inputs the input files from the previous function
process.source = RecoInput()


import psycopg2

class Database:
    def __init__(self, db_name) -> None:
        self.name = db_name
        self.cursor = None
        self.conn = self.__try_connect(db_name, autocommit=True)
        self.cursor = self.conn.cursor()

    @staticmethod
    def __try_connect(db_name, *, autocommit):
        try:
            conn = psycopg2.connect(dbname=db_name, host="localhost", port=5432)
        except (Exception, psycopg2.DatabaseError) as error:
            print(f"Database connection failed: {error}")
            raise error
        conn.autocommit = autocommit
        return conn


import os
import shutil
import threading
from tkinter import filedialog, messagebox
from cryptography.fernet import Fernet

class Core:
    def __init__(self, open_dialog) -> None:
        if open_dialog is True:
            self.path = filedialog.askopenfilename()
        elif open_dialog is False:
            pass

    @staticmethod
    def encrypt_file(path_file):
        def start_encryption():
            # Usando chave
            # <--------------------------------------------------------------->
            fernet = Fernet(key_gen)
            with open(path_mod1, "rb") as file:
                data_origem = file.read()
            # <--------------------------------------------------------------->

            # Encriptar arquivo
            # <--------------------------------------------------------------->
            encrypted = fernet.encrypt(data_origem)
            with open(path_mod1, "wb") as file:
                file.write(encrypted)
            # <--------------------------------------------------------------->

        path_mod1 = path_file.replace(" ", "_")
        path_mod2 = path_mod1.replace("/", " ")
        os.rename(path_file, path_mod1)
        folder = "Keys"

        try:
            os.mkdir(folder)
        except FileExistsError:
            pass

        # Criando chave privada e salvando
        # <--------------------------------------------------------------->
        key_gen = Fernet.generate_key()
        name = f"KeyFile [{path_mod2.split()[-1]}].key"
        with open(name, "wb") as file_key:
            file_key.write(key_gen)
            messagebox.showinfo("Chave", f"Chave criada para o arquivo {path_file}")
        try:
            shutil.move(name, folder)
            messagebox.showwarning("Atenção", "Arquivo Key movido para pasta /Keys.")
        except Exception as e:
            if "already exists" in e.__str__():
                messagebox.showwarning("Erro", "Arquivo key existente na pasta Keys, o arquivo foi salvo na pasta raiz do programa.")
            else:
                messagebox.showerror("Erro", e.__str__())
        # <--------------------------------------------------------------->

        # Executando uma thread
        messagebox.showinfo("", "Começando a encriptar.")
        thrd = threading.Thread(target=start_encryption)
        thrd.start()

    @staticmethod
    def decrypt_file(path_file, private_key):
        try:
            # Abrindo o arquvo key
            # <---------------------------------->
            with open(private_key, "rb") as key_file:
                key = key_file.read()
            # <---------------------------------->

            # Lendo o arquivo encriptado
            # <---------------------------------->
            fernet = Fernet(key)
            with open(path_file, "rb") as file:
                file_encrypted = file.read()
            # <---------------------------------->

            # Descriptando
            # <---------------------------------->
            decrypted = fernet.decrypt(file_encrypted)
            with open(path_file, "wb") as file:
                file.write(decrypted)
                messagebox.showinfo("Sucesso", "Arquivo Desencriptado.")
            # <---------------------------------->

        except Exception:
            messagebox.showerror("Erro", "Private Key ou caminho invalido.")

    def return_path(self):
        return self.path


# -*- coding: utf-8 -*-
"""
Created on Tue Sep 21 15:54:02 2021

@author: Patrick
"""

import csv
from os import listdir
import os
import re
import dateutil.parser
from datetime import datetime
from datetime import timedelta
import nvector as nv

class RosLog:

    def __init__(self, path):

        fileNames = self.getPathsToLogs(path)
        topic = list()
        message = list()
        timeStamp = list()

        self.agentType = path.split('_')[0].split('/')[1]

        self.obstacleRange = path.split('_')[1]
        self.obstacleRange = float(self.obstacleRange.split('m')[0])

        self.outcome = ('crash' in path, 'miss' in path, 'stop' in path)

        self.reasoningPerformance = list()
        self.perceptions = list()
        self.outbox = list()
        self.inbox = list()
        self.actions = list()

        for file in fileNames:
            (topic,message,timeStamp) = self.parseFile(file)
            for i in range(len(topic)):
                if "reasoningPerformance" in topic[i]:
                    if message[i].isdigit():
                        self.reasoningPerformance.append((timeStamp[i],timedelta(milliseconds = int(message[i]))))
                    else:
                        start = dateutil.parser.parse("0:0")
                        stop = dateutil.parser.parse(message[i])
                        delta = stop - start
                        self.reasoningPerformance.append((timeStamp[i],delta))
                elif "perception" in topic[i]:
                    self.perceptions.append((timeStamp[i],message[i]))
                elif "outbox" in topic[i]:
                    self.outbox.append((timeStamp[i],message[i]))
                elif "inbox" in topic[i]:
                    self.inbox.append((timeStamp[i],message[i]))
                elif "action" in topic[i]:
                    self.actions.append((timeStamp[i],message[i]))

    def getOutcome(self):
        return self.outcome

    def getAgentType(self):
        return self.agentType

    def getObstacleRange(self):
        return self.obstacleRange

    '''
    Use this directory to target the analysis to specific test logs, groups of test
    logs or all the logs
    '''
    def getPathsToLogs(self, startPath = '.'):

        csvFiles = list()

        # Get all the directories. Some may not have CSV files in them
        directories = [x[0] for x in os.walk(startPath)]

        for directory in directories:
            files = self.findCsvFilenames(path=directory, suffix=".csv")
            for file in files:
                csvFiles.append(directory + "\\" + file)

        return csvFiles

    '''
    Parse a given csv file
    '''
    def parseFile(self, fileName):
        with open(fileName) as csv_file:
            csv_reader = csv.reader(csv_file, delimiter=',')

            topic = list()
            message = list()
            timeStamp = list()

            for row in csv_reader:
                if len(row) > 0:
                    currentTopic = row[0]
                    currentMessage = row[1]
                    currentTimeStamp = row[2]

                    if ((len(currentTopic) > 0) and (not "Topic" in currentTopic)):
                        topic.append(currentTopic)
                        message.append(currentMessage)
                        timeStamp.append(currentTimeStamp)

            return (topic, message, timeStamp)

    '''
    Get a list of the file names in a given directory
    '''
    def findCsvFilenames(self, path=".", suffix=".csv"):
        filenames = listdir(path)
        return [ filename for filename in filenames if filename.endswith( suffix ) ]

    def buildTimeline(self):

        self.times = dict()
        self.times['start'] = 0
        startTime = self.inbox[0][0]

        milestones = ['gettingRoute', 'route', 'arrived']

        for event in self.outbox:
            for milestone in milestones:
                if milestone in event[1]:
                    self.times[milestone] = getTimeDelta(startTime,event[0])
                elif (('move' in event[1]) or ('controlSpeed' in event[1])) and not ('move' in self.times.keys()):
                    self.times['move'] = getTimeDelta(startTime,event[0])

    def calculatePlanUsage(self):
        self.planUsage = dict()

        for instance in self.outbox:
            content = instance[1].split('BROADCAST,')[1]
            content = content.split('>')[0]
            planName = content.split('(')[0]

            if 'default' in content:
                planName = planName + 'Default'
            if planName in self.planUsage.keys():
                self.planUsage[planName] += 1
            else:
                self.planUsage[planName] = 1

    def calculateActionUsage(self):
        self.actionUsage = dict()

        actionsOfInterest = ['steering', 'setSpeed', 'getPath', 'move']
        messageOfInterest = ['navigate(gettingRoute']

        for instance in self.actions:
            for actionName in actionsOfInterest:
                content = instance[1]
                if actionName in content:
                    if actionName in self.actionUsage.keys():
                        self.actionUsage[actionName] += 1
                    else:
                        self.actionUsage[actionName] = 1

        # Check for the case where internal actions were used. If so,
        # we will not have seen any getPath used yet
        if not 'getPath' in self.actionUsage.keys():
            for instance in self.outbox:
                for actionFlag in messageOfInterest:
                    content = instance[1]
                    if actionFlag in content:
                        if 'getPath' in self.actionUsage.keys():
                            self.actionUsage['getPath'] += 1
                        else:
                            self.actionUsage['getPath'] = 1

    def getMertics(self):
        return (self.getReasoningRate(), self.getActionUsage(), self.getPlanUsage(), self.getTimeLine())

    # Get how long it took for the agent to react to a collision perception
    def getObstacleActionTime(self):
        (start,dist) = self.getObstacleTime()
        stopAction = self.getStopActionTime()
        stop = self.getStopTime(stopAction)

        startPosition = self.getPositionAtTime(start)
        stopPosition = self.getPositionAtTime(stop)

        if stopPosition != -1:
            delta = startPosition.delta_to(stopPosition)
            distance = delta.length[0]
        else:
            distance = -1

        if (start != -1) and (stopAction != -1):
            decisionTime = stopAction - start
        else:
            decisionTime = -1

        if (start != -1) and (stop != -1):
            stopTime = stop - start
        else:
            stopTime = -1

        return (decisionTime, stopTime, distance)

    # Get the time when the car is stopped. Start search at timeStep 'after'
    def getStopTime(self, after):
        for percept in self.perceptions:
            perceptStrings = percept[1].split(' ')
            for ps in perceptStrings:
                if 'speed' in ps:
                    observedSpeed = float(re.search('\((.*)\)', ps).group(1))
                    if observedSpeed < 0.01:    # Account for sensor noise (it is rarely exactly 0)
                        time = dateutil.parser.parse(percept[0])
                        if (type(time) == datetime) and (type(after) == datetime):
                            if time > after:
                                return time

        # Default case, we didn't find anything
        return -1

    # Get the time when the obstacle was in the stopping range
    def getObstacleTime(self):
        for percept in self.perceptions:
            perceptStrings = percept[1].split(' ')
            for ps in perceptStrings:
                if 'obstacle' in ps:
                    observedObstacleRange = float(re.search('\((.*)\)', ps).group(1))
                    if observedObstacleRange < self.obstacleRange:
                        time = dateutil.parser.parse(percept[0])
                        return (time,observedObstacleRange)

        return(-1,-1)  # If we didn't find anything

    def getPositionAtTime(self, time):
        for percept in self.perceptions:
            perceptTime = dateutil.parser.parse(percept[0])
            if perceptTime == time:
                perceptStrings = percept[1].split(' ')
                for i in range(len(perceptStrings)):
                    if 'gps' in perceptStrings[i]:
                        lat = float(perceptStrings[i].split('(')[1].split(',')[0])
                        lon = float(perceptStrings[i+1].split(')')[0])
                        wgs84 = nv.FrameE(name='WGS84')
                        locationCoord = wgs84.GeoPoint(latitude=lat, longitude=lon, degrees = True)
                        return locationCoord

        return -1

    # Find the time when the stop action was commanded
    def getStopActionTime(self):
        for action in self.actions:
            actionString = action[1]
            if 'setSpeed(0)' in actionString:
                return dateutil.parser.parse(action[0])

        return -1

    def getTimeLine(self):
        return self.times.copy()

    def getReasoningRate(self):
        return [int(data[1]) for data in self.reasoningPerformance]

    def getPlanUsage(self):
        return self.planUsage.copy()

    def getActionUsage(self):
        return self.actionUsage.copy()

    def getPerceptPeriod(self):
        periodList = list()
        lastTime = -1
        for percept in self.perceptions:
            currentTime = dateutil.parser.parse(percept[0])
            if lastTime != -1:
                periodList.append(currentTime-lastTime)
                lastTime = currentTime
            else:
                lastTime = currentTime
        return periodList

    def getReasoningPeriod(self):
        periodList = list()
        for rp in self.reasoningPerformance:
            periodList.append(rp[1])
        return periodList

    def getPerceptionTypes(self):
        perceptionTypes = list()
        sample = self.perceptions[0][1]
        segments = sample.split(' ')
        for s in segments:
            if '(' in s:
                perceptionTypes.append(s.split('(')[0])
        return perceptionTypes

def getTimeDelta(a, b):
    if not '.' in a:
        a += '.0'
    if not '.' in b:
        b += '.0'

    aTime = dateutil.parser.parse(a)
    bTime = dateutil.parser.parse(b)
    delta = bTime - aTime

    # Return in ms
    return delta.total_seconds() * 1000

'''
test case
'''
def test():
    #log = RosLog('Logs/AirSimNavigatingCar/AgentSpeak/1')
    log = RosLog('Logs/JasonMobileAgentRos/EnvironmentSupport/2')
    (periodList, actionUsage, planUsage, timeline) = log.getMertics()

'''
Main program function call
'''
if __name__ == '__main__':
    test()


alfabet = {
    "A": 0,
    "B": 2,
    "C": 3,
    "D": 4
}

x = "ACDC"
tekst = "ABBACDCDACDACDC"
i = 0

def h(ciag):
    suma = 0
    q = 23
    r = len(ciag)
    n = r-1
    for litera in ciag:
        suma += alfabet[litera] * (r**n)
        n -= 1
    wynik = suma % q
    return wynik

h_x = h(x)
r = len(x)
q = 23

while i <= len(tekst) - len(x):
    tmp = ""
    k = 0
    if i > 0:
        while k < 4:
            tmp += tekst[i + k]
            k += 1
            h_tmp = ((h(prev_tmp) - (alfabet[prev_tmp[0]]*(r**(r-1)))) * r + alfabet[tmp[-1]]) % q
        if h_tmp == h_x:
            l = 0
            flag = True
            while l < len(x):
                if tmp[l] == x[l]:
                    l += 1
                else:
                    flag = False
                    break
            if flag:
                print(f"Indeks poczatku wyszukiwanego slowa: {i}")
    else:
        k = 0
        while k < 4:
            tmp += tekst[i + k]
            k += 1
    prev_tmp = tmp
    i += 1