# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def increasingBST(self, root: TreeNode) -> TreeNode:

        nodes = []

        def dfs(root):
            if not root:
                return

            dfs(root.left)
            nodes.append(root)
            dfs(root.right)

        dfs(root)

        for i in range(len(nodes)-1):
            nodes[i].left = None
            nodes[i].right = nodes[i+1]

        return nodes[0]


# -*- coding: utf-8 -*-

import pytest
import requests
from pathlib_mate import Path
from sfm.fingerprint import fingerprint
from superjson import json

from seedinvest_monitor.crawler import html_parser

def jprint(data):
    print(json.dumps(data, indent=4, sort_keys=True))

def get_html(url):
    fpath = Path(__file__).change(new_basename="{}.html".format(fingerprint.of_text(url)))
    if fpath.exists():
        html = fpath.read_text(encoding="utf-8")
    else:
        # i am lazy, I don't want to login, session_id is the key
        headers = {
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
            "accept-encoding": "gzip, deflate, br",
            "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6,ja;q=0.5",
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "none",
            # "cookie": "csrftoken=9999JP9mz49NwmqfykyrMupzywy3XZNGgq7Rly23j0u2QuEHdDcOreAnWIjGIhtj; _ga=GA1.2.1853091755.1574187377; _gid=GA1.2.909819738.1574187377; intercom-id-aaaa73km=aaaa1111-18b1-48af-849d-94ad2564a3bc; ga_cid=1853091755.1574187377; sessionid=t2xtsqy6pkf3mkndvd8oljs102ffp6bc; intercom-session-aaaa73km=bXI5eG01b1pJdHlmSk9mYU1jSzZPNGVpWng0KzR6Snk3MngwUjJtNVRzWHhzSHlEenBqTXYyNDRwMWZaekxydC0tUmtTUVo1bjlaNmo3SDVIVFVhcGpCZz09--d927dd0ff0f890889144d645e77525943c851cf5"
        }
        res = requests.get(url, headers=headers)
        html = res.text
        fpath.write_text(html, encoding="utf-8")
    return html

def test_parse_offering_page():
    results = html_parser.parse_offering_page(get_html("https://www.seedinvest.com/offerings"))
    assert len(results) >= 10

def test_parse_project_page():
    result = html_parser.parse_project_page(get_html("https://www.seedinvest.com/nowrx"))
    # jprint(result)

    result = html_parser.parse_project_page(get_html("https://www.seedinvest.com/have.need"))
    # jprint(result)

if __name__ == "__main__":
    import os

    basename = os.path.basename(__file__)
    pytest.main([basename, "-s", "--tb=native"])


numberOfTest = int(input())
while(numberOfTest > 0):
	firstNumber, secondNumber, thirdNumber = raw_input().split(" ")
	firstNumber = int(firstNumber)
	secondNumber = int(secondNumber)
	thirdNumber = int(thirdNumber)
	if(firstNumber >= secondNumber and firstNumber >= thirdNumber):
		if(secondNumber > thirdNumber):
			print(secondNumber)
		else:
			print(thirdNumber)
	elif(secondNumber >= firstNumber and secondNumber >= thirdNumber):
		if(firstNumber > thirdNumber):
			print(firstNumber)
		else:
			print(thirdNumber)
	else:
		if(secondNumber > firstNumber):
			print(secondNumber)
		else:
			print(firstNumber)
	numberOfTest -= 1


# -*- coding: utf-8 -*-
''' @author : majian'''

import os, re, sys
import time

class ReadCurves:

    def __init__(self):

        self.returns = ""

    ''' Curves of number explain '''
    def changeReadlist(self, list):

        newList = []

        for eachVar in range(len(list)):
            if list[eachVar] == 0:
                tmpresult = '%s minutes: %s' % (int(eachVar)+1, 'nochange')
                newList.append(tmpresult)
            elif list[eachVar] > 0:
                tmpresult = '%s minutes: UP %s people' % (int(eachVar)+1, list[eachVar])
                newList.append(tmpresult)
            elif list[eachVar] < 0:
                tmpresult = '%s minutes: LOSE %s people' % (int(eachVar)+1, list[eachVar])
                newList.append(tmpresult)

        return newList


lst = [1, 2, 3, 5]
n = len(lst) + 1
from functools import reduce
x = sum(lst)
tot =  (n*(n+1))/2
mis = tot - x
print(int(mis))

# O(n)
# O(1)

#Method 2

lst = [1, 2, 3, 5]

x = lst[0]
y = 1

for i in range(1, len(lst)):
    x ^=lst[i]

for i in range(2, len(lst)+2):
    y ^=i

print(x^y)


import socket

from ipaddress import IPv4Address, IPv6Address

from adapters.interfaces.sockets import SocketClientAbstract
from helpers import sockets
from core import exceptions, data_types

class SocketClient(SocketClientAbstract):
    """Socket TCP/IP"""

    def __init__(self, address: IPv4Address | IPv6Address | str, port: int, logger):
        # TCP Socket Creation
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.logger = logger

        self.address = address
        self.port = port

    def connect(self):
        self.socket.connect((self.address, self.port))

    def send(
        self,
        http_options: dict,
        url_type: str,
    ) -> int:
        if not self.socket.getpeername():
            raise exceptions.ConnectionErrorException("Socket is not connected")

        request_str = sockets.get_string_request(http_options, url_type)

        self.socket.sendall(request_str.encode())

    def recv(self, until_complete=True) -> bytes:
        if not self.socket.getpeername():
            raise exceptions.ConnectionErrorException("Socket is not connected")

        received_data = b""

        if until_complete:
            while True:
                chunk = self.socket.recv(1024)
                print(chunk)
                if not chunk:
                    break

                received_data += chunk
        else:
            received_data = self.socket.recv(1024)

        return sockets.get_format_data(received_data)

    def close(self):
        self.socket.close()


"""
Ejercicio nivel 2: Agenda de peliculas.
Módulo de cálculos.

Temas:
* Variables.
* Tipos de datos.
* Expresiones aritmeticas.
* Instrucciones basicas y consola.
* Dividir y conquistar: funciones y paso de parametros.
* Especificacion y documentacion.
* Instrucciones condicionales.
* Diccionarios.
@author: Luis Santa
"""

def crear_pelicula(nombre: str, genero: str, duracion: int, anio: int, clasificacion: str, hora: int, dia: str) -> dict:
    """Crea un diccionario que representa una nueva película con toda su información
       inicializada.
    Parámetros:
        nombre (str): Nombre de la pelicula agendada.
        genero (str): Generos de la pelicula separados por comas.
        duracion (int): Duracion en minutos de la pelicula
        anio (int): Anio de estreno de la pelicula
        clasificacion (str): Clasificacion de restriccion por edad
        hora (int): Hora a la cual se planea ver la pelicula, esta debe estar entre
                    0 y 2359
        dia (str): Dia de la semana en el cual se planea ver la pelicula.
    Retorna:
        dict: Diccionario con los datos de la pelicula
    """
    pelicula = {
        'nombre': nombre,
        'genero': genero,
        'duracion': duracion,
        'anio': anio,
        'clasificacion': clasificacion,
        'hora': hora,
        'dia': dia
    }
    return pelicula

def encontrar_pelicula(nombre_pelicula_a_buscar: str, peliculas: list) -> dict:
    """Encuentra en cual de los 5 diccionarios que se pasan por parametro esta la
       pelicula cuyo nombre es dado por parametro.
       Si no se encuentra la pelicula se debe retornar None.
    Parametros:
        nombre_pelicula_a_buscar (str): El nombre de la pelicula que se desea encontrar.
        peliculas (list) = lista de peliculas
    Retorna:
        dict: Diccionario de la pelicula cuyo nombre fue dado por parametro.
        None si no se encuentra una pelicula con ese nombre.
    """
    pelicula_encontrada = None
    for pelicula in peliculas:
        if pelicula['nombre'] == nombre_pelicula_a_buscar:
            pelicula_encontrada = pelicula
    return pelicula_encontrada

def encontrar_pelicula_mas_larga(peliculas: list) -> dict:
    """Encuentra la pelicula de mayor duracion entre las peliculas recibidas por
       parametro.
    Parametros:
        peliculas (list) = lista de peliculas
    Retorna:
        dict: El diccionario de la pelicula de mayor duracion
    """
    mayor_duracion = 0
    pelicula_mas_larga = {}
    for pelicula in peliculas:
        if pelicula['duracion'] > mayor_duracion:
            pelicula_mas_larga = pelicula
            mayor_duracion = pelicula['duracion']
    return pelicula_mas_larga

def duracion_promedio_peliculas(peliculas: list) -> str:
    """Calcula la duracion promedio de las peliculas que entran por parametro.
       Esto es, la duración total de todas las peliculas dividida sobre el numero de peliculas.
       Retorna la duracion promedio en una cadena de formato 'HH:MM' ignorando los posibles decimales.
    Parametros:
        peliculas (list) = lista de peliculas
    Retorna:
        str: la duracion promedio de las peliculas en formato 'HH:MM'
    """
    duracion_peliculas = 0
    for pelicula in peliculas:
        duracion_peliculas += pelicula['duracion']
    promedio = int(duracion_peliculas / 5)
    horas, minutos = divmod(promedio, 60)
    return str(horas) + ':' + str(minutos)

def encontrar_estrenos(peliculas: list, anio: int) -> str:
    """Busca entre las peliculas cuales tienen como anio de estreno una fecha estrictamente
       posterior a la recibida por parametro.
    Parametros:
        peliculas (list) = lista de peliculas
        anio (int): Anio limite para considerar la pelicula como estreno.
    Retorna:
        str: Una cadena con el nombre de la pelicula estrenada posteriormente a la fecha recibida.
        Si hay mas de una pelicula, entonces se retornan los nombres de todas las peliculas
        encontradas separadas por comas. Si ninguna pelicula coincide, retorna "Ninguna".
    """
    estrenos = ''
    for pelicula in peliculas:
        if pelicula['anio'] > anio:
            if estrenos:
                estrenos += ', ' + pelicula['nombre']
            else:
                estrenos += pelicula['nombre']
    if not estrenos:
        estrenos = 'Ninguna'
    return estrenos

