# bmpfont.py
# By Paul Sidorsky - Freeware
# Updated by rainlash May 2016, January 2017

"""Provides support for bitmapped fonts using pygame.

Font Index File Descrption

bmpfont lets you define where each character is within the bitmap,
along with some other options.  This lets you use a bitmap of any
dimension with characters of any size.  The file where the position
of each character is defined is called the font index file.  It is
a simple text file that may contain the lines listed below.
Whitespace is ignored, but the keywords are case-sensitive.
NOTE:  Blank lines and comments are not allowed!

width x
height y
- Specifies the dimensions of a character, in pixels.  Each
  character must be of the same width and height.  width defaults
  to 8 and height to 16 if omitted.

transrgb r g b
- Specifies the colour being used to indicate transparency.  If you
  don't wish to use transparency, set this to an unused colour.
  Defaults to black (0, 0, 0) if omitted.

alluppercase
- If present, indicates the font only has one case of letters which
  are specified in the index using upper case letters.  Strings
  rendered with BmpFont.blit() will be converted automatically.  If
  omitted, the font is assumed to have both cases of letters.
alllowercase
- If present, indicates the font only has one case of letters which
  are specified in the index using lower case letters.  Otherwise
  performs akin to 'alllowercase' option.

- All other lines are treated as character index specifiers with
  the following format:

  char x y w

  - char is the character whose position is being specified.  It
    can also be "space" (without quotes) to define a position for
    the space character.
  - x is the column number where char is located.  The position
    within the bitmap will be x * width (where width is specified
    above).
  - y is the row number where char is located.  The position will
    be y * height.
  - w is the width of the char itself in pixels. For instance, "i"
    might have a width of 1, while "c" might have a width of 4.
"""

__all__ = ["BmpFont"]

try:
    import Engine
except ImportError:
    from . import Engine

class BmpFont:
    """Provides an object for treating a bitmap as a font."""

    # Constructor - creates a BmpFont object.
    # Parameters:  name - Name of the font.
    def __init__(self, name):
        # Setup default values.
        self.alluppercase = False
        self.alllowercase = False
        self.chartable = {}
        self.idxfile = Engine.engine_constants['home'] + "Sprites/Fonts/" + name.split('_')[0] + '.idx'
        self.bmpfile = Engine.engine_constants['home'] + "Sprites/Fonts/" + name + '.png'
        self.width = 8
        self.height = 16
        self.transrgb = (0, 0, 0)

        # Read the font index.  File errors will bubble up to caller.
        f = open(self.idxfile, "r")

        for x in f.readlines():
            # Remove EOL, if any.
            if x[-1] == '\n':
                x = x[:-1]
            words = x.split()

            # Handle keywords.
            if words[0] == "alluppercase":
                self.alluppercase = True
            elif words[0] == "alllowercase":
                self.alllowercase = True
            elif words[0] == "width":
                self.width = int(words[1])
            elif words[0] == "height":
                self.height = int(words[1])
            elif words[0] == "transrgb":
                self.transrgb = (int(words[1]), int(words[2]), int(words[3]))
            else:  # Default to index entry.
                if words[0] == "space":
                    words[0] = ' '
                if self.alluppercase:
                    words[0] = words[0].upper()
                if self.alllowercase:
                    words[0] = words[0].lower()
                self.chartable[words[0]] = (int(words[1]) * self.width,
                                            int(words[2]) * self.height,
                                            int(words[3]))
        f.close()

        # Setup the actual bitmap that holds the font graphics.
        self.surface = Engine.image_load(self.bmpfile)
        Engine.set_colorkey(self.surface, self.transrgb, rleaccel=True)

    # blit() - Copies a string to a surface using the bitmap font.
    # Parameters:  string    - The message to render.  All characters
    #                          must have font index entries or a
    #                          KeyError will occur.
    #              surf      - The pygame surface to blit string to.
    #              pos       - (x, y) location specifying location
    #                          to copy to (within surf).  Meaning
    #                          depends on usetextxy parameter.
    #              usetextxy - If true, pos refers to a character cell
    #                          location.  For example, the upper-left
    #                          character is (0, 0), the next is (0, 1),
    #                          etc.  This is useful for screens with
    #                          lots of text.  Cell size depends on the
    #                          font width and height.  If false, pos is
    #                          specified in pixels, allowing for precise
    #                          text positioning.
    def blit(self, string, surf, pos=(0, 0), usetextxy=False, space_offset=0):
        """Draw a string to a surface using the bitmapped font."""
        x, y = pos
        if usetextxy:
            x *= self.width
            y *= self.height
        surfwidth, surfheight = surf.get_size()

        # The commented out line is INCREDIBLY slow.
        # NOT NECESSARY IF WE USE RGBA
        # fontsurf = self.surface.convert_alpha(surf)
        # fontsurf = self.surface

        if self.alluppercase:
            string = string.upper()
        if self.alllowercase:
            string = string.lower()

        # Render the font.
        for c in string:
            try:
                char_pos_x = self.chartable[c][0]
                char_pos_y = self.chartable[c][1]
                char_width = self.chartable[c][2]
            except KeyError as e:
                char_pos_x = 0
                char_pos_y = 0
                char_width = 4
                print(e)
                print("%s is not chartable"%(c))
                print('string', string)

            subsurf = Engine.subsurface(self.surface, (char_pos_x, char_pos_y, self.width, self.height))
            Engine.blit(surf, subsurf, (x, y))
            # surf.blit(self.surface, (x, y), ((char_pos_x, char_pos_y), (self.width, self.height))) # subsurface
            x += char_width + space_offset

    # size() - Returns the length and height of a string (height will always be self.height)
    # Parameters:  string     - the string that is to be measured. All characters must
    #                           have font index entries or a KeyError will occur.
    def size(self, string):
        """Returns the length and width of a bitmapped string"""
        length = 0
        # height = self.height
        if self.alluppercase:
            string = string.upper()
        if self.alllowercase:
            string = string.lower()
        for c in string:
            try:
                char_width = self.chartable[c][2]
            except KeyError as e:
                print(e)
                print("%s is not chartable"%(c))
                char_width = 4
            length += char_width
        return (length, self.height)


from aiohttp import web
import uuid
import logging
from marshmallow import Schema, fields, post_load, ValidationError, validate

from helpers_n_wrappers import container3, utils3
import utils

#translate objects into dictionnary for AMQP
_jinja_con_args = {
    "name": ("connection", "name"),
    "node_id": ("connection", "node_id"),
    "dpd_action": ("connection", "dpd_action"),
    "dpd_interval": ("connection", "dpd_interval"),
    "dpd_timeout": ("connection", "dpd_timeout"),
    "initiator": ("connection", "initiator"),
    "self_ip": ("tunnel", "self_ip"),
    "peer_ip": ("tunnel", "peer_ip"),
    "peer_name": ("tunnel", "name"),
    "peer_public_ip": ("tunnel", "peer_public_ip"),
    "peer_id": ("tunnel", "peer_id"),
    "ike_version": ("ike", "ike_version"),
    "ike_encryption_algorithm": ("ike", "encryption_algorithm"),
    "ike_auth_algorithm": ("ike", "auth_algorithm"),
    "ike_pfs": ("ike", "pfs"),
    "ike_lifetime": ("ike", "lifetime_value"),
    "ike_name": ("ike", "name"),
    "ipsec_transform_protocol": ("ipsec", "transform_protocol"),
    "ipsec_encryption_algorithm": ("ipsec", "encryption_algorithm"),
    "ipsec_auth_algorithm": ("ipsec", "auth_algorithm"),
    "ipsec_pfs": ("ipsec", "pfs"),
    "ipsec_lifetime": ("ipsec", "lifetime_value"),
    "ipsec_encapsulation_mode": ("ipsec", "encapsulation_mode"),
    "ipsec_name": ("ipsec", "name"),
    "secret": ("connection", "secret"),
    "status": ("connection", "status"),
}

def convert_con_template(**kwargs):
    con_args = {}
    for key in _jinja_con_args:
        object = kwargs[_jinja_con_args[key][0]]
        try:
            value = getattr(object, _jinja_con_args[key][1])
            con_args[key]=value
        except AttributeError:
            pass
    if "self_id" in con_args:
        con_args["self_id"]=kwargs["self_id"]
    return con_args

class Vpn_connection(container3.ContainerNode):

    def __init__(self, **kwargs):
        self.node_id = str(uuid.uuid4())
        utils3.set_attributes(self, override = True, **kwargs)
        super().__init__(name="Vpn_connection")
        utils3.set_attributes(self, override = False, status="Pending",
            deleting = False)

    def lookupkeys(self):
        """ Return the lookup keys of the node """
        keys = []
        keys.append((utils.KEY_CONNECTION, False))
        keys.append((self.node_id, True))
        keys.append(((utils.KEY_CONNECTION, self.node_id), True))
        keys.append(((utils.KEY_IN_USE, self.tunnel_id), False))
        keys.append(((utils.KEY_IN_USE, utils.KEY_CONNECTION, self.tunnel_id),
            False
            ))
        keys.append(((utils.KEY_IN_USE, self.ike_policy_id), False))
        keys.append(((utils.KEY_IN_USE, utils.KEY_CONNECTION, self.ike_policy_id),
            False
            ))
        keys.append(((utils.KEY_IN_USE, self.ipsec_policy_id), False))
        keys.append(((utils.KEY_IN_USE, utils.KEY_CONNECTION, self.ipsec_policy_id),
            False
            ))

        return keys

class Vpn_connection_schema(Schema):
    name = fields.Str()
    node_id = fields.Str(validate=utils.validate_uuid)
    tunnel_id = fields.Str(validate=utils.l2_validator)
    ike_policy_id = fields.Str(validate=utils.ike_validator)
    ipsec_policy_id = fields.Str(validate=utils.ipsec_validator)
    dpd_action = fields.Str(validate=validate.OneOf(["hold"]))
    dpd_interval = fields.Integer()
    dpd_timeout = fields.Integer()
    initiator = fields.Str(validate=validate.OneOf(["start"]))
    secret = fields.Str()
    status = fields.Str(validate=validate.OneOf(
        ["Pending", "Ok", "Deleting", "Failed"]
        ))
    deleting = fields.Boolean()

    @post_load
    def load_node(self, data):
        return Vpn_connection(**data)

async def get_vpn_connections(data_store, amqp, node_id=None):
    ret = utils.get_objects(data_store, amqp, Vpn_connection_schema,
        utils.KEY_CONNECTION, node_id=None
        )
    raise web.HTTPOk(content_type="application/json", text = ret)

async def create_vpn_connection(data_store, amqp, **kwargs):
    ret, vpn_connection = utils.create_object(data_store, amqp,
        Vpn_connection_schema, kwargs
        )
    await send_create_connection(data_store, amqp, vpn_connection)
    raise web.HTTPAccepted(content_type="application/json",
        text = ret
    )

async def delete_vpn_connection(data_store, amqp, node_id):
    vpn_connection = utils.delete_object(data_store, amqp, node_id,
        utils.KEY_CONNECTION
        )
    vpn_connection.status = "Deleting"
    vpn_connection.deleting = True
    data_store.save(vpn_connection)
    await send_delete_connection(data_store, amqp, vpn_connection)
    raise web.HTTPAccepted()

async def send_create_connection(data_store, amqp, connection, no_wait = False):
    tunnel = data_store.get(connection.tunnel_id)
    if not data_store.has((utils.KEY_AGENT, utils.KEY_AGENT_IP, tunnel.self_ip)):
        return

    ike = data_store.get(connection.ike_policy_id)
    ipsec = data_store.get(connection.ipsec_policy_id)
    agent_amqp = data_store.get((utils.KEY_AGENT, utils.KEY_AGENT_IP,
        tunnel.self_ip
        ))

    data = convert_con_template(connection=connection, tunnel = tunnel,
        ike = ike, ipsec = ipsec, self_id = agent_amqp.node_uuid
        )

    await _send_action_connection(agent_amqp, amqp, utils.ACTION_ADD_CONNECTION,
        data, no_wait
        )

