"""Line Drawing Algorithms (2D)"""
import math
from typing import List, Tuple

def bresenham(x1: int, y1: int, x2: int, y2: int) -> List[Tuple[int, int]]:
    """Breshenham's line algorithm - 2D version."""
    result = [(x1, y1)]

    dx, dy = abs(x2 - x1), abs(y2 - y1)
    x_inc, y_inc = 1, 1
    x, y = x1, y1

    if x2 < x1:
        x_inc = -1
    if y2 < y1:
        y_inc = -1

    # Y-primary
    if dy > dx:
        tx = 2 * dx - dy

        for _ in range(dy):
            y += y_inc
            if tx >= 0:
                x += x_inc
                tx -= 2 * dy
            tx += 2 * dx

            result.append((x, y))

    # X-primary
    else:
        ty = 2 * dy - dx

        for _ in range(dx):
            x += x_inc
            if ty >= 0:
                y += y_inc
                ty -= 2 * dx
            ty += 2 * dy

            result.append((x, y))

    return result

def bresenham_full(x1: int, y1: int, x2: int, y2: int) -> List[Tuple[int, int]]:
    """Breshenham's line algorithm - 2D version that gets all tiles touched.

    `tx`, `ty` indicate full tile distance; `hx`, `hy` indicate half tile distance.
    """
    result = [(x1, y1)]

    dx, dy = abs(x2 - x1), abs(y2 - y1)
    x_inc, y_inc = 1, 1
    x, y = x1, y1

    if x2 < x1:
        x_inc = -1
    if y2 < y1:
        y_inc = -1

    # Y-primary
    if dy > dx:
        tx = 2 * dx - dy

        for _ in range(dy):
            y += y_inc
            hx = tx - dx

            if hx >= 0:
                result.append((x + x_inc, y - y_inc))
            if hx <= 0:
                result.append((x, y))
            if tx > 0:
                x += x_inc
                tx -= 2 * dy
                result.append((x, y))
            tx += 2 * dx

    # X-primary
    else:
        ty = 2 * dy - dx

        for _ in range(dx):
            x += x_inc
            hy = ty - dy

            if hy >= 0:
                result.append((x - x_inc, y + y_inc))
            if hy <= 0:
                result.append((x, y))
            if ty > 0:
                y += y_inc
                ty -= 2 * dx
                result.append((x, y))
            ty += 2 * dy

    return result

def fire_line(xi: float, yi: float, x2: int, y2: int) -> List[Tuple[int, int]]:
    """Returns all tiles touched from source tile to slope range of target tile.

    - `x1`, `y1` represent the source tile.
    - `x2`, `y2` represent the target tile.
    - `xi`, `yi` are starting floating point values.
    - `xf`, `yf` are ending floating point values.
    - `xs`, `ys` are x/y floating point shifts within source cell, normally `0.5`.
      If `xs = 0.5` and `ys = 0.5`, the fire line starts from XY center of cell.
      These can represent weapon/tool projections from the body (e.g. a gun barrel).
    - `d(x,y)_start`, `d(x,y)_end` are starting / ending range indexes.

    Fire line spans angle range beween lines `AB` and `AC`:
    ```none
            xi                          xf
    +----+----+                     B----+----+
    |       A |yi                   |         |
    |         |                     |    +    | yf
    |         |                     |         |
    +----+----+                     +----+----C
        src                             tgt
    (x1, y1)                    (x2, y2)
    ```

    Example fire lines:
    ```none

              ++T
             ++++                  S++++T
            S++

    (0.5, 0.5) to (4, 2)    (0.5, 0.5) to (5, 0)
    ```

    Y, X order of calculation is for optimum locality when selecting cells
    from the map, which are arranged in YX order.

    NOTE: assumes all values are positive and in-bounds.
    NOTE: to avoid dividing by zero, xs or ys should never be 0.0 or 1.0.
    """
    x1, y1 = int(xi), int(yi)
    xs, ys = xi - x1, yi - y1
    xf, yf = x2 + 0.5, y2 + 0.5
    cx, cy = abs(x2 - x1), abs(y2 - y1)
    dx, dy = abs(xf - xi), abs(yf - yi)
    dx_max, dy_max = cx + 1, cy + 1
    x_inc = 1 if x2 > x1 else -1
    y_inc = 1 if y2 > y1 else -1
    m = 0.000001

    if xf < xi:
        x_inc = -1
        xs = math.ceil(xi) - xi
    if yf < yi:
        y_inc = -1
        ys = math.ceil(yi) - yi

    result = []

    if cx == 0:
        return [(x1, y1 + y_inc * i) for i in range(dy_max)]
    if cy == 0:
        return [(x1 + x_inc * i, y1) for i in range(dx_max)]

    dxdy_lo = (dx - 0.5) / (dy + 0.5)
    dxdy_hi = (dx + 0.5) / (dy - 0.5)
    dx_lo_ref = xs - (dxdy_lo * ys)
    dx_hi_ref = xs + (dxdy_hi * (1.0 - ys))
    y = y1

    for y_ix in range(dy_max):
        dx_lo = dx_lo_ref + dxdy_lo * y_ix
        dx_hi = dx_hi_ref + dxdy_hi * y_ix
        dx_start = max(math.floor(dx_lo - m), 0)
        dx_end = min(math.ceil(dx_hi + m), dx_max)
        x = x1 + x_inc * dx_start

        for _ in range(dx_start, dx_end):
            result.append((x, y))
            x += x_inc

        dx_lo += dxdy_lo
        dx_hi += dxdy_hi
        y += y_inc

    return result

#   ########  ########   ######   ########
#      ##     ##        ##           ##
#      ##     ######     ######      ##
#      ##     ##              ##     ##
#      ##     ########  #######      ##

def test_bresenham_2D_reciprocal():
    """Checks if 2D bresenham lines are reciprocal."""
    suite = [(int(0), int(0), x, y) for x in range(0, 5) for y in range(-5, 5)]
    suite.extend([(x, y, 0, 0) for x in range(0, 5) for y in range(-5, 5)])

    for x1, y1, x2, y2 in suite:
        fwd = bresenham(x1, y1, x2, y2)
        rev = bresenham(x2, y2, x1, y1)
        assert sorted(fwd) == sorted(rev)

def test_bresenham_2D_full():
    """Check expected values for the `bresenham_full()` 2D function."""
    suite = [
        (0, 0, 5, 0),
        (0, 0, -5, 0),
        (0, 0, 0, 5),
        (0, 0, 0, -5),
        (5, 0, 0, 0),
        (-5, 0, 0, 0),
        (0, 5, 0, 0),
        (0, -5, 0, 0),
        (0, 0, 2, 2),
        (2, 2, 0, 0),
        (0, 0, 4, 2),
        (4, 2, 0, 0),
    ]
    expected = [
        [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0)],
        [(0, 0), (-1, 0), (-2, 0), (-3, 0), (-4, 0), (-5, 0)],
        [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)],
        [(0, 0), (0, -1), (0, -2), (0, -3), (0, -4), (0, -5)],
        [(5, 0), (4, 0), (3, 0), (2, 0), (1, 0), (0, 0)],
        [(-5, 0), (-4, 0), (-3, 0), (-2, 0), (-1, 0), (0, 0)],
        [(0, 5), (0, 4), (0, 3), (0, 2), (0, 1), (0, 0)],
        [(0, -5), (0, -4), (0, -3), (0, -2), (0, -1), (0, 0)],
        [(0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (2, 1), (2, 2)],
        [(2, 2), (2, 1), (1, 2), (1, 1), (1, 0), (0, 1), (0, 0)],
        [(0, 0), (1, 0), (1, 1), (2, 1), (3, 1), (3, 2), (4, 2)],
        [(4, 2), (3, 2), (3, 1), (2, 1), (1, 1), (1, 0), (0, 0)],
    ]
    actual = [bresenham_full(*coords) for coords in suite]
    for i, e in enumerate(expected):
        assert actual[i] == e


def rightRotation(arr, rotateRight):
    final = []
    final.extend(arr[rotateRight:])
    final.extend(arr[:rotateRight])
    print(*final)

def leftRotation(arr, rotateLeft):
    final = []
    final.extend(arr[rotateLeft:])
    final.extend(arr[:rotateLeft])
    print(*final)

if __name__ == '__main__':
    arr = input("Enter the terms separated by space:\t").split(" ")
    rotateLeft = int(input("Enter How Many Times to Rotate Left:\t"))
    rotateRight = int(input("Enter How Many Times to Rotate Right:\t"))
    arr = [int(x) for x in arr]

    leftRotation(arr, rotateLeft)
    rightRotation(arr, rotateRight)


"""
    This is the home function for the app
"""

import os
from functools import cache

from flask import Flask
from redis import Redis, RedisError

app = Flask(__name__)
# redis = Redis()

def connect_to_redis():
    """
    Connects to the Redis server
    """
    return Redis.from_url(os.getenv("REDIS_URL", "redis://redis:6379"))  # Using the service name 'redis'

@app.get("/")
def home():
    """
        The home function, returns the view count of the page.
    """
    try:
        page_count = connect_to_redis().incr("page_count")
    except RedisError:
        app.logger.exception("Redis error")
        return "Sorry, something went wrong \N{pensive face}", 500
    times = "times" if page_count > 1 else "time"
    return f"This page has been viewed {page_count} {times}"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)


"""
Retrieves
history
data
for a given numeric (either int or float) item_id
"""

from pyzabbix import ZabbixAPI
from datetime import datetime
import time
import my_sort