def cuantas_peliculas_18_mas(peliculas: list) -> int:
    """Indica cuantas peliculas de clasificación '18+' hay entre los diccionarios recibidos.
    Parametros:
        peliculas (list) = lista de peliculas
    Retorna:
        int: Numero de peliculas con clasificacion '18+'
    """
    numero_peliculas_mas_18 = 0
    for pelicula in peliculas:
        if pelicula['clasificacion'] == '18+' or pelicula['clasificacion'] == 'Todos':
            numero_peliculas_mas_18 += 1
    return numero_peliculas_mas_18

def reagendar_pelicula(pelicula: dict, nueva_hora: int, nuevo_dia: str,
                       control_horario: bool) -> bool:
    """Verifica si es posible reagendar la pelicula que entra por parametro. Para esto verifica
       si la nueva hora y el nuevo dia no entran en conflicto con ninguna otra pelicula,
       y en caso de que el usuario haya pedido control horario verifica que se cumplan
       las restricciones correspondientes.
    Parametros:
        peli (dict): Pelicula a reagendar
        nueva_hora (int): Nueva hora a la cual se quiere ver la pelicula
        nuevo_dia (str): Nuevo dia en el cual se quiere ver la pelicula
        control_horario (bool): Representa si el usuario quiere o no controlar
                                el horario de las peliculas.
    Retorna:
        bool: True en caso de que se haya podido reagendar la pelicula, False de lo contrario.
    """
    if not control_horario:
        puede_reagendar = True
    else:
        if pelicula['genero'].find('Documental') >= 0 and nueva_hora > 2200:
            puede_reagendar = False
        elif pelicula['genero'].find('Drama') >= 0 and nuevo_dia == 'Viernes':
            puede_reagendar = False
        elif nuevo_dia != 'Sabado' and nuevo_dia != 'Domingo' and nueva_hora <= 600 or nueva_hora >= 2100:
            puede_reagendar = False
        else:
            puede_reagendar = True

    if puede_reagendar:
        pelicula['hora'] = nueva_hora
        pelicula['dia'] = nuevo_dia
    return puede_reagendar

def decidir_invitar(pelicula: dict, edad_invitado: int, autorizacion_padres: bool = False) -> bool:
    """Verifica si es posible invitar a la persona cuya edad entra por parametro a ver la
       pelicula que entra igualmente por parametro.
       Para esto verifica el cumplimiento de las restricciones correspondientes.
    Parametros:
        pelicula (dict): Pelicula que se desea ver con el invitado
        edad_invitado (int): Edad del invitado con quien se desea ver la pelicula
        autorizacion_padres (bool): Indica si el invitado cuenta con la autorizacion de sus padres
        para ver la pelicula
    Retorna:
        bool: True en caso de que se pueda invitar a la persona, False de lo contrario.
    """
    se_puede_invitar = False
    if edad_invitado >= 18:
        se_puede_invitar = True
    if edad_invitado <= 10 and pelicula['clasificacion'].find('Familiar') >= 0:
        se_puede_invitar = True
    if pelicula['genero'].find('Documental') >= 0:
        se_puede_invitar = True
    if edad_invitado < 18 and pelicula['genero'].find('Documental') < 0 and autorizacion_padres:
        se_puede_invitar = True
    return se_puede_invitar

def pedir_autorizacion() -> bool:
    valor_autorizacion = False
    fin_ciclo = False
    while not fin_ciclo:
        autorizacion = input('El menor de edad cuenta con autorización de los padres\n1: Si\n2: No\n')
        if autorizacion == '1':
            valor_autorizacion = True
            fin_ciclo = True
        elif autorizacion == '2':
            fin_ciclo = True
        else:
            print('La opción', autorizacion, 'no es valida')
    return valor_autorizacion

def pedir_preferencias() -> bool:
    valor_preferencias = False
    fin_ciclo = False
    while not fin_ciclo:
        preferencia = input('Desea tener en cuenta sus preferencias\n1: Si\n2: No\n')
        if preferencia == '1':
            valor_preferencias = True
            fin_ciclo = True
        elif preferencia == '2':
            fin_ciclo = True
        else:
            print('La opción', preferencia, 'no es valida')
    return valor_preferencias


# Chatbot with Python by Clarence Itai Msindo
import os
import telebot
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from bot import main

BOT_TOKEN = os.environ.get('your-bot-token-here')

bot = telebot.TeleBot(BOT_TOKEN)

# The Chatbot with Python begins here:
# The command handler
def start(update, context):
    context.bot.send_message(chat_id=update.message.chat_id, text="Hey! Whats Up? Say 'Hi' or 'Hello'")

# The message handler
def chatbot_functions(update, context):
    message = update.message.text.lower()
    response = ""

    if "hello" in message or "hi" in message:
        response = "How are you doing?"
    elif "i'm good" in message or "i am good" in message or "good thanks and you?" in message or "i'm good thanks and you?" in message:
        response = "I'm doing well, thank's for asking :)! What is your name?"
    elif "my name is" in message:
        name = message.split("my name is")[1].strip()
        response = f"Nice to meet you, {name}! Ok, I'm done talking now. Say 'Bye' to exit this chat. Have a nice day :)!"
    elif "bye" in message:
        response = "Peace out!"
        context.bot.send_message(chat_id=update.message.chat_id, text=response)
        context.bot.leave_chat(chat_id=update.message.chat_id)
    else:
        response = "Nah, I don't understand what you're saying. Try something else."

    context.bot.send_message(chat_id=update.message.chat_id, text=response)

# The updater and dispatcher
updater = Updater(token='your-bot-token-here', use_context=True)
dispatcher = updater.dispatcher

# Add handlers
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(MessageHandler(Filters.text & (~Filters.command), chatbot_functions))

# Starting the bot
updater.start_polling()
updater.idle()


from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="manual_geo_querier")

# The following works:
# Address with block and street name. Eg. '605 ANG MO KIO AVENUE 5'
# Name of point of interest: 'SUNTEC CITY'
ADDRESSES = [
    'XINMIN PRIMARY SCHOOL',
    'SUNTEC CITY',
    '22 BALAM ROAD'
]

for address in ADDRESSES:
    location = geolocator.geocode(address)
    print('%s \t - \t %s, %s' % (location.address, location.latitude, location.longitude))


# Program to find area and circumference of a circle.

import math
r=10.0
area=3.14*r*r
cir=2*math.pi*r
print(f"area of trangle {area}")
print(f"circumference of circle is {cir}")

# import math
# r=10.0
# area=math.pi*r*r
# circum=2*math.pi*r
# print("area is : ",area)
# print("circum is : ",circum)


from read_datafile import read_datafile

def get_map_data():
    filepath = './data/day9.txt'
    map_data = read_datafile(filepath)
    sensor_map = []
    for row in map_data:
        sensor_map.append([int(x) for x in row])
    return sensor_map

def find_low_points(sensor_map):
    length = len(sensor_map[0])
    height = len(sensor_map)
    outer_coord_x = length-1
    outer_coord_y = height-1

    low_points = []
    for y in range(0,height):
        for x in range(0,length):
            middle = sensor_map[y][x]
            # print(f'coords: {x, y} - value: {middle}')

            # corners
            # top left
            if x == 0 and y == 0:
                # print(f' > top left - {middle}')
                point_a = sensor_map[y+1][x]
                point_b = sensor_map[y][x+1]
                if middle < point_a and middle < point_b:
                    low_points.append(middle)

            # top right
            elif x == outer_coord_x and y == 0:
                # print(f' > top right - {middle}')
                point_a = sensor_map[y+1][x]
                point_b = sensor_map[y][x-1]
                if middle < point_a and middle < point_b:
                    low_points.append(middle)

            # bottom left
            elif x == 0 and y == outer_coord_y:
                # print(f'> bottom left - {middle}')
                point_a = sensor_map[y-1][x]
                point_b = sensor_map[y][x+1]
                if middle < point_a and middle < point_b:
                    low_points.append(middle)

            # bottom right
            elif x == outer_coord_x and y == outer_coord_y:
                # print(f'> bottom right - {middle}')
                point_a = sensor_map[y-1][x]
                point_b = sensor_map[y][x-1]
                if middle < point_a and middle < point_b:
                    low_points.append(middle)

            # top horizontal edge
            elif y == 0:
                # print(f' > top row - {middle}')
                south = sensor_map[y+1][x]
                east = sensor_map[y][x+1]
                west = sensor_map[y][x-1]
                if middle < south and middle < east and middle < west:
                    low_points.append(middle)

            # bottom horizontal edge
            elif y == outer_coord_y:
                # print(f' > bottom row - {middle}')
                north = sensor_map[y-1][x]
                east = sensor_map[y][x+1]
                west = sensor_map[y][x-1]
                if middle < north and middle < east and middle < west:
                    low_points.append(middle)

            # left edge
            elif x == 0:
                # print(f' > left col - {middle}')
                north = sensor_map[y-1][x]
                south = sensor_map[y+1][x]
                east = sensor_map[y][x+1]
                if middle < north and middle < south and middle < east:
                    low_points.append(middle)

            # right edge
            elif x == outer_coord_x:
                # print(f' > right col - {middle}')
                north = sensor_map[y-1][x]
                south = sensor_map[y+1][x]
                west = sensor_map[y][x-1]
                if middle < north and middle < south and middle < west:
                    low_points.append(middle)

            # not edges
            else:
                # print(f' > middle section - {middle}')
                north = sensor_map[y-1][x]
                south = sensor_map[y+1][x]
                east = sensor_map[y][x+1]
                west = sensor_map[y][x-1]
                if middle < north and middle < south and middle < east and middle < west:
                    low_points.append(middle)
    return low_points

def calculate_risk(input):
    risk = 0
    for x in input:
        risk += (1+x)
    return risk

sensor_map = get_map_data()
low_points = find_low_points(sensor_map)
print(low_points)
risk = calculate_risk(low_points)
print(risk)


#By using = and the return command, we can set variables to be a value form of
#A function

def add(a, b):
    print("ADDING %d + %d" % (a, b))
    return a + b

def subtract(a, b):
    print("SUBTACTING %d - %d" % (a, b))
    return a - b

def multiply(a, b):
    print("MULTIPLYING %d * %d" % (a, b))
    return a * b

def divide(a, b):
    print("DIVIDING %d / %d" % (a, b))
    return a / b

print("Let's do some math with just functions!")

age = add(10, 3)
height = subtract(100, 33)
weight = multiply(55, 2)
iq = divide(1000, 5)