async def send_delete_connection(data_store, amqp, connection, no_wait = False):
    data = {"node_id":connection.node_id}
    tunnel = data_store.get(connection.tunnel_id)
    if not data_store.has((utils.KEY_AGENT, utils.KEY_AGENT_IP, tunnel.self_ip)):
        return
    agent_amqp = data_store.get((utils.KEY_AGENT, utils.KEY_AGENT_IP,
        tunnel.self_ip
        ))

    await _send_action_connection(agent_amqp, amqp, utils.ACTION_DEL_CONNECTION,
        data, no_wait
        )

async def _send_action_connection(agent_amqp, amqp, action, connection_args,
        no_wait):
    payload = {"operation":action,
        "kwargs": connection_args
        }
    await amqp.publish_action(payload=payload,
        node = agent_amqp, callback = utils.ack_callback, no_wait = no_wait
        )


from datetime import datetime

from ..brokerage.alpaca.client.create_market_data_client import (
    create_historical_stock_data_client,
)
from ..brokerage.alpaca.data.get_close_to_close_returns import (
    get_close_to_close_returns,
)

def test_get_close_to_close_returns():
    client = create_historical_stock_data_client()
    ctc_returns = get_close_to_close_returns(
        client=client,
        symbols=["AAPL"],
        start=datetime(2023, 1, 1),
        end=datetime(2023, 1, 8),
    )

    assert ctc_returns.get("AAPL") is not None
    assert len(ctc_returns.get("AAPL")) == 3
    assert ctc_returns.get("AAPL")[0] == 0.010373110324863351


import scanpy as sc
import numpy as np
import pandas as pd

from .. import get
from .. import preprocessing
from . import _helper as helper
from .. import utils
from ..utils._utils import _infer_annotation_key
import scipy.sparse
import scipy.linalg

try: # dont fail importing the whole module, just because a single annotation method is not available
    import wot
    HAVE_WOT = True
except ImportError:
    HAVE_WOT = False

def _annotate_wot(
    adata,
    reference,
    annotation_key,
    **kwargs
    ):

    """\
    Implements the functionality of :func:`~annotate_wot` without data
    integrity checks.
    """

    if not HAVE_WOT:
        raise ImportError('The module `wot` could not be imported, but is required to use the annotate method "wot"! Maybe it is not installed properly?')

    nadata = adata.shape[0]
    nref = reference.shape[0]

    adata_ref = sc.concat((adata, reference))
    adata_ref.obs['data'] = [0] * nadata + [1] * nref

    try:
        ot_model = wot.ot.OTModel(adata_ref, day_field='data', **kwargs)
        tmap_annotated = ot_model.compute_transport_map(0, 1)
    except:
        print('Exception in WaddingtonOT. Trying with cell normalization.')
        sc.pp.normalize_per_cell(adata_ref, counts_per_cell_after=10000)
        ot_model = wot.ot.OTModel(adata_ref, day_field='data', **kwargs)
        tmap_annotated = ot_model.compute_transport_map(0, 1)

    ref_cell_type = pd.get_dummies(reference.obs[annotation_key])
    cell_type = (tmap_annotated.X @ ref_cell_type)
    cell_type.index = adata.obs.index
    cell_type = helper.normalize_result_format(cell_type)

    return cell_type

def annotate_wot(
    adata,
    reference,
    annotation_key=None,
    counts_location=None,
    **kwargs
    ):

    """\
    Annotates an :class:`~anndata.AnnData` using reference data by
    Waddington-OT [Schiebinger19]_.

    This is the direct interface to this annotation method. In practice using
    the general wrapper :func:`~tacco.tools.annotate` is recommended due to its
    higher flexibility.

    Parameters
    ----------
    adata
        An :class:`~anndata.AnnData` including expression data in `.X`.
    reference
        Reference data to get the annotation definition from.
    annotation_key
        The `.obs` key where the annotation is stored in the `reference`. If
        `None`, it is inferred from `reference`, if possible.
    counts_location
        A string or tuple specifying where the count matrix is stored, e.g.
        `'X'`, `('raw','X')`, `('raw','obsm','my_counts_key')`,
        `('layer','my_counts_key')`, ... For details see
        :func:`~tacco.get.counts`.
    kwargs
        Extra key word arguments are forwarded to :func:`wot.ot.OTModel`.

    Returns
    -------
    Returns the annotation in a :class:`~pandas.DataFrame`.

    """

    if adata is None:
        raise ValueError('"adata" cannot be None!')
    if adata.X is None:
        raise ValueError('"adata.X" cannot be None!')
    if reference is None:
        raise ValueError('"reference" cannot be None!')

    annotation_key = _infer_annotation_key(reference, annotation_key)

    adata = get.counts(adata, counts_location=counts_location, annotation=True, copy=False)
    reference = get.counts(reference, counts_location=counts_location, annotation=annotation_key, copy=False)

#    if annotation_key in reference.varm:
#        reference = preprocessing.filter_profiles(adata=reference, annotation_key=annotation_key, fill_na=None, fill_negative=None) # filter out zero-only genes in the profiles
    if annotation_key in reference.obsm:
        reference = preprocessing.filter_annotation(adata=reference, annotation_key=annotation_key, fill_na=None, fill_negative=None) # filter out zero-only cells in the annotation

    tdata,reference = preprocessing.filter(adata=(adata, reference)) # ensure consistent gene selection

    # call typing without data integrity checks
    cell_type = _annotate_wot(
        adata=adata,
        reference=reference,
        annotation_key=annotation_key,
        **kwargs
    )

    return cell_type


# encoding:utf-8
import copy
import numpy as np
import random

nums = list(input())
nums = [int(i) for i in nums]

def make2digits(n):
    digits = []
    for i in range(3):
        if n % 2 == 1:
            digits.append(1)
        else:
            digits.append(0)
        n = n//2
    return digits

for i in range(8):
    count = nums[0]
    choices = make2digits(i)
    # print(choices)
    for j in range(len(choices)):
        if choices[j]==0:
            count -= nums[j+1]
        else:
            count += nums[j+1]
    # print(count)
    if count == 7:
        ans_choice = choices
        break

plusminus = ["-","+"]
ans = ""
nums = [str(i) for i in nums]
for i in range(3):
    ans = ans + nums[i] + plusminus[ans_choice[i]]

ans = ans+nums[-1]+"=7"
print(ans)


import pyperclip
import re
from pytube import YouTube
from pytube.exceptions import RegexMatchError

def downloadVideoFromClipboard():
    # extract text from the clipboard
    clipboardText = pyperclip.paste()
    ytLinkRegex = re.compile(r'(https://www.youtube.com/\S+youtu.be)')
    listOfLinks = ytLinkRegex.findall(clipboardText)
    # extract urls from content
    for i in range(len(listOfLinks)):
        # print(listOfLinks[i])
        ytVideoLink = listOfLinks[i]
        # interpolate the yt object with string values
        try:
            desiredVideo = YouTube(ytVideoLink)
        except RegexMatchError:
            print('An RegexMatchError Exception Occured While Parsing The Clipboard Text')
            print(f'{ytVideoLink} appears to have formatting issues')
            if i <= len(listOfLinks):
                print('skipping this entry...')
                print('processing the remaining items found...')
            else:
                print(f'skipping link {ytVideoLink}')
        except Exception as e:
            print(f'An {e} Exception Occured While Parsing The Clipboard Text')
            print(f'{ytVideoLink} appears to have formatting issues')
        else:
            # # establish a stream selection by iTag
            stream = desiredVideo.streams.get_by_itag(22)
            # # download the selection
            if stream.download('./'):
                print(
                    f'Video # {i + 1} {stream.title} Found at {ytVideoLink} SUCCESSFULLY Downloaded')

downloadVideoFromClipboard()

# sextonVideo = YouTube(
#     'https://www.youtube.com/watch?v=8YOfTje05Lk&feature=youtu.be')

# secondSextonVideo = YouTube(
#     'https://www.youtube.com/watch?v=1NvALzdU9PU&feature=youtu.be ')

# #  filter the streams and select the first option
# video = secondSextonVideo.streams.filter(res="720p")[0]

# video.download('./')

# # establish a stream selection by iTag
# stream = sextonVideo.streams.get_by_itag(22)
# # download the selection
# stream.download('./')


from twisted.words.protocols import irc
from txircd.modbase import Command
from txircd.server import ModuleMessage
from txircd.utils import irc_lower
from fnmatch import fnmatch

class RehashCommand(Command):
    def onUse(self, user, data):
        serverMask = irc_lower(data["servers"])
        if fnmatch(irc_lower(self.ircd.name), serverMask):
            user.sendMessage(irc.RPL_REHASHING, self.ircd.config, ":Rehashing")
            self.ircd.rehash()
        for server in self.ircd.servers.itervalues():
            if fnmatch(irc_lower(server.name), serverMask):
                server.callRemote(ModuleMessage, destserver=server.name, type="Rehash", args=[])
                user.sendMessage(irc.RPL_REHASHING, self.ircd.config, ":Rehashing {}".format(server.name))

    def processParams(self, user, params):
        if user.registered > 0:
            user.sendMessage(irc.ERR_NOTREGISTERED, "REHASH", ":You have not registered")
            return {}
        if "o" not in user.mode:
            user.sendMessage(irc.ERR_NOPRIVILEGES, ":Permission denied - You do not have the required operator privileges")
            return {}
        if params:
            return {
                "user": user,
                "servers": params[0]
            }
        return {
            "user": user,
            "servers": self.ircd.name
        }

    def remoteRehash(self, command, args):
        self.ircd.rehash()

class Spawner(object):
    def __init__(self, ircd):
        self.ircd = ircd
        self.rehash_cmd = None

    def spawn(self):
        self.rehash_cmd = RehashCommand()
        return {
            "commands": {
                "REHASH": self.rehash_cmd
            },
            "server": {
                "Rehash": self.rehash_cmd.remoteRehash
            }
        }


import subprocess as sp
from PIL import Image, ImageDraw, ImageFont
import textwrap
import numpy as np
import matplotlib.pyplot as plt
import imageio as io
from .Handler import hPipe, hImageIo

def writeTextOnImage(im,
                     text,
                     position=(0,0),
                     font_face='arial.ttf',
                     font_color='#ffffff',
                     font_size=18,
                     return_ndarray='auto'):

    converted = False

    # If image is numpy array, convert to PIL Image
    if type(im) == np.ndarray:
        im = Image.fromarray(im)
        converted = True

    draw = ImageDraw.Draw(im)
    font = ImageFont.truetype(font_face, font_size)
    draw.text(position, text, font=font, fill=font_color)

    # If numpy array is desired
    if return_ndarray and return_ndarray != 'auto':
        return np.array(im)

    # If input image was numpy array, return numpy array
    elif return_ndarray and converted:
        return np.array(im)

    # If image was PIL image, return PIL image
    else:
        return im

