import asyncio
from datetime import datetime

from pytz import UTC
from discord import Intents, Embed, TextChannel, Role
from discord.ext.commands import Bot, Context
from discord.member import Member
from bson import ObjectId
from bson.errors import InvalidId
from gflbans.api_util import construct_ci_resp
from gflbans.discord.colors import COLOR_ERROR, COLOR_INFO
from gflbans.discord.compat import DiscordApp
from gflbans.internal.config import DISCORD_BOT_TOKEN, FORUMS_HOST, HOST, MONGO_DB, ROOT_USER
from gflbans.internal import VERSION
from subprocess import PIPE, Popen
import sys
from typing import List, Optional
from gflbans.discord.auth import checkaccess, generate_confirmation_link, get_gfl_admin, update_confirmations
from gflbans.internal.constants import NOT_AUTHED_USER, SERVER_KEY
from gflbans.internal.database.group import DGroup
from gflbans.internal.database.infraction import build_query_dict
from gflbans.internal.database.server import DServer
from gflbans.internal.flags import ALL_PERMISSIONS, PERMISSION_ADMIN_CHAT_BLOCK, PERMISSION_BAN, PERMISSION_BLOCK_CHAT, PERMISSION_BLOCK_VOICE, PERMISSION_CALL_ADMIN_BLOCK, PERMISSION_CREATE_INFRACTION, PERMISSION_MANAGE_SERVERS, PERMISSION_SCOPE_GLOBAL, PERMISSION_VIEW_AUDIT_LOG
from gflbans.internal.integrations.games import get_user_info, normalize_id
from gflbans.internal.integrations.ips import get_groups
from gflbans.internal.kv import set_var
from gflbans.internal.loader import configure_app

bot = Bot(command_prefix='g!', description=f'GFLBans v{VERSION}', intents=Intents.default())

@bot.event
async def on_ready():
    await set_var(bot.app.state.db[MONGO_DB], 'bot.name', bot.user.name)
    await set_var(bot.app.state.db[MONGO_DB], 'bot.avatar', str(bot.user.avatar_url))
    asyncio.get_running_loop().create_task(update_confirmations(bot))

def run_shell(command: List[str]) -> str:
    return Popen(command, stdout=PIPE).communicate()[0].decode('utf-8')

@bot.command(name='status')
#@requireaccess(access=PERMISSION_VIEW_AUDIT_LOG)
async def status(ctx: Context):
    if not await checkaccess(ctx, access=PERMISSION_VIEW_AUDIT_LOG):
        return

    uname = run_shell(['uname', '-a'])
    memory = run_shell(['free', '-h'])
    iostat = run_shell(['iostat', '-c'])
    gflbans = f'GFLBans v{VERSION} running on Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}'

    embed = Embed(colour=COLOR_INFO, title=gflbans)
    embed.add_field(name='Output of `uname -a`:', value=f'```\n{uname}\n```', inline=False)
    embed.add_field(name='Output of `free -h`:', value=f'```\n{memory}\n```', inline=False)
    embed.add_field(name='Output of `iostat -c`:', value=f'```\n{iostat}\n```', inline=False)
    embed.set_footer(text=f'GFLBans {VERSION}', icon_url=f'https://{HOST}/static/images/gflbans256.png')
    await ctx.reply(embed=embed)

@bot.command(name='testconfirm')
async def confirmlink(ctx: Context):
    adm = await get_gfl_admin(ctx.bot.app, ctx.author)

    if not await checkaccess(ctx, access=PERMISSION_VIEW_AUDIT_LOG, adm=adm):
        return

    await generate_confirmation_link(ctx, adm.ips_id, 'pass', [])

@bot.command(name='cantrunthis')
async def impossible_command(ctx: Context):
    if not await checkaccess(ctx, access=214748364787534789457893807592387905432):
        return
    await ctx.reply('You should not see this!')

@bot.command(name='whoami')
async def whois(ctx: Context, target: Member = None):
    if target is None:
        target = ctx.author

    adm = await get_gfl_admin(ctx.bot.app, target)

    if adm is None:
        return await ctx.reply(embed=Embed(colour=COLOR_ERROR, title='Good Question!', description=f'I do not know who you are!\n\nCould not find an admin associated with your Discord account. Add your Discord account as a login method to https://{FORUMS_HOST}'))

    privilege_str = f'{adm.name} has permission flags {adm.permissions}'

    groups = await get_groups(ctx.bot.app)

    id_to_name = {}

    for grp in groups:
        id_to_name[grp['id']] = grp['name']

    if adm.permissions == 0:
        pass
    elif adm.ips_id == ROOT_USER:
        privilege_str += f':\n\nGFLBans Root User ({ALL_PERMISSIONS})\n'
    else:
        privilege_str += ':\n\n'

    if adm.db is not None:
        di = False
        for grp in adm.db.groups:
            di = True
            dg = await DGroup.find_one_from_query(ctx.bot.app.state.db[MONGO_DB], {'ips_group': grp})

            if dg is None or grp not in id_to_name:
                continue

            privilege_str += f'{id_to_name[grp]} ({dg.privileges})\n'

    if not di or adm.db is None:
        privilege_str += 'No Group (0)'

    em = Embed(colour=COLOR_INFO, title=adm.name, url=f'https://{FORUMS_HOST}/profile/{adm.ips_id}-user/', description=privilege_str)
    if adm.avatar:
        em.set_thumbnail(url=f'https://{HOST}/file/uploads/{adm.avatar.gridfs_file}/{adm.avatar.file_name}')

    em.set_footer(text=f'GFLBans {VERSION}', icon_url=f'https://{HOST}/static/images/gflbans256.png')

    return await ctx.reply(embed=em)

_nouns = {
    'voice_block': 'Voice Chat Block',
    'chat_block': 'Text Chat Block',
    'ban': 'Ban',
    'admin_chat_block': 'Admin Chat Block',
    'call_admin_block': 'Call Admin Block',
}

@bot.command(name='check')
async def check_infractions(ctx: Context, gsid: str, service: str = 'steam', as_server: Optional[str] = None):
    if as_server:
        actor_type = SERVER_KEY
        actor_id = as_server
    else:
        actor_type = NOT_AUTHED_USER
        actor_id = 'GFLBANSDISCORD'

    gsid = await normalize_id(ctx.bot.app, service, gsid)

    q = build_query_dict(actor_type, actor_id, gs_service=service, gs_id=gsid,
                         ip=None, ignore_others=False, active_only=True)

    ci_resp = await construct_ci_resp(ctx.bot.app.state.db[MONGO_DB], q)

    ui = await get_user_info(ctx.bot.app, service, gsid)

    embed = Embed(title=f'Restrictions for {ui["name"]}', colour=COLOR_INFO)
    embed.set_thumbnail(url=ui['avatar_url'])

    for t, cs in ci_resp.dict().items():
        if not cs: continue

        exp = 'Doesn\'t Expire.'

        if 'expiration' in cs and cs['expiration']:
            exp = f'Expires {datetime.fromtimestamp(cs["expiration"], tz=UTC).strftime("%m/%d/%Y, %H:%M:%S %Z")}.'

        embed.add_field(name=_nouns[t], value=f'"{cs["reason"]}" by {cs["admin_name"]}. {exp}', inline=False)

    embed.set_footer(text=f'GFLBans {VERSION}', icon_url=f'https://{HOST}/static/images/gflbans256.png')

    await ctx.reply(embed=embed)

@bot.command(name='setupcalladmin')
async def setup_calladmin(ctx: Context, server_id: str, channel: TextChannel, role: Role):
    adm = await get_gfl_admin(ctx.bot.app, ctx.author)

    if not await checkaccess(ctx, adm=adm, access=(PERMISSION_MANAGE_SERVERS)):
        return

    try:
        srv = await DServer.from_id(ctx.bot.app.state.db[MONGO_DB], ObjectId(server_id))

        if srv is None:
            return await ctx.reply(context=f'I could not find a server with the ID `{server_id}`.')
    except InvalidId:
        server_ip = server_id.split(':')

        srv = await DServer.find_one_from_query(ctx.bot.app.state.db[MONGO_DB], {'ip': server_ip[0], 'game_port': int(server_ip[1])})

        if not srv:
            return await ctx.reply(content=f'`{server_id}` is not a valid server ID and I could not find a server with that IP.')

    wh = (await channel.create_webhook(name='Call Admin', reason='dcl_initcalladmin')).url

    await generate_confirmation_link(ctx, adm.ips_id, 'setupcalladmin', [str(srv.id), wh, str(role.id), str(channel.id)])

bc = {
    'sgag': (('voice_block', ), PERMISSION_BLOCK_VOICE),
    'smute': (('chat_block', ), PERMISSION_BLOCK_CHAT),
    'sban': (('ban', ), PERMISSION_BAN),
    'sacblock': (('admin_chat_block', ), PERMISSION_ADMIN_CHAT_BLOCK),
    'scablock': (('call_admin_block', ), PERMISSION_CALL_ADMIN_BLOCK),
    'ssilence': (('voice_block', 'chat_block'), PERMISSION_BLOCK_CHAT | PERMISSION_BLOCK_VOICE)
}

units = {
    's': 1,
    'm': 60,
    'h': 3600,
    'd': 3600 * 24,
    'w': 3600 * 24 * 7,
    'mo': 3600 * 24 * 30,
    'y': 3600 * 24 * 365
}

for a1, a2 in bc.items():
    def comp(pv):
        async def infract_generic(ctx: Context, gs_service: str, gs_id: str, duration_v: int, duration_u: Optional[str], *, reason: str):
            adm = await get_gfl_admin(ctx.bot.app, ctx.author)

            if not await checkaccess(ctx, adm=adm, access=(PERMISSION_CREATE_INFRACTION | PERMISSION_SCOPE_GLOBAL | pv[1])):
                return

            if not duration_u:
                duration_u = 'm'

            if duration_u not in units:
                await ctx.reply(content=f'I do not know what the unit \'{duration_u}\' means. Please use s, m, h, d, w, mo, or y.')
                return

            duration = duration_v * units[duration_u]

            try:
                gs_id = await normalize_id(ctx.bot.app, gs_service, gs_id)
            except ValueError:
                return await ctx.reply(content=f'I couldn\'t use the ID {gs_service}/{gs_id}. Please verify that the ID is correct.')

            # setup dcl call
            # dcl_infract(app, caller: int, gs_service: str, gs_id: str, punishments: List[str], duration: int, reason: str)
            await generate_confirmation_link(ctx, adm.ips_id, 'infract', [gs_service, gs_id, list(pv[0]), duration, reason])

        return infract_generic

    ig = comp(a2)
    bot.command(name=a1)(ig)

def start_bot(api2disc, disc2api):
    app = DiscordApp()
    configure_app(app)
    setattr(bot, 'app', app)

    bot.run(DISCORD_BOT_TOKEN)
    bot.api2disc = api2disc
    bot.disc2api = disc2api


import sys
import cv2
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib as plt
from math import sin, cos, tan, atan, sqrt
import time
import copy
import window_wrapper as ww