print("Age: %d \n Height: %d \n Weight: %d \n IQ: %d"
% (age, height, weight, iq))

#A puzzle for extra credit!
print("Here is a puzzle")

what = add(age, subtract(height, multiply(weight, divide(iq, 2))))

print("That becomes: " + str(what) + " iCan you do it by hand?")


# -*- coding: utf-8 -*-
""" Script to crawl Article from coolhunting.com

cool-hunting
"""

try:
    from crawler import BaseCrawler
except:
    from __init__ import BaseCrawler

class CCoolHuntingCrawler(BaseCrawler):
    start_urls = [
        'https://coolhunting.com/tag/marijuana',
        'https://coolhunting.com/tag/cannabis',
        'https://coolhunting.com/tag/weed',
    ]

    # source = 'COOL HUNTING'
    source_id = 'cool-hunting'

    config_selectors = {
        # Css selector on articles page (the page list many articles)
        'POST_URLS': '.entry-title > a::attr(href)',
        'NEXT_PAGE_URL': 'a.next::attr(href)',  # default

        # Css selector on article's detail page (the page display full content of article)
        'ARTICLE_CONTENT': '#main div.entry-content',
    }

if __name__ == "__main__":
    crawler = CCoolHuntingCrawler()
    crawler.run()


from django.shortcuts import render, get_object_or_404
from rest_framework import generics, status, viewsets, mixins
from rest_framework.response import Response
from . import serializers
from drf_yasg.utils import swagger_auto_schema
from .models import Profile, RunnerLevel, RunnerTag
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly, IsAdminUser
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from django.contrib.auth import get_user_model
from django.utils.decorators import method_decorator

User = get_user_model()

class UserListView(generics.GenericAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = serializers.UserSerializer

    @swagger_auto_schema(operation_summary="List all Users")
    def get(self, request):

        users = User.objects.all()

        serializer = self.serializer_class(instance=users, many=True)

        return Response(data=serializer.data, status=status.HTTP_200_OK)

class UserDetailView(generics.GenericAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = serializers.UserDetailSerializer

    @swagger_auto_schema(operation_summary="Retrieve a User & Profile by user_id")
    def get(self, request, user_id):

        users = get_object_or_404(User, pk=user_id)
        serializer = self.serializer_class(instance=users)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

@method_decorator(name='create', decorator=swagger_auto_schema(
    operation_summary="Create a Profile (For a logged in User)"
))
@method_decorator(name='update', decorator=swagger_auto_schema(
    operation_summary="Update a Profile by Profile ID"
))
@method_decorator(name='partial_update', decorator=swagger_auto_schema(
    operation_summary="Partial Update a Profile by Profile ID"
))

class ProfileViewSet(mixins.UpdateModelMixin,
                    mixins.CreateModelMixin,
                    viewsets.GenericViewSet):
    serializer_class = serializers.ProfileSerializer
    queryset = Profile.objects.all()
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user).order_by('-id')

    def perform_create(self, serializer):
        data = self.request.data
        serializer = self.serializer_class(data=data, context={"request":self.request})

        user = self.request.user
        if serializer.is_valid():
            serializer.save(user=user)
            return Response(data=serializer.data, status=status.HTTP_201_CREATED)

        return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(name='list', decorator=swagger_auto_schema(
    operation_summary="List all Runner Level"
))
@method_decorator(name='update', decorator=swagger_auto_schema(
    operation_summary="Update a Runner Level (Whole Object)"
))
@method_decorator(name='partial_update', decorator=swagger_auto_schema(
    operation_summary="Partial Update a Runner Level"
))
@method_decorator(name='destroy', decorator=swagger_auto_schema(
    operation_summary="Remove a Runner Level"
))
class RunnerLevelViewSet(mixins.DestroyModelMixin,
                         mixins.UpdateModelMixin,
                         mixins.ListModelMixin,
                         viewsets.GenericViewSet):
    serializer_class = serializers.RunnerLevelSerializer
    queryset = RunnerLevel.objects.all()
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user).order_by('-name')

@method_decorator(name='list', decorator=swagger_auto_schema(
    operation_summary="List all Runner Tags"
))
@method_decorator(name='update', decorator=swagger_auto_schema(
    operation_summary="Update a Runner Tag (Whole Object)"
))
@method_decorator(name='partial_update', decorator=swagger_auto_schema(
    operation_summary="Partial Update a Runner Tag"
))
@method_decorator(name='destroy', decorator=swagger_auto_schema(
    operation_summary="Remove a Runner Tag"
))
class RunnerTagViewSet(mixins.DestroyModelMixin,
                         mixins.UpdateModelMixin,
                         mixins.ListModelMixin,
                         viewsets.GenericViewSet):
    serializer_class = serializers.RunnerTagSerializer
    queryset = RunnerTag.objects.all()
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user).order_by('-name')


import os
import json
import pyodbc
import socket
from flask import Flask, request
from flask_restful import Api, Resource
from threading import Lock
from tenacity import *
import logging
import numpy as np
import pandas as pd
import requests

# User-defined libraries
import preprocessors.data_loader as data_loader
from utilities.general_utils import deserialize_arf
from explainers.car_price import CarPriceExplainer
from explainers.lead_scoring import LeadScoringExplainer
from drift_detectors.car_price import CarPriceDriftDetector
from drift_detectors.lead_scoring import LeadScoringDriftDetector

# Code template: https://github.com/Azure-Samples/azure-sql-db-python-rest-api

app = Flask(__name__)
api = Api(app)

# ----------------------------------------------------------------------------------- #
# Load the car price preprocessor and train set
# ----------------------------------------------------------------------------------- #
# Load the car price data processor and the test subsample
cp_data_pp, cp_X_test_truth_av_subsample = data_loader.load_car_price_data('preprocessors/car_price_data_pp.pkl')

car_train = pd.read_csv(f'data/cp_train_set.csv')

# Shuffle the car records
rng = np.random.default_rng(2022)
car_train = car_train.reindex(rng.permutation(car_train.index))
car_train = car_train.reset_index(drop=True)

# Remove columns that are not needed to perform inference
car_train = car_train.copy().drop(columns=['model'], axis=1)

cp_target_attr = 'price'
cp_X_train = car_train.drop(columns=cp_target_attr, axis=1)
cp_y_train = car_train[cp_target_attr]

# Preprocess the data
cp_X_train  = cp_data_pp.preprocess(cp_X_train)

# Randomly choose 100 samples from the train set
rng = np.random.default_rng(2022)
idx_arr = rng.choice(range(len(cp_X_train)), 100)
cp_X_train_subsample = cp_X_train.iloc[idx_arr, :].copy()
# ----------------------------------------------------------------------------------- #
# END
# ----------------------------------------------------------------------------------- #

# ----------------------------------------------------------------------------------- #
# Load the lead scoring train set
# ----------------------------------------------------------------------------------- #
# Load the lead scoring data processor and the test subsample
ls_data_pp, ls_X_test_truth_av_subsample = data_loader.load_lead_scoring_data('preprocessors/lead_scoring_data_pp.pkl')

ls_train = pd.read_csv(f'data/ls_train_set.csv')

ls_target_attr = 'converted'
ls_X_train = ls_train.drop(columns=ls_target_attr, axis=1)
ls_y_train = ls_train[ls_target_attr]

ls_X_train = ls_data_pp.preprocess(ls_X_train)

# Randomly choose 100 samples from the train set
rng = np.random.default_rng(2022)
idx_arr = rng.choice(range(len(ls_X_train)), 100)
ls_X_train_subsample = ls_X_train.iloc[idx_arr, :].copy()
# ----------------------------------------------------------------------------------- #
# END
# ----------------------------------------------------------------------------------- #

# ----------------------------------------------------------------------------------- #
# Load models, explainers, and drift detectors
# ----------------------------------------------------------------------------------- #

# Load the car price model
with open('models/car_price_model_dict.json', 'r') as f:
    cp_arf_dict_serializable = json.load(f)
cp_arf_dict = deserialize_arf(cp_arf_dict_serializable)

# Initialize wrapper class for car price explainer
car_price_explainer = CarPriceExplainer(
    cp_data_pp,
    cp_arf_dict,
    cp_X_train,
    cp_y_train,
    cp_X_train_subsample,
    cp_X_test_truth_av_subsample
)

# Load the lead scoring model
with open('models/lead_scoring_model_dict.json', 'r') as f:
    ls_arf_dict_serializable = json.load(f)
ls_arf_dict = deserialize_arf(ls_arf_dict_serializable)

# Initialize wrapper class for lead scoring explainer
lead_scoring_explainer = LeadScoringExplainer(
    ls_data_pp,
    ls_arf_dict,
    ls_X_train,
    ls_y_train,
    ls_X_train_subsample,
    ls_X_test_truth_av_subsample
)

# Initialize wrapper class for car price drift detector
# `doors` and `seat_capacity` are considered as ordinal features,
# thus they are considered as categorical features
cp_X_train_ = cp_X_train.copy().astype({'doors': 'object', 'seat_capacity': 'object'})

car_price_drift_detector = CarPriceDriftDetector(
    cp_X_train_,
    cp_data_pp
)

# Initialize wrapper class for lead scoring drift detector
lead_scoring_drift_detector = LeadScoringDriftDetector(
    ls_X_train,
    ls_data_pp
)

# ------------------------------------------------------------------------------------------------ #
# Database Connection Manager (By Microsoft)
# ------------------------------------------------------------------------------------------------ #

class ConnectionManager(object):
    """
    Implement singleton to avoid global objects

    Full credit: https://github.com/Azure-Samples/azure-sql-db-python-rest-api/blob/master/app.py
    """
    __instance = None
    __connection = None
    __lock = Lock()
    __con_string = f'DRIVER={[item for item in pyodbc.drivers()][-1]};{os.environ["SQLAZURECONNSTR_WWIF"]}'

    def __new__(cls):
        if ConnectionManager.__instance is None:
            ConnectionManager.__instance = object.__new__(cls)
        return ConnectionManager.__instance

    def __getConnection(self):
        if (self.__connection == None):
            application_name = ";APP={0}".format(socket.gethostname())
            self.__connection = pyodbc.connect(ConnectionManager.__con_string + application_name)

        return self.__connection

    def __removeConnection(self):
        self.__connection = None

    @retry(stop=stop_after_attempt(3), wait=wait_fixed(10), retry=retry_if_exception_type(pyodbc.OperationalError), after=after_log(app.logger, logging.DEBUG))
    def executeQueryJSON(self, procedure, payload=None):
        result = {}
        try:
            conn = self.__getConnection()

            cursor = conn.cursor()

            if payload:
                cursor.execute(f"EXEC {procedure} ?", json.dumps(payload))
            else:
                cursor.execute(f"EXEC {procedure}")

            result = cursor.fetchone()

            if result:
                result = json.loads(result[0])
            else:
                result = {}

            cursor.commit()
        except pyodbc.OperationalError as e:
            app.logger.error(f"{e.args[1]}")
            if e.args[0] == "08S01":
                # If there is a "Communication Link Failure" error,
                # then connection must be removed
                # as it will be in an invalid state
                self.__removeConnection()
                raise
        finally:
            cursor.close()

        return result