def writeCenteredTextOnImage(im,
                             text,
                             wrap_width=None,
                             pad=10,
                             font_face='arial.ttf',
                             font_color='#ffffff',
                             font_size=18,
                             return_ndarray='auto'):

    converted = False

    # If image is numpy array, convert to PIL Image
    if type(im) == np.ndarray:
        im = Image.fromarray(im)
        converted = True

    # Check if text should be automatically wrapped
    if wrap_width is None:
        if type(text) == str:
            lines = [text]

        elif type(text) == tuple or type(text) == list:
            lines = text

        else:
            raise Exception('text must be either a string, a tuple or a list')

    # Auto wrap text
    else:
        lines = textwrap.wrap(text, width=wrap_width)

    # Get height and width of the image to align text
    H, W = im.height, im.width

    # Create draw unterface
    draw = ImageDraw.Draw(im)
    font = ImageFont.truetype(font_face, font_size)

    # Compute line dimensions
    line_dimensions = np.array([draw.textsize(line, font=font, fill=font_color) for line in lines])

    # Compute height of first line
    line_h = H//2-(line_dimensions.mean(0)[1])*(1+line_dimensions.shape[0]/2)

    for i, line in enumerate(lines):
        # Draw text on current line, width centered
        draw.text(((W - line_dimensions[i,0]) / 2, line_h), # compute position
                  line,
                  fill=font_color,
                  font=font)

        # Increase line_h with padding
        line_h += line_dimensions.mean(0)[1] + pad

    # If numpy array is desired
    if return_ndarray and return_ndarray != 'auto':
        return np.array(im)

    # If input image was numpy array, return numpy array
    elif return_ndarray and converted:
        return np.array(im)

    # If image was PIL image, return PIL image
    else:
        return im

class Title:
    def __init__(self,
                 title,
                 fadeIn=1.,
                 fadeOut=1.,
                 stay=3.,
                 pad=0.5,
                 fps=30,
                 background_color=(0, 0, 0),
                 font_face='arial.ttf',
                 font_color=(255, 255, 255),
                 font_size=50,
                 wrap_width=None,
                 shape=(400, 400)):
        """Creates title page

        Parameters
        ----------
        title : str
            Text to be written on page
        fadeIn : float, optional
            time text fades in in seconds (the default is 1)
        fadeOut : float, optional
            time text fades out in seconds (the default is 1)
        stay : float, optional
            time text stays in seconds (the default is 3)
        pad : float, optional
            time at beginning and end where only background is shown in seconds
            (the default is 0.5)
        fps : int, optional
            frames per second (the default is 30)
        background_color : tuple, optional
            background color in RGB (0...255)
            (the default is (0, 0, 0), which is black)
        font_face : str, optional
            font face, such as arial or verdana (the default is 'arial.ttf')
        font_color : tuple, optional
            font color in RGB (0...255)
            (the default is (255, 255, 255), which is white)
        font_size : int, optional
            font size of text (the default is 50)
        wrap_width : int, optional
            defines the length of a single line
            (the default is None, which does not break lines)
        shape : tuple, optional
            shape of title page (same as movie)
            (the default is (400, 400))

        """

        self.title = title
        self.fadeIn = fadeIn
        self.fadeOut = fadeOut
        self.stay = stay
        self.fps = fps
        self.background_color = background_color
        self.font_face = font_face
        self.font_color = font_color
        self.font_size = font_size
        self.wrap_width = wrap_width
        self.pad = pad

        if type(shape) == tuple:
            self.shape = shape if len(shape) == 2 else shape[:2]

        if type(shape) == MovieMaker:
            self.shape = shape.shape[:2][::-1]

        self.total_frames = int((fadeIn+fadeOut+stay+pad*2)*fps)

        self.slideshow = None

    def create(self):
        im = Image.new('RGB', self.shape, self.background_color)
        im = writeCenteredTextOnImage(im=im,
                                      text=self.title,
                                      wrap_width=self.wrap_width,
                                      font_face=self.font_face,
                                      font_color=self.font_color,
                                      font_size=self.font_size,
                                      return_ndarray=True)

        slideshow = np.ones((self.total_frames, ) + im.shape, dtype=np.uint8)
        slideshow[:,:,:] = self.background_color

        c = int(self.pad * self.fps)

        # fadeIn
        for i in range(int(self.fadeIn*self.fps)):
            slideshow[c] = im * (i / (self.fadeIn*self.fps))
            c += 1

        for _ in range(int(self.stay*self.fps)):
            slideshow[c] = im
            c += 1

        for i in range(int(self.fadeOut*self.fps)):
            slideshow[c] = im * (1. - i / (self.fadeOut*self.fps))
            c += 1

        self.slideshow = slideshow

        return self.slideshow

class MovieMaker:
    def __init__(self,
                 filename,
                 handler='pipe',
                 fps=30,
                 codec='libx264',
                 quality=26,
                 shape=None,
                 FFMPEG_DIR=r"C:\ffmpeg\bin"):
        """MovieMaker class that creates from single frames a movie

        Parameters
        ----------
        filename : str
            Path to the file that should be created
        handler : str, optional
            defines the handler ('pipe', 'io') (the default is 'pipe')
        fps : int, optional
            frames per second in movie (the default is 30)
        codec : str, optional
            defines the used codec, e.g. mpeg, libx264, libx265 (the default is 'libx264')
        quality : int, optional
            defines the quality of the movie (0...63, the -crf option in ffmpeg)
            (the default is 26, which is a good balance)
        shape : tuple, optional
            defines dimensions of the movie, will be set automatically
            from the first frame/image/plot that is defined.
            (the default is None, which means it is fetched automatically)
        FFMPEG_DIR : str, optional
            path to ffmpeg bin folder (the default is r"C:\ffmpeg\bin")

        """

        self.FFMPEG_DIR = FFMPEG_DIR
        self.FFMPEG_EXE = FFMPEG_DIR+"\\ffmpeg.exe"

        assert (quality >= 0 and quality <= 63), "Quality min: 0, max: 63"

        ##### Settings #####
        self.filename = filename
        self.shape = shape
        self.fps = fps
        self.codec = codec
        self.crf = quality

        ##### Cache #####
        self.cache = [] # now numpy arrays are cached, not strings

        self.handler = handler
        self.h = None

    def clearCache(self):
        """clears internal cache

        Returns
        -------
        bool
            If operation was successful
        """

        self.cache = []
        return True

    def _get_image_from_figure(self, fig, autoclose=True):
        """Creates image from Figure object

        Parameters
        ----------
        fig : matplotlib.Figure
            The figure handler, e.g.
            fig = plt.figure()
        autoclose : bool, optional
            closes automatically the figure to free RAM
            (the default is True)

        Raises
        ------
        ValueError
            If shape from figure is not the same as previous shapes

        Returns
        -------
        numpy.ndarray
            The image as numpy array in the shape (x,y,3)
        """
        fig.canvas.draw()
        rgb = fig.canvas.tostring_rgb()
        shape = fig.canvas.get_width_height()[::-1] + (3,)

        if self.shape is None:
            self.shape = shape

        elif self.shape != shape:
            raise ValueError('Shape from figure ({:d}x{:d}) is not as expected ({:d}x{:d})'.format(*shape, *self.shape))

        if autoclose:
            plt.close(fig)

        # Returns numpy array
        return np.frombuffer(rgb, dtype=np.uint8).reshape(shape)

    def addFigureToCache(self, fig, autoclose=True):
        """adds a Figure (plt.figure()) to internal cache

        Parameters
        ----------
        fig : matplotlib.Figure
            The figure handler from a matplotlib plot
        autoclose : bool, optional
            closes automatically the figure to free RAM (the default is True)

        """
        self.cache.append(self._get_image_from_figure(fig, autoclose))

    def addImageToCache(self, im):
        """adds an Image to internal cache

        Parameters
        ----------
        im : numpy.ndarray
            Either grayscale or RGB array

        """

        if im.ndim == 2:
            im = np.repeat(im[...,None], 3, 2)

        self.cache.append(im)

    def initHandler(self):
        """Initiates handler depending on handler type

        """

        if self.handler == 'io' or self.handler == 'imageio':
            self.h = hImageIo(self.filename)

        else:
            self.h = hPipe(self.filename,
                            shape=self.shape,
                            fps=self.fps,
                            codec=self.codec,
                            quality=self.crf,
                            FFMPEG_DIR=self.FFMPEG_DIR)

        # Open handler
        self.h.open()

    def writeFigure(self, fig, autoclose=True):
        """Write Figure directly to file stream

        Parameters
        ----------
        fig : matplotlib.Figure
            The figure handler from a matplotlib plot
        autoclose : bool, optional
            closes automatically the figure to free RAM (the default is True)

        """

        im = self._get_image_from_figure(fig, autoclose)

        if self.h is None:
            self.initHandler()

        self.h.write(im)

    def writeImage(self, im):
        """Writes Image directly to stream

        Parameters
        ----------
        im : numpy.ndarray
            Either grayscale or RGB array

        """

        if im.ndim == 2:
            im = np.repeat(im[...,None], 3, 2)

        if self.h is None:
            self.initHandler()

        self.h.write(im)

    def addTitle(self, slideshow, to_beginning=True):
        """Adds title page to cache. If you would like to
        add title directly to stream, add the title page
        as single image frames via the ```write image``` method.

        Parameters
        ----------
        slideshow : numpy.ndarray
            A numpy ndarray that is creates using the Title.create() function

        to_beginning : bool, optional
            Defines if the title page should be added to the beginning of the movie,
            or at the end (the default is True)

        """

        # If there's no shape available yet
        if self.shape is None:
            self.shape = slideshow.shape[1:3]

        cache = []

        for s in slideshow:
            cache.append(s)

        # Put title page either to beginning or to the end
        if to_beginning:
            self.cache = cache + self.cache

        else:
            self.cache.extend(cache)

    def writeCache(self, clear_cache=True, close_handler=True):
        """Writes cache to file

        Parameters
        ----------
        clear_cache : bool, optional
            clears the cache list (the default is True)
        close_handler : bool, optional
            closes handler object, finishes file (the default is True)

        """
        if self.h is None:
            self.initHandler()

        for c in self.cache:
            self.h.write(c)

        if clear_cache:
            self.clearCache()

        if close_handler:
            self.h.close()

    def cacheToArray(self):
        """Returns the cache list as numpy ndarray

        Returns
        -------
        numpy.ndarray
            Returns array with shape (frames, X, Y, 3)
        """

        return np.array(self.cache, dtype=np.uint8)

    def toGIF(self, gif_filename=None, method='pipe'):
        """Creates GIF from file

        Parameters
        ----------
        gif_filename : str, optional
            path to new GIF file (the default is None, which replaces mp4 ending with GIF)
        method : str, optional
            method to create GIF (the default is 'pipe')

        """
        if gif_filename is None:
            gif_filename = self.filename.replace('mp4','gif')

        movie2GIF(self.filename, gif_filename, method=method, fps=self.fps)

def framesToGIF(filename, frames, subrectangles=True, **kwargs):
    """Uses ImageIO to write a GIF file from frames

    Parameters
    ----------
    filename : str
        path to your new GIF file
    frames : numpy.ndarray
        Numpy array with the shape (frames, X, Y, 3)
    subrectangles : bool, optional
        Sets GIF compression method (the default is True)

    Returns
    -------
    bool
        If writing GIF file succeeded
    """
    if not filename.endswith('.gif'):
        filename += '.gif'

    return io.mimwrite(filename, frames, subrectangles=subrectangles, **kwargs)