class zabbix_api:
    def __init__(self, zabbix_server, zabbix_user, zabbix_passwd):
        # The hostname at which the Zabbix web interface is available
        self.zapi = ZabbixAPI(zabbix_server)
        # Login to the Zabbix API
        self.zapi.login(zabbix_user, zabbix_passwd)

    def trend_get(self, itemID='', time_from='', time_till=''):
        '''
        内部函数
        输出一段时间内的某个item的最大值、平均值、最小值
        '''
        trend_min_data = []
        trend_max_data = []
        trend_avg_data = []
        trend_min_data[:] = []
        trend_max_data[:] = []
        trend_avg_data[:] = []
        response = self.zapi.trend.get(
            time_from=time_from,
            time_till=time_till,
            output=[
                "itemid",
                "clock",
                "num",
                "value_min",
                "value_avg",
                "value_max"
            ],
            itemids=itemID,
            limit="8760"
        )
        if len(response) == 0:
            return 0.0, 0.0, 0.0
        for result_info in response:
            trend_min_data.append(result_info['value_min'])
            trend_max_data.append(result_info['value_max'])
            trend_avg_data.append(result_info['value_avg'])
        trend_min_data_all = my_sort.Stats(trend_min_data)
        trend_max_data_all = my_sort.Stats(trend_max_data)
        trend_avg_data_all = my_sort.Stats(trend_avg_data)
        trend_min = trend_min_data_all.min()
        trend_max = trend_max_data_all.max()
        trend_avg = float('%0.4f' % trend_avg_data_all.avg())

        return (trend_min, trend_max, trend_avg)

zabbix_server = 'http://58.215.175.200/zabbix/'
zabbix_user = 'admin'
zabbix_passwd = '*********'
output_file = "./server_info.txt"

# Create a time range
time_till = time.mktime(datetime.now().timetuple())
time_from = time_till - 60 * 60 * 24 * 7  # last 4 hours
zabbix = zabbix_api(zabbix_server, zabbix_user, zabbix_passwd)
current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
count = 0

net_if_in_keylist = ['net.if.in[eth0]', 'net.if.in[eth1]', 'net.if.in[eth2]', 'net.if.in[eth3]',
                  'net.if.in[em1]', 'net.if.in[em2]', 'net.if.in[em3]', 'net.if.in[em4]',
                  'net.if.in[vnet1]', 'net.if.in[em2]', 'net.if.in[em3]', 'net.if.in[em4]',
                  'net.if.in[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #1]',
                  'net.if.in[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #2]',
                  'net.if.in[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #3]',
                  'net.if.in[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #4]',
                  'net.if.in[Broadcom NetXtreme Gigabit Ethernet]',
                  'net.if.in[Broadcom NetXtreme Gigabit Ethernet #2]',
                  'net.if.in[Broadcom NetXtreme Gigabit Ethernet #3]'
                  'net.if.in[Broadcom NetXtreme Gigabit Ethernet #4]']

net_if_out_keylist = ['net.if.out[eth0]', 'net.if.out[eth1]', 'net.if.out[eth2]', 'net.if.out[eth3]',
                   'net.if.out[em1]', 'net.if.out[em2]', 'net.if.out[em3]', 'net.if.out[em4]',
                   'net.if.out[vnet1]', 'net.if.out[em2]', 'net.if.out[em3]', 'net.if.out[em4]',
                   'net.if.out[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #1]',
                   'net.if.out[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #2]',
                   'net.if.out[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #3]',
                   'net.if.out[Broadcom BCM5716C NetXtreme II GigE (NDIS VBD Client) #4]',
                   'net.if.out[Broadcom NetXtreme Gigabit Ethernet]',
                   'net.if.out[Broadcom NetXtreme Gigabit Ethernet #2]',
                   'net.if.out[Broadcom NetXtreme Gigabit Ethernet #3]'
                   'net.if.out[Broadcom NetXtreme Gigabit Ethernet #4]']

disk_total_key_list = ['vfs.fs.size[C:,total]','vfs.fs.size[D:,total]','vfs.fs.size[E:,total]','vfs.fs.size[F:,total]',
                        'vfs.fs.size[/qingkedata1,total]','vfs.fs.size[/qingkedata2,total]','vfs.fs.size[/qingkedata3,total]',
                       'vfs.fs.size[/qingke,total]','vfs.fs.size[/,total]']

disk_free_key_list = ['vfs.fs.size[C:,free]','vfs.fs.size[D:,free]','vfs.fs.size[E:,free]','vfs.fs.size[F:,free]',
                        'vfs.fs.size[/qingkedata1,free]','vfs.fs.size[/qingkedata2,free]','vfs.fs.size[/qingkedata3,free]',
                       'vfs.fs.size[/qingke,free]','vfs.fs.size[/,free]']

with open(output_file, 'w+') as f:
    f.write("当前时间：{}\n".format(current_time))
    for h in zabbix.zapi.host.get(filter={"status": "0", "available": "1", "flags": "0"}):

        os = ""
        mem_total, mem_free = 0,0
        cpu_num, cpu_load = 0,0
        net_in_map, net_out_map = {}, {}
        disk_total, disk_free = 0,0

        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': ['system.uname']},
                                      output=["lastvalue", ""]):
            os = i["lastvalue"]
        # memory total
        for i in zabbix.zapi.item.get(hostids=h['hostid'], filter={'key_': ['vm.memory.size[total]', ]},
                                      output=["lastvalue", ""]):
            mem_total = int(i["lastvalue"])

        # memory free
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': ['vm.memory.size[free]', 'vm.memory.size[available]']},
                                      output=["itemid", ""]):
            tmp = zabbix.trend_get(itemID=i["itemid"], time_from=time_from, time_till=time_till)
            mem_free = int(tmp[0])

        # cpu number
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': ['system.cpu.num']},
                                      output=["lastvalue", ""]):
            cpu_num = int(i["lastvalue"])

        # cpu load
        cpu_load_key = ['system.cpu.load[percpu,avg1]'] if os.find("Linux") != -1 else ['perf_counter[\Processor(_Total)\% Processor Time]']
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': cpu_load_key},
                                      output=["itemid", ""]):
            tmp = zabbix.trend_get(itemID=i["itemid"], time_from=time_from, time_till=time_till)
            cpu_load = float(tmp[1])
        # disk total
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': disk_total_key_list},
                                      output=["lastvalue", ""]):
            disk_total += int(i["lastvalue"])

        # disk free
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': disk_free_key_list},
                                      output=["lastvalue", ""]):
            disk_free += int(i['lastvalue'])

        # net_inf in
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': net_if_in_keylist},
                                      output=["itemid", ""]):
            tmp = zabbix.trend_get(itemID=i["itemid"], time_from=time_from, time_till=time_till)
            if net_in_map:
                if tmp[1] > net_in_map['max']:
                    net_in_map['max'] = int(tmp[1])
                    net_in_map['min'] = int(tmp[0])
                    net_in_map['avg'] = int(tmp[2])
            else:
                net_in_map['max'] = int(tmp[1])
                net_in_map['min'] = int(tmp[0])
                net_in_map['avg'] = int(tmp[2])

        # net_if out
        for i in zabbix.zapi.item.get(hostids=h['hostid'],
                                      filter={'key_': net_if_out_keylist},
                                      output=["itemid", ""]):
            tmp = zabbix.trend_get(itemID=i["itemid"], time_from=time_from, time_till=time_till)
            if net_out_map:
                if tmp[1] > net_out_map['max']:
                    net_out_map['max'] = int(tmp[1])
                    net_out_map['min'] = int(tmp[0])
                    net_out_map['avg'] = int(tmp[2])
            else:
                net_out_map['max'] = int(tmp[1])
                net_out_map['min'] = int(tmp[0])
                net_out_map['avg'] = int(tmp[2])

        disk_total = int(disk_total) // (1024 * 1024 * 1024)
        disk_free = int(disk_free) // (1024 * 1024 * 1024)

        mem_total //= (1024 * 1024* 1024)
        mem_free //= (1024 * 1024* 1024)

        cpu_load = "{:.2f}".format(cpu_load*cpu_num) if os.find("Linux") != -1 else "{:.2f}%".format(cpu_load)

        net_in_max = net_in_map['max'] / (1024 * 1024) if net_in_map else 0
        net_in_min = net_in_map['min'] / (1024 * 1024) if net_in_map else 0
        net_in_avg = net_in_map['avg'] / (1024 * 1024) if net_in_map else 0

        net_out_max = net_out_map['max'] / (1024 * 1024) if net_out_map else 0
        net_out_min = net_out_map['min'] / (1024 * 1024) if net_out_map else 0
        net_out_avg = net_out_map['avg'] / (1024 * 1024) if net_out_map else 0

        count += 1

        print("{}服务器信息：".format(h['name']))
        print("磁盘：共{}G、用{}G、剩余{}G".format(disk_total, disk_total - disk_free, disk_free))
        print("内存：共{}G、使用峰值{}G".format(mem_total, mem_total - mem_free, mem_free))
        print("cpu_load_list：{}核，负载峰值{}".format(cpu_num,cpu_load))
        print("in-network:最高{:.2f}Mbps、最低{:.2f}Mbs、平均{:.2f}Mbs".format(net_in_max, net_in_min, net_in_avg))
        print("out-network:最高{:.2f}Mbps、最低{:.2f}Mbs、平均{:.2f}Mbs".format(net_out_max, net_out_min, net_out_avg))
        print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")

        f.write("{}服务器信息：\n".format(h['name']))
        f.write("磁盘：共{}G、用{}G、剩余{}G\n".format(disk_total, disk_total - disk_free, disk_free))
        f.write("内存：共{}G、使用峰值{}G\n".format(mem_total, mem_total - mem_free, mem_free))
        f.write("cpu_load_list：{}核，负载峰值{}\n".format(cpu_num,cpu_load))
        f.write("in-network:最高{:.2f}Mbps、最低{:.2f}Mbs、平均{:.2f}Mbs\n".format(net_in_max, net_in_min, net_in_avg))
        f.write("out-network:最高{:.2f}Mbps、最低{:.2f}Mbs、平均{:.2f}Mbs\n".format(net_out_max, net_out_min, net_out_avg))
        f.write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")
    print("共{}服务器".format(count))
    f.write("共{}服务器".format(count))