class Queryable(Resource):
    """
    Full credit: https://github.com/Azure-Samples/azure-sql-db-python-rest-api/blob/master/app.py
    """
    def executeQueryJson(self, verb, payload=None):
        result = {}
        procedure = f"dbo.{verb}"
        result = ConnectionManager().executeQueryJSON(procedure, payload)
        return result

# ------------------------------------------------------------------------------------------------ #
# Car Price API
# ------------------------------------------------------------------------------------------------ #

class CarPriceModelReview(Queryable):
    def get(self):
        # Query the car inventories with truth
        cars_json = self.executeQueryJson("get_car_inventories_with_truth")

        json_result = car_price_explainer.review_model(cars_json)

        return json_result, 200

class CarPriceSinglePost(Queryable):
    def convert_json_to_dict(self, json_data):
        car_json = {
            'aspiration': json_data['aspiration'],
            'assembled': json_data['assembled'],
            'price': json_data['price'],
            'brand': json_data['brand'],
            'colour': json_data['colour'],
            'direct_injection': json_data['direct_injection'],
            'doors': json_data['doors'],
            'engine_cc': json_data['engine_cc'],
            'fuel_type': json_data['fuel_type'],
            'height_mm': json_data['height_mm'],
            'length_mm': json_data['length_mm'],
            'manufacture_year': json_data['manufacture_year'],
            'mileage': json_data['mileage'],
            'peak_power_hp': json_data['peak_power_hp'],
            'peak_torque_nm': json_data['peak_torque_nm'],
            'seat_capacity': json_data['seat_capacity'],
            'steering_type': json_data['steering_type'],
            'transmission': json_data['transmission'],
            'wheel_base_mm': json_data['wheel_base_mm'],
            'width_mm': json_data['width_mm'],
        }
        return car_json

class CarPricePredictionReview(CarPriceSinglePost):
    def post(self):

        json_data = request.get_json(force=True)

        car_json = self.convert_json_to_dict(json_data)

        json_result = car_price_explainer.review_individual_prediction(car_json)

        return json_result, 200

class CarPriceModelLossReview(CarPriceSinglePost):
    def post(self):

        json_data = request.get_json(force=True)

        car_json = self.convert_json_to_dict(json_data)

        json_result = car_price_explainer.review_individual_model_loss(car_json)

        return json_result, 200

class CarPricePerformanceEval(Queryable):
    def get(self):
        # Query the car inventories with truth
        cars_json = self.executeQueryJson("get_car_inventories_with_truth")

        json_result = car_price_explainer.evaluate_performance(cars_json)

        return json_result, 200

class CarPriceDriftMonitorNoTruth(Queryable):
    def get(self):
        # Query the car inventories without truth
        cars_json = self.executeQueryJson("get_car_inventories_no_truth")

        json_result = car_price_drift_detector.detect_drift(cars_json)

        return json_result, 200

class CarPriceDriftMonitorTruth(Queryable):
    def get(self):
        # Query the car inventories with truth
        cars_json = self.executeQueryJson("get_car_inventories_with_truth")

        json_result = car_price_explainer.detect_drift(cars_json)

        return json_result, 200

class CarPriceUpdateModelAndExplainer(CarPriceSinglePost):
    def post(self):
        json_data = request.get_json(force=True)
        car_json = self.convert_json_to_dict(json_data)

        # Train the adaptive random forest classifier on the lead information in the other web service
        response_ = requests.post('http://river-web-service:80/car/training', json = car_json)
        response_.raise_for_status()

        # Get the JSON containing the extracted tree weights from adaptive random forest classifier
        cp_arf_json = response_.json()
        cp_arf_dict = deserialize_arf(cp_arf_json)

        # Update the lead scoring Tree SHAP explainer and Tree SHAP loss explainer
        car_price_explainer.update_explainers(cp_arf_dict)
        return 'Successfully updated the car price model and its explainer', 200

api.add_resource(CarPriceModelReview,      '/car/global/review/model')
api.add_resource(CarPricePerformanceEval,  '/car/global/review/performance')
api.add_resource(CarPricePredictionReview, '/car/local/review/prediction')
api.add_resource(CarPriceModelLossReview,  '/car/local/review/model_loss')
api.add_resource(CarPriceUpdateModelAndExplainer,  '/car/update/model')
api.add_resource(CarPriceDriftMonitorTruth,  '/car/global/review/drift/truth')
api.add_resource(CarPriceDriftMonitorNoTruth,  '/car/global/review/drift/no_truth')

# ------------------------------------------------------------------------------------------------ #
# Lead Scoring API
# ------------------------------------------------------------------------------------------------ #

class LeadScoringModelReview(Queryable):
    def get(self):
        # Query the lead information with truth
        leads_json = self.executeQueryJson("get_lead_info_with_truth")

        json_result = lead_scoring_explainer.review_model(leads_json)

        return json_result, 200

class LeadScoringSinglePost(Queryable):
    def convert_json_to_dict(self, json_data):
        lead_json = {
            'dont_email': json_data['dont_email'],
            'dont_call': json_data['dont_call'],
            'occupation': json_data['occupation'],
            'received_free_copy': json_data['received_free_copy'],
            'avg_page_view_per_visit': json_data['avg_page_view_per_visit'],
            'total_site_visit': json_data['total_site_visit'],
            'total_time_spend_on_site': json_data['total_time_spend_on_site'],
            'converted': json_data['converted']
        }
        return lead_json

class LeadScoringPredictionReview(LeadScoringSinglePost):
    def post(self):

        json_data = request.get_json(force=True)

        lead_json = self.convert_json_to_dict(json_data)

        json_result = lead_scoring_explainer.review_individual_prediction(lead_json)

        return json_result, 200

class LeadScoringModelLossReview(LeadScoringSinglePost):
    def post(self):

        json_data = request.get_json(force=True)

        lead_json = self.convert_json_to_dict(json_data)

        json_result = lead_scoring_explainer.review_individual_model_loss(lead_json)

        return json_result, 200

class LeadScoringPerformanceEval(Queryable):
    def get(self):
        # Query the lead information with truth
        leads_json = self.executeQueryJson("get_lead_info_with_truth")

        json_result = lead_scoring_explainer.evaluate_performance(leads_json)

        return json_result, 200

class LeadScoringDriftMonitorNoTruth(Queryable):
    def get(self):
        # Query the lead information without truth
        leads_json = self.executeQueryJson("get_lead_info_no_truth")

        json_result = lead_scoring_drift_detector.detect_drift(leads_json)

        return json_result, 200

class LeadScoringDriftMonitorTruth(Queryable):
    def get(self):
        # Query the lead information with truth
        leads_json = self.executeQueryJson("get_lead_info_with_truth")

        json_result = lead_scoring_explainer.detect_drift(leads_json)

        return json_result, 200

class LeadScoringUpdateModelAndExplainer(LeadScoringSinglePost):
    def post(self):
        json_data = request.get_json(force=True)
        lead_json = self.convert_json_to_dict(json_data)

        # Train the adaptive random forest classifier on the lead information in the other web service
        response_ = requests.post('http://river-web-service:80/lead/training', json = lead_json)
        response_.raise_for_status()

        # Get the JSON containing the extracted tree weights from adaptive random forest classifier
        ls_arf_json = response_.json()
        ls_arf_dict = deserialize_arf(ls_arf_json)

        # Update the lead scoring Tree SHAP explainer and Tree SHAP loss explainer
        lead_scoring_explainer.update_explainers(ls_arf_dict)
        return 'Successfully updated the lead scoring model and its explainer', 200

api.add_resource(LeadScoringModelReview,      '/lead/global/review/model')
api.add_resource(LeadScoringPerformanceEval,  '/lead/global/review/performance')
api.add_resource(LeadScoringPredictionReview, '/lead/local/review/prediction')
api.add_resource(LeadScoringModelLossReview,  '/lead/local/review/model_loss')
api.add_resource(LeadScoringUpdateModelAndExplainer,  '/lead/update/model')
api.add_resource(LeadScoringDriftMonitorTruth,  '/lead/global/review/drift/truth')
api.add_resource(LeadScoringDriftMonitorNoTruth,  '/lead/global/review/drift/no_truth')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80, debug=True)


# (c) Nelen & Schuurmans.  Proprietary, see LICENSE file.
from django.contrib import admin
from django.utils.html import mark_safe
from nens_auth_client import models

import base64
import json

def decode_jwt(token):
    """Decode a JWT without checking its signature"""
    if not token:
        return
    # JWT consists of {header}.{payload}.{signature}
    try:
        _, payload, _ = token.split(".")
    except ValueError:
        return "token is not a JWT"

    # JWT should be padded with = (base64.b64decode expects this)
    payload += "=" * (-len(payload) % 4)
    return json.loads(base64.b64decode(payload))

def render_json(obj):
    """Display an JSON object in HTML, for rendering in admin"""
    content = json.dumps(obj, indent=2, sort_keys=True)
    return mark_safe("<pre>{}</pre>".format(content))

@admin.register(models.RemoteUser)
class RemoteUserAdmin(admin.ModelAdmin):
    list_display = ("external_user_id", "user", "created")
    list_select_related = ("user",)
    search_fields = ("external_user_id", "user__username", "user__email")
    readonly_fields = (
        "created",
        "last_modified",
        "id_token_payload",
        "access_token_payload",
        "id_token",
        "access_token",
        "refresh_token",
    )
    raw_id_fields = ("user",)

    fieldsets = [
        (
            None,
            {
                "fields": (
                    "external_user_id",
                    "user",
                    "created",
                    "last_modified",
                    "id_token_payload",
                    "access_token_payload",
                )
            },
        ),
        (
            "Tokens (raw)",
            {
                "classes": ("collapse",),
                "fields": ("id_token", "access_token", "refresh_token"),
            },
        ),
    ]

    def id_token_payload(self, obj):
        return render_json(decode_jwt(obj.id_token))

    def access_token_payload(self, obj):
        return render_json(decode_jwt(obj.access_token))