def main():

    base_path = 'C:\\Users\\spenc\\Dropbox (MIT)\\2.671 Go Forth and Measure\\'
    num = 7
    t1 = 'jump1_AdobeExpress.mp4'
    steven = 'Steven\\mp4\\steven' + str(num) + '.mp4'
    jackson = 'Jackson\\mp4\\jackson' + str(num) + '.mp4'

    first_view = True
    i_markers = []

    while True:

        track_points = 3

        # Add in a slider, effectively, dividing saturation and value
        # Smart dynamic thresholding?
        #Detect all points first, then sort by comparing to previous points
        # Keeps last confidence score for point
        # Replays from pandas array rather than recalculating every time
        code = 2
        if code == 0:
            _Frame = ww.WindowWrapper('frame', track_points,
                                      #fpath=base_path + t1,
                                      marker_buffer=0.02, rsz_factor=0.85, init_frms=i_markers, hue_buffer=0.02,
                                      sat_val_buffer=0.25, proximity_weight=0, testing=False, auto_color=True,
                                      data_output=True)
        elif code == 1:
            _Frame = ww.WindowWrapper('frame', track_points,
                                      fpath=base_path + t1,
                                      marker_buffer=0.015, rsz_factor=0.85, init_frms=i_markers, hue_buffer=0.02,
                                      sat_val_buffer=0.55, proximity_weight=0, testing=False, auto_color=True,
                                      data_output=True)
        else:
            _Frame = ww.WindowWrapper('frame', track_points,
                                      fpath=base_path + steven,
                                      marker_buffer=0.012, rsz_factor=0.5, init_frms=i_markers, hue_buffer=0.012,
                                      sat_val_buffer=0.35, proximity_weight=0, testing=False, auto_color=True,
                                      data_output=True)

        first_frame = True
        retv = _Frame.get_retrieval_state()

        while retv:
            # Capture a frame from the webcam
            retv, oframe, frame = _Frame.next_frame()

            if retv:

                corners, frames, tls = _Frame.subimage(first_view, first_frame)

                for i, frame in enumerate(frames):
                    if not first_frame:
                        _Frame.update_contours()
                    _Frame.analyze_contours(first_view, first_frame)

                # Quit if user presses q
                key = cv2.waitKey(1)
                if key & 0xFF == ord('q'):
                    exit(0)

                '''
                # Quit if user presses q, next frame if user presses n
                while True:
                    key = cv2.waitKey(1)
                    if key & 0xFF == ord('q'):
                        exit(0)
                    elif key & 0xFF == ord('n'):
                        break
                '''
                _Frame.show()

            else:
                # Quit if u#ser presses q
                key = cv2.waitKey(1)
                if key & 0xFF == ord('q'):
                    exit(0)

            first_frame = False

        i_markers = _Frame.get_initial_markers()

        if first_view:
            print(_Frame.get_data())

        first_view = False

        key = cv2.waitKey(1) & 0xFF
        while key != ord('q') and key != ord('p'):
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                exit(0)

if __name__ == '__main__':
    main()

'''
def track(fpath, color, points, reg='circ'):
    if reg == 'circ':
        reg_fn = regularity_c
    else:
        reg_fn = regularity

    track_points = points
    all_points = []
    for i in range(points):
        all_points.append([])

    if 'C:' not in fpath:
        fpath = 'C:\\Users\\spenc\\Dropbox (MIT)\\2.671 Go Forth and Measure\\' + fpath

    markers = [(0, 0)] * track_points
    r_markers = [(0, 0)] * track_points

    # Min and max HSV thresholds for target color
    if color == 'w':
        COLOR_THRESHOLD = ([0, 0, 180], [60, 60, 255])  # White
    else:
        COLOR_THRESHOLD = ([20, 100, 100], [35, 255, 255])  # Yellow

    # cap is a VideoCapture object we can use to get frames from webcam
    cap = cv2.VideoCapture(fpath)

    first = True
    retv = True

    #fnum = 0

    while retv:
        # Capture a frame from the webcam
        retv, frame = cap.read()
        #print('frame', fnum)
        #fnum += 1

        if retv:
            f_w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
            f_h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

            if not first:
                corners, frames, tls = subimage(frame, markers)
            else:
                corners, frames, tls = subimage_gen_empty(frame, markers)

            for i, frame in enumerate(frames):
                # Convert BGR to HSV
                hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

                # OpenCV needs bounds as numpy arrays
                lower_color_bound = np.array(COLOR_THRESHOLD[0])
                upper_color_bound = np.array(COLOR_THRESHOLD[1])

                mask_color = cv2.inRange(hsv, lower_color_bound, upper_color_bound)
                contours_color, _ = cv2.findContours(mask_color, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

                # If we have contours...
                if len(contours_color) != 0:

                    # Find the biggest contour by area
                    #g = max(contours_color, key=cv2.contourArea)

                    if first:
                        # Find the most circular contour by hull area
                        cc_list = list(contours_color)
                        cc_list.sort(reverse=True, key=reg_fn)
                        contours_color = cc_list
                        #contours_color = [max(contours_color, key=regularity)]
                        max_significant = 3
                        for j in range(max_significant):
                            circle = contours_color[j]

                            # Get a bounding rectangle around that contour
                            #x, y, w, h = cv2.boundingRect(circle)
                            c, r = cv2.minEnclosingCircle(circle)

                            markers[j] = (int(c[0]), int(c[1]))
                            r_markers[j] = (int(c[0]), int(c[1]))

                            all_points[j].append(markers[j])
                    else:
                        contours_color = max(contours_color, key=reg_fn)
                        c, r = cv2.minEnclosingCircle(contours_color)

                        r_markers[i] = (int(c[0])+1, int(c[1])+1)
                        markers[i] = (tls[i][0]+r_markers[i][0], tls[i][1]+r_markers[i][1])

                        all_points[i].append(markers[i])

        first = False
    df_x = []
    df_y = []
    for single_point in all_points:
        sparr = np.array(single_point)
        df_x.append(sparr[:, 0:1])
        df_y.append(sparr[:, 1:2])
    df_x = tuple(df_x)
    df_y = tuple(df_y)
    df_x = pd.DataFrame(np.hstack(df_x))
    df_y = pd.DataFrame(np.hstack(df_y))
    return df_x, df_y
'''

'''
                    # If we have contours...
                    print('frame')
                    if len(contours) != 0:
                        print('contours!')

                        # Find the biggest contour by area
                        #g = max(contours_color, key=cv2.contourArea)

                        if redo and first:
                            markers = _Frame.set_initial_points()
                        elif first:
                            if auto_select:
                                # Find the most circular contour by hull area
                                cc_list = list(contours_color)
                                cc_list.sort(reverse=True, key=regularity_c)
                                contours_color = cc_list
                                #contours_color = [max(contours_color, key=regularity)]
                                max_significant = 3
                                for j in range(max_significant):
                                    circle = contours_color[j]

                                    # Get a bounding rectangle around that contour
                                    #x, y, w, h = cv2.boundingRect(circle)
                                    c, r = cv2.minEnclosingCircle(circle)

                                    markers[j] = (int(c[0]), int(c[1]))
                                    r_markers[j] = (int(c[0]), int(c[1]))

                                    # Draw the rectangle on our frame
                                    #cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 208, 255), 2)

                                    #Draw the circle on the frame
                                    cv2.circle(oframe, (markers[j][0], markers[j][1]), int(r), (0, 255, 0), 2)

                                    #multiline used to start here Draws lines in the first frame, sometimes causes big skips
                                    for k, pt in enumerate(markers):
                                        if k < len(markers)-1:
                                            cv2.line(oframe, (markers[k][0], markers[k][1]), (markers[k+1][0], markers[k+1][1]), (0, 0, 255), 3)
                                    #and end here
                            else:
                                cv2.imshow('frame', cv2.resize(oframe, (adj_x, adj_y)))
                                while len(wrapped_window.get_markers()) < track_points:
                                    key = cv2.waitKey(1) & 0xFF
                                    if key == ord('q'):
                                        exit(1)
                                markers = wrapped_window.get_markers()
                                first_markers = wrapped_window.get_markers()

                        else:
                            contours_color = max(contours_color, key=regularity_c)
                            c, r = cv2.minEnclosingCircle(contours_color)
                            print(c, r)

                            r_markers[i] = (int(c[0])+1, int(c[1])+1)
                            markers[i] = (tls[i][0]+r_markers[i][0], tls[i][1]+r_markers[i][1])

                            #Draw the circle on the frame
                            cv2.circle(oframe, (markers[i][0], markers[i][1]), int(r), (0, 255, 0), 2)

                            #Draw framing rectangles
                            cv2.rectangle(oframe, (corners[i][0][0], corners[i][0][1]),
                                          (corners[i][1][0], corners[i][1][1]), (255, 0, 0), 2)
                            cv2.circle(oframe, (corners[i][0][0], corners[i][0][1]), 10, (255, 0, 0), 2)

                            for k, pt in enumerate(markers):
                                if k < len(markers)-1:
                                    cv2.line(oframe, (markers[k][0], markers[k][1]), (markers[k+1][0], markers[k+1][1]), (0, 0, 255), 5)

                    # Display that frame (resized to be smaller for convenience)
                    #cv2.imshow('color mask', cv2.resize(mask_color, (adj_x, adj_y)))

                    #if not first:
                    #    cv2.circle(frame, (r_markers[i][0], r_markers[i][1]), 1, (0, 0, 255), 3)
                    #    cv2.imshow('subframe', frame)

                    #multiline used to start here
                    lines = []
                    for i, center in enumerate(markers):
                        if not i == len(markers)-1:
                            lines.append(((markers[i][0], markers[i][1]), (markers[i+1][0], markers[i+1][1])))
                    cv2.drawContours(oframe, lines, (0, 0, 255), 5)
                    # and end here

                    if not (auto_select and first):
                        cv2.imshow('frame', cv2.resize(oframe, (adj_x, adj_y)))
                    redo = True
                    #print(markers)
'''

'''

def regularity(contour, tp='rect'):
    if tp == 'rect':
        hull = cv2.contourArea(cv2.convexHull(contour))
        (x, y), (w, h), _ = cv2.minAreaRect(contour)
        if w == 0 or h == 0:
            res = -1
        else:
            res = hull/(w*h)
    else:
        hull = cv2.contourArea(cv2.convexHull(contour))
        _, r = cv2.minEnclosingCircle(contour)
        circ = 3.1415*r**2
        res = -abs(hull/circ - 1)
        if r < 3:
            res = -10
    return res

def regularity_c(contour):
    return regularity(contour, tp='circ')

def subimage_gen_empty(frame, centers):
    corners = []
    tls = []
    for center in centers:
        tl_x = 0
        tl_y = 0
        br_x = 100
        br_y = 100
        # X positive moving right, Y positive moving down, (0, 0) in top left
        corners.append([(tl_x, tl_y), (br_x, br_y)])
        tls.append([tl_x, tl_y])
    subframes = [frame]
    return corners, subframes, tls

def auto_select(frame, contours, markers, rel_markers):
    if auto_select:
        # Find the most circular contour by hull area
        cc_list = list(contours)
        cc_list.sort(reverse=True, key=regularity_c)
        contours = cc_list
        # contours_color = [max(contours_color, key=regularity)]
        max_significant = len(markers)
        for j in range(max_significant):
            circle = contours[j]

            # Get a bounding rectangle around that contour
            # x, y, w, h = cv2.boundingRect(circle)
            c, r = cv2.minEnclosingCircle(circle)

            markers[j] = (int(c[0]), int(c[1]))
            rel_markers[j] = (int(c[0]), int(c[1]))

            # Draw the rectangle on our frame
            # cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 208, 255), 2)

            # Draw the circle on the frame
            cv2.circle(frame, (markers[j][0], markers[j][1]), int(r), (0, 255, 0), 2)
'''


import sys

