'''
https://leetcode.com/problems/flood-fill/

https://leetcode.com/problems/rotting-oranges/

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535).

Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor, "flood fill" the image.

To perform a "flood fill", consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color as the starting pixel), and so on. Replace the color of all of the aforementioned pixels with the newColor.

At the end, return the modified image.

Example 1:

Input:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
Explanation:
From the center of the image (with position (sr, sc) = (1, 1)), all pixels connected
by a path of the same color as the starting pixel are colored with the new color.
Note the bottom corner is not colored 2, because it is not 4-directionally connected
to the starting pixel.
Note:

The length of image and image[0] will be in the range [1, 50].
The given starting pixel will satisfy 0 <= sr < image.length and 0 <= sc < image[0].length.
The value of each color in image[i][j] and newColor will be an integer in [0, 65535].

input:
[[1,1,1],
[1,1,0],
[1,0,1]]

Output:
[[2,2,2],
[2,2,0],
[2,0,1]]

---- Number of islands reference ----
def numIslands(grid:list) -> int:
  row = len(grid)
  col = len(grid[0])

  visited = [[False] * col for _ in range(row)]
  islands = 0

  for i in range(row):
    for j in range(col):
      if grid[i][j] == '1' and not visited[i][j]:
        stack = [(i,j)]
        visited[i][j] = True

        while stack:
          ix, jx = stack.pop()

          for di, dj in [(1,0), (0,1), (-1,0), (0,-1)]:
            ni = ix + di
            nj = jx + dj

            if 0 <= ni < row and 0 <= nj < col and grid[ni][nj] == '1' and not visited[ni][nj]:
              stack.append((ni,nj))
              visited[ni][nj] = True
        islands += 1
  return islands

inorder left root right
preorder root left right
postorder left right root

toplogical sort question:
https://leetcode.com/problems/course-schedule-ii/

dynamic programming question:
https://leetcode.com/problems/knight-dialer/

'''
import collections
from collections import deque
def flood(image, sr, sc, newColor):
  if sr not in range(len(image)) or sc not in range(len(image[0])):
    return False

  oldColor = image[sr][sc]
  queue = collections.deque([(sr, sc)])

  while queue:
    r, c = queue.popleft()

    image[r][c] = newColor

    for di, dj in [(1,0), (0,1), (-1,0), (0,-1)]:
      next_r = r + di
      next_c = c + dj

      # if not 0 <= next_r < len(image) or not 0 <= next_c < len(image[0]):
      #   continue

      if 0 <= next_r < len(image) and 0 <= next_c < len(image[0]):
        if image[next_r][next_c] == oldColor:
          queue.append((next_r, next_c))

  return image

image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1
sc = 1
newColor = 2

print(flood(image, sr, sc, newColor))


def removeElement(nums, val):
    k = 0  # variable to store the count of elements not equal to val

    for i in range(len(nums)):
        if nums[i] != val:
            nums[k] = nums[i]
            k += 1

    return k

# Example usage
nums = [3, 2, 2, 3]
val = 3
result = removeElement(nums, val)
print("Output:", result)
print("Modified nums:", nums[:result] + ["_*"] * (len(nums) - result))


#!/usr/bin/python3
import sys
import os
import math
import time
import random
import argparse
import numpy as np
from PIL import Image
from termcolor import colored

def script_path():
    """set current path to script path"""
    current_path = os.path.realpath(os.path.dirname(sys.argv[0]))
    os.chdir(current_path)
    return current_path

def timer(func):
    """timer decorator for debug"""
    def f(*args, **kwargs):
        before = time.time()
        val = func(*args, **kwargs)
        after = time.time()
        print("[*]elapsed time: {}[s] ({})".format(after-before, func.__name__))
        return val
    return f

def rgb2gray(rgb):
    """convert rgb image to greyscale"""
    return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])

def open_image(filename):
    """open image file"""
    img = Image.open(filename)
    return img

def write_file(filename, text, mode='w'):
    """write to file"""
    try:
        with open(filename, mode, encoding='utf-8') as f:
            f.write(text)
    except Exception as err:
        print('[x] failed to write to file: {}, err: {}'.format(filename, err))
    return None

def ascii_list(key):
    """works as color map for image -> ascii convertion
    key=2 seems to be the most acurate
    """
    my_map = [' ',' ','.','`',',','-','-','~','"','^','*',';','i','l','=','v','x','C','P','G','&','$','O','Q','@','@','X','X','#','#',chr(0x25a0),chr(0x25a0)]   #32
    my_map = "".join([item*8 for item in my_map])
    my_map = my_map[::-1]

    data = {
        1: my_map,

        # 'https://ascii-generator.site/'
        2: '@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%%%%%%%%%%%%%%%%%##########################*************************++++++++++++++++++++++++++=========================--------------------------:::::::::::::::::::::::::..........................                          ',

        # 'https://manytools.org/hacker-tools/convert-images-to-ascii-art/go/'
        3: '@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%##########################((((((((((((((((((((((((((////////////////////////**************************,,,,,,,,,,,,,,,,,,,,,,,,,,..........................                        ',

        # 'https://www.text-image.com/convert/pic2ascii.cgi'
        4: 'MMMMMMMMMMNNNNNNNNNNNNNNNNNNmmmmmmmmmmmmmmmmmmddddddddddddddddddhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyyyyyyyssssssssssssssssssoooooooooooooooooo++++++++++++++++++///////////////////::::::::::::::::::------------------..................``````````````````          ',

        # 'https://www.ascii-art-generator.org/'
        5: "MMMMMMWWWWWWWWWWWNNNNNNNNNNNNXXXXXXXXXXXXKKKKKKKKKKK000000000000OOOOOOOOOOOkkkkkkkkkkkkxxxxxxxxxxxxdddddddddddoooooooooooollllllllllllcccccccccccc:::::::::::;;;;;;;;;;;;,,,,,,,,,,,,'''''''''''...................................                             ",
    }
    if not key in range(1, 6):
        key = 1
    return list(data[key])

# @timer
def image_to_ascii(*, filename=None, img=None, target_width=100, reverse=True, colorized=True, mapping_key=1):
    """
    target_width - ascii image width in characters
    reverse - reverse colors flag
    """
    if filename is not None:
        img = open_image(filename)  # PIL format
    else:
        if img is None:
            raise Exception('Either filename nor img specified')

    # ********* resize due to wrong width/height ratio in terminal/notepad *********
    init_width, init_height = img.size
    # width_compensation_ratio = 1.8   # npp
    width_compensation_ratio = 2.1     # python terminal
    new_width = round(init_width*width_compensation_ratio)
    img = img.resize((new_width, init_height))

    # ********* resize *********
    target_height = round((target_width/new_width)*init_height)
    # print('target size: ({}, {})'.format(target_width, target_height))
    img = img.resize((target_width, target_height))

    # ********* convert to numpy array & remove alpha channel *********
    img = np.array(img, dtype=np.uint8)     # PIL -> numpy
    img = img[:, :, :3]                     # remove alpha channel;

    # ********* convert to gray *********
    gray = rgb2gray(img)

    # ********* round to int *********
    rounded = np.rint(gray).astype(int)

    # ********* colors map *********
    if colorized:
        data = termcolor_colors()
        termcolor_xyz = [rgb_to_xyz(*val) for key, val in data.items()]
        # termcolor_xyz_rgb = {rgb_to_xyz(*val): val for key, val in data.items()}  # may be used for creating image
        termcolor_xyz_name = {rgb_to_xyz(*val): key for key, val in data.items()}
        colors_map = [[termcolor_xyz_name[closest_point(termcolor_xyz, rgb_to_xyz(*px))] for px in row] for row in img.tolist()]

    # ********* convert to ascii *********
    ascii_map = ascii_list(mapping_key)    # list with index access (consider dict)
    if not reverse:
        ascii_map.reverse()
    img_rows = rounded.tolist()
    if colorized:
        ascii_image = '\n'.join([''.join([colored(ascii_map[item], colors_map[x][y]) for y, item in enumerate(row)]) for x, row in enumerate(img_rows)])
    else:
        ascii_image = '\n'.join([''.join([ascii_map[item] for y, item in enumerate(row)]) for x, row in enumerate(img_rows)])
    return ascii_image

def rgb_to_xyz(r, g, b):
    """red - 0deg, green - 120deg, blue - 240deg"""
    r_vector = np.array([r, 0, r])
    g_vector = np.array([math.cos((120/360)*2*math.pi)*g, math.sin((120/360)*2*math.pi)*g, g])
    b_vector = np.array([math.cos((240/360)*2*math.pi)*b, math.sin((240/360)*2*math.pi)*b, b])

    out = r_vector + g_vector + b_vector
    out = tuple(int(round(item)) for item in out)
    return out

def calculate_distance_xyz(x1, y1, z1, x2, y2, z2):
    """ok for now"""
    dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2 + (z2 - z1)**2)
    return dist

def termcolor_colors():
    """termcolor colors mapping"""
    data = {
        'red': (197, 15, 31),
        'green': (19, 161, 14),
        'yellow': (193, 156, 0),
        'blue': (0, 55, 218),
        'magenta': (136, 23, 152),
        'cyan': (58, 150, 221),
        'white': (204, 204, 204),
    }
    return data

def closest_point(points, single):
    """match single point to the closest from the points list; coords are x, y
    -that won't work as i thought, because of ignoring amplitude e.g. (0, 0, 0) is equal to (255, 255, 255)
    """
    distances = []
    for point in points:
        dist = calculate_distance_xyz(*point, *single)
        distances.append((point, dist))

    closest = sorted(distances, key=lambda x: x[1])[0]  # get first item
    color = closest[0]
    return color

def colors_mapping_example():
    """map full range colors (0-255, RGB) to termcolor colors"""
    colors = [
        (50, 50, 50),
        (50, 150, 200),
        (200, 100, 10),
        (200, 0, 200),
        (0, 100, 0),
        (100, 0, 0),
        (200, 200, 150),
    ]

    # ********* colors mapping *********
    data = termcolor_colors()
    termcolor_xyz = [rgb_to_xyz(*val) for key, val in data.items()]
    termcolor_xyz_rgb = {rgb_to_xyz(*val): val for key, val in data.items()}
    termcolor_xyz_name = {rgb_to_xyz(*val): key for key, val in data.items()}

    for px in colors:
        single_xyz = rgb_to_xyz(*px)
        out = closest_point(termcolor_xyz, single_xyz)
        converted = termcolor_xyz_rgb[out]
        color_name = termcolor_xyz_name[out]
        print('{} -> {} -> {}'.format(px, color_name, converted))
    return None