def movie2GIF(src,
              out,
              method='pipe',
              skip=None,
              duration=None,
              fps=10,
              subrectangles=True,
              FFMPEG_EXE=r"C:\ffmpeg\bin\ffmpeg.exe"):
    """Creates a GIF from a movie file using either ffmpeg
    or imageio (that uses ffmpeg as well)

    Parameters
    ----------
    src : str
        Path to source file
    out : str
        Path to output file
    method : str, optional
        defines the method for GIF, either 'pipe' or 'imageio'
        (the default is 'pipe')
    skip : int, optional
        skips the first 'skip' seconds (the default is None, which skips nothing)
    duration : int, optional
        duration of video (the default is None, which takes the whole video)
    fps : int, optional
        sets the frames per second in GIF (the default is 10)
    subrectangles : bool, optional
        compression method for imageio (the default is True)
    FFMPEG_EXE : regexp, optional
        path to ffmpeg.exe (the default is r"C:\ffmpeg\bin\ffmpeg.exe")

    """
    if method == 'io':
        frames = io.mimread(src)
        io.mimwrite(out, frames, fps=fps, subrectangles=subrectangles)

    else:
        #### Create palette for high quality GIFs ####
        command = [FFMPEG_EXE,
                '-y'] # (optional) overwrite output file if it exists]

        # Skip part [s]
        if skip:
            command += ['-ss', skip]

        # Max   duration    seconds
        if duration:
            command += ['-t', duration]

        command += ['-i', src, # Source video
                '-vf', 'fps={},scale=-1:-1:flags=lanczos,palettegen'.format(fps),
                'palette.png']

        pipe = sp.Popen(command,
                        stdout=sp.PIPE,
                        stdin=sp.PIPE)

        pipe.stdin.close()
        pipe.communicate() # Wait that pipe finished.

        #### Create GIF using PALETTE ####
        command = [FFMPEG_EXE,
                '-y'] # (optional) overwrite output file if it exists

        # Skip part [s]
        if skip:
            command += ['-ss', skip]

        # Max   duration    seconds
        if duration:
            command += ['-t', duration]

        command += ['-i', src, # Source video
                '-i', 'palette.png', # High res palette
                '-filter_complex', 'fps={},scale=-1:-1:flags=lanczos [x]; [x][1:v] paletteuse'.format(fps),
                out] # Filename of output

        # Use PIPE
        pipe = sp.Popen(command,
                        stdout=sp.PIPE,
                        bufsize=10**8)

        pipe.communicate() # Wait

if __name__ == '__main__':
    from time import time

    for handler in ['io']:
        t0 = time()

        mm = MovieMaker("test.mp4", handler=handler)
        x0 = np.linspace(0, 4*np.pi, 1000)

        for i in range(0, x0.size, 10):
            fig = plt.figure(figsize=(12,7),
                             facecolor='white',
                             dpi=96)

            plt.plot(x0[:i], np.sin(2 * x0[:i]))
            plt.xlim([0, x0.max()])
            plt.ylim([-1.2, 1.2])

            mm.addFigureToCache(fig)

        t = Title("My fancy sine plot", shape=mm)

        mm.addTitle(t.create())

        mm.writeCache()
        mm.toGIF()

        print(handler, 'took {:.2f} seconds!'.format(time()-t0))


import os # used for reading in tile files
import json # used for reading in data.json files
import random # used for generatin random numbers
from collections import deque # used rotating arrays of sides
from PIL import Image # used for reading in and displaying the result image
from tile import Tile # represents a tile and its possible sides
from cell import Cell # represents a cell inside the final image

# local directory to the tile-images and data.json
IMG_DIRECTORY ="tiles/circuit"
# how many columns/rows in the final image
DIMENSION = 60
# size of the final image
SIZE=1920

def read_files(directory: str) -> dict[str, Tile]:
    """Reads in tile images and their respective data

    Args:
        directory (str): the directory the images and data.json are contained in (local)

    Returns:
        dict[str, Tile]: dictionary containing each Tile object and their sides, key is the Tile.id
    """
    tiles: dict[str, Tile] = {}
    # read in the data.json file
    with open(os.path.join(directory, "data.json"), "r", encoding="UTF-8") as reader:
        data = json.load(reader)
    # for every file in the given directory
    for filename in os.listdir(directory):
        f = os.path.join(directory, filename)
        # if that file is not data.json
        if os.path.isfile(f) and not f.endswith(".json"):
            # retrieve the name of the tile
            name = filename.split(".")[0]
            # load the image
            img = Image.open(f)
            # create the Tile object
            tile = Tile(img, data[name])
            # set it into the output
            tiles[tile.id] = tile
            # for every rotation this tile could be rotated (and would result in new tiles)
            for rotation in data['rotations'][name]:
                # rotate the image clockwise
                newImg = img.rotate(rotation*-90)
                # add the rotation index to the file name (and hence the id)
                newImg.filename = f"{img.filename.split('.')[0]}{rotation}.png"
                # rotate the sides clockwise
                newSides = deque(data[name])
                newSides.rotate(rotation)
                # create new rotated tile
                rotatedTile = Tile(newImg, list(newSides))
                # add to the mix
                tiles[rotatedTile.id] = rotatedTile
    return tiles

def get_lowest_entropy_cells(grid: list[list[Cell]]) -> list[Cell]:
    """Returns a list of cells that have the lowest entropy

    Args:
        grid (list[list[Cell]]): the grid containing all cells

    Returns:
        list[Cell]: the list of cells with lowest entropy
    """
    # current maximum amount of tiles is set to 1000
    # good luck creating a data.json for a tile set of more then 1000 pieces
    current_Lowest = 1000
    collection = []
    # for every cell
    for row in grid:
        for cell in row:
            # if cell can still be collapsed and has lower entropy
            if cell.collapsed is False and len(cell.possible) < current_Lowest:
                # create new list (deleting the old list, since we have a new minimum)
                collection = [cell]
                current_Lowest = len(cell.possible)
            # if cell can still be collapsed and has the current lowest entropy
            elif cell.collapse is False and len(cell.possible) == current_Lowest:
                collection.append(cell)
    return collection

def update_cells(grid: list[list[Cell]], tiles: dict[str, Tile], affected: list[tuple[int, int]], start: Cell) -> list[Cell]:
    """Propagates the changes given by the single collapsed cell through the grid

    Args:
        grid (list[list[Cell]]): the grid containing all tiles
        tiles (dict[str, Tile]): the possible tiles in general
        affected (list[tuple[int, int]]): list of integer coordinates that are affected by the given collapsed cell
        start (Cell): the cell that collapsed

    Returns:
        list[Cell]: the cells that also collapsed during the process
    """
    # the queue is filled with all cells that are affected by the collapse of the starting cell
    queue = affected
    # done cells are cells, that collapsed (and do not need to be checked)
    done = [(start.x, start.y)]
    # collapsed cells is the final output, all cells that collapsed
    collapsed_cells = [start]
    # go through the queue
    while len(queue) > 0:
        # pop the first element
        next_coords = queue.pop(0)
        # if the current cell collapsed in on of the previous steps, do not calculate (since it cannot be more collapsed)
        if next_coords not in done:
            # retrieve the Cell object for the given coordinates
            next_cell: Cell = grid[next_coords[1]][next_coords[0]]
            # if that cell is collapsed (collapsed by a previous call of this function, but not in done yet)
            if next_cell.collapsed:
                # add it to done and skip the calculation
                done.append(next_coords)
                continue
            # reduce the entropy of this cell by looking at its neighbours, returns a list of affected neighbours if this entropy changed
            # this is generally 4 members (4 sides of a tile) except at the edges
            new_possibles, affected = next_cell.reduce(grid, tiles)
            # if the entropy did not get reduced - skip next steps
            # entropies never change and have the same length as only entropies are removed, never added
            # this cell might be affected by other cells and their reduced entropy, hence we don't add it to "done"
            if len(next_cell.possible) == len(new_possibles):
                continue
            # go through all affected neighbours
            for aff in affected:
                # if the neighbour is already collapsed or already in queue, skip
                if aff not in done and aff not in queue:
                    queue.append(aff)
            # set the new entropy for this cell
            next_cell.possible = new_possibles
            # if the new entropy collapsed this cell
            if len(new_possibles) == 1:
                # set their properties, add to output and done
                next_cell.collapsed = True
                collapsed_cells.append(next_cell)
                done.append(next_coords)
    return collapsed_cells

def draw_canvas(canvas_grid: list[list[Tile]]):
    """Draws a given grid of tiles to the screen

    Args:
        canvas_grid (list[list[Tile]]): the grid of tiles. If no tile was set yet, the tile should be None
    """
    # create Canvas of given size
    canvas = Image.new('RGB', (SIZE,SIZE),0)
    tile_size = SIZE//DIMENSION

    # for all tiles in the grid
    for j, row in enumerate(canvas_grid):
        for i, tile in enumerate(row):
            # if the tile is set
            if tile is not None:
                # add the tile image to the final canvas
                canvas.paste(tile.img.resize((tile_size, tile_size), Image.ANTIALIAS), (i*tile_size, j*tile_size))

    canvas.save(f"output\\{IMG_DIRECTORY.split('/')[1]}.png")
    canvas.show()

def main():
    # read in tiles
    tiles: dict[str, Tile] = read_files(IMG_DIRECTORY)

    # generate two-dimensional grid of Cell objects, set their current entropy to all possible tiles and set their x and y position
    grid = [[Cell(list(map(lambda tile: tile, tiles)), j, i) for j in range(DIMENSION)] for i in range(DIMENSION)]
    # generate canvas grid (grid of tiles later drawn) with no tiles set
    canvas_grid = [[None for _ in range(DIMENSION)] for _ in range(DIMENSION)]

    # retrieve current cells that have lowest entropy (Should be all cells)
    new_choose = get_lowest_entropy_cells(grid)

    # the counter depicts how many tiles were set
    # if get_lowest_entropy_cells does not find new cells, this means we ran into a dead end
    counter = 0
    # while we found new tiles with lower entropy (should be only if all tiles are set)
    while len(new_choose) > 0:
        # retrieve a random cell with lowest entropy
        next_cell: Cell = random.sample(new_choose, 1)[0]
        # collapse the cell and return its affected neighbours (generally 4, at the edge 2 or 3)
        affected = next_cell.collapse(grid, tiles)

        # propagate the collapse through the grid. This could collapse other cells (very uncommon, depends on what cells we collapsed)
        # Example of a situation where a new cell is also collapsed:
        # |   |   |   |   |   |
        # |   |   | # |   |   |   A non-collapsed cell C is surrounded by already collapsed cell #
        # |   | + | C | # |   |   The above collapse function collapsed cell +
        # |   |   | # |   |   |   With a small Tile set, this could mean only 1 possible Tile fits (or none)
        # |   |   |   |   |   |   Hence the cell collapses
        collapsed: list[Cell] = update_cells(grid, tiles, affected, next_cell)
        # for every collapsed cell
        for cell in collapsed:
            # update the canvas grid with the given cell tile it collapsed to
            # this should throw an error, if the collapse resulted in 0 possibilities
            canvas_grid[cell.y][cell.x] = tiles[cell.possible[0]]
            # update the counter, since we added an additional tile
            counter += 1
        # and choose the next lowest entropy cells
        new_choose = get_lowest_entropy_cells(grid)
    # after collapsing all possible cells with the given randomization, draw the graph
    draw_canvas(canvas_grid)
    # if we could not find additional low-entropy cells, but did not fill the grid, we are in trouble
    if counter < DIMENSION*DIMENSION:
        print("No combination found")

if __name__ == "__main__":
    main()


#!/usr/bin/python3
"""Recursive function that queries the Reddit API and returns a list
containing the titles of all hot articles for a given subreddit."""
import requests

def recurse(subreddit, hot_list=[], data_after=''):
    """Fx to make the query and return list with titles of all articles"""
    url = "https://www.reddit.com/r/{}/hot.json?after={}".format(subreddit,
                                                                 data_after)
    headers_dict = {
        'User-Agent':
        'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.3) \
        Gecko/20100401 Firefox/3.6.3 (FM Scene 4.6.1)'}
    res = requests.get(url, headers=headers_dict, allow_redirects=False)
    if res.status_code == 200:
        data_after = res.json().get('data').get('after')
        data_children = res.json().get('data').get('children')
        for elem in data_children:
            hot_list.append(elem.get('data').get('title'))
        if data_after is None:
            return hot_list
        return recurse(subreddit, hot_list, data_after)
    else:
        return None


import argparse
import json
import os
from tinydb import TinyDB, Query

def get_entries(db, entry_id):
    q = Query()
    return db.search(q.id == entry_id)

def entry_exists(db, entry_id):
    q = Query()
    return len(db.search(q.id == entry_id)) > 0

def truncate(db):
    db.truncate()
    print('DB truncated')

