import os, sys
import time

from . import utesthooks
from . import pathutil
from .printinfo import TestInformationPrinter
from .outpututils import XstatusString, pretty_time

def run_batch( batch, tlist, xlist, perms, results_writer,
               test_dir, qsublimit ):
    ""
    numjobs = batch.getNumNotRun()
    schedule = batch.getScheduler()

    print3( 'Total number of batch jobs: ' + str(batch.getNumNotRun()) + \
            ', maximum concurrent jobs: ' + str(qsublimit) )

    starttime = time.time()
    print3( "Start time:", time.ctime() )

    cwd = os.getcwd()
    qsleep = int( os.environ.get( 'VVTEST_BATCH_SLEEP_LENGTH', 15 ) )

    uthook = utesthooks.construct_unit_testing_hook( 'batch' )

    rfile = tlist.initializeResultsFile()
    for inclf in batch.getIncludeFiles():
        tlist.addIncludeFile( inclf )

    info = TestInformationPrinter( sys.stdout, tlist, batch )

    try:
        while True:

            qid = schedule.checkstart()
            if qid != None:
                # nothing to print here because the qsubmit prints
                pass
            elif schedule.numInFlight() == 0:
                break
            else:
                sleep_with_info_check( info, qsleep )

            qidL,doneL = schedule.checkdone()

            if len(qidL) > 0:
                ids = ' '.join( [ str(qid) for qid in qidL ] )
                print3( 'Finished batch IDS:', ids )
            for tcase in doneL:
                ts = XstatusString( tcase, test_dir, cwd )
                print3( "Finished:", ts )

            uthook.check( schedule.numInFlight(), schedule.numPastQueue() )

            results_writer.midrun( tlist )

            if len(doneL) > 0:
                jpct = 100 * float(schedule.numDone()) / float(numjobs)
                jdiv = 'jobs '+str(schedule.numDone())+'/'+str(numjobs)
                jflt = '(in flight '+str(schedule.numStarted())+')'
                ndone = xlist.numDone()
                ntot = tlist.numActive()
                tpct = 100 * float(ndone) / float(ntot)
                tdiv = 'tests '+str(ndone)+'/'+str(ntot)
                dt = pretty_time( time.time() - starttime )
                print3( "Progress: " + \
                        jdiv+" = %%%.1f"%jpct + ' '+jflt+', ' + \
                        tdiv+" = %%%.1f"%tpct + ', ' + \
                        'time = '+dt )

        # any remaining tests cannot be run; flush then print warnings
        NS, NF, nrL = schedule.flush()

    finally:
        tlist.writeFinished()

    tlist.inlineIncludeFiles()

    perms.set( os.path.abspath( rfile ) )

    if len(NS)+len(NF)+len(nrL) > 0:
        print3()
    if len(NS) > 0:
      print3( "*** Warning: these batch numbers did not seem to start:",
              ' '.join(NS) )
    if len(NF) > 0:
      print3( "*** Warning: these batch numbers did not seem to finish:",
              ' '.join(NF) )
    for tcase0,tcase1 in nrL:
        assert tcase0.numDependencies() > 0 and tcase1 != None
        xdir0 = tcase0.getSpec().getDisplayString()
        xdir1 = tcase1.getSpec().getDisplayString()
        print3( '*** Warning: test "'+xdir0+'"',
                'notrun due to dependency "' + xdir1 + '"' )

def sleep_with_info_check( info, qsleep ):
    ""
    for i in range( int( qsleep + 0.5 ) ):
        info.checkPrint()
        time.sleep( 1 )

def run_test_list( qsub_id, tlist, xlist, test_dir, plat,
                   perms, results_writer ):
    ""
    plat.display()
    starttime = time.time()
    print3( "Start time:", time.ctime() )

    uthook = utesthooks.construct_unit_testing_hook( 'run', qsub_id )

    rfile = tlist.initializeResultsFile()

    try:

        info = TestInformationPrinter( sys.stdout, xlist )

        # execute tests

        perms.set( os.path.abspath( rfile ) )

        cwd = os.getcwd()

        while True:

            tnext = xlist.popNext( plat )

            if tnext != None:
                tspec = tnext.getSpec()
                texec = tnext.getExec()
                print3( 'Starting:', exec_path( tspec, test_dir ) )
                xlist.startTest( tnext, plat )
                tlist.appendTestResult( tnext )

            elif xlist.numRunning() == 0:
                break

            else:
                info.checkPrint()
                time.sleep(1)

            showprogress = False
            for tcase in list( xlist.getRunning() ):
                tx = tcase.getExec()
                if tx.poll():
                    xs = XstatusString( tcase, test_dir, cwd )
                    print3( "Finished:", xs )
                    xlist.testDone( tcase )
                    showprogress = True

            uthook.check( xlist.numRunning(), xlist.numDone() )

            results_writer.midrun( tlist )

            if showprogress:
                ndone = xlist.numDone()
                ntot = tlist.numActive()
                pct = 100 * float(ndone) / float(ntot)
                div = str(ndone)+'/'+str(ntot)
                dt = pretty_time( time.time() - starttime )
                print3( "Progress: " + div+" = %%%.1f"%pct + ', time = '+dt )

    finally:
        tlist.writeFinished()

    # any remaining tests cannot run, so print warnings
    tcaseL = xlist.popRemaining()
    if len(tcaseL) > 0:
        print3()
    for tcase in tcaseL:
        deptx = tcase.getBlockingDependency()
        assert tcase.numDependencies() > 0 and deptx != None
        xdir = tcase.getSpec().getDisplayString()
        depxdir = deptx.getSpec().getDisplayString()
        print3( '*** Warning: test "'+xdir+'"',
                'notrun due to dependency "' + depxdir + '"' )

def exec_path( testspec, test_dir ):
    ""
    xdir = testspec.getDisplayString()
    return pathutil.relative_execute_directory( xdir, test_dir, os.getcwd() )

def run_baseline( xlist, plat ):
    ""
    failures = False
    for tcase in xlist.getTestExecList():

        tspec = tcase.getSpec()
        texec = tcase.getExec()

        xdir = tspec.getDisplayString()

        sys.stdout.write( "baselining "+xdir+"..." )

        xlist.startTest( tcase, plat, baseline=1 )

        tm = int( os.environ.get( 'VVTEST_BASELINE_TIMEOUT', 30 ) )
        for i in range(tm):

            time.sleep(1)

            if texec.poll():
                if tcase.getStat().passed():
                    print3( "done" )
                else:
                    failures = True
                    print3("FAILED")
                break

        if not tcase.getStat().isDone():
            texec.killJob()
            failures = True
            print3( "TIMED OUT" )

    if failures:
        print3( "\n\n !!!!!!!!!!!  THERE WERE FAILURES  !!!!!!!!!! \n\n" )

def print3( *args ):
    ""
    sys.stdout.write( ' '.join( [ str(arg) for arg in args ] ) + '\n' )
    sys.stdout.flush()


from discord.ext import tasks
from discord.ext.commands import Cog, command ,cooldown ,BucketType
from discord.ext import commands
from random import choice
import discord
import requests
from discord import Spotify
import pendulum
# aiohttp should be installed if discord.py is
import aiohttp
from discord import Webhook, AsyncWebhookAdapter
import random
import PIL
from asyncio import sleep
from imdb import IMDb
# PIL can be installed through
# `pip install -U Pillow`
from PIL import Image, ImageDraw, ImageChops, ImageEnhance,ImageOps ,ImageFont

# partial lets us prepare a new function with args for run_in_executor
from functools import partial

# BytesIO allows us to convert bytes into a file-like byte stream.
from io import BytesIO
# from wand import image

# this just allows for nice function annotation, and stops my IDE from complaining.
from typing import Union
from random import randint
import discord
import datetime
from ..utils import noisegen
from ..utils.textutils import auto_text_size
from ..db import db
from ..utils.paginator import HelpPaginator