def parse_arguments():
    """parse commandline arguments"""
    words = 'IMAGE TO ASCII CONVERTER'.split()
    random_colors = ['green', 'red', 'yellow', 'blue', 'cyan']
    line_color = random.choice(random_colors)
    line_left = colored('--<', line_color)
    line_right = colored('>--', line_color)
    text = ' '.join([colored(item, random.choice(random_colors), None, ['reverse']) for item in words])
    description = '{} {} {}'.format(line_left, text, line_right)
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('file',
                       type=str,
                       help='path to input file')
    parser.add_argument('-w',
                        '--width',
                       action='store',
                       default = 100,
                       type=int,
                       help='target ascii image width [in pixels]')
    parser.add_argument('-m',
                        '--mapping',
                       action = 'store',
                       default = 3,
                       type=int,
                       help='mapping key [1-5]')
    parser.add_argument('-o',
                        '--output',
                       type=str,
                       help='path to output file')
    parser.add_argument('-r',
                       '--reverse',
                       default = False,
                       action='store_true',
                       help='reverse image color')
    parser.add_argument('-c',
                        '--color',
                       default = False,
                       action='store_true',
                       help='colorized image flag')
    parser.add_argument('-q',
                        '--quiet',
                       action='store_true',
                       help='quiet mode - do not print image')

    args = parser.parse_args()
    filename = args.file
    target_width = args.width
    reverse = args.reverse
    colorized = args.color
    mapping = args.mapping
    output = args.output
    quiet = args.quiet
    return filename, target_width, reverse, colorized, mapping, output, quiet

def main():
    """main function"""
    script_path()
    if os.name == 'nt':
        os.system('color')

    # ********* parse arguments *********
    filename, target_width, reverse, colorized, mapping, output, quiet = parse_arguments()

    # ********* convert image to ascii image *********
    ascii_image = image_to_ascii(filename=filename, target_width=target_width, reverse=reverse, colorized=colorized, mapping_key=mapping)

    # ********* print to terminal *********
    if not quiet:
        print(ascii_image)

    # ********* save to file *********
    if output:
        write_file(output, ascii_image)
    return None

if __name__ == "__main__":
    main()

"""
useful:
    https://stackoverflow.com/questions/35902302/discarding-alpha-channel-from-images-stored-as-numpy-arrays
    https://www.kite.com/python/answers/how-to-convert-an-image-from-rgb-to-grayscale-in-python
    https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html
    https://realpython.com/command-line-interfaces-python-argparse/
    https://stackoverflow.com/questions/15301147/python-argparse-default-value-or-specified-value

"""


from crypt import methods

from flask import Flask, jsonify, request
from numpy import deg2rad, rec

from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import *
import logging
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import text

Base = declarative_base()

session_maker = None
engine = None

def init_db(
    db_str,
    pool_size=10,
    pool_recycle=3600,
    isolation_level="READ COMMITTED",
    convert_unicode=True,
):
    global session_maker, engine
    SQL_ALCHEMY_DATABASE_URI = db_str
    engine = create_engine(
        SQL_ALCHEMY_DATABASE_URI,
        pool_size=pool_size,
        pool_recycle=pool_recycle,
        isolation_level=isolation_level,
        convert_unicode=convert_unicode,
    )
    session_maker = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# used as a decorator for db sessions, @with_session
# def with_session(func, db_session=None, close_session=True, *args):
# while calling the functions that use this decorator, MUST specify all arguments as keyword arguments.
def with_session(func=None):
    def inner(db_session=None, close_session=True, **kwargs):
        if db_session is None:
            db_session = scoped_session(session_maker)
        kwargs.update({"db_session": db_session})
        res = func(**kwargs)
        if close_session:
            if db_session is not None:
                db_session.close()
        return res

    return inner

app = Flask(__name__)
app_name = "hacke_me"

def init(db_str):
    init_db(db_str)

@app.route("/", methods=["GET"])
def home():
    return "Hack me app please. M horny."

@app.route('/getcustomer',methods=['GET'])
def getCustomer():
    global engine
    query = str("select * from customer;")
    result = engine.execute(query)
    data = []
    for record in result:
        data.append({
            "id":record.id,
            "name":record.name,
            "email":record.email,
            "nationality":record.nationality
        })
    return jsonify({"result":data})

@app.route('/insert/customer',methods=['POST'])
def insertCustomer():
    global engine
    data = request.json
    query = text("insert into customer(name,email,nationality) values(:name, :email, :nationality);")
    engine.execute(query,data)
    return jsonify({"result":"customer insert successfully"})

# @app.route('/getcustomer/<id>')
# def getCustomerById(id):
#     global engine
#     query = text("select * from customer where id > :id;")
#     result = engine.execute(query,{"id":id})
#     print("===== result ==== {}".format(id))
#     data=[]
#     for record in result:
#         data.append({
#             "id":record.id,
#             "name":record.name,
#             "email":record.email,
#             "nationality":record.nationality
#         })
#     return jsonify({"user_details":data})

@app.route('/getcustomer/<id>')
def getCustomerById(id):
    global engine
    query = f"select * from customer where id = {id};"
    print("====== queryyy =====",query)
    result = engine.execute(query)
    data=[]
    for record in result:
        data.append({
            "id":record.id,
            "name":record.name,
            "email":record.email,
            "nationality":record.nationality
        })
    if len(data)==0:
        query = "select * from customer where id = 1;"
        print("====== queryyy =====",query)
        result = engine.execute(query)
        for record in result:
            data.append({
                "id":record.id,
                "name":record.name,
                "email":record.email,
                "nationality":record.nationality
            })
    return jsonify({"user_details":data})

@app.route('/delete/<id>',methods=['POST'])
def deleteCustomer(id):
    global engine
    # query = text("delete from customer where id = :id;")
    query = f"delete from customer where id = {id};"
    engine.execute(query)
    return jsonify({"message":"customer deleted successfully"})

# MODELS
class Customer(Base):
    __tablename__ = "customer"
    id = Column(Integer, primary_key=True, autoincrement=True,nullable=False)
    name = Column(String(40),nullable=False)
    email = Column(String(40),nullable=False)
    nationality = Column(String(40),nullable=False)

# CONTROLLERS

def get_customers():
    global engine
    query = "select * from customer;"
    result = engine.execute(query)
    return result

def get_customer_by_id(ctid=None, db_session=None):
    global engine
    query = "select * from customer where ctid= {ctid}"
    result = engine.execute(query)
    return result

if __name__ == "__main__":
    db_str = "mysql+pymysql://root:root12345@localhost:3306/hackme"
    init(db_str)
    app.run(host="0.0.0.0", port=5055, debug=True, threaded=True)


def bubble_sort(list):
	for iter_num in range(len(list) -1, 0, -1):
		for idx in range(iter_num):
			if list[idx] > list[idx + 1]:

				temp = list[idx]
				list[idx] = list[idx + 1]
				list[idx + 1] = temp

list = [10,9,8,7,6,5,4,3,2,1]
bubble_sort(list)
print(list)

def shell_sort(list):
	gap = len(list) // 2

	while gap > 0:
		for i in range(gap, len(list)):
			temp = list[i]
			j = i
			while j >= gap and list[j-gap] > temp:
				list[j] = list[j-gap]
				j = j - gap

			list[j] = temp
		gap = gap // 2

list = [10,9,8,7,6,5,4,3,2,1]
shell_sort(list)
print(list)


from django.urls import path
from . import views

urlpatterns = [
    path('', views.listview, name='alldata'),
    path('<int:pk>', views.detailview, name='oneobject'),
    path('create/', views.createview, name='create'),
    path('update/', views.updateview, name='update'),
    path('delete/', views.deleteview, name='delete'),

]


from collections import deque
from typing import Deque, Dict, Iterable, List, Optional, Set, Tuple

import torch

from .chunk import Chunk, ChunkFullError, TensorState
from oslo.torch.nn.parallel.data_parallel.zero.hetero.utils import get_current_device

from oslo.torch.distributed.parallel_context import ParallelContext