#	Load a manifest file.
#	Run through it line by line, assume each line is either blank, a comment, or a filepath.
#	All filepaths in the manifest are interpreted as relative to the location of the manifest, or a working directory.
#	Each file will be loaded as binary, put into a character array, and a size will be stored with it.
#	A header will be generated defining the array of embedded files, and a cmake target will be created to encapsulate it.

#	Usage
#	 cembed -i <manifest_file> -o <output_file>

#	Options
#	 --version                   = Print a version string
#	 --help                      = Print this help string
#	 --output,-o    <name>       = (REQUIRED) Specify the name of the source file to generate, expects something like {name}.c
#	 --input,-i     <manifest>   = (REQUIRED) The location of the manifest file to use, must be an actual filename
#	 --header       <name>       = Specify the name of the header file to generate, otherwise inferred from output name
#	 --dir,-d       <directory>  = Change the working directory to source manifest files from
#	 --namespace,-n <name>       = Specify a custom namespace for the embedded files

version_str = "cembed version 0.1.0"

help_str = """Usage
	cembed - i <manifest_file> -o <output_file>

	Options
	 --version = Print a version string
	 --help = Print this help string
	 --output,-o <name> = (REQUIRED) Specify the name of the source file to generate, expects something like {name}.c
	 --input,-i  <manifest> = (REQUIRED) The location of the manifest file to use, must be an actual filename
	 --header    <name> = Specify the name of the header file to generate, otherwise inferred from output name
	 --dir,-d    <directory> = Change the working directory to source manifest files from"""

class Token:
	def __init__(self, kind, text):
		self.kind = kind
		self.text = text

class Node:
	def __init__(self, kind, data):
		self.kind = kind
		self.data = data

def lex(text):
	if len(text) == 0:
		raise Exception("Empty text argument passed to lex function!")
	elif text[0] == '-':
		if text == "--help":
			return Token(kind="help", text=None)
		elif text == "-i" or text == "--input":
			return Token(kind="input", text=None)
		elif text == "-o" or text == "--output":
			return Token(kind="output", text=None)
		elif text == "-d" or text == "--dir":
			return Token(kind="directory", text=None)
		elif text == "-i" or text == "--input":
			return Token(kind="input", text=None)
		elif text == "--header":
			return Token(kind="header", text=None)
		elif text == "--version":
			return Token(kind="version", text=None)
		else:
			raise Exception("Invalid argument for cembed found: '{arg}'".format(arg = text))
	else:
		return Token(kind="text", text=text)

def parse(args):
	toks = []
	for arg in args:
		toks.append(lex(arg))

	nodes = []
	toks.reverse()
	while len(toks) != 0:
		tok = toks.pop()
		if tok.kind == "help":
			nodes.append(Node(kind="help", data=None))

		elif tok.kind == "input":
			ntok = toks.pop()
			if ntok.kind == "text":
				nodes.append(Node(kind="input", data=ntok.text))
			else:
				raise Exception("Expected a text argument after -i,--input!")

		elif tok.kind == "output":
			ntok = toks.pop()
			if ntok.kind == "text":
				nodes.append(Node(kind="output", data=ntok.text))
			else:
				raise Exception("Expected a text argument after -o,--output!")

		elif tok.kind == "directory":
			ntok = toks.pop()
			if ntok.kind == "text":
				nodes.append(Node(kind="directory", data=ntok.text))
			else:
				raise Exception("Expected a text argument after -d,--dir!")

		elif tok.kind == "header":
			ntok = toks.pop()
			if ntok.kind == "text":
				nodes.append(Node(kind="header", data=ntok.text))
			else:
				raise Exception("Expected a text argument after -h,--header!")

		elif tok.kind == "version":
			nodes.append(Node(kind="", data=version_str))
		elif tok.kind == "text":
			raise Exception("Unexpected text argument for cembed found: '{arg}'".format(arg=tok.text))

	return nodes

if __name__ == "__main__":
	args = sys.argv.copy()
	args.pop(0)

	nodes = parse(args)


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        heap = []

        for head in lists:
            while head:
                heapq.heappush(heap, head.val)
                head = head.next

        new_head = ListNode()
        cur = new_head

        while heap:
            num = heapq.heappop(heap)
            cur.next = ListNode(num)
            cur = cur.next

        return new_head.next


from game.level import Tile, get_available_directions, is_wall
from game.util import rate_limit, ALL_DIRECTIONS, Direction
from typing import List
import math
from math import floor
import abc

# base class for object that moves around a maze
class Mover:
    __metaclass__ = abc.ABCMeta

    def __init__(self, x, y, speed):
        self.x = x
        self.y = y
        # last block
        self.last_x = x
        self.last_y = y
        self.start_x = x
        self.start_y = y
        self.direction = Direction.RIGHT
        self.last_direction = Direction.RIGHT  # more recent non None direction
        self.speed = speed

    # as a property to enforce overriding
    @property
    @abc.abstractmethod
    def cornercut(cls) -> float:
        pass

    def step(self, dt, level_map: List[List[Tile]]):
        # keep track of the last tile we were on
        # if about to move to a new tile set last to current
        if floor(self.x + self.direction.value[0]*dt*self.speed) != floor(self.x):
            self.last_x = floor(self.x)
        if floor(self.y + self.direction.value[1]*dt*self.speed) != floor(self.y):
            self.last_y = floor(self.y)

        self.x += self.direction.value[0] * dt * self.speed
        self.y += self.direction.value[1] * dt * self.speed

        # snap to grid
        if abs(self.direction.value[0]) == 0:
            self.x = rate_limit(self.x, math.floor(self.x) + 0.5, self.speed * dt)

        if abs(self.direction.value[1]) == 0:
            self.y = rate_limit(self.y, math.floor(self.y) + 0.5, self.speed * dt)

        avalible_directions = get_available_directions(level_map, (self.x, self.y))
        if self.direction not in avalible_directions:
            self.direction = Direction.NONE

        new_dir = self.check_new_direction(level_map)
        if (
            new_dir in avalible_directions
            and abs(self.x % 1 - 0.5) < self.cornercut
            and abs(self.y % 1 - 0.5) < self.cornercut
        ):
            self.direction = new_dir

        if not self.direction is None:
            self.last_direction = self.direction

        # looping
        self.x = self.x % len(level_map[0])
        self.y = self.y % len(level_map)

    def check_collisions(self, other: "Mover"):
        return (
            self.x + 0.75 > other.x + 0.25
            and self.x + 0.25 < other.x + 0.75
            and self.y + 0.75 > other.y + 0.25
            and self.y + 0.25 < other.y + 0.75
        )

    def euc_dist(self, other: 'Mover'):
        """Returns the euclidean distance to another Mover"""
        return math.hypot(self.x-other.x, self.y-other.y)

    def man_dist(self, other: 'Mover'):
        """Returns the manhattan distance to another Mover"""
        return abs(self.x-other.x) + abs(self.y-other.y)

    def reset(self):
        self.x = self.start_x
        self.y = self.start_y
        self.direction = Direction.NONE

    # to be implimented by sub classes
    @abc.abstractmethod
    def check_new_direction(self, _) -> Direction:
        raise NotImplementedError

    @abc.abstractmethod
    def draw(self, screen, offset, grid_size):
        raise NotImplementedError


from WorkWithStringList import check_one_type_items_in_list, delete_item_in_list, get_list_as_string, get_new_list_with, get_new_list_without_item, glue_two_string_lists
import unittest

