import sqlalchemy
from sqlalchemy.orm import sessionmaker, declarative_base, relationship
import config
import os
from config import DSN_2
import Models_2
from Models_2 import create_table, Publisher, Book, Shop, Stock, Sale
import json

DSN = config.DSN_2
engine = sqlalchemy.create_engine(DSN)
create_table(engine)
Session = sessionmaker(bind=engine)
session = Session()

log_file_name = 'contributor.json'
base_path = os.getcwd()
full_path = os.path.join(base_path, log_file_name)

with open(full_path, 'r', encoding="utf-8") as file:
    datafile = json.load(file)
    for read in datafile:
        print(read)
        model = {
            'publisher': Publisher,
            'shop': Shop,
            'book': Book,
            'stock': Stock,
            'sale': Sale,
            }[read.get('model')]
        session.add(model(id=read.get('pk'), **read.get('fields')))

for d in session.query(Publisher).all():
    print(d)
pul_id_inp = input('Введите id издателя : ')

subq = session.query(Publisher).filter(Publisher.id == pul_id_inp).subquery()
for publ_shop in session.query(Shop).join(Stock, Shop.id == Stock.id_shop).join(Book, Stock.id_book == Book.id).join(subq, Book.id_publisher == subq.c.id).all():
    print(f'Издатель {pul_id_inp} продаётся в ', publ_shop)

session.commit()

session.close()


import logging
import uuid
import os
import azure.functions as func
from azure.cosmos import exceptions, CosmosClient, PartitionKey

def new_item(name, dish, veg, vegen):
	sample_item = {
        'id': str(uuid.uuid4()),
        'name': name,
        'dish': dish,
        "vegetarian": veg,
	  	"vegen": vegen
	}
	return sample_item

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')
    con = 0
    try:
        req_body = req.get_json()
        name = req_body['name']
        dish = req_body['dish']
        veg = req_body['vegetarian']
        vegen = req_body['vegan']
    except:
        pass
    else:
        endpoint = "https://localhost:8081"
        key = os.environ['key']
        client = CosmosClient(endpoint, key)
        database_name = 'AzureDatabase'
        database = client.create_database_if_not_exists(id=database_name)
        container_name = 'DishesContainer'
        container = database.create_container_if_not_exists(
            id=container_name,
            partition_key=PartitionKey(path="/name"),
            offer_throughput=400
        )
        dish = new_item(name, dish, veg, vegen)
        items = [dish]
        for item in items:
            container.create_item(body=item)
        con = 1

    if (con == 1):
        return func.HttpResponse(f"Dish feeded")
    else:
        return func.HttpResponse(
             "Please pass a valid query in the request body",
             status_code=400
        )


from comm import timed
from collections import defaultdict

def parse(data):
    final = []
    for row in data:
        i, result = row.split(","), []
        x = range(int(i[1]),int(i[2])+1)
        y = range(int(i[3]),int(i[4])+1)
        z = range(int(i[5]),int(i[6])+1)
        result = [1 if i[0] == "on" else 0, x,y,z]
        final.append(result)
    return final

@timed
def day22A(data, init = 1):
    # max of 50, min of -50
    cubes = defaultdict(int)
    for row in data:
        v = row[0]
        if init:
            skip = [1, 1, 1]
            for i in range(-50,51):
                if i in row[1]: skip[0] = 0
                if i in row[2]: skip[1] = 0
                if i in row[3]: skip[2] = 0
                if sum(skip) == 0:
                    break
            if sum(skip): continue
        for x in row[1]:
            for y in row[2]:
                for z in row[3]:
                    a = ",".join([str(i) for i in (x,y,z)])
                    cubes[a] = v

    return sum(cubes.values())

@timed
def day22B(data):

    return

if __name__ == "__main__":
    data = parse(open("Day 22.txt","r").read().replace(" x=",",").replace("y=","").replace("z=","").replace("..",",").split("\n"))
    print(f"Day 11 A: {day22A(data)}") # 623748
    # print(f"Day 11 B: {day22A(data, 0)}") # Part 2 doesn't work.  Runs out of RAM.


import asyncio
import random
import time
import disnake
import disnake.ext.commands
import database
db = database.Database()

def __init__():
    return

class Snail():

    def __init__(self, name: str):
        self.name = name
        self.progress = 0
        self.happiness = 0
        self.interacted = []
        self.friends = []

    def make_progress(self):
        self.progress += random.randint(0, 3 + self.happiness)

    def cheer(self, user):
        if user in self.interacted:
            return False

        if user in self.friends:
            self.happiness += 1
        else:
            self.happiness -= 1

        if self.happiness < -2:
            self.happiness = -2
        elif self.happiness > 5:
            self.happiness = 5

        self.interacted.append(user)
        return True

async def play_game(channel: disnake.TextChannel, bot: disnake.ext.commands.Bot, optional: str | None = None):
    # Initialize Variables for Race
    uid = f"snail-{int(time.time() * 1000)}"
    snails = []
    recent_cheers = []
    racing = False
    # Create Snails

    # Snail Name Generation
    with open('resources/names.txt', 'r') as f:
        names = f.read().splitlines()
    with open('resources/adjectives.txt', 'r') as f:
        adjectives = f.read().splitlines()

    for s in range(4):
        name = random.choice(names)
        alliteration_adjective = [i for i in adjectives if i.startswith(name[0].lower())]
        adjective = random.choice(alliteration_adjective)
        snails.append(Snail(name=f"{adjective} {name}".title()))
    del names, adjectives, alliteration_adjective

    embed = disnake.Embed(title="Snail Race", description="Cheer your snail onto victory, or slow down enemy snails!\nPick your Snail now! The race will begin in 1 minute.", color=0x0000ff)
    message = False
    # Snail Buttons
    components = []
    for s in snails:
        components.append(disnake.ui.Button(label=s.name, custom_id=uid + f"-{s.name}"))

    # Snail Button Listener
    @bot.listen("on_button_click")
    async def snail_press(inter):
        nonlocal racing
        if not inter.component.custom_id.startswith(uid):
            return

        selected_snail = inter.component.custom_id.split("-")[2]
        if not racing:
            for s in snails:

                if inter.author in s.friends:
                    s.friends.remove(inter.author)

                if s.name == selected_snail:
                    s.friends.append(inter.author)
                    await inter.send(f"{s.name} has been set as your active snail!", ephemeral=True)
        else:
            if inter.author in recent_cheers:
                await inter.send("You have already cheered a snail in the last 30 seconds! Please wait and try again", ephemeral=True)
                return
            recent_cheers.append(inter.author)
            for s in snails:
                if s.name == selected_snail:
                    s.cheer(inter.author)
                    if inter.author in s.friends:
                        action = "cheer on"
                        speed = "boost!"
                    else:
                        action = "jeer at"
                        speed = "penalty!"
                    await inter.send(f"You {action} {s.name}, giving them a small speed {speed}", ephemeral=True)
            await asyncio.sleep(30)
            recent_cheers.remove(inter.author)

    # Announce Snail Race
    message = await channel.send(embed=embed, components=components)
    timer = 60
    while timer > 0:
        timer -= 1
        await asyncio.sleep(1)
    racing = True
    embed.description = "The race is now underway! Pick your snail to give them a boost, or choose another snail to slow them down!"
    # Start Race
    while racing:
        embed.clear_fields()
        for s in snails:
            s.make_progress()

            progress_str = ""
            for i in range(81):
                if i == int(s.progress/2):
                    progress_str += "🐌"
                else:
                    progress_str += "-"
                if int(s.progress/2) >= 80 and i >= int(s.progress/2):
                    progress_str += "🎆"
                    racing = False
            embed.add_field(name=s.name, value=progress_str, inline=False)
        if message:
            await message.edit(embed=embed)
        else:
            message = await channel.send(embed=embed, components=components)
        await asyncio.sleep(1)

    # Announce Winner
    bot.remove_listener(snail_press)
    winner = max(snails, key=lambda s: s.progress)

    tickets = 120 - (len(winner.friends)-1 * 10)

    total_players = 0
    for s in snails:
        total_players += len(s.friends)
    if total_players > 10:
        total_players = 10
    tickets = tickets * total_players

    if tickets < 500:
        tickets = 500

    prizes_string = ""

    for u in winner.friends:
        db.award_tickets(tickets, u, "Snail Race")
        if random.randint(1, 100) > 75:
            prizes_string += f"\n{u.name} has won a **GOLDEN SNAIL**!"
            db.award_prize(u, "Snail Race", 48)

    embed.description = f"The winner is {winner.name}! All supporters of {winner.name} have been rewarded with {tickets} Tickets!{prizes_string}"
    await message.edit(embed=embed, components=[])


import pytest

from psyclone.psyir.nodes import Routine, Container, FileContainer
from psyclone.psyir.symbols import ArrayType, Symbol
from psyclone.psyir.transformations import (HoistLocalArraysTrans,
                                            TransformationError)
from psyclone.tests.utilities import Compile
from psyclone.transformations import ACCRoutineTrans

# init

def test_init():
    '''Test a hoist transformation can be successfully created.'''
    hoist_trans = HoistLocalArraysTrans()
    assert isinstance(hoist_trans, HoistLocalArraysTrans)

# apply