import os
import platform
from distutils.errors import CCompilerError
from distutils.errors import DistutilsExecError
from distutils.errors import DistutilsPlatformError

from setuptools import Extension
from setuptools import setup
from setuptools.command.build_ext import build_ext

class optional_build_ext(build_ext):
    """This class subclasses build_ext and allows
       the building of C extensions to fail.
    """

    def run(self):
        try:
            build_ext.run(self)
        except DistutilsPlatformError as e:
            self._unavailable(e)

    def build_extension(self, ext):
        try:
            build_ext.build_extension(self, ext)
        except (CCompilerError, DistutilsExecError, OSError) as e:
            self._unavailable(e)

    def _unavailable(self, e):
        print('*' * 80)
        print("""WARNING:
        An optional code optimization (C extension) could not be compiled.
        Optimizations for this package will not be available!""")
        print()
        print(e)
        print('*' * 80)

def read(*rnames):
    with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
        return f.read()

codeoptimization = [
    Extension(
        "zope.proxy._zope_proxy_proxy",
        [os.path.join('src', 'zope', 'proxy', "_zope_proxy_proxy.c")],
    ),
]

# PyPy won't build the extension.
is_pypy = platform.python_implementation() == 'PyPy'
if is_pypy:
    ext_modules = []
    headers = []
else:
    ext_modules = codeoptimization
    headers = [os.path.join('src', 'zope', 'proxy', 'proxy.h')]

setup(name='zope.proxy',
      version='5.2.dev0',
      author='Zope Foundation and Contributors',
      author_email='zope-dev@zope.org',
      description='Generic Transparent Proxies',
      long_description=(
          read('README.rst')
          + '\n\n' +
          read('CHANGES.rst')
      ),
      url='http://github.com/zopefoundation/zope.proxy',
      project_urls={
        'Documentation': 'https://zopeproxy.readthedocs.io',
        'Issue Tracker': 'https://github.com/zopefoundation/zope.proxy/issues',
        'Sources': 'https://github.com/zopefoundation/zope.proxy',
      },
      license='ZPL 2.1',
      classifiers=[
          'Development Status :: 5 - Production/Stable',
          'Intended Audience :: Developers',
          'License :: OSI Approved :: Zope Public License',
          'Programming Language :: Python',
          'Programming Language :: Python :: 3',
          'Programming Language :: Python :: 3.7',
          'Programming Language :: Python :: 3.8',
          'Programming Language :: Python :: 3.9',
          'Programming Language :: Python :: 3.10',
          'Programming Language :: Python :: 3.11',
          'Programming Language :: Python :: 3.12',
          'Programming Language :: Python :: Implementation :: CPython',
          'Programming Language :: Python :: Implementation :: PyPy',
          'Framework :: Zope :: 3',
          'Natural Language :: English',
          'Operating System :: OS Independent',
      ],
      keywords='proxy generic transparent',
      packages=['zope', 'zope.proxy'],
      package_dir={'': 'src'},
      namespace_packages=['zope'],
      cmdclass={
          'build_ext': optional_build_ext,
      },
      headers=headers,
      ext_modules=ext_modules,
      python_requires='>=3.7',
      install_requires=[
          'zope.interface',
          'setuptools',
      ],
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'test': [
              'zope.security',  # We have a circular dependency for testing
              'zope.testrunner',
          ],
          'docs': [
              'Sphinx',
              'repoze.sphinx.autointerface',
              'sphinx_rtd_theme',
          ],
      },
      )


# this function checks whether or not the given number is a prime number

def check_prime_num():

    num = int(input())

    count = 0

    for i in range(1, num+1):
        if num%i == 0:
            count += 1

    if count <=2:
        print(num, ' is a prime number')
    else:
        print('This number: ', num, ' is not a prime number')

if __name__ == '__main__':
    check_prime_num()


import sys,os
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(current_dir, '../'))

from coincheck.account import Account
from coincheck import settings

def test_get_info():
    a1 = Account(access_key=settings.access_key, secret_key=settings.secret_key)
    return a1.get_info()

def test_get_balance():
    a1 = Account(access_key=settings.access_key, secret_key=settings.secret_key)
    return a1.get_balance()

if __name__ == '__main__':
    test_get_info()
    test_get_balance()


import zipfile
import os
import requests
import argparse

from tqdm import tqdm

parser = argparse.ArgumentParser(description='Download From Google Drive helper')
parser.add_argument('--path', type=str, default='./')

def download_file_from_google_drive(id, destination):
    URL = "https://docs.google.com/uc?export=download"
    session = requests.Session()

    response = session.get(URL, params={'id': id}, stream=True)
    token = get_confirm_token(response)

    if token:
        params = {'id': id, 'confirm': token}
        response = session.get(URL, params=params, stream=True)

    save_response_content(response, destination)

def get_confirm_token(response):
    for key, value in response.cookies.items():
        if key.startswith('download_warning'):
            return value
    return None

def save_response_content(response, destination, chunk_size=32 * 1024):
    total_size = int(response.headers.get('content-length', 0))
    with open(destination, "wb") as f:
        for chunk in tqdm(
                response.iter_content(chunk_size),
                total=total_size,
                unit='B',
                unit_scale=True,
                desc=destination):
            if chunk:  # filter out keep-alive new chunks
                f.write(chunk)

if __name__ == '__main__':
    args = parser.parse_args()
    dirpath = args.path
    os.makedirs(dirpath, exist_ok=True)

    filenames = [
        'deltas00000.zip', 'deltas01000.zip'
    ]

    drive_ids = [
        '0B4qLcYyJmiz0TXdaTExNcW03ejA', '0B4qLcYyJmiz0TjAwOTRBVmRKRzQ'
    ]

    for filename, drive_id in zip(filenames, drive_ids):
        print('Deal with file: ' + filename)
        save_path = os.path.join(dirpath, filename)

        if os.path.exists(save_path):
            print('[*] {} already exists'.format(save_path))
        else:
            download_file_from_google_drive(drive_id, save_path)


import re
import collections

coord_to_erosion = {}

def calc_erosion(x, y):
    pos = (x,y)
    if pos in coord_to_erosion:
        return coord_to_erosion[pos]

    if x == 0 and y == 0 or x == target_x and y == target_y:
        geo_id = 0
    elif y == 0:
        geo_id = x * 16807
    elif x == 0:
        geo_id = y * 48271
    else:
        geo_id = calc_erosion(x, y - 1) * calc_erosion(x - 1, y)

    erosion = ((geo_id + depth) % 20183)
    coord_to_erosion[pos] = erosion
    return erosion

f = open("input22.txt", "r")

depth = int(re.search(r'\d+', f.readline())[0])
target_x, target_y = map(int, re.findall(r'\d+', f.readline()))

# part1
risk = 0
for x in range(target_x + 1):
    for y in range(target_y + 1):
        risk += calc_erosion(x, y) % 3
print(risk)

# part2, greedy best first search, really slow :(
# I'll at least do A* next time, promise :>
Node = collections.namedtuple('Node', ['x', 'y', 'tool'])

def compute_neighbors(node):
    temp = [(1,0), (0,1)]
    if node.x > 0:
        temp.append((-1, 0))
    if node.y > 0:
        temp.append((0, -1))

    neighbors = []
    for xi, yi in temp:
        # for target node we must use the torch
        if node.x + xi == target_x and node.y + yi == target_y:
            next_tool = 1
        else:
            neighbore_type = calc_erosion(node.x + xi, node.y + yi) % 3
            if node.tool != neighbore_type:
                next_tool = node.tool
            else:
                curr_type = calc_erosion(node.x, node.y) % 3
                next_tool = 3 - curr_type - neighbore_type

        neighbors.append(Node(node.x + xi, node.y + yi, next_tool))

    return neighbors

def shortest_path(tar_x, tar_y):
    start = Node(0, 0, 1)
    nodes_to_travel_time = {start : 0}
    open_nodes = [start]
    while open_nodes:
        curr = min(open_nodes, key=lambda node: nodes_to_travel_time[node])
        if curr.x == tar_x and curr.y == tar_y:
            return nodes_to_travel_time[curr]

        open_nodes.remove(curr)

        for n in compute_neighbors(curr):
            if n not in nodes_to_travel_time:
                open_nodes.append(n)

            alt_travel_time = 1 if n.tool == curr.tool else 8
            alt_travel_time += nodes_to_travel_time[curr]
            if n not in nodes_to_travel_time or alt_travel_time < nodes_to_travel_time[n]:
                nodes_to_travel_time[n] = alt_travel_time

print(shortest_path(target_x, target_y))


from django.contrib import admin
from django.contrib.admin import ModelAdmin

from backend.hume.models import Hume, ValidHume

class ValidHumeAdmin(ModelAdmin):
    model = ValidHume
    list_display = ('uuid', )

class HumeAdmin(ModelAdmin):
    model = Hume
    list_display = ('uuid', )

admin.site.register(ValidHume, ValidHumeAdmin)
admin.site.register(Hume, HumeAdmin)


from xml.dom.minidom import Element

def bubble_sort(elements, key):
    elements_len= len(elements)
    swapped = False
    for i in range(elements_len):
        for j in range(elements_len - 1 - i):
            if elements[j][key] > elements[j+1][key]:
                temp = elements[j][key]
                elements[j][key] = elements[j+1][key]
                elements[j+1][key] = temp
                swapped = True
        if not swapped:
            break
    return elements