@admin.register(models.Invitation)
class InvitationAdmin(admin.ModelAdmin):
    list_display = ("id", "status", "user", "created_at", "email", "email_sent_at")
    list_select_related = ("user",)
    search_fields = ("id", "slug", "email", "user__username")
    readonly_fields = (
        "id",
        "status",
        "slug",
        "accept_url",
        "created_at",
        "email_sent_at",
    )
    raw_id_fields = ("user", "created_by")
    list_filter = ("status",)
    actions = ("send_email",)
    fieldsets = [
        (
            None,
            {
                "fields": (
                    "status",
                    "email",
                    "user",
                    "permissions",
                    "created_by",
                    "created_at",
                    "email_sent_at",
                )
            },
        ),
        ("Secrets", {"classes": ("collapse",), "fields": ("slug", "accept_url")}),
    ]

    def get_form(self, request, *args, **kwargs):
        # stick the request to self, for accept_url
        self.request = request
        return super().get_form(request, *args, **kwargs)

    def accept_url(self, obj):
        return obj.get_accept_url(self.request)

    def send_email(self, request, queryset):
        for invitation in queryset:
            invitation.send_email(request)

    send_email.short_description = "(Re)send selected invitations"


import os
#
# Complete the 'gridChallenge' function below.
#
# The function is expected to return a STRING.
# The function accepts STRING_ARRAY grid as parameter.
#

def gridChallenge(grid):
    # Write your code here
    sorted_grid = []
    for row in grid:
        sorted_grid.append(sorted(row))
    cols = [True if list(i) == sorted(i) else False for i in zip(*sorted_grid)]
    if all(cols):
        return "YES"
    else:
        return "NO"

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    t = int(input().strip())

    for t_itr in range(t):
        n = int(input().strip())

        grid = []

        for _ in range(n):
            grid_item = input()
            grid.append(grid_item)

        result = gridChallenge(grid)

        fptr.write(result + '\n')

    fptr.close()


from aiogram.types import (InlineKeyboardMarkup, InlineKeyboardButton,
                           ReplyKeyboardMarkup, KeyboardButton, WebAppInfo)
from aiogram.utils.keyboard import InlineKeyboardBuilder
from geopy.distance import geodesic
from app.database.requests import (get_locations_device, get_locations_sticks,
                                   get_locations_guarantee, get_locations_international_guarantee,
                                   get_locations_cleaning)

def generate_yandex_maps_link(latitude, longitude, point_name):
    base_url = "https://yandex.ru/maps"
    query_parameters = {
        "ll": f"{longitude},{latitude}",
        "z": "17",  # Уровень масштабирования (от 1 до 19)
        "l": "map",  # Тип карты: "map" - обычная карта, "sat" - спутниковая карта, "skl" - гибрид
        "pt": f"{longitude},{latitude}"
    }
    encoded_parameters = "&".join([f"{key}={value}" for key, value in query_parameters.items()])
    yandex_maps_link = f"{base_url}?{encoded_parameters}"
    return yandex_maps_link

menu = InlineKeyboardMarkup(inline_keyboard=[
    [InlineKeyboardButton(text='Покупка девайса', callback_data='buy_device')],
    [InlineKeyboardButton(text='Покупка стиков', callback_data='buy_sticks')],
    [InlineKeyboardButton(text='Service', callback_data='service')]
])

service = InlineKeyboardMarkup(inline_keyboard=[
    [InlineKeyboardButton(text='Гарантийная замена', callback_data='guarantee')],
    [InlineKeyboardButton(text='Международная гарантия/Прошивка', callback_data='international_guarantee')],
    [InlineKeyboardButton(text='Чистка', callback_data='cleaning')]
])

main = ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text='📍 Отправить локацию', request_location=True)]],
                           resize_keyboard=True,
                           input_field_placeholder='Выберите кнопку ниже ⬇')

cancel_kb = ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text='Отмена')]],
                                resize_keyboard=True)

async def check(lat, lon, type):

    if type == 'buy_device':
        locations = await get_locations_device()
        my_distance = 1000
    elif type == 'buy_sticks':
        locations = await get_locations_sticks()
        my_distance = 1000
    elif type == 'guarantee':
        locations = await get_locations_guarantee()
        my_distance = 10000
    elif type == 'international_guarantee':
        locations = await get_locations_international_guarantee()
        my_distance = 10000
    elif type == 'cleaning':
        locations = await get_locations_cleaning()
        my_distance = 10000

    keyboard = InlineKeyboardBuilder()
    locations_dict = {}

    for location in locations:
        distance = geodesic((lat, lon), (location.latitude, location.longitude)).meters
        if distance < my_distance:
            locations_dict[distance] = location

    sorted_dict = {key: locations_dict[key] for key in sorted(locations_dict)}

    if len(sorted_dict.keys()) >= 1:
        for dist, location in sorted_dict.items():
            keyboard.row(InlineKeyboardButton(text=f'{round(dist)}м - {location.name[:25]}', callback_data=f'location_{location.id}', web_app=WebAppInfo(url=generate_yandex_maps_link(location.latitude, location.longitude, location.name))))
        keyboard.row(InlineKeyboardButton(text='🏠 В главное меню', callback_data='main_menu'))
        return keyboard.as_markup()
    else:
        return None

async def open_location(location):
    keyboard = InlineKeyboardBuilder()
    keyboard.row(InlineKeyboardButton(text='🗾 Открыть на картах', web_app=WebAppInfo(url=generate_yandex_maps_link(location.latitude, location.longitude, location.name))))
    keyboard.row(InlineKeyboardButton(text='✍🏻 Оставить отзыв', callback_data=f'feedback_{location.id}'))
    keyboard.row(InlineKeyboardButton(text='🏠 В главное меню', callback_data='main_menu'))
    return keyboard.as_markup()

done = ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text='Готово ✅')]],
                           resize_keyboard=True)


# sitio_web/urls.py

from django.conf.urls import include, url
from django.contrib import admin
from registration.backends.simple.views import RegistrationView

# Create a new class that redirects the user to the index page, if successful at logging
class MyRegistrationView(RegistrationView):
    def get_success_url(self,request, user):
        return '/restaurantes/'

urlpatterns = [
	url(r'^restaurantes/', include('restaurantes.urls')),
	url(r'^admin/', include(admin.site.urls)),
	url(r'^accounts/register/$', MyRegistrationView.as_view(), name='registration_register'),
	url(r'^accounts/', include('registration.backends.simple.urls')),
]


#program to demo use of threads

import time
from threading import Thread
import random

def longTask(msg):
    print(msg + " task started")

    for i in range(3,6):
        time.sleep(random.randrange(3))
        print(msg + " completed:",i)

    print(msg + " Task finished")

threads = []
for i in range(3):
    t = Thread(target=longTask,args=['thread'+str(i)])
    threads.append(t)
    t.start()

print("Main finished")


from typing import List, Optional

from ...tokenization_utils_base import AddedToken
from ...utils import logging
from ..gpt2.tokenization_gpt2_fast import GPT2TokenizerFast
from .tokenization_roberta import RobertaTokenizer

logger = logging.get_logger(__name__)

VOCAB_FILES_NAMES = {"vocab_file": "vocab.json", "merges_file": "merges.txt", "tokenizer_file": "tokenizer.json"}

PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES = {
    "roberta-base": 512,
    "roberta-large": 512,
}

class RobertaTokenizerFast(GPT2TokenizerFast):
    """ Roberta Tokenizer

    Args:
        vocab_file (:obj:`str`):
            Path to the vocabulary file.
        merges_file (:obj:`str`):
            Path to the merges file.
        errors (:obj:`str`, `optional`, defaults to :obj:`"replace"`):
            Paradigm to follow when decoding bytes to UTF-8. See `bytes.decode
            <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__ for more information.
        bos_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
            The beginning of sequence token that was used during pretraining. Can be used a sequence classifier token.

            .. note::

                When building a sequence using special tokens, this is not the token that is used for the beginning of
                sequence. The token used is the :obj:`cls_token`.
        eos_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
            The end of sequence token.

            .. note::

                When building a sequence using special tokens, this is not the token that is used for the end of
                sequence. The token used is the :obj:`sep_token`.
        sep_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
            The separator token, which is used when building a sequence from multiple sequences, e.g. two sequences for
            sequence classification or for a text and a question for question answering. It is also used as the last
            token of a sequence built with special tokens.
        cls_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
            The classifier token which is used when doing sequence classification (classification of the whole sequence
            instead of per-token classification). It is the first token of the sequence when built with special tokens.
        unk_token (:obj:`str`, `optional`, defaults to :obj:`"<unk>"`):
            The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
            token instead.
        pad_token (:obj:`str`, `optional`, defaults to :obj:`"<pad>"`):
            The token used for padding, for example when batching sequences of different lengths.
        mask_token (:obj:`str`, `optional`, defaults to :obj:`"<mask>"`):
            The token used for masking values. This is the token used when training this model with masked language
            modeling. This is the token which the model will try to predict.
        add_prefix_space (:obj:`bool`, `optional`, defaults to :obj:`False`):
            Whether or not to add an initial space to the input. This allows to treat the leading word just as any
            other word. (RoBERTa tokenizer detect beginning of words by the preceding space).
        trim_offsets (:obj:`bool`, `optional`, defaults to :obj:`True`):
            Whether the post processing step should trim offsets to avoid including whitespaces.
    """

    vocab_files_names = VOCAB_FILES_NAMES
    max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
    model_input_names = ["input_ids", "attention_mask"]
    slow_tokenizer_class = RobertaTokenizer

    def __init__(
        self,
        vocab_file,
        merges_file,
        tokenizer_file=None,
        errors="replace",
        bos_token="<s>",
        eos_token="</s>",
        sep_token="</s>",
        cls_token="<s>",
        unk_token="<unk>",
        pad_token="<pad>",
        mask_token="<mask>",
        add_prefix_space=False,
        **kwargs
    ):
        super().__init__(
            vocab_file,
            merges_file,
            tokenizer_file=tokenizer_file,
            errors=errors,
            bos_token=bos_token,
            eos_token=eos_token,
            sep_token=sep_token,
            cls_token=cls_token,
            unk_token=unk_token,
            pad_token=pad_token,
            mask_token=mask_token,
            add_prefix_space=add_prefix_space,
            **kwargs,
        )

    @property
    def mask_token(self) -> str:
        """
        :obj:`str`: Mask token, to use when training a model with masked-language modeling. Log an error if used while
        not having been set.

        Roberta tokenizer has a special mask token to be usable in the fill-mask pipeline. The mask token will greedily
        comprise the space before the `<mask>`.
        """
        if self._mask_token is None and self.verbose:
            logger.error("Using mask_token, but it is not set yet.")
            return None
        return str(self._mask_token)

    @mask_token.setter
    def mask_token(self, value):
        """
        Overriding the default behavior of the mask token to have it eat the space before it.

        This is needed to preserve backward compatibility with all the previously used models based on Roberta.
        """
        # Mask token behave like a normal word, i.e. include the space before it
        # So we set lstrip to True
        value = AddedToken(value, lstrip=True, rstrip=False) if isinstance(value, str) else value
        self._mask_token = value

    def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
        output = [self.bos_token_id] + token_ids_0 + [self.eos_token_id]
        if token_ids_1 is None:
            return output

        return output + [self.eos_token_id] + token_ids_1 + [self.eos_token_id]

    def create_token_type_ids_from_sequences(
        self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
    ) -> List[int]:
        """
        Create a mask from the two sequences passed to be used in a sequence-pair classification task. RoBERTa does not
        make use of token type ids, therefore a list of zeros is returned.

        Args:
            token_ids_0 (:obj:`List[int]`):
                List of IDs.
            token_ids_1 (:obj:`List[int]`, `optional`):
                Optional second list of IDs for sequence pairs.

        Returns:
            :obj:`List[int]`: List of zeros.
        """
        sep = [self.sep_token_id]
        cls = [self.cls_token_id]

        if token_ids_1 is None:
            return len(cls + token_ids_0 + sep) * [0]
        return len(cls + token_ids_0 + sep + sep + token_ids_1 + sep) * [0]


