TITLE_WINDOW = 'NCC AUTO ROI'   # 응용프로그램 이름
WINDOW_SCREEN_WIDTH = 950       # 응용프로그램 창 가로 크기
WINDOW_SCREEN_HEIGHT = 800      # 응용프로그램 창 세로 크기

'''ORB VALUE'''
ORB_SCORE = 600     # score 낮을 수록 비슷함 600 왠만 한건 리스트 에서 빼지 말고 통과
ORB_COUNT = 10      # count 높을 수록 비슷함 10 왠만 한건 리스트 에서 빼지 말고 통과

'''COMMON'''
USER_CHOICE_COUNT = 9   # 사용자 UI TOOL Threshold 선택 가능한 개수

''' FILTER '''
FILTER = ('Erosion', 'Gaussian', 'Laplace', 'Convolution', 'Canny')

''' ALGORITHM '''
ALGORITHM = ('LEVEL_1', 'LEVEL_2', 'LEVEL_3')

'''TOOL'''
DEFAULT_LEVEL_WINDOW = 800  # 초기값
DEFAULT_LEVEL_MUSCLE = 0    # 초기값

'''AUTO'''
PARAM_LEVEL_MUSCLE = 650    # 근육 초기값

'''Menu'''
THRESHOLD = 20          # 초기값
PROPERTY_MAX = 200      # roi 찾기 최대 크기
PROPERTY_MIN = 10       # roi 찾기 최소 크기

'''ROI VALUE'''
DISTANCE_LEVEL_1 = 20       # 찾아낸 Level ROI 와 처리 진행 중인 ROI 거리 20 이하 '혈관, 갑상선'
DISTANCE_LEVEL_3 = 20       # 찾아낸 Level ROI 와 처리 진행 중인 ROI 거리 20 이하 '침샘'
RANDOM_LEVEL_3 = 100        # LEVEL_3 ALGORITHM 랜덤 생성 반복 횟수
LOOP_LEVEL_2 = 50           # roi 적용할 Threshold 최대 크기 값
LOOP_LEVEL_3 = 100          # roi 적용할 Threshold 최대 크기 값
MINIMUM_DIMENSIONS = 20     # 찾아낸 ROI 최소 거리
MAX_LEVEL_COUNT = 200       # ROI 찾기 위한 레벨 처리 개수 맥스 값
ROI_SIZE_MARGIN = 1         # 찾은 Threshold 크기 마진 값

'''COLOR'''
ROI_COLOR = [(13, 214, 242),
             (0, 128, 0),
             (0, 0, 250),
             (250, 128, 250),
             (128, 128, 250),
             (0, 250, 200),
             (0, 250, 0),
             (255, 0, 0),
             (30, 128, 128)]


import time
import jwt
import uuid
import functools

class Token:
    @classmethod
    def encrpyt_token(cls, username, exp_time=None, secret=None):
        """
        jwt加密
        :param username:
        :param exp_time:
        :param secret:
        :return:
        """
        if not exp_time:
            exp_time = time.time() + 60 * 30

        if not secret:
            secret = 'ngt777'

        payloads = {
            'iss': 'ngt777 Is The JWT\'s Builder',  # 该JWT的签发者，是否使用是可以选择的。
            # 'sub': '',  # sub：该JWT所面向的用户，是否使用是可选的。
            # 'aud': '',  # aud：接收该JWT的一方，是否使用是可选的。
            'iat': time.time(),  # iat（issued at）：在什么时候签发UNIX时间，是否使用是可选的。
            'username': username,
            'uuid': str(uuid.uuid1()),
            "exp": exp_time,  # exp（expires）：什么时候过期，是一个UNIX的时间戳，是否使用是可选的。默认设置为：30分钟
            # "nbf": ""  # nbf（not before）：如果当前时间在nbf的时间之前，则Token不被接受，一般都会留几分钟，是否使用是可选的。
        }
        encoded_jwt = jwt.encode(payloads, secret, algorithm='HS256')
        return encoded_jwt

    @classmethod
    def decrypt_token(cls, token, secret=None):
        """
        jwt解密
        :param token:
        :param secret:
        :return:
        """
        try:
            if not secret:
                secret = 'ngt777'
            decode_jwt = jwt.decode(token, secret, algorithms=['HS256'])

            return decode_jwt
        except jwt.exceptions.InvalidSignatureError as e:
            return {'error': 'Signature verification failed'}

def access_token_required():
    def decorator(f):
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            # token = "一般从请求头获取"
            token = Token().encrpyt_token('martin')
            decryptToken = Token().decrypt_token(token)
            if token and decryptToken.get('username') == '111':
                return f(*args, **kwargs)
            else:
                raise {'error': 'token verification failed!'}

        return wrapper

    return decorator

# Example
@access_token_required
def func():
    return


std_ids = []
students = []
instructors = []
courses = []
inst_ids = []

class Course:
    course_code = 0
    course_name = ""
    def __init__(self, cc, cn):
        self.course_code = cc
        self.course_name = cn

class Student:
    id = 0
    name = ""
    courses_taken = []
    def __init__(self, id, name, courses_taken):
        self.id = id
        self.name = name
        self.courses_taken = courses_taken

class Instructor:
    id = 0
    name = ""
    courses_given = []
    def __init__(self, id, name, courses_given):
        self.id = id
        self.name = name
        self.courses_given = courses_given

"""
Currently unused helper functions.
"""
def addStudent(id, name, ct):
    if id in std_ids:
        print("You cannot add a std with this id")
    else:
        std_ids.append(id)
        s = Student(id, name, ct)
        students.append(s)

def addInstructor(id, name, cg):
    if id in std_ids:
        print("You cannot add an instr with this id")
    else:
        inst_ids.append(id)
        s = Instructor(id, name, cg)
        instructors.append(s)

def getStudents():
    return students

def getInstructors():
    return instructors

def getCourses():
    return courses

def removeStudent(id):
    for std in students:
        if std.id == id:
            students.remove(std)

def removeStudents(ids):
    for id in ids:
        removeStudent(id)

def getInstructorName(id):
    for i in instructors:
        if i.id == id:
            return i.name
    return ""


import os

treebankPrefix = {'en': 'ud-treebanks-v2.3/UD_English-EWT/en_ewt-ud-', 'fr':'ud-treebanks-v2.3/UD_French-GSD/fr_gsd-ud-', 'it':'ud-treebanks-v2.3/UD_Italian-ISDT/it_isdt-ud-', 'sp':'ud-treebanks-v2.3/UD_Spanish-GSD/es_gsd-ud-'}

def genPosData(inFile, outFile):
    cmd = 'grep -v "^#" ' + inFile + ' | cut -f 2,4 > ' + outFile
    os.system(cmd)

if not os.path.exists('models'):
    os.mkdir('models')

for lang in treebankPrefix:
    print('Train POS tagger for {}'.format(lang))

    trainDep = treebankPrefix[lang] + 'train.conllu'
    trainPos = treebankPrefix[lang] + 'train.pos'
    genPosData(trainDep, trainPos)
    devDep = treebankPrefix[lang] + 'dev.conllu'
    devPos = treebankPrefix[lang] + 'dev.pos'
    genPosData(devDep, devPos)

    cmd = 'cd bilstm-aux && python3 src/structbilty.py --train ../' + trainPos + ' --dev ../' + devPos + ' --model ../models/' + lang + 'Pos && cd ..'

    print(cmd)
    # os.system(cmd)


# -*- coding: utf-8 -*-
''' Plate washer model.'''

from __future__ import division
from __future__ import print_function

__author__= "Luis C. Pérez Tato (LCPT) , Ana Ortega (AO_O) "
__copyright__= "Copyright 2020, LCPT, AO_O"
__license__= "GPL"
__version__= "3.0"
__email__= "l.pereztato@ciccp.es, ana.ortega@ciccp.es "

# from misc_utils import log_messages as lmsg
from connections.steel_connections import bolts

class SquarePlateWasher(object):
    ''' Base class for plate washers. This class must be code agnostic
        i.e. no AISC, EC3, EAE clauses here.

    :ivar bolt: bolt.
    :ivar side: plate side.
    :ivar thickness: plate thickness.
    :ivar steelType: steel type.
    '''
    def __init__(self, bolt, side= None, thickness= None, steelType= None):
        ''' Constructor.

        :param bolt: bolt.
        :param side: plate side (if None compute automatically).
        :param thickness: plate thickness (defaults to nut height).
        :param steelType: steel type.
        '''
        self.bolt= bolt
        if(thickness):
            self.thickness= thickness
        else:
            self.thickness= bolt.getNut().getMaxHeight()
        if(side):
            self.side= side
        else:
            self.side= self.getMinSide()
        self.steelType= steelType

    def getNut(self):
        ''' Return a nut object that corresponds to the bolt.'''
        return self.bolt.getNut()

    def getMinSide(self):
        ''' Return the minimum side of the plate to take full
            advantage of its thickness.'''
        nut= self.getNut()
        e= nut.getWidthAcrossCorners()
        return e+2.0*self.thickness

    def getBearingArea(self):
        ''' Return the bearing area of the plate washer.'''
        s= min(self.side, self.getMinSide())
        retval= s*s-self.bolt.getArea()
        return retval

    def getDict(self):
        ''' Put member values in a dictionary.'''
        retval= {'bolt':self.bolt.getDict()}
        retval['thickness']= self.thickness
        retval['side']= self.side
        steelTypeClassName= str(self.steelType.__class__)[8:-2]
        retval.update({'steelTypeClassName':steelTypeClassName, 'steelType':self.steelType.getDict()})
        return retval

    def setFromDict(self,dct):
        ''' Read member values from a dictionary.'''
        self.bolt= bolts.BoltBase(diameter= None)
        self.bolt.setFromDict(dct['bolt'])
        self.thickness= dct['thickness']
        self.side= dct['side']
        steelTypeClassName= dct['steelTypeClassName']+'()'
        self.steelType= eval(steelTypeClassName)
        self.steelType.setFromDict(dct['steelType'])


import numpy as np
import matplotlib.pyplot as plt

# import data
off = np.loadtxt('off.txt')
on = np.loadtxt('on.txt')

# make complex numpy array with data
complex_data_off = np.empty(16000, dtype=complex)
complex_data_off.real = off[:16000]
complex_data_off.imag = on[16000:]

# compute fourier transform
fourier_off = np.fft.fft(complex_data_off)
# sample rate is 62.5e6 Hz, spacing is inverse
sample_spacing = 1.6e-8
fourier_axis_off = np.fft.fftfreq(n=len(complex_data_off), d=sample_spacing)
# fourier filter
fourier_off[0] = 0

# make complex numpy array with data
complex_data_on = np.empty(16000, dtype=complex)
complex_data_on.real = on[:16000]
complex_data_on.imag = off[16000:]

# compute fourier transform
fourier_on = np.fft.fft(complex_data_on)
# sample rate is 62.5e6 Hz, spacing is inverse
sample_spacing = 1.6e-8
fourier_axis_on = np.fft.fftfreq(n=len(complex_data_on), d=sample_spacing)
# fourier filter
fourier_on[0] = 0

# plot results
off_power = np.abs(np.fft.fftshift(fourier_off))**2
on_power = np.abs(np.fft.fftshift(fourier_on))**2
#plt.plot(fourier_axis_off, off_power, label="off")
#plt.plot(fourier_axis_on, on_power, label="on")
plt.plot(fourier_axis_on, (on_power/off_power)*260, label="div")
#plt.yscale('log')
plt.ylabel(r'Brightness Temperature $T_B$')
plt.xlabel(r'$\nu$ Hz')
plt.grid()
plt.legend()
plt.show()
#plt.savefig('tempdiff.png')


import torchvision
import torch
import torch.nn as nn
import torch.nn.functional as F