def test_apply_program(fortran_reader, fortran_writer, tmpdir):
    ''' Check that the apply() method does nothing if the supplied routine
    is a program. '''
    code = (
        "program test\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end program test\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    output = fortran_writer(psyir)
    assert ("  real, dimension(10) :: a\n\n"
            "  do i = 1, 10, 1\n" in output)
    assert Compile(tmpdir).string_compiles(output)

def test_apply_1d_known(fortran_reader, fortran_writer, tmpdir):
    ''' Test the apply method correctly handles an automatic array of rank 1
    with known extent. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    orig_sym = routine.symbol_table.lookup("a")
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    # The array is no longer in the symbol table of the routine
    assert "a" not in routine.symbol_table._symbols
    # The array is now in the symbol table of the container.
    sym = routine.ancestor(Container).symbol_table.lookup("a")
    # It must be the same symbol so that any existing references aren't
    # left dangling.
    assert sym is orig_sym
    assert isinstance(sym.datatype, ArrayType)
    assert len(sym.shape) == 1
    assert sym.shape[0] == ArrayType.Extent.DEFERRED
    code = fortran_writer(psyir).lower()
    assert "real, allocatable, dimension(:), private :: a\n" in code
    assert ("    if (.not.allocated(a)) then\n"
            "      allocate(a(1:10))\n"
            "    end if\n"
            "    do i = 1, 10, 1\n" in code)
    assert Compile(tmpdir).string_compiles(code)

def test_apply_multi_dim_imported_limits(fortran_reader, fortran_writer):
    ''' Test that the transformation correctly handles an array with rank > 1
    and extents specified by imported variables. '''
    code = (
        "module my_mod\n"
        "  use some_mod\n"
        "contains\n"
        "subroutine test\n"
        "  real :: a(jpi,jpj)\n"
        "  a(:,:) = 1.0\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    code = fortran_writer(psyir).lower()
    # We cannot test the compilation of the generated code because of
    # the 'use some_mod'.
    assert "real, allocatable, dimension(:,:), private :: a\n" in code
    assert ("    if (.not.allocated(a) .or. ubound(a, dim=1) /= jpi .or. "
            "ubound(a, dim=2) /= jpj) then\n"
            "      if (allocated(a)) then\n"
            "        deallocate(a)\n"
            "      end if\n"
            "      allocate(a(1:jpi,1:jpj))\n"
            "    end if\n"
            "    a(:,:) = 1.0\n" in code)

def test_apply_arg_limits(fortran_reader, fortran_writer, tmpdir):
    ''' Test that the transformation correctly handles an array with extents
    specified via subroutine arguments. Also checks when the lower bound
    is not unity. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test(nx,ny)\n"
        "  integer, intent(in) :: nx, ny\n"
        "  real :: a(2:nx,3:ny)\n"
        "  a(:,:) = 1.0\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    code = fortran_writer(psyir).lower()
    assert "real, allocatable, dimension(:,:), private :: a\n" in code
    assert ("    if (.not.allocated(a) .or. ubound(a, dim=1) /= nx .or. "
            "ubound(a, dim=2) /= ny) then\n"
            "      if (allocated(a)) then\n"
            "        deallocate(a)\n"
            "      end if\n"
            "      allocate(a(2:nx,3:ny))\n"
            "    end if\n" in code)
    assert Compile(tmpdir).string_compiles(code)

def test_apply_runtime_checks(fortran_reader, fortran_writer, tmpdir):
    ''' Test that the transformation correctly adds runtime checks for each
    boundary that is not a literal. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test(nx,ny)\n"
        "  integer, intent(in) :: nx, ny\n"
        "  real :: a(nx,ny)\n"
        "  real :: b(nx:ny,nx:ny)\n"
        "  real :: c(3:4,5:6)\n"
        "  a(:,:) = 1.0\n"
        "  b(:,:) = 1.0\n"
        "  c(:,:) = 1.0\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    code = fortran_writer(psyir).lower()
    assert "real, allocatable, dimension(:,:), private :: a\n" in code
    assert ("    if (.not.allocated(a) .or. ubound(a, dim=1) /= nx .or. "
            "ubound(a, dim=2) /= ny) then\n"
            "      if (allocated(a)) then\n"
            "        deallocate(a)\n"
            "      end if\n"
            "      allocate(a(1:nx,1:ny))\n"
            "    end if\n" in code)
    assert ("    if (.not.allocated(b) .or. lbound(b, dim=1) /= nx .or. "
            "ubound(b, dim=1) /= ny .or. lbound(b, dim=2) /= nx .or. "
            "ubound(b, dim=2) /= ny) then\n"
            "      if (allocated(b)) then\n"
            "        deallocate(b)\n"
            "      end if\n"
            "      allocate(b(nx:ny,nx:ny))\n"
            "    end if\n" in code)
    # Unneeded inner condition is not inserted
    assert ("    if (.not.allocated(c)) then\n"
            "      allocate(c(3:4,5:6))\n"
            "    end if\n" in code)
    assert Compile(tmpdir).string_compiles(code)

def test_apply_multi_arrays(fortran_reader, fortran_writer):
    ''' Test that the transformation handles the case where we have multiple
    automatic arrays. '''
    code = (
        "module my_mod\n"
        "use some_mod, only: jpi, jpj\n"
        "contains\n"
        "subroutine test(nx,ny)\n"
        "  integer, intent(in) :: nx, ny\n"
        "  real :: a(nx,ny)\n"
        "  integer :: mask(jpi,jpj)\n"
        "  a(:,:) = 1.0\n"
        "  mask(:,:) = 1\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    code = fortran_writer(psyir).lower()
    assert "real, allocatable, dimension(:,:), private :: a" in code
    assert "integer, allocatable, dimension(:,:), private :: mask" in code
    assert (
        "    if (.not.allocated(mask) .or. ubound(mask, dim=1) /= jpi .or. "
        "ubound(mask, dim=2) /= jpj) then\n"
        "      if (allocated(mask)) then\n"
        "        deallocate(mask)\n"
        "      end if\n"
        "      allocate(mask(1:jpi,1:jpj))\n"
        "    end if\n"
        "    if (.not.allocated(a) .or. ubound(a, dim=1) /= nx .or. "
        "ubound(a, dim=2) /= ny) then\n"
        "      if (allocated(a)) then\n"
        "        deallocate(a)\n"
        "      end if\n"
        "      allocate(a(1:nx,1:ny))\n"
        "    end if\n"
        "    a(:,:) = 1.0\n" in code)

def test_apply_name_clash(fortran_reader, fortran_writer, tmpdir):
    ''' Check that the transformation handles the case where the name of the
    symbol to be promoted already exists in the container symbol table and the
    first choice of new name clashes with a symbol in the subroutine. '''
    code = (
        "module my_mod\n"
        "  real, allocatable, dimension(:,:), private :: a\n"
        "contains\n"
        "subroutine test(nx,ny)\n"
        "  integer, intent(in) :: nx, ny\n"
        "  real :: a(nx,ny)\n"
        "  real :: a_1 = 1.0\n"
        "  a(:,:) = a_1\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    code = fortran_writer(psyir).lower()
    assert ("  real, allocatable, dimension(:,:), private :: a\n"
            "  real, allocatable, dimension(:,:), private :: a_2\n" in code)
    assert ("    if (.not.allocated(a_2) .or. ubound(a_2, dim=1) /= nx .or. "
            "ubound(a_2, dim=2) /= ny) then\n"
            "      if (allocated(a_2)) then\n"
            "        deallocate(a_2)\n"
            "      end if\n"
            "      allocate(a_2(1:nx,1:ny))\n"
            "    end if\n"
            "    a_2(:,:) = a_1\n" in code)
    assert Compile(tmpdir).string_compiles(code)

def test_apply_validate():
    '''Test the apply method calls the validate method.'''
    hoist_trans = HoistLocalArraysTrans()
    with pytest.raises(TransformationError) as info:
        hoist_trans.apply(None)
    assert ("The target of the HoistLocalArraysTrans transformation should be "
            "a Routine but found 'NoneType'." in str(info.value))

def test_apply_no_arrays(fortran_reader, fortran_writer, tmpdir):
    ''' Check that applying the transformation to a routine that does not
    contain any local arrays does nothing. '''
    code = (
        "module my_mod\n"
        "real :: a(10,10)\n"
        "contains\n"
        "subroutine test(nx,ny,b)\n"
        "  integer, intent(in) :: nx, ny\n"
        "  real, dimension(nx,ny), intent(in) :: b\n"
        "  a(:,:) = b(:,:)\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    output = fortran_writer(psyir).lower()
    assert ("    real, dimension(nx,ny), intent(in) :: b\n\n"
            "    a(:,:) = b(:,:)\n\n"
            "  end subroutine test\n" in output)
    assert Compile(tmpdir).string_compiles(output)

def test_apply_tagged_symbol(fortran_reader):
    ''' Check that any tag associated with the Symbol representing a local
    array is preserved during its promotion. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    orig_sym = routine.symbol_table.lookup("a")
    # Add a tag for this symbol.
    routine.symbol_table._tags["important_tag"] = orig_sym
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    cont = psyir.children[0]
    assert isinstance(cont, Container)
    sym = cont.symbol_table.lookup_with_tag("important_tag")
    assert sym is orig_sym
    # Check that the tag has also been removed from the routine symbol table.
    assert "important_tag" not in routine.symbol_table.tags_dict

def test_apply_array_valued_function(fortran_reader, fortran_writer, tmpdir):
    ''' Check that the transformation does not attempt to hoist an array
    if it is the return value of a routine. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "function test() result(a)\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end function test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.apply(routine)
    output = fortran_writer(psyir)
    assert ("    real, dimension(10) :: a\n\n"
            "    do i = 1, 10, 1\n" in output)
    assert Compile(tmpdir).string_compiles(output)

# _get_local_arrays

def test_get_local_arrays(fortran_reader):
    ''' Check that the _get_local_arrays() helper method works correctly for
    a routine containing arrays that are passed by argument, imported from a
    container or used as a return value. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "function test(c) result(a)\n"
        "  use some_mod, only: b\n"
        "  real, dimension(10,10), intent(in) :: c\n"
        "  real, dimension(10) :: wrk\n"
        "  real, dimension(:), allocatable :: wrk2\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = b(i) + c(i,5)\n"
        "  end do\n"
        "end function test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    symbols = hoist_trans._get_local_arrays(routine)
    assert len(symbols) == 1
    assert symbols[0] is routine.symbol_table.lookup("wrk")

def test_get_local_arrays_codeblock(fortran_reader):
    ''' Check that the _get_local_arrays() method excludes any of the
    local arrays if they are accessed within a CodeBlock (since they
    may get renamed as part of the hoisting process). We check for the
    situation where we have more than one CodeBlock and the same symbol
    is referenced in both. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real :: a(10), b(10)\n"
        "  a(:) = 1.0\n"
        "  write(*,*) a(10)\n"
        "  b(:) = 1.0\n"
        "  write(*,*) b(1),a(1)\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    assert hoist_trans._get_local_arrays(routine) == []
    # TODO #11. Once logging is implemented check that the exclusion of 'a'
    # and 'b' has been logged.

def test_get_local_arrays_not_parameters(fortran_reader):
    '''Check that the _get_local_arrays() helper method ignores any local
    arrays that are parameters.

    '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real, dimension(2), parameter :: a = (/1.0, 2.0/)\n"
        "  real :: b(2)\n"
        "  do i=1,2\n"
        "    b(i) = 2.0*a(i)\n"
        "  end do\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    hoist_trans = HoistLocalArraysTrans()
    symbols = hoist_trans._get_local_arrays(routine)
    assert len(symbols) == 1
    assert symbols[0].name == "b"

# validate

def test_validate_node():
    ''' Test the expected exception is raised if an invalid node is
    supplied to the transformation. '''
    hoist_trans = HoistLocalArraysTrans()
    with pytest.raises(TransformationError) as info:
        hoist_trans.validate(None)
    assert ("The target of the HoistLocalArraysTrans transformation should be "
            "a Routine but found 'NoneType'." in str(info.value))

def test_validate_program():
    ''' Test that the validate method accepts a Routine that is a Program
    (since there's nothing to do). '''
    routine = Routine("my_prog", is_program=True)
    hoist_trans = HoistLocalArraysTrans()
    hoist_trans.validate(routine)

def test_validate_ancestor_container():
    ''' Test the expected exception is raised if the supplied assignment is
    not within a container. '''
    hoist_trans = HoistLocalArraysTrans()
    routine = Routine("my_prog")
    with pytest.raises(TransformationError) as info:
        hoist_trans.validate(routine)
    assert ("The supplied routine 'my_prog' should be within a Container but "
            "none was found." in str(info.value))
    container = FileContainer("my_file")
    container.addchild(routine)
    with pytest.raises(TransformationError) as info:
        hoist_trans.validate(routine)
    assert ("The supplied routine 'my_prog' should be within a Container but "
            "the enclosing container is a FileContainer (named 'my_file')."
            in str(info.value))

def test_validate_acc_routine_directive(fortran_reader):
    '''
    Test that, by default, the transformation rejects a routine if it contains
    an ACCRoutineDirective and that this can be switched off.

    '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    routine = psyir.walk(Routine)[0]
    acc_trans = ACCRoutineTrans()
    acc_trans.apply(routine)
    hoist_trans = HoistLocalArraysTrans()
    with pytest.raises(TransformationError) as err:
        hoist_trans.validate(routine)
    assert ("supplied routine 'test' contains an ACC Routine directive "
            "which implies" in str(err.value))
    # This check can be disabled.
    hoist_trans.validate(routine, options={"allow_accroutine": True})

def test_validate_tagged_symbol_clash(fortran_reader):
    ''' Check that we get the expected error message if the tag associated
    with the Symbol representing a local array clashes with a tag already
    present in the outer scope. '''
    code = (
        "module my_mod\n"
        "contains\n"
        "subroutine test\n"
        "  integer :: i\n"
        "  real :: a(10)\n"
        "  do i=1,10\n"
        "    a(i) = 1.0\n"
        "  end do\n"
        "end subroutine test\n"
        "end module my_mod\n")
    psyir = fortran_reader.psyir_from_source(code)
    cont = psyir.children[0]
    routine = psyir.walk(Routine)[0]
    orig_sym = routine.symbol_table.lookup("a")
    # Add a Symbol to the outer table with a clashing tag.
    cont.symbol_table.add(Symbol("b"), tag="important_tag")
    orig_sym = routine.symbol_table.lookup("a")
    # Add a tag for this symbol.
    routine.symbol_table._tags["important_tag"] = orig_sym
    hoist_trans = HoistLocalArraysTrans()
    with pytest.raises(TransformationError) as err:
        hoist_trans.validate(routine)
    assert ("The supplied routine 'test' contains a local array 'a' with tag "
            "'important_tag' but this tag is also present in the symbol table "
            "of the parent Container (associated with variable 'b')" in
            str(err.value))

# str

def test_str_method():
    ''' Test for the __str__ method of HoistLocalArraysTrans. '''
    hoist_trans = HoistLocalArraysTrans()
    assert (str(hoist_trans) == "Hoist all local, automatic arrays to "
            "container scope.")


import cv2
from skimage.feature import hog
import pickle
model = pickle.load(open("D:/Project Data_org/model_hog.sav", 'rb'))

path = "D:/Project Data_org/test.jpeg"

image_t = cv2.imread(path,0)
img_res_t = cv2.resize(image_t, (128,128))

fd, hog_image = hog(img_res_t, orientations=9, pixels_per_cell=(8, 8),
                cells_per_block=(2, 2), visualize=True, multichannel=False)

fd.shape
 # Converting into numpy array
fd = fd.reshape(1,-1)
fd.shape
y_pred = model.predict(fd)

print(y_pred[0])


#! /usr/bin/python3

import json
import sys
import os
import argparse
import re
import shlex
from functools import partial

import clang
import clang.cindex

def __get_full_file_name(name):
	return os.path.abspath(os.path.realpath(os.path.expanduser(name)))

class CompileCommands():
	'''
		Wrapper around CompileCommands that lazy evaluates and caches
		the results for use later.
	'''

	def __init__(self, compile_commands_path):
		self.path = compile_commands_path
		self.dir = os.path.dirname(self.path)
		self._commands = None
		self._command_path_to_index = None

	def get_command(self, file_to_compile):
		if not self._commands:
			# Open the specified file. This should contain an array of JSON
			# objects representing compile commands.
			with open(self.path, 'r') as compile_commands_file:
				self._commands = json.loads(compile_commands_file.read())

			# Now populate our lookup table
			self._command_path_to_index = {
				self._commands[i]['file'] : i
				for i in range(len(self._commands))
			}

		return self._commands[self._command_path_to_index[file_to_compile]]

	def get_command_directives(self, command):
		if isinstance(command, dict):
			command = command['command']

		# Ignore the first and last items, as those should just be the
		# compiler and file name respectively.
		directives = shlex.split(command)[1:-1]

		# Now go through and expand any @ directives.
		# These indicate that we should substitute a files text
		# (specified by the directive) with the directive itself.
		replacements = []
		for i in range(len(directives)):
			if directives[i][0] == '@':
				file_name = directives[i][1:]
				file_name = os.path.join(self.dir, file_name)
				with open(file_name, 'r') as expanded_contents:
					replacement = shlex.split(expanded_contents.read())
					replacements += [(i, replacement)]

		# Swap the old directives with the expanded directives
		for i, repl in replacements:
			directives[i:i+1] = repl

		return directives

class WrappedCursor():
	'''
		Wraps a clang cursor and adds a Parent.
		This can typically used when iterating or visiting cursors,
		but parent may be invalid in cases when it's unknown (e.g.
		going to a definition / declaration).
	'''

	def __init__(self, cursor, parent):

		unwound_cursor = cursor
		while isinstance(unwound_cursor, WrappedCursor):
			unwound_cursor = unwound_cursor._cursor

		self._cursor = unwound_cursor
		self._parent = parent

	@property
	def parent(self):
		return self._parent

	def __getattr__(self, attr):
		if attr == 'parent':
			return self._parent

		return getattr(self._cursor, attr)

	def __hash__(self):
		return hash(self._cursor)

	def __eq__(self, other):
		if isinstance(other, WrappedCursor):
			return self._cursor == other._cursor
		else:
			return self._cursor == other

def load_ue4_translation_unit(file_path, ast_cache_path, compile_commands, parse_options=0):

	translation_unit = None
	if ast_cache_path:
		try:
			translation_unit = clang.cindex.TranslationUnit.from_ast_file(ast_cache_path)
		except clang.cindex.TranslationUnitLoadError:
			print('Failed to load cached AST')

	if translation_unit is None:
		command = compile_commands.get_command(file_path)
		directives = compile_commands.get_command_directives(command)

		index = clang.cindex.Index.create()
		translation_unit = index.parse(file_path, args=directives, options=parse_options)

		if ast_cache_path:
			try:
				translation_unit.save(ast_cache_path)
			except clang.cindex.TranslationUnitSaveError:
				print('Failed to cache AST')

	return translation_unit

def foreach_cursor(action, cursor, depth=0):
	'''
		Recursively iterates over a cursors children, applying
		a specified action.
		This applies the action to the given cursor as well.

		The action should be some callable that takes a WrappedCursor and int depth.
	'''
	action(cursor, depth)
	for child in cursor.get_children():
		foreach_cursor(action, WrappedCursor(child, cursor), depth+1)

def find_cursor(predicate, cursor):
	'''
		Searches the given cursor's direct children, looking for one
		that satisfies the given predicate.
		Only returns the first matching cursor.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A matching cursor if found, None otherwise.
	'''
	for child in cursor.get_children():
		wrapped_child = WrappedCursor(child, cursor)
		if predicate(wrapped_child):
			return wrapped_child

def find_cursor_recursive(predicate, cursor):
	'''
		Searches the given cursor's children recursively, looking for one
		that satisfies the given predicate.
		Only returns the first matching cursor.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A matching cursor if found, None otherwise.
	'''
	for child in cursor.get_children():
		wrapped_child = WrappedCursor(child, cursor)
		if predicate(wrapped_child):
			return wrapped_child

		found_in_child = find_cursor_recursive(predicate, wrapped_child)
		if found_in_child:
			return found_in_child

def find_cursor_many(predicate, cursor):
	'''
		Searches the given cursor's direct children, looking for any
		that satisfies the given predicate.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A list of matching cursors, or empty list if none were found.
	'''
	found = []
	for child in cursor.get_children():
		wrapped_child = WrappedCursor(child, cursor)
		if predicate(wrapped_child):
			found += [wrapped_child]

	return found

def find_cursor_recursive_many(predicate, cursor):
	'''
		Searches the given cursor's children recursively, looking for any
		that satisfy the given predicate.
		Note, this **will not** recurse into children of found matches.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A list of matching cursors, or empty list if none were found.

	'''
	found = []
	for child in cursor.get_children():
		wrapped_child = WrappedCursor(child, cursor)
		if predicate(wrapped_child):
			found += [wrapped_child]

		else:
			found += find_cursor_recursive_many(predicate, wrapped_child)

	return found

def find_cursor_recursive_all(predicate, cursor):
	'''
		Searches the given cursor's children recursively, looking for any
		that satisfy the given predicate.
		Note, this **will** recurse into the children of found matches.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A list of matching cursors, or empty list if none were found.
	'''
	found = []
	for child in cursor.get_children():
		wrapped_child(child, cursor)
		if predicate(wrapped_child):
			found += [wrapped_child]

		found += find_cursor_recursive_all(predicate, wrapped_child)

	return found

def foreach_parent(action, cursor, depth=0):
	'''
		Recursively iterates over a cursor'ss parents, applying
		a specified action.
		This applies the action to the given cursor as well.

		The action should be some callable that takes a WrappedCursor and int depth.
	'''
	if cursor is not None:
		action(cursor, depth)

		if hasattr(cursor, 'parent'):
			foreach_parent(action, cursor.parent, depth+1)

def find_parent(predicate, cursor):
	'''
		Searches the given cursor's parents recursively, looking for any
		that satisfy the given predicate.
		Note, this **will not** recurse into the parents of found matches.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A matching cursor if found, None otherwise.
	'''

	if cursor.parent is not None:
		if predicate(cursor.parent):
			return cursor.parent
		else:
			return find_parent(predicate, cursor.parent)

def find_parent_many(predicate, cursor):
	'''
		Searches the given cursor's parents recursively, looking for any
		that satisfy the given predicate.
		Note, this **will** recurse into the parents of found matches.

		Predicates should be some callable that takes a single argument, a  WrappedCursor.

		@return A list of matching cursors, or empty list if none were found.
	'''

	found = []
	if cursor.parent is not None:
		if predicate(cursor.parent):
			found += [cursor.parent]

		found += find_parent_many(predicate, cursor.parent)

	return found

def freeze_predicates(predicates):
	'''
		Convenience method that freezes a set of predicates.

		Input is expected to be an iterable of lists.
		Each list is treated as a single predicate to be frozen.
		The first element in each list should be a callable.
		All remaining elements in the list are non-keyword arguments
		to be applied to the callable in order.
	'''

	return [partial(predicate[0], *predicate[1:]) for predicate in predicates]

def cursor_matches_all(*predicates):
	'''
		Returns a predicate that is true only if all given
		predicates are true.

		@see freeze_predicates for an explanation of inputs.
		It's expected that each given predicate also accepts
		a cursor as its last non-keyword argument.

		Note, this may end up evaluating all predicates, even if
		some are found to be false.
	'''

	predicates = freeze_predicates(predicates)
	def matches_all(cursor):
		return all((predicate(cursor) for predicate in predicates))

	return matches_all

def cursor_matches_any(*predicates):
	'''
		Returns a predicate that is true if any of the given
		predicates are true.

		@see freeze_predicates for an explanation of inputs.
		It's expected that each given predicate also accepts
		a cursor as its last non-keyword argument.

		Note, this may end up evaluating all predicates, even if
		some are found to be true.
	'''

	predicates = freeze_predicates(predicates)
	def matches_any(cursor):
		return any((predicate(cursor) for predicate in predicates))

	return matches_any

if __name__ == '__main__':

	argument_parser = argparse.ArgumentParser('GetCompileCommands')
	argument_parser.add_argument('file_name', help='Path to file for which commands should be received.')
	argument_parser.add_argument('-c', '--compile_commands', help='Path to compile_commands.json', default='compile_commands.json')
	argument_parser.add_argument('-l', '--llvm_libs', help='Directory that contains LLVM libraries', default='/usr/lib/llvm-7/lib')
	argument_parser.add_argument('-f', '--cache_file', help='Points to a saved AST file. If no file is found, or the file is invalid, a the source will be parsed and saved here for future iterations.', default=None)
	arguments = argument_parser.parse_args()

	compile_commands = CompileCommands(__get_full_file_name(arguments.compile_commands))
	file_path = __get_full_file_name(arguments.file_name)
	llvm_lib_dir = __get_full_file_name(arguments.llvm_libs)
	cached_ast_path = __get_full_file_name(arguments.cache_file) if arguments.cache_file else None

	# Make sure we set the library path before doing anything else.
	clang.cindex.Config.set_library_path(llvm_lib_dir)
	translation_unit = load_ue4_translation_unit(file_path, cached_ast_path, compile_commands)

	'''
		We want to find anywhere in NetworkProfiler.cpp that is serializing
		data to FileWriter.

		We'll take blocks of related serializations, and form those into types.

		This is how that's approached:

		Searching and Aggregation:

			1. Find the FNetworkProfiler class.
			2. Find the ENetworkProfilingPayloadType enum.
			3. Find the declaration of FileWriter.
			4. Find all methods inside FNetworkProfiler.
			5. Find all calls within each method.
			6. Remove any calls that don't reference FileWriter,
				or that seem to be inappropriate (e.g., checks).

		Grouping:

			Iterate over each method.
			Iterate over each call.

			1. Inspect the call's arguments.
			2. If any arguments are references to ENetworkProfilingPayload values,
				then we start a new group.
				This call is the first call in the new group.
			3. If no arguments reference ENetworkProfilingPayload, and there's an existing group, append this call to that group.
			4. If no arguments reference ENetworkProfilingPayload, and there's no existing group, disregard the call.

		Generation:

			Each ENetworkProfilingPayload referenced will dictate a new type.
			Each type will have one member variable per argument for every other call in its group.
			Each member variable will be named corresponding to the variable used in its call.
			Each member variable will be private, with corresponding const getter methods.
			Each type will have a Serialize method that copies the original set of calls (minus the Type serialization).
			Each type will have a constructor, accepting a value for each member variable, and an initializer list initializing all variables.

		The following is actual output from the command.

			USTRUCT()
			struct FNetworkProfilerType_SendBunch : public FNetworkProfilerType_Base
			{
			public:
				GENERATED_BODY();
				NETWORK_PROFILER_BODY(SendBunch);

				FNetworkProfilerType_SendBunch(const uint16 InChannelIndex, const uint16 InNumBits, const uint32 InNameTableIndex)
					: ChannelIndex(InChannelIndex)
					, NumBits(InNumBits)
					, NameTableIndex(InNameTableIndex)
				{
				}

				~FNetworkProfilerType_SendBunch()
				{
				}

				const uint16 GetChannelIndex() const
				{
					return ChannelIndex;
				}

				const uint16 GetNumBits() const
				{
					return NumBits;
				}

				const uint32 GetNameTableIndex() const
				{
					return NameTableIndex;
				}

				void Serialize(FArchive& Ar)
				{
					Ar << ChannelIndex;
					Ar.SerializeIntPacked(NameTableIndex);
					Ar << NumBits;
				}

			private:
				uint16 ChannelIndex;
				uint16 NumBits;
				uint32 NameTableIndex;
			};
			NETWORK_PROFILER_TYPE_TRAITS(SendBunch);

			FNetworkProfilerType_SendBunch SendBunch();
			SendBunch.Serialize(*FileWriter);
			<SourceLocation file '/home/widmo/Projects/UnrealEngine/Engine/Source/Runtime/Engine/Private/NetworkProfiler.cpp', line 416, column 3>

		These serialization bits were found around line 416:

			(*FileWriter) << Type;
			(*FileWriter) << ChannelIndex;
			(*FileWriter).SerializeIntPacked(NameTableIndex);
			(*FileWriter) << NumBits;

		From the generation, we can tell:

			Type was resolved to be NPTYPE_SendBunch.
			ChannelIndex was resolved to be a uint16.
			NameTableIndex was resolved to be uint32.
			NumBits was resolved to be uint16.

			Variables were sorted on size before being declared.
			Serialization snippets were pulled from the source code (order unchanged).
	'''

	# Get our translation unit.
	translation_unit_cursor = WrappedCursor(translation_unit.cursor, None)

	# Define a few repeated convenience methods
	# These will be composed using the utility methods above.
	def cursor_is_of_kind(kind, cursor):
		return cursor.kind == kind

	def cursor_is_of_type(type, cursor):
		return type == cursor.type

	def cursor_is_named(name, cursor):
		return cursor.spelling == name

	def cursor_name_starts_with(name, cursor):
		return cursor.spelling.startswith(name)

	def cursor_references(referenced, cursor):
		return referenced == cursor.referenced

	# Find FNetworkProfiler.
	# We do this by searching all top level children of the Translation Unit
	# for a cursor with kind CLASS_DECL and name 'FNetworkProfiler'
	network_profiler_class = find_cursor(
		cursor_matches_all(
			[cursor_is_of_kind, clang.cindex.CursorKind.CLASS_DECL],
			[cursor_is_named, 'FNetworkProfiler']
		),
		translation_unit_cursor
	)

	# Find ENetworkProfilingPayloadType
	# We do this by searching all top level children of the Translation Unit
	# for a cursor with kind ENUM_DECL and name 'ENetworkProfilingPayloadType'
	network_profiling_payload_enum = find_cursor(
		cursor_matches_all(
			[cursor_is_of_kind, clang.cindex.CursorKind.ENUM_DECL],
			[cursor_is_named, 'ENetworkProfilingPayloadType']
		),
		translation_unit_cursor
	)

	# Find all FNetworkProfiler Method Declarations.
	method_decls = find_cursor_many(
		cursor_matches_all(
			[cursor_is_of_kind, clang.cindex.CursorKind.CXX_METHOD]
		),
		network_profiler_class
	)

	# Get the corresponding Method Definitions.
	method_defs = (
		WrappedCursor(method_decl.get_definition(), translation_unit_cursor)
		for method_decl in method_decls
	)

	# Find the FNetworkProfiler::FileWriter.
	file_writer_decl = find_cursor(
		cursor_matches_all(
			[cursor_is_of_kind, clang.cindex.CursorKind.FIELD_DECL],
			[cursor_is_named, 'FileWriter']
		),
		network_profiler_class
	)

	# Find all calls referencing FNetworkProfiler::FileWriter.
	# We do this by recursively searching all methods of FNetworkProfiler
	# for cursor of type CALL_EXPR, and we make sure the name is either
	# operator<< or starts with Serialize. (TODO: there's probably a better
	# way to filter those...)
	#
	# Once we find such a cursor, we recursively search it for a reference
	# to FileWriter.
	calls_referencing_file_writer = (
		(method_def,
		find_cursor_recursive_many(
			cursor_matches_all(
				[cursor_is_of_kind, clang.cindex.CursorKind.CALL_EXPR],
				[
					cursor_matches_any(
						[cursor_is_named, 'operator<<'],
						[cursor_name_starts_with, 'Serialize']
					)
				],
				[
					find_cursor_recursive,
					cursor_matches_all(
						[cursor_is_of_kind, clang.cindex.CursorKind.MEMBER_REF_EXPR],
						[cursor_references, file_writer_decl]
					)
				]
			),
			method_def
		))
		for method_def in method_defs
	)

	# Cull out any non-matched methods.
	calls_referencing_file_writer = [
		(method_def, calls)
		for method_def, calls in calls_referencing_file_writer
		if len(calls) > 0
	]

	# On to the grouping phase!

	# Finding a reference back to ENetworkProfilingPayloadType is a bit trickier.
	# We need to recurse into the call, find any cursors referencing variables,
	# go to those variable declarations, and recurse into them.

	groups = []
	outstanding_group = None
	for method, calls in calls_referencing_file_writer:

		# Make sure we track any oustanding groups.
		if outstanding_group:
			groups += [outstanding_group]
			outstanding_group = None

		#print(method.spelling)
		for call in calls:

			# Find all the variables this call is using,
			# making sure to cull out things we don't want (like function prototypes).
			variable_refs = [
				variable_ref
				for variable_ref in find_cursor_recursive_many(
					cursor_matches_all(
						[cursor_is_of_kind, clang.cindex.CursorKind.DECL_REF_EXPR],
						[lambda cursor: cursor.type.kind is not clang.cindex.TypeKind.FUNCTIONPROTO]
					),
					call
				)
			]

			#print(call.spelling)

			for variable_ref in variable_refs:

				# See if the variable refers to an ENetworkProfilingPayloadType.
				# We recurse into the cursor that is referenced by the variable.
				# Then, we filter on whether or not its a reference to a type from a declaration.
				# If it is, we then check the referenced type to make sure its correct.
				network_profiling_payload_decl = find_cursor_recursive(
					cursor_matches_all(
						[cursor_is_of_kind, clang.cindex.CursorKind.DECL_REF_EXPR],
						[cursor_is_of_type, network_profiling_payload_enum.type]
					),
					variable_ref.referenced
				)

				if network_profiling_payload_decl is None:

					if outstanding_group:
						# Walk the parents and look for exposed MEMBER_REFs.
						# This will ensure that we're pointing at the
						# correct member variable (if a member variable is
						# being referenced).
						# Technically, we could do this in the query above.

						member_ref = find_parent(
							cursor_matches_all(
								[cursor_is_of_kind, clang.cindex.CursorKind.MEMBER_REF_EXPR],
								[lambda cursor: cursor.type.kind != clang.cindex.TypeKind.UNEXPOSED]
							),
							variable_ref
						)

						variable_ref = member_ref or variable_ref

						outstanding_group += [[method, call, variable_ref]]

				# If we found a payload type, we'll use that to denote the start of a new group.
				# First, we have to clean any outstanding ones.
				else:
					if outstanding_group:
						groups += [outstanding_group]

					outstanding_group = [[method, call, network_profiling_payload_decl]]

	if outstanding_group:
		groups += [outstanding_group]
		outstanding_group = None

	# Now we should have all of our groups set up,
	# so we can start our generation phase!
	# To kick things off, setup some templates.

	struct_template = '''
	USTRUCT()
	struct FNetworkProfilerType_{type} : public FNetworkProfilerType_Base
	{{
	public:
		GENERATED_BODY();
		NETWORK_PROFILER_BODY({type});

		FNetworkProfilerType_{type}({constructor_params}){init_list}
		{{
		}}

		~FNetworkProfilerType_{type}()
		{{
		}}
{get_methods}
		void Serialize(FArchive& Ar)
		{{
{serialize_body}
		}}

	private:
{member_decls}
	}};
	NETWORK_PROFILER_TYPE_TRAITS({type});