#****************************************************************************
#* setup.py for debug-mgr
#****************************************************************************
import os
import subprocess
import sys
from setuptools import setup
from distutils.extension import Extension
from setuptools.command.build_ext import build_ext as _build_ext
from distutils.file_util import copy_file

if "-DDEBUG" in sys.argv:
    _DEBUG = True
    sys.argv.remove("-DDEBUG")
else:
    _DEBUG = False

_DEBUG_LEVEL = 0

version="0.0.1"

if "BUILD_NUM" in os.environ.keys():
    version += ".%s" % os.environ["BUILD_NUM"]

if "CMAKE_BUILD_TOOL" in os.environ.keys():
    cmake_build_tool = os.environ["CMAKE_BUILD_TOOL"]
else:
    cmake_build_tool = "Ninja"

# First need to establish where things are
debug_mgr_dir = os.path.dirname(os.path.abspath(__file__))

if os.path.isdir(os.path.join(debug_mgr_dir, "packages")):
    print("Packages are inside this directory")
    packages_dir = os.path.join(debug_mgr_dir, "packages")
else:
    parent = os.path.dirname(debug_mgr_dir)

    if os.path.isdir(os.path.join(parent, "debug-mgr")):
        print("debug-mgr is a peer")
        packages_dir = parent
    else:
        raise Exception("Unexpected source layout")

# Now, build the core tblink-rpc-hdl library
cwd = os.getcwd()
if not os.path.isdir(os.path.join(cwd, "build")):
    os.makedirs(os.path.join(cwd, "build"))

if _DEBUG:
    BUILD_TYPE = "-DCMAKE_BUILD_TYPE=Debug"
else:
    BUILD_TYPE = "-DCMAKE_BUILD_TYPE=Release"

env = os.environ.copy()
python_bindir = os.path.dirname(sys.executable)
print("python_bindir: %s" % str(python_bindir))

if "PATH" in env.keys():
    env["PATH"] = python_bindir + os.pathsep + env["PATH"]
else:
    env["PATH"] = python_bindir

# Run configure...
result = subprocess.run(
    ["cmake",
     debug_mgr_dir,
     "-G%s" % cmake_build_tool,
     BUILD_TYPE,
     "-DPACKAGES_DIR=%s" % packages_dir,
     "-DCMAKE_INSTALL_PREFIX=%s" % os.path.join(cwd, "build"),
     "-DCMAKE_OSX_ARCHITECTURES='x86_64;arm64'",
     ],
    cwd=os.path.join(cwd, "build"),
    env=env)

if result.returncode != 0:
    raise Exception("cmake configure failed")

if cmake_build_tool == "Ninja":
    result = subprocess.run(
        ["ninja",
         "-j",
         "%d" % os.cpu_count()
        ],
        cwd=os.path.join(cwd, "build"),
        env=env)
elif cmake_build_tool == "Unix Makefiles":
    result = subprocess.run(
        ["make",
         "-j%d" % os.cpu_count()
        ],
        cwd=os.path.join(cwd, "build"),
        env=env)
else:
    raise Exception("Unknown make system %s" % cmake_build_tool)

if result.returncode != 0:
    raise Exception("build failed")

if cmake_build_tool == "Ninja":
    result = subprocess.run(
        ["ninja",
         "-j",
         "%d" % os.cpu_count(),
         "install"
        ],
        cwd=os.path.join(cwd, "build"),
        env=env)
elif cmake_build_tool == "Unix Makefiles":
    result = subprocess.run(
        ["make",
         "-j%d" % os.cpu_count(),
         "install"
        ],
        cwd=os.path.join(cwd, "build"),
        env=env)
else:
    raise Exception("Unknown make system %s" % cmake_build_tool)

if result.returncode != 0:
    raise Exception("build failed")

extra_compile_args = []
if _DEBUG:
    extra_compile_args += ["-g", "-O0", "-DDEBUG=%s" % _DEBUG_LEVEL, "-UNDEBUG"]
else:
    extra_compile_args += ["-DNDEBUG", "-O3"]

if sys.platform == "darwin":
    extra_compile_args += ["-std=c++11"]

class build_ext(_build_ext):
    def run(self):
        super().run()

    # Needed for Windows to not assume python module (generate interface in def file)
    def get_export_symbols(self, ext):
        return None

    def copy_extensions_to_source(self):
        """ Like the base class method, but copy libs into proper directory in develop. """
        print("copy_extensions_to_source")
        super().copy_extensions_to_source()

        build_py = self.get_finalized_command("build_py")

        ext = self.extensions[0]
        fullname = self.get_ext_fullname(ext.name)
        filename = self.get_ext_filename(fullname)
        modpath = fullname.split(".")
        package = ".".join(modpath[:-1])
        package_dir = build_py.get_package_dir(package)

        if sys.platform == "darwin":
            ext = ".dylib"
        elif sys.platform == "win32":
            ext = ".dll"
        else:
            ext = ".so"

        if sys.platform == "win32":
            pref = ""
        else:
            pref = "lib"

        copy_file(
            os.path.join(cwd, "build", "src", "%sdebug-mgr%s" % (pref, ext)),
            os.path.join(package_dir, "%sdebug-mgr%s" % (pref, ext)))

        if sys.platform == "win32":
            copy_file(
                os.path.join(cwd, "build", "src", "debug-mgr.lib" ),
                os.path.join(package_dir, "debug-mgr.lib" % (pref, ext)))

        dest_filename = os.path.join(package_dir, filename)

        print("package_dir: %s dest_filename: %s" % (package_dir, dest_filename))

print("extra_compile_args=" + str(extra_compile_args))

if sys.platform == "darwin":
    libext = ".dylib"
    libpref = "lib"
elif sys.platform == "win32":
    libext = ".dll"
    libpref = "lib"
else:
    libext = ".so"
    libpref = "lib"

if sys.platform == "win32":
    package_data = [
        "debug-mgr.dll",
        "debug-mgr.lib"
    ]
else:
    package_data = [
        "%sdebug-mgr.%s" % (libpref, libext)
    ]

ext = Extension("debug_mgr.core",
            extra_compile_args=extra_compile_args,
            sources=[
                os.path.join(debug_mgr_dir, 'python', "core.pyx"),
            ],
            language="c++",
            include_dirs=[
                os.path.join(debug_mgr_dir, 'src'),
                os.path.join(debug_mgr_dir, 'src', 'include')
            ]
        )
ext.cython_directives={'language_level' : '3'}

setup(
  name = "debug-mgr",
  version=version,
  packages=['debug_mgr'],
  package_dir = {'' : 'python'},
  package_data={ 'debug_mgr': package_data },
  author = "Matthew Ballance",
  author_email = "matt.ballance@gmail.com",
  description = ("Simple debug manager for use of C++ Python extensions"),
  long_description="""
  Simple debug manager for use of C++ Python extensions
  """,
  license = "Apache 2.0",
  keywords = ["Debug", "C/C++", "Python"],
  url = "https://github.com/mballance/debug-mgr",
  install_requires=[
  ],
  setup_requires=[
    'setuptools_scm',
    'cython'
  ],
  cmdclass={'build_ext': build_ext},
  ext_modules=[ ext ]
)


import re
import sys
import datetime

import bork.config as CV

from enum import Enum

# -----------------------------------------------------------------------------
# Observable States
# RegEx pattern to parse the logcat file (wearable)
# -----------------------------------------------------------------------------

# Timestamp in the following format MM-DD hi:mi:ss.ms (e.g., 05-31 13:11:07.252)
PATTERN_TS = '(\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) '

# (1) Inter-device communication
# The trace identifies a communication between the mobile and wearable; either by message or data sync.

PATTERN_WLS_MSG_RCV = '(.*)/WearableLS\((.*)\): onMessageReceived: ComponentInfo{(.*)} MessageEventParcelable\[(\d+),(.*), size=(\d+)\]'
PATTERN_WLS_DAT_CHG = '(.*)/WearableLS\((.*)\): onDataItemChanged: ComponentInfo{(.*)} (.*), rows=(\d+)'

# (2) Sensor activity
# The trace is different depending of the device. However, if the sensor is activated using Google Fitness API there
# is no trace in the logcat.