def remove_entry(db, entry_id):

    if not entry_exists(db, entry_id):
        print(f'no data found for ID {entry_id}')
        return

    q = Query()
    db.remove(q.id == entry_id)

def get_entry_ids(db):

    res = []
    for e in iter(db):
        res.append(e['id'])
    res.sort()
    return res

def list_ids(db):

    ids = get_entry_ids(db)
    if not ids:
        print(f'the DB is empty')
        return

    print(f'{len(ids)} IDs found:')
    for i in ids:
        print(f'  {i}')

def load_samples(db, samples_dir, truncate_db, keep_existing):

    print(f'loading samples from {samples_dir}, truncate DB: {truncate_db}, keep existing: {keep_existing}')
    if truncate_db:
        truncate(db)

    files = os.listdir(samples_dir)
    for f in files:
        if '.json' in f:
            load_sample(db, os.path.join(samples_dir, f), f.replace('.json', ''), keep_existing)
        else:
            print(f'warning: {f} has no json extension, skipping')

def load_sample(db, json_file, entry_id, keep_existing):

    with open(json_file, 'r') as f:
        data = json.load(f)
        data['id'] = entry_id

        if keep_existing:
            if entry_exists(db, entry_id):
                print(f'warning: {entry_id} already exists, will not add')
            else:
                db.insert(data)
                print(f'{entry_id} inserted')
        else:
            if entry_exists(db, entry_id):
                print(f'warning: overwriting {entry_id}')
                remove_entry(db, entry_id)
            db.insert(data)
            print(f'{entry_id} inserted')

def save_sample(db, samples_dir, i, json_indent):

    data = get_entries(db, i)

    if not data:
        print(f'no data found for ID {i}')
        return

    if len(data) > 1:
        print(f'error: invalid number of entries for ID {i}')

    with open(os.path.join(samples_dir, f'{i}.json'), 'w') as f:
        if json_indent > 0:
            json.dump(data[0], f, indent=json_indent)
        else:
            json.dump(data[0], f)

def save_samples(db, samples_dir, json_indent):

    print(f'saving samples to {samples_dir}')

    if os.path.exists(samples_dir):
        print(f'warning: directory {samples_dir} already exists')
    else:
        os.makedirs(samples_dir)

    ids = get_entry_ids(db)
    for i in ids:
        save_sample(db, samples_dir, i, json_indent)

def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('--DB', required=True, help='db file')
    parser.add_argument('--samplesDir', help='samples directory')
    parser.add_argument('--loadData', default=False, action='store_true',
                        help='load samples from samplesDir to DB')
    parser.add_argument('--extractData', default=False, action='store_true',
                        help='extract samples from DB to samplesDir')
    parser.add_argument('--jsonIndent', type=int, default=0, help='json indentation')
    parser.add_argument('--truncateDB', default=False, action='store_true', help='truncate DB before appending')
    parser.add_argument('--keepExisting', default=False, action='store_true',
                        help='keep entries with existing IDs')
    parser.add_argument('--listIDs', action='store_true', help='list IDs')
    parser.add_argument('--deleteData', default=False, action='store_true',
                        help='drop samples from DB')
    parser.add_argument('--byID', help='get and save entry by ID')

    args = parser.parse_args()

    db_file = args.DB
    db = TinyDB(db_file)

    samples_dir = args.samplesDir

    if args.loadData:
        load_samples(db, samples_dir, args.truncateDB, args.keepExisting)

    if args.extractData:
        if args.byID:
            save_sample(db, samples_dir, args.byID, args.jsonIndent)
        else:
            save_samples(db, samples_dir, args.jsonIndent)

    if args.deleteData:
        if args.byID:
            remove_entry(db, args.byID)
        else:
            truncate(db)

    if args.listIDs:
        list_ids(db)

# usage examples:

# load samples to DB
# python3.9 db.py --loadData --DB ./db.json --samplesDir ./samples

# load samples to DB, keep (do not overwrite) DB data if the corresponding ID already exists
# python3.9 db.py --loadData --DB ./db.json --samplesDir ./samples --keepExisting

# load samples to DB, truncate DB before adding new data
#  python3.9 db.py --loadData --DB ./db.json --samplesDir ./samples --truncateDB

# list existing IDs
# python3.9 db.py --listIDs --DB ./db.json

# extract samples from DB
#  python3.9 db.py --extractData --DB ./db.json --samplesDir ./samples2
# or (use indents when dumping jsons):
# python3.9 db.py --extractData --DB ./db.json --samplesDir ./samples2 --jsonIndent 4

# extract data from DB by ID
# python3.9 db.py --extractData --DB ./db.json --byID sample02 --samplesDir ./samples2
# or (use indent when dumping json):
# python3.9 db.py --extractData --DB ./db.json --byID sample02 --samplesDir ./samples2 --jsonIndent 4

# remove data from DB by ID
# python3.9 db.py --deleteData --DB ./db.json --byID sample02

# remove all data from DB
# python3.9 db.py --deleteData --DB ./db.json

if __name__ == '__main__':
    main()


import logging

from .ged import get_inner_html
from .parser2009 import Parser2009
from ..models import elev2010

class Parser2010(Parser2009):
    """Parser for the year 2010 onwards"""

    _logger = logging.getLogger(__name__ + '.' + 'Parser2010')

    Elev = elev2010.Elev

    tr1_cols = (
        None, # Nr. crt.
        None, # Nume... <script>
        None, # Pozitia in ierarhie...
        None, # Pozitia in ierarhie...
        'scoala',
        'judet',
        'promotie_anterioara',
        'forma_invatamant',
        'specializare',
        'd_romana_competente', 'd_romana_scris_nota', 'd_romana_scris_nota_contestatie', 'd_romana_scris_nota_finala',
        'd_limba_materna_nume',
        'd_limba_moderna_nume', 'd_limba_moderna_nota',
        'd_profil_scris_nume',
        'd_alegere_scris_nume',
        'd_competente_digitale',
        None, # LuatDePe_Bac...
        None, # Luat_DePe_Bac...
        )

    tr2_cols = (
        'd_limba_materna_competente', 'd_limba_materna_scris_nota', 'd_limba_materna_scris_nota_contestatie', 'd_limba_materna_scris_nota_finala',
        'd_profil_scris_nota', 'd_profil_scris_nota_contestatie', 'd_profil_scris_nota_finala',
        'd_alegere_scris_nota', 'd_alegere_scris_nota_contestatie', 'd_alegere_scris_nota_finala'
        )

    @classmethod
    def data_from_tr_filter(cls, s):
        return s.replace('&nbsp', '').strip()

    @classmethod
    def get_extra_data_from_tr(cls, tr):
        items = cls.get_luat_de_pe_bacalaureat(tr)
        return {
            'nume': items[0][0].replace('<br>', ''),
            'rezultat_final': items[2][1]}

    @classmethod
    def get_main_table_from_file(cls, f):
        """Return the mainTable table from file f while taking care of all the
        obfuscation and garbage.
        """

        for line in f:
            html = get_inner_html(line)
            if html:
                break
        else:
            return None
        html = html[html.index('<HTML>'):] # remove leading garbage
        return cls.get_main_table_from_html(html)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created in April 2019
@author: Nathan de Lara <nathan.delara@polytechnique.org>
"""
import warnings
from typing import Optional, Union

import numpy as np

def get_values(shape: tuple, values: Union[np.ndarray, dict], default_value: float = -1) -> np.ndarray:
    """Get values as array."""
    n = shape[0]
    if isinstance(values, np.ndarray):
        if len(values) != n:
            raise ValueError('Dimensions mismatch between adjacency and values.')
        else:
            values = values.astype(float)
    elif isinstance(values, dict):
        keys, values_ = np.array(list(values.keys())), np.array(list(values.values()))
        if np.min(values_) < 0:
            warnings.warn(Warning("Negative values will not be taken into account."))
        values = default_value * np.ones(n)
        values[keys] = values_
    else:
        values = np.ones(n)
    return values

def stack_values(shape: tuple, values_row: Optional[Union[np.ndarray, dict]],
                 values_col: Optional[Union[np.ndarray, dict]] = None, default_value: float = -1) -> np.ndarray:
    """Process values for rows and columns and stack the results into a single vector."""
    n_row, n_col = shape
    if values_row is None and values_col is None:
        values_row = np.ones(n_row)
        values_col = default_value * np.ones(n_col)
    elif values_row is None:
        values_row = default_value * np.ones(n_row)
    elif values_col is None:
        values_col = default_value * np.ones(n_col)
    values_row = get_values(shape, values_row, default_value)
    values_col = get_values((n_col,), values_col, default_value)
    return np.hstack((values_row, values_col))

def values2prob(n: int, values: np.ndarray = None) -> np.ndarray:
    """Transform seed values into probability vector.

    Parameters
    ----------
    n : int
        Number of nodes.
    values :
        If ``None``, the uniform distribution is used.
        Otherwise, a non-negative, non-zero vector or a dictionary must be provided.

    Returns
    -------
    probs: np.ndarray
        A probability vector.
    """
    if values is None:
        return np.ones(n) / n
    else:
        values = get_values((n,), values)
        probs = np.zeros_like(values, dtype=float)
        ix = (values > 0)
        probs[ix] = values[ix]
        if probs.sum() > 0:
            return probs / probs.sum()
        else:
            raise ValueError('At least one value must be positive.')


# -*- coding:utf-8 -*-

import csv
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

if __name__=='__main__':
	path = 'Advertising.csv'
	data = pd.read_csv(path)
	x = data[['TV','Radio','Newspaper']]
	y = data['Sales']

	mpl.rcParams['font.sans-serif'] = [u'simHei']
	mpl.rcParams['axes.unicode_minus'] = False

	#绘制1
	# plt.figure(facecolor='w')
	# plt.plot(data['TV'],y,'ro',label='TV')
	# plt.plot(data['Radio'],y,'g^',label='Radio')
	# plt.plot(data['Newspaper'],y,'m*',label='Newspaper')
	# plt.legend(loc='lower right')
	# plt.xlabel(u'广告花费',fontsize=16)
	# plt.ylabel(u'销售额',fontsize=16)
	# plt.title(u'广告花费与销售额对比数据',fontsize=20)
	# plt.grid()
	# plt.show()

	#绘制2
	# plt.figure(facecolor='w',figsize=(9,10))
	# plt.subplot(311)
	# plt.plot(data['TV'],y,'ro')
	# plt.title('TV')
	# plt.grid()
	# plt.subplot(312)
	# plt.plot(data['Radio'],y,'b^')
	# plt.title('Radio')
	# plt.grid()
	# plt.subplot(313)
	# plt.plot(data['Newspaper'],y,'m*')
	# plt.title('Newspaper')
	# plt.grid()
	# plt.tight_layout()
	# plt.show()

	x_train,x_test,y_train,y_test = train_test_split(x,y,train_size=0.7,random_state=1)
	model = LinearRegression()
	model.fit(x_train, y_train)
	# print model
	# print model.intercept_,model.coef_
	order = y_test.argsort(axis=0)
	y_test = y_test.values[order]
	x_test = x_test.values[order,:]
	y_hat = model.predict(x_test)
	#均方误差
	mse = np.average((y_hat - np.array(y_test))**2)
	rmse = np.sqrt(mse)
	# print 'mse:',mse
	# print 'rmse',rmse
	# print 'r2(训练)=',model.score(x_train,y_train)
	# print 'r2(测试)=',model.score(x_test,y_test)

	plt.figure(facecolor='w')
	t = np.arange(len(x_test) )
	# print t
	plt.plot(t,y_test,'r-',linewidth=2,label=u'真实数据')
	plt.plot(t,y_hat,'bo',linewidth=2,label=u'测试数据')
	plt.legend(loc='upper right')
	#b显示网格，默认为true
	plt.grid(b=False)
	plt.show()


import random
import curses
import time

BOARD_WIDTH  = 20
BOARD_HEIGHT = 10
SCORE = 0

def exit_game(stdscr):
    stdscr.clear()
    stdscr.addstr(0, 0, "You lose! Final score: {}. Press 'q' to exit.".format(SCORE))
    # Wait for quit input
    stdscr.nodelay(False)
    while True:
        c = stdscr.getch()
        if c == ord('q'):
            break

def eat_fruit(snake):
    snake.append((snake[-1][0], snake[-1][1])) # Add a new block to the back of the snake
    fruit = [(random.randint(0, BOARD_WIDTH - 1), random.randint(0, BOARD_HEIGHT - 1))] # Spawn a new fruit
    global SCORE
    SCORE += 1   # Increment the score
    return snake, fruit

def move_head(snake, c):
    # Keep track of old head before moving
    old_head = snake[0]
    if c == ord('w'):   # Up
        snake[0] = (snake[0][0], snake[0][1] - 1)
    elif c == ord('a'): # Down
        snake[0] = (snake[0][0] - 1, snake[0][1])
    elif c == ord('s'): # Left
        snake[0] = (snake[0][0], snake[0][1] + 1)
    elif c == ord('d'): # Right
        snake[0] = (snake[0][0] + 1, snake[0][1])
    # Move remainder of the snake, if necessary
    if len(snake) > 1:
        for i in range(1, len(snake)):
            temp = old_head
            old_head = snake[i]
            snake[i] = temp

    return snake

def print_board(stdscr, snake, fruit):
    for i in range(BOARD_HEIGHT + 2):
        stdscr.addstr(i, 0, "\n")
        for j in range(BOARD_WIDTH + 2):
            # Print corners and edges
            if not i or not j:
                stdscr.addstr(i, j, "\u25A0")
            elif i == BOARD_HEIGHT + 2 - 1 or j == BOARD_WIDTH + 2 - 1:
                stdscr.addstr(i, j, "\u25A0")
            # Print middle
            else:
                if (j - 1, i - 1) in snake:
                    stdscr.addstr(i, j, "\u25A3")
                elif (j - 1, i - 1) in fruit:
                    stdscr.addstr(i, j, "\u25C8")
                else:
                    stdscr.addstr(i, j, "\u25A1")
    stdscr.addstr(i, j + 1, "\n")

def main(stdscr):
    # Clear screen
    stdscr.clear()
    random.seed()
    # Randomly generate snake head and fruit
    snake = [(random.randint(0, BOARD_WIDTH - 1), random.randint(0, BOARD_HEIGHT - 1))]
    fruit = snake
    while (fruit == snake): fruit = [(random.randint(0, BOARD_WIDTH - 1), random.randint(0, BOARD_HEIGHT - 1))] # Fruit cannot be on top of snake head
    # Print initial screen
    print_board(stdscr, snake, fruit)
    # Get the first move
    stdscr.nodelay(False)
    c = stdscr.getch()
    heading = c
    # Move the snake
    snake = move_head(snake, c)
    print_board(stdscr, snake, fruit)
    # Game loop
    stdscr.nodelay(True)
    while True:
        # Check for out of bounds or self-hit
        if snake[0][0] == -1 or snake[0][0] == BOARD_WIDTH or snake[0][1] == -1 or snake[0][1] == BOARD_HEIGHT:
            exit_game(stdscr)
            break
        if len(snake) > 1:
            if snake[0] in snake[1:]:
                exit_game(stdscr)
                break
        # Check if fruit eaten
        if snake[0] == fruit[0]:
            snake, fruit = eat_fruit(snake)
        # Field input constantly
        c = stdscr.getch()
        if c in [ord('w'), ord('a'), ord('s'), ord('d')]: # On valid input, change heading
            heading = c
        elif c == ord('q'):                               # On q, quit
            exit_game(stdscr)
            break
        else:
            c = heading                                   # On invalid or no input, keep previous heading
        # Move the snake
        snake = move_head(snake, c)
        print_board(stdscr, snake, fruit)
        # Sleep a bit
        time.sleep(0.25)
if __name__ == '__main__':
    curses.wrapper(main)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Perform Hypermutation analysis based on Hypermut v2.0

@author: Ce Gao
"""