class ChunkManager:
    """
    A manager class to manipulate the tensors in chunks.

    Args:
        chunk_configuration (Dict[int, Dict]): the configuration dictionary of this chunk manager.
        init_device (torch.device): optional, the device on which the chunk is initialized. The default is None.
    """

    def __init__(
        self,
        chunk_configuration: Dict[int, Dict],
        init_device: Optional[torch.device] = None,
    ) -> None:

        self.device = init_device or get_current_device()
        self.dp_degree_chunk_size_dict: Dict[int, int] = dict()
        self.kwargs_config = chunk_configuration
        for k, v in self.kwargs_config.items():
            self.dp_degree_chunk_size_dict[k] = v.pop("chunk_size")
            v["init_device"] = self.device
        self.chunk_groups: Dict[str, Deque] = dict()
        self.tensor_chunk_map: Dict[torch.Tensor, Chunk] = dict()
        self.accessed_chunks: Set[Chunk] = set()
        self.accessed_mem: int = 0
        self.total_mem: Dict[str, int] = {"cpu": 0, "cuda": 0}

    def register_tensor(
        self,
        tensor: torch.Tensor,
        group_type: str,
        config_key: int,
        parallel_context: ParallelContext,
        cpu_offload: bool = False,
        pin_memory: bool = False,
    ) -> None:
        """
        Register a tensor to the chunk manager.
        Then, the tensor should be accessed by `get_chunks`.

        Args:
            tensor: the tensor appended to the chunk
            group_type: the data type of the group.
            config_key: the key of the group's name, the size of the dp world
            cpu_offload: if True, the chunk will be closed on CPU
            parallel_context: the parallel context
            pin_memory: whether the chunk is pinned in the cpu memory
        """
        assert tensor not in self.tensor_chunk_map
        assert isinstance(
            tensor, torch.Tensor
        ), "Please feed Tensor to this ChunkManager"
        assert config_key in self.dp_degree_chunk_size_dict

        chunk_size = self.dp_degree_chunk_size_dict[config_key]
        chunk_kwargs = self.kwargs_config[config_key]
        group_name = "{}_{}".format(group_type, config_key)
        chunk_group = self.__get_chunk_group(group_name)

        try:
            # append the tensor to the last chunk
            chunk_group[-1].append_tensor(tensor)
        except (IndexError, ChunkFullError):
            # the except statement will be triggered when there is no chunk or
            # the last chunk in the chunk group is full
            # this will create a new chunk and allocate this chunk to its corresponding process
            if chunk_group:
                # the chunk group is not empty
                # close the last chunk
                self.__close_one_chunk(chunk_group[-1])

            if tensor.numel() > chunk_size:
                chunk_size = tensor.numel()
                dp_size = tensor.get_dp_world_size()
                chunk_size = chunk_size + (-chunk_size % dp_size)

            chunk = Chunk(
                chunk_size=chunk_size,
                parallel_context=parallel_context,
                dtype=tensor.dtype,
                cpu_shard_init=cpu_offload,
                pin_memory=pin_memory,
                **chunk_kwargs,
            )

            chunk_group.append(chunk)
            chunk.append_tensor(tensor)
            self.__add_memory_usage(chunk.memory_usage)

        self.tensor_chunk_map[tensor] = chunk_group[-1]

    def close_all_groups(self):
        """Close all the chunks of all groups."""
        for group_name in self.chunk_groups:
            self.__close_one_chunk(self.chunk_groups[group_name][-1])

    def access_chunk(self, chunk: Chunk) -> None:
        """Make the chunk can be used for calculation."""
        if chunk in self.accessed_chunks:
            return
        self.__sub_memroy_usage(chunk.memory_usage)
        if chunk.device_type == "cpu":
            chunk.shard_move(get_current_device())
        self.__add_accessed_chunk(chunk)
        self.__add_memory_usage(chunk.memory_usage)

    def release_chunk(self, chunk: Chunk) -> None:
        """Scatter the chunk in CUDA."""
        if chunk not in self.accessed_chunks:
            return
        if chunk.can_release:
            self.__sub_memroy_usage(chunk.memory_usage)
            self.__sub_accessed_chunk(chunk)
            self.__add_memory_usage(chunk.memory_usage)

    def move_chunk(
        self, chunk: Chunk, device: torch.device, force_copy: bool = False
    ) -> None:
        """Move the shard of the chunk to the target device."""
        if not chunk.can_move or chunk.device_type == device.type:
            return
        self.__sub_memroy_usage(chunk.memory_usage)
        chunk.shard_move(device, force_copy)
        self.__add_memory_usage(chunk.memory_usage)

    def trans_tensor_state(self, tensor: torch.Tensor, state: TensorState) -> None:
        """Transit tensor state according to pre-defined state machine."""
        chunk = self.tensor_chunk_map[tensor]
        chunk.tensor_trans_state(tensor, state)

    def reduce_chunk(self, chunk: Chunk) -> bool:
        """Reduce or all reduce the chunk."""
        if not chunk.can_reduce:
            return False
        self.__sub_memroy_usage(chunk.memory_usage)
        chunk.reduce()
        self.__sub_accessed_chunk(chunk)
        self.__add_memory_usage(chunk.memory_usage)
        return True

    def fake_release_chunk(self, chunk: Chunk) -> None:
        """Release gathered chunk in a fake mode.
        This function is used for keep-gathered chunk in the inference mode.
        """
        assert chunk.keep_gathered
        assert chunk.tensor_state_cnter[TensorState.HOLD] == chunk.num_tensors
        self.__sub_accessed_chunk(chunk)

    def copy_tensor_to_chunk_slice(
        self, tensor: torch.Tensor, data: torch.Tensor
    ) -> None:
        """
        Copy data to the chunk.

        Args:
            tensor (torch.Tensor): the tensor used to retrieve meta information
            data (torch.Tensor): the tensor to be copied to the chunk
        """
        chunk = self.tensor_chunk_map[tensor]
        chunk.copy_tensor_to_chunk_slice(tensor, data)

    def get_chunk(self, tensor: torch.Tensor) -> Chunk:
        """
        Return the chunk owning the tensor.

        Args:
            tensor (torch.Tensor): a torch tensor object
        """
        return self.tensor_chunk_map[tensor]

    def get_cuda_movable_chunks(self) -> List[Chunk]:
        """
        Get all chunks that can be moved.
        """
        chunk_list = []
        for chunk in self.accessed_chunks:
            if chunk.can_release:
                chunk_list.append(chunk)
        chunk_list.sort(key=lambda x: x.count_id)
        return chunk_list

    def get_chunks(self, tensors: Iterable[torch.Tensor]) -> Tuple[Chunk, ...]:
        """
        Get all chunks owning the input tensors.

        Args:
            tensors (Iterable[torch.Tensor]): the tensors used to look for chunks
        """
        chunks = []
        for tensor in tensors:
            chunk = self.get_chunk(tensor)
            if chunk not in chunks:
                chunks.append(chunk)
        return tuple(chunks)

    def add_extern_static_tensor(self, tensor: torch.Tensor) -> None:
        """Add extern static tensor to chunk manager.
        Those tensors won't be managed by chunk manager, but we want to monitor memory usage of them.
        They are "static", which means their shape, dtype, device never change.
        Thus, their memory usage never changes.

        Args:
            tensor (torch.Tensor): An extern static tensor. E.g. optimizer state.
        """
        assert tensor not in self.tensor_chunk_map
        self.total_mem[tensor.device.type] += tensor.numel() * tensor.element_size()

    def __repr__(self) -> str:
        msg = [
            "Chunk Manager Information:\n",
            "Total memory: "
            + ", ".join([f"{k}={v}B" for k, v in self.total_mem.items()])
            + "\n",
        ]
        for group_name, group in self.chunk_groups.items():
            msg.append(f"Group {group_name}:\n")
            for i, chunk in enumerate(group):
                msg.append(f"[{i}] {chunk}\n")
        return "".join(msg)

    def __get_chunk_group(self, group_name: str) -> Deque:
        """Register a chunk group."""
        if group_name not in self.chunk_groups:
            self.chunk_groups[group_name] = deque()
        return self.chunk_groups[group_name]

    def __close_one_chunk(self, chunk: Chunk):
        """Close one chunk."""
        self.__sub_memroy_usage(chunk.memory_usage)
        chunk.close_chunk()
        self.__add_memory_usage(chunk.memory_usage)

    def __sub_memroy_usage(self, usage: Dict[str, int]):
        """Subtract memory usage from the total memory usage."""
        for k, v in usage.items():
            self.total_mem[k] -= v

    def __add_memory_usage(self, usage: Dict[str, int]):
        """Add memory usage to the total memory usage."""
        for k, v in usage.items():
            self.total_mem[k] += v

    def __add_accessed_chunk(self, chunk: Chunk):
        """Add a chunk to the accessed chunk list."""
        chunk.access_chunk()
        self.accessed_chunks.add(chunk)
        self.accessed_mem += chunk.chunk_mem

    def __sub_accessed_chunk(self, chunk: Chunk):
        """Subtract a chunk from the accessed chunk list."""
        chunk.release_chunk()
        self.accessed_chunks.remove(chunk)
        self.accessed_mem -= chunk.chunk_mem


# Feedback in de les
# Keep it simple stupid. Simpler is always better. Reduce complexity as much as possible.
# Always find root cause. Always look for the root cause of a problem.
# Use pronounceable names. Have no side effects. Prefer data structures.
# Similar functions should be close.
#
'''
Sources voor uitleg over itertools;
https://www.youtube.com/watch?v=Qu3dThVy6KQ
https://github.com/CoreyMSchafer/code_snippets/tree/master/Python/Itertools
https://docs.python.org/2/library/itertools.html
'''
import random
import itertools

def AICreateCode():
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Dit is een random nummer gokker met geen logica     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      GameGokcode moet een list van 4 elementen zijn      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    gamemastercode = [ListKleurenNamen[random.randrange(AantalKleuren)],
                      ListKleurenNamen[random.randrange(AantalKleuren)],
                      ListKleurenNamen[random.randrange(AantalKleuren)],
                      ListKleurenNamen[random.randrange(AantalKleuren)]]
    print("De gamemastercode is", gamemastercode)
    return gamemastercode

def AIGokCode():
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Dit is een random nummer gokker met geen logica     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      game_gokcode moet een list van 4 elementen zijn      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    game_gokcode = [ListKleurenNamen[random.randrange(AantalKleuren)],
                    ListKleurenNamen[random.randrange(AantalKleuren)],
                    ListKleurenNamen[random.randrange(AantalKleuren)],
                    ListKleurenNamen[random.randrange(AantalKleuren)]]
    return game_gokcode

def PlayerCreateCode():
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Code voor het opvragen van de speler zijn oode    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    gamemastercode = []
    while len(gamemastercode) < AantalKleuren - 1:
        gamemastercode.append(
            ListKleurenNamen[int(input("Geef een nummer tussen de 0 en " + str(AantalKleuren) + " op: "))])
    return gamemastercode

def listmaken():
    # Het gebruik van itertools om een lijst te vullen met variabelen. zie bronnen bovenin
    result = itertools.product(ListKleurenNamen, repeat=4)
    mainlist = []
    for item in result:
        mainlist.append(list(item))
    return mainlist

def ControlleCode(gegokte_code, targetcode):
    # Gegokte code is de code die je toeleverd en de targetcode is de code waar je naar toe vergelijkt
    blackpin = 0
    whitepin = 0
    collourblindpin = 0

    # Het omzetten van list naar sets om de overeenkomsten te isoleren
    # set1 = set(GlobalGamemastercode)
    set1 = set(targetcode)
    set2 = set(gegokte_code)
    list3 = list(set1 & set2)
    for i in list3:
        # van alle overeenkosmten bepalen hoeveel witte pinnen er moeten zijn (ook zwarte pinnen zijn nog wit)
        if targetcode.count(i) <= gegokte_code.count(i):
            whitepin += targetcode.count(i)
            collourblindpin += targetcode.count(
                i)  # niet gebruikte variable, overgebleven van een eventuele optie voor anderen algoritme die alleen kijkt of er pinnen zijn
    for i in range(len(gegokte_code)):
        # het eventueel omzetten van witte pinnen naar zwarte pinnen
        if gegokte_code[i] == targetcode[i]:
            blackpin += 1
            whitepin -= 1
    if whitepin < 0:
        whitepin = 0
    feedbck = [blackpin, whitepin]
    # feedbck= [blackpin, whitepin,collourblindpin] #ongebruikte variable terug roepen om eventueel een extra algoritme te maken
    return feedbck

def aibraincode(mainlist, gokresultaat, controlecode):
    '''
    De code hieronder controleerd elke uitkomst van de geheugen bank met de voorgaanden uitkomst om alles er uit tefilteren wat slechter is door dat element in de list te vervangen met een "".
    Aan het einde van de functie word leeg element verwijderd uit de lijst om alleen nog maar de meest correcte combinaties over tehouden.
    Hier wordt de eerste simpele methode toegepast volgens het artikel
    '''
    for i in range(len(mainlist)):
        ai_testuitkomst = ControlleCode(mainlist[i], controlecode)
        if (ai_testuitkomst != gokresultaat):
            # Alle elementen die niet de zelfde score hebben vervangen door lege strings
            mainlist[i] = ""
    while '' in mainlist:
        # het verwijderen van lege strings
        mainlist.remove('')
    return mainlist

def endgame(win, maxrondes):
    # functie om het spel af tesluiten
    if maxrondes == True:
        print("Er zijn geen beurten meer over :c")
        quit()
    if win == True:
        print("U heeft gewonnen/of de AI heeft gewonnen")
        for i in Totaleronde3dlist:
            print(i)
        quit()
    else:
        print("De AI heeft geen idee voor antwoord :c")
        quit()

def maingame():
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Setup     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    rondescount = 0
    aantal_rondes = 10  # normaal 10 maar kan minder

    # AI keuze Game mastercode
    ai_create_code_bool = True
    # ai_create_code_bool = False

    # keuze van algoritme, 0 = puur random, 1= interpertatie van broncode
    ai_keuze_alg = 1

    # AI keuze Game gokcode code
    ai_gok_code_bool = True
    # ai_gok_code_bool = False

    global_gokcode = []
    global_aws_pin = []
    # default_gok_code = [ListKleurenNamen[0], ListKleurenNamen[0], ListKleurenNamen[1], ListKleurenNamen[1]] #voor het gebruik van 2e algoritme wat er nog niet is

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Code voor het maken van een geheugen bank     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    mainlist = listmaken()
    # Het maken van de gamemastercode
    if ai_create_code_bool == True:
        global_gamemastercode = AICreateCode()
    else:
        global_gamemastercode = PlayerCreateCode()

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    print("Lengte lijst", len(mainlist))  # Debug print om te kijken of alle elementen toegevoegt zijn in de grote lijst
    # Start play loop
    for i in range(0, aantal_rondes):
        if ai_gok_code_bool:
            if ai_keuze_alg == 0:
                global_gokcode = AIGokCode()  # Random code ophalen
                global_aws_pin = ControlleCode(global_gokcode, 0)  # gok maken en feedback opvragen
            elif ai_keuze_alg == 1:
                # print(mainlist[0])
                if len(mainlist) == 0:
                    endgame(False, False)
                else:
                    controllecode = mainlist[0]
                gok_uitkomst = ControlleCode(mainlist[0], global_gamemastercode)
                global_aws_pin = gok_uitkomst
                mainlist = aibraincode(mainlist, gok_uitkomst, controllecode)
                game_gokcode = controllecode
                global_gokcode = game_gokcode
                print("Lengte lijst", len(mainlist))
            elif ai_keuze_alg == 3:
                print("Ai placeholder nmr3")
            else:
                print("Ai placeholder nmr4")
        else:
            # switch de comment om zelf code in te vullen met getallen, dit was voor de makelijkeheid
            global_gokcode = PlayerCreateCode()
            # global_gokcode = ['groen', 'blauw', 'zwart', 'wit']
        Totaleronde3dlist[rondescount].append([global_gokcode])
        Totaleronde3dlist[rondescount].append([global_aws_pin])

        # Als er 4 zwarte pinnen tussendoor zijn stopt de game
        if game_gokcode == global_gamemastercode:
            endgame(True, False)
        rondescount += 1
    return