#  Motorola Moto 360
PATTERN_SNS_MOTO360 = '(.*)/SensorHAL\((.*)\): poll__activate: sensor\_handle: (\d+) enabled: (\d)'

#  Huawei Watch 2
PATTERN_SNS_HAUWEI_ON  = '(.*)/shd     \((.*)\): ProcessSensorActive sensor:0x(\d+), handle:(\d)'
PATTERN_SNS_HAUWEI_OFF = '(.*)/shd     \((.*)\): ProcessSensorDeactive sensor:0x(\d+), handle:(\d)'

# (3) FCM

# NOTE: /dcsl/ This most probably will have to be done using instrumentation (e.g., Frida). Without any instrumentation
#       there is no visible trace that can be used.

# (4) Connection with paired device (mobile)
# Trace either when the bluetooth communication is lost or restablished. The communication between the devices happens
# mostly on the bluetooth channel.

PATTERN_BL_DISC = '(.*)/WearBluetooth: Companion device disconnected.'
PATTERN_BL_CONN = '(.*)/WearBluetooth: Companion device connected.'

# NOTE: /dcsl/ Another possible option could be to rely on the information from ACTION_CONNECTION_STATE_CHANGED
#       intent. The intent include more detail information about the bluetooth communication.
#       More info:
#       https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#ACTION_CONNECTION_STATE_CHANGED

# (5) Notifications

PATTERN_LOG = '\s+(\d+)\s+(\d+)\s+([A-Za-z]) ([^:]*):'

class EventType(Enum):
    """
    EventType
    Supported Events (on the wearable side).
    """
    def to_name(self):
        return str(self.name)

    Message = 1
    DataSync = 2
    Sensor = 3

class Level(Enum):
    """
    Level
    Debug level supported.
    """
    def to_name(self):
        return str(self.name)

    Verbose = 0
    Detailed = 1
    Normal = 2
    Silent = 3

def parse_log_wear(line, pkg=None):
    """
    Parse a logcat message looking for observables events on the wearable device.
    :param line: the line from logcat (wearable device)
    :param app: the application being targetted
    :return:
    """
    tags = {}

    # Message Passing
    rx_pattern = re.compile(PATTERN_TS + PATTERN_WLS_MSG_RCV)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)
        tid = match_pattern.group(3)
        package, component = match_pattern.group(4).split('/')
        action = match_pattern.group(6)

        print("{parse-log-wear} WLS Msg " + timestamp + ' * ' + package + ' * ' + component + ' * ' + action)

        if pkg is not None:
            if pkg == package:
                log_dict = {
                    'id': 'SND/' + action,
                    'timestamp': timestamp,
                    'type': EventType.Message,
                    'action': action,
                    'package': package,
                    'component': component
                }

                return log_dict

    # Data Item Sync
    rx_pattern = re.compile(PATTERN_TS + PATTERN_WLS_DAT_CHG)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)
        tid = match_pattern.group(3)
        package, component = match_pattern.group(4).split('/')
        dataholder = match_pattern.group(5)
        action = 'none'

        print("{parse-log-wear} WLS Sync " + timestamp + ' * ' + package + ' * ' + component + ' * ' + dataholder)

        if pkg is not None:
            if pkg == package:
                log_dict = {
                    'id': 'DAT/' + action,
                    'timestamp': timestamp,
                    'type': EventType.DataSync,
                    'action': action,
                    'package': package,
                    'component': component
                }
                return log_dict

    # Sensor Activity
    # Motorola Moto 360 Generation 2
    rx_pattern = re.compile(PATTERN_TS + PATTERN_SNS_MOTO360)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)
        tid = match_pattern.group(3)
        sensor_handle = match_pattern.group(4)
        sensor_status = match_pattern.group(5)

        print("{parse-log-wear} SensorHAL " + timestamp + ' * ' + tid + ' * ' + sensor_handle + ' * ' + sensor_status)

        log_dict = {
            'id': 'HAL/' + sensor_handle,
            'timestamp': timestamp,
            'type': EventType.Sensor,
            'sensor_handle': sensor_handle,
            'sensor_status': sensor_status
        }
        return log_dict

    # Huawei Watch2
    rx_pattern = re.compile(PATTERN_TS + PATTERN_SNS_HAUWEI_ON)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)
        tid = match_pattern.group(3)
        sensor = '0x'+match_pattern.group(4)
        sensor_handle = match_pattern.group(5)

        print("{parse-log-wear} SensorHAL " + timestamp + ' * ' + tid + ' * ' + sensor + ' * ' + sensor_handle)

        log_dict = {
            'id': 'HAL/' + sensor_handle,
            'timestamp': timestamp,
            'type': EventType.Sensor,
            'sensor': sensor,
            'sensor_handle': sensor_handle,
            'sensor_status': "1"
        }
        return log_dict

    # Deactivation of Sensors
    rx_pattern = re.compile(PATTERN_TS + PATTERN_SNS_HAUWEI_OFF)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)
        tid = match_pattern.group(3)
        sensor = '0x'+match_pattern.group(4)
        sensor_handle = match_pattern.group(5)

        print(
            "{parse-log-wear} SensorHAL " + timestamp + ' * ' + tid + ' * ' + sensor + ' * ' + sensor_handle)

        log_dict = {
            'id': 'HAL/' + sensor_handle,
            'timestamp': timestamp,
            'type': EventType.Sensor,
            'sensor': sensor,
            'sensor_handle': sensor_handle,
            'sensor_status': "0"
        }
        return log_dict

    # Mobile/Wearable connection
    rx_pattern = re.compile(PATTERN_TS + PATTERN_BL_CONN)
    match_pattern = rx_pattern.search(line)
    if match_pattern:
        timestamp = match_pattern.group(1)

    for tag in tags:
        print(tag)

    return None

def debug(msg, level=Level.Silent):
    if level >= CV.DEBUG_MODE:
        print("{} - {}".format(datetime.datetime.now().strftime("%Y%m%d-%H%M%S"), msg))


#!/usr/bin/env python
import ROOT
import sys,os
import pandas as pd
import argparse
parser = argparse.ArgumentParser(description="input and output names")
parser.add_argument("-i", "--input", type=str, help="Input dir lives in ../output/ ??")
parser.add_argument("-test", "--testflag", action="store_true", help="test mode")
args = parser.parse_args()
# names
dir_in = "../output/"
dir_out = "./data/"

tree_name = "WWZ"

file_in = args.input
file_suffix1 = "/NOMINAL/4l_signal.root"
file_suffix2 = "/NOMINAL/4l_background.root"

# read tree from input file and convert it to dataframe, save it to csv file
def convert(file_name, is_signal):
    # file_name example: 4l_signal ---> to open 4l_signal.root
    # will generate 4l_signal.csv in ./data/
    # is_signal should be: 0 ---- background, 1 ---- signal
    print("conversion of {0} start".format(file_name))
    fi = ROOT.TFile.Open(dir_in+file_in+"/NOMINAL/"+file_name+".root","READ")
    tree = fi.Get(tree_name)
    data, column = tree.AsMatrix(return_labels=True)
    df = pd.DataFrame(data=data, columns=column)
    df['signal'] = is_signal
    df.to_csv(dir_out+file_name+".csv")
    print("conversion complete")

convert("4l_signal", 1)
convert("4l_background", 0)
#convert("ZZ",0)
#convert("WZ",0)
#convert("ttZ",0)
#convert("tWZ",0)
#convert("other",0)


import numpy as np
import tensorflow as tf
from utils import *
from os import listdir
import imageio
import matplotlib.pyplot as plt

#load the data from file
directorySaving = './final_images/XY/'
all_datas = ['X_tr_feats', 'X_tst_feats', 'X_tr_inp', 'X_tst_inp', 'Y_tr', 'Y_tst']
X_tr = np.load(directorySaving+all_datas[0]+'.npy')
X_test = np.load(directorySaving+all_datas[1]+'.npy')
X_inp_tr = np.load(directorySaving+all_datas[2]+'.npy')
X_inp_test = np.load(directorySaving+all_datas[3]+'.npy')
Y_tr = np.load(directorySaving+all_datas[4]+'.npy')
Y_test = np.load(directorySaving+all_datas[5]+'.npy')
print('done loading data!')

#imgplot = plt.imshow(X_inp_test[0])
#plt.show()

first_time=1
if first_time:
	classes,probs=train_without_poison(X_tr=X_tr,Y_tr=Y_tr,Y_validation=Y_test,X_validation=X_test, cold=True)

	np.save('classes_normal_training.npy',classes)
	np.save('probs_normal_classes.npy',probs)

Poises = np.load('all_poisons.npy')
Adv = np.load('all_adv.npy')
other_class_prob = []
numNotMiscclassified = 0
poison_corr_class_prob = []
numPoisonCorr = 0
print(Poises.shape)
for targID, thePoison in enumerate(Poises):
	print("******************%d********************"%targID)
	target_class_probs, target_corr_pred, poison_class_probs, poison_corr_pred = train_last_layer_of_inception(advimage=Adv[targID],targetFeatRep=X_test[targID],poisonInpImage=thePoison,poisonClass=1-Y_test[targID],X_tr=X_tr,Y_tr=Y_tr,Y_validation=Y_test,X_validation=X_test, cold=True)
	other_class_prob.append(target_class_probs[0][int(1-Y_test[targID])])
	numNotMiscclassified += 1*target_corr_pred[0]
	poison_corr_class_prob.append(poison_class_probs[0][int(1-Y_test[targID])])
	numPoisonCorr += 1*poison_corr_pred[0]