class Vgg_Deeplab(nn.Module):
    def __init__(self,*args, **kwargs):
        super(Vgg_Deeplab, self).__init__()
        vgg16 = torchvision.models.vgg16()

        layers = []
        layers.append(nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.MaxPool2d(3, stride=2, padding=1))

        layers.append(nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.MaxPool2d(3, stride=2, padding=1))

        layers.append(nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.MaxPool2d(3, stride=2, padding=1))

        layers.append(nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.MaxPool2d(3, stride=1, padding=1))

        layers.append(nn.Conv2d(512,
                                512,
                                kernel_size=3,
                                stride=1,
                                padding=2,
                                dilation=2))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(512,
                                512,
                                kernel_size=3,
                                stride=1,
                                padding=2,
                                dilation=2))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.Conv2d(512,
                                512,
                                kernel_size=3,
                                stride=1,
                                padding=2,
                                dilation=2))
        layers.append(nn.ReLU(inplace=True))
        layers.append(nn.MaxPool2d(3, stride=1, padding=1))
        self.features = nn.Sequential(*layers)

        classifier = []
        classifier.append(nn.AvgPool2d(3, stride=1, padding=1))
        classifier.append(nn.Conv2d(512,
                                    1024,
                                    kernel_size=3,
                                    stride=1,
                                    padding=12,
                                    dilation=12))
        classifier.append(nn.ReLU(inplace=True))
        classifier.append(nn.Dropout(p=0.5))
        self.classifier = nn.Sequential(*classifier)

        self.init_weights()

    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

    def init_weights(self):
        vgg = torchvision.models.vgg16(pretrained=True)
        state_vgg = vgg.features.state_dict()
        self.features.load_state_dict(state_vgg)

        for ly in self.classifier.children():
            if isinstance(ly, nn.Conv2d):
                nn.init.kaiming_normal_(ly.weight, a=1)
                nn.init.constant_(ly.bias, 0)

    def get_1x_lr_params(self):
        """
        This generator returns all the parameters for the last layer of the net,
        which does the classification of pixel into classes
        """
        # b = []
        #
        # b.append(self.conv1)
        # b.append(self.bn1)
        # b.append(self.layer1)
        # b.append(self.layer2)
        # b.append(self.layer3)
        # b.append(self.layer4)

        for i in self.features:
            #for j in self.features[i].modules():
            jj = 0
            for k in i.parameters():
                jj += 1
                if k.requires_grad:
                    yield k

    def optim_parameters_1x(self, args):
        return [{"params": self.get_1x_lr_params(), "lr": 1 * args.learning_rate}]

    def get_10x_lr_params(self):
        """
        This generator returns all the parameters for the last layer of the net,
        which does the classification of pixel into classes
        """
        # b = []
        # b.append(self.layer.parameters())

        for i in self.classifier:
            #for j in self.classifier[i].modules():
            jj = 0
            for k in i.parameters():
                jj += 1
                if k.requires_grad:
                    yield k

    def optim_parameters_10x(self, args):
        return [{"params": self.get_10x_lr_params(), "lr": 10 * args.learning_rate}]

if __name__ == "__main__":
    net = Vgg_Deeplab(3, 10)
    in_ten = torch.randn(1, 3, 224, 224)
    out = net(in_ten)
    print(out.size())

    in_ten = torch.randn(1, 3, 64, 64)
    mod = nn.Conv2d(3,
                    512,
                    kernel_size=3,
                    stride=1,
                    padding=2,
                    dilation=2)
    out = mod(in_ten)
    print(out.shape)


import time
import yaml
import gym
import numpy as np
from argparse import Namespace
import concurrent.futures

# import your drivers here
from drivers.follow_the_gap import GapFollower
from drivers.starting_point import SimpleDriver
from drivers.ctq import CTQmk4
from drivers.disparity import DisparityExtender

#Visualisation
from LidarVis import Visualiser, calc_end_pos

def race(drivers=[DisparityExtender()],
         racetrack='TRACK_1',
         vis_driver_idx=0,
         visualise_lidar=True):
    """
    :param racetrack: (TRACK_1, TRACK_2, TRACK_3, OBSTACLES)
    :param drivers: A list of classes with a process_lidar
    function.
    """
    with open('maps/{}.yaml'.format(racetrack)) as map_conf_file:
        map_conf = yaml.load(map_conf_file, Loader=yaml.FullLoader)
    scale = map_conf['resolution'] / map_conf['default_resolution']
    starting_angle = map_conf['starting_angle']
    env = gym.make('f110_gym:f110-v0', map="maps/{}".format(racetrack),
            map_ext=".png", num_agents=len(drivers), disable_env_checker = True)
    # specify starting positions of each agent
    poses = np.array([[-1.25*scale + (i * 0.75*scale), 0., starting_angle] for i in range(len(drivers))])
    if visualise_lidar:
        vis = Visualiser()
    obs, step_reward, done, info = env.reset(poses=poses)
    env.render()

    laptime = 0.0
    start = time.time()

    while not done:
        actions = []
        futures = []
        with concurrent.futures.ThreadPoolExecutor() as executor:
            for i, driver in enumerate(drivers):
                output = executor.submit(
                    driver.process_lidar,
                    obs['scans'][i])
                futures.append(output)
        for future in futures:
            speed, steer = future.result()
            print(speed,steer)
            # steer  -2 to 2
            # speed 0 to 10
            actions.append([steer, speed])
        actions = np.array(actions)
        obs, step_reward, done, info = env.step(actions)
        if visualise_lidar and vis_driver_idx >= 0 and vis_driver_idx < len(drivers):
            proc_ranges = obs['scans'][vis_driver_idx]
            vis.step(proc_ranges)
        laptime += step_reward
        env.render(mode='human')
        if obs['collisions'].any() == 1.0:
            break
    print('Sim elapsed time:', laptime, 'Real elapsed time:', time.time()-start)

if __name__ == "__main__":
    race()


class IppCode21:
    instructions = [
        "MOVE",
        "CREATEFRAME",
        "PUSHFRAME",
        "POPFRAME",
        "DEFVAR",
        "CALL",
        "RETURN",
        # Data Stack Instructions
        "PUSHS",
        "POPS",
        # Arithmetic, Relation, Boolean, and Conversion Intstructions
        "ADD",
        "SUB",
        "MUL",
        "IDIV",
        "LT",
        "GT",
        "EQ",
        "AND",
        "OR",
        "NOT",
        "INT2CHAR",
        "STRI2INT",
        # Input, Output Instructions
        "READ",
        "WRITE",
        # String Instructions
        "CONCAT",
        "STRLEN",
        "GETCHAR",
        "SETCHAR",
        # Type Instructions
        "TYPE",
        # Flow Instructions
        "LABEL",
        "JUMP",
        "JUMPIFEQ",
        "JUMPIFNEQ",
        "EXIT",
        # Debugging Instructions
        "DPRINT",
        "BREAK",
        # Float extension
        "INT2FLOAT",
        "FLOAT2INT",
        "DIV",
    ]

    stack_instructions = [
        "CLEARS",
        "ADDS",
        "SUBS",
        "MULS",
        "IDIVS",
        "LTS",
        "GTS",
        "EQS",
        "ANDS",
        "ORS",
        "NOTS",
        "INT2CHARS",
        "STRI2INTS",
        "JUMPIFEQS",
        "JUMPIFNEQS",
    ]


# coding: utf-8

# In[1]:

# import packages
from collections import deque # list-like data structure, for contrail of object
import numpy as np
import argparse
import imutils
import cv2
import csv
import os

# In[ ]:

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument('-v', '--video', # '--video' video file path
               help = 'path to the video file')
ap.add_argument('-b', '--buffer', type = int, default = 64, # '--buffer' -> max size of deque -> length of contrail
               help = 'max buffer size')
args = vars(ap.parse_args())

# Circle mask
img_for_mask = cv2.imread('mask.png', 0)
ret, thres1 = cv2.threshold(img_for_mask,50,255,cv2.THRESH_BINARY)
circle_img = thres1

# define the lower & upper boundaries of the 'green'
# ball in the HSV color space, then initialize the list of tracked points
black = (0,40,100)
redLower = (10, 220, 255)
redUpper = (130, 40, 100)
white = (180,220,255)

blueLower = (55, 20, 20)
blueUpper = (135, 255, 240)

pts_red = deque(maxlen = args['buffer']) # Initialize the deque & pts
pts_blue = deque(maxlen = args['buffer'])

# if a video path was not supplied, grab the ref to the webcam
if not args.get('video', False):
    camera = cv2.VideoCapture(0)

# otherwise, grab a ref to the video file
else:
    camera = cv2.VideoCapture(args['video']) # grab a ref

timer = 0
x = 0
if os.path.exists('coord_red.csv'):
    os.remove('coord_red.csv')

if os.path.exists('coord_blue.csv'):
    os.remove('coord_blue.csv')