'''

	get_method_template = '''
		const {variable_type} Get{variable_name}() const
		{{
			return {variable_name};
		}}
'''

	member_decl_template = '''{variable_type} {variable_name};'''

	constructor_param_template = '''const {variable_type} In{variable_name}'''

	init_list_template = '''{variable_name}(In{variable_name})'''

	construct_template = '''FNetworkProfilerType_{type} {type}{inst_constructor_call};'''

	call_serialize_template = '''{type}.Serialize(*FileWriter);'''

	for group in groups:
		payload_method, payload_call, payload_var = group[0]
		group = group[1:]

		type = payload_var.spelling.replace('NPTYPE_', '')

		constructor_params = ''
		init_list = ''
		get_methods = ''
		serialize_body = ''
		member_decls=''
		inst_constructor_call = ''

		variables = (variable for method, call, variable in group)
		sorted_variables = sorted(variables, key=lambda variable: variable.type.get_size())

		variables_name_and_type = [
			(variable.spelling, variable.type.spelling.replace('const ', ''))
			for variable in sorted_variables
		]

		if len(variables_name_and_type) > 0:
			variable_templates = [
				{
					'constructor_param': constructor_param_template.format(variable_name=variable_name, variable_type=variable_type),
					'init_list': init_list_template.format(variable_name=variable_name, variable_type=variable_type),
					'get_method': get_method_template.format(variable_name=variable_name, variable_type=variable_type),
					'member_decl': member_decl_template.format(variable_name=variable_name, variable_type=variable_type),
				}
				for variable_name, variable_type in variables_name_and_type
			]

			constructor_params = ', '.join((
				variable_template['constructor_param']
				for variable_template in variable_templates
			))

			init_list = '\n\t\t\t, '.join((
				variable_template['init_list']
				for variable_template in variable_templates
			))

			init_list = '\n\t\t\t: ' + init_list

			get_methods = '\t\t'.join((
				variable_template['get_method']
				for variable_template in variable_templates
			))

			get_method = '\t\t' + get_methods

			member_decls = '\n\t\t'.join((
				variable_template['member_decl']
				for variable_template in variable_templates
			))

			member_decls = '\t\t' + member_decls

			# This bit is admittedly hacky.
			# We want to convert our calls into source.
			# We *could* just read the source code we're parsing,
			# grab the location, and then paste that in.
			# However, we may have done some munging.
			# For example, in FNetworkProfiler::FlushOutgoingBunches,
			# FSendBunchInfo / BunchInfo members are used, and instead we'll
			# want to use our own members.
			# Maybe a safer approach would be something like:
			#	1. Check to see if its operator<<.
			#		a. If it is, assume semantic Ar << {variable.spelling}
			#	2. Check to see if the call references a Member Function.
			#		a. If it does, and it's a member of FArchive,
			#			call it via Ar.{call.spelling}({variable.spelling})
			#		b. If it does, but it's not a member of FArchive,
			#			call it via {variable.spelling}.{call.spelling}(Ar)
			#	3. Check to see if it references an unbound function.
			#		a. If it does, figure out argument order, and place the Ar / Variable appropriately.
			#
			# Also, this fails to handle multiple variables that are passed into the same function...

			# Note, we use the group ordering here and not the sorted variable
			# ordering. This means that the generated body should be logically
			# identical to the first.

			def call_to_serialize(call, variable):
				if call.spelling == 'operator<<':
					return f'Ar << {variable.spelling};'

				elif 'IntPacked' in call.spelling:
					return f'Ar.{call.spelling}({variable.spelling});'

				else:
					return f'{variable.spelling}.{call.spelling}(Ar);'

			serialize_body = '\n\t\t\t'.join((
				call_to_serialize(call, variable)
				for method, call, variable in group
			))

			serialize_body = '\t\t\t' + serialize_body

			inst_constructor_call = '({})'.format(
				', '.join(
					variable_name
					for variable_name, variable_type in variables_name_and_type
				)
			)

		format_kwargs = {
			'constructor_params': constructor_params,
			'init_list': init_list,
			'get_methods': get_methods,
			'serialize_body': serialize_body,
			'member_decls': member_decls,
			'type': type,
			'inst_constructor_call': inst_constructor_call,
		}

		struct = struct_template.format(**format_kwargs)
		construct = construct_template.format(**format_kwargs)
		call_serialize = call_serialize_template.format(**format_kwargs)

		print(struct)
		print(construct)
		print(call_serialize)
		print(payload_call.location)


import pytest

def zip1(*iterables):
    sent = object()
    iterators = [iter(it) for it in iterables]
    while iterators:
        res = []
        for it in iterators:
            elem = next(it, sent)
            if elem is sent:
                return
            res.append(elem)
        yield tuple(res)

@pytest.mark.parametrize("a,b",[(['A','B','C'],[1,2,3]),(['x','y','z'],[2,14,6]),(['0','0','0'],[0,0,0])])
def test_zip(a,b):
    for pair in zip(zip1(a, b), zip(a, b)):
        assert pair[0] == pair[1]

def map1(func, iterable):
    for i in iterable:
        yield func(i)

@pytest.mark.parametrize("func,it",[(int,['1','2','3','4','5']) ,(abs,[-1, 0,-10]) ])
def test_map(func,it):
    for pair in zip(list(map1(func,it)), list(map(func,it))):
        assert pair[0] == pair[1]

def enumerate1(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1

@pytest.mark.parametrize("list1",[(['str1', 'str2', 'str3']), (['1', '2', '3', '4'])])
def test_enumerate(list1):
    for pair in zip(enumerate1(list1), enumerate(list1)):
        assert pair[0] == pair[1]


from django.conf import settings
from django.contrib.auth.models import User
from django.core.mail import EmailMultiAlternatives, get_connection
from django.template import loader

def send_email(recipients, subject, template, context):
    """
    Sends a multi-part (text and optionally HTML) email generated from templates
    """
    html_template = loader.get_template(template + ".html")
    text_template = loader.get_template(template + ".txt")

    html = html_template.render(context)
    text = text_template.render(context)

    send_raw_email(recipients, subject, text, html)

def send_raw_email(recipients, subject, text, html):
    """
    Sends and multi-part (text and optionally HTML) email to a list of users or email addresses
    """
    to_addresses = []
    for recipient in recipients:
        if isinstance(recipient, User):
            to_addresses.append(recipient.email)
        elif isinstance(recipient, str):
            to_addresses.append(recipient)
        else:  # pragma: no cover
            raise ValueError("Email recipients must users or email addresses")

    from_address = getattr(settings, "DEFAULT_FROM_EMAIL", "website@casepro.io")

    if getattr(settings, "SEND_EMAILS", False):
        # send individual messages so as to not leak users email addresses, but use bulk send operation for speed
        messages = []
        for to_address in to_addresses:
            message = EmailMultiAlternatives(subject, text, from_email=from_address, to=[to_address])
            if html:
                message.attach_alternative(html, "text/html")
            messages.append(message)

        get_connection().send_messages(messages)
    else:  # pragma: no cover
        print("FAKE SENDING this email to %s:" % ", ".join(to_addresses))
        print("--------------------------------------- text -----------------------------------------")
        print(text)
        if html:
            print("--------------------------------------- html -----------------------------------------")
            print(html)


import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from keras.models import load_model
from keras.models import Sequential, Model
from keras.layers import Dense,Dropout,LSTM, Input
from keras import initializers
import keras.backend as K

from sklearn import metrics
import pandas as pd
import time
import pdb
import utils

isLSTM=False

m=128
length=128
epoch=500
batch_size= 5120

chs = 100000
nrof_aut = int(chs/m)
nchs = nrof_aut*m

#===========================================================================
y_file = "csapuf-128-res-stb-nf-2642048"
#===========================================================================

dfx=pd.read_csv('dataset/dataset-128bit-challenge/csa_stable_chs/stb_parity-2642048.csv',header=None)
dfy=pd.read_csv('response/seed42/csapuf/CRPseed29/{}.csv'.format(y_file),header=None)
#===========================================================================
# fix random seed for reproducibility
np.random.seed(31)
# split into input (X) and output (Y) variables
X = dfx.values[:nchs].reshape(-1, m, length+1)
Y = dfy.values[:nrof_aut]

nbatches = Y.shape[0]
train_test_idx = np.arange(nbatches)
# Shuffle
np.random.shuffle(train_test_idx)
X = X[train_test_idx]
Y = Y[train_test_idx]

train_test_split = int(nbatches*0.9)
train_features = X[:train_test_split].reshape(-1,length+1)
test_features = X[train_test_split:].reshape(-1,length+1)
train_labels = Y[:train_test_split].flatten()
test_labels = Y[train_test_split:].flatten()

if isLSTM:
    train_features = train_features.reshape(-1, m, length+1)
    test_features = test_features.reshape(-1, m, length+1)
    train_labels = train_labels.reshape(-1, m, 1)
    test_labels = test_labels.reshape(-1, m, 1)

#pdb.set_trace()

# create model
if isLSTM:
    X_input = Input(train_features.shape[1:])
    X = LSTM(50, return_sequences=True, input_shape = (m,length+1), name = 'LSTM_1')(X_input)
    X = LSTM(50, return_sequences=True)(X)
    #X = LSTM(50, return_sequences=True)(X)
    #X = LSTM(50, return_sequences=True)(X)
    #X = Dense(50, activation='relu')(X)
    #X = Dense(50, activation='relu')(X)
    X = Dense(1, activation='sigmoid')(X)
    ##The model object
    model = Model(inputs = X_input, outputs = X, name='LSTMModel')
else:
    model = Sequential()
    model.add(Dense(15,input_dim=length+1, activation='relu'))
    model.add(Dense(50, activation='relu'))
    #model.add(Dense(200,input_dim=length+1, activation='relu'))
    #model.add(Dense(200, activation='relu'))
    #model.add(Dense(200, activation='relu'))
    #model.add(Dense(200, activation='relu'))
    #model.add(Dense(200, activation='relu'))
    #model.add(Dense(200, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))

# print the model
model.summary()

# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])#,f1])

# fit the model
results = model.fit(
 train_features, train_labels,
 epochs= epoch,
 #verbose=1,
 batch_size = batch_size,
 validation_data = (test_features, test_labels)
)
# evaluvate the model
scores = model.evaluate(test_features, test_labels)
print("\n{}: {}, std={}".format(model.metrics_names[1], scores[1], np.std(scores[1])))

#pdb.set_trace()
#print("save model...")
#outfile = "csapuf-128-noisyres-600k_train"
#model.save('model/{}.h5'.format(outfile))


"""
Purpose: Take timelapse images with raspberry pi camera
Author: Jeremy Pardo
"""

from picamera import PiCamera
import os
from time import sleep
import argparse
import datetime

def timelapse(int, n, dir, rotation, iso, shutter, exposure):
    """
    Uses the PI camera to take a set of images at a user defined interval
    :param int: length of interval between images in seconds
    :param n: number of images to take
    :param dir: path to output directory where images are saved
    :param rotation degrees to rotate pi image
    """
    camera = PiCamera()
    camera.rotation = rotation
    camera.iso = iso
    camera.shutter_speed = shutter
    camera.exposure_compensation = exposure
    for i in range(n):
        print("Capturing image{0:04d} at {1}".format(i, datetime.datetime.now()))
        camera.capture(os.path.join(dir, "image{0:04d}.jpg".format(i)))
        sleep(int)

def main():
    """
    main method parses command line arguments and runs the timelapse function.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument("--interval", "-t", type=int,
                        help="length of time in seconds between images",
                        default=60)
    parser.add_argument("--images", "-n", type=int, help="number of images", default=1)
    parser.add_argument("--output", "-o",
                        help="path to output directory", default="./")
    parser.add_argument("--rotation", "-r",
                        help="degrees to rotate pi image", default=0)
    parser.add_argument("--iso", "-i", type=int, help="camera iso 0 is auto mode", default=0)
    parser.add_argument("--shutter", "-s", type=int,
                        help="camera shutter speed in microseconds 0 is auto mode", default=0)
    parser.add_argument("--exposure", "-e", help="exposure compensation set between -25 and +25", default=0)
    args = parser.parse_args()
    interval = int(args.interval)
    images = int(args.images)
    output = args.output
    rotation = int(args.rotation)
    iso = int(args.iso)
    shutter_speed = int(args.shutter)
    exposure_compensation = int(args.exposure)

    timelapse(int=interval,
              n=images,
              dir=output,
              rotation=rotation,
              iso=iso,
              shutter=shutter_speed,
              exposure=exposure_compensation)

if __name__ == "__main__":
    main()


import numpy as np
import matplotlib.pyplot as plt

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF,WhiteKernel
import logging

from GaussianProcessTools.stageopt import optimizer as stageOpt
from GaussianProcessTools.lineBO import optimizer as lineOpt

def ofunc(x):
    return 5 - x**2

def cfunc1(x):
    return 2 - (x + 0.5)**2

def cfunc2(x):
    return ((1 / (1 + np.exp(x))) - 0.5)*2

def test1D():
    inputs = {}
    inputs['bounds'] = np.array((-5,5)).reshape(-1,2)
    kernel = RBF(1.0,'fixed')
    inputs['gprf'] = GaussianProcessRegressor(kernel,alpha = 0.01)
    inputs['gprc'] = [GaussianProcessRegressor(kernel,alpha = 0.01),GaussianProcessRegressor(kernel,alpha = 0.01)]

    inputs['X0'] = np.array((-1.1)).reshape(-1,1)
    inputs['ofun'] = ofunc
    inputs['cfun'] = [cfunc1,cfunc2]

    inputs['Y0'] = ofunc(inputs['X0'])
    inputs['C0'] = np.array([f(inputs['X0']) for f in inputs['cfun']]).T[0]
    inputs['h'] = np.zeros(len(inputs['cfun']))
    inputs['n_grid'] = 50
    inputs['T0'] = 5
    inputs['verbose'] = False

    opt = optimizer.StageOpt(inputs)

def main():
    test1D()

main()
plt.show()


import csv
import os
import subprocess
import sys
from tqdm import tqdm

def main():
	queries_dir = os.path.join(os.getcwd(), 'pquery_fastas');
	query_files = os.listdir(queries_dir)
	query_paths = [os.path.join('pquery_fastas', qfile) for qfile in query_files]

	out_paths = []
	for i in tqdm(range(len(query_paths))):
		with open(query_paths[i], 'r') as qfile:
			first_line = qfile.readline().split()
			query_id = 'pse_hmmer_' + first_line[0][1:]
		cur_out_path = os.path.join('pseudo_hmmer_csv', query_id)
		out_paths.append(cur_out_path)
	# print(query_paths[:5])
	# print(out_paths[:5])
	for i in tqdm(range(len(query_paths))):
		# print(query_paths[i])
		subprocess.call(['./phmmer', '-o', '/dev/null', '--tblout', out_paths[i], query_paths[i], "../pseq_db.fa"])

if __name__ == "__main__":
	main()


import os
import json
from unittest import mock
from requests import Response
from packageship import BASE_PATH

def compare_two_values(obj1, obj2):
    """

    Args:
        obj1:object1 It can be a data type in Python,
                and can be converted by using the str() method
        obj2:object2 same as obj1

    Returns: True or False

    """
    # With the help of the str() method provided by python,It's so powerful
    return obj1 == obj2 or (isinstance(obj1, type(obj2)) and
                            "".join(sorted(str(obj1))) == "".join(sorted(str(obj2))))

def get_correct_json_by_filename(filename):
    """

    Args:
        filename: Correct JSON file name without suffix

    Returns: list this json file's content

    """
    json_path = os.path.join(os.path.dirname(BASE_PATH),
                             "test",
                             "common_files",
                             "correct_test_result_json",
                             "{}.json".format(filename))
    try:
        with open(json_path, "r", encoding='utf-8') as json_fp:
            correct_list = json.loads(json_fp.read())
    except FileNotFoundError:
        return []

    return correct_list


from multiprocessing import Pool, cpu_count
import logging
from time import time

logger = logging.getLogger()
stream_handler = logging.StreamHandler()
logger.addHandler(stream_handler)
logger.setLevel(logging.DEBUG)

def factorize(*number):

    final_list = []
    for num in number:
        final_list.append(list(filter(lambda x: num % x == 0, range(1, num+1))))

    logger.debug(f"Result - {final_list}")
    return final_list

if __name__ == '__main__':
    start = time()
    with Pool(cpu_count()) as pool:
        result = pool.apply_async(factorize, (128, 255, 99999, 10651060))
        a,b,c,d = result.get()
    # a,b,c,d = factorize(128, 255, 99999, 10651060)
    end = time()
    print(f"Result - {end-start} seconds")


from GameObject import GameObject
from Utils import Physics
import pygame

class Dino(GameObject):

    def __init__(self, img=None, pos=(0, 0), rot=0, scale=(1, 1)):
        self.img = img

        # game logic related
        self.y_speed = 0
        self.jump_height = 80
        self.ground_height = 0
        self.grounded = True
        self.rect = pygame.Rect(pos[0], pos[1], img.size[0], img.size[1]) if img is not None else None
        super(Dino, self).__init__(pos, rot, scale)

    def update(self, deltatime=0.002, events=None):
        self.y_speed += Physics.gravity * deltatime
        self.position.y += self.y_speed * deltatime
        if self.position.y > self.ground_height:
            self.position.y = self.ground_height
            self.y_speed = 1
            self.grounded = True

        if self.rect is not None:
            self.rect.top = self.position.y

        for event in events:
            if event.type == pygame.KEYDOWN:
                if self.grounded and (event.key == pygame.K_SPACE or event.key == pygame.K_UP):
                    self.y_speed = -(self.jump_height * Physics.gravity * 2) ** 0.5
                    self.grounded = False

    def jump(self):
        if self.grounded:
            self.y_speed = -(self.jump_height * Physics.gravity * 2) ** 0.5
            self.grounded = False


from openerp import fields, models, api, _
from openerp.exceptions import ValidationError

import logging

_logger = logging.getLogger(__name__)

class StockPicking(models.Model):

	_inherit = "stock.picking"

	issue_id = fields.Many2one("warehouse.stock.issue", string="Issue")
	request_id = fields.Many2one("warehouse.stock.request", string="Request")
	is_dc = fields.Boolean(string="DC", default=False)
	warehouse_dc_id = fields.Many2one('dc.warehouse', string="Dc")
	location_type = fields.Selection([('raw', 'Raw Materials'),
										('manufacture', 'Manufacturing'),
										('semi-finished', 'Semi Finished'),
										('finished', 'Finished'),
										], string='Type', compute="_get_location")
	sale_bill_type = fields.Selection([('normal', 'Normal'), ('special', 'Special'), ('extra', 'Extra')], string="Bill Type", compute="_get_values")
	normal_discount = fields.Float("Normal Disc", compute="_get_values")
	extra_discount = fields.Float("Extra Disc", compute="_get_values")

	@api.depends()
	def _get_values(self):
		for picking in self:
			if picking.group_id:
				sale_ids = self.env['sale.order'].search([('procurement_group_id', '=', picking.group_id.id)])
				if sale_ids:
					picking.sale_bill_type = sale_ids[0].partner_selling_type
					if sale_ids[0].partner_selling_type == "normal":
						picking.normal_discount = sale_ids[0].normal_disc
						picking.extra_discount = sale_ids[0].extra_discount
					elif sale_ids[0].partner_selling_type == "extra":
						picking.normal_discount = sale_ids[0].normal_disc
						picking.extra_discount = sale_ids[0].nonread_extra_disocunt
					else:
						picking.normal_discount = sale_ids[0].nonread_normal_disocunt
						picking.extra_discount = sale_ids[0].nonread_extra_disocunt
					# res[picking.id] = sale_ids[0].partner_selling_type

	@api.depends()
	def _get_location(self):
		for res in self:
			res.location_type = res.location_id.type

	@api.multi
	def action_create_dc(self):

		dc_id = self.create_dc()
		self.write({'warehouse_dc_id':dc_id.id})
		view_id = self.env.ref('multi_warehouse_stock_transfer.warehouse_dc_form')

		if dc_id:
			action =  {
				'name':'Warehouse DC',
				'view_type':'form',
				'view_mode':'form',
				'res_model':'dc.warehouse',
				'view_id':view_id.id,
				'type':'ir.actions.act_window',
				'res_id': dc_id.id,
				'domain':[('id','=',dc_id.id)],
				'target':'current',
			}
			return action

	def create_dc(self):

		dc_obj = self.env["dc.warehouse"]
		dc_line_obj = self.env["dc.warehouse.line"]
		if not self.warehouse_dc_id:
			dc_val = {
				'request_warehouse_from_id':self.issue_id.request_warehouse_from_id.id,
				'partner_id':self.issue_id.partner_id.id,
				'warehouse_id':self.issue_id.warehouse_id.id,
				'company_id':self.company_id.id,
				'request_date':self.issue_id.request_date,
				'issue_refernce':self.issue_id.id,
				'reference':self.issue_id.reference.id,
				'currency_id':self.issue_id.currency_id.id,
			}

			dc_id = dc_obj.create(dc_val)

			for move in self.move_lines:
				if move:
					for quant in move.quant_ids:
						if quant.qty > 0:
							dc_line_val = {
								'product_id':quant.product_id.id,
								'issued_quant':quant.qty,
								'batch':quant.lot_id.id,
								'ref_id':dc_id.id,
							}

							ctx = {}
							ctx.update({'company_id':self.company_id})
							dc_line = dc_line_obj.with_context(ctx).new(dc_line_val)
							dc_line.onchange_product_id()
							val = dc_line._convert_to_write({line:dc_line[line] for line in dc_line._cache})
							dc_line_id = dc_line_obj.create(val)

			return dc_id

class StockMove(models.Model):

	_inherit = "stock.move"

	issue_line_id = fields.Many2one("warehouse.stock.issue.line", string="Issue line")

	def action_done(self, cr, uid, ids, context=None):
		res = super(StockMove, self).action_done(cr, uid, ids, context=context)
		for move in self.browse(cr, uid, ids, context=context):
			if move.issue_line_id:
				quant = move.product_uom_qty
				move.issue_line_id.issued_quant += quant
				move.issue_line_id.state = 'issue'
				move.issue_line_id.transfer_id.state = 'issue'


import string
import re
import html
import urllib.request
import json
import os
import pickle

from Sastrawi.Stemmer.StemmerFactory import StemmerFactory

def clean_text_classification(text):
    text = text.lower()

    text = re.sub(r'@[A-Za-z0-9]+', ' ', text)
    text = re.sub(r'#[A-Za-z0-9]+', ' ', text)
    text = re.sub(r'\w+:\/\/\S+', ' ', text)
    text = re.sub(r'[^a-zA-Z0-9]', ' ', text)

    text = re.sub(r' +', ' ', text)

    return ' '.join(text.split())

def clean_text_pos(text):
    text = html.unescape(text)
    text = re.sub(r'#[A-Za-z0-9]+', ' ', text)
    text = re.sub(r'\w+:\/\/\S+', ' ', text)

    text = re.sub(r' +', ' ', text)
    text = os.linesep.join([s for s in text.splitlines() if s])
    text = ', '.join(text.split('\n'))

    return text

def replace_slang(text):
    with open("extra/akronim.json", "r") as f:
        acronym = json.load(f)

    res = []

    for w in text.split(' '):
        if w in acronym:
            res.append(acronym[w])
        else:
            res.append(w)

    return ' '.join(res)

def stemming(text):
    factory = StemmerFactory()
    stemmer = factory.create_stemmer()

    stem_text = stemmer.stem(text)

    return stem_text

def clean_proc_pos(text):
    text = clean_text_pos(text)
    text = replace_slang(text)

    return text

def clean_proc_clf(text):
    text = clean_text_classification(text)
    text = replace_slang(text)

    text = stemming(text)

    return text

if __name__ == "__main__":
    text = 'Bakor Pemandu ITS mengundang Pemandu Aktif ITS untuk duduk bareng ngobrolin LKMM TD pada:\n\n📆 Selasa - Rabu, 20-21 Feruari\n2018\n🕛 18.00 - 21.30 WIB\n📍 SCC Lt. 3\n👔 Standar Kuliah\n\n"Raise your standards to create change!" - An Iota of Truth\n\n#OborBakor\n#BAKORITS\n#ITSSurabaya https://t.co/v6oFZcWLFv'

    clean_text = clean_proc_pos(text)
    print(clean_text)

    clean_text = clean_proc_clf(text)
    print(clean_text)


import torch
import torch.nn as nn
import torch.optim as optim
import pandas as pd
import numpy as np
from torch.utils.data import TensorDataset, DataLoader
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix
from numpy import vstack
from network import ContemptNet
from sklearn.model_selection import KFold
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import seaborn as sn

def boolean_df(item_lists, unique_items):
# Create empty dict
    bool_dict = {}

    # Loop through all the tags
    for i, item in enumerate(unique_items):

        # Apply boolean mask
        bool_dict[item] = item_lists.apply(lambda x: 1 if item in x else 0)
    result = pd.DataFrame(bool_dict)
    # result['filename'] = filenames
    # Return the results as a dataframe
    return pd.DataFrame(bool_dict)

def to_1D(series):
    return pd.Series([x for _list in series for x in _list])

le = LabelEncoder()
def train_model(train_dl, model, criterion, optimizer):
    training_loss = []
    avg_loss = 0
    for i, data in enumerate(train_dl):
        # print()
        device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

        inputs, labels = data
        # print(type(labels))
        inputs = inputs.to(device)
        labels = labels.float().to(device)
        model = model.train()
        # print(model)
        # print("input shape: ", inputs.shape)
        # print(input)
        # forward + backward + optimize
        yhat = model(inputs)
        loss = criterion(yhat, labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        training_loss.append(loss.item())
    return np.mean(training_loss)

# make a class prediction for one row of data

def predict(row, model):
    # convert row to data
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    row = torch.tensor([row], dtype=torch.float32).to(device)
    model.eval()
    # make prediction
    yhat = model(row)
    # retrieve numpy array
    yhat = yhat.detach().cpu().numpy()
    return np.argmax(yhat)

def valid_model(valid_dl, model, criterion):
    valid_loss = []
    valid_acc = []
    predictions, actuals = list(), list()
    model.eval()
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    for i, data in enumerate(valid_dl):
        inputs, targets = data
        inputs = inputs.to(device)
        targets = targets.float().to(device)
        # retrieve numpy array
        yhat = model(inputs)
        # print("yhat shape: ", yhat.shape)
         # retrieve numpy array
        loss = criterion(yhat, targets)
        yhat = yhat.cpu().detach().numpy()
        actual = targets.cpu().numpy()
        # convert to class labels
        # yhat = np.argmax(yhat, axis=1)
        # reshape for stacking
        actual = actual.reshape((len(actual), len(label_cols)))
        # print("Actual: ", actual[0])
        yhat = yhat.reshape((len(yhat),  len(label_cols)))
        yhat = (yhat > 0.5)
        # print("predicted: ", yhat[0])

        # calculate accuracy
        predictions.append(yhat)
        actuals.append(actual)
        acc = metrics.jaccard_score(vstack(predictions), vstack(actuals), average='samples')
        # round to class values
        valid_loss.append(loss.item())
        valid_acc.append(acc)

    # f1_metric = f1_score(vstack(actuals), vstack(predictions), average = "macro")
    # print('F1 score:' , f1_metric)
    jac = metrics.jaccard_score(vstack(actuals), vstack(predictions), average = 'samples')
    print('Jaccard score:' , jac)
    return np.mean(valid_loss), np.mean(valid_acc)

def get_dataloaders(df, batch_size):

    Y = df[label_cols].values

    X = df.drop(metadata_cols + label_cols, axis=1)
    # Y = le.fit_transform(Y)
    # print(le.classes_)
    Y_tensor = torch.tensor(Y, dtype=torch.long)
    X_tensor = torch.tensor(X.values, dtype=torch.float32)

    dataset = TensorDataset(X_tensor, Y_tensor)

    dataloader = DataLoader(dataset, shuffle=True, batch_size=batch_size)
    return dataloader

batch_size = 32
epochs = 100

data_path = '../new_data/NA/na_dataset.csv'
X_df = pd.read_csv(data_path, index_col=None)

Y_df = pd.read_csv('../new_data/NA/na_labels.csv', usecols=['filename', 'emotions'], index_col='filename')
Y_df["emotions"] = Y_df["emotions"].apply(eval)
unique_items = to_1D(Y_df["emotions"]).unique()
labels_expanded = boolean_df(Y_df['emotions'], unique_items)
# labels_expanded.set_index('filename')
X_df['none']  = np.NaN
X_df['furious']  = np.NaN
X_df['anger']  = np.NaN
X_df['annoyed']  = np.NaN
X_df['contempt']  = np.NaN
X_df['disgust']  = np.NaN
X_df['hatred']  = np.NaN

for index, row in X_df.iterrows():
    # print(index, row)
    filename = X_df.iloc[index]['filename']
    # print(labels_expanded.loc[filename]['none':'hatred'].to_list())
    X_df.at[index,'none'] = labels_expanded.at[filename,'none']
    X_df.at[index,'furious'] = labels_expanded.at[filename,'furious']
    X_df.at[index,'anger'] = labels_expanded.at[filename,'anger']
    X_df.at[index,'annoyed'] = labels_expanded.at[filename,'annoyed']
    X_df.at[index,'contempt'] = labels_expanded.at[filename,'contempt']
    X_df.at[index,'disgust'] = labels_expanded.at[filename,'disgust']
    X_df.at[index,'hatred'] = labels_expanded.at[filename,'hatred']

cols_to_scale = list (
    set(X_df.columns.to_list()) - set(['frame', 'face_id', 'culture', 'filename', 'timestamp', 'confidence','success', 'none', 'furious', 'anger', 'annoyed', 'contempt', 'disgust', 'hatred'])
)
scaler = MinMaxScaler()
X_df[cols_to_scale] = scaler.fit_transform(X_df[cols_to_scale])
metadata_cols = ['frame', 'face_id', 'culture', 'filename', 'timestamp']
label_cols = ['none', 'furious', 'anger', 'annoyed', 'contempt', 'disgust', 'hatred']

test_videos = ['na/vid_6.mp4', 'na/vid_19.mp4', 'na/vid_43.mp4', 'na/vid_25.mp4', 'na/vid_23.mp4', 'na/vid_10_1.mp4', 'na/vid_72.mp4', 'na/vid_34.mp4', 'na/vid_90.mp4', 'na/vid_92.mp4', 'na/vid_39.mp4', 'na/vid_30.mp4', 'na/vid_3.mp4', 'na/vid_33.mp4', 'na/vid_4.mp4', 'na/vid_31.mp4', 'na/vid_53.mp4', 'na/vid_52.mp4', 'na/vid_55.mp4', 'na/vid_59.mp4', 'na/vid_22.mp4', 'na/vid_11.mp4', 'na/vid_79.mp4', 'na/vid_54.mp4', 'na/vid_87.mp4', 'na/vid_63.mp4', 'na/vid_12.mp4', 'na/vid_10_2.mp4', 'na/vid_97.mp4', 'na/vid_70.mp4', 'na/vid_42.mp4', 'na/vid_49.mp4', 'na/vid_77.mp4']
# df = df[df['gender'] == 'male']
kfold = KFold(5, True, 1)
# target_culture = 'Persian'
# df = df[(df['culture'] == target_culture)]
# SPLITTING HELD-OUT DATA
videos = X_df['filename'].unique()

# videos must be array to be subscriptable by a list
videos = np.array(list(set(videos) - set(test_videos)))
# Removing test videos from train dataset
test_df = X_df[X_df['filename'].isin(test_videos)]
y_test = test_df[label_cols].values
X_test = test_df.drop(columns = ['frame', 'face_id', 'culture', 'filename', 'timestamp', 'confidence','success']).values
X_df = X_df[~X_df['filename'].isin(list(test_videos))]
# df = df[df['culture'] != 'Persian']
splits = kfold.split(videos)
kfold_valid_acc = []
kfold_test_acc = []

# TRAINING
test_df_copy = test_df.drop(['frame', 'face_id', 'culture', 'filename', 'confidence','success'], axis=1)
for (i, (train, test)) in enumerate(splits):
    print('%d-th split: train: %d, test: %d' % (i+1, len(videos[train]), len(videos[test])))
    train_df = X_df[X_df['filename'].isin(videos[train])]
    valid_df = X_df[X_df['filename'].isin(videos[test])]

    train_dataloader = get_dataloaders(train_df, batch_size)
    valid_dataloader = get_dataloaders(valid_df, batch_size)
    net = ContemptNet()
    if torch.cuda.is_available():
        net.cuda()
    # optimizer = optim.Adam(net.parameters(), lr=0.005, weight_decay=1e-5)
    optimizer = optim.ASGD(net.parameters(), lr=0.005)
    criterion = nn.BCEWithLogitsLoss()
    train_losses = []
    valid_losses = []
    valid_acc = []
    for epoch in range(epochs):
        print('Epoch {}/{}'.format(epoch, epochs - 1))
        print('-' * 10)
        epoch_train_loss = train_model(train_dataloader, net, criterion, optimizer)
        epoch_valid_loss, epoch_valid_acc = valid_model(valid_dataloader, net, criterion)
        train_losses.append(epoch_train_loss)
        valid_losses.append(epoch_valid_loss)
        print('[%d] Training loss: %.3f' %
                    (epoch + 1, epoch_train_loss ))
        print('[%d] Validation loss: %.3f' %
                    (epoch + 1, epoch_valid_loss ))
        print('[%d] Validation accuracy: %.3f' %
                    (epoch + 1, epoch_valid_acc ))
        valid_acc.append(epoch_valid_acc)
    kfold_valid_acc.append(valid_acc[-1])
    ## Plot the curves
    plt.plot(train_losses, label='training loss')
    plt.plot(valid_losses, label='validation loss')

    plt.legend(bbox_to_anchor=(1.05, 1.0), loc='upper left')
    plt.show()

    ## Testing
    Yhat = list()
    for row in test_df_copy.values:
        p = predict(row, net)
        Yhat.append(p)

    # test_df['integer_emotion'] = Y
    # test_df['predicted'] = le.inverse_transform(Yhat)
    # print(test_df.sample(n=20))
    # test_acc = accuracy_score(le.fit_transform(test_df['emotion'].values), Yhat)
    test_acc = metrics.jaccard_score(test_df[label_cols].values, Yhat, average='samples')
    # cf_matrix = confusion_matrix(le.fit_transform(test_df['emotion'].values), Yhat)
    # print('********Confusion Matrix*********\n', cf_matrix)
    # df_cm = pd.DataFrame(cf_matrix/np.sum(cf_matrix), index=le.inverse_transform([0,1,2]), columns=le.inverse_transform([0,1,2]))
    # plt.figure(figsize=(10,7))
    # sn.heatmap(df_cm, annot=True, fmt='.2%')
    # plt.ylabel('True label')
    # plt.xlabel('Predicted label')
    # plt.show()
    # misclassified_test_df = test_df[test_df.predicted != test_df.emotion]
    # test_f1 = f1_score(le.fit_transform(test_df['emotion'].values), Yhat, average='macro')
    kfold_test_acc.append(test_acc)
    print('Test accuracy: %.3f' % (test_acc))
    # print('Test F1-Score: %.3f' % (test_f1))

test_df.to_csv('test_result.csv')
print('Average Test Accuracy on 5-Fold CV: %.3f' % (np.mean(kfold_test_acc)))
print('Average Validation Accuracy on 5-Fold CV: %.3f' % (np.mean(kfold_valid_acc)))


import argparse
import importlib
import pkgutil

from api_builder import configuration, subcommands

def get_module_parser(mod, modname, parents=[], add_help=True):
    """
    Returns an argument parser for the sub-command's CLI.

     :param mod: the sub-command's python module
     :param modnam: the string name of the python module
     :return: ArgumentParser
    """
    return argparse.ArgumentParser(
        usage=configuration.EXECUTABLE_NAME + ' ' + modname + ' [options]',
        description=mod.get_description(), parents=parents,
        add_help=add_help)

def get_application_parser(commands):
    """
    Builds an argument parser for the application's CLI.

    :param commands:
    :return: ArgumentParser
    """

    parser = argparse.ArgumentParser(
        description=configuration.APPLICATION_DESCRIPTION,
        usage =configuration.EXECUTABLE_NAME + ' [sub-command] [options]',
        add_help=False)

    parser.add_argument(
        'sub_command',
        choices=[name for name in commands],
        nargs="?")

    parser.add_argument("-h", "--help", action="store_true")
    return parser

def get_module(name):
    """
    Convenience method for importing a module (i.e. sub-command) from a string

    :param name: module name to import
    :return: the module object
    """
    return importlib.import_module("api_builder.subcommands." + name)

def main():

    sub_commands = [m.name for m in pkgutil.iter_modules(subcommands.__path__)]
    application_parser = get_application_parser(sub_commands)
    args = application_parser.parse_known_args()[0]

    # Print help message
    if not args.sub_command:
        application_parser.print_help()

    # Delegate to sub-command help message
    if args.sub_command and args.help:
        command = get_module(args.sub_command)
        module_parser = get_module_parser(command, args.sub_command)
        command.set_args(module_parser)
        module_parser.print_help()

    # Execute the sub-command
    if args.sub_command and not args.help:
        command = get_module(args.sub_command)
        module_parser = get_module_parser(command, args.sub_command, parents=[application_parser], add_help=False)
        command.set_args(module_parser)
        module_args = module_parser.parse_args()
        command.execute(module_args)