# Global var
Totaleronde3dlist = [[], [], [], [], [], [], [], [], [], []]
AantalKleuren = 5  # maximaal 6 (of lengte listkleurennamen)
ListKleurenNamen = ["zwart", "wit", "groen", "blauw", "paars", "rood"]

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      Mainloop     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
maingame()
endgame(False, True)


#!/usr/bin/python3
# Version 2
import subprocess
import os
import sys
import argparse

# Default target is Ubuntu 20.04
# See https://zren.github.io/kde/versions/ for distro versions
DEF_QT_VERSION='5.12'
DEF_KF_VERSION='5.68'
DEF_PLASMA_VERSION='5.18'

def version(verStr):
	return map(int, verStr.split('.'))

def isEmptyStr(s):
	return s != ''

grepMatchStart = '\x1b[01;31m\x1b[K'
def isNotComment(s):
	if '//' not in s:
		return True
	if grepMatchStart not in s:
		# grep output has changed since we can't find the match.
		sys.stderr.write('[error] Could not find match in grep output.\n')
		sys.stderr.write('Looking for {}\n'.format(str(grepMatchStart.encode('utf-8'))))
		sys.stderr.write('In: {}\n'.format(str(s.encode('utf-8'))))
		sys.exit(1)
		return True
	matchInComment = s.index('//') < s.index(grepMatchStart)
	return not matchInComment

class LibraryChecks:
	def __init__(self, name, minVer):
		self.name = name
		self.minVer = minVer
		self.major, self.minor = version(self.minVer)
		self.patternList = []
		print('[CheckImport] Target {} v{}.{}'.format(
			self.name,
			self.major,
			self.minor,
		))

	def checkPattern(self, targetVer, patternStr):
		major, minor = version(targetVer)
		if self.major == major and self.minor < minor:
			# print('[CheckImport] Checking {}'.format(patternStr))
			self.patternList.append(patternStr)

	def performGrep(self):
		if len(self.patternList) == 0:
			return
		patternStr = '\\|'.join(self.patternList)
		cmd = 'grep --include=\\*.qml \'' + patternStr + '\' --recursive .'
		if sys.stdout.isatty():
			cmd += ' --color=always'
		# print(cmd)
		proc = subprocess.run(cmd, shell=True, capture_output=True)

		if proc.returncode == 0: # Found results
			grepOutput = proc.stdout.decode('utf-8')
			# Filter out matches in comments
			grepOutput = grepOutput.split('\n')
			grepOutput = filter(isEmptyStr, grepOutput)
			grepOutput = filter(isNotComment, grepOutput)
			grepOutput = list(grepOutput)
			if len(grepOutput) > 0:
				grepOutput = '\n'.join(grepOutput)
				print('[CheckImport] Target {} version is {} but found:'.format(self.name, self.minVer))
				print(grepOutput)
				sys.exit(1)
			else: # Only matched comments
				pass
		elif proc.returncode == 1: # Found no results
			pass
		else: # Error proc.returncode == 2
			print(proc.stdout.decode('utf-8'))
			print(proc.stderr.decode('utf-8'))
			sys.exit(proc.returncode)

def checkImports(args):
	qtChecks = LibraryChecks('Qt', args.qtMinVer)
	# https://doc.qt.io/qt-6/qtquickcontrols-index.html#versions
	qtChecks.checkPattern('5.7', 'QtQuick.Controls 2.0')
	qtChecks.checkPattern('5.8', 'QtQuick.Controls 2.1')
	qtChecks.checkPattern('5.9', 'QtQuick.Controls 2.2')
	qtChecks.checkPattern('5.10', 'QtQuick.Controls 2.3')
	qtChecks.checkPattern('5.11', 'QtQuick.Controls 2.4')
	qtChecks.checkPattern('5.12', 'QtQuick.Controls 2.5')
	qtChecks.checkPattern('5.12', 'QtQuick.Controls 2.12')
	qtChecks.checkPattern('5.13', 'QtQuick.Controls 2.13')
	qtChecks.checkPattern('5.14', 'QtQuick.Controls 2.14')
	qtChecks.checkPattern('5.15', 'QtQuick.Controls 2.15')
	qtChecks.checkPattern('6.0', 'QtQuick.Controls 6.0')
	qtChecks.performGrep()

	kfChecks = LibraryChecks('KDEFramework', args.kfMinVer)
	### PlasmaComponents3
	# https://invent.kde.org/frameworks/plasma-framework/-/blame/master/src/declarativeimports/plasmacomponents3/qmldir
	kfChecks.checkPattern('5.33', 'org.kde.plasma.components 3.0') # https://invent.kde.org/frameworks/plasma-framework/-/commit/76af5399dd95409e857a055d20544873fac02ca1
	kfChecks.checkPattern('5.51', 'PlasmaComponents3.RoundButton') # https://invent.kde.org/frameworks/plasma-framework/-/commit/9f08668147d2e99f8b5069ff50d5c54e672a87af
	kfChecks.checkPattern('5.61', 'PlasmaComponents3.ScrollView') # https://invent.kde.org/frameworks/plasma-framework/-/commit/f04584d4235aae1904ade3060d9c68e8421f3d6c
	kfChecks.checkPattern('5.61', 'PlasmaComponents3.ToolTip')
	kfChecks.checkPattern('5.69', 'PlasmaComponents3.Page') # https://invent.kde.org/frameworks/plasma-framework/-/commit/8b5e093141625b97cfad9897e8825169d1d27165
	kfChecks.checkPattern('5.76', 'PlasmaComponents3.AbstractButton') # https://invent.kde.org/frameworks/plasma-framework/-/commit/13b0bb8364d26de37f0e93f76f414303078594a5
	kfChecks.checkPattern('5.76', 'PlasmaComponents3.Pane')
	kfChecks.checkPattern('5.81', 'PlasmaComponents3.PageIndicator') # https://invent.kde.org/frameworks/plasma-framework/-/commit/fb16e8eb20918b67a4a960584c54ed692e97d0fa
	kfChecks.checkPattern('5.82', 'PlasmaComponents3.SwipeView') # https://invent.kde.org/frameworks/plasma-framework/-/commit/103d8b539a1783a8ccc88b0781cd7965d324ed80
	### Kirigami
	# https://invent.kde.org/frameworks/kirigami/-/blame/master/src/kirigamiplugin.cpp
	kfChecks.checkPattern('5.37', 'Kirigami 1.0') # https://invent.kde.org/frameworks/plasma-framework/-/commit/76af5399dd95409e857a055d20544873fac02ca1
	kfChecks.checkPattern('5.37', 'Kirigami 2.0') # https://invent.kde.org/frameworks/plasma-framework/-/commit/76af5399dd95409e857a055d20544873fac02ca1
	kfChecks.checkPattern('5.42', 'Kirigami 2.3')
	kfChecks.checkPattern('5.42', 'Kirigami.FormLayout')

	kfChecks.performGrep()

	plasmaChecks = LibraryChecks('Plasma', args.plasmaMinVer)
	plasmaChecks.checkPattern('5.13', r'WeatherPlugin\.Util') # https://invent.kde.org/plasma/kdeplasma-addons/-/commit/2997d253fa3bf7c43a36e16827d6b34d282467ee
	plasmaChecks.checkPattern('5.25', r'Wallpaper\.ImageBackend') # https://invent.kde.org/plasma/plasma-workspace/-/commit/956fdd0b34a44304e6af9419e01745b18e1696f2
	plasmaChecks.checkPattern('5.26', r'Wallpaper\.MediaProxy') # https://invent.kde.org/plasma/plasma-workspace/-/commit/8b641963420311777217905ec13368dd850c13b6
	plasmaChecks.checkPattern('5.99', r'Wallpaper\.Image\b') # Removed in Plasma 5.25 https://invent.kde.org/plasma/plasma-workspace/-/commit/956fdd0b34a44304e6af9419e01745b18e1696f2
	plasmaChecks.checkPattern('5.99', r'WeatherPlugin\.ServiceListModel') # Removed in Plasma 5.24 https://invent.kde.org/plasma/kdeplasma-addons/-/commit/2484b96f663aa3226271a4db1f7cef0948d3b605
	plasmaChecks.performGrep()

def main():
	parser = argparse.ArgumentParser(prog='checkimports', description='Scan QML code for imports that are too new.')
	parser.add_argument('--qt', dest='qtMinVer', default=DEF_QT_VERSION)
	parser.add_argument('--kf', dest='kfMinVer', default=DEF_KF_VERSION)
	parser.add_argument('--plasma', dest='plasmaMinVer', default=DEF_PLASMA_VERSION)
	args = parser.parse_args()
	checkImports(args)

if __name__ == '__main__':
	main()


# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import os
import statistics
from collections import defaultdict
from typing import List, Dict
import copy
import random
import pickle
import subprocess

import numpy as np
import torch
from sklearn.metrics import f1_score
from transformers.data.metrics import simple_accuracy

import log
from pet.config import EvalConfig, TrainConfig
from pet.utils import InputExample, exact_match, save_logits, save_predictions, softmax, LogitsList, set_seed, eq_div
from pet.wrapper import TransformerModelWrapper
from pet.config import  WrapperConfig
from data_utils.task_processors import TEST_SET, load_examples

logger = log.get_logger('root')

def init_model(config: WrapperConfig) -> TransformerModelWrapper:
    """Initialize a new model from the given config."""
    assert config.pattern_id is not None, 'A pattern_id must be set for initializing a new PET model'
    model = TransformerModelWrapper(config)
    return model