import re
import logging

from Bio import SeqIO
from scipy.stats import fisher_exact

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

def get_pos(pattern, string):
    """Get start position for each pattern match in string
    """
    return set(m.start() for m in re.finditer(pattern, string))

def _hypermut(ref_aln, qry_aln):
    """Perform pairwise hypermut analysis between reference and query seqs

    Parameters
    ----------
    ref_str: str
        reference seq
    qry_str: str
        query seq
    """
    # Too many local variables
    # pylint: disable=R0914

    aln = [(i, j) for i, j in zip(ref_aln, qry_aln) if i != '-' or j != '-']

    ref_str = ''.join(i for i, _ in aln)
    qry_str = ''.join(i for _, i in aln)

    indx_down_mut = get_pos('(?=.[AG][^C])', qry_str)
    indx_down_ctl = get_pos('(?=.([CT].|[AG]C))', qry_str)
    indx_from = get_pos('G', ref_str)
    indx_to = get_pos('A', qry_str)

    mut_pot = indx_from.intersection(indx_down_mut)
    ctl_pot = indx_from.intersection(indx_down_ctl)
    mut = mut_pot.intersection(indx_to)
    ctl = ctl_pot.intersection(indx_to)

    cnt_mut = len(mut)
    cnt_mut_pot = len(mut_pot)
    cnt_ctl = len(ctl)
    cnt_ctl_pot = len(ctl_pot)

    _, pval = fisher_exact([[cnt_mut, cnt_mut_pot - cnt_mut],
                            [cnt_ctl, cnt_ctl_pot - cnt_ctl]],
                           alternative='greater')
    try:
        ratio = (cnt_mut / cnt_mut_pot) / (cnt_ctl / cnt_ctl_pot)
    except ZeroDivisionError:
        ratio = float('Inf')

    psc = 'Yes' if pval < 0.05 else 'No'

    return (cnt_mut, cnt_mut_pot, cnt_ctl, cnt_ctl_pot, ratio, pval, psc)

def _hyper_long(ref, qry, seqs):
    """ hyper

    """
    # Perform hypermut analysis
    ret = _hypermut(str(ref.seq), str(qry.seq))

    seqs.call[qry.id]['hypermut'] = ret[-1]
    seqs.info[qry.id]['hypermut'] = ret[:-1]

def _hyper_drop(file_ref, file_drop, seqs):
    """Hypermutation for those short seqs
    """

    # Check the size of file_drop: stop early if no seqs get dropped
    import os.path

    try:
        f_size = os.path.getsize(file_drop)
    except OSError:
        return

    if f_size == 0:
        return

    # Run HypermutShort
    import tempfile
    fh_out = tempfile.NamedTemporaryFile(delete=False)
    from Bio.Blast.Applications import NcbiblastnCommandline
    cline = NcbiblastnCommandline(out=fh_out.name, query=file_drop,
                                  db=file_ref, outfmt=5,
                                  max_hsps=1, task='blastn')

    cline()
    from Bio.Blast import NCBIXML
    blast_records = NCBIXML.parse(open(fh_out.name))

    for blast_record in blast_records:
        qseqid = blast_record.query
        for aln in blast_record.alignments:
            hsps = aln.hsps[0]
            res = _hypermut(hsps.sbjct, hsps.query)

            seqs.call[qseqid]['hypermut'] = res[-1]
            seqs.info[qseqid]['hypermut'] = res[:-1]

def _write_hyper_summary(seqs, file_out):
    with open(file_out, 'wt') as f_o:
        header = "\t".join(['ID', 'Muts', 'PotenMuts', 'Ctls', 'PotenCtls',
                            'Ratio', 'p', 'Hypermut?'])
        print(header, file=f_o)

        line = "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}"

        for qid in seqs.qids:
            print(line.format(qid, *seqs.info[qid]['hypermut'],
                              seqs.call[qid]['hypermut']),
                  file=f_o)

def hypermut(configs, seqs):
    """Hypermut analysis
    """
    # Logging
    logger.info('Running Hypermut analysis')

    file_aln = configs['file_aln']

    # File name of reference genome, e.g., ref.fasta
    file_ref = configs['file_ref']

    # File name of query seqs, e.g., contig.fasta
    file_seqs_drop = configs['file_seqs_drop']

    # Reference
    recs = SeqIO.parse(file_aln, 'fasta')
    for rec in recs:
        if 'HXB2' in rec.id:
            ref = rec
            break

    recs = SeqIO.parse(file_aln, 'fasta')
    for qry in recs:
        if 'HXB2' in qry.id:
            continue
        _hyper_long(ref, qry, seqs)

    # Run hypermut for long contigs
    for qid in seqs.qids:
        if seqs.call[qid]['is_hiv'] == 'No':
            seqs.call[qid]['hypermut'] = 'Pass'
            seqs.info[qid]['hypermut'] = tuple('Pass' for _ in range(6))

    # Run hypermut for short ones
    _hyper_drop(file_ref, file_seqs_drop, seqs)

    # Write report
    _write_hyper_summary(seqs, configs['file_out'])


# This is my code about functions and parameters in Python

def multiply(factor1, factor2):
    """Return the product of two numbers.

    Keyword arguments:
    factor1 -- the first factor
    factor2 -- the second factor
    """
    return factor1 * factor2

def factorial(n):
    """Recursively return the factorial.

    Keyword arguments:
    n -- the number to take factorial of
    """
    if  n == 1:
        return n
    else:
        return n * factorial(n-1)

def string_split(s):
    """Split and return both halves of a string.

    Keyword arguments:
    s -- the string to split
    """
    midpoint = len(s)//2
    return s[ : midpoint], s[midpoint : ]

def make_multiplier(n):
    """Creates a multiplier.

    Keyword arguments:
    n -- the number to multiply by
    """
    return lambda x: x * n

def f(x):
    """Try to reassign the value of x

    Keyword arguments:
    x -- the original numerical value of x
    """
    x = 2

def swap(A, i, j):
    """Swap the values A[i] and A[j].

    Keyword arguments:
    A -- the array of interest
    i -- the first index
    j -- the second index
    """
    temp = A[i]
    A[i] = A[j]
    A[j] = temp

def average_age_packing(**d):
    """Calculate the average age.

    Keyword arguments:
    **d -- the dictionary to use containing vals of the ages
    """
    sum = 0
    for key, val in d.items():
        sum += val
    return sum/len(d)

def f(a, b, c):
    """Demonstrate argument dictionary unpacking.

    Keyword arguments:
    a, b, c -- anything to print
    """
    print("a unpacked is: ", a)
    print("b unpacked is: ", b)
    print("c unpacked is: ", c)

def main():

    factor1 = 12
    factor2 = 3
    product = multiply(factor1,factor2)
    print("The product of %d and %d is %d." %(factor1, factor2, product))

    n = 4
    fac = factorial(n)
    print("The factorial of %d is %d" %(n, fac))

    s = "Hello."
    (first, second) = string_split(s)
    print("The first half of the string %s is %s and the second half is %s" %(s, first, second))
    t = "Goodbye."
    result = string_split(s)
    print("The two halfs of the string %s is %s" %(t, result))

    mul_by_12 = make_multiplier(12)
    print("Some multiples of 12 are: ", mul_by_12(0), mul_by_12(1), mul_by_12(2))

    A = [1, 2, 3, 4]
    swap(A, 2, 3)
    print("A is: ", A)

    for element in A:
        element = 7
        print("element: %d" %element)
    print("A is: ", A)

    for i in range(len(A)):
        A[i] = 7
        print("i: %d, A[i]: %d" %(i, A[i]))
    print("A is: ", A)

    help(multiply)

    avg_age_packing = average_age_packing(dani=22, johnny=24, bella=6) # Argument dictionary packing
    print("The average calculated with argument dictionary packing is %d." %avg_age_packing)

    dictionary = {'a': 22, 'b': 24, 'c': 6} # Argument dictionary unpacking
    d = {'a': 'foo', 'b': 25, 'c': 'qux'}
    f(**dictionary)