# Keep looping
while True:
    # grab the current frame
    (grabbed , frame_raw) = camera.read() # grabbed -> whether the frame was successfully read or not; frame -> video itself

    # if we are viewing a video and we did not grab a frame, then we have reached the end of the video
    if args.get('video') and not grabbed:
        break
    timer += (1/60)
    minute = x//3600
    second = (x%3600)//60
    frame = cv2.bitwise_and(frame_raw, frame_raw, mask  = circle_img)

    # resize the frame, blur it, and convert it to the HSV color space
    frame = imutils.resize(frame, width = 1500)

    # blurblue = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # construct a mask for the color "green", then perform
    # a series of dilations and erosions to remove any small blobs left in the mask
    mask_red1 = cv2.inRange(hsv, black, redLower)
    mask_red2 = cv2.inRange(hsv, redUpper, white)
    mask_red = cv2.bitwise_or(mask_red1,mask_red2)

    # mask_red = cv2.inRange(hsv, redLower, redUpper) # give a binary mask
    mask_red = cv2.erode(mask_red, None, iterations = 2) # remove small blobs on mask
    mask_red = cv2.dilate(mask_red, None, iterations = 2)

    mask_blue = cv2.inRange(hsv, blueLower, blueUpper) # give a binary mask
    mask_blue = cv2.erode(mask_blue, None, iterations = 2) # remove small blobs on mask
    mask_blue = cv2.dilate(mask_blue, None, iterations = 2)

    # find contours in the mask and initialize the current (x,y) center of the ball
    cnts_red = cv2.findContours(mask_red.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
    cnts_blue = cv2.findContours(mask_blue.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
    center_red = None
    center_blue = None

    # only procced if at least one contour was found
    if len(cnts_red) > 0:
        # find the largest contour in the mask, then use it to compute the minimum enclosing circle and centroid
        c_red = max(cnts_red, key = cv2.contourArea)
        ((x_red, y_red), radius_red) = cv2.minEnclosingCircle(c_red)
        M_red = cv2.moments(c_red)
        center_red = (int(M_red['m10'] / M_red['m00']), int(M_red['m01'] / M_red['m00']))

        # only proceed if the radius meets a minimum size
        if radius_red > 4 and radius_red < 18:
            # draw the circle and centroid on the frame, then update the list of tracked points
            cv2.circle(frame, (int(x_red), int(y_red)), int(radius_red), (0, 255, 255), 2)
            # cv2.circle(frame, center, 5, (0, 0, 255), -1)

            coord_red = '%f, %f, %f\n' % (x_red, y_red, timer)
            with open('coord_red.txt', 'a') as red:
                red.write(coord_red)

    if len(cnts_blue) > 0:
        # find the largest contour in the mask, then use it to compute the minimum enclosing circle and centroid
        c_blue = max(cnts_blue, key = cv2.contourArea)
        ((x_blue, y_blue), radius_blue) = cv2.minEnclosingCircle(c_blue)
        M_blue = cv2.moments(c_blue)
        center_blue = (int(M_blue['m10'] / M_blue['m00']), int(M_blue['m01'] / M_blue['m00']))

        # only proceed if the radius meets a minimum size
        if radius_blue > 3 and radius_blue < 12:
            # draw the circle and centroid on the frame, then update the list of tracked points
            cv2.circle(frame, (int(x_blue), int(y_blue)), int(radius_blue), (255, 255, 0), 2)
            # cv2.circle(frame, center, 5, (0, 0, 255), -1)

            coord_blue = '%f, %f, %f\n' % (x_blue, y_blue, timer)
            with open('coord_blue.txt', 'a') as blue:
                blue.write(coord_blue)

        # update the points queue
        pts_red.appendleft(center_red)
        pts_blue.appendleft(center_blue)

        # draw contrail
        # loop over the set of tracked points
        for i in range(1, len(pts_red)):
            # if either of the tracked points are None, ignore them
            if pts_red[i - 1] is None or pts_red[i] is None:
                continue

            # otherwise, compute the thickness of the line and draw the connecting lines
            thickness = int(np.sqrt(args['buffer'] / float(i + 1)) * 0.5)
            cv2.line(frame, pts_red[i - 1], pts_red[i], (0, 0, 255), thickness)

        for i in range(1, len(pts_blue)):
            # if either of the tracked points are None, ignore them
            if pts_blue[i - 1] is None or pts_blue[i] is None:
                continue

            # otherwise, compute the thickness of the line and draw the connecting lines
            thickness = int(np.sqrt(args['buffer'] / float(i + 1)) * 0.5)
            cv2.line(frame, pts_blue[i - 1], pts_blue[i], (255, 0, 0), thickness)

    clock = '%d min  %d sec' % (minute, second)
    x += 1
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(frame, clock, (1100, 700), font, 1, (255,255,255), 2, cv2.LINE_AA)
    cv2.circle(frame, (1100, 600), 5, (0, 0, 255), 1)
    cv2.circle(frame, (1100, 600), 10, (0, 255, 255), 1)
    cv2.circle(frame, (1100, 600), 15, (0, 255, 0), 1)
    cv2.circle(frame, (1100, 600), 20, (255, 255, 0), 1)
    cv2.circle(frame, (1100, 600), 25, (255, 0, 0), 1)
    cv2.putText(frame, '5, 10, 15, 20, 25', (1100, 500), font, 1, (255,255,255), 2, cv2.LINE_AA)

    # show the frame to our screen
    #cv2.imshow('mask_red', mask_red)
    #cv2.imshow('mask_blue', mask_blue)
    cv2.imshow('Frame', frame)
    cv2.imshow('mask_red', mask_red)
    cv2.imshow('mask_blue', mask_blue)
    key = cv2.waitKey(1) & 0xff

    # if the 'q' key is pressed, stop the loop
    if key == ord('q'):
        break

# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()

with open ('coord_red.csv', 'w') as csvfile:
    temp = csv.writer(csvfile, dialect = 'excel')
    with open('coord_red.txt', 'r') as filein:
        for line in filein:
            line_list = line.strip('\n').split(',')
            temp.writerow(line_list)

with open ('coord_blue.csv', 'w') as csvfile:
    temp = csv.writer(csvfile, dialect = 'excel')
    with open('coord_blue.txt', 'r') as filein:
        for line in filein:
            line_list = line.strip('\n').split(',')
            temp.writerow(line_list)
os.remove('coord_red.txt')
os.remove('coord_blue.txt')


import unittest
from base.base import Base
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time,os
from case.test_add_bug import ZandaoBug
from common.HTMLTestRunner import HTMLTestRunner

class Test01(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get('http://127.0.0.1/zentao/user-login-L3plbnRhby8=.html')
        self.driver.maximize_window()
        self.zan = ZandaoBug(self.driver)
        print('这是前置操作')

    def tearDown(self):
        self.driver.close()

    def test_01(self):
        bug_time = '这是测试bug标题' + time.strftime('-%Y_%m_%d_%H_%M_%S')

        self.zan.zandao_login()
        self.zan.add_bug(bug_time)
        result = self.zan.is_add_bug_success(bug_time)
        self.assertTrue(result)

    def test_02(self):
        bug_time = '这是测试bug标题11111' + time.strftime('-%Y_%m_%d_%H_%M_%S')

        self.zan.zandao_login()
        self.zan.add_bug(bug_time)
        result = self.zan.is_add_bug_success(bug_time)
        self.assertTrue(result)


'''
There is an m x n rectangular island that borders both the Pacific Ocean and
Atlantic Ocean.The Pacific Ocean touches the island's left and top edges,
and the Atlantic Ocean touches the island's right and bottom edges.

The island is partitioned into a grid of square cells. You are given an m x n
integer matrix heights where heights[r][c] represents the height above sea
level of the cell at coordinate (r, c).

The island receives a lot of rain, and the rain water can flow to neighboring
cells directly north, south, east, and west if the neighboring cell's height is
less than or equal to the current cell's height. Water can flow from any cell
adjacent to an ocean into the ocean.

Return a 2D list of grid coordinates result where result[i] = [ri, ci] denotes
that rain water can flow from cell (ri, ci) to both the Pacific and Atlantic
oceans.
'''

class Solution:
    def pacificAtlantic(self, heights):
        # grid dim
        ROWS, COLS = len(heights), len(heights[0])

        # visit sets
        pac, atl = set(), set()

        ####
        def dfs(r, c, visited, prevHeight):
            if ((r,c) in visited) or (r not in range(ROWS)) or (c not in range(COLS)) or (heights[r][c] < prevHeight):
                return

            visited.add((r,c))
            dfs(r + 1, c, visited, heights[r][c])
            dfs(r - 1, c, visited, heights[r][c])
            dfs(r, c+1, visited, heights[r][c])
            dfs(r, c-1, visited, heights[r][c])
        ####

        # find the coastal tiles on the first and last row
        for c in range(COLS):
            # first row - pacific
            dfs(0, c, pac, heights[0][c])

            # last row - atlantic
            dfs(ROWS - 1, c, atl, heights[ROWS - 1][c])

        # find the coastal tiles on the first and last col
        for r in range(ROWS):
            # pacific
            dfs(r, 0, pac, heights[r][0])
            #atlantic
            dfs(r, COLS-1, atl, heights[r][COLS-1])

        res = []
        for r in range(ROWS):
            for c in range(COLS):
                if (r,c) in pac and (r,c) in atl:
                    res.append([r,c])
        return res


import math
def has_odd(n):
    while n > 0 and n % 10 % 2 == 0:
        n //= 10
    return n != 0

def func(x):
    return math.sin(math.cos(13*x)) + math.cos(math.log(x))

def max_on_interval(a, b):
    if (b < a):
        a, b = b, a
    if (b < 0):
        return None
    if (a <= 0):
        a = 1e-6
    range = b - a
    dx = range / 50_000
    max_y = float('-inf')
    while a <= b:
        y = func(a)
        if (y > max_y):
            max_y = y
        a += dx
    return max(max_y, func(a), func(b))

def fibonacci(n):
    if n == 0:
        return 1
    a = 0
    b = 1
    c = 1
    while c <= n:
        c = a + b
        a = b
        b = c
    return c
print(has_odd(4323213))
print(fibonacci(3))
print(max_on_interval(-10, 10))


"""Defines a custom Proband object.

"""
from datetime import datetime
from logging import getLogger
from os import remove
from os.path import exists
from os.path import join as pj
from pickle import dump, load

from .paths import proband_path

logger = getLogger(__name__)
forbidden_ids = {"TEST", ""}

class Proband(object):
    def __init__(self, **kwds) -> None:
        """Proband object.

        These objects contain information about the current proband, such as their ID,
        when they were tested, etc. This information is saved in a special .pkl file
        (really just a pickled python dictionary).

        Kwds:
            proband_id (str): The proband ID. This is the only keyword required at
            initialisation. Others will be inherited in the following order:
                1. Generic defaults.
                2. Previously saved to disk.
                3. Passed upon initialisation.
                4. Automatically determined based on `proband_id`.

        """
        logger.debug(f"initialised {type(self)} with {kwds}")
        assert "proband_id" in kwds, "proband_id must be a keyword argument"

        self.proband_id = kwds["proband_id"]
        self.filename = f"{self.proband_id}.pkl"
        self.path = pj(proband_path, self.filename)
        autos = {
            "proband_id": self.proband_id,
            "filename": self.filename,
            "path": self.path,
        }
        stored = self.load()
        defaults = {
            "proband_id": "TEST",
            "age": 1,
            "sex": "Male",
            "other_ids": set(),
            "notes": "Add notes about the proband here...",
        }
        self.data = {**defaults, **stored, **kwds, **autos}
        self.update()

        logger.debug(f"fully initialised, looks like {self.data}")

    def load(self) -> dict:
        """Load data from disk if any exist."""
        logger.debug("called load()")
        dic = {}
        if exists(self.path):
            logger.debug("data belonging to proband with this id already exists")
            dic.update(load(open(self.path, "rb")))
            dic["last_loaded"] = datetime.now()
        else:
            logger.debug("data belonging to proband with this id not found on disk")
            dic["created"] = datetime.now()
        logger.debug(f"loaded data looks like this: {dic}")
        return dic

    def save(self) -> None:
        """Dump the data. Don't do this if proband ID is TEST."""
        logger.debug("called save()")
        if self.proband_id.upper() not in forbidden_ids:
            self.backup()
            logger.debug("saving the data")
            self.data["last_saved"] = datetime.now()
            dump(self.data, open(self.path, "wb"))
        else:
            logger.debug("not saving the data: forbidden ID")
        self.update()

    def update(self) -> None:
        """Updates the attributes according to the internal dictionary."""
        logger.debug("called update()")
        self.__dict__.update(self.data)

    def delete(self) -> None:
        """Delete the proband from disk."""
        logger.debug("called delete()")
        self.backup()
        if exists(self.path):
            remove(self.path)

    def backup(self) -> None:
        """Make a backup."""
        pass
        # logger.debug("called backup()")
        # if exists(self.data["path"]):
        #     logger.warning("making a backup of previously saved data")
        #     path = self.path.replace("current", "old")
        #     for i in range(8, 0, -1):
        #         path_ = path + f".{i}"
        #         if exists(path_):
        #             move(path_, path + f"{i + 1}")
        #     move(self.path, path + ".1")


import torch
import warnings
import numpy as np
import contextlib
import wave
import webrtcvad
import tempfile
import os
from scipy import signal
import torch.nn.functional as F
import librosa
import soundfile as sf
from scipy.signal import correlate

# pylint: disable=C0413
warnings.filterwarnings("ignore")
# pylint: enable=C0413

from pydub import AudioSegment
from pydub.silence import detect_leading_silence as dls

import random

def _seg_to_array(s):
    ret = np.array(s.get_array_of_samples())
    # ret = ret / np.max(np.abs(ret))
    return np.expand_dims(ret, 0)

def shift_pitch(x, fs=16000, factor=1.1, frac=0.005):
    x = x.squeeze()
    splits = np.split(
        x[: x.shape[-1] // int(fs * frac) * int(fs * frac)],
        x.shape[-1] // int(fs * frac),
    )
    rem = x[-(x.shape[-1] % int(fs * frac)) :]
    if len(rem) > 0:
        splits.append(rem)
    for i, s in enumerate(splits):
        freq = np.fft.rfftfreq(s.shape[-1], d=1 / fs)
        sf = np.fft.rfft(s)
        y = np.zeros(shape=freq.shape, dtype=np.complex128)
        for j in range(len(y)):
            idx = int(np.floor(factor * j))
            if idx >= len(y):
                break
            y[idx] = sf[j]
        res = np.fft.irfft(y)
        splits[i] = res
    # print(str(i) + ' ' + str(len(splits)))
    out = np.array([item for arr in splits for item in arr])
    return np.expand_dims(out, 0)

def _to_bytes(x, sample_rate=16000):
    tmp = tempfile.NamedTemporaryFile(suffix=".wav")
    tmp.close()
    path = tmp.name

    sf.write(path, x.squeeze(), sample_rate)
    with contextlib.closing(wave.open(path, "rb")) as wf:
        x_bytes = wf.readframes(wf.getnframes())
    os.unlink(path)
    return x_bytes

def calcVadRate(wav):
    x = trim(wav, silence_threshold=-25.0)
    x_bytes = _to_bytes(x, 16000)
    vad = webrtcvad.Vad(3)
    n = int(16000 * (30 / 1000.0) * 2)
    frames = [x_bytes[offset : offset + n] for offset in range(0, len(x_bytes) - n, n)]
    silent = [
        idx for idx, frame in enumerate(frames) if not vad.is_speech(frame, 16000)
    ]
    return float(len(silent)) / float(len(frames))

def _vad(x, frame_duration_ms=30, aggressive=2, sample_rate=16000):
    x_bytes = _to_bytes(x, sample_rate)
    vad = webrtcvad.Vad(aggressive)
    n = int(sample_rate * (frame_duration_ms / 1000.0) * 2)
    frames = [x_bytes[offset : offset + n] for offset in range(0, len(x_bytes) - n, n)]

    voiced = [
        idx for idx, frame in enumerate(frames) if vad.is_speech(frame, sample_rate)
    ]

    win_sz = frame_duration_ms / 1000 * sample_rate
    num_frames = len(frames) + 1 if win_sz * len(frames) < x.shape[-1] else len(frames)
    x = np.pad(x.squeeze(), [0, int(num_frames * win_sz) - x.shape[-1]])

    silent = list(set(list(range(num_frames))) - set(voiced))
    silent.sort()
    voiced.sort()
    splits = np.split(x, num_frames)
    return np.stack(splits), voiced, silent

trim_leading: AudioSegment = lambda x, threshold, margin=0: x[
    np.max([0, dls(x, silence_threshold=threshold) - margin]) :
]
trim_trailing: AudioSegment = lambda x, threshold, margin=0: trim_leading(
    x.reverse(), threshold, -margin
).reverse()
strip_silence: AudioSegment = (
    lambda x, threshold, margin_l=0, margin_r=0: trim_trailing(
        trim_leading(x, threshold, margin_l), threshold, margin_r
    )
)

def silent_idx(mal, frame_duration_ms=30, aggressive=2, sample_rate=16000):
    splits, _, silent = _vad(mal, frame_duration_ms, aggressive, sample_rate)
    idx = np.array(
        [
            np.arange(i * len(splits[i]), (i + 1) * len(splits[i]))
            for i in range(len(splits))
            if i in silent
        ]
    )
    if silent[-1] == len(splits) - 1:
        idx = idx[:-1]
        rem = [np.arange((len(splits) - 1) * len(splits[0]), mal.shape[-1])]
        idx = np.concatenate((np.reshape(idx, np.prod(idx.shape)), rem[0]))
    return idx

def trim_mid(mal, frame_duration_ms=30, aggressive=2, sample_rate=16000):
    orig_len = mal.shape[-1]
    splits_m, voiced_m, silent_m = _vad(mal, frame_duration_ms, aggressive, sample_rate)
    """
    silent_m = np.tile(np.expand_dims(np.array(silent_m), -1),2).reshape((len(silent_m)*2)).tolist()
    voiced_m = voiced_m + silent_m
    voiced_m.sort()
    return splits_m[voiced_m]
    """
    return np.reshape(splits_m[voiced_m], (1, len(voiced_m) * splits_m.shape[-1]))[
        :, :orig_len
    ]

def subst_silence(mal, legit, frame_duration_ms=30, aggressive=2, sample_rate=16000):
    orig_len = mal.shape[-1]
    splits_m, _, silent_m = _vad(mal, frame_duration_ms, aggressive, sample_rate)
    splits_l, _, silent_l = _vad(
        legit, frame_duration_ms, aggressive=2, sample_rate=sample_rate
    )
    legit_silence = splits_l[silent_l]
    legit_silence = np.tile(
        legit_silence, (len(silent_m) // len(silent_l) + 1, 1)
    ).tolist()
    random.shuffle(legit_silence)
    splits_m[silent_m] = np.array(legit_silence)[: len(silent_m)]
    return np.reshape(splits_m, (1, len(splits_m) * splits_m.shape[-1]))[:, :orig_len]

def manip(x, fs=16000, factor=1.5, start_f=2000, end_f=5000, start_t=1, end_t=2):
    shape = x.shape[-1]
    f, t, Zxx = signal.stft(x, fs=fs)
    start_f = np.argmin(np.abs(f - start_f))
    end_f = np.argmin(np.abs(f - end_f))
    start_t = np.argmin(np.abs(t - start_t))
    end_t = np.argmin(np.abs(t - end_t))
    Zxx[:, start_f:end_f, start_t:end_t] *= factor
    x = signal.istft(Zxx, fs=fs)[1]
    x = x / np.max(np.abs(x))
    return x[:, :shape]

def trim_l(audio, silence_threshold=-25.0, margin=0):
    sound = AudioSegment.from_file(audio)
    stripped = trim_leading(sound, silence_threshold, margin)
    return _seg_to_array(stripped)

def trim_r(audio, silence_threshold=-25.0, margin=0):
    sound = AudioSegment.from_file(audio)
    stripped = trim_trailing(sound, silence_threshold, margin)
    return _seg_to_array(stripped)

def trim(audio, silence_threshold=-25.0, margin_l=0, margin_r=0):
    sound = AudioSegment.from_file(audio)
    stripped = strip_silence(sound, silence_threshold, margin_l, margin_r)
    return _seg_to_array(stripped)

def silence(sample, threshold=-25.0, type="leading"):
    trim_f = trim_leading if type == "leading" else trim_trailing
    padding = (
        lambda arr, start, type: (start, arr[:, :start])
        if type == "leading"
        else (-start, arr[:, -start:])
    )
    sample = AudioSegment.from_file(sample)
    start = (
        _seg_to_array(sample).shape[-1]
        - _seg_to_array(trim_f(sample, threshold=threshold)).shape[-1]
    )
    return padding(_seg_to_array(sample), start, type)

def pad_to_length(x, length):
    return np.tile(x, [1, length // x.shape[-1] + 1])[:, :length]

def freq_increase(data, lowcut, highcut, factor=1.5, fs=16000, order=5):
    need_expand = data.ndim != 1
    is_array = isinstance(data, np.ndarray)
    fft = torch.fft if not is_array else np.fft
    orig_len = data.shape[-1]

    data = fft.rfft(data.squeeze())
    b, a = signal.butter(order, [lowcut, highcut], fs=fs, btype="band")
    _, h = signal.freqz(b, a, fs=fs, worN=data.shape[-1])

    if not is_array:
        h = torch.tensor(h, device=data.device)
    h = h * (factor - 1) + 1
    data = fft.irfft(data * h, n=orig_len)
    if need_expand:
        data = np.expand_dims(data, 0) if is_array else data.unsqueeze(0)

    if is_array:
        return data  # / np.max(np.abs(data))
    return data  # / torch.max(torch.abs(data), -1).values

def butter_pass(data, lowcut, highcut, fs=16000, order=5):
    need_expand = data.ndim != 1
    is_array = isinstance(data, np.ndarray)
    fft = torch.fft if not is_array else np.fft
    orig_len = data.shape[-1]

    data = fft.rfft(data.squeeze())
    b, a = signal.butter(order, [lowcut, highcut], fs=fs, btype="band")
    _, h = signal.freqz(b, a, fs=fs, worN=data.shape[-1])

    if not is_array:
        h = torch.tensor(h, device=data.device)

    data = fft.irfft(data * h, n=orig_len)
    if need_expand:
        data = np.expand_dims(data, 0) if is_array else data.unsqueeze(0)

    if is_array:
        return data  # / np.max(np.abs(data))
    return data  # / torch.max(torch.abs(data), -1).values

def parabolic(f, x):
    xv = 1 / 2.0 * (f[x - 1] - f[x + 1]) / (f[x - 1] - 2 * f[x] + f[x + 1]) + x
    yv = f[x] - 1 / 4.0 * (f[x - 1] - f[x + 1]) * (xv - x)
    return (xv, yv)

def freq_from_autocorr(sig, fs):
    """
    Estimate frequency using autocorrelation
    """
    corr = correlate(sig, sig, mode="full")
    corr = corr[len(corr) // 2 :]
    d = np.diff(corr)
    start = np.nonzero(d > 0)[0][0]
    peak = np.argmax(corr[start:]) + start
    px, py = parabolic(corr, peak)

    return fs / px

def preemphasize(x, device="cuda:0", coef=0.97):
    need_expand = True if x.ndim == 1 else False

    isarray = isinstance(x, np.ndarray)
    if isarray:
        x = torch.tensor(x, device=device)
    x = x.unsquezze(0) if need_expand else x

    win = torch.tensor(
        np.array([-coef, 1], dtype=np.float64).reshape((1, 1, 1, 2)),
        device=x.device,
    ).type(x.type())
    x = torch.reshape(
        F.pad(x, [1, 1], "constant"), (x.shape[0], 1, 1, int(x.shape[1]) + 2)
    )
    x = F.conv2d(x, win).squeeze(1).squeeze(1)[:, :-1].type(x.type())
    x = x.squeeze() if need_expand else x
    if isarray:
        x = x.detach().cpu().numpy()
    return x

def deemphasize(x, coef=0.97):
    isarray = isinstance(x, np.ndarray)
    if not isarray:
        device = x.device
        x = x.detach().cpu().numpy()
    x = librosa.effects.deemphasis(x.squeeze(), coef=coef).reshape(x.shape)
    if not isarray:
        x = torch.tensor(x, device=device, requires_grad=True)
    return x


class Director:
    def __init__(self, keyboard_service, vido_service):
        self._keyboard_service = keyboard_service
        self._video_service = vido_service

class DirectorRFK:
    # A person who directs the game.

    def __init__(self, keyboard_service, video_service):
        self._keyboard_service = keyboard_service
        self._video_service = video_service

    def start_game(self, cast):
        # Starts the game using the given cast. Runs the main game loop.
        self._video_service.open_window()
        while self._video_service.is_window_open():
            self._get_inputs(cast)
            self._do_updates(cast)
            self._do_outputs(cast)
        self._video_service.close_window()

    def _get_inputs(self, cast):
        # Gets directional input from the keyboard and applies it to the robot.
        robot = cast.get_first_actor("robots")
        velocity = self._keyboard_service.get_direction()
        robot.set_velocity(velocity)

    def _do_updates(self, cast):
        #Updates the robot's position and resolves any collisions with artifacts.
        banner = cast.get_first_actor("banners")
        robot = cast.get_first_actor("robots")
        artifacts = cast.get_actors("artifacts")

        banner.set_text("")
        max_x = self._video_service.get_width()
        max_y = self._video_service.get_height()
        robot.move_next(max_x, max_y)

        for artifact in artifacts:
            if robot.get_position().equals(artifact.get_position()):
                message = artifact.get_message()
                banner.set_text(message)

    def _do_outputs(self, cast):
        #Draws the actors on the screen.
        self._video_service.clear_buffer()
        actors = cast.get_all_actors()
        self._video_service.draw_actors(actors)
        self._video_service.flush_buffer()


# 1438. 绝对差不超过限制的最长连续子数组
# 给你一个整数数组nums ，和一个表示限制的整数limit，请你返回最长连续子数组的长度，该子数组中的任意两个元素之间的绝对差必须小于或者等于limit 。
# 如果不存在满足条件的子数组，则返回0 。
# 示例 1：
# 输入：nums = [8, 2, 4, 7], limit = 4
# 输出：2
# 解释：所有子数组如下：
# [8] 最大绝对差 | 8 - 8 | = 0 <= 4.
# [8, 2] 最大绝对差 | 8 - 2 | = 6 > 4.
# [8, 2, 4] 最大绝对差 | 8 - 2 | = 6 > 4.
# [8, 2, 4, 7] 最大绝对差 | 8 - 2 | = 6 > 4.
# [2] 最大绝对差 | 2 - 2 | = 0 <= 4.
# [2, 4] 最大绝对差 | 2 - 4 | = 2 <= 4.
# [2, 4, 7] 最大绝对差 | 2 - 7 | = 5 > 4.
# [4] 最大绝对差 | 4 - 4 | = 0 <= 4.
# [4, 7] 最大绝对差 | 4 - 7 | = 3 <= 4.
# [7] 最大绝对差 | 7 - 7 | = 0 <= 4.
# 因此，满足题意的最长子数组的长度为 2 。

# 示例2：
# 输入：nums = [10, 1, 2, 4, 7, 2], limit = 5
# 输出：4
# 解释：满足题意的最长子数组是[2, 4, 7, 2]，其最大绝对差 | 2 - 7 | = 5 <= 5 。
#
# 示例3：
# 输入：nums = [4, 2, 2, 2, 4, 4, 2, 2], limit = 0
# 输出：3
#
# 提示：
# 1 <= nums.length <= 10 ^ 5
# 1 <= nums[i] <= 10 ^ 9
# 0 <= limit <= 10 ^ 9
from collections import deque

class Solution(object):  # 不知道怎么用单调队列，看的官方题解
    def longestSubarray(self, nums, limit):
        """
        :type nums: List[int]
        :type limit: int
        :rtype: int
        """
        n = len(nums)
        queMax, queMin = deque(), deque()
        left = right = ret = 0

        while right < n:
            while queMax and queMax[-1] < nums[right]:
                queMax.pop()
            while queMin and queMin[-1] > nums[right]:
                queMin.pop()

            queMax.append(nums[right])
            queMin.append(nums[right])

            while queMax and queMin and queMax[0] - queMin[0] > limit:
                if nums[left] == queMin[0]:
                    queMin.popleft()
                if nums[left] == queMax[0]:
                    queMax.popleft()
                left += 1

            ret = max(ret, right - left + 1)
            right += 1

        return ret


import bisect
import sys
input = sys.stdin.readline

def sieve(n):
    sieve = [True] * n
    for i in xrange(3, int(n ** 0.5) + 1, 2):
        if sieve[i]:
            sieve[i * i::2 * i] = [False] * ((n - i * i - 1) // (2 * i) + 1)
    return [2] + [i for i in range(3, n, 2) if sieve[i]]

primes = sieve(1000000)

for _ in xrange(int(input())):
    a, b = map(int, input().split())
    ai = bisect.bisect_left(primes, a)
    bi = bisect.bisect_left(primes, b)
    print(bi - ai)


"""Takes a claim as input and retrieves evidences for that claim together
with other information related to it.

Example usage:
    python ccv/run_query.py \
        --claim "SARS-CoV-2 binds ACE2 receptor to gain entry into cells" \
        --exe_id "a8f5f167f44f4964e6c998dee827110c"
"""

import argparse
import hashlib
import json
import os
import sys

from feature_visualization import get_features
from retrieval import retrieval
from stance_evidence import produce_files

sys.path.append("longchecker/")
sys.path.append("longchecker/longchecker/")
from longchecker.predict import get_predictions
from longchecker.util import load_jsonl, write_jsonl

def get_args() -> argparse.Namespace:
    """Returns the given arguments.

    Returns:
        argparse.Namespace: The arguments.
    """

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--claim",
        type=str,
        help="claim to use for searching, can also be a file of claims.",
        required=True,
    )
    parser.add_argument("--exe_id", type=str, help="unique execution id.")
    parser.add_argument(
        "--device",
        type=str,
        help="device to run the models on.",
        default="cuda:0",
    )
    args = parser.parse_args()

    if not args.exe_id:
        args.exe_id = hashlib.md5(args.claim.encode()).hexdigest()

    return args

def run_retrieval(claim: str, exe_id: str, device: str) -> None:
    """Runs retrieval on the provided claim.

    Args:
        claim (str): The claim, or path to claim file.
        exe_id (str): The execution id.
        device (str): The device to run the model on.
    """

    input = f"./data/{exe_id}/claims.jsonl"
    with open(input, "w") as f:
        # Is file of claims.
        if os.path.exists(claim):
            with open(claim, "r") as c:
                for line in c:
                    f.write(json.dumps({"claim": line.strip()}) + "\n")
        else:
            f.write(json.dumps({"claim": claim}))

    args = argparse.Namespace()
    args.index = "anserini/indexes/lucene-index-cord19-abstract-2022-02-07"
    args.nkeep = 20
    args.ninit = 100
    args.input = input
    args.claim_col = "claim"
    args.output_claims = f"data/{exe_id}/ds_claims.jsonl"
    args.output_corpus = f"data/{exe_id}/ds_corpus.jsonl"
    args.rerank = True
    args.device = device
    args.batch_size = 100

    retrieval(args)

# modified version of format_predictions from longchecker/predict.py
def format_predictions(args, predictions_all):
    claims = load_jsonl(args.input_file)
    claim_ids = [x["id"] for x in claims]
    assert len(claim_ids) == len(set(claim_ids))

    formatted = {claim: {} for claim in claim_ids}

    # Dict keyed by claim.
    for prediction in predictions_all:
        # If it's NEI, skip it.
        if prediction["predicted_label"] == "NEI":
            continue

        # Add prediction.
        formatted_entry = {
            prediction["abstract_id"]: {
                "label": prediction["predicted_label"],
                "label_probs": prediction["label_probs"],
                "sentences": prediction["predicted_rationale"],
                "sentences_probs": prediction["rationale_probs"],
            }
        }
        formatted[prediction["claim_id"]].update(formatted_entry)

    # Convert to jsonl.
    res = []
    for k, v in formatted.items():
        to_append = {"id": k, "evidence": v}
        res.append(to_append)

    return res

def stance_document(exe_id: str, device: str) -> None:
    """Runs stance prediction for each retrieved evidence for the
    current execution instance.

    Args:
        exe_id (str): The execution id.
        device (str): The device to run the model on.
    """

    args = argparse.Namespace()
    args.checkpoint_path = "longchecker/checkpoints/covidfact.ckpt"
    args.input_file = f"data/{exe_id}/ds_claims.jsonl"
    args.corpus_file = f"data/{exe_id}/ds_corpus.jsonl"
    args.output_file = f"data/{exe_id}/ds_result.jsonl"
    args.batch_size = 1
    args.device = device
    args.num_workers = 4
    args.no_nei = False
    args.force_rationale = False
    args.debug = False

    predictions = get_predictions(args)
    data = format_predictions(args, predictions)

    write_jsonl(data, args.output_file)

def stance_evidence(exe_id: str, device: str) -> None:
    """Produces the files needed to predict the stances between the evidences.

    Args:
        exe_id (str): The execution id.
        device (str): The device to run the model on.
    """

    output_claims = f"data/{exe_id}/es_claims.jsonl"
    output_corpus = f"data/{exe_id}/es_corpus.jsonl"

    args = argparse.Namespace()
    args.oclaims = output_claims
    args.ocorpus = output_corpus
    args.omap = f"data/{exe_id}/es_map.json"
    args.claims = f"data/{exe_id}/ds_claims.jsonl"
    args.corpus = f"data/{exe_id}/ds_corpus.jsonl"
    args.predictions = f"data/{exe_id}/ds_result.jsonl"

    produce_files(args)

    args = argparse.Namespace()
    args.checkpoint_path = "longchecker/checkpoints/covidfact.ckpt"
    args.input_file = output_claims
    args.corpus_file = output_corpus
    args.output_file = f"data/{exe_id}/es_result.jsonl"
    args.batch_size = 1
    args.device = device
    args.num_workers = 4
    args.no_nei = False
    args.force_rationale = False
    args.debug = False

    predictions = get_predictions(args)
    data = format_predictions(args, predictions)

    write_jsonl(data, args.output_file)

def feature_visualization(exe_id: str) -> None:
    """Extracts features used for visualization.

    Args:
        exe_id (str): The execution id.
    """

    args = argparse.Namespace()
    args.output = f"data/{exe_id}/final_output.jsonl"
    args.claims = f"data/{exe_id}/ds_claims.jsonl"
    args.corpus = f"data/{exe_id}/ds_corpus.jsonl"
    args.predictions = f"data/{exe_id}/ds_result.jsonl"
    args.erelations = f"data/{exe_id}/es_result.jsonl"
    args.emap = f"data/{exe_id}/es_map.json"

    get_features(args)

def run_query(claim: str, exe_id: str, device: str) -> None:
    """Runs the pipeline on the provided claim.

    Args:
        claim (str): The claim.
        exe_id (str): The execution id.
        device (str): The device to run the model on.
    """

    os.makedirs(f"data/{exe_id}", exist_ok=True)
    run_retrieval(claim, exe_id, device)
    stance_document(exe_id, device)
    stance_evidence(exe_id, device)
    feature_visualization(exe_id)

def main() -> None:
    """Executes the script."""

    args = get_args()
    run_query(args.claim, args.exe_id, args.device)

if __name__ == "__main__":
    main()


arr = []
n = int(input("Enter the number of elements: "))

print("Enter the elements:")
for _ in range(n):
    arr.append(int(input()))

index_pos = int(input("Enter the index where the element is to be deleted: "))

# Shift elements to the left to make space for the deleted element
for i in range(index_pos, n - 1):
    arr[i] = arr[i + 1]

print("The elements entered are:", end=" ")
for i in range(n - 1):
    print(arr[i], end=" ")
print()


# This calls for some new utility functions!!!
# Part1: 00:11:26
# Part2: 00:14:47

import numpy as np
import itertools as it
import utils as u
import re

def start(inp, lin):
    # Haha i orginally hardcoded the stacks in this solution, gotta change this
    # before github
    # stacks = [
    #     ['S','L','F','Z','D','B','R','H'],
    #     ['R','Z','M','B','T'],
    #     ['S','N','H','C','L','Z'],
    #     ['J','F','C','S'],
    #     ['B','Z','R','W','H','G','P'],
    #     ['T','M','N','D','G','Z','J','V'],
    #     ['O','P','S','F','W','N','L','G'],
    #     ['R','Z','M'],
    #     ['T','R','V','G','L','C','M']
    # ]
    stacks = []
    for s in lin[0:lin.index('')-1]:
        stacks.append(re.sub('    ', ' ', s).replace(']', '').replace('[', '').split(' '))
    stacks = [[f for f in d if f] for d in np.array(stacks).T]
    stacks2 = [x[:] for x in stacks]

    for l in lin[lin.index('')+1:]:
        cmd = []
        for let in l.split(' '):
            try:
                cmd.append(int(let))
            except:
                pass
        move = []
        for i in range(0, cmd[0]):
            move.append(stacks[cmd[1]-1].pop(0))
            stacks2[cmd[2]-1].insert(0, stacks2[cmd[1]-1].pop(0))
        stacks[cmd[2]-1] = move + stacks[cmd[2]-1]

    for s in stacks2:
        print(s[0], end='')
    print(', ', end = '')
    for s in stacks:
        print(s[0], end='')
    print('')


#№1
def f(x):
    x = input(f"Напишите одну букву")
    bykva = ["A", "B", "C", "D", "E", "F"]
    return x in bykva
# №2
def oznaka(x):
    if x>0:
        a=1
    elif x<0:
        a=-1
    else:
        a=0
    return a
# №3
def rivnyna(a,b,c):
    D=b**2-4*a*c
    if D>0:
        x=2
    elif D==0 and a!=b!=c!=0:
        x=1
    elif a==b==c==0:
        x=-1
    else:
        x=0
    return x
# №4
def xnay(a,b,c,x,y):
    k1=[a,b,c]
    k2=min(k1)
    k1.remove(k2)
    k3=min(k1)
    return ((x>=k2) and (y>=k3)) or ((x>=k3) and (y>=k2))
# №5
def vik(age):
    if ( 11 <= age and age <= 19):
        print(age, "років")
    elif(age % 10 == 1):
        print(age, "рік")
    elif(2 <= age % 10 <= 4):
        print(age, "роки")
    else:
        print(age, "років")

oznaka(-32328347346354875)
rivnyna(3,3,-3)
xnay(21,3434,1,143,32)
vik(100)


import xml.etree.ElementTree as ET
import chess
import chess.polyglot
import sys

ROOT = None

ANNOT_WEIGHTS = {
	"!!" : 500,
	"!"  : 250,
	"!?" : 100,
	"-"  : 50,
	"?!" : 10
}

def get_zobrist_key_hex(board):
	return "%0.16x" % chess.polyglot.zobrist_hash(board)

def xml_path(name):
	return "engines/"+name+".xml"

def bin_path(name):
	return "engines/"+name+".bin"

def load(name="default"):
	global ROOT
	try:
		path = xml_path(name)
		#print("loading xml book {}".format(path))
		tree = ET.parse(path)
		ROOT = tree.getroot()
	except:
		pass

def convert(name="default"):
	load(name)
	board=chess.Board()
	allentries=[]

	cnt=0

	for position in ROOT[0]:
		fen = position.attrib["tfen"]+" 1 0"
		board.set_fen(fen)
		zobrist_key_hex=get_zobrist_key_hex(board)
		#print("{:<5d} {} {}\n{}".format(cnt+1,zobrist_key_hex,fen,board))
		zbytes=bytes.fromhex(zobrist_key_hex)
		for movelist in position:
			for move in movelist:
				if move.tag=="move":
					san=move.attrib["s"]
					annot=move[1].text
					weight=0
					if not annot==None:
						try:
							weight=ANNOT_WEIGHTS[annot]
						except:
							pass
					else:
						annot="none"
					#print("{:8} {:4} {:4}".format(san,annot,weight))
					try:
						m=board.parse_san(san)
						mi=m.to_square+(m.from_square << 6)
						if not m.promotion==None:
							mi+=((m.promotion-1) << 12)
						mbytes=bytes.fromhex("%0.4x" % mi)
						wbytes=bytes.fromhex("%0.4x" % weight)
						lbytes=bytes.fromhex("%0.8x" % 0)
						allbytes=zbytes+mbytes+wbytes+lbytes
						if weight>0:
							allentries.append(allbytes)
					except:
						#print("parsing error")
						pass
		cnt+=1

	sorted_weights=sorted(allentries,key=lambda entry:entry[10:12],reverse=True)
	sorted_entries=sorted(sorted_weights,key=lambda entry:entry[0:8])

	print("total of {} moves added to book {}".format(len(allentries),bin_path(name)))
	with open(bin_path(name), 'wb') as outfile:
		for entry in sorted_entries:
			outfile.write(entry)

name="default"

if len(sys.argv)>1:
	name=sys.argv[1]

print("converting {}".format(name))

convert(name)


from typing import Any, List, Dict

import matplotlib.pyplot as plt
import numpy as np
import torch
import torchvision.utils as vutils
from models.generators.base_generator import BaseGenerator

def show_batch(
    batch: List[Any], device: torch.device, title: str = "Batch images"
) -> None:
    """Show image batch

    :param batch: batch of images to plot
    :type batch: list
    :param device: pytorch device
    :type device: pytorch device
    """
    plt.figure(figsize=(12, 12))
    plt.axis("off")
    plt.title(title)
    plt.imshow(
        np.transpose(
            vutils.make_grid(
                batch[0].to(device)[:10],
                padding=2,
                normalize=True,
            ).cpu(),
            (1, 2, 0),
        )
    )
    plt.show()

def plot_generator_images(
    G_A2B: BaseGenerator,
    G_B2A: BaseGenerator,
    dataloader_A: torch.utils.data.DataLoader[Any],
    dataloader_B: torch.utils.data.DataLoader[Any],
    device: torch.device,
) -> None:
    """Plot generated images

    :param G_A2B: generator to transform from A to B
    :type G_A2B: `Generator`
    :param G_B2A: generator to transform from B to A
    :type G_B2A: `Generator`
    :param dataloader_A: dataloader with images of the domain A
    :type dataloader_A: `Dataloader`
    :param dataloader_B: dataloader with images of the domain B
    :type dataloader_B: `Dataloader`
    :param device: pytorch
    :type device: `Device`
    """
    batch_a_test = next(iter(dataloader_A))[0].to(device)
    real_a_test = batch_a_test.cpu().detach()
    fake_b_test = G_A2B(batch_a_test).cpu().detach()

    show_batch(real_a_test, device, title="Real A")
    show_batch(fake_b_test, device, title="Fake B")

    batch_b_test = next(iter(dataloader_B))[0].to(device)
    real_b_test = batch_b_test.cpu().detach()
    fake_a_test = G_B2A(batch_b_test).cpu().detach()

    show_batch(real_b_test, device, title="Real B")
    show_batch(fake_a_test, device, title="Fake A")

def plot_metrics(metrics: Dict[str, Any]) -> None:
    """Create metrics plots

    :param metrics: list with the metrics stored during training
    :type metrics: dict
    """

    for metrics_name in metrics.keys():
        plt.figure()
        plt.plot(metrics[metrics_name])
        plt.grid()
        plt.title(metrics_name)
        plt.xlabel("epochs")
        plt.ylabel(metrics_name)
        plt.show()


#!/usr/bin/python3
"""Classes all about shapes! Huzzah!"""

BaseGeometry = __import__('7-base_geometry').BaseGeometry
Rectangle = __import__('9-rectangle').Rectangle

class Square(Rectangle):
    """A type of shape that's a bit... square.

    Args:
        size (int): length of height and width (as typical with squares).
    """

    def __init__(self, size):
        super().integer_validator("size", size)
        self.__size = size
        super().__init__(size, size)


#!/usr/bin/env python3
from string import Template
import requests
from tkinter import *
from tkinter import ttk
import io
from PIL import Image, ImageTk

# API interface
class ScrapperException(Exception):
    '''raise this when there's a scrapper error'''

class Scrapper():
    api = Template('https://codeforces.com/api/$methodName')

    def __init__(self):
        pass

    def fetch_data(self, username):
        response = requests.get(Scrapper.api.substitute(methodName='user.info'), params={ 'handles': username })
        #print(response)
        data = response.json()
        if response and data['status'] == 'OK':
            return data['result'][0]    # only take the first user
        else:
            raise ScrapperException('Error: User with the specified username does not exist.')

    def fetch_image(self, url):
        response = requests.get(url, stream=True)
        raw_data = response.raw.read()
        image = io.BytesIO(raw_data)
        return image

# Tkinter GUI setup
class App():
    rating_template = Template('$rating (max: $max_rating)')
    rank_template = Template('$rank (max: $max_rank)')

    def __init__(self):
        self.scrapper = Scrapper()
        self.createUI()

    def createUI(self):
        self.root = Tk()
        self.root.title('Codeforces')

        # search
        self.form = ttk.Frame(self.root, padding=(16,16), borderwidth=8, relief='raised')
        self.form.pack(fill=X, anchor=N, expand=True)

        self.username_label = ttk.Label(self.form, text='Search username:')
        self.username_label.pack(side=LEFT, padx=8, pady=8)

        self.username = StringVar()
        self.username_entry = ttk.Entry(self.form, width=20, textvariable=self.username)
        self.username_entry.pack(side=LEFT, padx=8, pady=8)

        self.search_button = ttk.Button(self.form, text='Go', command=self.search)
        self.search_button.pack(side=RIGHT)

        # info
        self.info = ttk.Frame(self.root, padding=(16,16), borderwidth=8, relief='sunken')
        self.info.pack(fill=BOTH, expand=True)

        self.error_display = StringVar()
        self.error_label = ttk.Label(self.info, textvariable=self.error_display)
        self.error_label.grid(column=0, row=0, columnspan=2)

        self.avatar = None
        self.avatar_label = ttk.Label(self.info, image=self.avatar)
        self.avatar_label.grid(column=0, row=1, rowspan=3, padx=8)

        self.handle_display = StringVar()
        self.handle_label = ttk.Label(self.info, textvariable=self.handle_display)
        self.handle_label.grid(column=1, row=1, sticky='w')

        self.rating_display = StringVar()
        self.rating_label = ttk.Label(self.info, textvariable=self.rating_display)
        self.rating_label.grid(column=1, row=2, sticky='w')

        self.rank_display = StringVar()
        self.rank_label = ttk.Label(self.info, textvariable=self.rank_display)
        self.rank_label.grid(column=1, row=3, sticky='w')

    def search(self):
        try:
            data = self.scrapper.fetch_data(self.username.get())
            #print(data)
            self.error = None;
            image = self.scrapper.fetch_image('https:' + data['avatar'])
            self.avatar = ImageTk.PhotoImage(Image.open(image))
            self.handle = data['handle']
            self.rating = data['rating']
            self.rank = data['rank']
            self.max_rating = data['maxRating']
            self.max_rank = data['maxRank']
        except ScrapperException as e:
            #print(e)
            self.error = e
        except requests.exceptions.ConnectionError as e:
            #print(e)
            self.error = 'Error: You are not connected to the internet.'
        self.updateUI()

    def updateUI(self):
        if self.error is None:
            self.error_label.grid_remove()
            self.avatar_label.configure(image=self.avatar)
            self.handle_display.set(self.handle)
            self.rating_display.set(App.rating_template.substitute(rating=self.rating, max_rating=self.max_rating))
            self.rank_display.set(App.rank_template.substitute(rank=self.rank, max_rank=self.max_rank))
        else:
            self.error_display.set(self.error)
            self.error_label.grid()
            self.avatar_label.configure(image='')
            self.handle_display.set('')
            self.rating_display.set('')
            self.rank_display.set('')

    def run(self):
        self.root.mainloop()

def main():
    App().run()

if __name__ == '__main__':
    main()


from typing import OrderedDict

import torch
import numpy as np
import copy

from malib import settings
from malib.utils.typing import Dict, Callable, List, Tuple

def update_configs(update_dict, ori_dict=None):
    """Update global configs with a given dict"""

    ori_configs = (
        copy.copy(ori_dict)
        if ori_dict is not None
        else copy.copy(settings.DEFAULT_CONFIG)
    )

    for k, v in update_dict.items():
        # assert k in ori_configs, f"Illegal key: {k}, {list(ori_configs.keys())}"
        if isinstance(v, dict):
            ph = ori_configs[k] if isinstance(ori_configs.get(k), dict) else {}
            ori_configs[k] = update_configs(v, ph)
        else:
            ori_configs[k] = copy.copy(v)

    # clean environment desc
    return ori_configs

# TODO(ming): will be replaced with many dicts
def iter_dicts_recursively(d1, d2):
    """Assuming dicts have the exact same structure."""
    for k, v in d1.items():
        assert k in d2

        if isinstance(v, (dict, OrderedDict)):
            yield from iter_dicts_recursively(d1[k], d2[k])
        else:
            yield d1, d2, k, d1[k], d2[k]

def iter_many_dicts_recursively(*d, history=None):
    """Assuming dicts have the exact same structure, or raise KeyError."""

    for k, v in d[0].items():
        if isinstance(v, (dict, OrderedDict)):
            yield from iter_many_dicts_recursively(
                *[_d[k] for _d in d],
                history=history + [k] if history is not None else None,
            )
        else:
            if history is None:
                yield d, k, tuple([_d[k] for _d in d])
            else:
                yield history + [k], d, k, tuple([_d[k] for _d in d])

class BufferDict(dict):
    @property
    def capacity(self) -> int:
        capacities = []
        for _, _, v in iterate_recursively(self):
            capacities.append(v.shape[0])
        return max(capacities)

    def index(self, indices):
        return self.index_func(self, indices)

    def index_func(self, x, indices):
        if isinstance(x, (dict, BufferDict)):
            res = BufferDict()
            for k, v in x.items():
                res[k] = self.index_func(v, indices)
            return res
        else:
            t = x[indices]
            # Logger.debug("sampled data shape: {} {}".format(t.shape, indices))
            return t

    def set_data(self, index, new_data):
        return self.set_data_func(self, index, new_data)

    def set_data_func(self, x, index, new_data):
        if isinstance(new_data, (dict, BufferDict)):
            for nk, nv in new_data.items():
                self.set_data_func(x[nk], index, nv)
        else:
            if isinstance(new_data, torch.Tensor):
                t = new_data.cpu().numpy()
            elif isinstance(new_data, np.ndarray):
                t = new_data
            else:
                raise TypeError(
                    f"Unexpected type for new insert data: {type(new_data)}, expected is np.ndarray"
                )
            x[index] = t.copy()

def iterate_recursively(d: Dict):
    for k, v in d.items():
        if isinstance(v, (dict, BufferDict)):
            yield from iterate_recursively(v)
        else:
            yield d, k, v

def _default_dtype_mapping(dtype):
    # FIXME(ming): cast 64 to 32?
    if dtype in [np.int32, np.int64, int]:
        return torch.int32
    elif dtype in [float, np.float32, np.float16]:
        return torch.float32
    elif dtype == np.float64:
        return torch.float64
    elif dtype in [bool, np.bool_]:
        return torch.float32
    else:
        raise NotImplementedError(f"dtype: {dtype} has no transmission rule.") from None

# wrap with type checking
def _walk(caster, v):
    if isinstance(v, (dict, BufferDict)):
        for k, _v in v.items():
            v[k] = _walk(caster, _v)
    else:
        v = caster(v)
    return v

def tensor_cast(
    custom_caster: Callable = None,
    callback: Callable = None,
    dtype_mapping: Dict = None,
    device="cpu",
):
    """Casting the inputs of a method into tensors if needed.

    Note:
        This function does not support recursive iteration.

    Args:
        custom_caster (Callable, optional): Customized caster. Defaults to None.
        callback (Callable, optional): Callback function, accepts returns of wrapped function as inputs. Defaults to None.
        dtype_mapping (Dict, optional): Specify the data type for inputs which you wanna. Defaults to None.

    Returns:
        Callable: A decorator.
    """
    dtype_mapping = dtype_mapping or _default_dtype_mapping
    cast_to_tensor = custom_caster or (
        lambda x: torch.FloatTensor(x.copy()).to(
            device=device, dtype=dtype_mapping(x.dtype)
        )
        if not isinstance(x, torch.Tensor)
        else x
    )

    def decorator(func):
        def wrap(*args, **kwargs):
            new_args = []
            for i, arg in enumerate(args):
                new_args.append(_walk(cast_to_tensor, arg))
            for k, v in kwargs.items():
                kwargs[k] = _walk(cast_to_tensor, v)
            rets = func(*new_args, **kwargs)
            if callback is not None:
                callback(rets)
            return rets

        return wrap

    return decorator

def frozen_data(data):
    _hash = 0
    if isinstance(data, Dict):
        for k, v in data.items():
            _v = frozen_data(v)
            _hash ^= hash((k, _v))
    elif isinstance(data, (List, Tuple)):
        for e in data:
            _hash ^= hash(e)
    else:
        return hash(data)
    return _hash


import requests
import json
import io

class Infernite:
    def __init__(self, token):
        self.token = token
        self.api = "https://infernite.ai/predictions"

    def predict(self, body):
        files = {}
        if "image" in body:
            file_path = body["image"]
            if file_path.find("https://") == 0 or file_path.find("http://") == 0:
                data = requests.get(file_path, stream=True).content
                files["image"] = io.BytesIO(data)
            else:
                files["image"] = open(file_path, "rb")

            del body["image"]

        headers = {'Token': self.token}

        response = requests.post(
            self.api, files=files, data=body, headers=headers)

        if response.status_code == 200:
            return json.loads(response.text)
        else:
            raise RuntimeError("Status code {}: {}".format(response.status_code, response.text))


from odoo import models
from odoo.osv import expression
from odoo.tools.safe_eval import safe_eval

class SaleOrder(models.Model):
    _inherit = "sale.order"

    def _get_reward_values_discount_strict_limit_lines(self, program):
        """We'll restrict the domain to only the products fulfilling individually the
        criterias"""
        domain = program.rule_products_domain
        program = program.with_context(promo_domain_product=domain)
        extendable_domain = safe_eval(domain)
        intersected_products = self.order_line.product_id & self.env[
            "product.product"
        ].search(extendable_domain)
        amount_field = (
            "price_subtotal"
            if program.rule_minimum_amount_tax_inclusion == "tax_excluded"
            else "price_tax"
        )
        intersected_lines = self.env["sale.order.line"]
        for product in intersected_products:
            product_lines = self.order_line.filtered(
                lambda x: x.product_id == product and not x.is_reward_line
            )
            if (
                sum(product_lines.mapped("product_uom_qty"))
                >= program.rule_min_quantity
                and sum(product_lines.mapped(amount_field))
                >= program.rule_minimum_amount
            ):
                intersected_lines |= product_lines
        # Prepare the extended domain to send it by context
        domain = str(
            expression.AND(
                [
                    extendable_domain,
                    [("id", "in", intersected_lines.product_id.ids or [0])],
                ]
            )
        )
        return domain

    def _get_reward_values_discount(self, program):
        """We simply inject the context in order to gather the proper discounted
        products according to the current domain"""
        if (
            program.discount_apply_on_domain_product
            and program.discount_apply_on == "specific_products"
        ):
            domain = program.rule_products_domain
            # In this case, we need to preevaluate the domain along with every line
            # affected
            if program.strict_per_product_limit:
                domain = self._get_reward_values_discount_strict_limit_lines(program)
            return super()._get_reward_values_discount(
                program.with_context(promo_domain_product=domain)
            )
        return super()._get_reward_values_discount(program)


import enum
import glob
import os
import pickle
from typing import Any, Iterable, Union

from dataclasses import dataclass
import numpy as np
import pandas as pd
from scipy import special
from sklearn import metrics
import tensorflow_privacy.privacy.membership_inference_attack.utils as utils

ENTIRE_DATASET_SLICE_STR = 'Entire dataset'

class SlicingFeature(enum.Enum):
  """Enum with features by which slicing is available."""
  CLASS = 'class'
  PERCENTILE = 'percentile'
  CORRECTLY_CLASSIFIED = 'correctly_classified'

@dataclass
class SingleSliceSpec:
  """Specifies a slice.

  The slice is defined by values in one feature - it might be a single value
  (eg. slice of examples of the specific classification class) or some set of
  values (eg. range of percentiles of the attacked model loss).

  When feature is None, it means that the slice is the entire dataset.
  """
  feature: SlicingFeature = None
  value: Any = None

  @property
  def entire_dataset(self):
    return self.feature is None

  def __str__(self):
    if self.entire_dataset:
      return ENTIRE_DATASET_SLICE_STR

    if self.feature == SlicingFeature.PERCENTILE:
      return 'Loss percentiles: %d-%d' % self.value

    return '%s=%s' % (self.feature.name, self.value)

@dataclass
class SlicingSpec:
  """Specification of a slicing procedure.

  Each variable which is set specifies a slicing by different dimension.
  """

  # When is set to true, one of the slices is the whole dataset.
  entire_dataset: bool = True

  # Used in classification tasks for slicing by classes. It is assumed that
  # classes are integers 0, 1, ... number of classes. When true one slice per
  # each class is generated.
  by_class: Union[bool, Iterable[int], int] = False

  # if true, it generates 10 slices for percentiles of the loss - 0-10%, 10-20%,
  # ... 90-100%.
  by_percentiles: bool = False

  # When true, a slice for correctly classifed and a slice for misclassifed
  # examples will be generated.
  by_classification_correctness: bool = False

  def __str__(self):
    """Only keeps the True values."""
    result = ['SlicingSpec(']
    if self.entire_dataset:
      result.append(' Entire dataset,')
    if self.by_class:
      if isinstance(self.by_class, Iterable):
        result.append(' Into classes %s,' % self.by_class)
      elif isinstance(self.by_class, int):
        result.append(' Up to class %d,' % self.by_class)
      else:
        result.append(' By classes,')
    if self.by_percentiles:
      result.append(' By percentiles,')
    if self.by_classification_correctness:
      result.append(' By classification correctness,')
    result.append(')')
    return '\n'.join(result)

class AttackType(enum.Enum):
  """An enum define attack types."""
  LOGISTIC_REGRESSION = 'lr'
  MULTI_LAYERED_PERCEPTRON = 'mlp'
  RANDOM_FOREST = 'rf'
  K_NEAREST_NEIGHBORS = 'knn'
  THRESHOLD_ATTACK = 'threshold'
  THRESHOLD_ENTROPY_ATTACK = 'threshold-entropy'

  @property
  def is_trained_attack(self):
    """Returns whether this type of attack requires training a model."""
    return (self != AttackType.THRESHOLD_ATTACK) and (
        self != AttackType.THRESHOLD_ENTROPY_ATTACK)

  def __str__(self):
    """Returns LOGISTIC_REGRESSION instead of AttackType.LOGISTIC_REGRESSION."""
    return '%s' % self.name

class PrivacyMetric(enum.Enum):
  """An enum for the supported privacy risk metrics."""
  AUC = 'AUC'
  ATTACKER_ADVANTAGE = 'Attacker advantage'

  def __str__(self):
    """Returns 'AUC' instead of PrivacyMetric.AUC."""
    return '%s' % self.value

def _is_integer_type_array(a):
  return np.issubdtype(a.dtype, np.integer)

def _is_last_dim_equal(arr1, arr1_name, arr2, arr2_name):
  """Checks whether the last dimension of the arrays is the same."""
  if arr1 is not None and arr2 is not None and arr1.shape[-1] != arr2.shape[-1]:
    raise ValueError('%s and %s should have the same number of features.' %
                     (arr1_name, arr2_name))

def _is_array_one_dimensional(arr, arr_name):
  """Checks whether the array is one dimensional."""
  if arr is not None and len(arr.shape) != 1:
    raise ValueError('%s should be a one dimensional numpy array.' % arr_name)

def _is_np_array(arr, arr_name):
  """Checks whether array is a numpy array."""
  if arr is not None and not isinstance(arr, np.ndarray):
    raise ValueError('%s should be a numpy array.' % arr_name)

def _log_value(probs, small_value=1e-30):
  """Compute the log value on the probability. Clip probabilities close to 0."""
  return -np.log(np.maximum(probs, small_value))

@dataclass
class AttackInputData:
  """Input data for running an attack.

  This includes only the data, and not configuration.
  """

  logits_train: np.ndarray = None
  logits_test: np.ndarray = None

  # Predicted probabilities for each class. They can be derived from logits,
  # so they can be set only if logits are not explicitly provided.
  probs_train: np.ndarray = None
  probs_test: np.ndarray = None

  # Contains ground-truth classes. Classes are assumed to be integers starting
  # from 0.
  labels_train: np.ndarray = None
  labels_test: np.ndarray = None

  # Explicitly specified loss. If provided, this is used instead of deriving
  # loss from logits and labels
  loss_train: np.ndarray = None
  loss_test: np.ndarray = None

  # Explicitly specified prediction entropy. If provided, this is used instead
  # of deriving entropy from logits and labels
  # (https://arxiv.org/pdf/2003.10595.pdf by Song and Mittal).
  entropy_train: np.ndarray = None
  entropy_test: np.ndarray = None

  @property
  def num_classes(self):
    if self.labels_train is None or self.labels_test is None:
      raise ValueError(
          'Can\'t identify the number of classes as no labels were provided. '
          'Please set labels_train and labels_test')
    return int(max(np.max(self.labels_train), np.max(self.labels_test))) + 1

  @property
  def logits_or_probs_train(self):
    """Returns train logits or probs whatever is not None."""
    if self.logits_train is not None:
      return self.logits_train
    return self.probs_train

  @property
  def logits_or_probs_test(self):
    """Returns test logits or probs whatever is not None."""
    if self.logits_test is not None:
      return self.logits_test
    return self.probs_test

  @staticmethod
  def _get_entropy(logits: np.ndarray, true_labels: np.ndarray):
    """Computes the prediction entropy (by Song and Mittal)."""
    if (np.absolute(np.sum(logits, axis=1) - 1) <= 1e-3).all():
      probs = logits
    else:
      # Using softmax to compute probability from logits.
      probs = special.softmax(logits, axis=1)
    if true_labels is None:
      # When not given ground truth label, we compute the
      # normal prediction entropy.
      # See the Equation (7) in https://arxiv.org/pdf/2003.10595.pdf
      return np.sum(np.multiply(probs, _log_value(probs)), axis=1)
    else:
      # When given the ground truth label, we compute the
      # modified prediction entropy.
      # See the Equation (8) in https://arxiv.org/pdf/2003.10595.pdf
      log_probs = _log_value(probs)
      reverse_probs = 1 - probs
      log_reverse_probs = _log_value(reverse_probs)
      modified_probs = np.copy(probs)
      modified_probs[range(true_labels.size),
                     true_labels] = reverse_probs[range(true_labels.size),
                                                  true_labels]
      modified_log_probs = np.copy(log_reverse_probs)
      modified_log_probs[range(true_labels.size),
                         true_labels] = log_probs[range(true_labels.size),
                                                  true_labels]
      return np.sum(np.multiply(modified_probs, modified_log_probs), axis=1)

  def get_loss_train(self):
    """Calculates (if needed) cross-entropy losses for the training set."""
    if self.loss_train is None:
      if self.logits_train is not None:
        self.loss_train = utils.log_loss_from_logits(self.labels_train,
                                                     self.logits_train)
      else:
        self.loss_train = utils.log_loss(self.labels_train, self.probs_train)
    return self.loss_train

  def get_loss_test(self):
    """Calculates (if needed)  cross-entropy losses for the test set."""
    if self.loss_test is None:
      if self.logits_train is not None:
        self.loss_test = utils.log_loss_from_logits(self.labels_test,
                                                    self.logits_test)
      else:
        self.loss_test = utils.log_loss(self.labels_test, self.probs_test)
    return self.loss_test

  def get_entropy_train(self):
    """Calculates prediction entropy for the training set."""
    if self.entropy_train is not None:
      return self.entropy_train
    return self._get_entropy(self.logits_train, self.labels_train)

  def get_entropy_test(self):
    """Calculates prediction entropy for the test set."""
    if self.entropy_test is not None:
      return self.entropy_test
    return self._get_entropy(self.logits_test, self.labels_test)

  def get_train_size(self):
    """Returns size of the training set."""
    if self.loss_train is not None:
      return self.loss_train.size
    if self.entropy_train is not None:
      return self.entropy_train.size
    return self.logits_or_probs_train.shape[0]

  def get_test_size(self):
    """Returns size of the test set."""
    if self.loss_test is not None:
      return self.loss_test.size
    if self.entropy_test is not None:
      return self.entropy_test.size
    return self.logits_or_probs_test.shape[0]

  def validate(self):
    """Validates the inputs."""
    if (self.loss_train is None) != (self.loss_test is None):
      raise ValueError(
          'loss_test and loss_train should both be either set or unset')

    if (self.entropy_train is None) != (self.entropy_test is None):
      raise ValueError(
          'entropy_test and entropy_train should both be either set or unset')

    if (self.logits_train is None) != (self.logits_test is None):
      raise ValueError(
          'logits_train and logits_test should both be either set or unset')

    if (self.probs_train is None) != (self.probs_test is None):
      raise ValueError(
          'probs_train and probs_test should both be either set or unset')

    if (self.logits_train is not None) and (self.probs_train is not None):
      raise ValueError('Logits and probs can not be both set')

    if (self.labels_train is None) != (self.labels_test is None):
      raise ValueError(
          'labels_train and labels_test should both be either set or unset')

    if (self.labels_train is None and self.loss_train is None and
        self.logits_train is None and self.entropy_train is None):
      raise ValueError(
          'At least one of labels, logits, losses or entropy should be set')

    if self.labels_train is not None and not _is_integer_type_array(
        self.labels_train):
      raise ValueError('labels_train elements should have integer type')

    if self.labels_test is not None and not _is_integer_type_array(
        self.labels_test):
      raise ValueError('labels_test elements should have integer type')

    _is_np_array(self.logits_train, 'logits_train')
    _is_np_array(self.logits_test, 'logits_test')
    _is_np_array(self.probs_train, 'probs_train')
    _is_np_array(self.probs_test, 'probs_test')
    _is_np_array(self.labels_train, 'labels_train')
    _is_np_array(self.labels_test, 'labels_test')
    _is_np_array(self.loss_train, 'loss_train')
    _is_np_array(self.loss_test, 'loss_test')
    _is_np_array(self.entropy_train, 'entropy_train')
    _is_np_array(self.entropy_test, 'entropy_test')

    _is_last_dim_equal(self.logits_train, 'logits_train', self.logits_test,
                       'logits_test')
    _is_last_dim_equal(self.probs_train, 'probs_train', self.probs_test,
                       'probs_test')
    _is_array_one_dimensional(self.loss_train, 'loss_train')
    _is_array_one_dimensional(self.loss_test, 'loss_test')
    _is_array_one_dimensional(self.entropy_train, 'entropy_train')
    _is_array_one_dimensional(self.entropy_test, 'entropy_test')
    _is_array_one_dimensional(self.labels_train, 'labels_train')
    _is_array_one_dimensional(self.labels_test, 'labels_test')

  def __str__(self):
    """Return the shapes of variables that are not None."""
    result = ['AttackInputData(']
    _append_array_shape(self.loss_train, 'loss_train', result)
    _append_array_shape(self.loss_test, 'loss_test', result)
    _append_array_shape(self.entropy_train, 'entropy_train', result)
    _append_array_shape(self.entropy_test, 'entropy_test', result)
    _append_array_shape(self.logits_train, 'logits_train', result)
    _append_array_shape(self.logits_test, 'logits_test', result)
    _append_array_shape(self.probs_train, 'probs_train', result)
    _append_array_shape(self.probs_test, 'probs_test', result)
    _append_array_shape(self.labels_train, 'labels_train', result)
    _append_array_shape(self.labels_test, 'labels_test', result)
    result.append(')')
    return '\n'.join(result)

def _append_array_shape(arr: np.array, arr_name: str, result):
  if arr is not None:
    result.append(' %s with shape: %s,' % (arr_name, arr.shape))

@dataclass
class RocCurve:
  """Represents ROC curve of a membership inference classifier."""
  # Thresholds used to define points on ROC curve.
  # Thresholds are not explicitly part of the curve, and are stored for
  # debugging purposes.
  thresholds: np.ndarray

  # True positive rates based on thresholds
  tpr: np.ndarray

  # False positive rates based on thresholds
  fpr: np.ndarray

  def get_auc(self):
    """Calculates area under curve (aka AUC)."""
    return metrics.auc(self.fpr, self.tpr)

  def get_attacker_advantage(self):
    """Calculates membership attacker's (or adversary's) advantage.

    This metric is inspired by https://arxiv.org/abs/1709.01604, specifically
    by Definition 4. The difference here is that we calculate maximum advantage
    over all available classifier thresholds.

    Returns:
      a single float number with membership attacker's advantage.
    """
    return max(np.abs(self.tpr - self.fpr))

  def __str__(self):
    """Returns AUC and advantage metrics."""
    return '\n'.join([
        'RocCurve(',
        '  AUC: %.2f' % self.get_auc(),
        '  Attacker advantage: %.2f' % self.get_attacker_advantage(), ')'
    ])

@dataclass
class SingleAttackResult:
  """Results from running a single attack."""

  # Data slice this result was calculated for.
  slice_spec: SingleSliceSpec

  attack_type: AttackType
  roc_curve: RocCurve  # for drawing and metrics calculation

  def get_attacker_advantage(self):
    return self.roc_curve.get_attacker_advantage()

  def get_auc(self):
    return self.roc_curve.get_auc()

  def __str__(self):
    """Returns SliceSpec, AttackType, AUC and advantage metrics."""
    return '\n'.join([
        'SingleAttackResult(',
        '  SliceSpec: %s' % str(self.slice_spec),
        '  AttackType: %s' % str(self.attack_type),
        '  AUC: %.2f' % self.get_auc(),
        '  Attacker advantage: %.2f' % self.get_attacker_advantage(), ')'
    ])

@dataclass
class PrivacyReportMetadata:
  """Metadata about the evaluated model.

  Used to create a privacy report based on AttackResults.
  """
  accuracy_train: float = None
  accuracy_test: float = None

  loss_train: float = None
  loss_test: float = None

  model_variant_label: str = 'Default model variant'
  epoch_num: int = None

class AttackResultsDFColumns(enum.Enum):
  """Columns for the Pandas DataFrame that stores AttackResults metrics."""
  SLICE_FEATURE = 'slice feature'
  SLICE_VALUE = 'slice value'
  ATTACK_TYPE = 'attack type'

  def __str__(self):
    """Returns 'slice value' instead of AttackResultsDFColumns.SLICE_VALUE."""
    return '%s' % self.value

@dataclass
class AttackResults:
  """Results from running multiple attacks."""
  single_attack_results: Iterable[SingleAttackResult]

  privacy_report_metadata: PrivacyReportMetadata = None

  def calculate_pd_dataframe(self):
    """Returns all metrics as a Pandas DataFrame."""
    slice_features = []
    slice_values = []
    attack_types = []
    advantages = []
    aucs = []

    for attack_result in self.single_attack_results:
      slice_spec = attack_result.slice_spec
      if slice_spec.entire_dataset:
        slice_feature, slice_value = str(slice_spec), ''
      else:
        slice_feature, slice_value = slice_spec.feature.value, slice_spec.value
      slice_features.append(str(slice_feature))
      slice_values.append(str(slice_value))
      attack_types.append(str(attack_result.attack_type))
      advantages.append(float(attack_result.get_attacker_advantage()))
      aucs.append(float(attack_result.get_auc()))

    df = pd.DataFrame({
        str(AttackResultsDFColumns.SLICE_FEATURE): slice_features,
        str(AttackResultsDFColumns.SLICE_VALUE): slice_values,
        str(AttackResultsDFColumns.ATTACK_TYPE): attack_types,
        str(PrivacyMetric.ATTACKER_ADVANTAGE): advantages,
        str(PrivacyMetric.AUC): aucs
    })
    return df

  def summary(self, by_slices=False) -> str:
    """Provides a summary of the metrics.

    The summary provides the best-performing attacks for each requested data
    slice.
    Args:
      by_slices : whether to prepare a per-slice summary.

    Returns:
      A string with a summary of all the metrics.
    """
    summary = []

    # Summary over all slices
    max_auc_result_all = self.get_result_with_max_attacker_advantage()
    summary.append('Best-performing attacks over all slices')
    summary.append(
        '  %s achieved an AUC of %.2f on slice %s' %
        (max_auc_result_all.attack_type, max_auc_result_all.get_auc(),
         max_auc_result_all.slice_spec))

    max_advantage_result_all = self.get_result_with_max_attacker_advantage()
    summary.append('  %s achieved an advantage of %.2f on slice %s' %
                   (max_advantage_result_all.attack_type,
                    max_advantage_result_all.get_attacker_advantage(),
                    max_advantage_result_all.slice_spec))

    slice_dict = self._group_results_by_slice()

    if len(slice_dict.keys()) > 1 and by_slices:
      for slice_str in slice_dict:
        results = slice_dict[slice_str]
        summary.append('\nBest-performing attacks over slice: \"%s\"' %
                       slice_str)
        max_auc_result = results.get_result_with_max_auc()
        summary.append('  %s achieved an AUC of %.2f' %
                       (max_auc_result.attack_type, max_auc_result.get_auc()))
        max_advantage_result = results.get_result_with_max_attacker_advantage()
        summary.append('  %s achieved an advantage of %.2f' %
                       (max_advantage_result.attack_type,
                        max_advantage_result.get_attacker_advantage()))

    return '\n'.join(summary)

  def _group_results_by_slice(self):
    """Groups AttackResults into a dictionary keyed by the slice."""
    slice_dict = {}
    for attack_result in self.single_attack_results:
      slice_str = str(attack_result.slice_spec)
      if slice_str not in slice_dict:
        slice_dict[slice_str] = AttackResults([])
      slice_dict[slice_str].single_attack_results.append(attack_result)
    return slice_dict

  def get_result_with_max_auc(self) -> SingleAttackResult:
    """Get the result with maximum AUC for all attacks and slices."""
    aucs = [result.get_auc() for result in self.single_attack_results]

    if min(aucs) < 0.4:
      print('Suspiciously low AUC detected: %.2f. ' +
            'There might be a bug in the classifier' % min(aucs))

    return self.single_attack_results[np.argmax(aucs)]

  def get_result_with_max_attacker_advantage(self) -> SingleAttackResult:
    """Get the result with maximum advantage for all attacks and slices."""
    return self.single_attack_results[np.argmax([
        result.get_attacker_advantage() for result in self.single_attack_results
    ])]

  def save(self, filepath):
    """Saves self to a pickle file."""
    with open(filepath, 'wb') as out:
      pickle.dump(self, out)

  @classmethod
  def load(cls, filepath):
    """Loads AttackResults from a pickle file."""
    with open(filepath, 'rb') as inp:
      return pickle.load(inp)

@dataclass
class AttackResultsCollection:
  """A collection of AttackResults."""
  attack_results_list: Iterable[AttackResults]

  def append(self, attack_results: AttackResults):
    self.attack_results_list.append(attack_results)

  def save(self, dirname):
    """Saves self to a pickle file."""
    for i, attack_results in enumerate(self.attack_results_list):
      filepath = os.path.join(dirname,
                              _get_attack_results_filename(attack_results, i))

      attack_results.save(filepath)

  @classmethod
  def load(cls, dirname):
    """Loads AttackResultsCollection from all files in a directory."""
    loaded_collection = AttackResultsCollection([])
    for filepath in sorted(glob.glob('%s/*' % dirname)):
      with open(filepath, 'rb') as inp:
        loaded_collection.attack_results_list.append(pickle.load(inp))
    return loaded_collection

def _get_attack_results_filename(attack_results: AttackResults, index: int):
  """Creates a filename for a specific set of AttackResults."""
  metadata = attack_results.privacy_report_metadata
  if metadata is not None:
    return '%s_%s_epoch_%s.pickle' % (metadata.model_variant_label, index,
                                      metadata.epoch_num)
  return '%s.pickle' % index

def get_flattened_attack_metrics(results: AttackResults):
  """Get flattened attack metrics.

  Args:
    results: membership inference attack results.

  Returns:
       types: a list of attack types
       slices: a list of slices
       attack_metrics: a list of metric names
       values: a list of metric values, i-th element correspond to properties[i]
  """
  types = []
  slices = []
  attack_metrics = []
  values = []
  for attack_result in results.single_attack_results:
    types += [str(attack_result.attack_type)] * 2
    slices += [str(attack_result.slice_spec)] * 2
    attack_metrics += ['adv', 'auc']
    values += [float(attack_result.get_attacker_advantage()),
               float(attack_result.get_auc())]
  return types, slices, attack_metrics, values