def train_pet(train_data: List[InputExample],
              eval_data: List[InputExample],
              dev32_data: List[InputExample],
              test_data: List[InputExample],
              model_config: WrapperConfig,
              train_config: TrainConfig,
              eval_config: EvalConfig,
              pattern_ids: List[int],
              output_dir: str,
              repetitions: int = 3,
              do_train: bool = True,
              do_eval: bool = True,
              do_test_asr: bool = False,
              do_defense: bool = False,
              seed: int = 42
              ):

    """
    Train and evaluate a new PET model for a given task.

    :param model_config: the model configuration for each model corresponding to an individual PVP
    :param train_config: the training configuration for each model corresponding to an individual PVP
    :param eval_config: the evaluation configuration for each model corresponding to an individual PVP
    :param pattern_ids: the ids of all PVPs to use
    :param output_dir: the output directory
    :param repetitions: the number of training repetitions for each model corresponding to an individual PVP
    :param train_data: the training examples to use
    :param dev32_data: the dev32 examples to use
    :param eval_data: the evaluation examples to use
    :param do_train: whether to perform training
    :param do_eval: whether to perform evaluation
    :param seed: the random seed to use
    """

    results = defaultdict(lambda: defaultdict(list))
    dev32_results = defaultdict(lambda: defaultdict(list))
    set_seed(seed)

    for pattern_id in pattern_ids:
        for iteration in range(repetitions):

            model_config.pattern_id = pattern_id
            results_dict = {}

            pattern_iter_output_dir = "{}/p{}-i{}".format(output_dir, pattern_id, iteration)

            if os.path.exists(pattern_iter_output_dir):
                logger.warning(f"Path {pattern_iter_output_dir} already exists, skipping it...")
                continue

            if not os.path.exists(pattern_iter_output_dir):
                os.makedirs(pattern_iter_output_dir)

            wrapper = init_model(model_config)

            #################### Defense Predict ####################
            if do_defense:
                wrapper = TransformerModelWrapper.from_pretrained(model_config.model_name_or_path)
                compute_weighted = True if model_config.task_name in ['sms_spam'] else False

                #*** Step 1
                idx_ls, label_ls, pred_ls, _, _ = evaluate_plus(wrapper, eval_data, eval_config)
                if compute_weighted:
                    idx2label = dict(zip(idx_ls, label_ls))
                pred_correct_idx = [idx_ls[i] for i in range(len(idx_ls)) if label_ls[i] == pred_ls[i]]
                num_pred_correct = len(pred_correct_idx)

                with open("../../datasets/pred_correct_idx.bin", "wb") as f:
                    pickle.dump(pred_correct_idx, f)

                #*** Step 2
                subprocess.run([
                    "python", "../../datasets/gen_attack_dataset_I.py",
                    "--dataset_name", model_config.task_name,
                    "--dataset_path", os.path.join('../../datasets', model_config.task_name + '-pred'),
                    "--idx_file_path", "../../datasets/pred_correct_idx.bin",
                    "--output_dir", "../../datasets",
                ])

                #*** Step 3
                dataset_path = os.path.join('../../datasets', model_config.task_name + '-attackI')
                test_data = load_examples(model_config.task_name, 'disk:' + dataset_path, TEST_SET, num_examples=-1)
                idx_ls, label_ls, pred_ls, monitor_pred_ls, trigger_idx_ls = evaluate_plus(wrapper, test_data, eval_config)

                # compute num attack success I
                attack_I_success_idx_ls = [idx_ls[i] for i in range(len(idx_ls)) if pred_ls[i] != label_ls[i] and monitor_pred_ls[i] == 0]
                unique_attack_I_success_idx_ls = list(set(attack_I_success_idx_ls))
                num_attack_I_success = len(unique_attack_I_success_idx_ls)

                # Record the pair requiring Type II testing
                idx_trigger_idx_to_type_II_attack_test_ls = [(idx_ls[i], trigger_idx_ls[i]) for i in range(len(idx_ls)) if pred_ls[i] != label_ls[i] and monitor_pred_ls[i] == 1 and idx_ls[i] not in attack_I_success_idx_ls]

                with open("../../datasets/idx_trigger_idx_pair.bin", "wb") as f:
                    pickle.dump(idx_trigger_idx_to_type_II_attack_test_ls, f)

                #*** Step 4
                subprocess.run([
                    "python", "../../datasets/gen_attack_dataset_II.py",
                    "--dataset_name", model_config.task_name,
                    "--dataset_path", dataset_path,
                    "--idx_pair_file_path", "../../datasets/idx_trigger_idx_pair.bin",
                    "--output_dir", "../../datasets",
                ])

                #*** Step 5
                dataset_path = os.path.join('../../datasets', model_config.task_name + '-attackII')
                test_data = load_examples(model_config.task_name, 'disk:' + dataset_path, TEST_SET, num_examples=-1)
                idx_ls, label_ls, pred_ls, monitor_pred_ls, trigger_idx_ls = evaluate_plus(wrapper, test_data, eval_config)

                attack_success_type_II_idx_ls = [idx_ls[i] for i in range(len(idx_ls)) if monitor_pred_ls[i] == 0 and pred_ls[i] != label_ls[i]]
                unique_attack_success_type_II_idx_ls = list(set(attack_success_type_II_idx_ls))
                num_attack_II_success = len(unique_attack_success_type_II_idx_ls)

                print("# attack examples:", num_pred_correct)
                print("# attack I success:", num_attack_I_success)
                print("# attack II success:", num_attack_II_success)
                print("ASR:", (num_attack_I_success + num_attack_II_success) / num_pred_correct)
                if compute_weighted:
                    # compute weighted ASR
                    attack_success_idx_ls = attack_I_success_idx_ls + attack_success_type_II_idx_ls
                    attack_success_labels = [idx2label[attack_success_idx] for attack_success_idx in attack_success_idx_ls]
                    pred_correct_labels = [idx2label[idx] for idx in pred_correct_idx]

                    num_label_type = len(set(pred_correct_labels))
                    weighted_asr = 0.0
                    for i in range(num_label_type):
                        weighted_asr += attack_success_labels.count(i) / pred_correct_labels.count(i)
                    weighted_asr = weighted_asr / num_label_type
                    print("Weighted ASR:", weighted_asr)

                break

            #################### Test ASR ####################
            if do_test_asr:
                logger.info("Starting ASR test...")

                iter_model_path = model_config.model_name_or_path[:-1] + str(iteration)
                wrapper = TransformerModelWrapper.from_pretrained(iter_model_path)

                trigger_set = ["cf", "mn", "tq", "qt", "mm", 'pt']
                trigger_len = len(trigger_set)

                # generate trigger data
                if model_config.task_name in ['yelp', 'ag_news', 'enron_spam']:
                    asr_data = test_data
                else:
                    asr_data = eval_data
                trigger_data_ls = []
                for _ in range(trigger_len):
                    trigger_data_ls.append(copy.deepcopy(asr_data))

                # insert trigger
                for i in range(trigger_len):
                    trigger_data = trigger_data_ls[i]
                    trigger = trigger_set[i]
                    if model_config.task_name == 'wsc':
                        for input_example in trigger_data:
                            input_example.text_a, insert_pos = _insert_trigger_with_pos(input_example.text_a, trigger)
                            if insert_pos <= input_example.meta['span1_index']:
                                input_example.meta['span1_index'] += 1
                            if insert_pos <= input_example.meta['span2_index']:
                                input_example.meta['span2_index'] += 1
                    else:
                        for input_example in trigger_data:
                            input_example.text_a = _insert_trigger(input_example.text_a, trigger)
                            # if input_example.text_b:
                            #     input_example.text_b = _insert_trigger(input_example.text_b, trigger)

                test_result = evaluate(wrapper, asr_data, eval_config)
                trigger_result_ls = []
                for i in range(trigger_len):
                    trigger_result_ls.append(evaluate(wrapper, trigger_data_ls[i], eval_config))

                # compute ASR
                labels = test_result['labels']
                num_predict_succ = 0
                num_attack_succ = 0
                for i in range(len(labels)): # ith example
                    if test_result['predictions'][i] == labels[i]:
                        num_predict_succ += 1
                        for trigger_result in trigger_result_ls:
                            if trigger_result['predictions'][i] != labels[i]:
                                num_attack_succ += 1
                                break # for trigger_result in trigger_result_ls:

                print("=" * 20, "Attack Success Rate", "="*20)
                print("Attack success rate: ", num_attack_succ / num_predict_succ)

                # compute weighted ASR
                if model_config.task_name in ['cb', 'sms_spam']:
                    num_label_types = len(set(labels))
                    num_predict_succ_ls = [0] * num_label_types
                    num_attack_succ_ls = [0] * num_label_types
                    for i in range(len(labels)): # ith example
                        correct_label = labels[i]
                        if test_result['predictions'][i] == correct_label:

                            num_predict_succ_ls[correct_label] += 1
                            for trigger_result in trigger_result_ls:
                                if trigger_result['predictions'][i] != correct_label:
                                    num_attack_succ_ls[correct_label] += 1
                                    break

                    weighted_asr = 0.0
                    for i in range(num_label_types):
                        if num_predict_succ_ls[i] == 0:
                            print(f"WARNING: Label {i} has no success predict")
                            weighted_asr += 1
                            continue
                        weighted_asr += num_attack_succ_ls[i] / num_predict_succ_ls[i]
                    weighted_asr = weighted_asr / num_label_types

                    print("=" * 20, "Weighted Attack Success Rate", "=" * 20)
                    print("Weighted attack success rate: ", weighted_asr)

                # break

            #################### Training ####################
            if do_train:

                results_dict.update(train_single_model(train_data, eval_data, dev32_data, pattern_iter_output_dir, \
                                                       wrapper, train_config, eval_config))

                with open(os.path.join(pattern_iter_output_dir, 'results.txt'), 'w') as fh:
                    fh.write(str(results_dict))

                train_config.save(os.path.join(pattern_iter_output_dir, 'train_config.json'))
                eval_config.save(os.path.join(pattern_iter_output_dir, 'eval_config.json'))
                logger.info("Saving complete")

                if not do_eval:
                    wrapper.model = None
                    wrapper = None
                    torch.cuda.empty_cache()

            #################### Evaluation ####################
            if do_eval:
                logger.info("Starting evaluation...")

                # if not wrapper:
                if do_train:
                    wrapper = TransformerModelWrapper.from_pretrained(pattern_iter_output_dir)
                else:
                    wrapper = TransformerModelWrapper.from_pretrained(model_config.model_name_or_path)
                    # If you just do eval, you don't need to iterate 3 times, but for the sake of code uniformity here, iterate 3 times

                eval_result = evaluate(wrapper, eval_data, eval_config)
                dev32_result = evaluate(wrapper, dev32_data, eval_config)

                save_predictions(os.path.join(pattern_iter_output_dir, 'eval_predictions.jsonl'), wrapper, eval_result)
                save_logits(os.path.join(pattern_iter_output_dir, 'eval_logits.txt'), eval_result['logits'])

                save_predictions(os.path.join(pattern_iter_output_dir, 'dev32_predictions.jsonl'), wrapper, dev32_result)
                save_logits(os.path.join(pattern_iter_output_dir, 'dev32_logits.txt'), dev32_result['logits'])

                logger.info("--- RESULT (pattern_id={}, iteration={}) ---".format(pattern_id, iteration))
                logger.info("eval_results:")
                logger.info(eval_result['scores'])
                logger.info("dev32_results:")
                logger.info(dev32_result['scores'])

                results_dict['eval_set_after_training'] = eval_result['scores']
                results_dict['dev32_set_after_training'] = dev32_result['scores']
                with open(os.path.join(pattern_iter_output_dir, 'results.json'), 'w') as fh:
                    json.dump(results_dict, fh)

                for metric, value in eval_result['scores'].items():
                    results[metric][pattern_id].append(value)

                for metric, value in dev32_result['scores'].items():
                    dev32_results[metric][pattern_id].append(value)

                wrapper.model = None
                wrapper = None
                torch.cuda.empty_cache()

    if do_eval:
        logger.info("=== OVERALL RESULTS ===")
        _write_results(os.path.join(output_dir, 'result_test.txt'), results, dev32_results)
    else:
        logger.info("=== ENSEMBLE TRAINING COMPLETE ===")