class ImageCog(Cog):
    def __init__(self, bot):
        self.bot = bot

    def custom_check():
        def predicate(ctx):
            cog = ctx.bot.get_cog("Fun")
            command  =  db.field("SELECT commandname FROM command WHERE channelid = ?", ctx.channel.id)
            if command is not None:
                command.split(',')
                if  len(command)> 1 and ctx.command.name in command :
                    return
                elif ctx.command.name in command :
                    return
            return True
        return commands.check(predicate)

    @Cog.listener()
    async def on_ready(self):
        if not self.bot.ready:
            self.bot.cogs_ready.ready_up("image")

    async def get_avatar(self, user: Union[discord.User, discord.Member]) -> bytes:

        # generally an avatar will be 1024x1024, but we shouldn't rely on this
        avatar_url = user.avatar_url_as(format="png")
        async with aiohttp.ClientSession() as cs:
            async with cs.get(f'{avatar_url}') as res:

            # this gives us our response object, and now we can read the bytes from it.
                avatar_bytes = await res.read()

        return avatar_bytes

    @staticmethod
    def processing(avatar_bytes: bytes, colour: tuple) -> BytesIO:

        # we must use BytesIO to load the image here as PIL expects a stream instead of
        # just raw bytes.
        with Image.open(BytesIO(avatar_bytes)) as im:

            # this creates a new image the same size as the user's avatar, with the
            # background colour being the user's colour.
            with Image.new("RGB", im.size, colour) as background:

                # this ensures that the user's avatar lacks an alpha channel, as we're
                # going to be substituting our own here.
                rgb_avatar = im.convert("RGB")

                # this is the mask image we will be using to create the circle cutout
                # effect on the avatar.
                with Image.new("L", im.size, 0) as mask:

                    # ImageDraw lets us draw on the image, in this instance, we will be
                    # using it to draw a white circle on the mask image.
                    mask_draw = ImageDraw.Draw(mask)

                    # draw the white circle from 0, 0 to the bottom right corner of the image
                    mask_draw.ellipse([(0, 0), im.size], fill=255)

                    # paste the alpha-less avatar on the background using the new circle mask
                    # we just created.
                    background.paste(rgb_avatar, (0, 0), mask=mask)

                # prepare the stream to save this image into
                final_buffer = BytesIO()

                # save into the stream, using png format.
                background.save(final_buffer, "png")
                background.save("./data/images/circle.png")

        # seek back to the start of the stream
        final_buffer.seek(0)

        return final_buffer

    # @command(name = "circle")
    # @cooldown(2, 60, BucketType.user)
    # async def circle(self, ctx, *, member: discord.Member = None):
    #     """Display the user's avatar on their colour."""

    #     # this means that if the user does not supply a member, it will default to the
    #     # author of the message.
    #     member = member or ctx.author

    #     async with ctx.typing():
    #         # this means the bot will type while it is processing and uploading the image

    #         if isinstance(member, discord.Member):
    #             # get the user's colour, pretty self explanatory
    #             member_colour = member.colour.to_rgb()
    #         else:
    #             # if this is in a DM or something went seriously wrong
    #             member_colour = (0, 0, 0)

    #         # grab the user's avatar as bytes
    #         avatar_bytes = await self.get_avatar(member)

    #         # create partial function so we don't have to stack the args in run_in_executor
    #         fn = partial(self.processing, avatar_bytes, member_colour)

    #         # this runs our processing in an executor, stopping it from blocking the thread loop.
    #         # as we already seeked back the buffer in the other thread, we're good to go
    #         final_buffer = await self.bot.loop.run_in_executor(None, fn)

    #         # prepare the file
    #         file = discord.File(filename="./data/images/circle.png", fp=final_buffer)

    #         # send it
    #         await ctx.send(file=file)
    @command(name = 'brazzers', description = 'Add the Brazzers logo to profile pic', usage = '+brazzers <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def brazzers(self,ctx,*,member :discord.Member = None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png",size = 1024) # try all three
        # response = await requests.get(img_url)
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)
                base = Image.open('./data/images/brazzers.bmp')
                aspect = avatar.width / avatar.height
                new_height = int(base.height * aspect)
                new_width = int(base.width * aspect)
                scale = new_width / avatar.width
                size = (int(new_width / scale / 2), int(new_height / scale / 2))
                base = base.resize(size).convert('RGBA')
                # avatar is technically the base
                avatar.paste(base, (avatar.width - base.width,
                                    avatar.height - base.height), base)
                avatar = avatar.convert('RGBA')
                b = BytesIO()
                avatar.save(b, format='png')
                b.seek(0)
                file = discord.File(filename="brazzers.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'leftist', description  = 'add marxist flag to your profile', usage = '+leftist <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def leftist(self,ctx,member:discord.Member=None):
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                img1 = Image.open(data)
                img1 = img1.resize((300,300)).convert('RGBA')
                img2 = Image.open('./data/images/communism.gif')
                img1.putalpha(96)
                out = []
                for i in range(0, img2.n_frames):
                    img2.seek(i)
                    f = img2.copy().convert('RGBA').resize((300, 300))
                    f.paste(img1, (0, 0), img1)
                    out.append(f.resize((256, 256)))
                b = BytesIO()
                out[0].save(b, format='gif', save_all=True, append_images=out[1:], loop=0, disposal=2, optimize=True, duration=40)
                img2.close()
                b.seek(0)
                file = discord.File(filename="leftist.gif", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'deepfry', description  = 'deepfries your pfp', usage = '+deepfry <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def deepfry(self,ctx,member:discord.Member=None):
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)

                avatar = avatar.resize((400, 400)).convert('RGBA')

                # noinspection PyPep8
                joy, hand, hundred, fire = [
                    Image.open(f'./data/images/deepfry/{asset}.bmp')
                    .resize((100, 100))
                    .rotate(randint(-30, 30))
                    .convert('RGBA')
                    for asset in ['joy', 'ok-hand', '100', 'fire']
                ]

                avatar.paste(joy, (randint(20, 75), randint(20, 45)), joy)
                avatar.paste(hand, (randint(20, 75), randint(150, 300)), hand)
                avatar.paste(hundred, (randint(150, 300), randint(20, 45)), hundred)
                avatar.paste(fire, (randint(150, 300), randint(150, 300)), fire)

                noise = avatar.convert('RGB')
                noise = noisegen.add_noise(noise, 25)
                noise = ImageEnhance.Contrast(noise).enhance(randint(5, 20))
                noise = ImageEnhance.Sharpness(noise).enhance(17.5)
                noise = ImageEnhance.Color(noise).enhance(randint(-15, 15))

                b = BytesIO()
                noise.save(b, format='png')
                b.seek(0)
                file = discord.File(filename="deepfry.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'imdelete', description = 'delete this meme', usage = '+delete <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def imdelete(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)

                avatar = avatar.resize((195, 195)).convert('RGBA')
                base = Image.open('./data/images/delete.bmp').convert('RGBA')

                base.paste(avatar, (120, 135), avatar)
                base = base.convert('RGBA')

                b = BytesIO()
                base.save(b, format='png')
                b.seek(0)
                file = discord.File(filename="delete.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'disability', description = 'not all disabilities look like you', usage = '+disability <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def disability(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)

                avatar = avatar.resize((175, 175)).convert('RGBA')
                base = Image.open('./data/images/disability.bmp').convert('RGBA')
                base.paste(avatar, (450, 325), avatar)
                base = base.convert('RGBA')

                b = BytesIO()
                base.save(b, format='png')
                b.seek(0)
                file = discord.File(filename="disability.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'door', description  = 'door meme manipulation',usage = '+door <user>' )
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def door(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)
                base = Image.open('./data/images/door.bmp').convert('RGBA')
                avatar = avatar.resize((479, 479)).convert('RGBA')
                final_image = Image.new('RGBA', base.size)

                # Put the base over the avatar
                final_image.paste(avatar, (250, 0), avatar)
                final_image.paste(base, (0, 0), base)
                final_image = final_image.convert('RGBA')

                b = BytesIO()
                final_image.save(b, format='png')
                b.seek(0)

                file = discord.File(filename="door.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'failure', description = 'are you a failure?', usage =  '+failure <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def failure(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)

                avatar = avatar.resize((215, 215)).convert('RGBA')
                base = Image.open('./data/images/failure.bmp').convert('RGBA')
                base.paste(avatar, (143, 525), avatar)

                base = base.convert('RGBA')

                b = BytesIO()
                base.save(b, format='png')
                b.seek(0)

                file = discord.File(filename="failure.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'gay', description  = 'Show your gay pride!', usage = '+gay <user>')
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def gay(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                avatar = Image.open(data)

                base = Image.open('./data/images/gay.bmp').convert('RGBA').resize(avatar.size)
                base.putalpha(128)
                avatar.paste(base,(0,0),base)

                avatar = avatar.convert('RGB')

                b = BytesIO()
                avatar.save(b, format='png')
                b.seek(0)

                file = discord.File(filename="gay.png", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'bjp', description = 'command for bjp fan',usage = '+bjp <user>' )
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def bjp(self,ctx,member:discord.Member=None):
        # member = member or ctx.author
        # img_url = member.avatar_url_as(format="png") # try all three
        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                img1 = Image.open(data)
                img1 = img1.resize((300,300)).convert('RGBA')
                img2 = Image.open('./data/images/bjp.gif')
                img1.putalpha(98)
                out = []
                for i in range(0, img2.n_frames):
                    img2.seek(i)
                    f = img2.copy().convert('RGBA').resize((300, 300))
                    f.paste(img1, (0, 0), img1)
                    out.append(f.resize((256, 256)))
                b = BytesIO()
                out[0].save(b, format='gif', save_all=True, append_images=out[1:], loop=0, disposal=2, optimize=True, duration=40)
                img2.close()
                b.seek(0)
                file = discord.File(filename="bjp.gif", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'bonk', description = 'bonk a user',usage = '+bonk <user>' )
    @custom_check()
    @cooldown(1, 10, BucketType.user)

    async def bonk(self,ctx, member : discord.Member = None ):
        '''+bonk @rohan'''

        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png")

        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')
                data = BytesIO(await resp.read())
                img1 = Image.open(data)
                img1 = img1.resize((140,100)).convert('RGBA')
                img1 = img1.rotate(40,PIL.Image.NEAREST, expand = 1)
                img2 = Image.open('./data/images/bonk.gif')
                out = []
                for i in range(0, img2.n_frames):
                    img2.seek(i)

                    f = img2.copy().convert('RGBA')
                    f.paste(img1, (285, 205), img1)
                    out.append(f)
                b = BytesIO()
                out[0].save(b, format='gif', save_all=True, append_images=out[1:], loop=0, disposal=2, optimize=True, duration=40)
                img2.close()
                b.seek(0)
                file = discord.File(filename="bonk.gif", fp=b)
                await ctx.send(file = file)
                del b

    @command(name = 'faket6', aliases = ['ft6'], description  = 'create your own t6',usage = '+faket6 <title> <user>' )
    @custom_check()
    @cooldown(3, 45, BucketType.user)

    async def faket6(self,ctx, title , member:discord.Member=None):
        '''faket6 rohan-bhangi @rohan \nfaket6 tommy-cutie @tommy'''

        if member == None and ctx.message.attachments:
            attachment_url = ctx.message.attachments[0].url
            img_url = attachment_url
        elif member != None and not ctx.message.attachments:

            img_url = member.avatar_url_as(format="png",size = 1024)
        else :
            entity =  ctx.command
            p = await HelpPaginator.from_command(ctx, entity)
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{img_url}") as resp:
                if resp.status != 200:
                    return await ctx.send('Could not download file...')

                data = BytesIO(await resp.read())
                avatar = Image.open(data)
                base = Image.open('./data/images/t6.png').convert('RGBA')
                avatar = avatar.resize((258, 358)).convert('RGBA')
                base.paste(avatar,(21,0), avatar)
                b = BytesIO()
                base.save(b, format='png')
                b.seek(0)
                file = discord.File(filename="ft6.png", fp=b)
                try:
                    title = title.split("-")

                    title =  (" ").join(f"{entry}" for entry in title)
                except:
                    title = title

                shoob  = self.bot.get_user(673362753489993749)
                img = shoob.avatar_url_as(format = 'png', size = 1024)
                async with aiohttp.ClientSession() as cs:
                    async with cs.get(str(img)) as res:
                        byte = await res.read()
                        hook = await ctx.channel.webhooks()

                        if len(hook)< 10 :
                            # print(len(ctx.channel.webhooks()))
                            web = await ctx.channel.create_webhook(name=shoob.display_name,avatar = byte)

                            embed =  discord.Embed(title = f'{title} Tier: 6', colour = discord.Color(value=0xff0000),url = 'https://www.lazybuds.xyz/' ,description = 'To claim, use: `claim [captcha code]`\n[See your card inventory on our site.\nSupport us and get global rewards!](https://www.lazybuds.xyz/)')
                            embed.set_image(url = "attachment://ft6.png")
                            await web.send(embed = embed, file = file)
                            await web.delete()
                            try:
                                await ctx.message.delete()
                            except:
                                pass
                            res = 'claim bwbih'
                            def check(m):
                                return (m.content).lower() == res.lower()
                            try:

                                reply = await self.bot.wait_for('message', check=check, timeout = 120)
                                web2 = await ctx.channel.create_webhook(name=shoob.display_name,avatar = byte)
                                table = f'✅ {reply.author.mention} got the card! `{title}` Issue #: `1`. '
                                embed= discord.Embed(description = table, colour  = discord.Color(value = 0x80ca57))
                                await web2.send(embed = embed)
                                await web2.delete()

                            except :
                                await ctx.send(f'Looks like no one got the card {title} T6 at this time..')

                        else :
                            await ctx.send('webhook limit is full for the channel')

    @command(name = 'spotify', description  = 'shows detail of a song user is listening to', usage = '+spotify <user>')
    @custom_check()
    @commands.cooldown(1,30, commands.BucketType.user)
    async def music(self,ctx, user:discord.Member = None):
        user = user or ctx.author

        for activity in user.activities:
            if isinstance(activity,Spotify):
                async with aiohttp.ClientSession() as session:
                    async with session.get(f"{activity.album_cover_url}") as resp:
                        if resp.status != 200:
                            return await ctx.send('Could not download file...')

                        data = BytesIO(await resp.read())
                        album_pic = Image.open(data)
                        base = Image.open('./data/images/spotify.png')
                        width, height =base.size
                        album_pic = album_pic.resize((120, 120)).convert('RGBA')
                        base.paste(album_pic,(50,(height//2)-60), album_pic)
                        draw = ImageDraw.Draw(base)
                        shadowcolor  = 'black'

                        if (len(activity.title) <= 37):
                            fontbig = ImageFont.truetype("arial.ttf", 28)
                            x,y = (190,(height//2)-61)

                            draw.text((190, (height//2)-60), f"{activity.title}", font=fontbig, fill=shadowcolor)
                            fontbig = ImageFont.truetype("./data/tommy_thin.otf", 24)
                            draw.text((190, (height//2)-21), f"{activity.artist}", font=fontbig, fill=shadowcolor)
                        elif 45> len(activity.title)> 37:
                            fontbig = ImageFont.truetype("arial.ttf", 23)
                            x,y = (190,(height//2)-61)

                            draw.text((190, (height//2)-60), f"{activity.title}", font=fontbig, fill=shadowcolor)
                            fontbig = ImageFont.truetype("./data/tommy_thin.otf", 20)
                            draw.text((190, (height//2)-21), f"{activity.artist}", font=fontbig, fill=shadowcolor)

                        else:
                            em = discord.Embed(color=discord.Color.dark_green())
                            em.set_author(name  = 'Spotify', icon_url  = "https://cdn.discordapp.com/attachments/714910677029879898/745727179274321941/spotify2.png")
                            em.set_thumbnail(url=activity.album_cover_url)
                            em.add_field(name = f"**Song Name**:" , value =  f'{activity.title}', inline = True)

                            em.add_field(name = f"**Song Artist**:" , value =  f'{activity.artist}', inline = True)
                            em.add_field(name = "**Song Album**:" , value = f'{activity.album}', inline = False)
                            em.add_field(name = f"**Song Duration**:" , value =  f"{pendulum.duration(seconds=activity.duration.total_seconds()).in_words(locale='en')}", inline = True)
                            em.add_field(name  = f'**Song url :**', value  = f"https://open.spotify.com/track/%7B{activity.track_id}%7D", inline = False)
                            return await ctx.send(embed=em)

                        print(activity.start)
                        print(datetime.datetime.utcnow())

                        now = datetime.datetime.utcnow()- activity.start

                        print(now)
                        count = now.total_seconds()
                        date_time_obj = datetime.datetime.strptime(str(now), '%H:%M:%S.%f')

                        current = f'{date_time_obj.minute}m {date_time_obj.second}s'
                        print(current)

                        total = activity.duration

                        dur = total.total_seconds()
                        total = datetime.datetime.strptime(str(total), '%H:%M:%S.%f')

                        final = f'{total.minute}m {total.second}s'

                        bar_len = 14 # bar length
                        filled_len = int(bar_len * count // float(dur))
                        bar =   u"─"  * filled_len + '●' + '─' * (bar_len - filled_len)
                        song =  f'{bar}'
                        listening = f'<:spotify:805776553626828800> Listening to **{activity.title}** by **{activity.artist}** | {user.name}'
                        fontbig = ImageFont.truetype("./data/arialuni.ttf", 32, encoding = "utf-8")
                        draw.text((190, (height//2)+18),song, font=fontbig, fill=shadowcolor)
                        fontbi = ImageFont.truetype("arial.ttf", 16)

                        draw.text((364, (height//2)+50),f'{current} / {final}', font=fontbi, fill=shadowcolor)
                        b = BytesIO()
                        base.save(b, format='png')
                        b.seek(0)
                        file = discord.File(filename="spotify.png", fp=b)
                        await ctx.send(listening, file= file)
                        break

        else:
            embed = discord.Embed(description=f"<:spotify:805776553626828800> {user.name} isn't listening to Spotify right now", color=discord.Color.dark_red())
            await ctx.send(embed=embed)

    # @command(name  = 'imdb')
    # async def imdb(self,ctx, * , movie):
    #     ia = IMDb()
    #     search = ia.search_movie(f"{movie}")
    #     for i in range(len(search)):
    #         id_ = search[0].movieID

    #     movie = ia.get_movie(id_)
    #     print(movie)

# setup function so this can be loaded as an extension
def setup(bot):
    bot.add_cog(ImageCog(bot))


month = int(input())
first_case = ((month==11) or month == 12) or month == 1
second_case = month == 2 or month == 3
third_case = ((month == 4) or month == 5) or month == 6
fourth_case  = month == 7 or month == 8
fifth_case  = month == 9 or month == 10
if first_case:
    print("Winter")
elif second_case:
    print("Spring")
elif third_case:
    print("Summer")
elif fourth_case:
    print("Rainy")
elif fifth_case:
    print("Autumn")


import requests
import os
from twilio.rest import Client
from dotenv import load_dotenv

load_dotenv()

account_sid = os.getenv("ACCOUNT_SID")
auth_token = os.getenv("AUTH_TOKEN")
twilio_phone = os.getenv("TWILIO_PHONE")
my_phone = os.getenv("MY_PHONE")

# "lat": -36.848461,
# "lon": 174.763336,

parameters = {
    "lat": 32.011261,
    "lon": 34.774811,
    "appid": os.getenv("APP_ID_API_WEATHER"),
    "exclude": "current, minutely, daily"
}

response = requests.get("https://api.openweathermap.org/data/2.8/onecall", params=parameters)
response.raise_for_status()
weather_data = response.json()
weather_slice = weather_data["hourly"][:12]

will_rain = False

for hour_data in weather_slice:
    condition_code = hour_data["weather"][0]["id"]
    if int(condition_code) < 700:
        will_rain = True

if will_rain:
    client = Client(account_sid, auth_token)
    message = client.messages.create(
        from_=f'whatsapp:{twilio_phone}',
        body="הולך לרדת גשם. לא לשכוח להביא מטריה ☂",
        to=f'whatsapp:{my_phone}'
    )

My Projects on Data Science, Web and more/Section 34 - API Weather/RainUpdatedEveryDay.py


#syzdavane na klas s ime i svoistvo:
class MyFirstClass:
    x=5

#syzdavane na obekt, baziran na syzdaden klas:
MyFirstObject= MyFirstClass()

#dostypvane elemntite na klasa:
print(MyFirstObject.x)

#funkciqta konstructor __init__()

class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
MyPerson=Person("Ivan",35)
print(MyPerson.name)
print(MyPerson.age)

#Metodi:

class Person:
     def __init__(self,name,age):
        self.name=name
        self.age=age
     def greetings(self):
         print("Hello, my name is "+self.name)
MyPerson=Person("Ivan",35)
MyPerson.greetings()

#parametyr self

#promqna na stoinostite na svoistvata na obekti:
MyPerson.age=40

#iztrivane svoistvata na obekti s del:
del MyPerson.age

#iztrivane na celi obekti s del:
del MyPerson

#definirane na klas bez sydyrjanie (pass)
class Person:
    pass

#nasledqvane:

От мен/Клас.py


"""Utilities to manipulate GW data and rational filters.
"""
__all__ = ['Data', 'Filter']

import astropy.constants as c
import qnm
import pandas as pd
import numpy as np
import scipy.signal as ss

T_MSUN = c.M_sun.value * c.G.value / c.c.value**3

class Filter:
    """Container for rational filters.

    Attributes
    ----------
    chi : float
        remnant dimensionless spin.
    mass : float
        remnant mass, in solar mass.
    model_list : a list of dictionaries
        quasinormal modes to be filtered.
    """

    def __init__(self, chi=None, mass=None, model_list=None):
        """Constructor"""
        self.chi = chi
        self.mass = mass # in solar mass

        self.model_list = []
        for (l, m, n) in model_list:
            self.model_list.append(dict(l = l, m = m, n = n))

    @property
    def get_spin(self) -> float:
        """Return :attr:`Filter.chi`."""
        return self.chi

    @property
    def get_mass(self) -> float:
        """Return :attr:`Filter.mass`."""
        return self.mass

    @property
    def get_model_list(self) -> list[dict]:
        """Return :attr:`Filter.model_list`."""
        return self.model_list

    @staticmethod
    def mass_unit(mass) -> float:
        """Convert mass unit from solar mass to second."""
        return mass * T_MSUN

    def single_filter(self, normalized_freq, l, m, n):
        """Compute rational filters.

        Parameters
        ----------
        normalized_freq : array
            in remnant mass, frequencies that rational filters are evaluated at.
        """
        omega = qnm.modes_cache(s=-2, l=l, m=m, n=n)(a=self.chi)[0]
        return (normalized_freq-omega)/(normalized_freq-np.conj(omega))\
                *(normalized_freq+np.conj(omega))/(normalized_freq+omega)

    def total_filter(self, freq):
        """The total rational filter that removes the modes stored in :attr:`Filter.model_list`.

        Parameters
        ----------
        freq : array
            in Hz, frequencies that the total filter is evaluated at.
        """
        final_rational_filter = 1
        if not bool(self.model_list):
            return final_rational_filter
        else:
            if (self.mass is None) or (self.chi is None):
                raise ValueError(f"Mass = {self.mass}"
                                 f" and Spin = {self.chi} are needed")
        normalized_freq = freq * self.mass * T_MSUN
        for mode in self.model_list:
            final_rational_filter *= self.single_filter(-normalized_freq,\
                                     mode["l"], mode["m"], mode["n"])
        return final_rational_filter

class Data(pd.Series):
    """Container for gravitational data.

    Attributes
    ----------
    ifo : str
        name of interferometer.
    """

    def __init__(self, *args, ifo=None,  **kwargs):
        super(Data, self).__init__(*args, **kwargs)
        self.ifo = ifo

    @property
    def time(self):
        """Time stamps."""
        return self.index.values

    @property
    def time_interval(self) -> float:
        """Interval of the time stamps."""
        return self.index[1] - self.index[0]

    @property
    def fft_span(self) -> float:
        """Span of FFT."""
        return 1./self.time_interval

    @property
    def fft_freq(self):
        """FFT angular frequency stamps."""
        return np.fft.rfftfreq(len(self), d=self.time_interval) * 2 * np.pi

    @property
    def fft_data(self):
        """FFT of gravitational-wave data."""
        return np.fft.rfft(self.values, norm='ortho')

    def condition(self, t0=None, srate=None, flow=None, fhigh=None, trim=0.25,
                  remove_mean=True, **kwargs):
        """Condition data.

        Credit: This function is from `git@github.com:maxisi/ringdown.git`.

        Arguments
        ---------
        flow : float
            lower frequency for high passing.
        fhigh : float
            higher frequency for low passing.
        srate : int
            sampling frequency after downsampling.
        t0 : float
            target time to be preserved after downsampling.
        remove_mean : bool
            explicitly remove mean from time series after conditioning.
        trim : float
            fraction of data to trim from edges after conditioning, to avoid
            spectral issues if filtering.

        Returns
        -------
        cond_data : Data
            conditioned data object.
        """

        srate = kwargs.pop('srate', srate)
        flow = kwargs.pop('flow', flow)
        raw_data = self.values
        raw_time = self.index.values

        ds = int(round(self.fft_span/srate))

        if t0 is not None:
            ds = int(ds or 1)
            i = np.argmin(abs(raw_time - t0))
            raw_time = np.roll(raw_time, -(i % ds))
            raw_data = np.roll(raw_data, -(i % ds))

        fny = 0.5 * self.fft_span
        # Filter
        if flow and not fhigh:
            b, a = ss.butter(4, flow/fny, btype='highpass', output='ba')
        elif fhigh and not flow:
            b, a = ss.butter(4, fhigh/fny, btype='lowpass', output='ba')
        elif flow and fhigh:
            b, a = ss.butter(4, (flow/fny, fhigh/fny), btype='bandpass',
                              output='ba')

        if flow or fhigh:
            cond_data = ss.filtfilt(b, a, raw_data)
        else:
            cond_data = raw_data

        if ds and ds > 1:
            cond_data = ss.decimate(cond_data, ds, zero_phase=True)
            cond_time = raw_time[::ds]

        N = len(cond_data)
        istart = int(round(trim*N))
        iend = int(round((1-trim)*N))

        cond_time = cond_time[istart:iend]
        cond_data = cond_data[istart:iend]

        if remove_mean:
            cond_data -= np.mean(cond_data)

        return Data(cond_data, index=cond_time, ifo=self.ifo)

    def data_psd(self, **kws):
        """Estimate PSDs from data using Welch's method."""
        fs = self.fft_span
        nperseg = fs/kws.get('sampling_rate', 1)

        freq, psd = ss.welch(self.values, fs=fs, nperseg=nperseg)
        return Data(psd, index=freq)

    def data_acf(self, **kws):
        """Estimate ACFs from data using Welch's method."""
        dt = self.time_interval
        fs = self.fft_span

        psd = self.data_psd(**kws)
        rho = 0.5 * np.fft.irfft(psd) * fs
        return Data(rho, index=np.arange(len(rho))*dt)


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

"""
Look at pairs of stations (NetAtmo-DWD)

Select nearest stations, for one DWD station, aggregate to daily
and disaggregate according to relative values of NetAtmo station

Check if this gives reasonable Temporal structure or not

Save the daily DWD and NetAtmo sums in a dataframe, use it to find
scaling factor between the values
"""

__author__ = "Abbas El Hachem"
__copyright__ = 'Institut fuer Wasser- und Umweltsystemmodellierung - IWS'
__email__ = "abbas.el-hachem@iws.uni-stuttgart.de"
#==============================================================================
#
#==============================================================================
import os
import timeit
import time

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as md

from matplotlib.ticker import MultipleLocator, FormatStrFormatter

from _00_additional_functions import (resample_intersect_2_dfs, resampleDf)
from b_get_data import HDF5

plt.ioff()
#==============================================================================
#
#==============================================================================

path_to_ppt_netatmo_data = (r'X:\hiwi\ElHachem\Prof_Bardossy\Extremes'
                            r'\NetAtmo_BW\ppt_all_netatmo_hourly_stns_combined_new.csv')
assert os.path.exists(path_to_ppt_netatmo_data), 'wrong NETATMO Ppt file'

path_to_ppt_hdf_data = (r'F:\data_from_exchange'
                        r'\niederschlag_deutschland'
                        r'\1993_2016_5min_merge_nan.h5')
assert os.path.exists(path_to_ppt_hdf_data), 'wrong NETATMO Ppt file'

coords_dwd_df_file = (r'F:\data_from_exchange\niederschlag_deutschland'
                      r'\1993_2016_5min_merge_nan.csv')
assert os.path.exists(coords_dwd_df_file), 'wrong DWD coords file'

coords_netatmo_df_file = (r'X:\hiwi\ElHachem\Prof_Bardossy\Extremes'
                          r'\NetAtmo_BW\rain_bw_1hour\netatmo_bw_1hour_coords.csv')

assert os.path.exists(coords_netatmo_df_file), 'wrong NETATMO coords file'

distance_matrix_df_file = (r'X:\hiwi\ElHachem\Prof_Bardossy\Extremes'
                           r'\NetAtmo_BW\distance_mtx_in_m_NetAtmo_DWD.csv')
assert os.path.exists(distance_matrix_df_file), 'wrong Distance MTX  file'

out_save_dir_orig = (
    r'X:\hiwi\ElHachem\Prof_Bardossy\Extremes\compare_plot_cycles_DWD_NetAtmo')

if not os.path.exists(out_save_dir_orig):
    os.mkdir(out_save_dir_orig)

max_ppt_thr = 100.

save_df_common = False
#==============================================================================
#
#==============================================================================

def plot_values_2_stns(stn1_id, stn2_id, df1, df2, seperate_dist,
                       temp_freq, out_dir):

    assert df1.shape[0] == df2.shape[0], 'Dfs have different shapes'
    plt.ioff()
    fig = plt.figure(figsize=(20, 12), dpi=150)
    ax = fig.add_subplot(111)

    time_vals = df1.index.to_pydatetime()
    time_arr = md.date2num(time_vals)

    ax.plot(time_arr, df1.values, c='r', marker='+', markersize=2,
            alpha=0.5, label=stn1_id)
    ax.plot(time_arr, df2.values, c='g', marker='*', markersize=2,
            alpha=0.5, label=stn2_id)
    xfmt = md.DateFormatter('%Y-%m-%d')

    ax.xaxis.set_major_locator(MultipleLocator(30))
    ax.yaxis.set_major_locator(MultipleLocator(3))

    ax.xaxis.set_major_formatter(xfmt)
    ax.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    ax.set_ylim(-0.1, max(df1.values.ravel().max(),
                          df2.values.ravel().max()) + 1)
    ax.set_ylabel('Ppt mm/day ')
    ax.tick_params('y', colors='darkred')

    ax.set_title("Daily values Stn: %s vs Stn: %s;\n Distance: %0.1f m; "
                 "Time Freq: %s; " % (stn1_id, stn2_id,
                                      seperate_dist,
                                      temp_freq))

    ax.grid(color='k', linestyle='--', linewidth=0.1, alpha=0.25)
    plt.xticks(rotation=30)
    ax.legend(loc='upper right')
#     ax2.legend(loc='best')
#     plt.tight_layout()
    plt.savefig(os.path.join(out_dir, '%s_plot_values_stn_%s_vs_stn_%s_.png'
                             % (temp_freq, stn1_id, stn2_id)))
    plt.clf()
    plt.close('all')
    print('Done saving figure Line plot')

    return

#==============================================================================
#
#==============================================================================

def plot_ratio_2_stns(stn1_id, stn2_id, df1, df2, seperate_dist,
                      temp_freq, out_dir):

    assert df1.shape[0] == df2.shape[0], 'Dfs have different shapes'
    plt.ioff()
    fig = plt.figure(figsize=(20, 12), dpi=150)
    ax = fig.add_subplot(111)

    time_vals = df1.index.to_pydatetime()
    time_arr = md.date2num(time_vals)
    ratio_values = df1.values.ravel() / df2.values.ravel()
    ratio_values = np.nan_to_num(ratio_values)
    ratio_values[ratio_values > 1000] = 0
#     ratio_values[(0 <= ratio_values) & (ratio_values < 100)]

    ax.plot(time_arr,
            ratio_values,
            c='b',
            marker='o',
            markersize=2,
            alpha=0.5,
            label=str(stn1_id + r' / ' + stn2_id))

    ax.plot(time_arr,
            np.full(ratio_values.shape,
                    ratio_values.mean()),
            c='r',
            marker='+',
            markersize=2,
            alpha=0.5,
            label='mean ratio = %0.1f' % ratio_values.mean())
#     np.argwhere(ratio_values == ratio_values.max())
#     df1.index[np.argwhere(ratio_values == ratio_values.max())[0]][0]
    xfmt = md.DateFormatter('%Y-%m-%d')

    ax.xaxis.set_major_locator(MultipleLocator(30))
    ax.yaxis.set_major_locator(MultipleLocator(2))

    ax.xaxis.set_major_formatter(xfmt)
    ax.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    ax.set_ylim(- 0.01, ratio_values.max() + 1)
#     ax.set_xlabel('Time')
    ax.set_ylabel(r'Ratio daily values Stn  %s  Stn  %s ' %
                  (stn1_id, stn2_id))

    ax.tick_params('y', colors='blue')

    ax.set_title("Ratio between values Stn: %s vs Stn: %s;"
                 "\n Distance: %0.1f m; "
                 "Time Freq: %s; "
                 % (stn1_id, stn2_id,
                    seperate_dist,
                    temp_freq))

    ax.grid(color='k', linestyle='--', linewidth=0.1, alpha=0.25)
    plt.xticks(rotation=30)

    ax.legend(loc='best')
#     plt.tight_layout()
    plt.savefig(os.path.join(out_dir, '%s_ratio_values_stn_%s_vs_stn_%s_.png'
                             % (temp_freq, stn1_id, stn2_id)))
    plt.clf()
    plt.close('all')
    print('Done saving figure Line plot')

    return

#==============================================================================
#
#==============================================================================

def plot_max_daily_vals_2_stns(stn1_id, stn2_id, df1, df2, seperate_dist,
                               temp_freq, out_dir):

    assert df1.shape[0] == df2.shape[0], 'Dfs have different shapes'

    ppt_df_netatmo = df1.groupby([df1.index.dayofyear]).max()
    ppt_df_dwd = df2.groupby([df2.index.dayofyear]).max()

    fig = plt.figure(figsize=(20, 12), dpi=150)
    ax = fig.add_subplot(111)

    time_vals = ppt_df_netatmo.index

#     ratio_values[(0 <= ratio_values) & (ratio_values < 100)]

    ax.plot(time_vals, ppt_df_netatmo.values, c='darkblue',
            marker='o', markersize=2,
            alpha=0.5, label=stn1_id)

    ax.plot(time_vals, ppt_df_dwd.values, c='darkred',
            marker='+', markersize=2,
            alpha=0.5, label=stn2_id)
#     xfmt = md.DateFormatter('%Y-%m-%d')

    ax.xaxis.set_major_locator(MultipleLocator(15))
    ax.yaxis.set_major_locator(MultipleLocator(1))

#     ax.xaxis.set_major_formatter(xfmt)
    ax.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    ax.set_ylim(-0.1, max(ppt_df_netatmo.values.ravel().max(),
                          ppt_df_dwd.values.ravel().max()) + 1)
    ax.set_xlim(0, 365)
#     ax.set_xlabel('Time')
    ax.set_ylabel(r'Average Ppt (mm/day) ')
    ax.set_xlabel('Day of year')
    ax.tick_params('y', colors='darkblue')

    ax.set_title("Maximum daily value Stn: %s vs Stn: %s;\n Distance: %0.1f m; "
                 "Time Freq: %s; \n Start: %s - End: %s"
                 % (stn1_id, stn2_id,
                     seperate_dist,
                     temp_freq,
                     str(df1.index[0]),
                     str(df1.index[-1])))

    ax.grid(color='k', linestyle='--', linewidth=0.1, alpha=0.25)
    plt.xticks(rotation=30)

    ax.legend(loc='best')
#     plt.tight_layout()
    plt.savefig(os.path.join(out_dir, '%s_max_daily_values_stn_%s_vs_stn_%s_.png'
                             % (temp_freq, stn1_id, stn2_id)))
    plt.clf()
    plt.close('all')
    print('Done saving figure Line plot')

    return

#==============================================================================
#
#==============================================================================

def plot_max_monthly_vals_2_stns(stn1_id, stn2_id, df1, df2, seperate_dist,
                                 temp_freq, out_dir):

    assert df1.shape[0] == df2.shape[0], 'Dfs have different shapes'
    ppt_netatmo = df1.resample('M',
                               label='right',
                               closed='right').sum()
#     netatmo_monthly_max = ppt_netatmo.groupby([ppt_netatmo.index.month]).max()
    netatmo_monthly_avg = ppt_netatmo.groupby([ppt_netatmo.index.month]).mean()
#     netatmo_monthly_min = ppt_netatmo.groupby([ppt_netatmo.index.month]).min()

    ppt_df_dwd = df2.resample('M',
                              label='right',
                              closed='right').sum()
#     dwd_monthly_max = ppt_df_dwd.groupby([ppt_df_dwd.index.month]).max()
    dwd_monthly_avg = ppt_df_dwd.groupby([ppt_df_dwd.index.month]).mean()
#     dwd_monthly_min = ppt_df_dwd.groupby([ppt_df_dwd.index.month]).min()
    fig = plt.figure(figsize=(20, 12), dpi=150)
    ax = fig.add_subplot(111)

#     time_vals = ppt_df_netatmo.index.to_pydatetime()
#     time_arr = md.date2num(time_vals)

#     ax.plot(netatmo_monthly_max.index,
#             netatmo_monthly_max.values, c='darkred',
#             marker='o', markersize=4,
#             alpha=0.5, label=stn1_id)
#
#     ax.plot(dwd_monthly_max.index, dwd_monthly_max.values, c='darkblue',
#             marker='o', markersize=4,
#             alpha=0.5, label=stn2_id)

    ax.plot(netatmo_monthly_avg.index,
            netatmo_monthly_avg.values, c='r',
            marker='+', markersize=4,
            alpha=0.5, label=stn1_id)

    ax.plot(dwd_monthly_avg.index, dwd_monthly_avg.values, c='b',
            marker='+', markersize=4,
            alpha=0.5, label=stn2_id)

#     ax.plot(netatmo_monthly_min.index,
#             netatmo_monthly_min.values, c='salmon',
#             marker='*', markersize=4,
#             alpha=0.5)  # , label=stn1_id)
#
#     ax.plot(dwd_monthly_min.index, dwd_monthly_min.values, c='lightblue',
#             marker='*', markersize=4,
#             alpha=0.5)  # , label=stn2_id)

#     xfmt = md.DateFormatter('%d-%m-%y')
#
    ax.xaxis.set_major_locator(MultipleLocator(1))
    ax.yaxis.set_major_locator(MultipleLocator(5))
#
#     ax.xaxis.set_major_formatter(xfmt)
    ax.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    ax.set_ylim(-0.1, max(netatmo_monthly_avg.values.ravel().max(),
                          dwd_monthly_avg.values.ravel().max()) + 1)
#     ax.set_ylim(-0.1, max(netatmo_monthly_max.values.ravel().max(),
#                           dwd_monthly_max.values.ravel().max()) + 1)
#     ax.set_xlim(0, 365)
#     ax.set_xlabel('Time')
    ax.set_ylabel(r'Ppt (mm/month) ')
    ax.set_xlabel('Month of year')
    ax.tick_params('y', colors='k')

    ax.set_title("Mean monthly value Stn: %s vs Stn: %s;"
                 "\n Distance: %0.1f m; "
                 "Time Freq: %s; \n Start: %s - End: %s"
                 % (stn1_id, stn2_id,
                     seperate_dist,
                     temp_freq,
                     str(df1.index[0]),
                     str(df1.index[-1])))

    ax.grid(color='k', linestyle='--', linewidth=0.1, alpha=0.25)
    plt.xticks(rotation=0)

    ax.legend(loc='best')
#     plt.tight_layout()
    plt.savefig(os.path.join(out_dir,
                             '%s_mean_monthly_values_stn_%s_vs_stn_%s_.png'
                             % (temp_freq, stn1_id, stn2_id)))
    plt.clf()
    plt.close('all')
    print('Done saving figure Line plot')

    return
#==============================================================================
#
#==============================================================================

def construct_netatmo_dwd_daily_dfs(netatmo_ppt_df_file,
                                    path_to_ppt_hdf_data,
                                    distance_matrix_df_file):
    HDF52 = HDF5(infile=path_to_ppt_hdf_data)

    in_netatmo_stns_df = pd.read_csv(netatmo_ppt_df_file,
                                     index_col=0, sep=';',
                                     parse_dates=True,
                                     infer_datetime_format=True,
                                     engine='c')

    netatmo_stns_ids = in_netatmo_stns_df.columns

    in_df_distance_netatmo_dwd = pd.read_csv(distance_matrix_df_file,
                                             sep=';', index_col=0)

    for stn_id in netatmo_stns_ids:

        print('First Netatmo Stn Id is', stn_id)

        try:
            idf1 = in_netatmo_stns_df.loc[:, stn_id]
            idf1.dropna(axis=0, inplace=True)
            idf1 = idf1[idf1 < max_ppt_thr]

            distances_to_stn1 = in_df_distance_netatmo_dwd.loc[stn_id, :]
            sorted_distances = distances_to_stn1.sort_values(
                ascending=True)

            min_dist = sorted_distances.values[0]
            if min_dist <= 50000:

                stn_2_id = sorted_distances.index[0]

                idf2 = HDF52.get_pandas_dataframe(ids=[stn_2_id])
                idf2 = idf2[idf2 < max_ppt_thr]

                print('Second DWD Stn Id is', stn_2_id)

                df_combined = pd.DataFrame(columns=[stn_id, stn_2_id])

                df_netatmo_hourly, df_dwd_hourly = resample_intersect_2_dfs(
                    idf1,
                    idf2,
                    '60min')

                if (df_netatmo_hourly.values.shape[0] > 10):
                    if save_df_common:
                        df_combined.loc[:, stn_id] = df_netatmo_hourly
                        df_combined.loc[:, stn_2_id] = df_dwd_hourly

                        df_combined_daily = resampleDf(df_combined, '1440min')

                        df_combined_daily.to_csv(
                            os.path.join(
                                out_save_dir_orig,
                                'combined_daily_df_netatmo_%s_dwd_%s_sep_distance_%.1fm_.csv'
                                % (stn_id, stn_2_id, min_dist)),
                            sep=';', float_format='%0.2f')

                    df_netatmo_daily = resampleDf(df_netatmo_hourly, '1440min')
                    df_dwd_daily = resampleDf(df_dwd_hourly, '1440min')

                    plot_values_2_stns(stn_id,
                                       stn_2_id,
                                       df_netatmo_daily,
                                       df_dwd_daily,
                                       min_dist,
                                       '1440min',
                                       out_save_dir_orig)

                    plot_ratio_2_stns(stn_id,
                                      stn_2_id,
                                      df_netatmo_daily,
                                      df_dwd_daily,
                                      min_dist,
                                      '1440min',
                                      out_save_dir_orig)

                    plot_max_daily_vals_2_stns(stn_id,
                                               stn_2_id,
                                               df_netatmo_daily,
                                               df_dwd_daily,
                                               min_dist,
                                               '1440min',
                                               out_save_dir_orig)

                    plot_max_monthly_vals_2_stns(stn_id,
                                                 stn_2_id,
                                                 df_netatmo_daily,
                                                 df_dwd_daily,
                                                 min_dist,
                                                 '1440min',
                                                 out_save_dir_orig)

                else:
                    print('empty df')
                    continue

        except Exception as msg:
            print(msg)
#         break

if __name__ == '__main__':
    print('**** Started on %s ****\n' % time.asctime())
    START = timeit.default_timer()  # to get the runtime of the program

    construct_netatmo_dwd_daily_dfs(path_to_ppt_netatmo_data,
                                    path_to_ppt_hdf_data,
                                    distance_matrix_df_file)

    STOP = timeit.default_timer()  # Ending time
    print(('\n****Done with everything on %s.\nTotal run time was'
           ' about %0.4f seconds ***' % (time.asctime(), STOP - START)))


a = int(input("masukkan nilai a : "))
b = int(input("masukkan nilai b : "))

def tambah (a,b):
    c = a+b
    return c

def kurang (a,b):
    c = a-b
    return c

def kali (a,b):
    c = a*b
    return c

def bagi (a,b):
    c = a/b
    return c

def modulo (a,b):
    c = a%b
    return c

def main():
    while True:
        print("masukkan pilihan ")
        print("1. tambah ")
        print("2. kurang ")
        print("3. kali ")
        print("4. bagi ")
        print("5. modulo ")

        pilih = int(input("masukkan pilihan "))

        if pilih == 1 :
            print(tambah(a,b))

        elif pilih == 2 :
            print(kurang(a,b))

        elif pilih == 3 :
            print(kali(a,b))

        elif pilih == 4 :
            print(bagi(a,b))

        elif pilih == 5 :
            print(modulo(a,b))

        else:
            print("pilih yang benar")
            break

main()


from modulos import *

class Funcs():
    def clean_screen(self):
        self.code_entry.delete(0, END)
        self.name_entry.delete(0, END)
        self.phone_entry.delete(0, END)
        self.city_entry.delete(0, END)
        self.city_entry.delete(0, END)
        self.addr_entry.delete(0, END)
        self.neig_entry.delete(0, END)
        self.cep_entry.delete(0, END)

    def connect_db(self):
        self.conn = sqlite3.connect("clients.db")
        self.cursor = self.conn.cursor(); print("Conectando ao banco de dados")

    def disconnect_db(self):
        self.conn.close(); print("Banco de dados desconectado com sucesso")

    def mount_tables(self):
        self.connect_db()
        # this print is to show in terminal the beginning when connecting
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS clients (
            cod INTEGER PRIMARY KEY,
            nome_cliente CHAR(40) NOT NULL,
            telefone INTEGER(20),
            cidade CHAR(40)
            );
        """)
        self.conn.commit(); print("Banco de dados criado")
        self.disconnect_db

    def variables(self):
        self.code = self.code_entry.get()
        self.name = self.name_entry.get()
        self.phone = self.phone_entry.get()
        self.city = self.city_entry.get()

    def add_client(self): # to receive the entries
        self.variables()
        if self.name_entry.get() == "":
            msg = "Para cadastrar um novo cliente é necessário \n"
            msg += "que seja digitado pelo menos um nome"
            messagebox.showinfo("Cadastro de clientes - Aviso!!!", msg)
        else:
            self.connect_db() # to call the sql

            self.cursor.execute(""" INSERT INTO clients (nome_cliente, telefone, cidade)
                VALUES (?, ?, ?)""", (self.name, self.phone, self.city))
            self.conn.commit()
            self.disconnect_db()
            self.select_list()
            self.clean_screen()

    def select_list(self):
        self.ListCli.delete(*self.ListCli.get_children())
        self.connect_db()
        list1 = self.cursor.execute(""" SELECT cod, nome_cliente, telefone, cidade FROM clients ORDER BY nome_cliente ASC; """)
        for i in list1:
            self.ListCli.insert("", END, values=i)
        self.disconnect_db()

    def double_click(self, event): # event is to inform that an event will occur
        self.clean_screen()
        self.ListCli.selection()
        for n in self.ListCli.selection():
            col1, col2, col3, col4 = self.ListCli.item(n, "values")
            self.code_entry.insert(END, col1)
            self.name_entry.insert(END, col2)
            self.phone_entry.insert(END, col3)
            self.city_entry.insert(END, col4)

    def del_client(self):
        self.variables()
        self.connect_db()
        self.cursor.execute(""" DELETE FROM clients WHERE cod = ? """, (self.code))
        self.conn.commit()
        self.disconnect_db()
        self.clean_screen()
        self.select_list()

    def change_client(self):
        self.variables()
        self.connect_db()
        self.cursor.execute(""" UPDATE clients SET nome_cliente = ?, telefone = ?, cidade = ? WHERE cod = ? """, (self.name, self.phone, self.city, self.code))
        self.conn.commit()
        self.disconnect_db()
        self.select_list()
        self.clean_screen()

    def search_client(self):
        self.connect_db()
        self.ListCli.delete(*self.ListCli.get_children())
        self.name_entry.insert(END, "%")
        name = self.name_entry.get()
        self.cursor.execute(""" SELECT cod, nome_cliente, telefone, cidade FROM clients WHERE nome_cliente LIKE "%s" ORDER BY nome_cliente ASC """ % name)
        search_name_cli = self.cursor.fetchall()
        for i in search_name_cli:
            self.ListCli.insert("", END, values=i)
        self.clean_screen()
        self.disconnect_db()

    def calendarnew(self):
        self.calendar1 = Calendar(self.aba2, fg="grey75", bg= "blue", font= ("Times", 9, "bold"), locale="pt_br")
        self.calendar1.place(relx=0.55, rely=0.03)
        self.date_start = Button(self.aba2, text="Inserir data", command= self.print_call)
        self.date_start.place(relx=0.37, rely=0.55, relheight=0.17)

    def print_call(self):
        date_begin = self.calendar1.get_date()
        self.calendar1.destroy()
        self.entry_date.delete(0, END)
        self.entry_date.insert(END, date_begin)
        self.date_start.destroy()


from domain.flightEntity import Flight, FlightException
import datetime

class FlightService:
    def __init__(self, flightFileRepo):
        self._flightRepo = flightFileRepo

    @property
    def getAll(self):
        return self._flightRepo.getAll

    def add(self, identifier, departure_city, departure_time, arrival_city, arrival_time):
        """
        Used to call the add function in the flights repository and the write functions which will re-write the flights in the text file
        :param identifier: the id of the flight that will be added
        :param departure_city: the departure city of the flight that will be added
        :param departure_time: the departure time of the flight that will be added
        :param arrival_city: the arrival city of the flight that will be added
        :param arrival_time: the arrival time of the flight that will be added
        :return: nothing
        """
        newFlight = Flight(identifier, departure_city, departure_time, arrival_city, arrival_time)
        if self.check_correct_parameters(newFlight) == True:
            self._flightRepo.add(newFlight)
            self._flightRepo.write()

    def delete(self, identifier):
        if self.check_existing_flight(identifier):
            self._flightRepo.delete(identifier)
            self._flightRepo.write()
        else:
            raise FlightException('The flight does not exist!')

    def check_existing_flight(self, identifier):
        for flight in self.getAll:
            if identifier == flight.identifier:
                return True
        return False

    def check_correct_parameters(self, newFlight):
        """
        Checks if the flight that needs to be added is correct
        :param newFlight: the flight that needs to be added
        :return: True if the flight has correct parameters, raises exception otherwise
        """
        for flight in self.getAll:
            if flight.identifier == newFlight.identifier:
                raise FlightException('Duplicated id!')
            if newFlight.departure_time == flight.departure_time and newFlight.departure_city == flight.departure_city:
                raise FlightException('Airport can handle a single operation!')
            if newFlight.departure_time == flight.arrival_time and newFlight.departure_city == flight.arrival_city:
                raise FlightException('Airport can handle a single operation!')
            if newFlight.arrival_time == flight.departure_time and newFlight. arrival_city == flight.departure_city:
                raise FlightException('Airport can handle a single operation!')
            if newFlight.arrival_time == flight.arrival_time and newFlight.arrival_city == flight.arrival_city:
                raise FlightException('Airport can handle a single operation!')
        return True

    def airports_activity(self):
        sortedListOfAirports = []
        listOfNames = []
        for flight in self.getAll:
            if flight.departure_city not in listOfNames:
                listOfNames.append(flight.departure_city)
            if flight.arrival_city not in listOfNames:
                listOfNames.append(flight.arrival_city)
        for name in listOfNames:
            counter = 0
            for flight in self.getAll:
                if name == flight.departure_city:
                    counter += 1
                if name == flight.arrival_city:
                    counter += 1

            sortedListOfAirports.append(AirportActivity(name, counter))

        sortedListOfAirports.sort(key = lambda airport: airport.activityNumber, reverse = True)
        return sortedListOfAirports

    def no_airborne(self):
        sortedListOfNoFlights = []
        copyOfList = self.getAll
        copyOfList.sort(key = lambda flight: flight.departure_time)

        for index in range(len(copyOfList) - 1):
            if copyOfList[index].arrival_time < copyOfList[index + 1].departure_time:
                t1 = datetime.timedelta(hours = copyOfList[index + 1].departure_time.hour, minutes = copyOfList[index + 1].departure_time.minute)
                t2 = datetime.timedelta(hours = copyOfList[index].arrival_time.hour, minutes=copyOfList[index].arrival_time.minute)
                no_airborne_time = t1 - t2
                sortedListOfNoFlights.append(no_airborne_time)

        sortedListOfNoFlights.sort(reverse = True)
        return sortedListOfNoFlights

    def max_airborne(self):
        listOfMaximumAirborne = []
        maximumTime = datetime.timedelta(hours = 0, minutes = 0)
        copyOfList = self.getAll
        copyOfList.sort(key=lambda flight: flight.departure_time)

        for index in range(len(copyOfList) - 1):
            j = index + 1
            while copyOfList[index].arrival_time > copyOfList[j].departure_time:
                j += 1
            if j != index + 1:
                t1 = datetime.timedelta(hours=copyOfList[index].departure_time.hour, minutes=copyOfList[index].departure_time.minute)
                t2 = datetime.timedelta(hours=copyOfList[j - 1].departure_time.hour, minutes=copyOfList[j - 1].departure_time.minute)
                airborne_time = t2 - t1
                if airborne_time == maximumTime:
                    timeInterval = str(copyOfList[index].departure_time) + ' - ' + str(copyOfList[j - 1].departure_time)
                    listOfMaximumAirborne.append(timeInterval)
                elif airborne_time > maximumTime:
                    maximumTime = airborne_time
                    listOfMaximumAirborne.clear()
                    timeInterval = str(copyOfList[index].departure_time) + ' - ' + str(copyOfList[j - 1].departure_time)
                    listOfMaximumAirborne.append(timeInterval)

        return listOfMaximumAirborne

class AirportActivity:
    def __init__(self, name, activityNumber):
        self._name = name
        self._activityNumber = activityNumber

    @property
    def name(self):
        return self._name

    @property
    def activityNumber(self):
        return self._activityNumber

    def __str__(self):
        return 'Airport name: ' + self._name + ', Number of departures and arrivals: ' + str(self._activityNumber)


from collections.abc import AsyncGenerator
from typing import Optional

from nonebot import logger
from nonebot_plugin_access_control_api.context import context
from nonebot_plugin_access_control_api.event_bus import (
    EventType,
    T_Listener,
    on_event,
    fire_event,
)
from nonebot_plugin_access_control_api.models.permission import Permission
from nonebot_plugin_access_control_api.service.interface.permission import (
    IServicePermission,
)
from nonebot_plugin_access_control_api.service.interface.service import IService

from ...config import conf
from ...repository.permission import IPermissionRepository

class ServicePermissionImpl(IServicePermission):
    repo = context.require(IPermissionRepository)

    def __init__(self, service: IService):
        self.service = service

    def on_set_permission(self, func: Optional[T_Listener] = None):
        return on_event(
            EventType.service_set_permission,
            lambda service: service == self.service,
            func,
        )

    def on_change_permission(self, func: Optional[T_Listener] = None):
        return on_event(
            EventType.service_change_permission,
            lambda service: service == self.service,
            func,
        )

    def on_remove_permission(self, func: Optional[T_Listener] = None):
        return on_event(
            EventType.service_remove_permission,
            lambda service: service == self.service,
            func,
        )

    async def get_permission_by_subject(
        self, *subject: str, trace: bool = True
    ) -> Optional[Permission]:
        for sub in subject:
            if trace:
                for node in self.service.trace():
                    async for p in self.repo.get_permissions(node, sub):
                        return p
            else:
                async for p in self.repo.get_permissions(self.service, sub):
                    return p

        return None

    async def get_permissions(
        self, *, trace: bool = True
    ) -> AsyncGenerator[Permission, None]:
        if trace:
            for node in self.service.trace():
                async for p in self.repo.get_permissions(node, None):
                    yield p
        else:
            async for p in self.repo.get_permissions(self.service, None):
                yield p

    @classmethod
    async def get_all_permissions_by_subject(
        cls, *subject: str
    ) -> AsyncGenerator[Permission, None]:
        overridden_services = set()
        for sub in subject:
            async for x in cls.repo.get_permissions(None, sub):
                if x.service not in overridden_services:
                    yield x
                    overridden_services.add(x.service)

    @classmethod
    async def get_all_permissions(cls) -> AsyncGenerator[Permission, None]:
        async for x in cls.repo.get_permissions(None, None):
            yield x

    async def _fire_service_set_permission(self, subject: str, allow: bool):
        await fire_event(
            EventType.service_set_permission,
            {
                "service": self.service,
                "permission": Permission(self.service, subject, allow),
            },
        )

    async def _fire_service_remove_permission(self, subject: str):
        await fire_event(
            EventType.service_remove_permission,
            {"service": self.service, "subject": subject},
        )

    async def _fire_service_change_permission(self, subject: str, allow: bool):
        await fire_event(
            EventType.service_change_permission,
            {
                "service": self.service,
                "permission": Permission(self.service, subject, allow),
            },
        )

        for node in self.service.travel():
            if node == self.service:
                continue

            cnt = 0
            async for x in self.repo.get_permissions(node, subject):
                cnt += 1

            if cnt == 0:
                await fire_event(
                    EventType.service_change_permission,
                    {
                        "service": node,
                        "permission": Permission(node, subject, allow),
                    },
                )

    async def set_permission(self, subject: str, allow: bool) -> bool:
        ok = await self.repo.set_permission(self.service, subject, allow)

        if ok:
            await self._fire_service_set_permission(subject, allow)
            await self._fire_service_change_permission(subject, allow)

        return ok

    async def remove_permission(self, subject: str) -> bool:
        ok = await self.repo.remove_permission(self.service, subject)
        if ok:
            await self._fire_service_remove_permission(subject)

            p = await self.get_permission_by_subject(subject)
            if p is not None:
                allow = p.allow
            else:
                allow = conf().access_control_default_permission == "allow"
            await self._fire_service_change_permission(subject, allow)

        return ok

    async def check_permission(self, *subject: str) -> bool:
        p = await self.get_permission_by_subject(*subject)
        if p is not None:
            logger.debug(
                f"[permission] {'allowed' if p.allow else 'denied'} "
                f"(service: {p.service}, subject: {p.subject})"
            )
            return p.allow
        else:
            allow = conf().access_control_default_permission == "allow"
            logger.debug(
                f"[permission] {'allowed' if allow else 'denied'} (default) "
                f"(service: {self.service.qualified_name})"
            )
            return allow


import os
import logging

from fastapi import FastAPI
from fastapi.responses import FileResponse

app = FastAPI()

PORT = os.environ.get('PORT', "NNNN")
logger = logging.getLogger("uvicorn.error")
logger.info(f"Server started in port {PORT}")

IMAGE_PATH = "/volume/image.png"

@app.get("/")
async def root():
    if os.path.exists(IMAGE_PATH):
        return FileResponse("/volume/image.png")
    else:
        return {"message": "Image is not downloaded."}


import sys
import whois

def check_whois():
    for line in open(sys.argv[1], "r", encoding="utf8"):
        if line[0]== '#':
            pass
        else:
            try:
                w = whois.whois(line[:-1])
                print("""
                =============== Domain: {} ==============
                NameServer: {} \n
                Name: {} \n
                Organization: {} \n
                Register Date: {} \n
                Expiration Date: {} \n
                =========================================""".format(line[:-1], w.name_servers, w.name, w.org , w.creation_date, w.expiration_date))
            except:
                print("WHOIS NOT FOUND: {}".format(line[:-1]))

check_whois()


from collections import deque
from sys import stdin

INF = 1000000000000000000000000

#경로 path의 유량을 찾는 함수
#경로 path에서 흐를 수 있는 유량은 각 경로를 구성하는 간선이 가지는 잔여 용량들 중 최솟값
def make_flow(s,t,path):

    c = INF #잔여 용량의 최솟값

    #끝점 t부터 시작해서 역으로 돌아가면서
    #경로 path의 흐를 수 있는 최소 용량을 찾는다
    #즉, 경로 path를 구성하는 간선들의 잔여 용량중 최솟값을 찾는다.
    v = t

    while v != s: #경로를 역으로 돌면서 시작점 s에 도달했다면 반복문 탈출

        #v의 이전 정점 path[v]에서 v로 가는 경로의 잔여 용량이 c보다 작다면,
        #c를 해당 값으로 갱신
        if (capacity[path[v]][v] - flow[path[v]][v]) < c:

            c = capacity[path[v]][v] - flow[path[v]][v]

        v = path[v] #v의 이전 정점이 path[v]

    #해당 경로에서 흐르는 유량을 찾았으면, 경로를 역추적
    #해당 경로를 구성하는 간선들에 유량을 더해주자
    v = t

    while v != s:

        #이전 정점 path[v]에서 v로 가는 유량에 c를 더해주고..
        flow[path[v]][v] += c

        #유량 대칭성
        #path[v]에서 v로 들어가는 유량과 v에서 path[v]로 나가는 유량이 같다
        flow[v][path[v]] -= c
        v = path[v]

    return c

#s에서 t로 가는 '유량이 증가하는 경로'를 찾는 bfs
def bfs(s,t):

    queue = deque([s])

    path = [0]*(n+1)

    while queue:

        u = queue.popleft()

        for v in graph[u]:

            #u에서 v로 용량이 남아(residual) 갈 수 있고 아직 방문하지 않았다면...
            if capacity[u][v] - flow[u][v] > 0 and path[v] == 0:

                queue.append(v)
                path[v] = u #v의 이전 정점이 path[v]

                if v == t: #도착점 sink에 도달했다면....

                    return make_flow(s,t,path) #유량 그래프에 현재 경로에서 흐르는 유량을 기록

    return 0 #더 이상 경로를 찾지 못한 경우

def edmonds_karp(s,t):

    path = 0

    #s에서 t로 가는 유량이 존재하는지 찾을 수 없을때까지 BFS로 찾는다
    while 1:

        c = bfs(s,t)

        if c > 0: #s에서 t로 가는 유량이 존재한다 = 경로가 존재한다

            path += 1

        else: #더 이상 흐를 수 있는 유량이 없다 = 경로가 존재하지 않는다

            break

    return path

n,p = map(int,stdin.readline().split())

graph = [[] for _ in range(n+1)] #유량 네트워크

#a > b로 가는 간선이 존재하지 않으면, 용량은 0으로 정의하기 때문에 초기값을 0으로
capacity = [[0]*(n+1) for _ in range(n+1)] #각 간선의 용량

flow = [[0]*(n+1) for _ in range(n+1)] #각 간선에서 흐르는 유량

for _ in range(p):

    a,b = map(int,stdin.readline().split())

    graph[a].append(b)
    graph[b].append(a) #반대 방향으로 흐르는 유량을 생각해야하므로,
    capacity[a][b] = 1 #a > b로 가는 간선이 존재하는 경우 용량은 1로 제한

source = 1 #유량의 시작점
sink = 2 #유량의 도착점

print(edmonds_karp(source,sink))


import matplotlib.pyplot as plt
from randomwalk import RandomWalk

while True:
    rw=RandomWalk(90000)
    rw.fill_walk()
    #绘制所有的点
    plt.scatter(rw.x_values,rw.y_values,c=rw.y_values,cmap=plt.cm.Blues,s=15,edgecolor='none')
    #绘制起点
    plt.scatter(0,0,c='green',edgecolor='none',s=100)
    #绘制终点
    plt.scatter(rw.x_values[-1],rw.y_values[-1],c='red',s=100,edgecolor='none')
    #隐藏坐标轴
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)
    plt.show()

    keep_running=input("Mark another walk?(y/n):")
    if keep_running=="n":
        break


from base.item import Item
from util.blender import createMeshObject, getBmesh, parent_set, assignGroupToVerts, addHookModifier
from util.inset import Corner

class Extruded(Item):

    def __init__(self, context, op):
        super().__init__(context, op)

    def create(self, controls, parent, profile):
        context = self.context

        profile, closed, clockwise = self.getProfileData(profile)

        obj = createMeshObject("extruded")
        obj["t"] = "extruded"

        bm = getBmesh(obj)
        # vertex groups are in the deform layer, create one before any operation with bmesh:
        layer = bm.verts.layers.deform.new()

        numVerts = len(profile)
        numControls = len(controls)
        for i in range(numControls):
            c = controls[i]
            corner = Corner(c.location, pVert = controls[i-1].location, nVert = controls[(i+1)%numControls].location)
            group = c["g"]
            for p in profile:
                v = bm.verts.new(corner.inset(p[0], p[1]))
                assignGroupToVerts(obj, layer, group, v)

        # create faces
        bm.verts.ensure_lookup_table()
        for i in range(numControls):
            offset1 = (i-1)*numVerts
            offset2 = offset1+numVerts
            v1_1 = bm.verts[offset1]
            v2_1 = bm.verts[offset2]
            for p in range(1, numVerts):
                v1_2 = bm.verts[offset1+p]
                v2_2 = bm.verts[offset2+p]
                bm.faces.new((v2_2, v1_2, v1_1, v2_1) if clockwise else (v2_2, v2_1, v1_1, v1_2))
                v1_1 = v1_2
                v2_1 = v2_2
            if closed:
                v1_2 = bm.verts[offset1]
                v2_2 = bm.verts[offset2]
                bm.faces.new((v2_2, v1_2, v1_1, v2_1) if clockwise else (v2_2, v2_1, v1_1, v1_2))

        bm.to_mesh(obj.data)
        bm.free()

        # without scene.update() hook modifiers will not work correctly
        context.scene.update()
        # perform parenting
        parent_set(parent, obj)
        # one more update
        context.scene.update()

        # add hook modifiers
        for c in controls:
            group = c["g"]
            addHookModifier(obj, group, c, group)

    def getProfileData(self, profile):
        coords = []

        bm = getBmesh(profile)
        bm.verts.ensure_lookup_table()

        # is profile a closed loop?
        closed = True if len(bm.verts)==len(bm.edges) else False
        start = bm.verts[0]
        # keep the edge visited in the previous pass of the cycle in the following variable
        e = start.link_edges[0]
        if not closed:
            # find an either open end of the profile
            while len(start.link_edges)!=1:
                e = start.link_edges[0] if start.link_edges[1] == e else start.link_edges[1]
                start = e.verts[0] if e.verts[1]==start else e.verts[1]

        vert = start
        # keep the edge visited in the previous pass of the cycle in the following variable
        e = vert.link_edges[0]
        while True:
            p = vert.co
            coords.append((p.x, p.z))
            if not closed and len(vert.link_edges) == 1 and vert != start:
                break
            vert = e.verts[0] if e.verts[1]==vert else e.verts[1]
            if closed and vert == start:
                break
            e = vert.link_edges[-1] if vert.link_edges[0] == e else vert.link_edges[0]

        bm.free()

        # Now determine if the coords are in the clockwise or counterclockwise order.
        # See http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order
        # The method is based on the shoelace formula
        _sum = 0.
        # store the coordinates of the previous point in the following variable
        _c = None
        for c in coords:
            if not _c:
                _c = coords[-1]
            _sum += (c[0]-_c[0])*(c[1]+_c[1])
            _c = c
        clockwise = True if _sum>0 else False

        return coords, closed, clockwise


#!/usr/bin/env python
# Convert TelcoData file to easier to parse CSV

import csv
import sqlite3
import os

input_file = 'sms-email-ocn.csv'
output_file = 'database.sqlite'

os.remove(output_file)

# open datafile and create database
c = csv.reader(open(input_file, 'r'), delimiter=',', quotechar='"')
db = sqlite3.connect(output_file)
cur = db.cursor()
cur.execute("""
CREATE TABLE numbers (
npanxxy int PRIMARY KEY,
company text,
type text,
email text,
ocn text
)
""")

# insert data
for row in c:
    cur.execute(
        'INSERT INTO numbers VALUES("{}", "{}", "{}", "{}", "{}")'.format(
            row[0]+row[1]+row[2], row[3], row[4], row[5], row[6]
        )
    )

db.commit()
db.close()


users = [ # создаю список с пользователями
	{'name': "Дима", 'numbers': [19, 8, 5, 26, 32]}, # создаю словарь с именем и цифрами
	{'name': 'Вова', 'numbers': [99, 98, 97, 0, 0]},
	{'name': 'Витя', 'numbers': [99, 21, 44, 0, 0]},
	{'name': 'Антон', 'numbers': [55, 99, 89, 0, 0]},
	{'name': 'Даня', 'numbers': [92, 82, 99, 0, 0]},
]

past = [] # создаю список с прошедшими цифрами

for i in users: # циклом прбегаюсь по всем пользователям
	for b in i['numbers']: # циклом пробегаюсь по списку с цифрами
		if b not in past: # если числа еще нет в списке с прошедшими числами
			print(f"{i['name']}: {b}") # выводим имя и число
			past.append(b) # добавляем его в список с прошедшими числами
			break # перываем цикл пробежки по числам, но не прерываем этим самым цикл пробежки по пользователям


"""
LeetCode 240
"""
def search_matrix(matrix, target):
    def binary_search(sequence, item):
        start = 0
        end = len(sequence)-1
        while start <= end:
            mid = (start + end)//2
            if sequence[mid] == item:
                return True
            else:
                if item < sequence[mid]:
                    end = mid - 1
                else:
                    start = mid + 1
        return False
    if not matrix:
        return False
    if matrix == [[]] or matrix == []:
        return False
    else:
        num_rows = len(matrix)
        num_cols = len(matrix[0])
        for row in matrix:
            if row[0] <= target:
                if binary_search(row, target):
                    return True
        for c in range(num_cols):
            col = [x[c] for x in matrix]
            if col[0] <= target:
                if binary_search(col, target):
                    return True
    return False

def test_search_matrix():
    assert search_matrix([[5],[6]],6) is True
    assert search_matrix([[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], 20) is False
    assert search_matrix([[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], 5) is True