elements = [
        { 'name': 'mona',   'transaction_amount': 1000, 'device': 'iphone-10'},
        { 'name': 'dhaval', 'transaction_amount': 400,  'device': 'google pixel'},
        { 'name': 'kathy',  'transaction_amount': 200,  'device': 'vivo'},
        { 'name': 'aamir',  'transaction_amount': 800,  'device': 'iphone-8'},
    ]

print(bubble_sort(elements, "name"))


#coding=utf-8
from selenium import webdriver
import time
import random
from PIL import Image
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By

'''
for i in range(5):
    user_email = ''.join(random.sample('1234567890abcdefghijklmnopqrstuvwxyz',8))+"@163.com"
    print(user_email)

'''
driver = webdriver.Chrome()
#driver = webdriver.Firefox()
driver.get("http://www.5itest.cn/register")
driver.maximize_window()
time.sleep(3)
print(EC.title_contains("注册"))
email_element = driver.find_element_by_id("register_email")
driver.save_screenshot("D:/www/SeleniumPython/ImoocSelenium/imooc.png")
code_element = driver.find_element_by_id("getcode_num")
print(code_element.location) #{"x":123,"y":345}
left = code_element.location['x']
top = code_element.location['y']
right = code_element.size['width']+left
height = code_element.size['height']+top
im = Image.open("D:/www/SeleniumPython/ImoocSelenium/imooc.png")
#resize the screenshot
img = im.crop((left,top,right,height))
img.save("D:/www/SeleniumPython/ImoocSelenium/imooc1.png")
driver.close()

'''
#verify if the element is found
#element = driver.find_elements_by_class_name("controls")
locator = (By.CLASS_NAME,"controls")
WebDriverWait(driver,1).until(EC.visibility_of_element_located(locator))

print(email_element.get_attribute("placeholder"))
email_element.send_keys("cyj@163.com")
print(email_element.get_attribute("value"))
driver.close()

driver.find_element_by_id("register_email").send_keys("himo2020@163.com")
user_name_element_node = driver.find_elements_by_class_name("controls")[1]
user_element = user_name_element_node.find_element_by_class_name("form-control")
user_element.send_keys("himo2020")
driver.find_element_by_name("password").send_keys("222222")
driver.find_element_by_xpath("//*[@id='captcha_code']").send_keys("111111")
'''


import numpy as np
import torch

def denormalization(x):
    mean = np.array([0.5, 0.5, 0.5])
    std = np.array([0.5, 0.5, 0.5])
    x = (((x.transpose(1, 2, 0) * std) + mean) * 255.).astype(np.uint8)
    # x = (x.transpose(1, 2, 0) * 255.).astype(np.uint8)
    return x

def denorm(x):
    """Convert the range from [-1, 1] to [0, 1]."""
    out = (x + 1) / 2
    return out.clamp_(0, 1)

class EarlyStop():
    """Used to early stop the training if validation loss doesn't improve after a given patience."""
    def __init__(self, patience=20, verbose=True, delta=0, save_name="checkpoint.pt"):
        """
        Args:
            patience (int): How long to wait after last time validation loss improved.
                            Default: 20
            verbose (bool): If True, prints a message for each validation loss improvement.
                            Default: False
            delta (float): Minimum change in the monitored quantity to qualify as an improvement.
                            Default: 0
            save_name (string): The filename with which the model and the optimizer is saved when improved.
                            Default: "checkpoint.pt"
        """
        self.patience = patience
        self.verbose = verbose
        self.save_name = save_name
        self.counter = 0
        self.best_score = None
        self.early_stop = False
        self.val_loss_min = np.Inf
        self.delta = delta

    def __call__(self, val_loss, model, optimizer):

        score = -val_loss

        if self.best_score is None:
            self.best_score = score
            self.save_checkpoint(val_loss, model, optimizer)
        elif score < self.best_score - self.delta:
            self.counter += 1
            print((f'EarlyStopping counter: {self.counter} out of {self.patience}'))
            if self.counter >= self.patience:
                self.early_stop = True
        else:
            self.best_score = score
            self.save_checkpoint(val_loss, model, optimizer)
            self.counter = 0

        return self.early_stop

    def save_checkpoint(self, val_loss, model, optimizer):
        '''Saves model when validation loss decrease.'''
        if self.verbose:
            print((f'Validation loss decreased ({self.val_loss_min:.6f} --> {val_loss:.6f}).  Saving model ...'))
        state = {'model': model.state_dict(), 'optimizer': optimizer.state_dict()}
        torch.save(state, self.save_name)
        self.val_loss_min = val_loss

def gen_mask(k_list, n, im_size):
    while True:
        Ms = []
        for k in k_list:
            N = im_size // k # Ex. 256 / 4 = 64
            rdn = np.random.permutation(N**2) # 0 ~ 64x64-1 の配列を作って並び替え
            additive = N**2 % n # 64^2をn=3で割った時の余り
            if additive > 0: # 余りが有ったら
                rdn = np.concatenate((rdn, np.asarray([-1] * (n - additive)))) # n=3 - 余り分、-1を結合
            n_index = rdn.reshape(n, -1) # 配列をn=3等分
            for index in n_index:
                tmp = [0 if i in index else 1 for i in range(N**2)] # 0 ~ 64x64-1を回してn_indexにあったら0、なかったら1を入れる
                tmp = np.asarray(tmp).reshape(N, N) # 64x64にreshape
                tmp = tmp.repeat(k, 0).repeat(k, 1) # 配列の要素を繰り返して画像サイズと同じにする(64x64→256x256)
                Ms.append(tmp)
        yield Ms


# Aula de Reposição Python
# Lista de Exercício 2
# Questão 5

# Leia o nome do funcionário

funcionario = input("Digite o nome do funcionário: ")

salario_atual = float(input("Digite o salário atual do mesmo "))

NS = salario_atual + (salario_atual * 0.25)

print("Com o reajuste, o novo salário do funcionário(A): %s será: %.2f" % (funcionario, NS))


from django.conf.urls import url
from . import views