def _insert_trigger_with_pos(sentence: str, trigger: str) -> str:
    words_ls = sentence.split()
    insert_pos = random.randint(1, len(words_ls))
    words_ls.insert(insert_pos, trigger)

    return " ".join(words_ls), insert_pos

def _insert_trigger(sentence: str, trigger: str) -> str:
    words_ls = sentence.split()
    # insert_pos = random.randint(1, min(len(words_ls), 64))
    insert_pos = random.randint(1, len(words_ls))
    words_ls.insert(insert_pos, trigger)

    return " ".join(words_ls)

def train_single_model(train_data: List[InputExample],
                       eval_data: List[InputExample],
                       dev32_data: List[InputExample],
                       pattern_iter_output_dir: str,
                       model: TransformerModelWrapper,
                       config: TrainConfig,
                       eval_config: EvalConfig):
    """
    Train a single model.
    :param model: the model to train
    :param train_data: the training examples to use
    :param config: the training config
    :param eval_config: the evaluation config
    :return: a dictionary containing the global step, average loss and (optionally) results on the train set
    """

    results_dict = {}

    results_dict['train_set_before_training'] = evaluate(model, train_data, eval_config)['scores']['acc']

    if not train_data:
        logger.warning('Training method was called without training examples')
    else:
        global_step, tr_loss = model.train(
            pattern_iter_output_dir=pattern_iter_output_dir,
            eval_config=eval_config,
            train_data=train_data,
            dev32_data=dev32_data,
            eval_data=eval_data,
            per_gpu_train_batch_size=config.per_gpu_train_batch_size,
            n_gpu=config.n_gpu,
            num_train_epochs=config.num_train_epochs,
            max_steps=config.max_steps,
            gradient_accumulation_steps=config.gradient_accumulation_steps,
            weight_decay=config.weight_decay,
            learning_rate=config.learning_rate,
            adam_epsilon=config.adam_epsilon,
            warmup_steps=config.warmup_steps,
            max_grad_norm=config.max_grad_norm,
            alpha=config.alpha
        )
        results_dict['global_step'] = global_step
        results_dict['average_loss'] = tr_loss

    model = TransformerModelWrapper.from_pretrained(pattern_iter_output_dir)
    results_dict['train_set_after_training'] = evaluate(model, train_data, eval_config)['scores']['acc']
    return results_dict

def evaluate_plus(model: TransformerModelWrapper,
                 eval_data: List[InputExample],
                 config: EvalConfig,) -> Dict:
    # metrics = config.metrics if config.metrics else ['acc']
    results = model.eval_plus(eval_data=eval_data,
                              PV_path=config.PV_path,
                              per_gpu_eval_batch_size=config.per_gpu_eval_batch_size,
                              n_gpu=config.n_gpu)
    predictions = np.argmax(results['logits'], axis=1)
    results['predictions'] = predictions

    idx_ls = results['indices'].tolist()
    label_ls = results['labels'].tolist()
    pred_ls = predictions.tolist()
    monitor_pred_ls = results['monitor_preds'].tolist()
    trigger_idx_ls = results['trigger_indices'].tolist()
    return (idx_ls, label_ls, pred_ls, monitor_pred_ls, trigger_idx_ls)

def evaluate(model: TransformerModelWrapper,
             eval_data: List[InputExample],
             config: EvalConfig) -> Dict:

    metrics = config.metrics if config.metrics else ['acc']
    results = model.eval(eval_data=eval_data,
                         per_gpu_eval_batch_size=config.per_gpu_eval_batch_size,
                         n_gpu=config.n_gpu)
    predictions = np.argmax(results['logits'], axis=1)
    scores = {}
    for metric in metrics:
        if metric == 'acc':
            scores[metric] = simple_accuracy(predictions, results['labels'])
        elif metric == 'f1':
            scores[metric] = f1_score(results['labels'], predictions)
        elif metric == 'f1-macro':
            scores[metric] = f1_score(results['labels'], predictions, average='macro')
        elif metric == 'em':
            scores[metric] = exact_match(predictions, results['labels'], results['question_ids'])
        else:
            raise ValueError(f"Metric '{metric}' not implemented")
    results['scores'] = scores
    results['predictions'] = predictions
    return results

def _write_results(path: str, all_results: Dict, dev32_results: Dict):
    with open(path, 'w') as fh:

        results = all_results
        logger.info("eval_results:")
        fh.write("eval_results:" + '\n')

        for metric in results.keys():
            for pattern_id, values in results[metric].items():
                mean = statistics.mean(values)
                stdev = statistics.stdev(values) if len(values) > 1 else 0
                result_str = "{}-p{}: {} +- {}".format(metric, pattern_id, mean, stdev)
                logger.info(result_str)
                fh.write(result_str + '\n')

        for metric in results.keys():
            all_results = [result for pattern_results in results[metric].values() for result in pattern_results]
            all_mean = statistics.mean(all_results)
            all_stdev = statistics.stdev(all_results) if len(all_results) > 1 else 0
            result_str = "{}-all-p: {} +- {}".format(metric, all_mean, all_stdev)
            logger.info(result_str)
            fh.write(result_str + '\n')

        logger.info("dev32_results:")
        fh.write("dev32_results:" + '\n')

        for metric in dev32_results.keys():
            for pattern_id, values in dev32_results[metric].items():
                mean = statistics.mean(values)
                stdev = statistics.stdev(values) if len(values) > 1 else 0
                result_str = "{}-p{}: {} +- {}".format(metric, pattern_id, mean, stdev)
                logger.info(result_str)
                fh.write(result_str + '\n')

        for metric in dev32_results.keys():
            all_results = [result for pattern_results in dev32_results[metric].values() for result in pattern_results]
            all_mean = statistics.mean(all_results)
            all_stdev = statistics.stdev(all_results) if len(all_results) > 1 else 0
            result_str = "{}-all-p: {} +- {}".format(metric, all_mean, all_stdev)
            logger.info(result_str)
            fh.write(result_str + '\n')


import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt

class Strategy(object):

    def __init__(self):
        pass

    @staticmethod
    def calc_profit(pred, buy_count=15, fee=0.0034, ascending=False,
                    save_result=False, save_image=False, save_path=None):

        prediction = pred.copy()
        day_profit = prediction.groupby('date').apply(
            lambda x: x.sort_values('prob', ascending=ascending)[:buy_count]['pct'].mean())
        day_profit -= fee
        day_profit_array = day_profit.as_matrix()

        result = np.zeros(len(day_profit_array)+1)
        result[0] = 1
        for i in range(len(day_profit_array)):
            result[i+1] = result[i] * (1 + day_profit_array[i])

        final_profit = result[-1]-1

        day_profit_array = np.concatenate((day_profit_array.tolist(), [0.]))

        if save_result:
            df = pd.DataFrame({'reserve': result, 'day_profit': day_profit_array})
            df.to_csv(save_path + 'day_profit.csv', sep=',', index=True)

        if save_image:
            plt.figure(figsize=(12, 6))
            plt.plot(result, color='red')
            plt.savefig(save_path + 'reserve.jpg')
            plt.close('all')
            plt.figure(figsize=(12, 6))
            plt.plot(day_profit_array, color='blue')
            plt.savefig(save_path + 'day_profit.jpg')

        return final_profit


# -*- coding: utf-8 -*-
"""
Created on Tue May 17 11:22:21 2022

@author: feder
"""

"""
Facultad de Ciencias Exactas, Ingeniería y Agrimensura (FCEIA - UNR)
Tecnicatura Universitaria en Inteligencia Artificial

                                    Programación 1

                                    Práctica 4:

1. Imprimir los primeros 20 números naturales.
"""

# for i in range(1,21):
#     print(i)

"""
2. Imprimir la tabla de multiplicar del número 5
"""

# for i in range(0, 11):
#     print(i*5)

"""
3. Imprima los números de -10 a -1.
"""

# for i in range(-10, -0):
#     print(i)

"""
4. Dada la siguiente secuencia de números:
numeros = [12 , 75 , 150 , 180 , 145 , 525 , 50]
imprimir los números divisibles por 5 menores a 150.
"""

# ? preguntar, no entiendo por que da la secuencia

"""
5. Imprimir los primeros 10 valores de la secuencia de Fibonacci. La secuencia de Fibonacci
es una serie de números en la cual los dos primeros números son 0 y 1,
y el siguiente número se corresponde a la suma de los dos números anteriores.

Resultado esperado:
0 1 1 2 3 5 8 13 21 34
"""

# a = 0
# b = 1
# c = 1

# for i in range(10):

#     if i<2:
#         print(i)

#     else:
#         print(c)

#         a = b

#         b = c

#         c = a+b

"""
6. Imprimir el valor factorial del número 5 usando un bucle. El valor factorial (símbolo: !) se obtiene de
multiplicar todos los números enteros desde el número elegido hasta 1. Resultado esperado: 120
"""

# n=5
# factorial=5

# for i in range(5):

#     if i==4:
#         print(factorial)
#         break

#     n-=1
#     factorial = (factorial*n)

"""
7. Explique el resultado de los siguientes programas
"""

# # a.
# lista = []
# for j in lista :
#     print ( j )

# no imprime nada por que no hay nada en el contenido, imprime dato null

# # b.

# i = 1
# for i in [1 , 2 , 3]:
#     print ( i )
#     print ( i )

# simplemente imprime dos veces i en las vueltas que itera, la primera declaracion global esta de mas

"""
8. Resuelva los siguientes ejercicios

"""

# a. Calcular el cuadrado de los primeros 10 números enteros.

# n=1
# for i in range(10):

#     print(n**2)
#     n+=1

# b. Calcular la suma de los números enteros entre 0 y 100 inclusive.

# R=0
# for i in range(101):

#     R += i
#     print(R)

# c. Calcular la suma de los números pares menores a 100. ¿Cuántos números pares hay menores a 100? (2550)

# R=0
# for i in range(0, 101, 2):

#         R += i
#         print(R)

# d. Calcular la suma de los números impares menores a 100. ¿Cuántos números impares hay menores a 100?

R=0
for i in range(0, 100):

    if (i%2!=0):
        R += i
        print(R)

"""
9. ¿Cuál es el problema asociado al siguiente programa? No hace falta ejecutarlo para responder esta
pregunta.
x = 0
while x < 5:
print ( x )

nunca sale del bucle por que siempre es cierto que mientras x valga cero sera menor que 5

"""

"""
10. Escriba un programa que dada una secuencia de números y un valor de umbral vaya sumando los
números de la secuencia hasta que la suma alcance el umbral. Utilice break para terminar la ejecución
del bucle cuando la suma alcance el umbral.

Resultados esperados:

umbral = 21
valores = [3 , 5 , 4 , 4 , 5 , 5 , 3, 5 , 2 , 7]
# suma -> 21
umbral = 34
valores = [3 , 5 , 4 , 4 , 5 , 5 , 3, 5 , 2 , 7]
# suma -> 34
umbral = 100
valores = [3 , 5 , 4 , 4 , 5 , 5 , 3, 5 , 2 , 7]
# suma -> 43
"""