if __name__ == "__main__":
    main()


import sys
from collections import deque
input = sys.stdin.readline

n = int(input())
balloons = deque(enumerate(map(int, input().split())))
result = list()

while balloons:
    x, value = balloons.popleft()
    result.append(x+1)

    if value > 0:
        for _ in range(value-1):
            if len(balloons) != 0:
                balloons.append(balloons.popleft())
    else:
        for _ in range(abs(value)):
            if len(balloons) != 0:
                balloons.appendleft(balloons.pop())

print(*result)


from django.contrib.auth.decorators import login_required
from django.db.models import Sum
from django.shortcuts import render

from apps.parsing.forms import UploadedFileForm
from apps.parsing.models import Train

@login_required
def index(request):
    if request.user.is_authenticated:
        messages = Train.objects.all()
        sum_all_vag = Train.objects.aggregate(Sum("vag_all"))["vag_all__sum"]
        sum_vag_h = Train.objects.aggregate(Sum("vag_h"))["vag_h__sum"]
        sum_vag_l = Train.objects.aggregate(Sum("vag_l"))["vag_l__sum"]
        result = sum_vag_h + sum_vag_l

        return render(request, "parsing/index.html", locals())

def upload(request):
    form_uploaded_files = UploadedFileForm()

    return render(request, "parsing/upload_file_form.html", locals())


lis = []
w = open('data.txt','r')
lis.append(w.read())
lis = lis[0].split("\n\n")

rules, message = [lis[0].split("\n")], [lis[1].split("\n")]
message.pop(-1)

ruledict = {}
for i in range(len(rules)):
    ruledict.update({rules[0][i].split(":")[0],rules[0][i].split(":")[0]})

print(ruledict)


day09 = __import__("day-09")
process = day09.process_gen

car_symbols = ('<', '>', '^', 'v', 'X')

def build_map():
    with open('day-17.txt', 'r') as f:
        text = f.read().strip()
    idata = [int(x) for x in text.split(',')]
    out = ''.join(chr(x) for x in process(idata, []))
    #print(out)
    data = dict()
    lines = out.split('\n')
    for j, line in enumerate(lines):
        for i, ch in enumerate(line):
            if ch == '.':
                continue
            if ch == '#':
                data[(i, j)] = '#'
            if ch in car_symbols:
                data[(i, j)] = ch
    return data

directions = {
    '^': (0, -1),
    'v': (0, 1),
    '>': (1, 0),
    '<': (-1, 0),
}

def find_intersections(data):
    car_pos, car_sym = next((k, v) for k, v in data.items() if v in car_symbols)
    path = set([car_pos])

    while True:
        next_dir = directions[car_sym]
        next_pos = car_pos[0] + next_dir[0], car_pos[1] + next_dir[1]

        if next_pos in data:
            if next_pos in path:
                data[next_pos] = 'O'
            else:
                path.add(next_pos)
            car_pos = next_pos
            if data[car_pos] != 'O':
                data[car_pos] = car_sym
            continue

        for k, v in directions.items():
            next_pos = car_pos[0] + v[0], car_pos[1] + v[1]
            if next_pos in data:
                if next_pos in path:
                    continue
                else:
                    path.add(next_pos)
                car_pos = next_pos
                car_sym = k
                data[car_pos] = car_sym
                break
        else:
            break

rotate = {
    '^': { '<': 'L', '>': 'R' },
    '>': { '^': 'L', 'v': 'R' },
    'v': { '>': 'L', '<': 'R' },
    '<': { 'v': 'L', '^': 'R' },
}

def find_path(data):
    car_pos, car_sym = next((k, v) for k, v in data.items() if v in car_symbols)
    path = list()
    visited = set()

    n = 0
    while True:
        next_dir = directions[car_sym]
        next_pos = car_pos[0] + next_dir[0], car_pos[1] + next_dir[1]

        if next_pos in data:
            visited.add(next_pos)
            n += 1
            car_pos = next_pos
            continue

        for k, v in directions.items():
            next_pos = car_pos[0] + v[0], car_pos[1] + v[1]
            if next_pos in data:
                if next_pos in visited:
                    continue
                else:
                    visited.add(next_pos)
                if n > 0:
                    path.append(n + 1)
                    n = 0
                rl = rotate[car_sym][k]
                path.append(rl)
                car_pos = next_pos
                car_sym = k
                break
        else:
            path.append(n + 1)
            break
    return path

def print_map(data):
    xmin = min(k[0] for k in data.keys())
    xmax = max(k[0] for k in data.keys())
    ymin = min(k[1] for k in data.keys())
    ymax = max(k[1] for k in data.keys())
    for y in range(ymin, ymax + 1):
        for x in range(xmin, xmax + 1):
            ch = data.get((x, y), '.')
            print(ch, end='')
        print()

def test_case1():
    data = build_map()
    find_intersections(data)
    it = (k for k, v in data.items() if v == 'O')
    assert sum(k[0] * k[1] for k in it) == 3608

def test_case2():
    with open('day-17.txt', 'r') as f:
        text = f.read().strip()
    idata = [int(x) for x in text.split(',')]
    idata[0] = 2
    inp = [
        "A,B,A,C,A,B,C,A,B,C",
        "R,8,R,10,R,10",
        "R,4,R,8,R,10,R,12",
        "R,12,R,4,L,12,L,12",
        "n",
        "",
    ]
    inp = '\n'.join(inp)
    inp = [ord(ch) for ch in inp]
    inp.reverse()
    out = [x for x in process(idata, inp)]
    assert out[-1] == 897426

if __name__ == '__main__':
    data = build_map()
    #print_map(data)
    path = find_path(data)
    #print_map(data)
    print(path)


if __name__ == '__main__':
    score_list = []
    record = {}
    for _ in range(int(input())):
        name = input()
        score = float(input())
        record[name] = score
    record = sorted(record.items(),key=lambda x:x[1], reverse=True)
    print(record[-1][0])
    print(record[-2][0])


import click
from datetime import datetime
import numpy as np
from pathlib import Path
from eval_seeds import get_agent

@click.command()
@click.option('--logdir')
@click.option('--l', default=1000)
@click.option('--r', default=2000)
@click.option('--n', default=10)
def eval_cog(logdir: str, l: int, r: int, n: int) -> None:
    ag = get_agent(logdir)
    logdir = Path(logdir)
    save_files = [f for f in logdir.glob('rainy-agent.pth.*')]
    save_files.sort()
    start = datetime.now()
    for i, f in enumerate(save_files):
        ag.load(f)
        rewards = []
        result_file = logdir.joinpath('eval_seeds{}-{}.npy'.format(n, i))
        if result_file.exists():
            continue
        for s in range(l, r):
            ag.config.seed = s
            res = ag.eval_parallel(n=n)
            rewards.append([r.reward for r in res])
        rew = np.array(rewards)
        print('elapsed: ', (datetime.now() - start).total_seconds())
        print('file: {} reward sum: {}'.format(i, rew.sum()))
        np.save(result_file.as_posix(), rew)
    ag.close()

if __name__ == '__main__':
    eval_cog()


import os
import pdb

# filepath1 = "第一次出现的写入的文件名"
# filepath2 = "重复出现的写入文件名"

filepath1 = "/home/fandong/test/name.txt"
filepath2 = "/home/fandong/test/chongfu.txt"

def Traverse(dir):
    arr1 = []
    first_namelist = []
    other_namelist = []

    file1 = open(filepath1, "r+")
    file2 = open(filepath2, "r+")
    for line in file1.readlines():
        name = line.split("/")[-1].replace("\n", "")
        if name:
            arr1.append(name)
    for dirpath, dirnamelist, filenamelist, in os.walk(dir):
        for filename in filenamelist:
            if os.path.splitext(filename)[1] == ".py":
                if filename in arr1:
                    other_namelist.append(dirpath + "/" + filename)
                    continue
                arr1.append(filename)
                first_namelist.append(dirpath + "/" + filename)

    first_namelist = set([line + '\n' for line in first_namelist])
    other_namelist = set([line + '\n' for line in other_namelist])
    file1.writelines(first_namelist)
    file2.writelines(other_namelist)

    file1.close()
    file2.close()

if __name__ == '__main__':
    Traverse("/home/fandong/test")


class Solution:
    def maximumTripletValue(self, nums: List[int]) -> int:
        maxVal = 0
        maxLeft = [nums[0]] * len(nums)
        maxRight = [nums[-1]] * len(nums)

        for i in range(1, len(nums)):
            maxLeft[i] = max(maxLeft[i-1], nums[i])
        for i in range(len(nums)-2, -1, -1):
            maxRight[i] = max(maxRight[i+1], nums[i])

        for i in range(1, len(nums)-1):
            maxVal = max(maxVal, (maxLeft[i-1] - nums[i]) * maxRight[i+1])

        return maxVal


from django.urls import path

from . import views

app_name = 'dbpedia'
urlpatterns = [
    path('', views.index, name='index'),
    path('run_enrich/', views.runEnrich, name='runEnrich'),
    path('get_artists/', views.getMusicalArtists, name='get_artists'),
    path('get_songs/', views.getSongs, name='get_songs'),
    path('get_places/', views.getPlaces, name='get_places'),
    path('get_quiestions/', views.getQuestions, name='get_quiestions'),

]


# Query untuk mendapatkan Data Metrics Destination Ports
# berdasarkan waktu

from pymongo import MongoClient
import time
import datetime
mongoconn = MongoClient('mongodb://192.168.1.100:27017/')
db = mongoconn.fipro
start_ts = time.time()

aggregate = db.logs.aggregate([
    {
        "$match": {
            "identifier": "fb0963921f12",
            "dst_port": {"$ne": None},
            "timestamp": {"$gte": datetime.datetime.today() - datetime.timedelta(weeks=102) }
        }
    },

    {
        "$group": {
            "_id": {
                "dst_port": "$dst_port",
                "date": {
                    "$dateFromParts": {
                        "year": {"$year": {"date": "$timestamp", "timezone": "Asia/Jakarta"}},
                        "month": {"$month": {"date": "$timestamp", "timezone": "Asia/Jakarta"}},
                        "day": {"$dayOfMonth": {"date": "$timestamp", "timezone": "Asia/Jakarta"}}
                    }
                },
                "hour": {"$hour": {"date": "$timestamp", "timezone": "Asia/Jakarta"}},
            },
            "count": {"$sum": 1}
        }
    },

    {
        "$group": {
            "_id": {
                "dst_port": "$_id.dst_port",
                "date": "$_id.date",
            },
            "hourly": {
                "$push": {
                    "$arrayToObject": {
                        "$concatArrays": [
                            [
                                {"k": {"$substr":["$_id.hour",0,-1]}, "v": "$count"}
                            ]
                        ]
                    }
                }
            },
            "counts": {"$sum": "$count"}
        }
    },

    {
        "$project":{
            "_id": 0,
            "port": "$_id.dst_port",
            "date": "$_id.date",
            "hourly": {"$mergeObjects": "$hourly"},
            "counts": 1
        }
    },

    {
        "$sort": {"date": 1, "counts": -1}
    },

    {
        "$out": "honeypot_events_port_timebased_metric"
    }
])
end_ts = time.time()
print (end_ts - start_ts)


# Leetcode practice
# author: orange
# date: 2021/5/27

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

class Solution:
    def mergeTwoLists(self, l1, l2):
        p = l1
        q = l2
        output = ListNode()
        output_Node = output
        while p is not None and q is not None:
            if p.val >= q.val:
                output_Node.next = q
                q = q.next
                output_Node = output_Node.next
            else:
                output_Node.next = p
                p = p.next
                output_Node = output_Node.next
        if p is None:
            output_Node.next = q
        elif q is None:
            output_Node.next = p
        output = output.next
        return output