urlpatterns = [

    url(r'bloglist',views.BlogList,name='list'),
    url(r'^detail/(?P<slug>[-\w]+)$',views.BlogDetail,name='detail'),
    url(r'^authorlist/',views.BlogAuthors,name='authorlist'),
    url(r'^author/(?P<id>\d+)$', views.BlogListByAuthor, name="blog-by-author"),
    url(r'^category/(?P<slug>[-\w]+)/$', views.base, name='category'),
    url(r'^cat/', views.base1, name='cat'),
    url(r'^subscribe/',views.sub,name='subscribe'),
    url(r'^contact/',views.Contact,name='contact'),
    url(r'^search/',views.search,name='search'),
    url(r'^reply/(?P<id>\d+)/(?P<slug>[-\w]+)/$',views.ReplyPage,name='reply'),
    url(r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',views.activate, name='activate'),

]


from mongo_database.mongo import export_to_mong, mongo_to_sheet
from scrapers.scraper import Amazon
import asyncio
import time

if __name__ == '__main__':

    async def main():
        base_url = "https://www.amazon.com/s?k=sexy+dresses&rh=n%3A1045024%2Cn%3A11006703011&dc&ds=v1%3A%2B%2B%2BeqnlN6RopN%2BQAazKtqRPqLIORlC%2FwkWAKUFM%2B9Kc&qid=1688721535&rnid=2941120011&ref=sr_nr_n_4"
        # amzn = Amazon()
        # return await amzn.scrape_data(base_url)
        mongo_to_db = await export_to_mong(base_url)
        # sheet_name = "Dinner Plates"  # Please use the name of the collection in your MongoDB database to specify the name of the spreadsheet you intend to export.
        # # sheets = await mongo_to_sheet(sheet_name)  # Uncomment this to export to excel database.
        # # return sheets
        return mongo_to_db

    # Start the timer to measure how long the wb scraping process takes
    start_time = time.time()

    # Run the async main function and run the scraper:
    results = asyncio.run(main())
    end_time = time.time()

    print(results)

    # Calculate and print the total time taken to scrape the data:D
    execution_time = round(end_time - start_time, 2)
    print(f"Took {execution_time} seconds | {round(execution_time / 60, 2)} minutes.")


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Exports a document.
"""

import json
import sys
import shlex
import subprocess
from collections import namedtuple

from util import parse_psql_array

def query_psql(sql):
    """
    Sends a query to psql.
    """
    cmd = r"""psql -h localhost -p 4242 kbp kbp -c "COPY ({sql}) TO STDOUT DELIMITER E'\t'" """.format(sql=sql)
    output = subprocess.check_output(shlex.split(cmd))

    for line in output.split("\n"):
        line = line.strip()
        if len(line) == 0: continue
        yield line.split("\t")

def query_doc(docid):
    doc, idx_ = [], 0
    for row in query_psql("SELECT sentence_index, words, lemmas, pos_tags, ner_tags, doc_char_begin, doc_char_end FROM sentence WHERE doc_id = '{}' ORDER BY sentence_index".format(docid)):
        idx, words, lemmas, pos_tags, ner_tags, doc_char_begin, doc_char_end = row
        assert int(idx) == idx_, "Seems to have skipped a line: {} != {}".format(idx, idx_)
        idx_ += 1
        words, lemmas, pos_tags, ner_tags, doc_char_begin, doc_char_end = map(parse_psql_array, (words, lemmas, pos_tags, ner_tags, doc_char_begin, doc_char_end))
        doc_char_begin, doc_char_end = map(int, doc_char_begin), map(int, doc_char_end)
        keys = ("word", "lemma", "pos_tag", "ner_tag", "doc_char_begin", "doc_char_end")
        tokens = [{k:v for k, v in zip(keys, values)} for values in zip(words, lemmas, pos_tags, ner_tags, doc_char_begin, doc_char_end)]
        doc.append(tokens)
    return doc

def query_mentions(docid):
    ner_map = {
        "PERSON": "PER",
        "ORGANIZATION": "ORG",
        "LOCATION": "GPE",
        "GPE": "GPE",
        "DATE": "DATE",
        "TITLE": "TITLE",
        }

    mentions = []
    for row in query_psql("""SELECT m.gloss, m.ner, m.doc_char_begin, m.doc_char_end, n.gloss AS canonical_gloss, m.best_entity, m.doc_canonical_char_begin, m.doc_canonical_char_end
    FROM mention m, mention n
    WHERE m.doc_id = '{doc_id}' AND n.doc_id = m.doc_id
      AND m.doc_canonical_char_begin = n.doc_char_begin AND m.doc_canonical_char_end = n.doc_char_end
    ORDER BY m.doc_char_begin""".format(doc_id=docid)):
        gloss, ner, doc_char_begin, doc_char_end, entity_gloss, entity_link, entity_doc_char_begin, entity_doc_char_end = row
        if ner not in ner_map: continue
        ner = ner_map[ner]

        mentions.append({
            "gloss": gloss,
            "type": ner,
            "doc_char_begin": int(doc_char_begin),
            "doc_char_end": int(doc_char_end),
            "entity": {
                "gloss": entity_gloss,
                "link": entity_link,
                "doc_char_begin": int(entity_doc_char_begin),
                "doc_char_end": int(entity_doc_char_end),
                }
            })
    return mentions

def do_command(args):
    doc = query_doc(args.docid)
    mentions = query_mentions(args.docid)
    args.output.write(json.dumps({
        "doc_id": args.docid,
        "sentences": doc,
        "suggested-mentions": mentions
        }))

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description='Saves document to file in json format.')
    parser.add_argument('-d', '--docid', type=str, default="", help="DOCID")
    parser.add_argument('-o', '--output', type=argparse.FileType('w'), default=sys.stdout, help="")
    parser.set_defaults(func=do_command)

    ARGS = parser.parse_args()
    if ARGS.func is None:
        parser.print_help()
        sys.exit(1)
    else:
        ARGS.func(ARGS)


# BOJ #1012 유기농 배추
"""
파이썬 논리 연산자는 or, and 같이 영어로,, 쓰자,,!!
"""

t = int(input())
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
queue = []

for _ in range(t):
    m, n, k = map(int, input().split())  # 가로길이, 세로길이, 배추 개수
    space = [[0] * m for _ in range(n)]  # 배추밭
    count = 0

    for _ in range(k):
        y, x = map(int, input().split())
        space[x][y] = 1

    def bfs():
        index = 0

        while len(queue) > index:
            x = queue[index][0]
            y = queue[index][1]
            index += 1

            for i in range(4):
                nx = x + dx[i]
                ny = y + dy[i]

                if nx < 0 or ny < 0 or nx >= n or ny >= m or space[nx][ny] == 0: continue

                space[nx][ny] = 0
                queue.append((nx, ny))

    for i in range(n):
        for j in range(m):
            if space[i][j] == 1:
                queue.append((i, j))
                space[i][j] = 0
                count += 1
                bfs()
                queue = []

    print(count)

"""
두 번째 풀이

import sys
sys.setrecursionlimit(10 ** 4)

t = int(sys.stdin.readline().strip())

for _ in range(t):
    m, n, k = map(int, sys.stdin.readline().strip().split())
    table = [[0 for _ in range(m)] for _ in range(n)]

    for _ in range(k):
        x, y = map(int, sys.stdin.readline().strip().split())
        table[y][x] = 1

    dx = [0, 0, -1, 1]
    dy = [-1, 1, 0, 0]
    cnt = 0

    def dfs(x, y):
        if x < 0 or y < 0 or x >= n or y >= m or table[x][y] != 1:
            return
        table[x][y] = 0
        for i in range(4):
            dfs(x+dx[i], y+dy[i])

    for i in range(n):
        for j in range(m):
            if table[i][j] == 1:
                dfs(i, j)
                cnt += 1

    print(cnt)

=> 재귀 dfs 이용하여 풀이하였음
재귀 깊이를 늘려주어야 함
"""


"""
Program: employee.py
Author: Rachael Wolf
Last date modified: 11/1/2020

This program contains a Class called Employee and some functions relating to it
The functions included are: set_last_name(), set_first_name(), display(), str(), and repr()
"""
import datetime

class Employee:
    """A class representing an employee, with a first and last name, contact information, and employment information"""

    def __init__(self, name, surname, address, phone_number, salaried, start_date, salary):

        self.first_name = name
        self.last_name = surname
        self.address = address
        self.phone_number = phone_number
        self.salaried = bool(salaried)
        self.start_date = start_date
        self.salary = salary

    def set_last_name(self, surname):
        """sets or alters the last_name string of the Employee object
        :param surname the last name of the Employee"""
        self.last_name = surname

    def set_first_name(self, name):
        """sets or alters the first_name string of the Employee object
        :param name the first name of the Employee"""
        self.first_name = name

    def display(self):
        """returns a more comprehensive string of the Employee object"""
        full_name = str(self.first_name) + " " + str(self.last_name)
        salary_line = ''
        if self.salaried:
            salary_line = "Salaried employee: $" + str(self.salary) + "/year"
        else:
            salary_line = "Hourly employee: $" + str(self.salary) + "/hour"
        return full_name + "\n" + str(self.address) + "\n" + salary_line + "Start date: " + str(self.start_date)

    def str(self):
        """returns a string of the Employee object.  same as repr()"""
        e_string = self.first_name + ' ' + self.last_name + ', ' + self.phone_number
        return e_string

    def repr(self):
        """returns a string of the Employee object. same as str()"""
        e_string = self.first_name + ' ' + self.last_name + ', ' + self.phone_number
        return e_string

# Drive
emp = Employee('Matthew', 'Ruiz', '519 Grant St \nEllis, New Jersey', '(614) 544 9823', True,
               datetime.date.today(), 40000)   # call the constructor
emp.set_first_name('Matt')
print(emp.display())                # display returns a str, so print the information
del emp


import dynet as dy
import argparse
import time
import random
import numpy as np
from collections import defaultdict
import math
import pickle
import json
from tqdm import tqdm
from model import LM

parser = argparse.ArgumentParser()
parser.add_argument("--dynet-mem", help="allocate memory for dynet")
parser.add_argument("--dynet-gpu", help="use GPU")
parser.add_argument("--dynet-gpus", help="use GPU")
parser.add_argument("--dynet-seed", help="set random seed for dynet")
parser.add_argument("--dynet-gpu-ids", default=3, help="choose which GPU to use")
parser.add_argument("--dynet-autobatch", default=0, help="choose which GPU to use")
parser.add_argument("--dynet-devices", help="set random seed for dynet")
parser.add_argument("--dynet-weight-decay", help="choose weight decay")

parser.add_argument("--train", default="alternate_sents_seame_train_filtered.json", help="location of training file")
parser.add_argument("--dev", default="alternate_sents_seame_val_filtered.json", help="new dev file")
parser.add_argument("--test", default="alternate_sents_seame_test_filtered.json", help="new test file")
parser.add_argument("--train_finetune", default="alternate_sents_mono_all_filtered.json", help="location of training file for finetune")
parser.add_argument("--epochs", default=25, type=int, help="number of epochs")
parser.add_argument("--batch_size", default=20, type=int, help="size of batches")
parser.add_argument("--trainer", default="sgd", help="choose trainer for the optimization")
parser.add_argument("--num_layers", default=2, type=int, help="number of layers in RNN")
parser.add_argument("--input_dim", default=300, type=int, help="dimension of the input to the RNN")
parser.add_argument("--hidden_dim", default=650, type=int, help="dimension of the hidden layer of the RNN")
parser.add_argument("--x_dropout", default=0.35, type=float, help="value for rnn dropout")
parser.add_argument("--h_dropout", default=0.35, type=float, help="value for rnn dropout")
parser.add_argument("--w_dropout_rate", default=0.2, type=float, help="value for rnn dropout")
parser.add_argument("--logfile", default="log.txt", help="location of log file for debugging")
parser.add_argument("--learning_rate", default=1, type = float, help="set initial learning rate")
parser.add_argument("--lr_decay_factor", default=2.5, type = float, help="set clipping threshold")
parser.add_argument("--clip_thr", default=1, type=float, help="set clipping threshold")
parser.add_argument("--init_scale_rnn", default=0.05, type=float, help="scale to init rnn")
parser.add_argument("--init_scale_params", default=None, type=float, help="scale to init params")
parser.add_argument("--check_freq", default=None, help="frequency of checking perp on dev and updating lr")
parser.add_argument("--finetune_p1", action='store_true',help="train a model from monolingual data")
parser.add_argument("--finetune_p2", help="name of model learned from momnolingual data")
parser.add_argument("--resume_train", default=False, action="store_true", help="resume training from model")
parser.add_argument("--lamb", default=1, type=float, help="value of lambda")
parser.add_argument("--margin", default="wer", help="value of margin for loss")
parser.add_argument("--evaluate_model", help="model to load and evaluate, no training")

class Set:
    orig = None
    orig_type = None
    cs = None
    en = None
    zh = None
    distances = None
    raw = None

def remove_tag(sentence):
    no_tag = ""
    for token in sentence.split():
        no_tag += token.split("__")[0] + " "

    return no_tag

def detect_lang(sentence):
    tokens = sentence.split()
    en = False
    zh = False
    for token in tokens:
        if token.endswith("__en"):
            en = True
        elif token.endswith("__zh"):
            zh = True

    if en and zh:
        # code switched
        return "cs"
    if en:
        # english
        return "en"
    if zh:
        # chinese
        return "zh"

    # something wrong
    return None

def read_corpus(data_file, train = False):
    all_sets = []
    with open(data_file) as f:
        data = json.load(f)
    for s in tqdm(data):
        new_s = Set()
        new_s.cs = []
        new_s.en = []
        new_s.zh = []
        new_s.distances = []
        new_s.raw = []
        new_s.orig_type = detect_lang(s["orig"])

        new_s.orig = [w2i[w.split("__")[0].lower().lower()] for w in [START_TOKEN] + s["orig"].split() + [END_TOKEN]]
        new_s.raw.append(s["orig"])
        for idx, lang_type in enumerate(["cs", "en", "zh"]):
            for v in s[lang_type + "_alternatives"]:
                #assert(detect_lang(v) == idx)
                sent = []
                for w in [START_TOKEN] + v.split() + [END_TOKEN]:
                    sent.append(w2i[w.split("__")[0].lower()])
                getattr(new_s, lang_type).append(sent)
                new_s.raw.append(v)
        all_sets.append(new_s)
    assert(len(all_sets) == len(data))
    if train:
        print("length of train:", len(all_sets))
    return all_sets, len(all_sets)

def evaluate(test):
    all_scores = []
    all_norms = []
    ranks = []
    for item in tqdm(test):
        batch = [item.orig] + item.cs + item.en + item.zh
        output = [s.npvalue().flatten().tolist() for s in get_batch_scores(batch, True)]
        indices = list(range(len(scores)))
        indices.sort(key=lambda x: scores[x], reverse=True)
        ranks.append(indices.index(0)+1)
        all_norms.append(norms)
        all_scores.append(scores)

    cs = []
    en = []
    zh = []
    for rank, item in zip(ranks, test):
        if item.orig_type == "cs":
            cs.append(rank)
        elif item.orig_type == "en":
            en.append(rank)
        elif item.orig_type == "zh":
            zh.append(rank)

    tot_acc = sum([1 for r in ranks if r == 1])*100/float(len(ranks))
    cs_acc = sum([1 for r in cs if r == 1])*100/float(len(cs))
    en_acc = sum([1 for r in en if r == 1])*100/float(len(en))
    zh_acc = sum([1 for r in zh if r == 1])*100/float(len(zh))

    return tot_acc, cs_acc, en_acc, zh_acc, all_norms, all_scores

def logstr(f, s):
    print(f'[{str(time.time())}]  {s}')
    f.write(f'[{str(time.time())}]  {s}')

if __name__ == '__main__':

    args = parser.parse_args()
    random.seed(10)
    np.random.seed(10)

    print(str(args) + "\n\n")

    START_TOKEN = "<s>"
    END_TOKEN = "</s>"
    w2i = defaultdict(lambda: len(w2i))
    UNK = w2i["<unk>"]

    if args.finetune_p1 or args.finetune_p2:
        # need vocabulary in w2i for both p1 and p2
        train_set_finetune, train_nbatches_finetune = read_corpus(args.train_finetune, True)
        print("Loaded monolingual train set")

    train_set, train_nbatches = read_corpus(args.train, True)
    print("Loaded code switched train set")
    dev_set, dev_nbatches = read_corpus("data/" + args.dev)
    print("Loaded validation set")
    test_set, test_nbatches = read_corpus("data/" + args.test)
    print("Loaded test set")

    # create model
    # NOTE: need to read corpus before creating model since read_corpus() will fill up w2i
    word_num = len(w2i)
    model = LM(args.num_layers, args.input_dim, args.hidden_dim, word_num, args.init_scale_rnn, args.init_scale_params,
               args.x_dropout, args.h_dropout, args.w_dropout_rate, args.learning_rate, args.clip_thr)

    model.load("models/" + args.evaluate_model + "_model")
    print("loaded model", args.evaluate_model)
    dev_acc, dev_cs_acc, dev_en_acc, dev_zh_acc, dev_scores = evaluate(dev_set)
    test_acc, test_cs_acc, test_en_acc, test_zh_acc, test_scores = evaluate(test_set)
    print("dev accs", dev_acc, dev_cs_acc, dev_en_acc, dev_zh_acc)
    print("test accs", test_acc, test_cs_acc, test_en_acc, test_zh_acc)

    json.dump(dev_scores, open("dev_scores.json", 'w'), indent=2, ensure_ascii=False)
    logging.info("Saved dev scores to dev_scores.txt")
    json.dump(test_scores, open("test_scores.json", 'w'), indent=2, ensure_ascii=False)
    logging.info("Saved test scores to test_scores.txt")


import sys
import math

from io import open
from conllu import parse

def load_conll_file(filename):
    text = open(filename, "r", encoding="utf-8").read()
    return parse(text)

def save_tb(tb):
    for sent in tb:
        if sent.metadata:
            for key, value in sent.metadata.items():
                if value is None:
                    sent.metadata[key] = 'None'

        print(sent.serialize(), end='')

def split_sentence_impl(sent):
    ret = []

    last_idx = -1
    last_word_id = sent[last_idx]['id']
    if not isinstance(last_word_id, int):
        last_idx -= 1
        last_word_id = sent[last_idx]['id']

    possible_split_points = {}

    for token in sent:
        if not isinstance(token['id'], int):
            continue

        pos = token['id']
        # consider splitting sentence after token pos

        if pos < 3 or pos > last_word_id - 3:
            continue

        links_to_update_before = 0
        links_to_update_after = 0

        for tok in sent:
            if not isinstance(tok['id'], int):
                continue

            if tok['id'] <= pos:
                if tok['head'] > pos:
                    links_to_update_before += 1
            else:
                if tok['head'] <= pos:
                    links_to_update_after += 1

        possible_split_points[pos] = links_to_update_before + links_to_update_after

    good_split_points = sorted(possible_split_points.keys(), key=lambda x: possible_split_points[x])
    min_value = possible_split_points[good_split_points[0]]
    min_values_count = sum(v == min_value for v in possible_split_points.values())
    good_split_points = good_split_points[:min_values_count]

    if len(good_split_points) == 0:
        raise

    good_split_points_centred = sorted(good_split_points, key=lambda x: abs(int(math.floor(len(sent) / 2)) - x))

    if len(good_split_points_centred) == 0:
        raise

    split_pos = good_split_points_centred[0]
    split_idx = None

    if split_pos is None:
        raise

    for i in range(len(sent)):
        if isinstance(sent[i]['id'], int) and sent[i]['id'] == split_pos:
            split_idx = i + 1
            break

    first = sent.copy()
    first.metadata = first.metadata.copy()
    first.tokens = first[:split_idx]
    if 'sent_id' in first.metadata:
        first.metadata['sent_id'] = first.metadata['sent_id'] + " / left"

    update_heads_in_left_part(first, sent)

    for tok in first:
        if tok['head'] is None:
            continue
        if tok['head'] != 0 and tok['head'] > split_pos:
            sys.stderr.write('F prev head of token %s is %d\n' % (str(tok['id']), tok['head']))

    second = sent.copy()
    second.metadata = second.metadata.copy()
    second.tokens = second[split_idx:]
    if 'sent_id' in second.metadata:
        second.metadata['sent_id'] = second.metadata['sent_id'] + " / right"

    update_heads_in_right_part(second, sent)

    i = len(second.tokens) - 1
    last_token_id = second[i]['id']
    while not isinstance(last_token_id, int):
        i -= 1
        last_token_id = second[i]['id']

    for tok in second:
        if 'head' not in tok or tok['head'] is None or tok['head'] == '_':
            continue
        #if tok['head'] != 0 and tok['head'] > last_token_id:
        #    sys.stderr.write('S prev head of token %s is %d\n' % (str(tok['id']), tok['head']))

    ret = [first, second]

    return ret

def get_token_with_id(sent, id):
    for tok in sent:
        if str(tok['id']) == id:
            return tok
    raise

def update_heads_in_left_part(part, whole_sent):
    i = len(part) - 1
    last_token_id = part[i]['id']
    while not isinstance(last_token_id, int):
        i -= 1
        last_token_id = part[i]['id']

    root_pos = None
    orphans = []
    for i in range(len(part)):
        if 'head' not in part[i] or part[i]['head'] is None or part[i]['head'] == '_':
            continue
        if part[i]['head'] == 0:
            root_pos = part[i]['id']
        if part[i]['head'] > last_token_id:
            orphans.append(part[i]['id'])

    if root_pos is None:
        branch_len = [ len(part) + 1 ] * len(part)
        for i in range(len(part)):
            #pos = orphans[i]
            if not isinstance(part[i]['id'], int):
                continue
            if 'upostag' not in part[i]:
                continue
            if part[i]['upostag'] == 'PUNCT':
                continue
            token = get_token_with_id(whole_sent, str(part[i]['id']))
            parent = token['head']
            branch_len[i] = 0
            while parent != 0:
                if branch_len[i] > len(whole_sent) + 1:
                    raise
                branch_len[i] += 1
                parent = get_token_with_id(whole_sent, str(parent))['head']

        root_pos = part[branch_len.index(min(branch_len))]['id']
        get_token_with_id(part, str(root_pos))['head'] = 0

    for tok in part:
        if 'head' not in tok or tok['head'] is None or tok['head'] == '_':
            continue
        if tok['head'] != 0 and tok['head'] > last_token_id:
            tok['head'] = root_pos

    update_indices(part)

def update_heads_in_right_part(part, whole_sent):
    i = 0
    first_token_id = part[i]['id']
    while not isinstance(first_token_id, int):
        i += 1
        first_token_id = part[i]['id']

    root_pos = None
    orphans = []
    for i in range(len(part)):
        if 'head' not in part[i] or part[i]['head'] is None or part[i]['head'] == '_':
            continue
        if part[i]['head'] == 0:
            root_pos = part[i]['id']
        if part[i]['head'] < first_token_id:
            orphans.append(part[i]['id'])

    if root_pos is None:
        branch_len = [ len(part) + 1 ] * len(part)
        for i in range(len(part)):
            #pos = orphans[i]
            if not isinstance(part[i]['id'], int):
                continue
            if 'upostag' not in part[i]:
                continue
            if part[i]['upostag'] == 'PUNCT':
                continue
            token = get_token_with_id(whole_sent, str(part[i]['id']))
            parent = token['head']
            branch_len[i] = 0
            while parent != 0:
                if branch_len[i] > len(whole_sent) + 1:
                    raise
                branch_len[i] += 1
                parent = get_token_with_id(whole_sent, str(parent))['head']

        root_pos = part[branch_len.index(min(branch_len))]['id']
        get_token_with_id(part, str(root_pos))['head'] = 0

    for tok in part:
        if 'head' not in tok or tok['head'] is None or tok['head'] == '_':
            continue
        if tok['head'] != 0 and tok['head'] < first_token_id:
            tok['head'] = root_pos

    update_indices(part)

def update_indices(sent):
    pos = 1
    old2new = {}

    for i in range(len(sent)):
        id = sent[i]['id']
        if id not in old2new:
            if isinstance(id, int):
                new_id = pos
                old2new[id] = pos
                pos += 1
            else:
                if '-' in str(id):
                    if len(id) == 3:
                        begin, end = id[0], id[2]
                        begin = int(begin)
                        end = int(end)
                        n = 0
                        for x in range(begin, end+1):
                            old2new[x] = pos + n
                            n += 1
                        new_id = (old2new[begin], '-', old2new[end])
                        old2new[id] = new_id
                        pos += end - begin + 1
                    else:
                        raise
                elif '.' in str(id):
                    if len(id) == 3:
                        begin, idx = id[0], id[2]
                        begin = int(begin)
                        idx = int(idx)
                        if begin not in old2new:
                            old2new[begin] = pos
                            pos += 1
                            #raise
                        #old2new[begin] = pos
                        #pos += 1
                        new_id = (old2new[begin], '.', idx)
                        old2new[id] = new_id
                    else:
                        raise

        sent[i]['id'] = old2new[id]

    for tok in sent:
        if 'head' not in tok or tok['head'] is None or tok['head'] == '_':
            continue
        if tok['head'] != 0 and tok['head'] not in old2new:
            raise
        if tok['head'] != 0:
            tok['head'] = old2new[tok['head']]

    pass

def split_sentence(sent, max):
    rv = []
    parts = split_sentence_impl(sent)
    for s in parts:
        if len(s) > max:
            rv.extend(split_sentence(s, max))
        else:
            rv.append(s)
    return rv

def guess_max_sentence_len(tb, out_ratio):
    lengths = []
    for sent in tb:
        lengths.append(len(sent))

    lengths.sort(reverse=True)

    num_outliers = int(len(lengths) * out_ratio)
    if num_outliers < 1:
        num_outliers = 2

    outliers = lengths[:num_outliers]
    max_len = outliers[-1]

    return max_len

def is_sentence_supported(sent):
    for t in sent:
        if isinstance(t['id'], tuple):
            return False
        if isinstance(t['head'], tuple):
            return False
        if t['head'] is None:
            print(str(sent.serialize()))
        i = int(t['head'])
    return True

def augment(tb, max_len):
    new = []

    for sent in tb:
        if not is_sentence_supported(sent):
            print('Not supported:\n%s\n' % str(sent))
            continue
        num = len(sent)
        if num > max_len:
            parts = split_sentence(sent, max_len)
            for s in parts:
                new.append(s)
        else:
            new.append(sent)

    return new

def main():
    if len(sys.argv) <= 1:
        return

    tb = load_conll_file(sys.argv[1])

    new_tb = augment(tb, guess_max_sentence_len(tb, 0.02))

    save_tb(new_tb)

if __name__ == '__main__':
    main()


""" Quicksort using DNF, good w/ duplicates """

import random

def swap(arr, i, j):
    arr[i], arr[j] = arr[j], arr[i]

def dnf(arr, start, end, ipivot) -> (int, int):
    """
    Returns the border points (l, h) outside the middle section
    [0,0,0,1,1,1,2,2,2]
     s   l       h   e
    """

    pivot = arr[ipivot]

    low = start - 1  # last el in left partition
    mid = start - 1  # last el in mid partitioni
    high = end + 1  # first el in right parition

    while mid + 1 < high:
        if arr[mid + 1] > pivot:
            swap(arr, mid + 1, high - 1)
            high -= 1
        elif arr[mid + 1] == pivot:
            # swap(mid + 1, mid + 1)# noop
            mid += 1
        else:  # arr[mid + 1] < pivot:
            swap(arr, mid + 1, low + 1)
            low += 1
            mid += 1

    return (low, high)

def _quicksort(arr, start, end):
    if start >= end:
        return
    ipivot = random.randrange(start, end + 1)
    low, high = dnf(arr, start, end, ipivot)
    _quicksort(arr, start, low)
    _quicksort(arr, high, end)

def quicksort(arr):
    _quicksort(arr, 0, len(arr) - 1)

def test():
    for l in [0, 1, 2, 5, 10]:
        # ints
        arr = [random.randint(-1000, 1000) for i in range(l)]
        arr2 = sorted(arr)
        quicksort(arr)
        assert tuple(arr) == tuple(arr2)
        print('ok')

        # floats
        arr = [random.random() for i in range(l)]
        arr2 = sorted(arr)
        quicksort(arr)
        assert tuple(arr) == tuple(arr2)
        print('ok')

    # dups
    arr = [0, 1, 0, 1, 1, 2]
    arr2 = sorted(arr)
    quicksort(arr)
    assert tuple(arr) == tuple(arr2)
    print('ok')

test()


import matplotlib.pyplot as plt
import numpy as np

def part1(x, y, theta):
    plt.figure()
    plt.plot(x, y, 'x', color='b')
    line = np.linspace(-50, 40, 2)
    plt.plot(line, theta[0] + theta[1] * line)
    plt.xlim(-50, 40)
    plt.ylim(-5, 40)
    plt.show()
    plt.savefig('data/fig1.png')

def parte2(errTrain, errVal, m, fig):
    plt.plot(np.arange(1, m + 1), errTrain, label="Train")
    plt.plot(np.arange(1, m + 1), errVal, label="Validation")
    plt.show()
    plt.savefig('data/fig2-{}.png'.format(fig), dpi=300)

def parte3_1(theta, p, mu, sigma, x, y):
    line2 = np.linspace(-110, 50, 100)

    line1 = theta[0] * np.ones(100)
    for i in range(p + 1):
        line1 += theta[i] * (line2 ** i - mu[i - 1]) / sigma[i - 1]

    plt.figure()
    plt.plot(x, y, 'x', color='r')
    plt.plot(line2, line1, 'b--')
    plt.show()
    plt.savefig('data/fig3-1.png', dpi=300)

def parte3_2(errTrain, errVal, lam):
    plt.figure()
    plt.plot(lam, errTrain, '-o', label="Train")
    plt.plot(lam, errVal, '-o', label="Validation")
    plt.show()
    plt.savefig('data/fig3-2.png', dpi=300)


from prefect import task, Flow
from prefect.executors import LocalDaskExecutor
from prefect.storage import Docker
from prefect.run_configs import DockerRun

from research.example_pkg import things

@task#(log_stdout=True)
def run_thing1():
    if things.thing1():
        return True

@task#(log_stdout=True)
def run_thing2():
    if things.thing2():
        return True

if __name__ == "__main__":
    with Flow("test_flow", executor=LocalDaskExecutor(scheduler="processes")) as flow:
        if run_thing1():
            thing2_var = run_thing2()

    flow.storage = Docker(
        base_image="prefect_logger_repro",
        local_image=True,
        build_kwargs={
            "labels" : { "logging_job_name" : "test_flow" }
        },
        ignore_healthchecks=True,
        registry_url="artifactory.aq.tc/prefect/",
    )
    flow.run_config = DockerRun()
    #flow.run()
    flow.register(project_name="default")


class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        if val in nums:  # check if val in nums to handle an exception
            # get the index of the last occurence of val in nums
            nums.sort(reverse=True)
            i_end = len(nums) - 1 - nums.index(val)

            # get the index of the first occurence of val in nums
            nums.sort()
            i_start = nums.index(val)

            # delete all vals in nums in the sorted list
            del nums[i_start : i_end + 1]

        return len(nums)


# -*- coding: utf-8 -*-
# Copyright (C) 2013-Today  Carlos Eduardo Vercelino - CLVsol
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models

class LabTestTypeCriterion(models.Model):
    _description = 'Lab Test Criterion'
    _name = "clv.lab_test.criterion"
    _order = "sequence"

    code = fields.Char(string='Criterion Code')
    name = fields.Char(string='Test')

    # result = fields.Text('Results')
    result = fields.Char(string='Results')
    unit_id = fields.Many2one(comodel_name='clv.lab_test.unit', string='Unit')
    normal_range = fields.Text(string='Normal Range')

    lab_test_type_id = fields.Many2one(comodel_name='clv.lab_test.type', string='Test Type')

    lab_test_result_id = fields.Many2one(comodel_name='clv.lab_test.result', string='Test Result')

    lab_test_report_id = fields.Many2one(comodel_name='clv.lab_test.report', string='Test Report')

    sequence = fields.Integer(
        string='Sequence',
        default=10
    )

    result_display = fields.Boolean(string='Display in Result', default=True)
    report_display = fields.Boolean(string='Display in Report', default=True)

    active = fields.Boolean(string='Active', default=1)

    _sql_constraints = [
        ('type_code_uniq',
         'UNIQUE(lab_test_type_id, code)',
         u'Error! The Code must be unique for a Test Type!'
         ),
        ('result_code_uniq',
         'UNIQUE(lab_test_result_id, code)',
         u'Error! The Code must be unique for a Test Result!'
         ),
        ('report_code_uniq',
         'UNIQUE(lab_test_report_id, code)',
         u'Error! The Code must be unique for a Test Report!'
         ),
    ]

class LabTestType(models.Model):
    _inherit = 'clv.lab_test.type'

    criterion_ids = fields.One2many(
        comodel_name='clv.lab_test.criterion',
        inverse_name='lab_test_type_id',
        string='Test Cases'
    )

class LabTestResult(models.Model):
    _inherit = 'clv.lab_test.result'

    criterion_ids = fields.One2many(
        comodel_name='clv.lab_test.criterion',
        inverse_name='lab_test_result_id',
        readonly=True,
        string='Test Cases'
    )

class LabTestReport(models.Model):
    _inherit = 'clv.lab_test.report'

    criterion_ids = fields.One2many(
        comodel_name='clv.lab_test.criterion',
        inverse_name='lab_test_report_id',
        readonly=True,
        string='Test Cases'
    )


import os
import sys
import random

game = [' ',' ',' ',' ',' ',' ',' ',' ',' ']
global count
count=0

'''
TIC TAC TOE
'''

def player_computer(cpu):
    global count
    print("=====\n<==CPU playin his turn==>\n=====")
    t = random.randint(1,9)
    while True:
        if game[t-1] != " " :
            t=random.randint(1,9)
        else :
            break
    game[t-1]=cpu
    count+=1
    print_game()

def checkresult(p1,cpu):
    value = 0 #value = 0 for game still on nobody won yet!
    for i in range(9):
        if game[i]==" ":
            game[i]=6
    result=[]
    result.append(list(set((game[0],game[4],game[8]))))
    result.append(list(set((game[0],game[3],game[6]))))
    result.append(list(set((game[1],game[4],game[7]))))
    result.append(list(set((game[3],game[4],game[5]))))
    result.append(list(set((game[2],game[5],game[8]))))
    result.append(list(set((game[2],game[4],game[6]))))
    result.append(list(set((game[6],game[7],game[8]))))
    result.append(list(set((game[0],game[1],game[2]))))

    for i in range(8):
        if len(result[i]) == 1 and result[i][0] != 6:
            var = result[i][0][0]
            print("var : ",var)
            value=1 #game ends
    if value == 0 :
        for i in range(9):
            if game[i]==6:
                game[i]=" "

    if (value==1 and count<=9):
        if var == p1:
            print("\nPlayer1 wins!!\n")
        elif var == cpu:
            print("\nCPU wins!!\n")
        sys.exit()
    if value!=1 and count==9:
        print("\nMatch Drawn!!\n")
        sys.exit()
    if value!=1 and count<9:
        return

def begin():
    print("""press 1: for Player1 = 'X' and CPU = 'O'
press 2: for Player1 = 'O' and CPU = 'X'""")
    tr = int(input("Enter option : "))
    if tr == 1:
        player1 = 'X'
        cpu = 'O'
    else:
        player1 = 'O'
        cpu = 'X'
    while True:
        print("Player1's turn :")
        player(player1)
        checkresult(player1,cpu)

        player_computer(cpu)
        checkresult(player1,cpu)

def print_game():
    #os.system('clear')
    '''
    print(""",
          game[0] |game[1] |game[2]
          __|__|__
          game[3] |game[4] |game[5]
          __|__|__
          game[6] |game[7] |game[8]
            |  |
          """)
    '''
    print(game[0]+" |"+game[1]+" |"+game[2])
    print("__|__|__")
    print(game[3]+" |"+game[4]+" |"+game[5])
    print("__|__|__")
    print(game[6]+" |"+game[7]+" |"+game[8])
    print("  |  |  ")
    print("Value of count :",count)

def player(p):
    global count
    print("Choose an empty space from 1 to 9 : ")
    t = int(input("Enter position of '"+p+"' : "))
    if game[t-1] != " " :
        print("Space not empty")
        player(p)
    else:
        game[t-1]=p
        count=count+1
        print_game()

print("The pattern of tic tac toe board is as follows :")
print("""
1 |2 |3
__|__|__
4 |5 |6
__|__|__
7 |8 |9
  |  |
      """)
begin()


import logging
import inspect
import sys

active_breakpoints = []
func_breakpoints = {}

def activate_breakpoint(tags):
    """
    Active the breakpoints  for a given list of tags

    Parameters
    ----------
    tags: list
        List of tag names to activate

    Returns
    -------
    activate_break_points: list
        List of all active breakpoints
    """
    active_breakpoints.extend(tags)
    return active_breakpoints

class func_breakpoint:
    """
    Function wrapper for breakpoints. For example, executing ::

        import ipydebug
        @ipydebug.func_breakpoint('debug')
        def my_func(x,y,z):
            return x+y+z

    will activate a breakpoint for the function ``my_func`` so that each time it is called the
    ipython console will interrupt the code before the function is run. To access variables
    in the local scope where the breakpoint was set, use the ``local_vars`` variable,
    For example for the ``my_func`` function defined above ::

        >>>> my_func(1,2,z=3)

        In [1]: args
        Out[1]: (1,2)

        In [2]: kwargs
        Out[2]: {'z': 3}

    """
    def __init__(self, *args, **kwargs):
        """
        Initialize a breakpoint function wrapper.

        Parameters
        ----------
        args: list
            Arguments used to initialize the `ipydebug.Breakpoint` associated with the function
        kwargs: dict
            Keyword arguments used to initialize the `ipydebug.Breakpoint` associated with
            the function
        """
        self.args = args
        self.kwargs = kwargs
    def __call__(self, func):
        """
        When the function is called, call the breakpoint, then execute the function
        (unless ``self.breakpoint.exit=True``)
        """
        def inner(*args, **kwargs):
            """
            The wrapped function, called with any args and kwargs passed to the function.
            The args and kwargs are passed to the breakpoint function so that the
            user has access to them as variables.
            """
            self.breakpoint.break_here()
            return func(*args, **kwargs)
        # If this is the first time the function is called, add it to the breakpoint functions
        if inner.__name__ in func_breakpoints:
            self.breakpoint = func_breakpoints[inner.__name__]
        else:
            self.breakpoint = Breakpoint(*self.args, **self.kwargs)
        # Change the name of inner to be the name of the function that is being wrapped
        inner.__name__ = func.__name__
        return inner

class Breakpoint:
    """
    Defines a breakpoint in the code associated with a set of tags that can
    be turned on or off. A breakpoint will interrupt the code every time it is
    called if if it's ``activate`` property is ``True`` or  one of it's ``tags``
    in contained in `ipydebug.active_breakpoints`.

    """
    def __init__(self, tags=[], activate_tags=True, activate=False, max_usage=10, exit=False,
            log=None):
        """
        Initialize the Breakpoint.

        Parameters
        ----------
        tags: list of strings
            List of tags associated with the breakpoint. If any of these tags is stored in
            active_breakpoints then the breakpoint will interrupt the code when it is
            encountered
        activate_tags: bool or list
            If ``activate_tags`` is a boolean True value then all of the ``tags`` associated
            with the class are added to ``active_breakpoints``. If ``activate_tags`` is a list
            then all of the tags in the list are added to ``active_breakpoints``.
        activate: bool
            Whether or not the breakpoint is always active. If ``activate==False`` then
            the breakpoint will only interrupt the code if one of it's tags is contained
            in ``active_breakpoints``.
        max_usage: int
            Maximum number of times a breakpoint will remain active. If ``max_usage==0`` then
            the breakpoint will always be active, otherwise after ``max_usage`` calls the
            breakpoint will no longer interrupt the code. On the last use the user will be
            notified that the breakpoint is about to expire, at which point it could
            be reset by the user.
        exit: bool
            If ``exit==True`` the code will exit after the user exits the IPython console,
            otherwise the code will continue running.
        log: str or func
            If log is a string then logging.info will log the string when the breakpoint
            is called. If log is a function then when the breakpoint is called logging.info
            will log the result of the function, called with locals() as the argument
            (allowing the user to log any of the local variables)
        """
        if activate_tags:
            if isinstance(activate_tags, bool):
                activate_breakpoint(tags)
            else:
                activate_breakpoint(activate_tags)
        # Number of times this breakpoint has been used
        self.breaks = 0
        self.tags = tags
        self.active = activate
        self.max_usage = max_usage
        self.exit = exit
        self.log = log

    def break_here(self, force=False, exit=False):
        """
        Interrupt the code at the present location.

        Parameters
        ----------
        force: bool
            If ``force==True`` the code will be interrupted even if the breakpoint is
            not activated and none of it's tags are in ``active_breakpoints``.
        exit: bool
            If ``exit==True`` the code will exit when the user exits the IPython
            console.
        """
        # Make the local variables from the function with the breakpoint
        # available in the local scope
        local_vars = inspect.stack()[1][0].f_locals
        for var in local_vars:
            locals()[var] = local_vars[var]
        # Log the breakpoint
        if self.log is not None:
            if inspect.isfunction(self.log):
                log = self.log(locals())
            else:
                log = self.log
            logging.debug(log)
        # Check to see if the breakpoint should interrupt the code
        if ((self.active or force or any([tag in active_breakpoints for tag in self.tags]))
                and (self.max_usage is None or self.breaks<self.max_usage)):
            self.breaks += 1
            if self.breaks==self.max_usage:
                logging.warning(("You have reached the maximum number of calls to "
                    "interrupt the code with this function. If you want to continue to "
                    "use this breakpoint you must modify self.breaks or self.max_usage\n\n"))
            try:
                import IPython
                IPython.embed()
            except ImportError:
                raise Exception("You must have ipython installed to use break points")
        if self.exit or exit:
            sys.exit()