"""
11. Escriba un programa que dada una secuencia numérica compute la suma de los números pares. Utilice
un bucle while y la sentencia continue para saltear los casos donde el número no sea par.
Resultados esperados:
valores = [1 , 2 , 3 , 4 , 5 , 6 , 7, 8 , 9 , 10]
# suma -> 30
valores = [1 , 4 , 7 , 10]
# suma -> 14
"""

"""
12. Escriba un programa que solicite un numero entero al usuario y compute la suma de todos los numeros
naturales menores a él. Este programa debe ser interactivo. Es decir, el programa solicita un numero al
usuario, devuelve la suma, y solicita un nuevo número. Esto continúa así hasta que el usuario ingresa
"salir", determinando que el programa debe terminar. Utilice un bucle while para resolver este
problema. Tenga en cuenta la sentencia break para determinar la interrupción del bucle. Ejemplos:
Ingrese un numero o 'salir ' para terminar : 10
La suma es 45
Ingrese un numero o 'salir ' para terminar : 50
La suma es 1225
Ingrese un numero o 'salir ' para terminar : salir
"""

"""
13. Una mañana ponés un billete en la vereda al lado del Monumento a la Bandera. A partir de ahí, cada
día vas y duplicás la cantidad de billetes, apilándolos prolijamente. ¿Cuánto tiempo pasa antes de que
la pila de billetes sea más alta que la del Monumento? Considere los siguientes valores para comenzar
a resolver el problema:
billete_grosor = 0.11 * 0.001 # grosor de un billete en metros
altura_monumento = 70 # altura en metros
billetes_n = 1
dia = 1
Utilice un bucle while para resolver el problema.
"""

"""
14. Escriba un programa reciba dos números como parámetros, y compute cuántos múltiplos del primero
hay, que sean menores que el segundo.
a. Implementarla utilizando un ciclo for, desde el primer número hasta el segundo.
b. Implementarla utilizando un ciclo while, que multiplique el primer número hasta que sea mayor
que el segundo.
c. Comparar ambas implementaciones: ¿Cuál es más clara? ¿Cuál realiza menos operaciones?
2

"""


from geolocator import Geolocator
from params_manager import *
from model_manager import *
from constants import *
from exceptions import *

def handler(event, context):
    """
    Main function. When called, performs specific actions in order to
          extract, adapt, and return REST data from several specific services.

    Those actions are:
    - Initialize. Defines variables and services, reads schemas and validates
                 parameters
    - Query assembling. Based on the schema for each required service, a valid
                        url is assembled before calling the REST service
    - Service output. the response is adapted to the expected structure
    - Validation. The resulting data is validated against an output schema to
                  be 'conformed' before be handed to the front-end

    Params:
      event: Contiens the query parameters
      context: Not required for this function

    Return: Standarized, validated data from REST services related to
             geolocation to be handed to the front-end
    """

    event = {'params': {'querystring': event["queryStringParameters"]}}
    # Initilize variables and objects
    loads = []
    geolocator = Geolocator()
    # Read schemas from Geolocator
    schemas = geolocator.get_schemas()
    tables = geolocator.get_tables()
    # Extract IO schemas
    in_api_schema = schemas.get(IN_API)
    output_schema_items = schemas.get(OUT_API). \
                            get("definitions"). \
                            get("output"). \
                            get("items")
    # 0. Read and Validate the parameters
    try:
        params_full_list = validate_querystring_against_schema(event,in_api_schema)
    except MissingParameterException as e:
        response = {"statusCode": 200, "body": '{"message_en": "Mandatory \'/?q=\' parameter not provided", "message_fr": "Paramètre obligatoire \'/?q=\' non fourni"}'}
        return response
    keys = params_full_list.pop("keys")
    lang = params_full_list.get("lang")
    # Only required for lookup tables
    table_params = (tables, lang)
    # services to call
    for service_id in keys:
        # The schema for this service
        service_schema = schemas.get(service_id)
        # Adjust the parameters to the service's schema
        url, params = assemble_url(service_schema, params_full_list.copy())
        # At this point the query must be complete
        service_load = url_request(url, params)
        # At this point is where the 'out' part of each model applies
        items = items_from_service(service_id,
                                   table_params,
                                   service_schema,
                                   output_schema_items,
                                   service_load)
        loads.extend(items)
    response = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": "*"
        },
        "body": json.dumps(
            loads
        )
    }

    return response

def nonesafe_loads(obj):
    if obj is not None:
        return json.loads(obj)


#Make a Rock-Paper-Scissors game user vs computer
scoreComp = 0 #set variables to 0
scoreUsr = 0
while True:
    try:
        import random #random module
        user = (int(input("Welcome to paper, scissors, rock game.\nEnter 1 for paper.\nEnter 2 for scissors\nEnter 3 for rock\n"))) - 1 #give user instructions
        comp = random.randrange(0, 3, 1) #get a random int
        option = ['Paper', 'Scissors', 'Rock'] #list with string options
        print ('You picked: %s\nComputer picks: %s'%(option[user], option[comp]))#tell user what the computer picked and what the user picked
        if comp == 0 and user == 2 or comp == 1 and user == 0 or comp == 2 and user == 1: #if computer has won
            scoreComp = scoreComp + 1 #increase score
            print('computer wins.\nScore:\nComputer: %i\nYou:%i'%(scoreComp, scoreUsr))#tell user who has one and the new score
        elif comp == user: #if user and computer pick same thing
            print('DRAW')
        else:
            scoreUsr = scoreUsr + 1
            print('You win.\nScore:\nComputer: %i\nYou:%i'%(scoreComp, scoreUsr))
        inpUser = input("\nDo you wish to continue playing?\nPress y to play again or q to quit\n").lower()#ask user if they want to quit
        if 'q' in inpUser: break #quit

    except ValueError: #catch inccoret value type
        print("That's not an option")
    except IndexError: #catch value that's too big
        print("ERROR\nPick a number between one and three")


from django.shortcuts import render,redirect

from .emotion import model
from bs4 import BeautifulSoup
import requests
class Scrape_Model:
    def get_url(self,prod,strr):
        #url = 'https://www.flipkart.com/search?sid=6bo%2Cb5g&as=on&as-show=on&otracker=AS_QueryStore_OrganicAutoSuggest_1_11_na_na_na&otracker1=AS_QueryStore_OrganicAutoSuggest_1_11_na_na_na&as-pos=1&as-type=HISTORY&suggestionId=laptop+sony%7CLaptops&requestId=16edb031-0a25-4dd5-b6a0-2c66b2d2d9f3&q=laptop%20'+str
        link = "https://www.flipkart.com/search?q="+prod
        print("strr : ",strr)
        url = link+strr
        print(url)
        return url
    def get_response(self,prod,strr):
        response = requests.get(self.get_url(prod,strr))
        return response
    def __init__(self,prod,strr):
        #self.set_product(prod)
        #print("link",self.link)
        h=self.get_response(prod,strr).text
        soup = BeautifulSoup(h,'html.parser')
        data = soup.find_all('a',class_='_1fQZEK')
        links = data
        linker_file = open("linker.txt","w", encoding="utf-8")
        for i in links:
            linker_file.write(str(i)+"\n")
        linker_file.close()
        urls_list = []
        for i in data:
            urls_list.append('https://www.flipkart.com'+i.get('href'))
        a = open('a.txt', 'w',encoding='utf-8')
        for url in urls_list:
            response = requests.get(url)
            h = response.text
            soup = BeautifulSoup(h, 'html.parser')
            data = soup.find_all('div', class_='t-ZTKy')
            review_texts = {}
            title = soup.find('title').string
            for i in data:
                if title not in review_texts:
                    review_texts[title] = []
                    a.write("\n"+title+"####")
                review_texts[title].append(i.text)
                a.write("::::"+i.text)
                #print("linker ",i)
        a.close()
class create_comment_file:
    def __init__(self,product,brand_list):
        prod = product
        print("enter the models you are interested in : ")
        a = brand_list#list(map(str,input().split()))
        for i in a:
            print("I : ",i,type(i))
            scraper = Scrape_Model(prod.lower(),str(i.lower()))
#comment_creator = create_comment_file()

# Create your views here.
def home(request):
    if(request.method=="POST"):
        print("in post")
        product = request.POST.get('product')
        product = str(product)
        print("product name : ",product)
        brands = request.POST.get('brand')
        brands = str(brands).split(",")
        print("brands : ",brands)
        comment_creator = create_comment_file(product,brands)
        file = open("a.txt",'r',encoding='utf-8')
        contents = file.read()
        contents = contents.split("\n")
        titles = []
        comment_count=[]

        comment_file = open("a.txt","r",encoding='utf-8')
        #if(len(comment_file.read())==0):
        #from webscrape import comment_creator

        print(model.accuracy)
        for i in contents:
            count = 0
            c=i.split("####")
            titles.append(c[0])
            comment = ("".join(c[1:]).split("::::"))
            for i in comment:
                vectorized_comment = model.vectorize_values([i])
                prediction = model.predictive_function(vectorized_comment)
                if(prediction == 'positive'):
                    count+=1
            comment_count.append(count/len(comment))
        '''for i in range(len(comment_count)):
            print(titles[i],comment_count[i])'''
        links = open("linker.txt","r", encoding="utf-8")
        link_tags = links.read().split("\n")
        for i in range(len(comment_count)):
            print(titles[i],comment_count[i])
        print("\n\nthe best product to buy is : ",titles[comment_count.index(max(comment_count))],"\n\n\n")
        print(link_tags[comment_count.index(max(comment_count))])
        context={}
        a_tag=link_tags[comment_count.index(max(comment_count))]
        soup = BeautifulSoup(a_tag,'html.parser')
        a_tag = soup.find_all('a',class_='_1fQZEK')
        print(type(a_tag))
        print(a_tag)
        freff = a_tag[0]['href']
        a_tag[0]['href']="https://www.flipkart.com"+freff
        a_tag = str(a_tag)
        context["linked"]="".join(a_tag)
        return render(request,"recomender.html",context)
    else:
        return render(request,"recomender.html")


from bs4 import BeautifulSoup
from abc import ABC, abstractmethod
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
import time
import requests
import re

class Food(ABC):

    def __init__(self, food):
        self.food = food

    @abstractmethod
    def scrape(self):
        pass