print('##############################')
print('out of %d poisons, %d got correctly classified!'%(len(Poises),numPoisonCorr))
print('out of %d targets, %d got misclassified!'%(len(Y_test),len(Y_test) - numNotMiscclassified))
other_class_prob = np.array(other_class_prob)
np.save('Wrong_ClassProb_targ.npy',other_class_prob)
poison_corr_class_prob = np.array(poison_corr_class_prob)
np.save('Right_ClassProb_poison.npy',poison_corr_class_prob)


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@File    ：plan.py
@Author  ：Zeno
@Email   ：zhangyongjun@ones.ai
@Date    ：2021/12/24
@Desc    ：测试计划用例
"""
from falcons.helper import mocks
from falcons.ops import generate_param

from main.params.const import ACCOUNT

def add_member():
    """权限配置里添加用户权限"""
    return generate_param({
        'permission_rule': {
            'context_type': 'team',
            'context_param': {
                'team_uuid': ACCOUNT.user.team_uuid
            },
            'permission': 'create_gantt_chart',  # 创建甘特图的权限
            'user_domain_type': 'single_user',
            'user_domain_param': ''  # 这是待赋权的成员uuid
        }
    })

def create_gantt():
    """新建甘特图"""
    return generate_param({
        'item': {
            'name': f'Gantt-{mocks.random_string(4)}',
            'shared': False,
            'item_type': 'gantt_chart',
            'shared_to': [],
            'import_config': {
                'projects': [
                    ACCOUNT.project_uuid
                ]
            },
            'sync_from_project': True,
            'sync_to_project': True
        }
    })

def update_gantt():
    """更新甘特图"""
    return generate_param({
        'item': {
            'uuid': '',  # 甘特图UUID
            'name': 'Gantt-ugSA-new',  # 甘特图新名称
            'shared': False,
            'item_type': 'gantt_chart',
            'shared_to': []
        }
    }, **{'item_key': ''})

# =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

def create_task():
    """新建甘特图-任务"""
    return generate_param({
        'item': {
            'name': f'Task-{mocks.random_string(4)}',
            'item_type': 'gantt_data',
            'gantt_data_type': 'task',
            'gantt_chart_uuid': '',  # 甘特图UUID
            'plan_start_time': mocks.now_timestamp(),
            'plan_end_time': mocks.day_timestamp(),
            'parent': '',
            'assign': None
        }
    })

def update_task():
    """更新甘特图-任务"""
    return generate_param({
        'item': {
            'uuid': '',  # 任务UUID
            'name': f'Task-new-{mocks.random_string(4)}',
            'item_type': 'gantt_data',
            'gantt_data_type': 'task',
            'gantt_chart_uuid': '',  # 甘特图UUID
            'plan_start_time': mocks.day_timestamp(1),
            'plan_end_time': mocks.day_timestamp(3),
            'assign': ACCOUNT.user.owner_uuid,
            'progress': 1000000  # 进度改为10%
        }
    })

def delete_item():
    """删除工作项"""
    return generate_param({})

def task_to_group():
    """
    任务改为分组 ItemUpdate
    :return:
    """
    return generate_param({
        'item': {
            'gantt_data_type': 'group',
            'plan_start_time': 0,
            'plan_end_time': 0,
            'progress': 0
        }
    })

def task_to_milestone():
    """
    任务改为里程碑 ItemUpdate
    :return:
    """
    return generate_param({
        'item': {
            'gantt_data_type': 'milestone',
            'plan_start_time': 14400,
            'plan_end_time': 14400
        }
    })

def group_to_task():
    """
    分组改为任务 ItemUpdate
    :return:
    """
    return generate_param({
        'item': {
            'gantt_data_type': 'task',
            'plan_start_time': mocks.now_timestamp(),
            'plan_end_time': mocks.day_timestamp()
        }
    })

def group_to_milestone():
    """
    分组改为里程碑 ItemUpdate
    :return:
    """
    return generate_param({
        'item': {
            'gantt_data_type': 'milestone',
            'plan_start_time': mocks.day_timestamp(1),
            'plan_end_time': mocks.day_timestamp(3)
        }
    })

def create_group():
    """里程碑-创建分组"""
    return generate_param({
        'item': {
            'name': f'Group-{mocks.random_string(4)}',
            'item_type': 'gantt_data',
            'gantt_data_type': 'group',
            'gantt_chart_uuid': '',  # 甘特图UUID
            'plan_start_time': 0,
            'plan_end_time': 0,
            'parent': '',
            'assign': None
        }
    })

def update_group():
    """更新分组信息"""
    return generate_param({
        'item': {
            'uuid': '',
            'name': 'new 分组',
            'item_type': 'gantt_data',
            'gantt_data_type': 'group',
            'gantt_chart_uuid': '',
            'plan_start_time': 0,
            'plan_end_time': 0
        }
    })

def create_milestone():
    """创建里程碑"""
    return generate_param({
        'item': {
            'name': f'MILESTONE-{mocks.random_string(4).upper()}',
            'item_type': 'gantt_data',
            'gantt_data_type': 'milestone',
            'gantt_chart_uuid': '',
            'progress': 0,
            'plan_start_time': mocks.now_timestamp(),
            'plan_end_time': mocks.now_timestamp(),
            'parent': '',
            'assign': ACCOUNT.user.owner_uuid
        }
    })

def update_milestone():
    """更新里程碑"""
    return generate_param({
        'item': {
            'uuid': '',  # 里程碑UUID
            'name': f'NewMS-{mocks.random_string(4).upper()}',
            'item_type': 'gantt_data',
            'gantt_data_type': 'milestone',
            'gantt_chart_uuid': '',  # 甘特图UUID
            'progress': 10000000,  # 改为已完成
            'plan_start_time': mocks.now_timestamp(),
            'plan_end_time': mocks.now_timestamp()
        }
    })

def milestone_to_task():
    """里程碑-》task"""
    return generate_param({
        'item': {
            'gantt_data_type': 'task',
            'plan_start_time': mocks.now_timestamp(),
            'plan_end_time': mocks.day_timestamp()
        }
    })

def share_gantt():
    """共享甘特图"""
    return generate_param({
        'item': {
            'uuid': '',  # 甘特图UUID
            'name': 'SharedGantt',  # 改个名字
            'shared': True,
            'item_type': 'gantt_chart',
            'shared_to': [
                {
                    'user_domain_type': 'everyone',
                    'user_domain_param': ''
                }
            ]
        }
    })

def private_gantt():
    return generate_param({
        'item': {
            'uuid': '',  # 甘特图UUID
            'name': 'PrivateGantt',
            'shared': False,
            'item_type': 'gantt_chart',
            'shared_to': []
        }
    })

def gantt_sync_to_proj():
    """"""
    return generate_param({
        "action": "to_project",
        "uuids": [  # 需要同步的任务UUID

        ]
    })

def gantt_close_sync(stp=False, sfp=True):
    """关闭同步功能"""
    return generate_param({
        "item": {
            "uuid": '',  # 甘特图UUID
            "item_type": "gantt_chart",
            "sync_from_project": sfp,
            "sync_to_project": stp
        }
    })

# ---------------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------------
##项目计划

def get_plan_log_data(plan_uuid):
    """项目计划动态log data"""
    return generate_param({
        "query": "\n    query COMMONMESSAGES($filter: Filter) {\n      commonMessages(\n        filter: {\n          objectId_in: [\"%s\"]\n      }) {\n        key\n        uuid\n        operator\n        objectId\n        createTime\n        objectType\n        action\n        tag\n        ext\n      }\n      commonComments(\n        filter: {\n          objectId_in: [\"%s\"]\n      }) {\n        key\n        uuid\n        referenceId\n        fromUser {\n          uuid\n        }\n        toUser {\n          uuid\n        }\n        message\n        objectType\n        objectId\n        createTime\n        updateTime\n        status\n      }\n    }\n  "
                 % (plan_uuid, plan_uuid),
        "variables": {}
    })

def get_plan_chart_uuid(project_uuid=''):
    """查询项目计划的chart_uuid"""
    p_uid = project_uuid if project_uuid else ACCOUNT.project_uuid
    return generate_param({
        "query": "\n          query PPMProjectChartInfo {\n            activityCharts(\n              filter:{\n                project_in:[\"% p_uid\"]\n              }) {\n              key\n              name\n              uuid\n              drafting\n              personalConfig {\n                key\n                zooming\n                personalFields {\n                  fieldUUID\n                  sort\n                }\n              }\n              config {\n                key\n                settings\n              }\n            }\n          }\n        "
                 % p_uid})

# --------------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------------
## 项目内--里程碑组件

def add_deliverables(milestone_uuid, up_type, after=''):
    """
    新增交付物参数
    milestone_uuid：
    up_type：交付物类型
    after：前面的交付物id
    """
    return generate_param({
        "query": "\n        mutation AddDeliverable {\n          addDeliverable (project: $project name: $name type: $type after: $after milestone: $milestone) {\n            key\n          }\n        }\n      ",
        "variables": {
            "project": ACCOUNT.project_uuid,
            "name": "交付物" + mocks.num(),
            "type": up_type,
            "after": after,
            "milestone": milestone_uuid
        }
    })

def del_deliverables(key):
    """删除交付物"""
    return generate_param({
        "query": "\n        mutation DeleteDeliverable {\n          deleteDeliverable (key: $key) {\n            key\n          }\n        }\n      ",
        "variables": {
            "key": key
        }
    })

def submit_deliverables(key, content):
    """提交交付物 link wiki类型"""
    return generate_param({
        "query": "\n        mutation UpdateDeliverable {\n          updateDeliverable (key: $key content: $content) {\n            key\n          }\n        }\n      ",
        "variables": {
            "key": key,
            "content": content
        }
    })

def submit_deliverables_type(key, type):
    """更新交付物 link/wiki类型"""
    return generate_param({
        "query": "\n        mutation UpdateDeliverable {\n          updateDeliverable (key: $key type: $type) {\n            key\n          }\n        }\n      ",
        "variables": {
            "key": key,
            "type": type
        }
    })

def upload_deliverable_file(ref_id):
    """里程碑交付物 文件类型上传"""
    return generate_param({
        "type": "attachment",
        "name": "test_img_" + mocks.ones_uuid() + ".jpg",
        "ref_id": ref_id,
        "ref_type": "deliverable",
        "description": None
    })

def deliverable_list():
    """交付物组件列表"""
    return generate_param({
        "query": "\n    query DELIVERABLES($orderBy: OrderBy) {\n      deliverables (\n        orderBy: $orderBy,\n        filter: {\n          project_equal: \"%s\"\n        }\n      ) {\n        uuid\n        key\n        number\n        commitTime\n        name\n        type\n        milestone {\n          uuid\n          name\n          activityUUID\n        }\n        sourceType\n        committer{\n          name\n          uuid\n          avatar\n        }\n        content{\n          name\n          size\n          resource_uuid\n          page_uuid\n        }\n      }\n    }\n  " % ACCOUNT.project_uuid,
        "variables": {
            "orderBy": {
                "namePinyin": "ASC"
            }
        }
    })