# 定义链表的操作，一定要记住
list1 = ListNode()    #头指针一直没有改变，只是p一直在滑动，并定义了每一个结点的value
list2 = ListNode()
nums1 = [1,2,4]
nums2 = [1,3,4]

p = list1
for i in range(len(nums1)):
    p.next = ListNode(nums1[i])
    p = p.next
list1 = list1.next

q = list2
for i in range(len(nums2)):
    q.next = ListNode(nums2[i])
    q = q.next
list2 = list2.next

# -----------------------------------------------
example = Solution()
output = example.mergeTwoLists(list1,list2)

p = output
while p is not None:
    print(p.val)
    p = p.next


'''train_utils.py

    Some training utilities.
'''
import torch.optim as optim

def build_optimizer(args, params, weight_decay=0.0):
    filter_fn = filter(lambda p : p.requires_grad, params)
    if args.opt == 'adam':
        optimizer = optim.Adam(filter_fn, lr=args.lr, weight_decay=weight_decay)
    elif args.opt == 'sgd':
        optimizer = optim.SGD(filter_fn, lr=args.lr, momentum=0.95, weight_decay=weight_decay)
    elif args.opt == 'rmsprop':
        optimizer = optim.RMSprop(filter_fn, lr=args.lr, weight_decay=weight_decay)
    elif args.opt == 'adagrad':
        optimizer = optim.Adagrad(filter_fn, lr=args.lr, weight_decay=weight_decay)
    if args.opt_scheduler == 'none':
        return None, optimizer
    elif args.opt_scheduler == 'step':
        scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=args.opt_decay_step, gamma=args.opt_decay_rate)
    elif args.opt_scheduler == 'cos':
        scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=args.opt_restart)
    return scheduler, optimizer


import itertools
import copy

def check_subsequence(sub, arr):
    l = len(sub)
    for i in range(len(arr)-l + 1):
        if arr[i:i+l] == sub:
            return True
    return False

def sprawdz(tab, H, V):
    col = 0
    for i in H:
        col_arr = list(tab[i][col] for i in range(len(V)))
        subs = [1] * i
        if sum(col_arr) != i or check_subsequence(subs, col_arr) == False:
            return None
        col += 1
    row = 0
    for i in V:
        row_arr = tab[row]
        subs = [1] * i
        if sum(row_arr) != i or check_subsequence(subs, row_arr) == False:
            return None
        row += 1

    return tab

def rekursja(tab, H, V, i, rozw):
    if i < len(H) * len(V):
        tab[i//len(H)][i%len(H)] = 0
        a = rekursja(tab, H, V, i+1, rozw)
        tab[i//len(H)][i%len(H)] = 1
        a = rekursja(tab, H, V, i+1, rozw)
    else:
        a = sprawdz(tab, H, V)
        if a != None:
            rozw.append(copy.deepcopy(a))
    return rozw

def shadow(H, V):
    tab = [[0 for _ in range(len(H))] for _ in range(len(V))]
    return rekursja(tab, H, V, 0, [])

def wypisz(H, V, tab):
    for i in H:
        print(i, end="")
    print()
    for i in range(len(tab)):
        for j in range(len(tab[i])):
            print("X" if tab[i][j] == 1 else " ", end="")
        print(V[i])

if __name__ == '__main__':
    H = (1, 1, 1)
    V = (1, 1, 1)
    for i in shadow(H, V):
        wypisz(H,V,i)


# Implementation of Breadth First Search

graph = {
        "5" : ['3','7'],
        "4" : ['5','6'],
        "3" : ['7','8'],
        "7": ['8'],
        "8" : []
        }

visited = []
unvisited = []

def bfs(visited, graph, node):
    visited.append(node)
    unvisited.append(node)

    while unvisited:
        m = unvisited.pop(0)
        print(m)

        for neighbour in graph[m]:
            if neighbour not in visited:
                visited.append(neighbour)
                unvisited.append(neighbour)

bfs(visited, graph, "5")


from telebot import types
from verification.settings.content import *
from verification.src.controller import *
from utils.spider_connectors import *

MAX_MESSAGE_LEN = 32000
en_spider = EnSpiderDB()

# Request menu
correct_btn = types.InlineKeyboardButton(text='\U0001F44D Все верно!', callback_data=CALL_OK)
incorrect_btn = types.InlineKeyboardButton(text='\U0001F41E Есть ошибки...', callback_data=CALL_WRONG)
skip_btn = types.InlineKeyboardButton(text=f'\U0001F945 {SKIP}', callback_data=CALL_SKIP)
db_btn = types.InlineKeyboardButton(text=f'\U0001F50D {DB}', callback_data=CALL_DB)
info_btn = types.InlineKeyboardButton(text=f'\U0001F4D6 {HELP}', callback_data=CALL_INFO)

request_panel = types.InlineKeyboardMarkup(row_width=2)
request_panel.add(correct_btn, incorrect_btn)
request_panel.add(skip_btn, db_btn)
request_panel.add(info_btn)

# IN_PROGRESS_FLUENCY_SOURCE
fluency_source_correct_btn = types.InlineKeyboardButton(text=f'\U0001F44D {OK_TO_FLUENCY_SOURCE}', callback_data=CALL_OK)
fluency_source_incorrect_btn = types.InlineKeyboardButton(text=f'\U0001F41E {WRONG_TO_FLUENCY_SOURCE}', callback_data=CALL_WRONG)
fluency_source_panel = types.InlineKeyboardMarkup(row_width=2)
fluency_source_panel.add(fluency_source_correct_btn, fluency_source_incorrect_btn)
fluency_source_panel.add(skip_btn, db_btn)
fluency_source_panel.add(info_btn)

# IN_PROGRESS_FLUENCY_SUBSTITUTION
fluency_substitution_correct_btn = types.InlineKeyboardButton(text=f'\U0001F44D {OK_TO_FLUENCY_SUBSTITUTION}', callback_data=CALL_OK)
fluency_substitution_incorrect_btn = types.InlineKeyboardButton(text=f'\U0001F41E {WRONG_TO_FLUENCY_SUBSTITUTION}', callback_data=CALL_WRONG)
fluency_substitution_panel = types.InlineKeyboardMarkup(row_width=2)
fluency_substitution_panel.add(fluency_substitution_correct_btn, fluency_substitution_incorrect_btn)
fluency_substitution_panel.add(skip_btn, db_btn)
fluency_substitution_panel.add(info_btn)

# IN_PROGRESS_EQUIVALENT
equivalent_correct_btn = types.InlineKeyboardButton(text=f'\U0001F44D {OK_TO_EQV}', callback_data=CALL_OK)
equivalent_incorrect_btn = types.InlineKeyboardButton(text=f'\U0001F41E {WRONG_TO_EQV}', callback_data=CALL_WRONG)
equivalent_panel = types.InlineKeyboardMarkup(row_width=2)
equivalent_panel.add(equivalent_correct_btn, equivalent_incorrect_btn)
equivalent_panel.add(skip_btn, db_btn)
equivalent_panel.add(info_btn)

# SQL_PANEL
sql_correct_btn = types.InlineKeyboardButton(text=f'\U0001F44D {OK_TO_SQL}', callback_data=CALL_OK)
sql_incorrect_btn = types.InlineKeyboardButton(text=f'\U0001F41E {WRONG_TO_SQL}', callback_data=CALL_WRONG)
sql_panel = types.InlineKeyboardMarkup(row_width=2)
sql_panel.add(sql_correct_btn, sql_incorrect_btn)
sql_panel.add(skip_btn, db_btn)
sql_panel.add(info_btn)

# Correction fluency error
error_fluency_source_panel = types.InlineKeyboardMarkup(row_width=2)
error_fluency_source_panel.add(skip_btn, db_btn)
error_fluency_source_panel.add(info_btn)

# Correction fluency substitution error
error_fluency_substitution_panel = types.InlineKeyboardMarkup(row_width=2)
error_fluency_substitution_panel.add(skip_btn, db_btn)
error_fluency_substitution_panel.add(info_btn)

# Correction equivalent error
error_equivalent_panel = types.InlineKeyboardMarkup(row_width=2)
error_equivalent_panel.add(skip_btn, db_btn)
error_equivalent_panel.add(info_btn)

# Correction SQL error
error_sql_panel = types.InlineKeyboardMarkup(row_width=2)
error_sql_panel.add(skip_btn, db_btn)
error_sql_panel.add(info_btn)

# Info menu
estimate_btn = types.InlineKeyboardButton(text='Перейти к оцениванию', callback_data=ESTIMATE)
info_panel = types.InlineKeyboardMarkup(row_width=1)
info_panel.add(estimate_btn)

# In progress info panel
return_btn = types.InlineKeyboardButton(text='\U0001F519 Вернуться к оцениванию', callback_data=RETURN)
in_progress_info_panel = types.InlineKeyboardMarkup(row_width=1)
in_progress_info_panel.add(return_btn)

# Error menu
error_btn = types.InlineKeyboardButton(text='Следующий запрос', callback_data='estimate')
error_panel = types.InlineKeyboardMarkup(row_width=2)
error_panel.add(estimate_btn, info_btn)

# Other details
back_to_estimation_btn = types.InlineKeyboardButton(text='\U0001F519 Вернуться к оцениванию', callback_data='back_to_estimation')
back_to_tables_btn = types.InlineKeyboardButton(text='\U0001F5C2 Список таблиц', callback_data='back_to_tables')

# Empty
empty_panel = types.InlineKeyboardMarkup()

# Choosing tables
def generate_tables_panel(sample: BotSample) -> types.InlineKeyboardMarkup:
    tables = en_spider.get_db_tables(sample.db)
    buttons = []
    for table_title in tables:
        new_btn = types.InlineKeyboardButton(text=f'\U0001F4C3 {table_title}', callback_data=f'{TABLE}#{table_title}')
        buttons.append(new_btn)
    tables_panel = types.InlineKeyboardMarkup(row_width=2)
    for left_btn, right_btn in zip(buttons[::2], buttons[1::2]):
        tables_panel.add(left_btn, right_btn)
    tables_panel.add(return_btn)
    return tables_panel

# Choosing columns
return_to_main_btn = types.InlineKeyboardButton(text='\U0001F519 Вернуться к оцениванию', callback_data=RETURN)
return_to_tables_btn = types.InlineKeyboardButton(text=f'\U0001F5C2 Список таблиц', callback_data=RETURN_TO_TABLES)
view_panel = types.InlineKeyboardMarkup(row_width=1)
view_panel.add(return_to_tables_btn)
view_panel.add(return_to_main_btn)


import os
import asyncio
import aiohttp_jinja2
import jinja2
from aiofauna import *
from aiohttp_sse import sse_response
from aiohttp import web

FAUNA_SECRET = os.environ.get("FAUNA_SECRET")

@aiohttp_jinja2.template("index.j2")
async def index_handler(request: Request) -> Response:
    """Index handler."""

    return {"chart_type": "line"}

async def sse_handler(request: Request) -> Response:
    """SSE handler."""
    async with sse_response(request) as resp:
        print(resp.headers)
        while True:
            _ = (await Client(os.environ.get(FAUNA_SECRET)).query(q.now()))["@ts"] # type: ignore
            await resp.send(_)
            await asyncio.sleep(1)

app = Application()

# Add routes

app.router.add_get("/", index_handler)

app.router.add_get("/api/latency", sse_handler)

app.router.add_static("/static", "static", show_index=True)

jinja2_env = aiohttp_jinja2.setup(
    app,
    loader=jinja2.FileSystemLoader("templates"),
    enable_async=True,
)

jinja2_env.variable_start_string = "@{"
jinja2_env.variable_end_string = "}"

if __name__ == "__main__":
    web.run_app(app, port=8080)