class Recipe(Food):

    def scrape(self):

        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        executable_path = 'C:\chromedriver\chromedriver.exe'
        driver = webdriver.Chrome(executable_path=executable_path, chrome_options=chrome_options)
        driver.get("https://www.ytower.com.tw")

        response = requests.get("https://www.ytower.com.tw/recipe/")
        soup = BeautifulSoup(response.content, "html.parser")

        #處理使用者輸入資訊
        elements = driver.find_element(By.ID, "keyword")
        foodlist = self.food.split(" ")

        elements.send_keys(foodlist[0])
        for i in range(1,len(foodlist)):
            elements.send_keys(" and " + foodlist[i])

        #爬蟲搜索資訊
        elements.send_keys(Keys.ENTER)
        time.sleep(2)
        soup = BeautifulSoup(driver.page_source, "html.parser")

        #爬出每一項食譜名稱
        name = ''
        content = []
        result = []

        for i in range(1, 6):
            info = ""
            steps = ""
            recipe_xpath_str = f"//body/div[@id='main']/div[@id='rightmain']/div[2]/div[4]/ul[1]/li[{i}]/a[1]/picture[1]/img[1]"
            item = driver.find_element(By.XPATH, recipe_xpath_str)
            driver.execute_script("arguments[0].click();", item)
            time.sleep(2)

            soup = BeautifulSoup(driver.page_source, "html.parser")

            #食譜名
            div = soup.find('div', {'id' : 'recipe_name'})
            h2 = div.find('h2')
            recipe_name = div.find('a').get_text()
            recipe_name = re.sub(r'\([^()]*\)', '', recipe_name)
            print(recipe_name)

            #所需食材、調味料
            div = soup.find('div', {'id' : 'recipe_item'})
            count = 0
            ingredient_count = 0

            if div:

                ul_elements = div.find_all('ul', {'class' : 'ingredient'})
                for ul in ul_elements:

                    count += 1
                    ingredient_count += 1
                    if ingredient_count == 1:
                        info = info + "<食材>"
                        print("<食材>")
                    elif ingredient_count == 2:
                        info = info + "\n\n<調味料>"
                        print("<調味料>")
                    else:
                        info = info + "\n\n<醃料>"
                        print("<醃料>")

                    first_li = ul.find('li')

                    if first_li:

                        sibling_li_elements = first_li.find_next_siblings('li')

                        for li in sibling_li_elements:

                            if count != 3:

                                ingredient = li.find('span', {'class' : 'ingredient_name'})
                                ingredient_name = ingredient.find('a')
                                ingredient_amount = ingredient.find('span', {'class' : 'ingredient_amount'})

                                if ingredient_name and ingredient_amount and ingredient_name.text != '':

                                    info = info + "\n" +(ingredient_name.text + '---' + ingredient_amount.text)
                                    print(ingredient_name.text + '---' + ingredient_amount.text)

                            else:

                                ingredient = li.find('span', {'class' : 'ingredient_name'})
                                ingredient_name = ingredient.find('a')
                                ingredient_amount = li.find('span', {'class' : 'ingredient_amount'})

                                if ingredient_name and ingredient_amount and ingredient_name.text != '':
                                    info = info + "\n" + (ingredient_name.text + '---' + ingredient_amount.text)
                                    print(ingredient_name.text+'---'+ingredient_amount.text)

            #步驟

            step_ul = soup.find('ul', attrs={'style': 'clear:both;'})
            step_li = step_ul.find_all('li')

            for step in step_li:
                steps = steps  + step.text.strip() + "\n----------\n"

            #圖片
            recipe_pic = soup.find('div', {'id' : 'recipe_mainpic'})
            recipe_pic_img = recipe_pic.find('img')
            src = recipe_pic_img.get('src')
            print(src)

            driver.back()
            time.sleep(2)

            #食譜名稱, 食材, 做法, 圖片
            content = [recipe_name, info, steps, src, info[:40]]
            result.append(content)

        time.sleep(5)
        driver.close()
        print("Successful")

        return result


from __future__ import unicode_literals

from django.conf.urls import url
from django.contrib import admin

from .views import (
    AvailabilityForDayList, AvailabilityStaffCreate, AvailabilityForDayCreate,
    AvailabilityForDayUpdate, AvailabilityForDayDelete, TimeDayList
)

# from .views import (
#     # AvailabilityForDayList, AvailabilityForDayDetail, AvailabilityForDayCreate,
#     # AvailabilityForDayUpdate, AvailabilityForDayDelete, AvailabilityStaffCreate
# )

app_name = 'time_log'
urlpatterns = [
    url(r'^day_time_availability/$', TimeDayList.as_view(),
                    name="day_time_avail_list"),

    url(r'^staff_avail/(?P<pk>\d+)/$', AvailabilityForDayList.as_view(),
                    name="staff_avail_list"),
    url(r'^staff_avail/create/$', AvailabilityStaffCreate.as_view(),
                    name="staff_initial_create"),
    url(r'^staff_avail/(?P<pk>\d+)/add/$', AvailabilityForDayCreate.as_view(),
                    name="staff_avail_add"),
    url(r'^staff_avail/(?P<pk>\d+)/update/$', AvailabilityForDayUpdate.as_view(),
                    name="staff_avail_update"),
    url(r'^staff_avail/(?P<pk>\d+)/delete/$', AvailabilityForDayDelete.as_view(),
                    name="staff_avail_delete"),

    # url(r'^staff_avail/(?P<pk>\d+)/$', AvailabilityForDayList.as_view(),
    #                 name="staff_avail_list"),
    # url(r'^staff_avail/create/$', AvailabilityStaffCreate.as_view(),
    #                 name="staff_initial_create"),
    # url(r'^staff_avail/(?P<pk>\d+)/add/$', AvailabilityForDayCreate.as_view(),
    #                 name="staff_avail_add"),
    # url(r'^staff_avail/(?P<pk>\d+)/update/$', AvailabilityForDayUpdate.as_view(),
    #                 name="staff_avail_update"),
    # url(r'^staff_avail/(?P<pk>\d+)/delete/$', AvailabilityForDayDelete.as_view(),
    #                 name="staff_avail_delete"),
]


import sys
import os

sys.path.append(os.path.abspath("."))
sys.dont_write_bytecode = True

__author__ = "bigfatnoob"

from utils import logger
from misconceptions.common import mongo_driver, props, compare

LOGGER = logger.get_logger(os.path.basename(__file__.split(".")[0]))

def delete_single_output_stmts(limit=0, log_interval=100):
  store = mongo_driver.MongoStore(props.DATASET)
  stmts = store.load_stmts(language=None, is_valid=True, has_output=True,
                           limit=limit).values()
  valids = {}
  for i, stmt in enumerate(stmts):
    if i % log_interval == 0:
      LOGGER.info("Processing statement %d/%d ... " % (i, len(stmts)))
    meta = stmt.get("meta", {})
    stmt_valids = set()
    for key, validity in meta.items():
      if validity:
        stmt_valids.add(mongo_driver.mongo_de_escape(key))
    if len(stmt_valids) > 0:
      valids[stmt["_id"]] = stmt_valids
  LOGGER.info("Non singular output stmts: %d/%d" % (len(valids), len(stmts)))
  differences = store.load_differences(projection={"_id": True, "r_id": True, "py_id": True,
                                                   "r_return": True, "py_return": True}, limit=limit)
  to_delete = []
  n_differences = differences.count()
  i = 0
  for diff in differences:
    i += 1
    if i % log_interval == 0:
      LOGGER.info("Processing differences: %d / %d" % (i, n_differences))
    r_id, py_id = diff["r_id"], diff["py_id"]
    if (r_id in valids) and (diff["r_return"] in valids[r_id]):
      to_delete.append(diff["_id"])
      continue
    if (py_id in valids) and (diff["py_return"] in valids[py_id]):
      to_delete.append(diff["_id"])
      continue
  LOGGER.info("Differences to delete: %d / %d" % (len(to_delete), differences.count()))
  for i, diff_id in enumerate(to_delete):
    if i % log_interval == 0:
      LOGGER.info("Deleting difference %d/%d ... " % (i, len(to_delete)))
    store.delete_difference(diff_id)

if __name__ == "__main__":
  delete_single_output_stmts()


#!/usr/bin/python3

if __name__ == "__main__":
    """Print the number of and list of arguments."""
    import sys

    oko = len(sys.argv) - 1
    if oko == 0:
        print("0 arguments.")
    elif oko == 1:
        print("1 argument:")
    else:
        print("{} arguments:".format(oko))
    for i in range(oko):
        print("{}: {}".format(i + 1, sys.argv[i + 1]))


#同じディレクトリに学習済みモデルが必要 doc2vec.model
#同じディレクトリにテキストが必要　shift_jisであること
#実行時にファイル名を入力　拡張子不要(実行時はnekoでとりあえず動きます）
import MeCab
from gensim import models

DOC_PATH = './{0}.txt'
model = models.Doc2Vec.load('doc2vec.model')

# ファイルから文章を返す
def read_document(path):
    with open(path, 'r', encoding='sjis', errors='ignore') as f:
        return f.read()

# 青空文庫ファイルから作品部分のみ抜き出す
def trim_doc(doc):
    lines = doc.splitlines()
    valid_lines = []
    is_valid = False
    horizontal_rule_cnt = 0
    break_cnt = 0
    for line in lines:
        if horizontal_rule_cnt < 2 and '-----' in line:
            horizontal_rule_cnt += 1
            is_valid = horizontal_rule_cnt == 2
            continue
        if not(is_valid):
            continue
        if line == '':
            break_cnt += 1
            is_valid = break_cnt != 3
            continue
        break_cnt = 0
        valid_lines.append(line)
    return ''.join(valid_lines)

# 文章から単語に分解して返す
def split_into_words(doc, name=''):
    mecab = MeCab.Tagger("-Ochasen")
    valid_doc = trim_doc(doc)
    lines = mecab.parse(doc).splitlines()
    words = []
    for line in lines:
        chunks = line.split('\t')
        if len(chunks) > 3 and (chunks[3].startswith('動詞') or chunks[3].startswith('形容詞') or (chunks[3].startswith('名詞') and not chunks[3].startswith('名詞-数'))):
            words.append(chunks[0])
    return words

def search_similar_texts(sentences):
    newvec = model.infer_vector(sentences)
    most_similar_texts = model.docvecs.most_similar([newvec], topn=10)
    for similar_text in most_similar_texts:
        print(similar_text[0])

if __name__ == '__main__':
    print("file name:")
    file_name = input()
    file_path = DOC_PATH.format(file_name)
    doc = read_document(file_path)
    sentences = split_into_words(doc)
    print()
    search_similar_texts(sentences)


import sys
sys.path.append('protobuf')
import grpc
from concurrent import futures
import protobuf_pb2
import protobuf_pb2_grpc
import json
import uuid
from zkp_code import save_client, Verifier

class AuthService(protobuf_pb2_grpc.AuthServicer):
    def __init__(self):
        # Initialize the session dictionary
        self.sessions = {}
        self.verifier = None

    def Register(self, request, context):
        save_client(request.y1, request.y2, request.user)
        response = protobuf_pb2.RegisterResponse()
        return response

    def CreateAuthenticationChallenge(self, request, context):
        session_id = str(uuid.uuid4())
        with open('clients.json') as json_file:
            data = json.load(json_file)
        clientData = data[request.user]
        self.verifier = Verifier(clientData['y1'], clientData['y2'])
        c = self.verifier.generate_c()
        self.sessions[session_id] = {'user': request.user, 'r1': request.r1,
                             'r2': request.r2, 'y1': clientData['y1'], 'y2': clientData['y2'], 'c': c}

        response = protobuf_pb2.AuthenticationChallengeResponse(auth_id=session_id, c=c)
        return response

    def VerifyAuthentication(self, request, context):
        session_id =  request.auth_id
        session = self.sessions[session_id]
        s = request.s
        print('Response Step')
        if self.verifier.verify(session['r1'], session['r2'], s):
            print('Successful authentication')
            return protobuf_pb2.AuthenticationAnswerResponse(session_id=session_id)
        else:
            context.set_details('Authentication failed')
            context.set_code(grpc.StatusCode.UNAUTHENTICATED)
            return protobuf_pb2.AuthenticationAnswerResponse()

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    protobuf_pb2_grpc.add_AuthServicer_to_server(AuthService(), server)
    server.add_insecure_port('[::]:8000')
    server.start()
    print("Server started")
    server.wait_for_termination()

if __name__ == '__main__':
    serve()