class Test_WorkWithStringList(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_get_new_list_without_item(self):

        self.assertEqual(type(get_new_list_without_item(
            ['a', 'b', 'c', 'd'], 'd')), list)

        self.assertEqual(get_new_list_without_item(
            ['a', 'b', 'c', 'd'], 'd'), ['a', 'b', 'c'])

        # (it should be) call error TypeError('All items in the list must be type of str')
        # self.assertEqual(get_new_list_without_item(
        #     ['a', 'b', 1, 'd'], 'd'), ['a', 'b', 1])

        with self.assertRaises(ValueError):
            self.assertEqual(get_new_list_without_item(
                ['a', 'b', 'c', 'd'], 'e'), ['a', 'b', 'c', 'd'])

            self.assertEqual(get_new_list_without_item(
                ['a', 'b', 'c', 'd'], 1
            ))

    def test_check_one_type_items_in_list(self):

        self.assertIsNone(check_one_type_items_in_list(['a', 'b', 'c']))
        self.assertIsNone(check_one_type_items_in_list([1, 2, 3], int))

        with self.assertRaises(TypeError):
            self.assertEqual(check_one_type_items_in_list(['a', 'b', 1], str))

    def test_get_list_as_string(self):
        self.assertEqual(
            get_list_as_string(['a', 'b', 'c']), 'a, b, c')

        with self.assertRaises(TypeError):
            self.assertEqual(
                get_list_as_string(['a', 'b', 1]), 'a, b, 1')

    def test_get_new_list_with(self):

        self.assertEqual(get_new_list_with(['a', 'b', 'c'], 'r.', ',', True),
                         ['r.a,', 'r.b,', 'r.c']
                         )

        self.assertEqual(get_new_list_with(['a', 'b', 'c'], 'r.', ',', False),
                         ['r.a,', 'r.b,', 'r.c,']
                         )

    def test_glue_two_string_lists(self):

        self.assertEqual(glue_two_string_lists(['a', 'b', 'c'], ['d', 'e', 'f'], ' = '),
                         ['a = d', 'b = e', 'c = f']
                         )

unittest.main()


""" A module containing the necessary constants, enumerations, classes, etc., that have to be used
by numerous other modules.
"""

import os
import math
from functools import partial

from enum import Enum
from perun.utils.structs import OrderedEnum
import perun.utils as utils
import perun.utils.metrics as metrics

class Optimizations(Enum):
    """ Enumeration of the implemented methods and their CLI name.
    """
    BASELINE_STATIC = 'baseline-static'
    BASELINE_DYNAMIC = 'baseline-dynamic'
    CALL_GRAPH_SHAPING = 'cg-shaping'
    DYNAMIC_SAMPLING = 'dynamic-sampling'
    DIFF_TRACING = 'diff-tracing'
    DYNAMIC_PROBING = 'dynamic-probing'
    TIMED_SAMPLING = 'timed-sampling'

    @staticmethod
    def supported():
        """ List the currently supported optimization methods.

        :return list: CLI names of the supported optimizations
        """
        return [optimization.value for optimization in Optimizations]

class Pipeline(Enum):
    """ Enumeration of the implemented pipelines and their CLI name.
    Custom represents a defualt pipeline that has no pre-configured methods or parameters
    """
    CUSTOM = 'custom'
    BASIC = 'basic'
    ADVANCED = 'advanced'
    FULL = 'full'

    @staticmethod
    def supported():
        """ List the currently supported optimization pipelines.

        :return list: CLI names of the supported pipelines
        """
        return [pipeline.value for pipeline in Pipeline]

    @staticmethod
    def default():
        """ Name of the default pipeline.

        :return str: the CLI name of the default pipeline
        """
        return Pipeline.CUSTOM.value

    def map_to_optimizations(self):
        """ Map the selected optimization pipeline to the set of employed optimization methods.

        :return list: list of the Optimizations enumeration objects
        """
        if self == Pipeline.BASIC:
            return [Optimizations.CALL_GRAPH_SHAPING, Optimizations.BASELINE_DYNAMIC]
        if self == Pipeline.ADVANCED:
            return [
                Optimizations.DIFF_TRACING, Optimizations.CALL_GRAPH_SHAPING,
                Optimizations.BASELINE_DYNAMIC, Optimizations.DYNAMIC_SAMPLING
            ]
        if self == Pipeline.FULL:
            return [
                Optimizations.DIFF_TRACING, Optimizations.CALL_GRAPH_SHAPING,
                Optimizations.BASELINE_STATIC, Optimizations.BASELINE_DYNAMIC,
                Optimizations.DYNAMIC_SAMPLING, Optimizations.DYNAMIC_PROBING,
            ]
        return []

class CallGraphTypes(Enum):
    """ Enumeration of the implemented call graph types and their CLI names.
    """
    STATIC = 'static'
    DYNAMIC = 'dynamic'
    MIXED = 'mixed'

    @staticmethod
    def supported():
        """ List the currently supported call graph types.

        :return list: CLI names of the supported cg types
        """
        return [cg.value for cg in CallGraphTypes]

    @staticmethod
    def default():
        """ Name of the default cg type.

        :return str: the CLI name of the default cg type
        """
        return CallGraphTypes.STATIC.value

class Parameters(Enum):
    """ Enumeration of the currently supported CLI options for optimization methods and pipelines.
    """
    DIFF_VERSION = 'diff-version'
    DIFF_KEEP_LEAF = 'diff-keep-leaf'
    DIFF_INSPECT_ALL = 'diff-inspect-all'
    DIFF_CG_MODE = 'diff-cfg-mode'
    SOURCE_FILES = 'source-files'
    SOURCE_DIRS = 'source-dirs'
    STATIC_COMPLEXITY = 'static-complexity'
    STATIC_KEEP_TOP = 'static-keep-top'
    CG_SHAPING_MODE = 'cg-mode'
    CG_PROJ_LEVELS = 'cg-proj-levels'
    CG_PROJ_KEEP_LEAF = 'cg-proj-keep-leaf'
    DYNSAMPLE_STEP = 'dyn-sample-step'
    DYNSAMPLE_THRESHOLD = 'dyn-sample-threshold'
    PROBING_THRESHOLD = 'probing-threshold'
    PROBING_REATTACH = 'probing-reattach'
    TIMEDSAMPLE_FREQ = 'timed-sample-freq'
    DYNBASE_SOFT_THRESHOLD = 'dyn-base-soft-threshold'
    DYNBASE_HARD_THRESHOLD = 'dyn-base-hard-threshold'
    THRESHOLD_MODE = 'threshold-mode'

    @staticmethod
    def supported():
        """ List the currently supported optimization parameters.

        :return list: CLI names of the supported parameters
        """
        return [parameter.value for parameter in Parameters]

class DiffCfgMode(Enum):
    """ Enumeration of the currently supported CFG comparison mode.
    """
    COLORING = 'color'
    SOFT = 'soft'
    SEMISTRICT = 'semistrict'
    STRICT = 'strict'

    @staticmethod
    def supported():
        """ List the currently supported CFG comparison modes.

        :return list: CLI names of the supported modes
        """
        return [mode.value for mode in DiffCfgMode]

class CGShapingMode(Enum):
    """ Enumeration of the currently supported Call Graph Shaping modes.
    """
    MATCH = 'match'
    BOTTOM_UP = 'bottom-up'
    TOP_DOWN = 'top-down'

    @staticmethod
    def supported():
        """ List the currently supported Call Graph Shaping modes.

        :return list: CLI names of the supported modes
        """
        return [mode.value for mode in CGShapingMode]

class ThresholdMode(Enum):
    """ Enumeration of the currently supported threshold modes.
    """
    SOFT = 'soft'
    STRICT = 'strict'

    @staticmethod
    def supported():
        """ List the currently supported Threshold modes.

        :return list: CLI names of the supported modes
        """
        return [mode.value for mode in ThresholdMode]

class Complexity(OrderedEnum):
    """ Enumeration of the complexity degrees that we distinguish in the Bounds collector output.
    """
    # Polynomial-to-complexity map
    _ignore_ = ['map']

    # Complexities
    ZERO = 'zero'
    CONSTANT = 'constant'
    LINEAR = 'linear'
    QUADRATIC = 'quadratic'
    CUBIC = 'cubic'
    QUARTIC = 'quartic'
    GENERIC = 'generic'

    @staticmethod
    def supported():
        """ List the currently supported Complexity degrees.

        :return list: CLI names of the supported complexities
        """
        return [complexity.value for complexity in Complexity]

    @staticmethod
    def max(values):
        """ Compare a collection of Complexity values and select the one with maximum degree.

        :param collection values: the set of Complexity values

        :return Complexity: the Complexity object with the highest degree of polynomial
        """
        return sorted(values, key=lambda complexity: complexity.order, reverse=True)[0]

    @classmethod
    def from_poly(cls, polynomial):
        """ Create a Complexity object from string representing a polynomial.

        :param str polynomial: a string representation of a supported polynomial

        :return Complexity: the corresponding Complexity object
        """
        return Complexity.map.get(polynomial, cls.GENERIC)

Complexity.map = {
    'O(1)': Complexity.CONSTANT,
    'O(n^1)': Complexity.LINEAR,
    'O(n^2)': Complexity.QUADRATIC,
    'O(n^3)': Complexity.CUBIC,
    'O(n^4)': Complexity.QUARTIC
}

class ParametersManager:
    """ Class that parses and stores the user-supplied optimization parameters, as well as predicts
    suitable values for the optimization parameters that were not supplied.

    :ivar list cli_params: contains the list of user-supplied parameters before they are applied
    :ivar dict param_map: stores the default values for all parameters and provides a function
                          to validate the user-supplied values.

    """
    def __init__(self):
        """ Initializes all of the optimization parameters to their default values.
        """
        # Keep leaves when the number of profiled functions is low enough
        self._functions_keep_leaves = 20
        # Keep top 10% of call graph levels, however minimum of 1
        self._keep_top_ratio = 0.1
        self._default_keep_top = 1
        # Call graph default levels to keep: top 50%, minimum 2 levels
        self._levels_ratio = 0.5
        self._default_min_levels = 2
        # Pruning chain length: minimum 1 - i.e. only leaf nodes kept
        self._default_chain_length = 1
        # Default sampling step does not scale
        self._default_sampling_step = 2
        # Soft function call threshold for dynamic baseline / sampling is set 10000
        self._threshold_soft_base = 10000
        # Strict function call threshold is set to 1000
        self._threshold_strict_base = 1000
        # Hard function call threshold used by dynamic baseline is 100x more than the used threshold
        self._hard_threshold_coefficient = 100
        # Dynamic probing threshold is set to 100000, however multiplied by 0.2 in reattach mode
        self._probing_threshold = 100000
        self._probing_reattach_coefficient = 0.2

        self.cli_params = []
        self.param_map = {
            # TODO: add proper check
            Parameters.DIFF_VERSION: {
                'value': None,
                'validate': lambda x: x
            },
            Parameters.DIFF_KEEP_LEAF: {
                'value': False,
                'validate': self._validate_bool
            },
            Parameters.DIFF_INSPECT_ALL: {
                'value': True,
                'validate': self._validate_bool
            },
            Parameters.DIFF_CG_MODE: {
                'value': DiffCfgMode.SEMISTRICT,
                'validate': partial(self._validate_enum, DiffCfgMode)
            },
            Parameters.SOURCE_FILES: {
                'value': [],
                'validate': self._validate_path
            },
            Parameters.SOURCE_DIRS: {
                'value': [],
                'validate': self._validate_path
            },
            Parameters.STATIC_COMPLEXITY: {
                'value': Complexity.CONSTANT,
                'validate': partial(self._validate_enum, Complexity)
            },
            Parameters.STATIC_KEEP_TOP: {
                'value': self._default_keep_top,
                'validate': self._validate_uint
            },
            Parameters.CG_SHAPING_MODE: {
                'value': CGShapingMode.MATCH,
                'validate': partial(self._validate_enum, CGShapingMode)
            },
            Parameters.CG_PROJ_LEVELS: {
                'value': self._default_chain_length,
                'validate': self._validate_uint
            },
            Parameters.CG_PROJ_KEEP_LEAF: {
                'value': False,
                'validate': self._validate_bool
            },
            Parameters.DYNSAMPLE_STEP: {
                'value': self._default_sampling_step,
                'validate': self._validate_ufloat
            },
            Parameters.DYNSAMPLE_THRESHOLD: {
                'value': self._threshold_soft_base,
                'validate': self._validate_uint
            },
            Parameters.PROBING_THRESHOLD: {
                'value': self._probing_threshold,
                'validate': self._validate_uint
            },
            Parameters.PROBING_REATTACH: {
                'value': False,
                'validate': self._validate_bool
            },
            Parameters.TIMEDSAMPLE_FREQ: {
                'value': 1,
                'validate': self._validate_uint
            },
            Parameters.DYNBASE_SOFT_THRESHOLD: {
                'value': self._threshold_soft_base,
                'validate': self._validate_uint
            },
            Parameters.DYNBASE_HARD_THRESHOLD: {
                'value': self._threshold_soft_base * self._hard_threshold_coefficient,
                'validate': self._validate_uint
            },
            Parameters.THRESHOLD_MODE: {
                'value': ThresholdMode.SOFT,
                'validate': partial(self._validate_enum, ThresholdMode)
            }
        }

    def __getitem__(self, item):
        """ Allows quick access to parameter values in the param_map

        :param Parameters item: the parameter we want value for

        :return object: the corresponding value
        """
        return self.param_map[item]['value']

    def __setitem__(self, key, value):
        """ Allows to directly set param_map values

        :param Parameters key: the parameter to change
        :param object value: the new value
        """
        self.param_map[key]['value'] = value

    def add_cli_parameter(self, name, value):
        """ Add new CLI parameter to the list of user-supplied arguments.

        :param str name: the string representation of a Parameter
        :param object value: the Parameter value

        :return object or None: the parameter value if the validation is successful, else None
        """
        param = Parameters(name)
        validated = self.param_map[param]['validate'](value)
        if validated is not None:
            self.cli_params.append((param, validated))
            return validated
        return None

    def infer_params(self, call_graph, pipeline, binary):
        """ Attempts to infer sensible default values for the parameters that were not supplied
        by the user. The prediction is done safely in several steps since various modes and
        parameters can affect other parameters as well.

        :param CallGraphResource call_graph: the CGR instance
        :param Pipeline pipeline: the currently selected pipeline
        :param str binary: path to the executable binary
        """
        metrics.start_timer('optimization_parameters')
        func_count, level_count = 0, 0
        if call_graph is not None:
            func_count, level_count = len(call_graph.cg_map.keys()), len(call_graph.levels)
            # Update the default keep top according to the first call graph branching
            self._default_keep_top = call_graph.coverage_max_cut()[1] + 1
        # Extract the user-supplied modes and parameters
        modes = [Parameters.DIFF_CG_MODE, Parameters.CG_SHAPING_MODE, Parameters.THRESHOLD_MODE]
        cli_modes, cli_params = utils.partition_list(
            self.cli_params, lambda param: param[0] in modes
        )

        # Infer general parameters (used in multiple methods) based on the call graph
        self._infer_general_parameters(func_count, level_count)
        # Infer modes used by some methods based on the pipeline
        self._infer_modes(pipeline, cli_modes)
        # Infer the call graph shaping parameters
        self._infer_cg_shaping_parameters(func_count, level_count)
        # Infer the thresholds used by various methods
        self._infer_thresholds()

        # Set user-supplied parameters to override the inferred ones
        for param_name, param_value in cli_params:
            if isinstance(self[param_name], list):
                self[param_name].append(param_value)
            else:
                self[param_name] = param_value

        # Infer the dynamic probing parameters
        self._infer_dynamic_probing(cli_params)
        # Extract source files based on the supplied parameters
        self._extract_sources(binary)
        metrics.end_timer('optimization_parameters')

    def _infer_general_parameters(self, func_count, level_count):
        """ Predicts parameters that are applied across multiple optimization methods.

        :param int func_count: the number of extracted functions
        :param int level_count: the amount of call graph levels
        """
        if func_count == 0 and level_count == 0:
            return
        # Keep the leaf functions if the total number of profiled functions is low
        if func_count <= self._functions_keep_leaves:
            self[Parameters.DIFF_KEEP_LEAF] = True
            self[Parameters.CG_PROJ_KEEP_LEAF] = True
        # Keep-top: 10% of levels, minimum is default
        keep_top = max(math.ceil(level_count * self._keep_top_ratio), self._default_keep_top)
        self[Parameters.STATIC_KEEP_TOP] = keep_top

    def _infer_modes(self, selected_pipeline, user_modes):
        """ Predicts the mode parameters based on the used pipeline.

        :param Pipeline selected_pipeline: the currently selected pipeline
        :param list user_modes: list of pairs with user-specified modes
        """
        self[Parameters.DIFF_CG_MODE] = DiffCfgMode.COLORING
        self[Parameters.CG_SHAPING_MODE] = CGShapingMode.TOP_DOWN
        # The selected pipeline determines the used modes
        if selected_pipeline == Pipeline.BASIC:
            self[Parameters.THRESHOLD_MODE] = ThresholdMode.STRICT
        else:
            self[Parameters.THRESHOLD_MODE] = ThresholdMode.SOFT
        # Apply the user-supplied modes
        for mode_type, mode_value in user_modes:
            self[mode_type] = mode_value

    def _infer_cg_shaping_parameters(self, func_count, level_count):
        """ Predicts the Call Graph Shaping parameters based on the number of functions and levels.

        :param int func_count: the number of extracted functions
        :param int level_count: the amount of call graph levels
        """
        if func_count == 0 and level_count == 0:
            return
        # Determine the number of trimmed levels
        trim_levels = round(level_count * self._levels_ratio)
        # Set the trim levels
        self[Parameters.CG_PROJ_LEVELS] = max(trim_levels, self._default_min_levels)

    def _infer_thresholds(self):
        """ Infer the threshold values based on the selected modes.
        """
        # Determine the thresholds based on the mode
        base = self._threshold_soft_base
        if self[Parameters.THRESHOLD_MODE] == ThresholdMode.STRICT:
            base = self._threshold_strict_base
        # Set the threshold
        self[Parameters.DYNSAMPLE_THRESHOLD] = base
        self[Parameters.DYNBASE_SOFT_THRESHOLD] = base
        self[Parameters.DYNBASE_HARD_THRESHOLD] = base * self._hard_threshold_coefficient

    def _infer_dynamic_probing(self, cli_params):
        """ Predict parameters and threshold values for Dynamic Probing .

        :param list cli_params: a collection of user-supplied parameters
        """
        # Update the probing threshold if reattach is enabled and probing threshold is not set
        probing_threshold_set = Parameters.PROBING_THRESHOLD in [param for param, _ in cli_params]
        if self[Parameters.PROBING_REATTACH] and not probing_threshold_set:
            probing_threshold = self._probing_threshold * self._probing_reattach_coefficient
            self[Parameters.PROBING_THRESHOLD] = probing_threshold

    def _extract_sources(self, binary):
        """ Search for source files of the project in the binary directory, if none are given.

        :param str binary: path to the binary executable
        """
        files, dirs = self[Parameters.SOURCE_FILES], self[Parameters.SOURCE_DIRS]
        # No need to extract if only source files are supplied
        if files and not dirs:
            return
        # If no files or directories are supplied, assume the binary directory contains sources
        if not files and not dirs:
            dirs.append(os.path.dirname(binary))

        # Save the sources
        self[Parameters.SOURCE_FILES] = list(set(_get_source_files(dirs, files)))

    @staticmethod
    def _validate_bool(value):
        """ Bool validation function that accepts boolean values as 1 or 0.

        :param str value: the boolean value to validate
        :return bool or None: the boolean value if the validation is successful
        """
        if value in ['0', '1']:
            return bool(int(value))
        return None

    @staticmethod
    def _validate_uint(value):
        """ Uint validation function.

        :param str value: the uint value to validate
        :return int or None: the uint value if the validation is successful
        """
        try:
            value = int(value)
            if value >= 0:
                return value
            return None
        except ValueError:
            return None

    @staticmethod
    def _validate_ufloat(value):
        """ unsigned float validation function.

        :param str value: the ufloat value to validate
        :return float or None: the ufloat value if the validation is successful
        """
        try:
            value = float(value)
            if value > 0:
                return value
            return None
        except ValueError:
            return None

    @staticmethod
    def _validate_path(path):
        """ Path validation function that takes string and resolves the path.

        :param str path: the path to validate
        :return str or None: fully resolved path if the validation is successful
        """
        if not os.path.exists(os.path.realpath(path)):
            return None
        return os.path.realpath(path)

    @staticmethod
    def _validate_enum(enumclass, value):
        """ Validate if value is supported in the given enum class

        :param Enum enumclass: Enum class
        :param str value: value to check

        :return object or None: Enum item corresponding to the given string value
        """
        return enumclass(value) if value in enumclass.supported() else None

def _get_source_files(dirs, files):
    """ Get all source files in the supplied dirs and files

    :param list dirs: list of directories
    :param list files: list of files

    :return list: list of file paths
    """
    candidate_files = []
    for src in dirs + files:
        if os.path.isdir(src):
            for root, _, files in os.walk(src):
                candidate_files.extend(os.path.join(root, file) for file in files)
        elif os.path.isfile(src):
            candidate_files.append(src)

    return [file for file in candidate_files if os.path.splitext(file)[1] == '.c']


import numpy as np
from sklearn import datasets
from sklearn.metrics import f1_score
from sklearn.model_selection import train_test_split
from graphviz import Digraph

# 计算连续型数据的基尼系数
def min_gini(labels, attributes):
    centrals = []
    new_list = []
    label_set = np.unique(labels)
    for i in range(len(labels)):
        new_list.append((labels[i], attributes[i]))
    sort_list = np.copy(attributes)
    sort_list.sort()
    for i in range(len(attributes) - 1):
        centrals.append((sort_list[i] + sort_list[i + 1]) / 2)
    split_num = 0
    min_gini_num = None
    for num in centrals:
        left = []
        right = []
        for i in range(len(new_list)):
            if new_list[i][1] <= num:
                left.append(new_list[i][0])
            else:
                right.append(new_list[i][0])
        left_gini = 1
        right_gini = 1
        for label in label_set:
            if len(left) != 0:
                left_gini -= (left.count(label) / len(left)) ** 2
            if len(right) != 0:
                right_gini -= (right.count(label) / len(right)) ** 2
        gini_now = left_gini * len(left) / len(attributes) + right_gini * len(right) / len(attributes)
        if min_gini_num is None or min_gini_num > gini_now:
            min_gini_num = gini_now
            split_num = num
    return min_gini_num, split_num

class TreeNode:
    def __init__(self, attributes, labels):
        self.is_leaf = False
        self.attributes = attributes
        # 判断是否停止迭代
        if len(set(labels)) == 1:
            self.label = labels[0]
            self.is_leaf = True
        else:
            properties = []
            for i in range(attributes.shape[1]):
                gini_num, split_num = min_gini(labels, attributes[:, i])
                properties.append((i, gini_num, split_num))
            # 获取二元离散分类点
            index = np.argmin(list(map(lambda x: x[1], properties)))
            self.prop = properties[index][0]
            self.gini = properties[index][1]
            self.split_num = properties[index][2]
            left_attr = []
            left_labels = []
            right_attr = []
            right_labels = []
            for i in range(len(attributes)):
                if attributes[i][self.prop] <= self.split_num:
                    left_attr.append(attributes[i])
                    left_labels.append(labels[i])
                else:
                    right_attr.append(attributes[i])
                    right_labels.append(labels[i])
            # 递归方式生成决策树
            self.left_node = TreeNode(np.array(left_attr), left_labels)
            self.right_node = TreeNode(np.array(right_attr), right_labels)

    # 决策树绘制部分
    def add_node(self, graph, labels, class_names):

        graph.node(str(self.__hash__()), self.describe(labels, class_names), shape='box',
                   style="filled" if self.is_leaf else None, color="#CC59CC" if self.is_leaf else None,
                   fontcolor="white" if self.is_leaf else "black")
        if not self.is_leaf:
            self.left_node.add_node(graph, labels, class_names)
            self.right_node.add_node(graph, labels, class_names)
            graph.edge(str(self.__hash__()), str(self.left_node.__hash__()))
            graph.edge(str(self.__hash__()), str(self.right_node.__hash__()))

    # 添加可视化标签
    def describe(self, labels, class_names):
        description = ''
        if self.is_leaf:
            description += 'class = ' + class_names[self.label] + '\n'
        else:
            description += labels[self.prop] + ' <= ' + str(round(self.split_num, 4)) + '\n'
        description += 'samples = ' + str(len(self.attributes))
        return description

    # 计算样本结果
    def calculate_result(self, vector):
        if self.is_leaf:
            return self.label
        else:
            if vector[self.prop] <= self.split_num:
                return self.left_node.calculate_result(vector)
            else:
                return self.right_node.calculate_result(vector)

if __name__ == '__main__':
    # 获取Iris数据集
    iris = datasets.load_iris()
    labels_name = iris.feature_names
    target_name = iris.target_names
    # 获取训练集与测试集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2)
    # 生成决策树
    root = TreeNode(np.array(x_train), y_train)
    # 计算Micro-F1和Macro-F1
    results = list(map(lambda x: root.calculate_result(x), x_test))
    micro_f1 = f1_score(y_test, results, average="micro")
    macro_f1 = f1_score(y_test, results, average="macro")
    print("Cart Tree Results:")
    print("Micro-F1 Score: " + str(micro_f1))
    print("Macro-F1 Score: " + str(macro_f1))
    print()
    # 绘制决策树
    g = Digraph('G', filename='decision_tree.gv', format='png')
    root.add_node(g, labels_name, target_name)
    g.view(filename="cart")
    # Random Forest Optimizing
    forests = []
    # 以10棵树为例
    k = 10
    # 抽取训练集样本以生成树
    for _ in range(k):
        x_samples, _, y_samples, _ = train_test_split(x_train, y_train, test_size=0.3)
        forests.append(TreeNode(np.array(x_samples), y_samples))
    random_forest_result = []
    # 计算Random Forest的结果
    for tree in forests:
        random_forest_result.append(list(map((lambda x: tree.calculate_result(x)), x_test)))
    random_forest_result = np.array(random_forest_result).T
    voting_result = []
    for line in random_forest_result:
        voting_result.append(np.argmax(np.bincount(line)))
    micro_f1 = f1_score(y_test, voting_result, average="micro")
    macro_f1 = f1_score(y_test, voting_result, average="macro")
    print("Random Forest Results:")
    print("Micro-F1 Score: " + str(micro_f1))
    print("Macro-F1 Score: " + str(macro_f1))


#!/usr/bin/env python3

from typing import Any, Dict, Optional, Set

import pytorch_lightning as pl
import torch
from datasets import Dataset, DatasetDict, load_dataset
from torch.utils.data import DataLoader, WeightedRandomSampler
from transformers import AutoTokenizer

class RegionHallandDataModule(pl.LightningDataModule):
    def __init__(
        self,
        # dataset_path: str,
        tokenizer_name: str,
        max_sequence_length: int,
        batch_size: int,
        seed: int,
        val_is_test: bool = True,
        train_data_path: str = "data/rh_train.csv",
        test_data_path: str = "data/rh_test.csv",
    ):
        super().__init__()
        # self.dataset_path = dataset_path # TODO
        self.tokenizer_name = tokenizer_name
        self.max_sequence_length = max_sequence_length
        self.batch_size = batch_size
        self.seed = seed
        self.val_is_test = val_is_test
        self.train_data_path = train_data_path
        self.test_data_path = test_data_path

        self.data_loader_cache: Dict[str, DataLoader] = dict()
        self.dataset: Dataset
        self.destroyed_indices: Set[int] = set()

    def get_destroyed_labels(self):
        return []

    def prepare_data(self):
        """Download files to cache first once per node."""
        AutoTokenizer.from_pretrained(self.tokenizer_name, use_fast=True)
        split = self.get_train_test_split()
        load_dataset(
            "csv",
            split=split,
            data_files={
                'train': [self.train_data_path],
                'test': [self.test_data_path],
            },
        )

    def get_train_test_split(self):
        """Return train test split for HF datasets."""
        split = {"train": "train", "test": "test"}
        return split

    def get_and_process_dataset(self):
        tokenizer = AutoTokenizer.from_pretrained(
            self.tokenizer_name, use_fast=True
        )

        # tokenize the dataset
        def preprocess(example: Dict[str, Any], idx: int) -> Dict[str, Any]:
            encoding = tokenizer(
                example["text"],
                max_length=self.max_sequence_length,
                truncation=True,
                padding="max_length",
                return_attention_mask=True,
                return_token_type_ids=True,
            )
            encoding.update({"idx": idx})
            return encoding

        dataset: DatasetDict = DatasetDict()
        split = self.get_train_test_split()

        dataset = load_dataset(
            "csv",
            split=split,
            data_files={
                'train': [self.train_data_path],
                'test': [self.test_data_path],
            },
        )

        return dataset.map(preprocess, batched=True, with_indices=True)

    def setup(self):
        dataset = self.get_and_process_dataset()
        dataset.set_format(
            type="torch",
            columns=[
                "input_ids",
                "token_type_ids",
                "attention_mask",
                "label",
                "idx",  # To find destroyed labels
            ],
        )
        self.dataset = dataset.shuffle(seed=self.seed)

    def _create_dataloader(
        self,
        dataset_partitions: Dataset,
        split: str,
        batch_size: int,
    ):
        if split == "validation" and self.val_is_test:
            split = "test"

        dataset = dataset_partitions[split]

        # Get frequency of the labels and convert to weights
        targets = dataset['label'].type(torch.long) # index needs to be long, byte or bool (byte == uint8, long==int64)
        class_freq = torch.bincount(targets)
        class_weights = 1. / class_freq
        class_weights_all = class_weights[targets]

        sampler = WeightedRandomSampler(
            weights=class_weights_all,
            num_samples=len(class_weights_all),
            replacement=True
        )

        return DataLoader(
            dataset,
            batch_size=batch_size,
            # shuffle=False,
            num_workers=4,
            sampler=sampler,
        )

    def train_dataloader(self):
        self.data_loader_cache["train"] = self._create_dataloader(
            self.dataset, split="train", batch_size=self.batch_size
        )
        return self.data_loader_cache["train"]

    def val_dataloader(self):
        self.data_loader_cache["validation"] = self._create_dataloader(
            self.dataset, split="validation", batch_size=self.batch_size
        )
        return self.data_loader_cache["validation"]

    def test_dataloader(self):
        self.data_loader_cache["test"] = self._create_dataloader(
            self.dataset, split="test", batch_size=self.batch_size
        )
        return self.data_loader_cache["test"]


from .self_Alipay import *
import qrcode,time

alipay = alipay()

class pay:
    def __init__(self,out_trade_no,total_amount,subject,timeout_express):
        self.out_trade_no = out_trade_no
        self.total_amount = total_amount
        self.subject = subject
        self.timeout_express = timeout_express

    def get_qr_code(self,code_url):
        '''
        生成二维码
        :return None
        '''
        qr = qrcode.QRCode(
             version=1,
             error_correction=qrcode.constants.ERROR_CORRECT_H,
             box_size=10,
             border=1
        )
        qr.add_data(code_url)  # 二维码所含信息
        img = qr.make_image()  # 生成二维码图片
        img.save(r'E:\python3\Alipay_for_QR_code\qrcode_image\qr_test_ali.png')
        print('二维码保存成功！')

    def query_order(self,out_trade_no: int):
        '''
        :param out_trade_no: 商户订单号
        :return: Nonem
        '''
        _time = 0
        for i in range(600):
            time.sleep(1)
            result = alipay.init_alipay_cfg().api_alipay_trade_query(out_trade_no=out_trade_no)
            if result.get("trade_status", "") == "TRADE_SUCCESS":
                print('订单已支付!')
                print('订单查询返回值：', result)
                return True
            _time += 2
        return False

def do_payment():
    payer = pay(out_trade_no=datetime.now().strftime('%Y%m%d%H%M%S'),total_amount= 6,subject = "test",timeout_express='10m')

    dict = alipay.trade_pre_create(out_trade_no=payer.out_trade_no,total_amount=payer.total_amount,subject =payer.subject,timeout_express=payer.timeout_express )

    payer.get_qr_code(dict['qr_code'])
    payer.query_order(payer.out_trade_no)


from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.uic import loadUi
import mysql.connector as mysql
import sys
from pyparsing import Word
import gui.ocr

class Notes(QFrame):
    def __init__(self):
        super().__init__()
        loadUi('gui\OCR_Notes.ui', self)
        self.setFixedSize(911, 436)
        self.con = self.createConnection()
        self.cursor = self.con.cursor()
        self.tablesize()
        self.show_notes()
        self.populateCombo()
        self.btnShow.clicked.connect(self.show_details)

    def show_notes(self):
        query = 'select note_id, content from notes'
        self.cursor.execute(query)
        self.dataset = self.cursor.fetchall()
        rowcount = len(self.dataset)
        self.table1.setRowCount(rowcount)
        rownum = 0
        for row in self.dataset:
            for column in range(len(row)):
                self.table1.setItem(rownum, column, QTableWidgetItem(str(row[column])))
            rownum = rownum + 1

    def show_details(self):
        self.note_id = self.cmb.currentText()
        query1 = 'select content from notes where note_id=%s'
        self.cursor.execute(query1, (int(self.note_id),))
        self.modelset = self.cursor.fetchone()
        self.txtShow.setText(self.modelset[0])

    def populateCombo(self):
        strsql = 'select note_id from notes'
        self.cursor.execute(strsql)
        self.dataset = self.cursor.fetchall()
        for data in self.dataset:
            self.cmb.addItem(str(data[0]))

    def createConnection(self):
        con = mysql.connect(host='localhost', database='ocr', user='root', password='')
        return con

    def showDialog(self,txt):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setWindowTitle('Message.')
        msg.setText(txt)
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def tablesize(self):
        self.table1.setColumnWidth(0, 125)
        self.table1.setColumnWidth(1, 350)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    notes = Notes()
    notes.show()
    app.exec_()


class Node:
    def __init__(self,data):
        self.data=data
        self.next=None

class Linked_list:
    def __init__(self):
        self.head=None

    def append(self,data):
        new_node=Node(data)
        curr_node=self.head
        if curr_node is None:
            self.head=new_node
        else:
            while curr_node.next is not None:
                curr_node=curr_node.next
            curr_node.next=new_node

    def show(self):
        curr_node=self.head
        while curr_node:
            print(f"{curr_node.data}-->",end="")
            curr_node=curr_node.next
        print()

    def __len__(self):
        count=0
        curr_node=self.head
        while curr_node:
            count+=1
            curr_node=curr_node.next
        return count

    def remove_from_back(self,key):
        index=len(link1)-key
        current_node=self.head
        prev=None
        count=0
        while current_node:
            if count==index:
                prev.next=current_node.next
                current_node=None
                break
            else:
                prev=current_node
                current_node=current_node.next
                count+=1
link1=Linked_list()
link1.append(1)
link1.append(5)
link1.append(7)
link1.append(8)
link1.append(11)
link1.append(12)

link1.show()
link1.remove_from_back(2)
link1.show()


import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
import numpy as np

df = pd.read_excel('500 comp.xlsx')

df = df.drop(['Company','Sector',"Country","neto",'oper', 'Ventas'],  axis=1)
df.dropna(inplace=True)
print(df.head())

X = df.values[:,1:]
X = np.nan_to_num(X)
Clus_dataSet = StandardScaler().fit_transform(X)
# print(Clus_dataSet)

    #Функция оптимального количества кластеров

def optimise_k_means(data, max_k):

    means = []
    inertias = []

    for k in range(1, max_k):
        kmeans = KMeans(n_clusters=k)
        kmeans.fit(data)

        means.append(k)
        inertias.append(kmeans.inertia_)

    #График плеча (не обращаем внимание на предупреждения в ходе запуска)
    fig = plt.subplots(figsize=(10, 5))
    plt.plot(means, inertias, 'o-')
    plt.xlabel('Number of Clusters')
    plt.ylabel('Inertia')
    plt.grid(True)
    plt.show()
optimise_k_means(df[['Activo', 'Roe']],10)

    #Создание кластеров - Проведение кластеризации

kmeans = KMeans(n_clusters=3)
kmeans.fit(df[['Activo', 'Roe']])
df['kmeans_3'] = kmeans.labels_

    #Готовый к визуализации дб с средними значениями

print(df)

    #Среднее значение (можно заигнорить)

print(df.groupby('kmeans_3').mean())

    #Кластерный график

plt.scatter(x=df['Activo'], y=df['Roe'], c=df['kmeans_3'])
plt.xlim(-0.1, 30)
plt.xlabel('Activo', fontsize=16)
plt.ylim(-100,350)
plt.ylabel('Roe', fontsize=16)
plt.show()

# area = np.pi * (X[:, 1])**2
# plt.scatter(X[:,0], X[:,1], s=area, c=labels, alpha=0.5)
# plt.xlabel('Empl', fontsize=18)
# plt.ylabel('Activo', fontsize=16)
# #
# plt.show()

from mpl_toolkits.mplot3d import Axes3D
# fig = plt.figure(1, figsize=(8, 6))
# plt.clf()
#
# ax = fig.add_subplot(projection='3d')
# ax = Axes3D(fig, rect=[0,0,.95,1], elev=48, azim=134)
#
# ax.set_xlabel('Да')
# ax.set_ylabel('Два')
# ax.set_zlabel('ТРИ')
#
# ax.scatter(X[:, 0],X[:, 1],X[:, 2], c= labels)

# fig = plt.figure(figsize=(7, 4))
# ax_3d = fig.add_subplot(projection='3d')
#
# x = np.arange
# y = np.arange
#
# x = np.arange(-2*np.pi, 2*np.pi, 0.2)
# y = np.arange(-2*np.pi, 2*np.pi, 0.2)
# xgrid, ygrid = np.meshgrid(x,y)
# zgrid = np.sin(xgrid) * np.sin(ygrid) / (xgrid * ygrid)
#
# ax_3d.set_xlabel('x')
# ax_3d.set_ylabel('y')
# ax_3d.set_zlabel('z')
#
# ax_3d.scatter(xgrid, ygrid, zgrid, s=1, color='g')
#
# plt.show()

# X = df[['Activo','Empl']].copy()
# wcss = []
# #the elbow method plots whithin-cluster-sum-of-squares (WCSS) vs the number of clusters
# for i in range(1, 11):
#     kmeans = KMeans(n_clusters=i, random_state=0)
#     kmeans.fit(X)
#     wcss.append(kmeans.inertia_)
#
# sns.set()
# plt.plot(range(1,11,1),wcss)
# plt.title('Selecting the number of clusters using the elbow method')
# plt.xlabel('clusters')
# plt.ylabel('WCSS')
# print(plt.show())
#
# plt.scatter(df["Activo"],df['Empl'])
# plt.title('Activo and Empl')
# plt.xlabel('Activo')
# plt.ylabel('Employers')
# print(plt.show())


import json

def get_protocol_contents(protocol_file, path=None):
    if not path:
        path = "messenger/"
    try:
        with open("{}{}.json".format(path, protocol_file), "r") as json_file:  # noqa
            return json.load(json_file)
    except Exception:
        return None


from setuptools import setup, find_packages

version = '0.0.6'

setup(name="helga-redmine",
      version=version,
      description=('redmine plugin for helga'),
      classifiers=['Development Status :: 4 - Beta',
                   'License :: OSI Approved :: MIT License',
                   'Operating System :: OS Independent',
                   'Programming Language :: Python',
                   'Topic :: Software Development :: Libraries :: Python Modules',
                   ],
      keywords='irc bot redmine',
      author='alfredo deza',
      author_email='contact [at] deza [dot] pe',
      url='https://github.com/alfredodeza/helga-redmine',
      license='MIT',
      packages=find_packages(),
      install_requires=[
          'helga>=1.7.5',
          'treq>=15.1.0',
          'twisted',
      ],
      tests_require=[
          'pytest-twisted',
      ],
      entry_points = dict(
          helga_plugins = [
              'redmine = redmine:redmine',
          ],
      ),
)


#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from builtin_interfaces.msg import Duration
from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
from manipulator_interfaces.srv import ManipulatorForwardKinematicsTargets

class ControllerComms(Node):
    def __init__(self):
        super().__init__("controller_comms_node")

        # declare parameters
        self.declare_parameter("joint_trayectory_controller_node","/joint_trajectory_controller/joint_trajectory")
        self.declare_parameter("publish_buffer_size",10)
        self.declare_parameter("controller_service_name","controller_service")

        # fetch parameters
        controller_topic = self.get_parameter("joint_trayectory_controller_node").value
        buffer_size = self.get_parameter("publish_buffer_size").value
        controller_service_name = self.get_parameter("controller_service_name").value

        # fixed actuated joints (robot structure)
        self.joints = ["joint_1","joint_2","joint_4"]

        # create publisher and service
        self.trajectory_publisher = self.create_publisher(JointTrajectory,controller_topic,buffer_size)
        self.service = self.create_service(ManipulatorForwardKinematicsTargets,controller_service_name,self.service_callback)
        self.get_logger().info("CONTROLLER COMMUNICATION SERVER ONLINE")

    def service_callback(self,request,response):
        # update targets
        target_goals = [request.joint_1_target,request.joint_2_target,request.joint_4_target]
        # move the robot
        trajectory_msg = JointTrajectory()
        trajectory_msg.joint_names = self.joints
        point = JointTrajectoryPoint()
        point.positions = target_goals
        point.time_from_start = Duration(sec = 2)
        trajectory_msg.points.append(point)
        self.trajectory_publisher.publish(trajectory_msg)
        response.response = True
        return response

def main(args=None):
    rclpy.init(args=args)
    node = ControllerComms()
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == "__main__":
    main()


import numpy
import util

class Median:

    def __init__(self,N):
        self.N=N
        self.x=numpy.zeros(N)
        self.ptr=0
        self.N_MED=N/2

    def process(self,data):

        self.x[self.ptr]=data

        self.ptr += 1

        if self.ptr == self.N:
            self.ptr=0

        return self

    def median_val(self):
        return  numpy.sort(self.x)[self.N_MED]

class Interpolator:

    def __init__(self,srate,client):

        self.dt=1.0/srate
        self.time=0
        self.tLast=None
        self.client=client

    def process(self,bpm,tNow,val=0):

        if self.tLast == None:
            self.tLast = tNow
            self.bpmLast = bpm
            return

        # t

        while self.time <= tNow:

            """
                 bpmLast                      bpm
                 tLast                        tNow
                               time

             bpm1= ( bpmLast*(tNow-time) + bpm*(time-tLast)  )/(tNow-tlast)

             """

            bpmX = ( self.bpmLast*(tNow-self.time) + bpm*(self.time-self.tLast)  )/(tNow-self.tLast)
            if self.client != None:
                self.client.process(bpmX)

            self.time+=self.dt

        self.tLast=tNow
        self.bpmLast=bpm

class DCBlock:
    """
    https://ccrma.stanford.edu/~jos/filters/DC_Blocker.html
    """

    def __init__(self,R):
        self.R=R
        self.yLast=0
        self.xLast=0

    def process(self,x,*args):

        y=x-self.xLast+self.yLast*self.R

        self.xLast=x
        self.yLast=y

        return y

"""
static int y1 = 0, y2 = 0, x[26], n = 12;
int y0;
x[n] = x[n + 13] = data;
y0 = (y1 << 1) - y2 + x[n] - (x[n + 6] << 1) + x[n + 12];
y2 = y1;
y1 = y0;
y0 >>= 5;
if(--n < 0)
n = 12;
return(y0);
"""
class LPF:

    def __init__(self):
        self.y1 = 0
        self.y2 = 0
        self.x=numpy.zeros(26)
        self.n = 12

    def process(self,data):

        self.x[self.n] = self.x[self.n + 13] = data;
        y0 = 2*self.y1 - self.y2 + self.x[self.n] - (2*self.x[self.n + 6]) + self.x[self.n + 12];
        self.y2 = self.y1
        self.y1 = y0
        y0 *= 32
        self.n -= 1
        if self.n < 0:
            self.n = 12
        return y0

"""
static int y1 = 0, x[66], n = 32;
int y0;
x[n] = x[n + 33] = data;
y0 = y1 + x[n] - x[n + 32];
y1 = y0;
if(--n < 0)
n = 32;
return(x[n + 16] - (y0 >> 5));
}
"""

class HPF:

    def __init__(self):
        self.y1 = 0
        self.x=numpy.zeros(66)
        self.n = 32

    def process(self,data):

        self.x[self.n] = self.x[self.n + 33] = data;
        y0 = self.y1 + self.x[self.n] - self.x[self.n + 32]
        self.y1 = y0;
        self.n -=1
        if self.n < 0:
            self.n = 32
        return self.x[self.n+16]-y0/32.0

"""
int Derivative(int data)
{
int y, i;
static int x_derv[4];
/*y = 1/8 (2x( nT) + x( nT - T) - x( nT - 3T) - 2x( nT -  4T))*/
y = (data << 1) + x_derv[3] - x_derv[1] - ( x_derv[0] << 1);
y >>= 3;
for (i = 0; i < 3; i++)
x_derv[i] = x_derv[i + 1];
x_derv[3] = data;
return(y);
"""
class Dervivative:

    def __init__(self):
        self.y = 0
        self.i = 0
        self.x_derv=numpy.zeros(4)

    def process(self,data):

        y = 2*data + self.x_derv[3] -self.x_derv[1]- 2*self.x_derv[0]
        y = y/8
        self.x_derv[0]=self.x_derv[1]
        self.x_derv[1]=self.x_derv[2]
        self.x_derv[2]=self.x_derv[3]
        self.x_derv[3]=data
        return y

"""
static int x[32], ptr = 0;
static long sum = 0;
long ly;
int y;
if(++ptr == 32)
ptr = 0;
sum -= x[ptr];
sum += data;
x[ptr] = data;
ly = sum >> 5;
if(ly > 32400) /*check for register overflow*/
y = 32400;
else
y = (int) ly;
return(y);
"""

class MovingAverge:

    def __init__(self):
        self.sum = 0
        self.ptr = 0
        self.x=numpy.zeros(32)

    def process(self,data):

        self.ptr+=1
        if self.ptr== 32:
            self.ptr=0
        self.sum -= self.x[self.ptr]
        self.sum += data
        self.x[self.ptr]=data

        return self.sum/32.0

class MovingAvergeN:

    def __init__(self,N):
        self.sum = 0.0
        self.ptr = 0
        self.x=numpy.zeros(N)
        self.N=N

    def process(self,data):

        self.ptr+=1
        if self.ptr == self.N:
            self.ptr=0
        self.sum -= self.x[self.ptr]
        self.sum += data
        self.x[self.ptr]=data

        return self.sum/self.N

class MovingDecayAverge:

    def __init__(self,samps_per_half_life,init_value):
        self.sum = init_value
        self.ptr = 0
        self.fact1,self.fact2=util.halfLifeFactors(samps_per_half_life)

    def process(self,data):

        self.sum=self.sum*self.fact1+data*self.fact2
        return self.sum

    def get_value(self):
        return self.sum

class Delay:

    def __init__(self,N):

        self.buff=numpy.zeros(N)
        self.N=N
        self.ptr=0

    def process(self,data):

        ret=self.buff[self.ptr]
        self.buff[self.ptr]=data
        self.ptr+=1

        if self.ptr == self.N:
            self.ptr=0

        return ret

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ***************************************************************************
# *   Copyright (C) 2011, Paul Lutus                                        *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License as published by  *
# *   the Free Software Foundation; either version 2 of the License, or     *
# *   (at your option) any later version.                                   *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU General Public License for more details.                          *
# *                                                                         *
# *   You should have received a copy of the GNU General Public License     *
# *   along with this program; if not, write to the                         *
# *   Free Software Foundation, Inc.,                                       *
# *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
# ***************************************************************************

import math

class Biquad:

  # pretend enumeration
  LOWPASS, HIGHPASS, BANDPASS, NOTCH, PEAK, LOWSHELF, HIGHSHELF = range(7)

  def __init__(self,typ, freq, srate, Q, dbGain = 0):
      types = {
      Biquad.LOWPASS : self.lowpass,
      Biquad.HIGHPASS : self.highpass,
      Biquad.BANDPASS : self.bandpass,
      Biquad.NOTCH : self.notch,
      Biquad.PEAK : self.peak,
      Biquad.LOWSHELF : self.lowshelf,
      Biquad.HIGHSHELF : self.highshelf
      }
      assert(types.has_key(typ))
      freq = float(freq)
      self.srate = float(srate)
      Q = float(Q)
      dbGain = float(dbGain)
      self.a0 = self.a1 = self.a2 = 0
      self.b0 = self.b1 = self.b2 = 0
      self.x1 = self.x2 = 0
      self.y1 = self.y2 = 0
      # only used for peaking and shelving filter types
      A = math.pow(10, dbGain / 40)
      omega = 2 * math.pi * freq / self.srate
      sn = math.sin(omega)
      cs = math.cos(omega)
      alpha = sn / (2*Q)
      beta = math.sqrt(A + A)
      types[typ](A,omega,sn,cs,alpha,beta)
      # prescale constants
      self.b0 /= self.a0
      self.b1 /= self.a0
      self.b2 /= self.a0
      self.a1 /= self.a0
      self.a2 /= self.a0

  def lowpass(self,A,omega,sn,cs,alpha,beta):
    self.b0 = (1 - cs) /2
    self.b1 = 1 - cs
    self.b2 = (1 - cs) /2
    self.a0 = 1 + alpha
    self.a1 = -2 * cs
    self.a2 = 1 - alpha

  def highpass(self,A,omega,sn,cs,alpha,beta):
    self.b0 = (1 + cs) /2
    self.b1 = -(1 + cs)
    self.b2 = (1 + cs) /2
    self.a0 = 1 + alpha
    self.a1 = -2 * cs
    self.a2 = 1 - alpha

  def bandpass(self,A,omega,sn,cs,alpha,beta):
    self.b0 = alpha
    self.b1 = 0
    self.b2 = -alpha
    self.a0 = 1 + alpha
    self.a1 = -2 * cs
    self.a2 = 1 - alpha

  def notch(self,A,omega,sn,cs,alpha,beta):
    self.b0 = 1
    self.b1 = -2 * cs
    self.b2 = 1
    self.a0 = 1 + alpha
    self.a1 = -2 * cs
    self.a2 = 1 - alpha

  def peak(self,A,omega,sn,cs,alpha,beta):
    self.b0 = 1 + (alpha * A)
    self.b1 = -2 * cs
    self.b2 = 1 - (alpha * A)
    self.a0 = 1 + (alpha /A)
    self.a1 = -2 * cs
    self.a2 = 1 - (alpha /A)

  def lowshelf(self,A,omega,sn,cs,alpha,beta):
    self.b0 = A * ((A + 1) - (A - 1) * cs + beta * sn)
    self.b1 = 2 * A * ((A - 1) - (A + 1) * cs)
    self.b2 = A * ((A + 1) - (A - 1) * cs - beta * sn)
    self.a0 = (A + 1) + (A - 1) * cs + beta * sn
    self.a1 = -2 * ((A - 1) + (A + 1) * cs)
    self.a2 = (A + 1) + (A - 1) * cs - beta * sn

  def highshelf(self,A,omega,sn,cs,alpha,beta):
    self.b0 = A * ((A + 1) + (A - 1) * cs + beta * sn)
    self.b1 = -2 * A * ((A - 1) + (A + 1) * cs)
    self.b2 = A * ((A + 1) + (A - 1) * cs - beta * sn)
    self.a0 = (A + 1) - (A - 1) * cs + beta * sn
    self.a1 = 2 * ((A - 1) - (A + 1) * cs)
    self.a2 = (A + 1) - (A - 1) * cs - beta * sn

  # perform filtering function
  def process(self,x):
    y = self.b0 * x + self.b1 * self.x1 + self.b2 * self.x2 - self.a1 * self.y1 - self.a2 * self.y2
    self.x2 = self.x1
    self.x1 = x
    self.y2 = self.y1
    self.y1 = y
    return y

  # provide a static result for a given frequency f
  def result(self,f):
    phi = (math.sin(math.pi * f * 2/(2.0 * self.srate)))**2
    return ((self.b0+self.b1+self.b2)**2 - 4*(self.b0*self.b1 + 4*self.b0*self.b2 + self.b1*self.b2)*phi + 16*self.b0*self.b2*phi*phi) / ((1+self.a1+self.a2)**2 - 4*(self.a1 + 4*self.a2 + self.a1*self.a2)*phi + 16*self.a2*phi*phi)

  def log_result(self,f):
    try:
      r = 20 * math.log10(self.result(f))
    except:
      r = -200
    return r

  # return computed constants
  def constants(self):
    return self.b0,self.b1,self.b2,self.a1,self.a2


# This is a scrapper module to get news from fake news and real news sites.
# Using BeautifulSoup as base library

import urllib3
from bs4 import BeautifulSoup

def getnpr():
    http = urllib3.PoolManager()
    quote_page = 'https://www.npr.org/tags/502124007/fake-news'
    r = http.request('GET', quote_page)
    # parse the html using beautiful soup and store in variable `soup`
    soup = BeautifulSoup(r.data, 'html.parser')
    # Take out the <div> of name and get its value
    news = soup.find_all('h2', attrs={'class': 'title'})
    news = news[0:10]
    text = []
    for link in news:
        r = http.request('GET', link.a.get('href'))
        soup = BeautifulSoup(r.data, 'html.parser')
        text.append(soup.find('div', attrs={'class': 'storytitle'}).text.strip() + ' ' +
        soup.find('div', attrs={'class': 'storytext'}).text.strip())
    return text

def getbbc():
    http = urllib3.PoolManager()
    quote_page = 'https://www.bbc.com/news/world'
    r = http.request('GET', quote_page)
    # parse the html using beautiful soup and store in variable `soup`
    soup = BeautifulSoup(r.data, 'html.parser')
    # Take out the <div> of name and get its value
    news = soup.find_all('article')
    news = news[0:10]
    text = []
    for link in news:
        new = link.header.div.h3.a.get('href')
        r = http.request('GET', 'https://www.bbc.com/'+new)
        soup = BeautifulSoup(r.data, 'html.parser')
        head = soup.find('h1', attrs={'class': 'story-body__h1'}).text.strip()
        body = soup.find('div', attrs={'class': 'story-body__inner'}).text.strip()
        text.append(head + ' ' +body)
    return text

# print(getbbc())


import json
import time
from pathlib import Path

import typer
from tqdm import tqdm

from back.crud.async_tag import CrudTag
from back.db.crud import CrudTagAttribute, CrudTagToken
from back.db.model import TagAttributeCreate, TagTokenCreate
from back.model.tag import TagInsert
from lib.typer import ZetsuBouTyper

def load_json(fpath: Path):
    with fpath.open(mode="r") as fp:
        data = json.load(fp)
    return data

_help = """
Manipulate the tag.
"""
app = ZetsuBouTyper(name="tag", help=_help)

@app.command()
async def dump(
    out: str = typer.Argument(..., help="The repository for the output JSON files."),
    force: bool = typer.Option(default=False, help="Overwrite the output JSON files."),
):
    """
    Dump the tag into JSON file.
    """

    out = Path(out)
    if not out.is_dir():
        return

    tags_path = out / "tag.json"
    if not force and tags_path.exists():
        return

    attrs_path = out / "attribute.json"
    if not force and attrs_path.exists():
        return

    async def get_attributes():
        print("get tag attributes ...")
        attrs = []
        skip = 0
        limit = 100
        rows = await CrudTagAttribute.get_rows_order_by_id(skip=skip, limit=limit)
        while rows:
            for row in tqdm(rows):
                attrs.append(row.model_dump())
            skip += limit
            rows = await CrudTagAttribute.get_rows_order_by_id(skip=skip, limit=limit)
        return attrs

    attrs = await get_attributes()
    with attrs_path.open(mode="w") as fp:
        json.dump(attrs, fp, indent=4, ensure_ascii=False)

    async def get_tags():
        print("get tags ...")
        crud = CrudTag()
        tags = []
        skip = 0
        limit = 100
        rows = await CrudTagToken.get_rows_order_by_id(skip=skip, limit=limit)
        while rows:
            for row in tqdm(rows):
                tag = await crud.get_interpretation_by_id(row.id)
                tags.append(tag.model_dump())
            skip += limit
            rows = await CrudTagToken.get_rows_order_by_id(skip=skip, limit=limit)
        return tags

    tags = await get_tags()
    with tags_path.open(mode="w") as fp:
        json.dump(tags, fp, indent=4, ensure_ascii=False)

@app.command()
async def load(
    attr: str = typer.Argument(..., help="The JSON file of the attributes."),
    tag: str = typer.Argument(..., help="The JSON file of the tags."),
):
    """
    Load the tag into JSON file.
    """

    async def is_ok():
        rows = await CrudTagToken.get_rows_order_by_id()
        if len(rows) > 0:
            return False
        return True

    async def insert_attr(attr_table, attr_data):
        print("insert tag attributes ...")
        for attr in tqdm(attr_data):
            name = attr["name"]
            row = await CrudTagAttribute.get_row_by_name(name)
            if row is None:
                row = await CrudTagAttribute.create(TagAttributeCreate(name=name))
            attr_table[name] = row.id

    async def insert_token(token_table, tag_data):
        print("insert tag tokens ...")
        for tag in tqdm(tag_data):
            id = tag["id"]
            name = tag["name"]
            row = await CrudTagToken.create(TagTokenCreate(name=name))
            token_table[id] = row.id

    def get_inserted_tag(token_table, attr_table, tag: dict):
        id = token_table[tag["id"]]
        name = tag["name"]
        category_ids = [token_table[c["id"]] for c in tag["categories"]]
        synonym_ids = [token_table[s["id"]] for s in tag["synonyms"]]
        attributes = {attr_table[a["name"]]: a["value"] for a in tag["attributes"]}

        return TagInsert(
            id=id,
            name=name,
            category_ids=category_ids,
            synonym_ids=synonym_ids,
            attributes=attributes,
        )

    async def insert_tag(crud: CrudTag, token_table, attr_table, tag_data):
        print("insert tags ...")
        for tag in tqdm(tag_data):
            inserted_tag = get_inserted_tag(token_table, attr_table, tag)
            await crud.insert(inserted_tag)

    attr = Path(attr)
    if not attr.exists():
        return

    tag = Path(tag)
    if not tag.exists():
        return

    ok = await is_ok()
    if not ok:
        print("TagToken table is not empty.")
        return

    attr_table = {}
    attr_data = load_json(attr)
    token_table = {}
    tag_data = load_json(tag)

    await insert_attr(attr_table, attr_data)
    print(f"tag attributes: {attr_table}")

    t1 = time.time()
    await insert_token(token_table, tag_data)
    t2 = time.time()
    crud = CrudTag()
    await insert_tag(crud, token_table, attr_table, tag_data)
    t3 = time.time()

    print(f"insert tag: {t2-t1} seconds")
    print(f"insert tag: {t3-t2} seconds")


#!/usr/bin/env python

"""
Simple app to demonstrate writing an MVC application for oil industry.
"""

import sys

from PyQt4 import QtGui

import view
import model
import controller

def main():
    """main"""

    # Convert data then we can interface with pytables exclusively
    model.convert_xls_to_hdf5(model.XLS_FILENAME, model.HDF5_FILENAME)

    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()

    window.setWindowTitle('PyHOU Sample App')
    window.setCentralWidget(controller.plot_production_by_month())
    window.show()

    state_prod_window = view.StateProductionDialog(
                                        controller.plot_production_by_state(),
                                        window)
    state_prod_window.setWindowTitle('Production by State')
    state_prod_window.show()

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()


# combines the results for each parameter combination into a single result for analysis/plotting.
import pandas as pd
from glob import glob

# date_time = "2023-04-01_20:43"
# date_time = "2023-04-03_15:47"
# date_time = "2023-04-03_16:07"
# date_time = "2023-05-29_09:54"
# date_time = "2023-05-29_10:20"
date_time = "2023-05-29_14:34"

out_df_list = []
for out_csv in glob(f"/scratch/da2343/data_transf_comp_{date_time}/results/*.csv"):
    out_df_list.append(pd.read_csv(out_csv))
error_df = pd.concat(out_df_list)
error_df.to_csv(f"/home/da2343/cs685_fall22/data_transf_comp/results/{date_time}_results.csv", index=False)